diff --git a/Telegram/Resources/basic.style b/Telegram/Resources/basic.style index 5b3a6aa48..36f48aa70 100644 --- a/Telegram/Resources/basic.style +++ b/Telegram/Resources/basic.style @@ -402,25 +402,12 @@ noContactsHeight: 100px; noContactsFont: font(fsize); noContactsColor: #777777; -fieldSearchIcon: icon {{ "box_search", #aaaaaa, point(10px, 9px) }}; -dlgFilter: flatInput(inpDefGray) { - font: font(fsize); - bgColor: #f2f2f2; - phColor: #949494; - phFocusColor: #a4a4a4; - icon: fieldSearchIcon; - - width: 240px; - height: 34px; - textMrg: margins(34px, 2px, 34px, 4px); -} - topBarHeight: 54px; topBarDuration: 200; -topBarForward: icon {{ "title_next", #a3a3a3 }}; -topBarBackward: icon {{ "title_previous", #a3a3a3 }}; +topBarForward: icon {{ "title_back-flip_horizontal", #a3a3a3 }}; +topBarBackward: icon {{ "title_back", #a3a3a3 }}; topBarForwardAlpha: 0.6; -topBarBack: icon {{ "title_previous", #259fd8 }}; +topBarBack: icon {{ "title_back", #259fd8 }}; topBarBackAlpha: 0.8; topBarBackColor: #005faf; topBarBackFont: font(16px); @@ -1104,15 +1091,15 @@ infoButton: PeerAvatarButton { photoSize: 42px; } -// forward declaration for single "title_previous" usage. +// forward declaration for single "title_back" usage. profileTopBarBackIconFg: #0290d7; -profileTopBarBackIcon: icon {{ "title_previous", profileTopBarBackIconFg }}; +profileTopBarBackIcon: icon {{ "title_back", profileTopBarBackIconFg }}; historyReplyCancelIcon: icon {{ "box_button_close-invert", historyReplyBg }}; boxSearchCancelIcon: icon {{ "box_button_close-invert", boxSearchBg }}; settingsFixedBarCloseIcon: icon {{ "box_button_close-invert", settingsFixedBarBg }}; -notifyFadeRight: icon {{ "fade_horizontal_right", notificationBg }}; +notifyFadeRight: icon {{ "fade_horizontal", notificationBg }}; -stickerIconLeft: icon {{ "fade_horizontal_left", emojiPanCategories }}; -stickerIconRight: icon {{ "fade_horizontal_right", emojiPanCategories }}; +stickerIconLeft: icon {{ "fade_horizontal-flip_horizontal", emojiPanCategories }}; +stickerIconRight: icon {{ "fade_horizontal", emojiPanCategories }}; diff --git a/Telegram/Resources/colors.palette b/Telegram/Resources/colors.palette index c449b8ed8..da55dde33 100644 --- a/Telegram/Resources/colors.palette +++ b/Telegram/Resources/colors.palette @@ -24,7 +24,7 @@ windowBg: #ffffff; // white: fallback for background windowTextFg: #000000; // black: fallback for text color windowSubTextFg: #8a8a8a; // gray: fallback for subtext color windowActiveFill: #40ace3; // bright blue: fallback for blue filled active areas -windowOverBg: #edf2f5; // light blue: fallback for over background +windowOverBg: #f3f3f3; // light blue: fallback for over background windowSubTextFgOver: #7c99b2; // gray over light blue: fallback for subtext over color windowActiveTextFg: #1485c2; // online blue: fallback for active color windowShadowFg: #000000; // black: fallback for shadow color @@ -32,22 +32,7 @@ windowShadowFg: #000000; // black: fallback for shadow color imageBg: #000000; imageBgTransparent: #ffffff; -// custom title bar for Windows -titleBg: #f3f3f3; -titleShadow: #00000003; -titleButtonFg: #ababab; -titleButtonBgOver: #e5e5e5; -titleButtonFgOver: #9a9a9a; -titleButtonCloseBgOver: #e81123; -titleButtonCloseFgOver: #ffffff; - -// tray icon -trayCounterBg: #f23c34; -trayCounterBgMute: #888888; -trayCounterFg: #ffffff; -trayCounterBgMacInvert: #ffffff; -trayCounterFgMacInvert: #ffffff01; - +// widgets cancelIconFg: #a2a2a2; cancelIconFgOver: #808080; @@ -63,6 +48,24 @@ lightButtonBgOver: #f2f7fa | lightButtonBg; lightButtonFg: #2b99d5; lightButtonFgOver: lightButtonFg; +menuIconFg: #808080 | windowSubTextFg; + +// custom title bar for Windows +titleBg: windowOverBg; +titleShadow: #00000003; +titleButtonFg: #ababab; +titleButtonBgOver: #e5e5e5; +titleButtonFgOver: #9a9a9a; +titleButtonCloseBgOver: #e81123; +titleButtonCloseFgOver: #ffffff; + +// tray icon +trayCounterBg: #f23c34; +trayCounterBgMute: #888888; +trayCounterFg: #ffffff; +trayCounterBgMacInvert: #ffffff; +trayCounterFgMacInvert: #ffffff01; + // layers layerBg: #0000007f; diff --git a/Telegram/Resources/icons/dialogs_add_contact.png b/Telegram/Resources/icons/dialogs_add_contact.png deleted file mode 100644 index 0569c8732..000000000 Binary files a/Telegram/Resources/icons/dialogs_add_contact.png and /dev/null differ diff --git a/Telegram/Resources/icons/dialogs_add_contact@2x.png b/Telegram/Resources/icons/dialogs_add_contact@2x.png deleted file mode 100644 index 6fca9095d..000000000 Binary files a/Telegram/Resources/icons/dialogs_add_contact@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/dialogs_menu.png b/Telegram/Resources/icons/dialogs_menu.png new file mode 100644 index 000000000..9e3833ce6 Binary files /dev/null and b/Telegram/Resources/icons/dialogs_menu.png differ diff --git a/Telegram/Resources/icons/dialogs_menu@2x.png b/Telegram/Resources/icons/dialogs_menu@2x.png new file mode 100644 index 000000000..a5beed83c Binary files /dev/null and b/Telegram/Resources/icons/dialogs_menu@2x.png differ diff --git a/Telegram/Resources/icons/emoji_switch_right.png b/Telegram/Resources/icons/emoji_switch.png similarity index 100% rename from Telegram/Resources/icons/emoji_switch_right.png rename to Telegram/Resources/icons/emoji_switch.png diff --git a/Telegram/Resources/icons/emoji_switch_right@2x.png b/Telegram/Resources/icons/emoji_switch@2x.png similarity index 100% rename from Telegram/Resources/icons/emoji_switch_right@2x.png rename to Telegram/Resources/icons/emoji_switch@2x.png diff --git a/Telegram/Resources/icons/emoji_switch_left.png b/Telegram/Resources/icons/emoji_switch_left.png deleted file mode 100644 index c4b3f9089..000000000 Binary files a/Telegram/Resources/icons/emoji_switch_left.png and /dev/null differ diff --git a/Telegram/Resources/icons/emoji_switch_left@2x.png b/Telegram/Resources/icons/emoji_switch_left@2x.png deleted file mode 100644 index 63c5dc067..000000000 Binary files a/Telegram/Resources/icons/emoji_switch_left@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/fade_horizontal_right.png b/Telegram/Resources/icons/fade_horizontal.png similarity index 100% rename from Telegram/Resources/icons/fade_horizontal_right.png rename to Telegram/Resources/icons/fade_horizontal.png diff --git a/Telegram/Resources/icons/fade_horizontal_right@2x.png b/Telegram/Resources/icons/fade_horizontal@2x.png similarity index 100% rename from Telegram/Resources/icons/fade_horizontal_right@2x.png rename to Telegram/Resources/icons/fade_horizontal@2x.png diff --git a/Telegram/Resources/icons/fade_horizontal_left.png b/Telegram/Resources/icons/fade_horizontal_left.png deleted file mode 100644 index 93db9ad4c..000000000 Binary files a/Telegram/Resources/icons/fade_horizontal_left.png and /dev/null differ diff --git a/Telegram/Resources/icons/fade_horizontal_left@2x.png b/Telegram/Resources/icons/fade_horizontal_left@2x.png deleted file mode 100644 index d4e9f55a1..000000000 Binary files a/Telegram/Resources/icons/fade_horizontal_left@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/mediaview_previous.png b/Telegram/Resources/icons/mediaview_previous.png deleted file mode 100644 index 8fb04e034..000000000 Binary files a/Telegram/Resources/icons/mediaview_previous.png and /dev/null differ diff --git a/Telegram/Resources/icons/mediaview_previous@2x.png b/Telegram/Resources/icons/mediaview_previous@2x.png deleted file mode 100644 index d746a1056..000000000 Binary files a/Telegram/Resources/icons/mediaview_previous@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/menu_contacts.png b/Telegram/Resources/icons/menu_contacts.png new file mode 100644 index 000000000..5df86715b Binary files /dev/null and b/Telegram/Resources/icons/menu_contacts.png differ diff --git a/Telegram/Resources/icons/menu_contacts@2x.png b/Telegram/Resources/icons/menu_contacts@2x.png new file mode 100644 index 000000000..5b879588a Binary files /dev/null and b/Telegram/Resources/icons/menu_contacts@2x.png differ diff --git a/Telegram/Resources/icons/menu_help.png b/Telegram/Resources/icons/menu_help.png new file mode 100644 index 000000000..80de9d1ea Binary files /dev/null and b/Telegram/Resources/icons/menu_help.png differ diff --git a/Telegram/Resources/icons/menu_help@2x.png b/Telegram/Resources/icons/menu_help@2x.png new file mode 100644 index 000000000..1444e19c9 Binary files /dev/null and b/Telegram/Resources/icons/menu_help@2x.png differ diff --git a/Telegram/Resources/icons/menu_new_channel.png b/Telegram/Resources/icons/menu_new_channel.png new file mode 100644 index 000000000..03a1b1f40 Binary files /dev/null and b/Telegram/Resources/icons/menu_new_channel.png differ diff --git a/Telegram/Resources/icons/menu_new_channel@2x.png b/Telegram/Resources/icons/menu_new_channel@2x.png new file mode 100644 index 000000000..f84f7b6ac Binary files /dev/null and b/Telegram/Resources/icons/menu_new_channel@2x.png differ diff --git a/Telegram/Resources/icons/menu_new_group.png b/Telegram/Resources/icons/menu_new_group.png new file mode 100644 index 000000000..4d9b1380f Binary files /dev/null and b/Telegram/Resources/icons/menu_new_group.png differ diff --git a/Telegram/Resources/icons/menu_new_group@2x.png b/Telegram/Resources/icons/menu_new_group@2x.png new file mode 100644 index 000000000..3512799e6 Binary files /dev/null and b/Telegram/Resources/icons/menu_new_group@2x.png differ diff --git a/Telegram/Resources/icons/menu_settings.png b/Telegram/Resources/icons/menu_settings.png new file mode 100644 index 000000000..355f00e2e Binary files /dev/null and b/Telegram/Resources/icons/menu_settings.png differ diff --git a/Telegram/Resources/icons/menu_settings@2x.png b/Telegram/Resources/icons/menu_settings@2x.png new file mode 100644 index 000000000..17d626cb7 Binary files /dev/null and b/Telegram/Resources/icons/menu_settings@2x.png differ diff --git a/Telegram/Resources/icons/player_panel_previous.png b/Telegram/Resources/icons/player_panel_previous.png deleted file mode 100644 index 4460c3daf..000000000 Binary files a/Telegram/Resources/icons/player_panel_previous.png and /dev/null differ diff --git a/Telegram/Resources/icons/player_panel_previous@2x.png b/Telegram/Resources/icons/player_panel_previous@2x.png deleted file mode 100644 index bb31bf531..000000000 Binary files a/Telegram/Resources/icons/player_panel_previous@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/player_previous.png b/Telegram/Resources/icons/player_previous.png deleted file mode 100644 index cd71dc0ed..000000000 Binary files a/Telegram/Resources/icons/player_previous.png and /dev/null differ diff --git a/Telegram/Resources/icons/player_previous@2x.png b/Telegram/Resources/icons/player_previous@2x.png deleted file mode 100644 index 3ddcc5ab5..000000000 Binary files a/Telegram/Resources/icons/player_previous@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/dialogs_new_chat.png b/Telegram/Resources/icons/settings_edit_name.png similarity index 100% rename from Telegram/Resources/icons/dialogs_new_chat.png rename to Telegram/Resources/icons/settings_edit_name.png diff --git a/Telegram/Resources/icons/dialogs_new_chat@2x.png b/Telegram/Resources/icons/settings_edit_name@2x.png similarity index 100% rename from Telegram/Resources/icons/dialogs_new_chat@2x.png rename to Telegram/Resources/icons/settings_edit_name@2x.png diff --git a/Telegram/Resources/icons/title_previous.png b/Telegram/Resources/icons/title_back.png similarity index 100% rename from Telegram/Resources/icons/title_previous.png rename to Telegram/Resources/icons/title_back.png diff --git a/Telegram/Resources/icons/title_previous@2x.png b/Telegram/Resources/icons/title_back@2x.png similarity index 100% rename from Telegram/Resources/icons/title_previous@2x.png rename to Telegram/Resources/icons/title_back@2x.png diff --git a/Telegram/Resources/icons/title_button_lock.png b/Telegram/Resources/icons/title_button_lock.png deleted file mode 100644 index 61984e5df..000000000 Binary files a/Telegram/Resources/icons/title_button_lock.png and /dev/null differ diff --git a/Telegram/Resources/icons/title_button_lock@2x.png b/Telegram/Resources/icons/title_button_lock@2x.png deleted file mode 100644 index 578eec430..000000000 Binary files a/Telegram/Resources/icons/title_button_lock@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/title_button_unlock.png b/Telegram/Resources/icons/title_button_unlock.png deleted file mode 100644 index 37031e3d7..000000000 Binary files a/Telegram/Resources/icons/title_button_unlock.png and /dev/null differ diff --git a/Telegram/Resources/icons/title_button_unlock@2x.png b/Telegram/Resources/icons/title_button_unlock@2x.png deleted file mode 100644 index 3e99f232b..000000000 Binary files a/Telegram/Resources/icons/title_button_unlock@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/title_next.png b/Telegram/Resources/icons/title_next.png deleted file mode 100644 index 62fd6f276..000000000 Binary files a/Telegram/Resources/icons/title_next.png and /dev/null differ diff --git a/Telegram/Resources/icons/title_next@2x.png b/Telegram/Resources/icons/title_next@2x.png deleted file mode 100644 index 04dd1b4c6..000000000 Binary files a/Telegram/Resources/icons/title_next@2x.png and /dev/null differ diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 48c1fb41f..c7b5a66fc 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -519,9 +519,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_create_group_next" = "Next"; "lng_create_group_create" = "Create"; "lng_create_group_title" = "New Group"; -"lng_create_group_about" = "Groups are ideal for limited communities,\nthey can have up to {count:_not_used|# member|# members}"; "lng_create_channel_title" = "New Channel"; -"lng_create_channel_about" = "Channels are a tool for broadcasting your messages to unlimited audiences"; "lng_create_public_channel_title" = "Public Channel"; "lng_create_public_channel_about" = "Anyone can find the channel in search and join"; "lng_create_private_channel_title" = "Private Channel"; diff --git a/Telegram/Resources/sample.tdesktop-theme b/Telegram/Resources/sample.tdesktop-theme index 93f199062..5c61386ef 100644 --- a/Telegram/Resources/sample.tdesktop-theme +++ b/Telegram/Resources/sample.tdesktop-theme @@ -25,24 +25,12 @@ windowBg: #ffffff; windowTextFg: #000000; windowSubTextFg: #8a8a8a; windowActiveFill: #40ace3; -windowOverBg: #edf2f5; +windowOverBg: #f3f3f3; windowSubTextFgOver: #7c99b2; windowActiveTextFg: #1485c2; windowShadowFg: #000000; imageBg: #000000; imageBgTransparent: #ffffff; -titleBg: #f3f3f3; -titleShadow: #00000003; -titleButtonFg: #ababab; -titleButtonBgOver: #e5e5e5; -titleButtonFgOver: #9a9a9a; -titleButtonCloseBgOver: #e81123; -titleButtonCloseFgOver: #ffffff; -trayCounterBg: #f23c34; -trayCounterBgMute: #888888; -trayCounterFg: #ffffff; -trayCounterBgMacInvert: #ffffff; -trayCounterFgMacInvert: #ffffff01; cancelIconFg: #a2a2a2; cancelIconFgOver: #808080; activeButtonBg: windowActiveFill; @@ -55,6 +43,19 @@ lightButtonBg: windowBg; lightButtonBgOver: #f2f7fa; // lightButtonBg; lightButtonFg: #2b99d5; lightButtonFgOver: lightButtonFg; +menuIconFg: #808080; // windowSubTextFg; +titleBg: windowOverBg; +titleShadow: #00000003; +titleButtonFg: #ababab; +titleButtonBgOver: #e5e5e5; +titleButtonFgOver: #9a9a9a; +titleButtonCloseBgOver: #e81123; +titleButtonCloseFgOver: #ffffff; +trayCounterBg: #f23c34; +trayCounterBgMute: #888888; +trayCounterFg: #ffffff; +trayCounterBgMacInvert: #ffffff; +trayCounterFgMacInvert: #ffffff01; layerBg: #0000007f; boxBg: windowBg; boxTextFg: windowTextFg; diff --git a/Telegram/SourceFiles/boxes/addcontactbox.cpp b/Telegram/SourceFiles/boxes/addcontactbox.cpp index 9cf16de1e..17bf2fea9 100644 --- a/Telegram/SourceFiles/boxes/addcontactbox.cpp +++ b/Telegram/SourceFiles/boxes/addcontactbox.cpp @@ -260,64 +260,6 @@ void AddContactBox::onRetry() { update(); } -NewGroupBox::NewGroupBox() : AbstractBox(), -_group(this, qsl("group_type"), 0, lang(lng_create_group_title), true), -_channel(this, qsl("group_type"), 1, lang(lng_create_channel_title)), -_aboutGroupWidth(width() - st::boxPadding.left() - st::boxButtonPadding.right() - st::newGroupPadding.left() - st::defaultRadiobutton.textPosition.x()), -_aboutGroup(st::normalFont, lng_create_group_about(lt_count, Global::MegagroupSizeMax()), _defaultOptions, _aboutGroupWidth), -_aboutChannel(st::normalFont, lang(lng_create_channel_about), _defaultOptions, _aboutGroupWidth), -_next(this, lang(lng_create_group_next), st::defaultBoxButton), -_cancel(this, lang(lng_cancel), st::cancelBoxButton) { - _aboutGroupHeight = _aboutGroup.countHeight(_aboutGroupWidth); - setMaxHeight(st::boxPadding.top() + st::newGroupPadding.top() + _group->height() + _aboutGroupHeight + st::newGroupSkip + _channel->height() + _aboutChannel.countHeight(_aboutGroupWidth) + st::newGroupPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _next->height() + st::boxButtonPadding.bottom()); - - connect(_next, SIGNAL(clicked()), this, SLOT(onNext())); - connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); - - prepare(); -} - -void NewGroupBox::showAll() { - _group->show(); - _channel->show(); - _cancel->show(); - _next->show(); -} - -void NewGroupBox::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { - onNext(); - } else { - AbstractBox::keyPressEvent(e); - } -} - -void NewGroupBox::paintEvent(QPaintEvent *e) { - Painter p(this); - if (paint(p)) return; - - p.setPen(st::newGroupAboutFg->p); - - QRect aboutGroup(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultRadiobutton.textPosition.x(), _group->y() + _group->height() + st::lineWidth, _aboutGroupWidth, _aboutGroupHeight); - _aboutGroup.drawLeft(p, aboutGroup.x(), aboutGroup.y(), aboutGroup.width(), width()); - - QRect aboutChannel(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultRadiobutton.textPosition.x(), _channel->y() + _channel->height() + st::lineWidth, _aboutGroupWidth, _aboutGroupHeight); - _aboutChannel.drawLeft(p, aboutChannel.x(), aboutChannel.y(), aboutChannel.width(), width()); -} - -void NewGroupBox::resizeEvent(QResizeEvent *e) { - _group->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), st::boxPadding.top() + st::newGroupPadding.top()); - _channel->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), _group->y() + _group->height() + _aboutGroupHeight + st::newGroupSkip); - - _next->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _next->height()); - _cancel->moveToRight(st::boxButtonPadding.right() + _next->width() + st::boxButtonPadding.left(), _next->y()); - AbstractBox::resizeEvent(e); -} - -void NewGroupBox::onNext() { - Ui::showLayer(new GroupInfoBox(_group->checked() ? CreatingGroupGroup : CreatingGroupChannel, true), KeepOtherLayers); -} - GroupInfoBox::GroupInfoBox(CreatingGroupType creating, bool fromTypeChoose) : AbstractBox(), _creating(creating), a_photoOver(0, 0), diff --git a/Telegram/SourceFiles/boxes/addcontactbox.h b/Telegram/SourceFiles/boxes/addcontactbox.h index d38ca6095..805426311 100644 --- a/Telegram/SourceFiles/boxes/addcontactbox.h +++ b/Telegram/SourceFiles/boxes/addcontactbox.h @@ -78,34 +78,6 @@ private: QString _sentName; }; -class NewGroupBox : public AbstractBox { - Q_OBJECT - -public: - NewGroupBox(); - -public slots: - void onNext(); - -protected: - void keyPressEvent(QKeyEvent *e) override; - void paintEvent(QPaintEvent *e) override; - void resizeEvent(QResizeEvent *e) override; - - void showAll() override; - -private: - ChildWidget _group; - ChildWidget _channel; - - int32 _aboutGroupWidth, _aboutGroupHeight; - Text _aboutGroup, _aboutChannel; - - ChildWidget _next; - ChildWidget _cancel; - -}; - class GroupInfoBox : public AbstractBox, public RPCSender { Q_OBJECT diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index 1852efe0c..ac9b071f3 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -19,6 +19,7 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ using "basic.style"; + using "ui/widgets/widgets.style"; using "intro/intro.style"; @@ -143,7 +144,7 @@ contactsMultiSelect: MultiSelect { font: normalFont; } fieldMinWidth: 42px; - fieldIcon: fieldSearchIcon; + fieldIcon: boxFieldSearchIcon; fieldIconSkip: 36px; fieldCancel: MaskButton(defaultMaskButton) { diff --git a/Telegram/SourceFiles/codegen/style/generator.cpp b/Telegram/SourceFiles/codegen/style/generator.cpp index 22e879252..0b1db3d34 100644 --- a/Telegram/SourceFiles/codegen/style/generator.cpp +++ b/Telegram/SourceFiles/codegen/style/generator.cpp @@ -38,8 +38,8 @@ namespace codegen { namespace style { namespace { -constexpr int kErrorBadIconSize = 861; -constexpr int kErrorBadIconFormat = 862; +constexpr int kErrorBadIconSize = 861; +constexpr int kErrorBadIconFormat = 862; // crc32 hash, taken somewhere from the internet @@ -1017,10 +1017,10 @@ QByteArray iconMaskValueSize(int width, int height) { QByteArray iconMaskValuePng(QString filepath) { QByteArray result; - auto inverted = filepath.endsWith("-invert"); - if (inverted) { - filepath.chop(QLatin1String("-invert").size()); - } + auto pathAndModifiers = filepath.split('-'); + filepath = pathAndModifiers[0]; + auto modifiers = pathAndModifiers.mid(1); + QImage png100x(filepath + ".png"); QImage png200x(filepath + "@2x.png"); png100x.setDevicePixelRatio(1.); @@ -1041,9 +1041,13 @@ QByteArray iconMaskValuePng(QString filepath) { common::logError(kErrorBadIconSize, filepath + ".png") << "bad icons size, 1x: " << png100x.width() << "x" << png100x.height() << ", 2x: " << png200x.width() << "x" << png200x.height(); return result; } - if (inverted) { - png100x.invertPixels(); - png200x.invertPixels(); + for (auto modifierName : modifiers) { + if (auto modifier = GetModifier(modifierName)) { + modifier(png100x, png200x); + } else { + common::logError(common::kErrorInternal, filepath) << "modifier should be valid here, name: " << modifierName.toStdString(); + return result; + } } QImage png125x = png200x.scaled(structure::data::pxAdjust(png100x.width(), 5), structure::data::pxAdjust(png100x.height(), 5), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); QImage png150x = png200x.scaled(structure::data::pxAdjust(png100x.width(), 6), structure::data::pxAdjust(png100x.height(), 6), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); diff --git a/Telegram/SourceFiles/codegen/style/parsed_file.cpp b/Telegram/SourceFiles/codegen/style/parsed_file.cpp index 7277dc2e5..a0e77fb5e 100644 --- a/Telegram/SourceFiles/codegen/style/parsed_file.cpp +++ b/Telegram/SourceFiles/codegen/style/parsed_file.cpp @@ -44,6 +44,7 @@ constexpr int kErrorIdentifierNotFound = 804; constexpr int kErrorAlreadyDefined = 805; constexpr int kErrorBadString = 806; constexpr int kErrorIconDuplicate = 807; +constexpr int kErrorBadIconModifier = 808; QString findInputFile(const Options &options) { for (const auto &dir : options.includePaths) { @@ -151,6 +152,25 @@ bool validateAlignString(const QString &value) { } // namespace +Modifier GetModifier(const QString &name) { + static QMap modifiers; + if (modifiers.empty()) { + modifiers.insert("invert", [](QImage &png100x, QImage &png200x) { + png100x.invertPixels(); + png200x.invertPixels(); + }); + modifiers.insert("flip_horizontal", [](QImage &png100x, QImage &png200x) { + png100x = png100x.mirrored(true, false); + png200x = png200x.mirrored(true, false); + }); + modifiers.insert("flip_vertical", [](QImage &png100x, QImage &png200x) { + png100x = png100x.mirrored(false, true); + png200x = png200x.mirrored(false, true); + }); + } + return modifiers.value(name); +} + ParsedFile::ParsedFile(const Options &options) : filePath_(findInputFile(options)) , file_(filePath_) @@ -821,21 +841,26 @@ structure::data::monoicon ParsedFile::readMonoIconFields() { QString ParsedFile::readMonoIconFilename() { if (auto filename = readValue()) { if (filename.type().tag == structure::TypeTag::String) { - auto filepath = QString::fromStdString(filename.String()); - auto inverted = filepath.endsWith("-invert"); - if (inverted) { - filepath.chop(QLatin1String("-invert").size()); - } - for (const auto &path : options_.includePaths) { - QFileInfo fileinfo(path + '/' + filepath + ".png"); - if (fileinfo.exists()) { - return path + '/' + filepath + (inverted ? "-invert" : ""); + auto fullpath = QString::fromStdString(filename.String()); + auto pathAndModifiers = fullpath.split('-'); + auto filepath = pathAndModifiers[0]; + auto modifiers = pathAndModifiers.mid(1); + for (auto modifierName : modifiers) { + if (!GetModifier(modifierName)) { + logError(kErrorBadIconModifier) << "unknown modifier: " << modifierName.toStdString(); + return QString(); } } - for (const auto &path : options_.includePaths) { + for (auto &path : options_.includePaths) { + QFileInfo fileinfo(path + '/' + filepath + ".png"); + if (fileinfo.exists()) { + return path + '/' + fullpath; + } + } + for (auto &path : options_.includePaths) { QFileInfo fileinfo(path + "/icons/" + filepath + ".png"); if (fileinfo.exists()) { - return path + "/icons/" + filepath + (inverted ? "-invert" : ""); + return path + "/icons/" + fullpath; } } logError(common::kErrorFileNotFound) << "could not open icon file '" << filename.String() << "'"; diff --git a/Telegram/SourceFiles/codegen/style/parsed_file.h b/Telegram/SourceFiles/codegen/style/parsed_file.h index 520e0aad2..1c2271fe4 100644 --- a/Telegram/SourceFiles/codegen/style/parsed_file.h +++ b/Telegram/SourceFiles/codegen/style/parsed_file.h @@ -22,6 +22,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include #include +#include +#include #include "codegen/common/basic_tokenized_file.h" #include "codegen/style/options.h" #include "codegen/style/module.h" @@ -29,6 +31,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace codegen { namespace style { +using Modifier = std::function; +Modifier GetModifier(const QString &name); + // Parses an input file to the internal struct. class ParsedFile { public: @@ -44,7 +49,6 @@ public: } private: - bool failed() const { return failed_ || file_.failed(); } diff --git a/Telegram/SourceFiles/core/stl_subset.h b/Telegram/SourceFiles/core/stl_subset.h index 26596b22b..41d4f0007 100644 --- a/Telegram/SourceFiles/core/stl_subset.h +++ b/Telegram/SourceFiles/core/stl_subset.h @@ -59,6 +59,8 @@ template struct remove_reference { using type = T; }; +template +using remove_reference_t = typename remove_reference::type; template struct is_lvalue_reference : false_type { diff --git a/Telegram/SourceFiles/core/utils.h b/Telegram/SourceFiles/core/utils.h index 60a3527b4..7f6ea2715 100644 --- a/Telegram/SourceFiles/core/utils.h +++ b/Telegram/SourceFiles/core/utils.h @@ -25,7 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace base { template -inline constexpr size_t array_size(T(&)[N]) { +inline constexpr size_t array_size(const T(&)[N]) { return N; } @@ -35,6 +35,27 @@ inline T take(T &source, T &&new_value = T()) { return std_::move(new_value); } +namespace internal { + +template +inline constexpr D up_cast_helper(std_::true_type, T object) { + return object; +} + +template +inline constexpr D up_cast_helper(std_::false_type, T object) { + return nullptr; +} + +} // namespace internal + +template +inline constexpr D up_cast(T object) { + using DV = std_::decay_simple_t; + using TV = std_::decay_simple_t; + return internal::up_cast_helper(std_::integral_constant::value || std_::is_same::value>(), object); +} + } // namespace base template diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index c20e90955..cf7470bef 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -48,7 +48,7 @@ dialogsNameFg: #000000; dialogsNameTop: 2px; dialogsRowHeight: 62px; -dialogsFilterPadding: 10px; +dialogsFilterPadding: point(11px, 11px); dialogsPhotoSize: 46px; dialogsPhotoPadding: 12px; dialogsPadding: point(10px, 8px); @@ -83,24 +83,44 @@ dialogsTextStyleDraftActive: textStyle(dialogsTextStyle) { linkFgDown: #c6e1f7; } -dialogsNewChatIcon: icon {{ "dialogs_new_chat", #b7b7b7 }}; -dialogsNewChatButton: IconButton { - width: 36px; - height: 36px; +dialogsMenuToggle: IconButton { + width: 32px; + height: 32px; - icon: dialogsNewChatIcon; - iconPosition: point(9px, 10px); - iconPositionDown: point(9px, 11px); + icon: icon {{ "dialogs_menu", #999999 }}; + iconPosition: point(6px, 6px); + iconPositionDown: point(6px, 6px); } -dialogsAddContact: IconButton(dialogsNewChatButton) { - icon: icon {{ "dialogs_add_contact", #a6a6a6 }}; - iconPosition: point(8px, 8px); - iconPositionDown: point(8px, 9px); +dialogsFilter: flatInput(inpDefGray) { + font: font(fsize); + bgColor: #f2f2f2; + phColor: #949494; + phFocusColor: #a4a4a4; + icon: fieldSearchIcon; + + width: 240px; + height: 32px; + textMrg: margins(32px, 3px, 32px, 3px); } -dialogsCancelSearch: IconButton(dialogsAddContact) { - icon: icon {{ "dialogs_cancel_search", #a6a6a6 }}; +dialogsCancelSearch: IconButton(dialogsMenuToggle) { + icon: icon {{ "dialogs_cancel_search", #a6a6a6, point(0px, 1px) }}; } +dialogsMenu: DropdownMenu(defaultDropdownMenu) { + menu: Menu(defaultMenu) { + skip: 8px; + + itemIconPosition: point(15px, 8px); + itemPadding: margins(56px, 10px, 56px, 12px); + } +} +dialogsMenuPosition: point(-3px, -2px); +dialogsMenuNewGroup: icon {{ "menu_new_group", menuIconFg }}; +dialogsMenuNewChannel: icon {{ "menu_new_channel", menuIconFg }}; +dialogsMenuContacts: icon {{ "menu_contacts", menuIconFg }}; +dialogsMenuSettings: icon {{ "menu_settings", menuIconFg }}; +dialogsMenuHelp: icon {{ "menu_help", menuIconFg }}; + dialogsChatTypeSkip: 22px; dialogsChatIcon: icon {{ "dialogs_chat", #373737, point(1px, 4px) }}; dialogsChatActiveIcon: icon {{ "dialogs_chat", #ffffff, point(1px, 4px) }}; diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index b3d59aac2..c08c99a85 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -36,10 +36,12 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "boxes/addcontactbox.h" #include "boxes/contactsbox.h" #include "boxes/confirmbox.h" +#include "boxes/aboutbox.h" #include "localstorage.h" #include "apiwrap.h" +#include "ui/widgets/dropdown_menu.h" -DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(parent) +DialogsInner::DialogsInner(QWidget *parent, QWidget *main) : SplittedWidget(parent) , dialogs(std_::make_unique(Dialogs::SortMode::Date)) , contactsNoDialogs(std_::make_unique(Dialogs::SortMode::Name)) , contacts(std_::make_unique(Dialogs::SortMode::Name)) @@ -1770,28 +1772,13 @@ MsgId DialogsInner::lastSearchMigratedId() const { return _lastSearchMigratedId; } -DialogsWidget::DialogsWidget(MainWidget *parent) : TWidget(parent) -, _dragInScroll(false) -, _dragForward(false) -, _dialogsFull(false) -, _dialogsOffsetDate(0) -, _dialogsOffsetId(0) -, _dialogsOffsetPeer(0) -, _dialogsRequest(0) -, _contactsRequest(0) -, _filter(this, st::dlgFilter, lang(lng_dlg_filter)) -, _newGroup(this, st::dialogsNewChatButton) -, _addContact(this, st::dialogsAddContact) +DialogsWidget::DialogsWidget(QWidget *parent) : TWidget(parent) +, _mainMenuToggle(this, st::dialogsMenuToggle) +, _filter(this, st::dialogsFilter, lang(lng_dlg_filter)) , _cancelSearch(this, st::dialogsCancelSearch) , _scroll(this, st::dialogsScroll) , _inner(&_scroll, parent) -, _a_show(animation(this, &DialogsWidget::step_show)) -, _searchInPeer(0) -, _searchInMigrated(0) -, _searchFull(false) -, _searchFullMigrated(false) -, _peopleFull(false) -{ +, _a_show(animation(this, &DialogsWidget::step_show)) { _scroll.setWidget(&_inner); _scroll.setFocusPolicy(Qt::NoFocus); connect(&_inner, SIGNAL(mustScrollTo(int,int)), &_scroll, SLOT(scrollToY(int,int))); @@ -1803,14 +1790,13 @@ DialogsWidget::DialogsWidget(MainWidget *parent) : TWidget(parent) connect(&_inner, SIGNAL(cancelSearchInPeer()), this, SLOT(onCancelSearchInPeer())); connect(&_scroll, SIGNAL(geometryChanged()), &_inner, SLOT(onParentGeometryChanged())); connect(&_scroll, SIGNAL(scrolled()), this, SLOT(onListScroll())); - connect(&_filter, SIGNAL(cancelled()), this, SLOT(onCancel())); - connect(&_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate())); - connect(&_filter, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(onFilterCursorMoved(int,int))); - connect(parent, SIGNAL(dialogsUpdated()), this, SLOT(onListScroll())); - connect(_addContact, SIGNAL(clicked()), this, SLOT(onAddContact())); - connect(_newGroup, SIGNAL(clicked()), this, SLOT(onNewGroup())); + connect(_filter, SIGNAL(cancelled()), this, SLOT(onCancel())); + connect(_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate())); + connect(_filter, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(onFilterCursorMoved(int,int))); connect(_cancelSearch, SIGNAL(clicked()), this, SLOT(onCancelSearch())); + _mainMenuToggle->setClickedCallback([this] { showMainMenu(); }); + _chooseByDragTimer.setSingleShot(true); connect(&_chooseByDragTimer, SIGNAL(timeout()), this, SLOT(onChooseByDrag())); @@ -1819,21 +1805,13 @@ DialogsWidget::DialogsWidget(MainWidget *parent) : TWidget(parent) _searchTimer.setSingleShot(true); connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchMessages())); - _scroll.show(); - _filter.show(); - _filter.move(st::dialogsPadding.x(), st::dialogsFilterPadding); - _filter.setFocusPolicy(Qt::StrongFocus); - _filter.customUpDown(true); - _addContact->hide(); - _newGroup->show(); + _filter->setFocusPolicy(Qt::StrongFocus); + _filter->customUpDown(true); _cancelSearch->hide(); - _newGroup->move(width() - _newGroup->width() - st::dialogsPadding.x(), 0); - _addContact->move(width() - _addContact->width() - st::dialogsPadding.x(), 0); - _cancelSearch->move(width() - _cancelSearch->width() - st::dialogsPadding.x(), 0); } void DialogsWidget::activate() { - _filter.setFocus(); + _filter->setFocus(); _inner.activate(); } @@ -1858,7 +1836,7 @@ void DialogsWidget::dlgUpdated(History *row, MsgId msgId) { } void DialogsWidget::dialogsToUp() { - if (_filter.getLastText().trimmed().isEmpty()) { + if (_filter->getLastText().trimmed().isEmpty()) { _scroll.scrollToY(0); } } @@ -1873,9 +1851,8 @@ void DialogsWidget::showAnimated(Window::SlideDirection direction, const Window: _a_show.stop(); _scroll.hide(); - _filter.hide(); + _filter->hide(); _cancelSearch->hide(); - _newGroup->hide(); int delta = st::slideShift; if (direction == Window::SlideDirection::FromLeft) { @@ -1903,7 +1880,7 @@ void DialogsWidget::step_show(float64 ms, bool timer) { _cacheUnder = _cacheOver = QPixmap(); _scroll.show(); - _filter.show(); + _filter->show(); _a_show.stop(); onFilterUpdate(); @@ -1930,8 +1907,8 @@ void DialogsWidget::updateNotifySettings(PeerData *peer) { void DialogsWidget::notify_userIsContactChanged(UserData *user, bool fromThisApp) { if (fromThisApp) { - _filter.setText(QString()); - _filter.updatePlaceholder(); + _filter->setText(QString()); + _filter->updatePlaceholder(); onFilterUpdate(); } _inner.notify_userIsContactChanged(user, fromThisApp); @@ -2031,7 +2008,7 @@ bool DialogsWidget::dialogsFailed(const RPCError &error, mtpRequestId req) { } bool DialogsWidget::onSearchMessages(bool searchCache) { - QString q = _filter.getLastText().trimmed(); + QString q = _filter->getLastText().trimmed(); if (q.isEmpty()) { if (_searchRequest) { MTP::cancel(_searchRequest); @@ -2098,16 +2075,39 @@ void DialogsWidget::onChooseByDrag() { _inner.choosePeer(); } +void DialogsWidget::showMainMenu() { + if (!_mainMenu) { + _mainMenu.create(this, st::dialogsMenu); + _mainMenu->addAction(lang(lng_create_group_title), [] { + App::wnd()->onShowNewGroup(); + }, &st::dialogsMenuNewGroup); + _mainMenu->addAction(lang(lng_create_channel_title), [] { + App::wnd()->onShowNewChannel(); + }, &st::dialogsMenuNewChannel); + _mainMenu->addAction(lang(lng_menu_contacts), [] { + Ui::showLayer(new ContactsBox()); + }, &st::dialogsMenuContacts); + _mainMenu->addAction(lang(lng_menu_settings), [] { + App::wnd()->showSettings(); + }, &st::dialogsMenuSettings); + _mainMenu->addAction(lang(lng_settings_faq), [] { + QDesktopServices::openUrl(telegramFaqLink()); + }, &st::dialogsMenuHelp); + } + updateMainMenuGeometry(); + _mainMenu->showAnimated(); +} + void DialogsWidget::searchMessages(const QString &query, PeerData *inPeer) { - if ((_filter.getLastText() != query) || (inPeer && inPeer != _searchInPeer && inPeer->migrateTo() != _searchInPeer)) { + if ((_filter->getLastText() != query) || (inPeer && inPeer != _searchInPeer && inPeer->migrateTo() != _searchInPeer)) { if (inPeer) { onCancelSearch(); _searchInPeer = inPeer->migrateTo() ? inPeer->migrateTo() : inPeer; _searchInMigrated = _searchInPeer ? _searchInPeer->migrateFrom() : 0; _inner.searchInPeer(_searchInPeer); } - _filter.setText(query); - _filter.updatePlaceholder(); + _filter->setText(query); + _filter->updatePlaceholder(); onFilterUpdate(true); _searchTimer.stop(); onSearchMessages(); @@ -2371,17 +2371,15 @@ void DialogsWidget::onListScroll() { void DialogsWidget::onFilterUpdate(bool force) { if (_a_show.animating() && !force) return; - QString filterText = _filter.getLastText(); + QString filterText = _filter->getLastText(); _inner.onFilterUpdate(filterText, force); if (filterText.isEmpty()) { _searchCache.clear(); _searchQueries.clear(); _searchQuery = QString(); _cancelSearch->hide(); - _newGroup->show(); } else if (_cancelSearch->isHidden()) { _cancelSearch->show(); - _newGroup->hide(); } if (filterText.size() < MinUsernameLength) { _peopleCache.clear(); @@ -2399,8 +2397,8 @@ void DialogsWidget::searchInPeer(PeerData *peer) { } void DialogsWidget::onFilterCursorMoved(int from, int to) { - if (to < 0) to = _filter.cursorPosition(); - QString t = _filter.getLastText(); + if (to < 0) to = _filter->cursorPosition(); + QString t = _filter->getLastText(); QStringRef r; for (int start = to; start > 0;) { --start; @@ -2415,8 +2413,8 @@ void DialogsWidget::onFilterCursorMoved(int from, int to) { } void DialogsWidget::onCompleteHashtag(QString tag) { - QString t = _filter.getLastText(), r; - int cur = _filter.cursorPosition(); + QString t = _filter->getLastText(), r; + int cur = _filter->cursorPosition(); for (int start = cur; start > 0;) { --start; if (t.size() <= start) break; @@ -2427,8 +2425,8 @@ void DialogsWidget::onCompleteHashtag(QString tag) { } if (cur - start - 1 == tag.size() && cur < t.size() && t.at(cur) == ' ') ++cur; r = t.mid(0, start + 1) + tag + ' ' + t.mid(cur); - _filter.setText(r); - _filter.setCursorPosition(start + 1 + tag.size() + 1); + _filter->setText(r); + _filter->setCursorPosition(start + 1 + tag.size() + 1); onFilterUpdate(true); return; } @@ -2436,22 +2434,23 @@ void DialogsWidget::onCompleteHashtag(QString tag) { } if (!t.at(start).isLetterOrNumber() && t.at(start) != '_') break; } - _filter.setText(t.mid(0, cur) + '#' + tag + ' ' + t.mid(cur)); - _filter.setCursorPosition(cur + 1 + tag.size() + 1); + _filter->setText(t.mid(0, cur) + '#' + tag + ' ' + t.mid(cur)); + _filter->setCursorPosition(cur + 1 + tag.size() + 1); onFilterUpdate(true); } void DialogsWidget::resizeEvent(QResizeEvent *e) { int32 w = width(); - _filter.setGeometry(st::dialogsPadding.x(), st::dialogsFilterPadding, w - 2 * st::dialogsPadding.x(), _filter.height()); - _newGroup->move(w - _newGroup->width() - st::dialogsPadding.x(), _filter.y()); - _addContact->move(w - _addContact->width() - st::dialogsPadding.x(), _filter.y()); - _cancelSearch->move(w - _cancelSearch->width() - st::dialogsPadding.x(), _filter.y()); - _scroll.move(0, _filter.height() + 2 * st::dialogsFilterPadding); + _filter->setGeometryToLeft(st::dialogsFilterPadding.x() * 2 + _mainMenuToggle->width(), st::dialogsFilterPadding.y(), w - 3 * st::dialogsFilterPadding.x() - _mainMenuToggle->width(), _filter->height()); + _mainMenuToggle->moveToLeft(st::dialogsFilterPadding.x(), _filter->y()); + _cancelSearch->moveToRight(st::dialogsFilterPadding.x(), _filter->y()); + _scroll.move(0, _filter->height() + 2 * st::dialogsFilterPadding.y()); + + updateMainMenuGeometry(); int32 addToY = App::main() ? App::main()->contentScrollAddToY() : 0; int32 newScrollY = _scroll.scrollTop() + addToY; - _scroll.resize(w, height() - _filter.y() - _filter.height() - st::dialogsFilterPadding - st::dialogsPadding.y()); + _scroll.resize(w, height() - _filter->y() - _filter->height() - st::dialogsFilterPadding.y() - st::dialogsPadding.y()); if (addToY) { _scroll.scrollToY(newScrollY); } else { @@ -2459,6 +2458,12 @@ void DialogsWidget::resizeEvent(QResizeEvent *e) { } } +void DialogsWidget::updateMainMenuGeometry() { + if (!_mainMenu) return; + + _mainMenu->moveToLeft(st::dialogsMenuPosition.x(), st::dialogsMenuPosition.y()); +} + void DialogsWidget::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Escape) { e->ignore(); @@ -2548,16 +2553,8 @@ Dialogs::IndexedList *DialogsWidget::dialogsList() { return _inner.dialogsList(); } -void DialogsWidget::onAddContact() { - Ui::showLayer(new AddContactBox(), KeepOtherLayers); -} - -void DialogsWidget::onNewGroup() { - Ui::showLayer(new NewGroupBox()); -} - bool DialogsWidget::onCancelSearch() { - bool clearing = !_filter.getLastText().isEmpty(); + bool clearing = !_filter->getLastText().isEmpty(); if (_searchRequest) { MTP::cancel(_searchRequest); _searchRequest = 0; @@ -2571,8 +2568,8 @@ bool DialogsWidget::onCancelSearch() { clearing = true; } _inner.clearFilter(); - _filter.clear(); - _filter.updatePlaceholder(); + _filter->clear(); + _filter->updatePlaceholder(); onFilterUpdate(); return clearing; } @@ -2590,8 +2587,8 @@ void DialogsWidget::onCancelSearchInPeer() { _inner.searchInPeer(0); } _inner.clearFilter(); - _filter.clear(); - _filter.updatePlaceholder(); + _filter->clear(); + _filter->updatePlaceholder(); onFilterUpdate(); if (!Adaptive::OneColumn() && !App::main()->selectingPeer()) { emit cancelled(); diff --git a/Telegram/SourceFiles/dialogswidget.h b/Telegram/SourceFiles/dialogswidget.h index e3aec8945..68a5a2b30 100644 --- a/Telegram/SourceFiles/dialogswidget.h +++ b/Telegram/SourceFiles/dialogswidget.h @@ -31,10 +31,9 @@ class IndexedList; namespace Ui { class IconButton; class PopupMenu; +class DropdownMenu; } // namespace Ui -class MainWidget; - enum DialogsSearchRequestType { DialogsSearchFromStart, DialogsSearchFromOffset, @@ -48,7 +47,7 @@ class DialogsInner : public SplittedWidget, public RPCSender, private base::Subs Q_OBJECT public: - DialogsInner(QWidget *parent, MainWidget *main); + DialogsInner(QWidget *parent, QWidget *main); void dialogsReceived(const QVector &dialogs); void addSavedPeersAfter(const QDateTime &date); @@ -238,7 +237,7 @@ class DialogsWidget : public TWidget, public RPCSender { Q_OBJECT public: - DialogsWidget(MainWidget *parent); + DialogsWidget(QWidget *parent); void dialogsReceived(const MTPmessages_Dialogs &dialogs, mtpRequestId req); void contactsReceived(const MTPcontacts_Contacts &contacts); @@ -295,17 +294,13 @@ public: void notify_historyMuteUpdated(History *history); signals: - void cancelled(); public slots: - void onCancel(); void onListScroll(); void activate(); void onFilterUpdate(bool force = false); - void onAddContact(); - void onNewGroup(); bool onCancelSearch(); void onCancelSearchInPeer(); @@ -319,8 +314,11 @@ public slots: void onChooseByDrag(); private: + void showMainMenu(); + void updateMainMenuGeometry(); - bool _dragInScroll, _dragForward; + bool _dragInScroll = false; + bool _dragForward = false; QTimer _chooseByDragTimer; void unreadCountsReceived(const QVector &dialogs); @@ -329,15 +327,16 @@ private: bool searchFailed(DialogsSearchRequestType type, const RPCError &error, mtpRequestId req); bool peopleFailed(const RPCError &error, mtpRequestId req); - bool _dialogsFull; - int32 _dialogsOffsetDate; - MsgId _dialogsOffsetId; - PeerData *_dialogsOffsetPeer; - mtpRequestId _dialogsRequest, _contactsRequest; + bool _dialogsFull = false; + int32 _dialogsOffsetDate = 0; + MsgId _dialogsOffsetId = 0; + PeerData *_dialogsOffsetPeer = nullptr; + mtpRequestId _dialogsRequest = 0; + mtpRequestId _contactsRequest = 0; - FlatInput _filter; - ChildWidget _newGroup; - ChildWidget _addContact; + ChildWidget _mainMenuToggle; + ChildWidget _mainMenu = { nullptr }; + ChildWidget _filter; ChildWidget _cancelSearch; ScrollArea _scroll; DialogsInner _inner; @@ -347,11 +346,14 @@ private: anim::ivalue a_coordUnder, a_coordOver; anim::fvalue a_progress; - PeerData *_searchInPeer, *_searchInMigrated; + PeerData *_searchInPeer = nullptr; + PeerData *_searchInMigrated = nullptr; QTimer _searchTimer; QString _searchQuery, _peopleQuery; - bool _searchFull, _searchFullMigrated, _peopleFull; + bool _searchFull = false; + bool _searchFullMigrated = false; + bool _peopleFull = false; mtpRequestId _searchRequest, _peopleRequest; typedef QMap SearchCache; diff --git a/Telegram/SourceFiles/intro/intro.style b/Telegram/SourceFiles/intro/intro.style index e2a43097e..a751a9088 100644 --- a/Telegram/SourceFiles/intro/intro.style +++ b/Telegram/SourceFiles/intro/intro.style @@ -151,11 +151,11 @@ introBackButton: IconButton { icon: icon { { size(40px, 40px), #f2f2f2 }, - { "title_previous", #adadad, point(12px, 12px) }, + { "title_back", #adadad, point(12px, 12px) }, }; iconOver: icon { { size(40px, 40px), #eeeeee }, - { "title_previous", #969696, point(12px, 12px) }, + { "title_back", #969696, point(12px, 12px) }, }; iconPosition: point(0px, 0px); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index b9749d72f..db1c94f6f 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -83,6 +83,7 @@ MainWidget::MainWidget(QWidget *parent) : TWidget(parent) updateScrollColors(); connect(_dialogs, SIGNAL(cancelled()), this, SLOT(dialogsCancelled())); + connect(this, SIGNAL(dialogsUpdated()), this, SLOT(onListScroll())); connect(_history, SIGNAL(cancelled()), _dialogs, SLOT(activate())); connect(this, SIGNAL(peerPhotoChanged(PeerData*)), this, SIGNAL(dialogsUpdated())); connect(&noUpdatesTimer, SIGNAL(timeout()), this, SLOT(mtpPing())); @@ -1448,14 +1449,6 @@ void MainWidget::checkLastUpdate(bool afterSleep) { } } -void MainWidget::showAddContact() { - _dialogs->onAddContact(); -} - -void MainWidget::showNewGroup() { - _dialogs->onNewGroup(); -} - void MainWidget::overviewLoaded(History *history, const MTPmessages_Messages &result, mtpRequestId req) { OverviewsPreload::iterator it; MediaOverviewType type = OverviewCount; diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 32cf8519b..8840579ef 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -312,8 +312,6 @@ public: void loadMediaBack(PeerData *peer, MediaOverviewType type, bool many = false); void checkLastUpdate(bool afterSleep); - void showAddContact(); - void showNewGroup(); void serviceNotification(const QString &msg, const MTPMessageMedia &media); void serviceHistoryDone(const MTPmessages_Messages &msgs); diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index 83a2309b6..c91a2b906 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -44,7 +44,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "apiwrap.h" #include "settings/settings_widget.h" #include "platform/platform_notifications_manager.h" -#include "platform/platform_window_title.h" #include "window/notifications_manager.h" #include "window/window_theme.h" #include "window/window_theme_warning.h" @@ -86,7 +85,7 @@ void ConnectingWidget::onReconnect() { MTP::restart(); } -MainWindow::MainWindow() : Platform::MainWindow(), _body(this) { +MainWindow::MainWindow() { icon16 = icon256.scaledToWidth(16, Qt::SmoothTransformation); icon32 = icon256.scaledToWidth(32, Qt::SmoothTransformation); icon64 = icon256.scaledToWidth(64, Qt::SmoothTransformation); @@ -105,15 +104,9 @@ MainWindow::MainWindow() : Platform::MainWindow(), _body(this) { } }); - if (objectName().isEmpty()) { - setObjectName(qsl("MainWindow")); - } - resize(st::windowDefWidth, st::windowDefHeight); + resize(st::windowDefaultWidth, st::windowDefaultHeight); setLocale(QLocale(QLocale::English, QLocale::UnitedStates)); - setCentralWidget(_body); - - QMetaObject::connectSlotsByName(this); _inactiveTimer.setSingleShot(true); connect(&_inactiveTimer, SIGNAL(timeout()), this, SLOT(onInactiveTimer())); @@ -162,26 +155,17 @@ void MainWindow::onStateChanged(Qt::WindowState state) { if (state == Qt::WindowMinimized && cWorkMode() == dbiwmTrayOnly) { App::wnd()->minimizeToTray(); } - psSavePosition(state); + savePosition(state); } void MainWindow::init() { - psInitFrameless(); - setWindowIcon(wndIcon); + Platform::MainWindow::init(); - _title = Platform::CreateTitleWidget(this); + setWindowIcon(wndIcon); Application::instance()->installEventFilter(this); connect(windowHandle(), SIGNAL(windowStateChanged(Qt::WindowState)), this, SLOT(onStateChanged(Qt::WindowState))); connect(windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWindowActiveChanged()), Qt::QueuedConnection); - - QPalette p(palette()); - p.setColor(QPalette::Window, st::windowBg->c); - setPalette(p); - - setMinimumWidth(st::windowMinWidth); - setMinimumHeight(st::windowMinHeight); - psInitSize(); } void MainWindow::onWindowActiveChanged() { @@ -241,9 +225,7 @@ void MainWindow::clearWidgets() { QPixmap MainWindow::grabInner() { QPixmap result; - if (_settings) { - result = myGrab(_settings); - } else if (_intro) { + if (_intro) { result = myGrab(_intro); } else if (_main) { result = myGrab(_main); @@ -274,13 +256,13 @@ void MainWindow::clearPasscode() { } void MainWindow::setupPasscode(bool anim) { - QPixmap bg = grabInner(); + auto bg = grabInner(); if (_passcode) { _passcode->stop_show(); _passcode.destroyDelayed(); } - _passcode.create(_body); + _passcode.create(bodyWidget()); updateControlsGeometry(); if (_main) _main->hide(); @@ -332,7 +314,7 @@ void MainWindow::setupIntro(bool anim) { QPixmap bg = anim ? grabInner() : QPixmap(); clearWidgets(); - _intro.create(_body); + _intro.create(bodyWidget()); updateControlsGeometry(); if (anim) { @@ -382,7 +364,7 @@ void MainWindow::sendServiceHistoryRequest() { void MainWindow::setupMain(bool anim, const MTPUser *self) { QPixmap bg = anim ? grabInner() : QPixmap(); clearWidgets(); - _main.create(_body); + _main.create(bodyWidget()); updateControlsGeometry(); if (anim) { @@ -418,7 +400,7 @@ void MainWindow::showSettings() { } if (!_layerBg) { - _layerBg.create(_body); + _layerBg.create(bodyWidget()); } _settings.create(this); connect(_settings, SIGNAL(destroyed(QObject*)), this, SLOT(onSettingsDestroyed(QObject*))); @@ -492,7 +474,7 @@ void MainWindow::showDocument(DocumentData *doc, HistoryItem *item) { void MainWindow::ui_showLayer(LayerWidget *box, ShowLayerOptions options) { if (box) { if (!_layerBg) { - _layerBg.create(_body); + _layerBg.create(bodyWidget()); } if (options.testFlag(KeepOtherLayers)) { if (options.testFlag(ShowAfterOtherLayers)) { @@ -532,7 +514,7 @@ bool MainWindow::ui_isMediaViewShown() { void MainWindow::ui_showMediaPreview(DocumentData *document) { if (!document || ((!document->isAnimation() || !document->loaded()) && !document->sticker())) return; if (!_mediaPreview) { - _mediaPreview.create(_body); + _mediaPreview.create(bodyWidget()); updateControlsGeometry(); } if (_mediaPreview->isHidden()) { @@ -544,7 +526,7 @@ void MainWindow::ui_showMediaPreview(DocumentData *document) { void MainWindow::ui_showMediaPreview(PhotoData *photo) { if (!photo) return; if (!_mediaPreview) { - _mediaPreview.create(_body); + _mediaPreview.create(bodyWidget()); updateControlsGeometry(); } if (_mediaPreview->isHidden()) { @@ -571,7 +553,7 @@ void MainWindow::showConnecting(const QString &text, const QString &reconnect) { if (_connecting) { _connecting->set(text, reconnect); } else { - _connecting.create(_body, text, reconnect); + _connecting.create(bodyWidget(), text, reconnect); updateControlsGeometry(); fixOrder(); } @@ -586,15 +568,13 @@ void MainWindow::hideConnecting() { void MainWindow::themeUpdated(const Window::Theme::BackgroundUpdate &data) { using Type = Window::Theme::BackgroundUpdate::Type; if (data.type == Type::TestingTheme) { - if (_title) _title->update(); if (!_testingThemeWarning) { - _testingThemeWarning.create(_body); + _testingThemeWarning.create(bodyWidget()); _testingThemeWarning->setGeometry(rect()); _testingThemeWarning->setHiddenCallback([this] { _testingThemeWarning.destroyDelayed(); }); } _testingThemeWarning->showAnimated(); } else if (data.type == Type::RevertingTheme || data.type == Type::ApplyingTheme) { - if (_title) _title->update(); _testingThemeWarning->hideAnimated(); } } @@ -659,44 +639,6 @@ void MainWindow::setInnerFocus() { } } -Window::HitTestResult MainWindow::hitTest(const QPoint &p) const { - int x(p.x()), y(p.y()), w(width()), h(height()); - - const int32 raw = psResizeRowWidth(); - if (!windowState().testFlag(Qt::WindowMaximized)) { - if (y < raw) { - if (x < raw) { - return Window::HitTestResult::TopLeft; - } else if (x > w - raw - 1) { - return Window::HitTestResult::TopRight; - } - return Window::HitTestResult::Top; - } else if (y > h - raw - 1) { - if (x < raw) { - return Window::HitTestResult::BottomLeft; - } else if (x > w - raw - 1) { - return Window::HitTestResult::BottomRight; - } - return Window::HitTestResult::Bottom; - } else if (x < raw) { - return Window::HitTestResult::Left; - } else if (x > w - raw - 1) { - return Window::HitTestResult::Right; - } - } - auto titleTest = _title ? _title->hitTest(p - _title->geometry().topLeft()) : Window::HitTestResult::None; - if (titleTest != Window::HitTestResult::None) { - return titleTest; - } else if (x >= 0 && y >= 0 && x < w && y < h) { - return Window::HitTestResult::Client; - } - return Window::HitTestResult::None; -} - -QRect MainWindow::iconRect() const { - return _title ? _title->iconRect() : QRect(); -} - bool MainWindow::eventFilter(QObject *obj, QEvent *e) { switch (e->type()) { case QEvent::MouseButtonPress: @@ -757,7 +699,7 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *e) { case QEvent::Move: case QEvent::Resize: if (obj == this) { - psUpdatedPosition(); + positionUpdated(); } break; } @@ -821,13 +763,17 @@ void MainWindow::updateTrayMenu(bool force) { void MainWindow::onShowAddContact() { if (isHidden()) showFromTray(); - if (_main) _main->showAddContact(); + if (App::self()) { + Ui::showLayer(new AddContactBox(), KeepOtherLayers); + } } void MainWindow::onShowNewGroup() { if (isHidden()) showFromTray(); - if (_main) Ui::showLayer(new GroupInfoBox(CreatingGroupGroup, false), KeepOtherLayers); + if (App::self()) { + Ui::showLayer(new GroupInfoBox(CreatingGroupGroup, false), KeepOtherLayers); + } } void MainWindow::onShowNewChannel() { @@ -906,7 +852,6 @@ void MainWindow::layerFinishedHide(LayerStackWidget *was) { } void MainWindow::fixOrder() { - if (_title) _title->raise(); if (_layerBg) _layerBg->raise(); if (_mediaPreview) _mediaPreview->raise(); if (_connecting) _connecting->raise(); @@ -980,7 +925,7 @@ void MainWindow::closeEvent(QCloseEvent *e) { } void MainWindow::resizeEvent(QResizeEvent *e) { - if (!_title) return; + Platform::MainWindow::resizeEvent(e); Adaptive::Layout layout = Adaptive::OneColumnLayout; if (width() > st::adaptiveWideWidth) { @@ -993,17 +938,11 @@ void MainWindow::resizeEvent(QResizeEvent *e) { Adaptive::Changed().notify(true); } - auto bodyTop = 0; - if (_title) { - _title->setGeometry(0, bodyTop, width(), st::titleHeight); - bodyTop += _title->height(); - } - _body->setGeometry(0, bodyTop, width(), height() - bodyTop); updateControlsGeometry(); } void MainWindow::updateControlsGeometry() { - auto body = _body->rect(); + auto body = bodyWidget()->rect(); if (_passcode) _passcode->setGeometry(body); if (_main) _main->setGeometry(body); if (_intro) _intro->setGeometry(body); diff --git a/Telegram/SourceFiles/mainwindow.h b/Telegram/SourceFiles/mainwindow.h index 7578e6a7d..39874f2c5 100644 --- a/Telegram/SourceFiles/mainwindow.h +++ b/Telegram/SourceFiles/mainwindow.h @@ -23,7 +23,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "pspecific.h" #include "ui/effects/rect_shadow.h" #include "platform/platform_main_window.h" -#include "window/window_title.h" #include "core/single_timer.h" class MediaView; @@ -71,7 +70,7 @@ private: class MediaPreviewWidget; -class MainWindow : public Platform::MainWindow, private base::Subscriber { +class MainWindow : public Platform::MainWindow { Q_OBJECT public: @@ -97,9 +96,6 @@ public: void mtpStateChanged(int32 dc, int32 state); - Window::HitTestResult hitTest(const QPoint &p) const; - QRect iconRect() const; - IntroWidget *introWidget(); MainWidget *mainWidget(); PasscodeWidget *passcodeWidget(); @@ -233,14 +229,10 @@ private: void placeSmallCounter(QImage &img, int size, int count, const style::color &bg, const QPoint &shift, const style::color &color); QImage icon16, icon32, icon64, iconbig16, iconbig32, iconbig64; - QWidget *centralwidget; - typedef QPair DelayedServiceMsg; QVector _delayedServiceMsgs; mtpRequestId _serviceHistoryRequest = 0; - Window::TitleWidget *_title = nullptr; - ChildWidget _body; ChildWidget _passcode = { nullptr }; ChildWidget _intro = { nullptr }; ChildWidget _main = { nullptr }; diff --git a/Telegram/SourceFiles/media/player/media_player.style b/Telegram/SourceFiles/media/player/media_player.style index 85e9d2aa6..41804f51e 100644 --- a/Telegram/SourceFiles/media/player/media_player.style +++ b/Telegram/SourceFiles/media/player/media_player.style @@ -125,11 +125,11 @@ mediaPlayerNextDisabledIcon: icon { }; mediaPlayerPreviousButton: IconButton(mediaPlayerNextButton) { icon: icon { - { "player_previous", mediaPlayerActiveFg, mediaPlayerSkipIconPosition }, + { "player_next-flip_horizontal", mediaPlayerActiveFg, mediaPlayerSkipIconPosition }, }; } mediaPlayerPreviousDisabledIcon: icon { - { "player_previous", mediaPlayerInactiveFg, mediaPlayerSkipIconPosition }, + { "player_next-flip_horizontal", mediaPlayerInactiveFg, mediaPlayerSkipIconPosition }, }; mediaPlayerClose: IconButton(mediaPlayerRepeatButton) { width: 37px; @@ -178,10 +178,10 @@ mediaPlayerPanelNextDisabledIcon: icon { { "player_panel_next", mediaPlayerInactiveFg, point(10px, 10px) }, }; mediaPlayerPanelPreviousButton: IconButton(mediaPlayerPanelNextButton) { - icon: icon {{ "player_panel_previous", mediaPlayerActiveFg, point(10px, 10px) }}; + icon: icon {{ "player_panel_next-flip_horizontal", mediaPlayerActiveFg, point(10px, 10px) }}; } mediaPlayerPanelPreviousDisabledIcon: icon { - { "player_panel_previous", mediaPlayerInactiveFg, point(10px, 10px) }, + { "player_panel_next-flip_horizontal", mediaPlayerInactiveFg, point(10px, 10px) }, }; mediaPlayerPanelPadding: 16px; diff --git a/Telegram/SourceFiles/media/view/mediaview.style b/Telegram/SourceFiles/media/view/mediaview.style index 23d8280a4..4390bd489 100644 --- a/Telegram/SourceFiles/media/view/mediaview.style +++ b/Telegram/SourceFiles/media/view/mediaview.style @@ -81,7 +81,7 @@ mediaviewVolumeOnIconOver: icon {{ "media_volume", mediaviewPlaybackActiveOver, mediaviewVolumeIconTop: 8px; mediaviewControllerRadius: 25px; -mediaviewLeft: icon {{ "mediaview_previous", #ffffff }}; +mediaviewLeft: icon {{ "mediaview_next-flip_horizontal", #ffffff }}; mediaviewRight: icon {{ "mediaview_next", #ffffff }}; mediaviewClose: icon {{ "mediaview_close", #ffffff }}; mediaviewSave: icon {{ "mediaview_download", #ffffff }}; diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index 3a952395f..0b648782e 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -54,7 +54,7 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, PeerD , _history(App::history(_peer->id)) , _channel(peerToChannel(_peer->id)) , _rowWidth(st::msgMinWidth) -, _search(this, st::dlgFilter, lang(lng_dlg_filter)) +, _search(this, st::dialogsFilter, lang(lng_dlg_filter)) , _cancelSearch(this, st::dialogsCancelSearch) , _itemsToBeLoaded(LinksOverviewPerPage * 2) , _width(st::windowMinWidth) { diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index 167d9202f..10e61acf9 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -431,89 +431,6 @@ void MainWindow::LibsLoaded() { #endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION } -void MainWindow::psInitSize() { - TWindowPos pos(cWindowPos()); - QRect avail(QDesktopWidget().availableGeometry()); - bool maximized = false; - QRect geom(avail.x() + (avail.width() - st::windowDefWidth) / 2, avail.y() + (avail.height() - st::windowDefHeight) / 2, st::windowDefWidth, st::windowDefHeight); - if (pos.w && pos.h) { - QList screens = Application::screens(); - for (QList::const_iterator i = screens.cbegin(), e = screens.cend(); i != e; ++i) { - QByteArray name = (*i)->name().toUtf8(); - if (pos.moncrc == hashCrc32(name.constData(), name.size())) { - QRect screen((*i)->geometry()); - int32 w = screen.width(), h = screen.height(); - if (w >= st::windowMinWidth && h >= st::windowMinHeight) { - if (pos.w > w) pos.w = w; - if (pos.h > h) pos.h = h; - pos.x += screen.x(); - pos.y += screen.y(); - if (pos.x < screen.x() + screen.width() - 10 && pos.y < screen.y() + screen.height() - 10) { - geom = QRect(pos.x, pos.y, pos.w, pos.h); - } - } - break; - } - } - - if (pos.y < 0) pos.y = 0; - maximized = pos.maximized; - } - setGeometry(geom); -} - -void MainWindow::psInitFrameless() { - psUpdatedPositionTimer.setSingleShot(true); - connect(&psUpdatedPositionTimer, SIGNAL(timeout()), this, SLOT(psSavePosition())); -} - -void MainWindow::psSavePosition(Qt::WindowState state) { - if (state == Qt::WindowActive) state = windowHandle()->windowState(); - if (state == Qt::WindowMinimized || !posInited) return; - - TWindowPos pos(cWindowPos()), curPos = pos; - - if (state == Qt::WindowMaximized) { - curPos.maximized = 1; - } else { - QRect r(geometry()); - curPos.x = r.x(); - curPos.y = r.y(); - curPos.w = r.width(); - curPos.h = r.height(); - curPos.maximized = 0; - } - - int px = curPos.x + curPos.w / 2, py = curPos.y + curPos.h / 2, d = 0; - QScreen *chosen = 0; - QList screens = Application::screens(); - for (QList::const_iterator i = screens.cbegin(), e = screens.cend(); i != e; ++i) { - int dx = (*i)->geometry().x() + (*i)->geometry().width() / 2 - px; if (dx < 0) dx = -dx; - int dy = (*i)->geometry().y() + (*i)->geometry().height() / 2 - py; if (dy < 0) dy = -dy; - if (!chosen || dx + dy < d) { - d = dx + dy; - chosen = *i; - } - } - if (chosen) { - curPos.x -= chosen->geometry().x(); - curPos.y -= chosen->geometry().y(); - QByteArray name = chosen->name().toUtf8(); - curPos.moncrc = hashCrc32(name.constData(), name.size()); - } - - if (curPos.w >= st::wndMinWidth && curPos.h >= st::wndMinHeight) { - if (curPos.x != pos.x || curPos.y != pos.y || curPos.w != pos.w || curPos.h != pos.h || curPos.moncrc != pos.moncrc || curPos.maximized != pos.maximized) { - cSetWindowPos(curPos); - Local::writeSettings(); - } - } -} - -void MainWindow::psUpdatedPosition() { - psUpdatedPositionTimer.start(SaveWindowPositionTimeout); -} - void MainWindow::psCreateTrayIcon() { if (!noQtTrayIcon) { cSetSupportTray(QSystemTrayIcon::isSystemTrayAvailable()); @@ -641,7 +558,7 @@ void MainWindow::psFirstShow() { show(); } - posInited = true; + setPositionInited(); } void MainWindow::psInitSysMenu() { diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.h b/Telegram/SourceFiles/platform/linux/main_window_linux.h index 63551b249..bff10d103 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.h +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.h @@ -30,18 +30,10 @@ class MainWindow : public Window::MainWindow { public: MainWindow(); - int32 psResizeRowWidth() const { - return 0;//st::wndResizeAreaWidth; - } - - void psInitFrameless(); - void psInitSize(); - void psFirstShow(); void psInitSysMenu(); void psUpdateSysMenu(Qt::WindowState state); void psUpdateMargins(); - void psUpdatedPosition(); void psFlash(); void psNotifySettingGot(); @@ -51,10 +43,6 @@ public: void psRefreshTaskbarIcon() { } - bool psPosInited() const { - return posInited; - } - void psUpdateCounter(); bool psHasNativeNotifications(); @@ -66,7 +54,6 @@ public: ~MainWindow(); public slots: - void psSavePosition(Qt::WindowState state = Qt::WindowActive); void psShowTrayMenu(); void psStatusIconCheck(); @@ -76,7 +63,6 @@ protected: bool psHasTrayIcon() const; - bool posInited = false; QSystemTrayIcon *trayIcon = nullptr; QMenu *trayIconMenu = nullptr; QImage icon256, iconbig256; diff --git a/Telegram/SourceFiles/platform/mac/main_window_mac.h b/Telegram/SourceFiles/platform/mac/main_window_mac.h index e82f2b27d..15aec9e32 100644 --- a/Telegram/SourceFiles/platform/mac/main_window_mac.h +++ b/Telegram/SourceFiles/platform/mac/main_window_mac.h @@ -38,18 +38,10 @@ class MainWindow : public Window::MainWindow { public: MainWindow(); - int32 psResizeRowWidth() const { - return 0;//st::wndResizeAreaWidth; - } - - void psInitFrameless(); - void psInitSize(); - void psFirstShow(); void psInitSysMenu(); void psUpdateSysMenu(Qt::WindowState state); void psUpdateMargins(); - void psUpdatedPosition(); void psFlash(); @@ -58,10 +50,6 @@ public: void psRefreshTaskbarIcon() { } - bool psPosInited() const { - return posInited; - } - bool psFilterNativeEvent(void *event); bool eventFilter(QObject *obj, QEvent *evt) override; @@ -79,7 +67,6 @@ public: ~MainWindow(); public slots: - void psSavePosition(Qt::WindowState state = Qt::WindowActive); void psShowTrayMenu(); void psMacUndo(); @@ -103,7 +90,6 @@ protected: void psMacUpdateMenu(); - bool posInited; QSystemTrayIcon *trayIcon = nullptr; QMenu *trayIconMenu = nullptr; QImage icon256, iconbig256; @@ -118,6 +104,8 @@ protected: QTimer psUpdatedPositionTimer; private: + void createGlobalMenu(); + MacPrivate _private; mutable bool psIdle; diff --git a/Telegram/SourceFiles/platform/mac/main_window_mac.mm b/Telegram/SourceFiles/platform/mac/main_window_mac.mm index 0de7a6a3f..ca658345a 100644 --- a/Telegram/SourceFiles/platform/mac/main_window_mac.mm +++ b/Telegram/SourceFiles/platform/mac/main_window_mac.mm @@ -52,8 +52,7 @@ void MacPrivate::darkModeChanged() { } MainWindow::MainWindow() -: posInited(false) -, icon256(qsl(":/gui/art/icon256.png")) +: icon256(qsl(":/gui/art/icon256.png")) , iconbig256(qsl(":/gui/art/iconbig256.png")) , wndIcon(QPixmap::fromImage(iconbig256, Qt::ColorOnly)) { QImage tray(qsl(":/gui/art/osxtray.png")); @@ -190,89 +189,11 @@ void MainWindow::psUpdateCounter() { } } -void MainWindow::psInitSize() { - TWindowPos pos(cWindowPos()); - QRect avail(QDesktopWidget().availableGeometry()); - bool maximized = false; - QRect geom(avail.x() + (avail.width() - st::windowDefWidth) / 2, avail.y() + (avail.height() - st::windowDefHeight) / 2, st::windowDefWidth, st::windowDefHeight); - if (pos.w && pos.h) { - QList screens = Application::screens(); - for (QList::const_iterator i = screens.cbegin(), e = screens.cend(); i != e; ++i) { - QByteArray name = (*i)->name().toUtf8(); - if (pos.moncrc == hashCrc32(name.constData(), name.size())) { - QRect screen((*i)->geometry()); - int32 w = screen.width(), h = screen.height(); - if (w >= st::windowMinWidth && h >= st::windowMinHeight) { - if (pos.w > w) pos.w = w; - if (pos.h > h) pos.h = h; - pos.x += screen.x(); - pos.y += screen.y(); - if (pos.x < screen.x() + screen.width() - 10 && pos.y < screen.y() + screen.height() - 10) { - geom = QRect(pos.x, pos.y, pos.w, pos.h); - } - } - break; - } - } - - if (pos.y < 0) pos.y = 0; - maximized = pos.maximized; - } - setGeometry(geom); -} - void MainWindow::psInitFrameless() { psUpdatedPositionTimer.setSingleShot(true); connect(&psUpdatedPositionTimer, SIGNAL(timeout()), this, SLOT(psSavePosition())); } -void MainWindow::psSavePosition(Qt::WindowState state) { - if (state == Qt::WindowActive) state = windowHandle()->windowState(); - if (state == Qt::WindowMinimized || !posInited) return; - - TWindowPos pos(cWindowPos()), curPos = pos; - - if (state == Qt::WindowMaximized) { - curPos.maximized = 1; - } else { - QRect r(geometry()); - curPos.x = r.x(); - curPos.y = r.y(); - curPos.w = r.width(); - curPos.h = r.height(); - curPos.maximized = 0; - } - - int px = curPos.x + curPos.w / 2, py = curPos.y + curPos.h / 2, d = 0; - QScreen *chosen = 0; - QList screens = Application::screens(); - for (QList::const_iterator i = screens.cbegin(), e = screens.cend(); i != e; ++i) { - int dx = (*i)->geometry().x() + (*i)->geometry().width() / 2 - px; if (dx < 0) dx = -dx; - int dy = (*i)->geometry().y() + (*i)->geometry().height() / 2 - py; if (dy < 0) dy = -dy; - if (!chosen || dx + dy < d) { - d = dx + dy; - chosen = *i; - } - } - if (chosen) { - curPos.x -= chosen->geometry().x(); - curPos.y -= chosen->geometry().y(); - QByteArray name = chosen->name().toUtf8(); - curPos.moncrc = hashCrc32(name.constData(), name.size()); - } - - if (curPos.w >= st::wndMinWidth && curPos.h >= st::wndMinHeight) { - if (curPos.x != pos.x || curPos.y != pos.y || curPos.w != pos.w || curPos.h != pos.h || curPos.moncrc != pos.moncrc || curPos.maximized != pos.maximized) { - cSetWindowPos(curPos); - Local::writeSettings(); - } - } -} - -void MainWindow::psUpdatedPosition() { - psUpdatedPositionTimer.start(SaveWindowPositionTimeout); -} - void MainWindow::psFirstShow() { psUpdateMargins(); @@ -296,9 +217,14 @@ void MainWindow::psFirstShow() { show(); } - posInited = true; + setPositionInited(); - // init global menu + createGlobalMenu(); + + psMacUpdateMenu(); +} + +void MainWindow::createGlobalMenu() { auto main = psMainMenu.addMenu(qsl("Telegram")); auto about = main->addAction(lng_mac_menu_about_telegram(lt_telegram, qsl("Telegram"))); connect(about, SIGNAL(triggered()), base::lambda_slot(about, [] { @@ -339,8 +265,6 @@ void MainWindow::psFirstShow() { psNewChannel = window->addAction(lang(lng_mac_menu_new_channel), App::wnd(), SLOT(onShowNewChannel())); window->addSeparator(); psShowTelegram = window->addAction(lang(lng_mac_menu_show), App::wnd(), SLOT(showFromTray())); - - psMacUpdateMenu(); } namespace { @@ -398,23 +322,23 @@ void MainWindow::psUpdateMargins() { } void MainWindow::psMacUpdateMenu() { - if (!posInited) return; + if (!positionInited()) return; QWidget *focused = QApplication::focusWidget(); bool isLogged = !!App::self(), canUndo = false, canRedo = false, canCut = false, canCopy = false, canPaste = false, canDelete = false, canSelectAll = false; - if (QLineEdit *edit = qobject_cast(focused)) { + if (auto edit = qobject_cast(focused)) { canCut = canCopy = canDelete = edit->hasSelectedText(); canSelectAll = !edit->text().isEmpty(); canUndo = edit->isUndoAvailable(); canRedo = edit->isRedoAvailable(); canPaste = !Application::clipboard()->text().isEmpty(); - } else if (FlatTextarea *edit = qobject_cast(focused)) { + } else if (auto edit = qobject_cast(focused)) { canCut = canCopy = canDelete = edit->textCursor().hasSelection(); canSelectAll = !edit->isEmpty(); canUndo = edit->isUndoAvailable(); canRedo = edit->isRedoAvailable(); canPaste = !Application::clipboard()->text().isEmpty(); - } else if (HistoryInner *list = qobject_cast(focused)) { + } else if (auto list = qobject_cast(focused)) { canCopy = list->canCopySelected(); canDelete = list->canDeleteSelected(); } diff --git a/Telegram/SourceFiles/platform/win/main_window_win.cpp b/Telegram/SourceFiles/platform/win/main_window_win.cpp index b44401412..e328e4dcb 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.cpp +++ b/Telegram/SourceFiles/platform/win/main_window_win.cpp @@ -194,7 +194,7 @@ public: max_w = avail.width(); accumulate_max(max_w, st::windowMinWidth); max_h = avail.height(); - accumulate_max(max_h, st::windowMinHeight); + accumulate_max(max_h, st::titleHeight + st::windowMinHeight); HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0); HWND hwnd = App::wnd() ? App::wnd()->psHwnd() : 0; @@ -350,7 +350,7 @@ public: } return; } - if (!App::wnd()->psPosInited()) return; + if (!App::wnd()->positionInited()) return; int x = _x, y = _y, w = _w, h = _h; if (pos && (!(pos->flags & SWP_NOMOVE) || !(pos->flags & SWP_NOSIZE) || !(pos->flags & SWP_NOREPOSITION))) { @@ -644,6 +644,17 @@ void MainWindow::psShowTrayMenu() { trayIconMenu->popup(QCursor::pos()); } +int32 MainWindow::screenNameChecksum(const QString &name) const { + constexpr int DeviceNameSize = base::array_size(MONITORINFOEX().szDevice); + wchar_t buffer[DeviceNameSize] = { 0 }; + if (name.size() < DeviceNameSize) { + name.toWCharArray(buffer); + } else { + memcpy(buffer, name.toStdWString().data(), sizeof(buffer)); + } + return hashCrc32(buffer, sizeof(buffer)); +} + void MainWindow::psRefreshTaskbarIcon() { QWidget *w = new QWidget(this); w->setWindowFlags(static_cast(Qt::Tool) | Qt::FramelessWindowHint); @@ -754,58 +765,7 @@ void MainWindow::psUpdateCounter() { SetWindowPos(ps_hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); } -namespace { -HMONITOR enumMonitor = 0; -RECT enumMonitorWork; - -BOOL CALLBACK _monitorEnumProc( - _In_ HMONITOR hMonitor, - _In_ HDC hdcMonitor, - _In_ LPRECT lprcMonitor, - _In_ LPARAM dwData -) { - MONITORINFOEX info; - info.cbSize = sizeof(info); - GetMonitorInfo(hMonitor, &info); - if (dwData == hashCrc32(info.szDevice, sizeof(info.szDevice))) { - enumMonitor = hMonitor; - enumMonitorWork = info.rcWork; - return FALSE; - } - return TRUE; -} -} // namespace - -void MainWindow::psInitSize() { - TWindowPos pos(cWindowPos()); - QRect avail(Sandbox::availableGeometry()); - bool maximized = false; - QRect geom(avail.x() + (avail.width() - st::windowDefWidth) / 2, avail.y() + (avail.height() - st::windowDefHeight) / 2, st::windowDefWidth, st::windowDefHeight); - if (pos.w && pos.h) { - if (pos.y < 0) pos.y = 0; - enumMonitor = 0; - EnumDisplayMonitors(0, 0, &_monitorEnumProc, pos.moncrc); - if (enumMonitor) { - int32 w = enumMonitorWork.right - enumMonitorWork.left, h = enumMonitorWork.bottom - enumMonitorWork.top; - if (w >= st::windowMinWidth && h >= st::windowMinHeight) { - if (pos.w > w) pos.w = w; - if (pos.h > h) pos.h = h; - pos.x += enumMonitorWork.left; - pos.y += enumMonitorWork.top; - if (pos.x < enumMonitorWork.right - 10 && pos.y < enumMonitorWork.bottom - 10) { - geom = QRect(pos.x, pos.y, pos.w, pos.h); - } - } - } - maximized = pos.maximized; - } - setGeometry(geom); -} - -void MainWindow::psInitFrameless() { - psUpdatedPositionTimer.setSingleShot(true); - connect(&psUpdatedPositionTimer, SIGNAL(timeout()), this, SLOT(psSavePosition())); - +void MainWindow::initHook() { auto platformInterface = QGuiApplication::platformNativeInterface(); ps_hWnd = static_cast(platformInterface->nativeResourceForWindow(QByteArrayLiteral("handle"), windowHandle())); @@ -816,53 +776,9 @@ void MainWindow::psInitFrameless() { Dlls::WTSRegisterSessionNotification(ps_hWnd, NOTIFY_FOR_THIS_SESSION); } -// RegisterApplicationRestart(NULL, 0); - psInitSysMenu(); } -void MainWindow::psSavePosition(Qt::WindowState state) { - if (state == Qt::WindowActive) state = windowHandle()->windowState(); - if (state == Qt::WindowMinimized || !posInited) return; - - TWindowPos pos(cWindowPos()), curPos = pos; - - if (state == Qt::WindowMaximized) { - curPos.maximized = 1; - } else { - RECT w; - GetWindowRect(ps_hWnd, &w); - curPos.x = w.left; - curPos.y = w.top; - curPos.w = w.right - w.left; - curPos.h = w.bottom - w.top; - curPos.maximized = 0; - } - - HMONITOR hMonitor = MonitorFromWindow(ps_hWnd, MONITOR_DEFAULTTONEAREST); - if (hMonitor) { - MONITORINFOEX info; - info.cbSize = sizeof(info); - GetMonitorInfo(hMonitor, &info); - if (!curPos.maximized) { - curPos.x -= info.rcWork.left; - curPos.y -= info.rcWork.top; - } - curPos.moncrc = hashCrc32(info.szDevice, sizeof(info.szDevice)); - } - - if (curPos.w >= st::windowMinWidth && curPos.h >= st::windowMinHeight) { - if (curPos.x != pos.x || curPos.y != pos.y || curPos.w != pos.w || curPos.h != pos.h || curPos.moncrc != pos.moncrc || curPos.maximized != pos.maximized) { - cSetWindowPos(curPos); - Local::writeSettings(); - } - } -} - -void MainWindow::psUpdatedPosition() { - psUpdatedPositionTimer.start(SaveWindowPositionTimeout); -} - bool MainWindow::psHasNativeNotifications() { return Notifications::supported(); } @@ -894,7 +810,7 @@ void MainWindow::psFirstShow() { show(); } - posInited = true; + setPositionInited(); if (showShadows) { shadowsUpdate(ShadowsChange::Moved | ShadowsChange::Resized | ShadowsChange::Shown); } diff --git a/Telegram/SourceFiles/platform/win/main_window_win.h b/Telegram/SourceFiles/platform/win/main_window_win.h index 0aad21bc1..e7e232926 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.h +++ b/Telegram/SourceFiles/platform/win/main_window_win.h @@ -35,12 +35,6 @@ class MainWindow : public Window::MainWindow { public: MainWindow(); - int32 psResizeRowWidth() const { - return 0;//st::wndResizeAreaWidth; - } - - void psInitFrameless(); - void psInitSize(); HWND psHwnd() const; HMENU psMenu() const; @@ -48,7 +42,6 @@ public: void psInitSysMenu(); void psUpdateSysMenu(Qt::WindowState state); void psUpdateMargins(); - void psUpdatedPosition(); void psFlash(); void psNotifySettingGot(); @@ -57,10 +50,6 @@ public: void psRefreshTaskbarIcon(); - bool psPosInited() const { - return posInited; - } - void psUpdateCounter(); bool psHasNativeNotifications(); @@ -99,15 +88,16 @@ public: ~MainWindow(); public slots: - void psSavePosition(Qt::WindowState state = Qt::WindowActive); void psShowTrayMenu(); protected: + void initHook() override; + int32 screenNameChecksum(const QString &name) const override; + bool psHasTrayIcon() const { return trayIcon; } - bool posInited = false; QSystemTrayIcon *trayIcon = nullptr; Ui::PopupMenu *trayIconMenu = nullptr; QImage icon256, iconbig256; diff --git a/Telegram/SourceFiles/platform/win/window_title_win.cpp b/Telegram/SourceFiles/platform/win/window_title_win.cpp index 61c348fd5..e542e965d 100644 --- a/Telegram/SourceFiles/platform/win/window_title_win.cpp +++ b/Telegram/SourceFiles/platform/win/window_title_win.cpp @@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "platform/win/window_title_win.h" #include "ui/buttons/icon_button.h" +#include "ui/widgets/shadow.h" #include "styles/style_window.h" namespace Platform { @@ -30,7 +31,8 @@ TitleWidget::TitleWidget(QWidget *parent) : Window::TitleWidget(parent) , _minimize(this, st::titleButtonMinimize) , _maximizeRestore(this, st::titleButtonMaximize) , _close(this, st::titleButtonClose) -, _maximized(parent->window()->windowState() & Qt::WindowMaximized) { +, _maximized(parent->window()->windowState() & Qt::WindowMaximized) +, _shadow(this, st::titleShadow) { _minimize->setClickedCallback([this]() { window()->setWindowState(Qt::WindowMinimized); _minimize->clearState(); @@ -65,6 +67,7 @@ void TitleWidget::updateControlsPosition() { void TitleWidget::resizeEvent(QResizeEvent *e) { updateControlsPosition(); + _shadow->setGeometry(0, height() - st::lineWidth, width(), st::lineWidth); } void TitleWidget::updateControlsVisibility() { diff --git a/Telegram/SourceFiles/platform/win/window_title_win.h b/Telegram/SourceFiles/platform/win/window_title_win.h index 1fd97d0bf..49a4f11d2 100644 --- a/Telegram/SourceFiles/platform/win/window_title_win.h +++ b/Telegram/SourceFiles/platform/win/window_title_win.h @@ -24,6 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Ui { class IconButton; +class PlainShadow; } // namespace Ui namespace Platform { @@ -51,6 +52,7 @@ private: ChildWidget _minimize; ChildWidget _maximizeRestore; ChildWidget _close; + ChildWidget _shadow; bool _maximized = false; diff --git a/Telegram/SourceFiles/platform/win/windows_event_filter.cpp b/Telegram/SourceFiles/platform/win/windows_event_filter.cpp index b3202da59..5137ca0a1 100644 --- a/Telegram/SourceFiles/platform/win/windows_event_filter.cpp +++ b/Telegram/SourceFiles/platform/win/windows_event_filter.cpp @@ -155,7 +155,7 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa } emit App::wnd()->windowHandle()->windowStateChanged(state); } else { - App::wnd()->psUpdatedPosition(); + App::wnd()->positionUpdated(); } App::wnd()->psUpdateMargins(); MainWindow::ShadowsChanges changes = (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXIMIZED) ? ShadowsChange::Hidden : (ShadowsChange::Resized | ShadowsChange::Shown); @@ -172,7 +172,7 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa case WM_MOVE: { App::wnd()->shadowsUpdate(ShadowsChange::Moved); - App::wnd()->psUpdatedPosition(); + App::wnd()->positionUpdated(); } return false; case WM_NCHITTEST: { @@ -185,7 +185,6 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa switch (res) { case Window::HitTestResult::Client: case Window::HitTestResult::SysButton: *result = HTCLIENT; break; - case Window::HitTestResult::Icon: *result = HTCAPTION; break; case Window::HitTestResult::Caption: *result = HTCAPTION; break; case Window::HitTestResult::Top: *result = HTTOP; break; case Window::HitTestResult::TopRight: *result = HTTOPRIGHT; break; @@ -204,42 +203,6 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa SendMessage(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam); } return true; - case WM_NCLBUTTONDOWN: { - POINTS p = MAKEPOINTS(lParam); - RECT r; - GetWindowRect(hWnd, &r); - auto res = App::wnd()->hitTest(QPoint(p.x - r.left + App::wnd()->deltaLeft(), p.y - r.top + App::wnd()->deltaTop())); - switch (res) { - case Window::HitTestResult::Icon: - if (menuHidden && getms() < menuHidden + 10) { - menuHidden = 0; - if (getms() < menuShown + GetDoubleClickTime()) { - App::wnd()->close(); - } - } else { - QRect icon = App::wnd()->iconRect(); - p.x = r.left - App::wnd()->deltaLeft() + icon.left(); - p.y = r.top - App::wnd()->deltaTop() + icon.top() + icon.height(); - App::wnd()->psUpdateSysMenu(App::wnd()->windowHandle()->windowState()); - menuShown = getms(); - menuHidden = 0; - TrackPopupMenu(App::wnd()->psMenu(), TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON, p.x, p.y, 0, hWnd, 0); - menuHidden = getms(); - } - return true; - }; - } return false; - - case WM_NCLBUTTONDBLCLK: { - POINTS p = MAKEPOINTS(lParam); - RECT r; - GetWindowRect(hWnd, &r); - auto res = App::wnd()->hitTest(QPoint(p.x - r.left + App::wnd()->deltaLeft(), p.y - r.top + App::wnd()->deltaTop())); - switch (res) { - case Window::HitTestResult::Icon: App::wnd()->close(); return true; - }; - } return false; - case WM_SYSCOMMAND: { if (wParam == SC_MOUSEMENU) { POINTS p = MAKEPOINTS(lParam); diff --git a/Telegram/SourceFiles/pspecific_win.cpp b/Telegram/SourceFiles/pspecific_win.cpp index 78fe71759..7558b4c5a 100644 --- a/Telegram/SourceFiles/pspecific_win.cpp +++ b/Telegram/SourceFiles/pspecific_win.cpp @@ -924,7 +924,7 @@ void psUpdateOverlayed(TWidget *widget) { if (!wv) widget->setAttribute(Qt::WA_WState_Visible, true); widget->update(); QEvent e(QEvent::UpdateRequest); - widget->event(&e); + QGuiApplication::sendEvent(widget, &e); if (!wm) widget->setAttribute(Qt::WA_Mapped, false); if (!wv) widget->setAttribute(Qt::WA_WState_Visible, false); } diff --git a/Telegram/SourceFiles/settings/settings.style b/Telegram/SourceFiles/settings/settings.style index b56e2f95b..32ad78e0f 100644 --- a/Telegram/SourceFiles/settings/settings.style +++ b/Telegram/SourceFiles/settings/settings.style @@ -74,10 +74,11 @@ settingsButtonTop: 75px; settingsButtonSkip: 10px; settingsPrimaryButton: defaultActiveButton; settingsSecondaryButton: defaultLightButton; -settingsEditButton: IconButton(dialogsNewChatButton) { +settingsEditButton: IconButton { width: 24px; height: 34px; + icon: icon {{ "settings_edit_name", #b7b7b7 }}; iconPosition: point(3px, 9px); iconPositionDown: point(3px, 10px); } diff --git a/Telegram/SourceFiles/stickers/stickers.style b/Telegram/SourceFiles/stickers/stickers.style index 397d149d2..91ba059a5 100644 --- a/Telegram/SourceFiles/stickers/stickers.style +++ b/Telegram/SourceFiles/stickers/stickers.style @@ -136,8 +136,8 @@ emojiColorsSepColor: #d5d5d5; emojiSwitchSkip: 27px; emojiSwitchImgSkip: 21px; emojiSwitchColor: #42a8db; -emojiSwitchStickers: icon {{ "emoji_switch_right", emojiSwitchColor }}; -emojiSwitchEmoji: icon {{ "emoji_switch_left", emojiSwitchColor }}; +emojiSwitchStickers: icon {{ "emoji_switch", emojiSwitchColor }}; +emojiSwitchEmoji: icon {{ "emoji_switch-flip_horizontal", emojiSwitchColor }}; stickerPanSize: size(64px, 64px); stickerPanPadding: 11px; diff --git a/Telegram/SourceFiles/ui/twidget.h b/Telegram/SourceFiles/ui/twidget.h index b8bb58a7c..9970640fc 100644 --- a/Telegram/SourceFiles/ui/twidget.h +++ b/Telegram/SourceFiles/ui/twidget.h @@ -138,9 +138,6 @@ class TWidget : public QWidget { public: TWidget(QWidget *parent = nullptr) : QWidget(parent) { } - bool event(QEvent *e) override { - return QWidget::event(e); - } virtual void grabStart() { } virtual void grabFinish() { @@ -238,39 +235,39 @@ private: // A simple wrap around T* to explicitly state ownership template -class ChildWidget { +class ChildObject { public: - ChildWidget(std_::nullptr_t) : _widget(nullptr) { + ChildObject(std_::nullptr_t) : _object(nullptr) { } // No default constructor, but constructors with at least // one argument are simply make functions. template - ChildWidget(Parent &&parent, Args&&... args) : _widget(new T(std_::forward(parent), std_::forward(args)...)) { + ChildObject(Parent &&parent, Args&&... args) : _object(new T(std_::forward(parent), std_::forward(args)...)) { } - ChildWidget(const ChildWidget &other) = delete; - ChildWidget &operator=(const ChildWidget &other) = delete; + ChildObject(const ChildObject &other) = delete; + ChildObject &operator=(const ChildObject &other) = delete; - ChildWidget &operator=(std_::nullptr_t) { - _widget = nullptr; + ChildObject &operator=(std_::nullptr_t) { + _object = nullptr; return *this; } - ChildWidget &operator=(T *widget) { - _widget = widget; + ChildObject &operator=(T *object) { + _object = object; return *this; } T *operator->() const { - return _widget; + return _object; } T &operator*() const { - return *_widget; + return *_object; } // So we can pass this pointer to methods like connect(). T *ptr() const { - return _widget; + return _object; } operator T*() const { return ptr(); @@ -279,28 +276,30 @@ public: // Use that instead "= new T(parent, ...)" template void create(Parent &&parent, Args&&... args) { - delete _widget; - _widget = new T(std_::forward(parent), std_::forward(args)...); + delete _object; + _object = new T(std_::forward(parent), std_::forward(args)...); } void destroy() { - if (_widget) { - delete _widget; - _widget = nullptr; - } + delete base::take(_object); } void destroyDelayed() { - if (_widget) { - _widget->hide(); - _widget->deleteLater(); - _widget = nullptr; + if (_object) { + if (auto widget = base::up_cast(_object)) { + widget->hide(); + } + _object->deleteLater(); + _object = nullptr; } } private: - T *_widget; + T *_object; }; +template +using ChildWidget = ChildObject; + void sendSynteticMouseEvent(QWidget *widget, QEvent::Type type, Qt::MouseButton button, const QPoint &globalPoint); inline void sendSynteticMouseEvent(QWidget *widget, QEvent::Type type, Qt::MouseButton button) { diff --git a/Telegram/SourceFiles/ui/widgets/dropdown_menu.cpp b/Telegram/SourceFiles/ui/widgets/dropdown_menu.cpp index a13a453d2..938a86bf8 100644 --- a/Telegram/SourceFiles/ui/widgets/dropdown_menu.cpp +++ b/Telegram/SourceFiles/ui/widgets/dropdown_menu.cpp @@ -68,6 +68,10 @@ QAction *DropdownMenu::addAction(const QString &text, const QObject *receiver, c return _menu->addAction(text, receiver, member, icon, iconOver); } +QAction *DropdownMenu::addAction(const QString &text, base::lambda_unique callback, const style::icon *icon, const style::icon *iconOver) { + return _menu->addAction(text, std_::move(callback), icon, iconOver); +} + QAction *DropdownMenu::addSeparator() { return _menu->addSeparator(); } diff --git a/Telegram/SourceFiles/ui/widgets/dropdown_menu.h b/Telegram/SourceFiles/ui/widgets/dropdown_menu.h index 3d0092c14..6d63733ab 100644 --- a/Telegram/SourceFiles/ui/widgets/dropdown_menu.h +++ b/Telegram/SourceFiles/ui/widgets/dropdown_menu.h @@ -31,6 +31,7 @@ public: DropdownMenu(QWidget *parent, const style::DropdownMenu &st = st::defaultDropdownMenu); QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr); + QAction *addAction(const QString &text, base::lambda_unique callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr); QAction *addSeparator(); void clearActions(); diff --git a/Telegram/SourceFiles/ui/widgets/menu.cpp b/Telegram/SourceFiles/ui/widgets/menu.cpp index baa2c2da1..d98fb8e31 100644 --- a/Telegram/SourceFiles/ui/widgets/menu.cpp +++ b/Telegram/SourceFiles/ui/widgets/menu.cpp @@ -50,9 +50,15 @@ void Menu::init() { } QAction *Menu::addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon, const style::icon *iconOver) { - auto action = new QAction(text, this); + auto action = addAction(new QAction(text, this), icon, iconOver); connect(action, SIGNAL(triggered(bool)), receiver, member, Qt::QueuedConnection); - return addAction(action, icon, iconOver); + return action; +} + +QAction *Menu::addAction(const QString &text, base::lambda_unique callback, const style::icon *icon, const style::icon *iconOver) { + auto action = addAction(new QAction(text, this), icon, iconOver); + connect(action, SIGNAL(triggered(bool)), base::lambda_slot(action, std_::move(callback)), SLOT(action()), Qt::QueuedConnection); + return action; } QAction *Menu::addAction(QAction *action, const style::icon *icon, const style::icon *iconOver) { diff --git a/Telegram/SourceFiles/ui/widgets/menu.h b/Telegram/SourceFiles/ui/widgets/menu.h index 51e706001..a468dd88f 100644 --- a/Telegram/SourceFiles/ui/widgets/menu.h +++ b/Telegram/SourceFiles/ui/widgets/menu.h @@ -32,6 +32,7 @@ public: Menu(QWidget *parent, QMenu *menu, const style::Menu &st = st::defaultMenu); QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr); + QAction *addAction(const QString &text, base::lambda_unique callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr); QAction *addSeparator(); void clearActions(); diff --git a/Telegram/SourceFiles/ui/widgets/popup_menu.cpp b/Telegram/SourceFiles/ui/widgets/popup_menu.cpp index 03e267598..6dc106def 100644 --- a/Telegram/SourceFiles/ui/widgets/popup_menu.cpp +++ b/Telegram/SourceFiles/ui/widgets/popup_menu.cpp @@ -84,6 +84,10 @@ QAction *PopupMenu::addAction(const QString &text, const QObject *receiver, cons return _menu->addAction(text, receiver, member, icon, iconOver); } +QAction *PopupMenu::addAction(const QString &text, base::lambda_unique callback, const style::icon *icon, const style::icon *iconOver) { + return _menu->addAction(text, std_::move(callback), icon, iconOver); +} + QAction *PopupMenu::addSeparator() { return _menu->addSeparator(); } diff --git a/Telegram/SourceFiles/ui/widgets/popup_menu.h b/Telegram/SourceFiles/ui/widgets/popup_menu.h index 9699cd6dc..6863a311e 100644 --- a/Telegram/SourceFiles/ui/widgets/popup_menu.h +++ b/Telegram/SourceFiles/ui/widgets/popup_menu.h @@ -29,6 +29,7 @@ public: PopupMenu(QMenu *menu, const style::PopupMenu &st = st::defaultPopupMenu); QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr); + QAction *addAction(const QString &text, base::lambda_unique callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr); QAction *addSeparator(); void clearActions(); diff --git a/Telegram/SourceFiles/ui/widgets/widgets.style b/Telegram/SourceFiles/ui/widgets/widgets.style index b144ffa49..40604159d 100644 --- a/Telegram/SourceFiles/ui/widgets/widgets.style +++ b/Telegram/SourceFiles/ui/widgets/widgets.style @@ -190,6 +190,9 @@ defaultMaskButton: MaskButton { widgetSlideDuration: 200; widgetFadeDuration: 200; +fieldSearchIcon: icon {{ "box_search", #aaaaaa, point(9px, 8px) }}; +boxFieldSearchIcon: icon {{ "box_search", #aaaaaa, point(10px, 9px) }}; + discreteSliderHeight: 39px; discreteSliderTop: 5px; discreteSliderSkip: 3px; diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp index 0ae9526ba..02aef33b2 100644 --- a/Telegram/SourceFiles/window/main_window.cpp +++ b/Telegram/SourceFiles/window/main_window.cpp @@ -21,9 +21,147 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "stdafx.h" #include "window/main_window.h" +#include "localstorage.h" +#include "styles/style_window.h" +#include "platform/platform_window_title.h" +#include "window/window_theme.h" + namespace Window { -MainWindow::MainWindow() { +MainWindow::MainWindow() : QMainWindow() +, _positionUpdatedTimer(this) +, _body(this) { + setCentralWidget(_body); + subscribe(Theme::Background(), [this](const Theme::BackgroundUpdate &data) { + using Type = Theme::BackgroundUpdate::Type; + if (data.type == Type::TestingTheme || data.type == Type::RevertingTheme || data.type == Type::ApplyingTheme) { + if (_title) { + _title->update(); + } + } + }); +} + +void MainWindow::init() { + _positionUpdatedTimer->setSingleShot(true); + connect(_positionUpdatedTimer, SIGNAL(timeout()), this, SLOT(savePositionByTimer())); + + _title = Platform::CreateTitleWidget(this); + + auto p = palette(); + p.setColor(QPalette::Window, st::windowBg->c); + setPalette(p); + + initSize(); + + initHook(); +} + +HitTestResult MainWindow::hitTest(const QPoint &p) const { + auto titleResult = _title ? _title->hitTest(p - _title->geometry().topLeft()) : Window::HitTestResult::None; + if (titleResult != Window::HitTestResult::None) { + return titleResult; + } else if (rect().contains(p)) { + return Window::HitTestResult::Client; + } + return Window::HitTestResult::None; +} + +void MainWindow::initSize() { + setMinimumWidth(st::windowMinWidth); + setMinimumHeight((_title ? _title->height() : 0) + st::windowMinHeight); + + auto pos = cWindowPos(); + auto avail = QDesktopWidget().availableGeometry(); + bool maximized = false; + auto geom = QRect(avail.x() + (avail.width() - st::windowDefaultWidth) / 2, avail.y() + (avail.height() - st::windowDefaultHeight) / 2, st::windowDefaultWidth, st::windowDefaultHeight); + if (pos.w && pos.h) { + for (auto screen : QGuiApplication::screens()) { + if (pos.moncrc == screenNameChecksum(screen->name())) { + auto screenGeometry = screen->geometry(); + auto w = screenGeometry.width(), h = screenGeometry.height(); + if (w >= st::windowMinWidth && h >= st::windowMinHeight) { + if (pos.w > w) pos.w = w; + if (pos.h > h) pos.h = h; + pos.x += screenGeometry.x(); + pos.y += screenGeometry.y(); + if (pos.x + st::windowMinWidth <= screenGeometry.x() + screenGeometry.width() && + pos.y + st::windowMinHeight <= screenGeometry.y() + screenGeometry.height()) { + geom = QRect(pos.x, pos.y, pos.w, pos.h); + } + } + break; + } + } + + if (pos.y < 0) pos.y = 0; + maximized = pos.maximized; + } + setGeometry(geom); +} + +void MainWindow::positionUpdated() { + _positionUpdatedTimer->start(SaveWindowPositionTimeout); +} + +int32 MainWindow::screenNameChecksum(const QString &name) const { + auto bytes = name.toUtf8(); + return hashCrc32(bytes.constData(), bytes.size()); +} + +void MainWindow::setPositionInited() { + _positionInited = true; +} + +void MainWindow::resizeEvent(QResizeEvent *e) { + auto bodyTop = 0; + if (_title) { + _title->setGeometry(0, bodyTop, width(), st::titleHeight); + bodyTop += _title->height(); + } + _body->setGeometry(0, bodyTop, width(), height() - bodyTop); +} + +void MainWindow::savePosition(Qt::WindowState state) { + if (state == Qt::WindowActive) state = windowHandle()->windowState(); + if (state == Qt::WindowMinimized || !positionInited()) return; + + TWindowPos pos(cWindowPos()), curPos = pos; + + if (state == Qt::WindowMaximized) { + curPos.maximized = 1; + } else { + QRect r(geometry()); + curPos.x = r.x(); + curPos.y = r.y(); + curPos.w = r.width(); + curPos.h = r.height(); + curPos.maximized = 0; + } + + int px = curPos.x + curPos.w / 2, py = curPos.y + curPos.h / 2; + int minDelta = 0; + QScreen *chosen = 0; + auto screens = QGuiApplication::screens(); + for (auto screen : QGuiApplication::screens()) { + auto delta = (screen->geometry().center() - QPoint(px, py)).manhattanLength(); + if (!chosen || delta < minDelta) { + minDelta = delta; + chosen = screen; + } + } + if (chosen) { + curPos.x -= chosen->geometry().x(); + curPos.y -= chosen->geometry().y(); + curPos.moncrc = screenNameChecksum(chosen->name()); + } + + if (curPos.w >= st::windowMinWidth && curPos.h >= st::windowMinHeight) { + if (curPos.x != pos.x || curPos.y != pos.y || curPos.w != pos.w || curPos.h != pos.h || curPos.moncrc != pos.moncrc || curPos.maximized != pos.maximized) { + cSetWindowPos(curPos); + Local::writeSettings(); + } + } } MainWindow::~MainWindow() { diff --git a/Telegram/SourceFiles/window/main_window.h b/Telegram/SourceFiles/window/main_window.h index ae15bd5f9..aeffea703 100644 --- a/Telegram/SourceFiles/window/main_window.h +++ b/Telegram/SourceFiles/window/main_window.h @@ -20,20 +20,63 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once +#include "window/window_title.h" + namespace Window { -class MainWindow : public QMainWindow { +class TitleWidget; + +class MainWindow : public QMainWindow, protected base::Subscriber { + Q_OBJECT + public: MainWindow(); + void init(); + HitTestResult hitTest(const QPoint &p) const; + + bool positionInited() const { + return _positionInited; + } + void positionUpdated(); + virtual void closeWithoutDestroy(); virtual ~MainWindow(); protected: + void resizeEvent(QResizeEvent *e) override; + + QWidget *bodyWidget() { // temp + return _body; + } + void savePosition(Qt::WindowState state = Qt::WindowActive); + + virtual void initHook() { + } + virtual void stateChangedHook(Qt::WindowState state) { } + // This one is overriden in Windows for historical reasons. + virtual int32 screenNameChecksum(const QString &name) const; + + void setPositionInited(); + +private slots: + void savePositionByTimer() { + savePosition(); + } + +private: + void initSize(); + + ChildObject _positionUpdatedTimer; + bool _positionInited = false; + + ChildWidget _title = { nullptr }; + ChildWidget _body; + }; } // namespace Window diff --git a/Telegram/SourceFiles/window/notifications_manager_default.cpp b/Telegram/SourceFiles/window/notifications_manager_default.cpp index 50f584808..16348efff 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.cpp +++ b/Telegram/SourceFiles/window/notifications_manager_default.cpp @@ -446,6 +446,7 @@ void Widget::addToHeight(int add) { auto newHeight = height() + add; auto newPosition = computePosition(newHeight); updateGeometry(newPosition.x(), newPosition.y(), width(), newHeight); + psUpdateOverlayed(this); } void Widget::updateGeometry(int x, int y, int width, int height) { diff --git a/Telegram/SourceFiles/window/window.style b/Telegram/SourceFiles/window/window.style index 262520044..50bd74cad 100644 --- a/Telegram/SourceFiles/window/window.style +++ b/Telegram/SourceFiles/window/window.style @@ -24,8 +24,8 @@ using "ui/widgets/widgets.style"; windowMinWidth: 380px; windowMinHeight: 480px; -windowDefWidth: 800px; -windowDefHeight: 600px; +windowDefaultWidth: 800px; +windowDefaultHeight: 600px; windowShadow: icon {{ "window_shadow", windowShadowFg }}; windowShadowShift: 1px; diff --git a/Telegram/SourceFiles/window/window_title.h b/Telegram/SourceFiles/window/window_title.h index 41916387a..15dad581d 100644 --- a/Telegram/SourceFiles/window/window_title.h +++ b/Telegram/SourceFiles/window/window_title.h @@ -26,7 +26,6 @@ enum class HitTestResult { None = 0, Client, SysButton, - Icon, Caption, Top, TopRight,