mp3 audio downloaded, play corrupt voice messages, -startintray cmdline param, always to recent emojis, local images cache respects filesize and last modified, removed stickers from documents overview, notify remove in Windows fullscreen and lockscreen

This commit is contained in:
John Preston 2015-01-27 19:58:58 +03:00
parent dde1a5a6eb
commit de784d2bbc
25 changed files with 182 additions and 69 deletions

View File

@ -314,7 +314,7 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParama
LPWSTR *args; LPWSTR *args;
int argsCount; int argsCount;
bool needupdate = false, autostart = false, debug = false, writeprotected = false; bool needupdate = false, autostart = false, debug = false, writeprotected = false, startintray = false;
args = CommandLineToArgvW(GetCommandLine(), &argsCount); args = CommandLineToArgvW(GetCommandLine(), &argsCount);
if (args) { if (args) {
for (int i = 1; i < argsCount; ++i) { for (int i = 1; i < argsCount; ++i) {
@ -325,6 +325,8 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParama
} else if (equal(args[i], L"-debug")) { } else if (equal(args[i], L"-debug")) {
debug = _debug = true; debug = _debug = true;
openLog(); openLog();
} else if (equal(args[i], L"-startintray")) {
startintray = true;
} else if (equal(args[i], L"-writeprotected") && ++i < argsCount) { } else if (equal(args[i], L"-writeprotected") && ++i < argsCount) {
writeprotected = true; writeprotected = true;
updateTo = args[i]; updateTo = args[i];
@ -373,6 +375,7 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParama
wstring targs; wstring targs;
if (autostart) targs += L" -autostart"; if (autostart) targs += L" -autostart";
if (debug) targs += L" -debug"; if (debug) targs += L" -debug";
if (startintray) targs += L" -startintray";
bool executed = false; bool executed = false;
if (writeprotected) { // run un-elevated if (writeprotected) { // run un-elevated

View File

@ -303,7 +303,7 @@ int main(int argc, char *argv[]) {
writeLog("Updater started.."); writeLog("Updater started..");
bool needupdate = true, autostart = false, debug = false, tosettings = false; bool needupdate = true, autostart = false, debug = false, tosettings = false, startintray = false;
char *key = 0; char *key = 0;
for (int i = 1; i < argc; ++i) { for (int i = 1; i < argc; ++i) {
@ -314,6 +314,8 @@ int main(int argc, char *argv[]) {
} else if (equal(argv[i], "-debug")) { } else if (equal(argv[i], "-debug")) {
debug = _debug = true; debug = _debug = true;
openLog(); openLog();
} else if (equal(argv[i], "-startintray")) {
startintray = true;
} else if (equal(argv[i], "-tosettings")) { } else if (equal(argv[i], "-tosettings")) {
tosettings = true; tosettings = true;
} else if (equal(argv[i], "-key") && ++i < argc) { } else if (equal(argv[i], "-key") && ++i < argc) {
@ -377,12 +379,13 @@ int main(int argc, char *argv[]) {
char path[MaxLen] = {0}; char path[MaxLen] = {0};
strcpy(path, (exeDir + "Telegram").c_str()); strcpy(path, (exeDir + "Telegram").c_str());
char *args[MaxArgsCount] = {0}, p_noupdate[] = "-noupdate", p_autostart[] = "-autostart", p_debug[] = "-debug", p_tosettings[] = "-tosettings", p_key[] = "-key"; char *args[MaxArgsCount] = {0}, p_noupdate[] = "-noupdate", p_autostart[] = "-autostart", p_debug[] = "-debug", p_tosettings[] = "-tosettings", p_key[] = "-key", p_startintray[] = "-startintray";
int argIndex = 0; int argIndex = 0;
args[argIndex++] = path; args[argIndex++] = path;
args[argIndex++] = p_noupdate; args[argIndex++] = p_noupdate;
if (autostart) args[argIndex++] = p_autostart; if (autostart) args[argIndex++] = p_autostart;
if (debug) args[argIndex++] = p_debug; if (debug) args[argIndex++] = p_debug;
if (startintray) args[argIndex++] = p_startintray;
if (tosettings) args[argIndex++] = p_tosettings; if (tosettings) args[argIndex++] = p_tosettings;
if (key) { if (key) {
args[argIndex++] = p_key; args[argIndex++] = p_key;

View File

@ -78,7 +78,7 @@ int main(int argc, const char * argv[]) {
openLog(); openLog();
pid_t procId = 0; pid_t procId = 0;
BOOL update = YES, toSettings = NO, autoStart = NO; BOOL update = YES, toSettings = NO, autoStart = NO, startInTray = NO;
NSString *key = nil; NSString *key = nil;
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i) {
if ([@"-workpath" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) { if ([@"-workpath" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
@ -99,6 +99,8 @@ int main(int argc, const char * argv[]) {
autoStart = YES; autoStart = YES;
} else if ([@"-debug" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) { } else if ([@"-debug" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
_debug = YES; _debug = YES;
} else if ([@"-startintray" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
startInTray = YES;
} else if ([@"-key" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) { } else if ([@"-key" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
if (++i < argc) key = [NSString stringWithUTF8String:argv[i]]; if (++i < argc) key = [NSString stringWithUTF8String:argv[i]];
} }
@ -191,6 +193,7 @@ int main(int argc, const char * argv[]) {
NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:@"-noupdate", nil]; NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:@"-noupdate", nil];
if (toSettings) [args addObject:@"-tosettings"]; if (toSettings) [args addObject:@"-tosettings"];
if (_debug) [args addObject:@"-debug"]; if (_debug) [args addObject:@"-debug"];
if (startInTray) [args addObject:@"-startintray"];
if (autoStart) [args addObject:@"-autostart"]; if (autoStart) [args addObject:@"-autostart"];
if (key) { if (key) {
[args addObject:@"-key"]; [args addObject:@"-key"];

View File

@ -843,7 +843,7 @@ namespace App {
} }
AudioData *feedAudio(const MTPDaudio &audio, AudioData *convert) { AudioData *feedAudio(const MTPDaudio &audio, AudioData *convert) {
return App::audio(audio.vid.v, convert, audio.vaccess_hash.v, audio.vuser_id.v, audio.vdate.v, audio.vduration.v, audio.vdc_id.v, audio.vsize.v); return App::audio(audio.vid.v, convert, audio.vaccess_hash.v, audio.vuser_id.v, audio.vdate.v, qs(audio.vmime_type), audio.vduration.v, audio.vdc_id.v, audio.vsize.v);
} }
DocumentData *feedDocument(const MTPdocument &document, const QPixmap &thumb) { DocumentData *feedDocument(const MTPdocument &document, const QPixmap &thumb) {
@ -1043,7 +1043,7 @@ namespace App {
return result; return result;
} }
AudioData *audio(const AudioId &audio, AudioData *convert, const uint64 &access, int32 user, int32 date, int32 duration, int32 dc, int32 size) { AudioData *audio(const AudioId &audio, AudioData *convert, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) {
if (convert) { if (convert) {
if (convert->id != audio) { if (convert->id != audio) {
AudiosData::iterator i = audiosData.find(convert->id); AudiosData::iterator i = audiosData.find(convert->id);
@ -1057,6 +1057,7 @@ namespace App {
if (!convert->user && !convert->date && (user || date)) { if (!convert->user && !convert->date && (user || date)) {
convert->user = user; convert->user = user;
convert->date = date; convert->date = date;
convert->mime = mime;
convert->duration = duration; convert->duration = duration;
convert->dc = dc; convert->dc = dc;
convert->size = size; convert->size = size;
@ -1068,7 +1069,7 @@ namespace App {
if (convert) { if (convert) {
result = convert; result = convert;
} else { } else {
result = new AudioData(audio, access, user, date, duration, dc, size); result = new AudioData(audio, access, user, date, mime, duration, dc, size);
} }
audiosData.insert(audio, result); audiosData.insert(audio, result);
} else { } else {
@ -1077,6 +1078,7 @@ namespace App {
result->access = access; result->access = access;
result->user = user; result->user = user;
result->date = date; result->date = date;
result->mime = mime;
result->duration = duration; result->duration = duration;
result->dc = dc; result->dc = dc;
result->size = size; result->size = size;
@ -1467,7 +1469,7 @@ namespace App {
} }
void playSound() { void playSound() {
if (cSoundNotify()) audioPlayNotify(); if (cSoundNotify() && !psSkipAudioNotify()) audioPlayNotify();
} }
void writeConfig() { void writeConfig() {

View File

@ -106,7 +106,7 @@ namespace App {
QString peerName(const PeerData *peer, bool forDialogs = false); QString peerName(const PeerData *peer, bool forDialogs = false);
PhotoData *photo(const PhotoId &photo, PhotoData *convert = 0, const uint64 &access = 0, int32 user = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr()); PhotoData *photo(const PhotoId &photo, PhotoData *convert = 0, const uint64 &access = 0, int32 user = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr());
VideoData *video(const VideoId &video, VideoData *convert = 0, const uint64 &access = 0, int32 user = 0, int32 date = 0, int32 duration = 0, int32 w = 0, int32 h = 0, const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0); VideoData *video(const VideoId &video, VideoData *convert = 0, const uint64 &access = 0, int32 user = 0, int32 date = 0, int32 duration = 0, int32 w = 0, int32 h = 0, const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0);
AudioData *audio(const AudioId &audio, AudioData *convert = 0, const uint64 &access = 0, int32 user = 0, int32 date = 0, int32 duration = 0, int32 dc = 0, int32 size = 0); AudioData *audio(const AudioId &audio, AudioData *convert = 0, const uint64 &access = 0, int32 user = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0);
DocumentData *document(const DocumentId &document, DocumentData *convert = 0, const uint64 &access = 0, int32 date = 0, const QVector<MTPDocumentAttribute> &attributes = QVector<MTPDocumentAttribute>(), const QString &mime = QString(), const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0); DocumentData *document(const DocumentId &document, DocumentData *convert = 0, const uint64 &access = 0, int32 date = 0, const QVector<MTPDocumentAttribute> &attributes = QVector<MTPDocumentAttribute>(), const QString &mime = QString(), const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0);
ImageLinkData *imageLink(const QString &imageLink, ImageLinkType type = InvalidImageLink, const QString &url = QString()); ImageLinkData *imageLink(const QString &imageLink, ImageLinkType type = InvalidImageLink, const QString &url = QString());
void forgetMedia(); void forgetMedia();

View File

@ -600,7 +600,7 @@ void VoiceMessagesLoader::onLoad(AudioData *audio) {
int ret = op_read_stereo(l->file, pcm, sizeof(pcm) / sizeof(*pcm)); int ret = op_read_stereo(l->file, pcm, sizeof(pcm) / sizeof(*pcm));
if (ret < 0) { if (ret < 0) {
{ /*{
QMutexLocker lock(&voicemsgsMutex); QMutexLocker lock(&voicemsgsMutex);
VoiceMessages *voice = audioVoice(); VoiceMessages *voice = audioVoice();
if (voice) { if (voice) {
@ -609,9 +609,11 @@ void VoiceMessagesLoader::onLoad(AudioData *audio) {
m.state = VoiceMessageStopped; m.state = VoiceMessageStopped;
} }
} }
} }*/
LOG(("Audio Error: op_read_stereo failed, error code %1").arg(ret)); LOG(("Audio Error: op_read_stereo failed, error code %1 (corrupted voice message?)").arg(ret));
return loadError(j); finished = true;
break;
// return loadError(j);
} }
int li = op_current_link(l->file); int li = op_current_link(l->file);

View File

@ -774,6 +774,7 @@ void EmojiPan::hideStart() {
void EmojiPan::hideFinish() { void EmojiPan::hideFinish() {
hide(); hide();
_cache = QPixmap(); _cache = QPixmap();
_recent.setChecked(true);
} }
void EmojiPan::showStart() { void EmojiPan::showStart() {

View File

@ -481,9 +481,11 @@ LocalImage::~LocalImage() {
} }
LocalImage *getImage(const QString &file, QByteArray format) { LocalImage *getImage(const QString &file, QByteArray format) {
LocalImages::const_iterator i = localImages.constFind(file); QFileInfo f(file);
QString key = qsl("//:%1//:%2//:").arg(f.size()).arg(f.lastModified().toTime_t()) + file;
LocalImages::const_iterator i = localImages.constFind(key);
if (i == localImages.cend()) { if (i == localImages.cend()) {
i = localImages.insert(file, new LocalImage(file, format)); i = localImages.insert(key, new LocalImage(file, format));
} }
return i.value(); return i.value();
} }

View File

@ -24,6 +24,7 @@ namespace {
namespace style { namespace style {
FontData::FontData(uint32 size, uint32 flags, uint32 family, Font *other) : f(_fontFamilies[family]), m(f), _size(size), _flags(flags), _family(family) { FontData::FontData(uint32 size, uint32 flags, uint32 family, Font *other) : f(_fontFamilies[family]), m(f), _size(size), _flags(flags), _family(family) {
// f.setStyleStrategy(QFont::NoAntialias);
if (other) { if (other) {
memcpy(modified, other, sizeof(modified)); memcpy(modified, other, sizeof(modified));
} else { } else {

View File

@ -546,8 +546,10 @@ void AudioOpenLink::onClick(Qt::MouseButton button) const {
AudioData *data = audio(); AudioData *data = audio();
if ((!data->user && !data->date) || button != Qt::LeftButton) return; if ((!data->user && !data->date) || button != Qt::LeftButton) return;
bool mp3 = (data->mime == QLatin1String("audio/mp3"));
QString already = data->already(true); QString already = data->already(true);
bool play = audioVoice(); bool play = !mp3 && audioVoice();
if (!already.isEmpty() || (!data->data.isEmpty() && play)) { if (!already.isEmpty() || (!data->data.isEmpty() && play)) {
if (play) { if (play) {
AudioData *playing = 0; AudioData *playing = 0;
@ -566,7 +568,7 @@ void AudioOpenLink::onClick(Qt::MouseButton button) const {
if (data->status != FileReady) return; if (data->status != FileReady) return;
QString filename = saveFileName(lang(lng_save_audio), qsl("OGG Opus Audio (*.ogg);;All files (*.*)"), qsl("audio"), qsl(".ogg"), false); QString filename = saveFileName(lang(lng_save_audio), mp3 ? qsl("MP3 Audio (*.mp3);;All files (*.*)") : qsl("OGG Opus Audio (*.ogg);;All files (*.*)"), qsl("audio"), mp3 ? qsl(".mp3") : qsl(".ogg"), false);
if (!filename.isEmpty()) { if (!filename.isEmpty()) {
data->openOnSave = 1; data->openOnSave = 1;
data->openOnSaveMsgId = App::hoveredLinkItem() ? App::hoveredLinkItem()->id : 0; data->openOnSaveMsgId = App::hoveredLinkItem() ? App::hoveredLinkItem()->id : 0;
@ -586,8 +588,9 @@ void AudioSaveLink::doSave(bool forceSavingAs) const {
} }
} else { } else {
QDir alreadyDir(already.isEmpty() ? QDir() : QFileInfo(already).dir()); QDir alreadyDir(already.isEmpty() ? QDir() : QFileInfo(already).dir());
QString name = already.isEmpty() ? QString(".ogg") : already; bool mp3 = (data->mime == QLatin1String("audio/mp3"));
QString filename = saveFileName(lang(lng_save_audio), qsl("OGG Opus Audio (*.ogg);;All files (*.*)"), qsl("audio"), name, forceSavingAs, alreadyDir); QString name = already.isEmpty() ? (mp3 ? qsl(".mp3") : qsl(".ogg")) : already;
QString filename = saveFileName(lang(lng_save_audio), mp3 ? qsl("MP3 Audio (*.mp3);;All files (*.*)") : qsl("OGG Opus Audio (*.ogg);;All files (*.*)"), qsl("audio"), name, forceSavingAs, alreadyDir);
if (!filename.isEmpty()) { if (!filename.isEmpty()) {
if (forceSavingAs) { if (forceSavingAs) {
data->cancel(); data->cancel();
@ -612,8 +615,8 @@ void AudioCancelLink::onClick(Qt::MouseButton button) const {
data->cancel(); data->cancel();
} }
AudioData::AudioData(const AudioId &id, const uint64 &access, int32 user, int32 date, int32 duration, int32 dc, int32 size) : AudioData::AudioData(const AudioId &id, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) :
id(id), access(access), user(user), date(date), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) { id(id), access(access), user(user), date(date), mime(mime), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
location = Local::readFileLocation(mediaKey(mtpc_inputAudioFileLocation, dc, id)); location = Local::readFileLocation(mediaKey(mtpc_inputAudioFileLocation, dc, id));
} }
@ -2607,7 +2610,8 @@ void HistoryAudio::draw(QPainter &p, const HistoryItem *parent, bool selected, i
width = _maxw; width = _maxw;
} }
if (!data->loader && data->status != FileFailed && !already && !hasdata && data->size < AudioVoiceMsgInMemory) { bool mp3 = (data->mime == QLatin1String("audio/mp3"));
if (!data->loader && !mp3 && data->status != FileFailed && !already && !hasdata && data->size < AudioVoiceMsgInMemory) {
data->save(QString()); data->save(QString());
} }
@ -2639,11 +2643,11 @@ void HistoryAudio::draw(QPainter &p, const HistoryItem *parent, bool selected, i
AudioData *playing = 0; AudioData *playing = 0;
VoiceMessageState playingState = VoiceMessageStopped; VoiceMessageState playingState = VoiceMessageStopped;
int64 playingPosition = 0, playingDuration = 0; int64 playingPosition = 0, playingDuration = 0;
if (audioVoice()) { if (!mp3 && audioVoice()) {
audioVoice()->currentState(&playing, &playingState, &playingPosition, &playingDuration); audioVoice()->currentState(&playing, &playingState, &playingPosition, &playingDuration);
} }
QRect img; QRect img;
if (already || hasdata) { if (!mp3 && (already || hasdata)) {
bool showPause = (playing == data) && (playingState == VoiceMessagePlaying || playingState == VoiceMessageResuming || playingState == VoiceMessageStarting); bool showPause = (playing == data) && (playingState == VoiceMessagePlaying || playingState == VoiceMessageResuming || playingState == VoiceMessageStarting);
img = out ? (showPause ? st::mediaPauseOutImg : st::mediaPlayOutImg) : (showPause ? st::mediaPauseInImg : st::mediaPlayInImg); img = out ? (showPause ? st::mediaPauseOutImg : st::mediaPlayOutImg) : (showPause ? st::mediaPauseInImg : st::mediaPlayInImg);
} else { } else {
@ -2667,7 +2671,7 @@ void HistoryAudio::draw(QPainter &p, const HistoryItem *parent, bool selected, i
style::color status(selected ? (out ? st::mediaOutSelectColor : st::mediaInSelectColor) : (out ? st::mediaOutColor : st::mediaInColor)); style::color status(selected ? (out ? st::mediaOutSelectColor : st::mediaInSelectColor) : (out ? st::mediaOutColor : st::mediaInColor));
p.setPen(status->p); p.setPen(status->p);
if (already || hasdata) { if (!mp3 && (already || hasdata)) {
if (playing == data && playingState != VoiceMessageStopped) { if (playing == data && playingState != VoiceMessageStopped) {
statusText = formatDurationText(playingPosition / AudioVoiceMsgFrequency) + qsl(" / ") + formatDurationText(playingDuration / AudioVoiceMsgFrequency); statusText = formatDurationText(playingPosition / AudioVoiceMsgFrequency) + qsl(" / ") + formatDurationText(playingDuration / AudioVoiceMsgFrequency);
} else { } else {

View File

@ -306,7 +306,7 @@ public:
}; };
struct AudioData { struct AudioData {
AudioData(const AudioId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, int32 duration = 0, int32 dc = 0, int32 size = 0); AudioData(const AudioId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0);
void forget() { void forget() {
} }
@ -343,6 +343,7 @@ struct AudioData {
uint64 access; uint64 access;
int32 user; int32 user;
int32 date; int32 date;
QString mime;
int32 duration; int32 duration;
int32 dc; int32 dc;
int32 size; int32 size;
@ -574,8 +575,8 @@ inline MediaOverviewType mediaToOverviewType(HistoryMediaType t) {
switch (t) { switch (t) {
case MediaTypePhoto: return OverviewPhotos; case MediaTypePhoto: return OverviewPhotos;
case MediaTypeVideo: return OverviewVideos; case MediaTypeVideo: return OverviewVideos;
case MediaTypeDocument: case MediaTypeDocument: return OverviewDocuments;
case MediaTypeSticker: return OverviewDocuments; // case MediaTypeSticker: return OverviewDocuments;
case MediaTypeAudio: return OverviewAudios; case MediaTypeAudio: return OverviewAudios;
} }
return OverviewCount; return OverviewCount;

View File

@ -1099,8 +1099,9 @@ void MainWidget::audioLoadProgress(mtpFileLoader *loader) {
if (audio->loader) { if (audio->loader) {
if (audio->loader->done()) { if (audio->loader->done()) {
audio->finish(); audio->finish();
bool mp3 = (audio->mime == QLatin1String("audio/mp3"));
QString already = audio->already(); QString already = audio->already();
bool play = audio->openOnSave > 0 && audioVoice(); bool play = !mp3 && audio->openOnSave > 0 && audioVoice();
if ((!already.isEmpty() && audio->openOnSave) || (!audio->data.isEmpty() && play)) { if ((!already.isEmpty() && audio->openOnSave) || (!audio->data.isEmpty() && play)) {
if (play) { if (play) {
AudioData *playing = 0; AudioData *playing = 0;

View File

@ -760,8 +760,7 @@ void PsMainWindow::psFirstShow() {
setWindowState(Qt::WindowMaximized); setWindowState(Qt::WindowMaximized);
} }
if (cFromAutoStart()) { if ((cFromAutoStart() && cStartMinimized()) || cStartInTray()) {
if (cStartMinimized()) {
setWindowState(Qt::WindowMinimized); setWindowState(Qt::WindowMinimized);
if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) { if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) {
hide(); hide();
@ -772,9 +771,7 @@ void PsMainWindow::psFirstShow() {
} else { } else {
show(); show();
} }
} else {
show();
}
posInited = true; posInited = true;
} }
@ -1312,6 +1309,14 @@ uint64 psIdleTime() {
return getms(true) - _lastUserAction; return getms(true) - _lastUserAction;
} }
bool psSkipAudioNotify() {
return false;
}
bool psSkipDesktopNotify() {
return false;
}
QStringList psInitLogs() { QStringList psInitLogs() {
return _initLogs; return _initLogs;
} }
@ -1646,7 +1651,7 @@ bool _execUpdater(bool update = true) {
QByteArray data(QFile::encodeName(cExeDir() + "Updater")); QByteArray data(QFile::encodeName(cExeDir() + "Updater"));
memcpy(path, data.constData(), data.size()); memcpy(path, data.constData(), data.size());
char *args[MaxArgsCount] = {0}, p_noupdate[] = "-noupdate", p_autostart[] = "-autostart", p_debug[] = "-debug", p_tosettings[] = "-tosettings", p_key[] = "-key", p_path[] = "-workpath"; char *args[MaxArgsCount] = {0}, p_noupdate[] = "-noupdate", p_autostart[] = "-autostart", p_debug[] = "-debug", p_tosettings[] = "-tosettings", p_key[] = "-key", p_path[] = "-workpath", p_startintray[] = "-startintray";
char p_datafile[MaxLen] = {0}, p_pathbuf[MaxLen] = {0}; char p_datafile[MaxLen] = {0}, p_pathbuf[MaxLen] = {0};
int argIndex = 0; int argIndex = 0;
args[argIndex++] = path; args[argIndex++] = path;
@ -1656,6 +1661,7 @@ bool _execUpdater(bool update = true) {
} }
if (cFromAutoStart()) args[argIndex++] = p_autostart; if (cFromAutoStart()) args[argIndex++] = p_autostart;
if (cDebug()) args[argIndex++] = p_debug; if (cDebug()) args[argIndex++] = p_debug;
if (cStartInTray()) args[argIndex++] = p_startintray;
if (cDataFile() != (cTestMode() ? qsl("data_test") : qsl("data"))) { if (cDataFile() != (cTestMode() ? qsl("data_test") : qsl("data"))) {
QByteArray dataf = QFile::encodeName(cDataFile()); QByteArray dataf = QFile::encodeName(cDataFile());
if (dataf.size() < MaxLen) { if (dataf.size() < MaxLen) {

View File

@ -169,6 +169,9 @@ private:
void psUserActionDone(); void psUserActionDone();
uint64 psIdleTime(); uint64 psIdleTime();
bool psSkipAudioNotify();
bool psSkipDesktopNotify();
QStringList psInitLogs(); QStringList psInitLogs();
void psClearInitLogs(); void psClearInitLogs();

View File

@ -290,8 +290,7 @@ void PsMainWindow::psFirstShow() {
setWindowState(Qt::WindowMaximized); setWindowState(Qt::WindowMaximized);
} }
if (cFromAutoStart()) { if ((cFromAutoStart() && cStartMinimized()) || cStartInTray()) {
if (cStartMinimized()) {
setWindowState(Qt::WindowMinimized); setWindowState(Qt::WindowMinimized);
if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) { if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) {
hide(); hide();
@ -302,9 +301,7 @@ void PsMainWindow::psFirstShow() {
} else { } else {
show(); show();
} }
} else {
show();
}
posInited = true; posInited = true;
// init global menu // init global menu
@ -930,6 +927,14 @@ uint64 psIdleTime() {
return objc_idleTime(idleTime) ? idleTime : (getms(true) - _lastUserAction); return objc_idleTime(idleTime) ? idleTime : (getms(true) - _lastUserAction);
} }
bool psSkipAudioNotify() {
return false;
}
bool psSkipDesktopNotify() {
return false;
}
QStringList psInitLogs() { QStringList psInitLogs() {
return _initLogs; return _initLogs;
} }

View File

@ -198,6 +198,9 @@ private:
void psUserActionDone(); void psUserActionDone();
uint64 psIdleTime(); uint64 psIdleTime();
bool psSkipAudioNotify();
bool psSkipDesktopNotify();
QStringList psInitLogs(); QStringList psInitLogs();
void psClearInitLogs(); void psClearInitLogs();

View File

@ -897,6 +897,7 @@ BOOL _execUpdater(BOOL update = YES) {
if (!update) [args addObject:@"-noupdate"]; if (!update) [args addObject:@"-noupdate"];
if (cFromAutoStart()) [args addObject:@"-autostart"]; if (cFromAutoStart()) [args addObject:@"-autostart"];
if (cDebug()) [args addObject:@"-debug"]; if (cDebug()) [args addObject:@"-debug"];
if (cStartInTray()) [args addObject:@"-startintray"];
if (cDataFile() != (cTestMode() ? qsl("data_test") : qsl("data"))) { if (cDataFile() != (cTestMode() ? qsl("data_test") : qsl("data"))) {
[args addObject:@"-key"]; [args addObject:@"-key"];
[args addObject:QNSString(cDataFile()).s()]; [args addObject:QNSString(cDataFile()).s()];

View File

@ -29,6 +29,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
#include <Strsafe.h> #include <Strsafe.h>
#include <shlobj.h> #include <shlobj.h>
#include <Windowsx.h> #include <Windowsx.h>
#include <WtsApi32.h>
#include <qpa/qplatformnativeinterface.h> #include <qpa/qplatformnativeinterface.h>
@ -59,12 +60,15 @@ namespace {
bool useTheme = false; bool useTheme = false;
bool useOpenWith = false; bool useOpenWith = false;
bool useOpenAs = false; bool useOpenAs = false;
bool useWtsapi = false;
bool useShellapi = false;
bool themeInited = false; bool themeInited = false;
bool finished = true; bool finished = true;
int menuShown = 0, menuHidden = 0; int menuShown = 0, menuHidden = 0;
int dleft = 0, dtop = 0; int dleft = 0, dtop = 0;
QMargins simpleMargins, margins; QMargins simpleMargins, margins;
HICON bigIcon = 0, smallIcon = 0, overlayIcon = 0; HICON bigIcon = 0, smallIcon = 0, overlayIcon = 0;
bool sessionLoggedOff = false;
UINT tbCreatedMsgId = 0; UINT tbCreatedMsgId = 0;
ITaskbarList3 *tbListInterface = 0; ITaskbarList3 *tbListInterface = 0;
@ -633,6 +637,15 @@ namespace {
typedef HRESULT (FAR STDAPICALLTYPE *f_shLoadIndirectString)(LPCWSTR pszSource, LPWSTR pszOutBuf, UINT cchOutBuf, void **ppvReserved); typedef HRESULT (FAR STDAPICALLTYPE *f_shLoadIndirectString)(LPCWSTR pszSource, LPWSTR pszOutBuf, UINT cchOutBuf, void **ppvReserved);
f_shLoadIndirectString shLoadIndirectString = 0; f_shLoadIndirectString shLoadIndirectString = 0;
typedef BOOL (FAR STDAPICALLTYPE *f_wtsRegisterSessionNotification)(HWND hWnd, DWORD dwFlags);
f_wtsRegisterSessionNotification wtsRegisterSessionNotification = 0;
typedef BOOL (FAR STDAPICALLTYPE *f_wtsUnRegisterSessionNotification)(HWND hWnd);
f_wtsUnRegisterSessionNotification wtsUnRegisterSessionNotification = 0;
typedef HRESULT (FAR STDAPICALLTYPE *f_shQueryUserNotificationState)(QUERY_USER_NOTIFICATION_STATE *pquns);
f_shQueryUserNotificationState shQueryUserNotificationState = 0;
template <typename TFunction> template <typename TFunction>
bool loadFunction(HINSTANCE dll, LPCSTR name, TFunction &func) { bool loadFunction(HINSTANCE dll, LPCSTR name, TFunction &func) {
if (!dll) return false; if (!dll) return false;
@ -650,6 +663,7 @@ namespace {
setupUx(); setupUx();
setupShell(); setupShell();
setupWtsapi();
} }
void setupDWM() { void setupDWM() {
HINSTANCE procId = LoadLibrary(L"DWMAPI.DLL"); HINSTANCE procId = LoadLibrary(L"DWMAPI.DLL");
@ -669,6 +683,7 @@ namespace {
HINSTANCE procId = LoadLibrary(L"SHELL32.DLL"); HINSTANCE procId = LoadLibrary(L"SHELL32.DLL");
setupOpenWith(procId); setupOpenWith(procId);
setupOpenAs(procId); setupOpenAs(procId);
setupShellapi(procId);
} }
void setupOpenWith(HINSTANCE procId) { void setupOpenWith(HINSTANCE procId) {
if (!loadFunction(procId, "SHAssocEnumHandlers", shAssocEnumHandlers)) return; if (!loadFunction(procId, "SHAssocEnumHandlers", shAssocEnumHandlers)) return;
@ -682,6 +697,17 @@ namespace {
if (!loadFunction(procId, "SHOpenWithDialog", shOpenWithDialog) && !loadFunction(procId, "OpenAs_RunDLLW", openAs_RunDLL)) return; if (!loadFunction(procId, "SHOpenWithDialog", shOpenWithDialog) && !loadFunction(procId, "OpenAs_RunDLLW", openAs_RunDLL)) return;
useOpenAs = true; useOpenAs = true;
} }
void setupWtsapi() {
HINSTANCE procId = LoadLibrary(L"WTSAPI32.DLL");
if (!loadFunction(procId, "WTSRegisterSessionNotification", wtsRegisterSessionNotification)) return;
if (!loadFunction(procId, "WTSUnRegisterSessionNotification", wtsUnRegisterSessionNotification)) return;
useWtsapi = true;
}
void setupShellapi(HINSTANCE procId) {
if (!loadFunction(procId, "SHQueryUserNotificationState", shQueryUserNotificationState)) return;
useShellapi = true;
}
}; };
_PsInitializer _psInitializer; _PsInitializer _psInitializer;
@ -713,6 +739,14 @@ namespace {
} }
switch (msg) { switch (msg) {
case WM_WTSSESSION_CHANGE: {
if (wParam == WTS_SESSION_LOGOFF || wParam == WTS_SESSION_LOCK) {
sessionLoggedOff = true;
} else if (wParam == WTS_SESSION_LOGON || wParam == WTS_SESSION_UNLOCK) {
sessionLoggedOff = false;
}
} return false;
case WM_DESTROY: { case WM_DESTROY: {
App::quit(); App::quit();
} return false; } return false;
@ -753,9 +787,9 @@ namespace {
} return true; } return true;
case WM_NCACTIVATE: { case WM_NCACTIVATE: {
Application::wnd()->psUpdateMargins(); //Application::wnd()->psUpdateMargins();
*result = LRESULT(TRUE); *result = DefWindowProc(hWnd, msg, wParam, -1);
Application::wnd()->repaint(); //Application::wnd()->repaint();
} return true; } return true;
case WM_WINDOWPOSCHANGING: case WM_WINDOWPOSCHANGING:
@ -964,6 +998,7 @@ void PsMainWindow::psUpdateWorkmode() {
HICON qt_pixmapToWinHICON(const QPixmap &); HICON qt_pixmapToWinHICON(const QPixmap &);
HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &, int hbitmapFormat); HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &, int hbitmapFormat);
static HICON _qt_createHIcon(const QIcon &icon, int xSize, int ySize) { static HICON _qt_createHIcon(const QIcon &icon, int xSize, int ySize) {
if (!icon.isNull()) { if (!icon.isNull()) {
const QPixmap pm = icon.pixmap(icon.actualSize(QSize(xSize, ySize))); const QPixmap pm = icon.pixmap(icon.actualSize(QSize(xSize, ySize)));
@ -1003,6 +1038,7 @@ void PsMainWindow::psUpdateCounter() {
description.toWCharArray(descriptionArr); description.toWCharArray(descriptionArr);
tbListInterface->SetOverlayIcon(ps_hWnd, ps_iconOverlay, descriptionArr); tbListInterface->SetOverlayIcon(ps_hWnd, ps_iconOverlay, descriptionArr);
} }
SetWindowPos(ps_hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
} }
void PsMainWindow::psUpdateDelegate() { void PsMainWindow::psUpdateDelegate() {
@ -1072,6 +1108,8 @@ void PsMainWindow::psInitFrameless() {
if (!ps_hWnd) return; if (!ps_hWnd) return;
if (useWtsapi) wtsRegisterSessionNotification(ps_hWnd, NOTIFY_FOR_THIS_SESSION);
if (frameless) { if (frameless) {
setWindowFlags(Qt::FramelessWindowHint); setWindowFlags(Qt::FramelessWindowHint);
} }
@ -1138,8 +1176,7 @@ void PsMainWindow::psFirstShow() {
setWindowState(Qt::WindowMaximized); setWindowState(Qt::WindowMaximized);
} }
if (cFromAutoStart()) { if ((cFromAutoStart() && cStartMinimized()) || cStartInTray()) {
if (cStartMinimized()) {
setWindowState(Qt::WindowMinimized); setWindowState(Qt::WindowMinimized);
if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) { if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) {
hide(); hide();
@ -1150,9 +1187,7 @@ void PsMainWindow::psFirstShow() {
} else { } else {
show(); show();
} }
} else {
show();
}
posInited = true; posInited = true;
if (showShadows) { if (showShadows) {
_psShadowWindows.update(_PsShadowMoved | _PsShadowResized | _PsShadowShown); _psShadowWindows.update(_PsShadowMoved | _PsShadowResized | _PsShadowShown);
@ -1297,6 +1332,13 @@ void PsMainWindow::psDestroyIcons() {
} }
PsMainWindow::~PsMainWindow() { PsMainWindow::~PsMainWindow() {
if (useWtsapi) {
QPlatformNativeInterface *i = QGuiApplication::platformNativeInterface();
if (HWND hWnd = static_cast<HWND>(i->nativeResourceForWindow(QByteArrayLiteral("handle"), windowHandle()))) {
wtsUnRegisterSessionNotification(hWnd);
}
}
finished = true; finished = true;
if (ps_menu) DestroyMenu(ps_menu); if (ps_menu) DestroyMenu(ps_menu);
psDestroyIcons(); psDestroyIcons();
@ -1742,6 +1784,7 @@ namespace {
void psUserActionDone() { void psUserActionDone() {
_lastUserAction = getms(true); _lastUserAction = getms(true);
if (sessionLoggedOff) sessionLoggedOff = false;
} }
uint64 psIdleTime() { uint64 psIdleTime() {
@ -1750,6 +1793,22 @@ uint64 psIdleTime() {
return GetLastInputInfo(&lii) ? (GetTickCount() - lii.dwTime) : (getms(true) - _lastUserAction); return GetLastInputInfo(&lii) ? (GetTickCount() - lii.dwTime) : (getms(true) - _lastUserAction);
} }
bool psSkipAudioNotify() {
QUERY_USER_NOTIFICATION_STATE state;
if (useShellapi && SUCCEEDED(shQueryUserNotificationState(&state))) {
if (state == QUNS_NOT_PRESENT || state == QUNS_PRESENTATION_MODE) return true;
}
return sessionLoggedOff;
}
bool psSkipDesktopNotify() {
QUERY_USER_NOTIFICATION_STATE state;
if (useShellapi && SUCCEEDED(shQueryUserNotificationState(&state))) {
if (state == QUNS_PRESENTATION_MODE || state == QUNS_RUNNING_D3D_FULL_SCREEN || state == QUNS_BUSY) return true;
}
return false;
}
QStringList psInitLogs() { QStringList psInitLogs() {
return _initLogs; return _initLogs;
} }
@ -2400,6 +2459,7 @@ void psExecUpdater() {
QString targs = qsl("-update"); QString targs = qsl("-update");
if (cFromAutoStart()) targs += qsl(" -autostart"); if (cFromAutoStart()) targs += qsl(" -autostart");
if (cDebug()) targs += qsl(" -debug"); if (cDebug()) targs += qsl(" -debug");
if (cStartInTray()) targs += qsl(" -startintray");
if (cWriteProtected()) targs += qsl(" -writeprotected \"") + cExeDir() + '"'; if (cWriteProtected()) targs += qsl(" -writeprotected \"") + cExeDir() + '"';
QString updaterPath = cWriteProtected() ? (cWorkingDir() + qsl("tupdates/ready/Updater.exe")) : (cExeDir() + qsl("Updater.exe")); QString updaterPath = cWriteProtected() ? (cWorkingDir() + qsl("tupdates/ready/Updater.exe")) : (cExeDir() + qsl("Updater.exe"));
@ -2420,6 +2480,7 @@ void psExecTelegram() {
if (cRestartingToSettings()) targs += qsl(" -tosettings"); if (cRestartingToSettings()) targs += qsl(" -tosettings");
if (cFromAutoStart()) targs += qsl(" -autostart"); if (cFromAutoStart()) targs += qsl(" -autostart");
if (cDebug()) targs += qsl(" -debug"); if (cDebug()) targs += qsl(" -debug");
if (cStartInTray()) targs += qsl(" -startintray");
if (cDataFile() != (cTestMode() ? qsl("data_test") : qsl("data"))) targs += qsl(" -key \"") + cDataFile() + '"'; if (cDataFile() != (cTestMode() ? qsl("data_test") : qsl("data"))) targs += qsl(" -key \"") + cDataFile() + '"';
QString telegram(QDir::toNativeSeparators(cExeDir() + QString::fromWCharArray(AppFile) + qsl(".exe"))), wdir(QDir::toNativeSeparators(cWorkingDir())); QString telegram(QDir::toNativeSeparators(cExeDir() + QString::fromWCharArray(AppFile) + qsl(".exe"))), wdir(QDir::toNativeSeparators(cWorkingDir()));

View File

@ -170,6 +170,9 @@ private:
void psUserActionDone(); void psUserActionDone();
uint64 psIdleTime(); uint64 psIdleTime();
bool psSkipAudioNotify();
bool psSkipDesktopNotify();
QStringList psInitLogs(); QStringList psInitLogs();
void psClearInitLogs(); void psClearInitLogs();

View File

@ -37,6 +37,7 @@ bool gSoundNotify = true;
bool gDesktopNotify = true; bool gDesktopNotify = true;
DBINotifyView gNotifyView = dbinvShowPreview; DBINotifyView gNotifyView = dbinvShowPreview;
bool gStartMinimized = false; bool gStartMinimized = false;
bool gStartInTray = false;
bool gAutoStart = false; bool gAutoStart = false;
bool gSendToMenu = false; bool gSendToMenu = false;
bool gAutoUpdate = true; bool gAutoUpdate = true;
@ -151,6 +152,8 @@ void settingsParseArgs(int argc, char *argv[]) {
gNoStartUpdate = true; gNoStartUpdate = true;
} else if (string("-tosettings") == argv[i]) { } else if (string("-tosettings") == argv[i]) {
gStartToSettings = true; gStartToSettings = true;
} else if (string("-startintray") == argv[i]) {
gStartInTray = true;
} else if (string("-sendpath") == argv[i] && i + 1 < argc) { } else if (string("-sendpath") == argv[i] && i + 1 < argc) {
for (++i; i < argc; ++i) { for (++i; i < argc; ++i) {
gSendPaths.push_back(QString::fromLocal8Bit(argv[i])); gSendPaths.push_back(QString::fromLocal8Bit(argv[i]));
@ -169,7 +172,7 @@ void settingsParseArgs(int argc, char *argv[]) {
const RecentEmojiPack &cGetRecentEmojis() { const RecentEmojiPack &cGetRecentEmojis() {
if (cRecentEmojis().isEmpty()) { if (cRecentEmojis().isEmpty()) {
RecentEmojiPack r; RecentEmojiPack r;
if (false && !cRecentEmojisPreload().isEmpty()) { if (!cRecentEmojisPreload().isEmpty()) {
RecentEmojiPreload p(cRecentEmojisPreload()); RecentEmojiPreload p(cRecentEmojisPreload());
cSetRecentEmojisPreload(RecentEmojiPreload()); cSetRecentEmojisPreload(RecentEmojiPreload());
r.reserve(p.size()); r.reserve(p.size());

View File

@ -46,6 +46,7 @@ DeclareSetting(QString, LoggedPhoneNumber);
DeclareReadSetting(uint32, ConnectionsInSession); DeclareReadSetting(uint32, ConnectionsInSession);
DeclareSetting(bool, AutoStart); DeclareSetting(bool, AutoStart);
DeclareSetting(bool, StartMinimized); DeclareSetting(bool, StartMinimized);
DeclareSetting(bool, StartInTray);
DeclareSetting(bool, SendToMenu); DeclareSetting(bool, SendToMenu);
DeclareReadSetting(bool, FromAutoStart); DeclareReadSetting(bool, FromAutoStart);
DeclareSetting(QString, WorkingDir); DeclareSetting(QString, WorkingDir);

View File

@ -302,7 +302,7 @@ void TitleWidget::showUpdateBtn() {
_update.hide(); _update.hide();
if (cPlatform() == dbipWindows) { if (cPlatform() == dbipWindows) {
_minimize.show(); _minimize.show();
maximizedChanged(wnd->windowState().testFlag(Qt::WindowMaximized), true); maximizedChanged(lastMaximized, true);
_close.show(); _close.show();
} }
anim::stop(this); anim::stop(this);

View File

@ -1133,7 +1133,7 @@ void Window::notifySchedule(History *history, MsgId msgId) {
uint64 when = getms(true) + delay; uint64 when = getms(true) + delay;
notifyWhenAlerts[history].insert(when, NullType()); notifyWhenAlerts[history].insert(when, NullType());
if (cDesktopNotify()) { if (cDesktopNotify() && !psSkipDesktopNotify()) {
NotifyWhenMaps::iterator i = notifyWhenMaps.find(history); NotifyWhenMaps::iterator i = notifyWhenMaps.find(history);
if (i == notifyWhenMaps.end()) { if (i == notifyWhenMaps.end()) {
i = notifyWhenMaps.insert(history, NotifyWhenMap()); i = notifyWhenMaps.insert(history, NotifyWhenMap());
@ -1256,7 +1256,7 @@ void Window::notifyShowNext(NotifyWindow *remove) {
--count; --count;
} }
} }
if (count <= 0 || !cDesktopNotify()) { if (count <= 0 || notifyWaiters.isEmpty() || !cDesktopNotify() || psSkipDesktopNotify()) {
if (nextAlert) { if (nextAlert) {
notifyWaitTimer.start(nextAlert - ms); notifyWaitTimer.start(nextAlert - ms);
} }

View File

@ -1780,6 +1780,7 @@
<None Include="SourceFiles\langs\lang_de.strings" /> <None Include="SourceFiles\langs\lang_de.strings" />
<None Include="SourceFiles\langs\lang_es.strings" /> <None Include="SourceFiles\langs\lang_es.strings" />
<None Include="SourceFiles\langs\lang_it.strings" /> <None Include="SourceFiles\langs\lang_it.strings" />
<None Include="SourceFiles\langs\lang_ko.strings" />
<None Include="SourceFiles\langs\lang_nl.strings" /> <None Include="SourceFiles\langs\lang_nl.strings" />
<None Include="SourceFiles\langs\lang_pt_BR.strings" /> <None Include="SourceFiles\langs\lang_pt_BR.strings" />
</ItemGroup> </ItemGroup>

View File

@ -1060,5 +1060,8 @@
<None Include="SourceFiles\langs\lang_pt_BR.strings"> <None Include="SourceFiles\langs\lang_pt_BR.strings">
<Filter>langs</Filter> <Filter>langs</Filter>
</None> </None>
<None Include="SourceFiles\langs\lang_ko.strings">
<Filter>langs</Filter>
</None>
</ItemGroup> </ItemGroup>
</Project> </Project>