diff --git a/Telegram/Resources/default_shortcuts-custom.json b/Telegram/Resources/default_shortcuts-custom.json new file mode 100644 index 000000000..42d412b15 --- /dev/null +++ b/Telegram/Resources/default_shortcuts-custom.json @@ -0,0 +1,14 @@ +// This is a list of your own shortcuts for Telegram Desktop +// You can see full list of commands in the 'shortcuts-default.json' file +// Place a null value instead of a command string to switch the shortcut off + +[ + // { + // "command": "close_telegram", + // "keys": "ctrl+f4" + // }, + // { + // "command": "quit_telegram", + // "keys": "ctrl+q" + // } +] diff --git a/Telegram/Resources/qrc/telegram.qrc b/Telegram/Resources/qrc/telegram.qrc index 5d4433627..99f66c5cb 100644 --- a/Telegram/Resources/qrc/telegram.qrc +++ b/Telegram/Resources/qrc/telegram.qrc @@ -65,6 +65,9 @@ qmime/freedesktop.org.xml + + ../default_shortcuts-custom.json + ../langs/lang_it.strings ../langs/lang_es.strings diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index 2fa792747..e2a02f4be 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -68,8 +68,6 @@ enum { MaxZoomLevel = 7, // x8 ZoomToScreenLevel = 1024, // just constant - ShortcutsCountLimit = 256, // how many shortcuts can be in json file - PreloadHeightsCount = 3, // when 3 screens to scroll left make a preload request SearchPeopleLimit = 5, diff --git a/Telegram/SourceFiles/core/shortcuts.cpp b/Telegram/SourceFiles/core/shortcuts.cpp new file mode 100644 index 000000000..01bf152db --- /dev/null +++ b/Telegram/SourceFiles/core/shortcuts.cpp @@ -0,0 +1,451 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "core/shortcuts.h" + +#include "mainwindow.h" +#include "mainwidget.h" +#include "messenger.h" +#include "media/player/media_player_instance.h" +#include "platform/platform_specific.h" +#include "base/parse_helper.h" + +namespace Shortcuts { +namespace { + +constexpr auto kCountLimit = 256; // How many shortcuts can be in json file. + +rpl::event_stream> RequestsStream; + +const auto AutoRepeatCommands = base::flat_set{ + Command::MediaPrevious, + Command::MediaNext, + Command::ChatPrevious, + Command::ChatNext, +}; + +const auto MediaCommands = base::flat_set{ + Command::MediaPlay, + Command::MediaPause, + Command::MediaPlayPause, + Command::MediaStop, + Command::MediaPrevious, + Command::MediaNext, +}; + +const auto CommandByName = base::flat_map{ + { qsl("close_telegram") , Command::Close }, + { qsl("lock_telegram") , Command::Lock }, + { qsl("minimize_telegram"), Command::Minimize }, + { qsl("quit_telegram") , Command::Quit }, + + { qsl("media_play") , Command::MediaPlay }, + { qsl("media_pause") , Command::MediaPause }, + { qsl("media_playpause") , Command::MediaPlayPause }, + { qsl("media_stop") , Command::MediaStop }, + { qsl("media_previous") , Command::MediaPrevious }, + { qsl("media_next") , Command::MediaNext }, + + { qsl("search") , Command::Search }, + + { qsl("previous_chat") , Command::ChatPrevious }, + { qsl("next_chat") , Command::ChatNext }, +}; + +const auto CommandNames = base::flat_map{ + { Command::Close , qsl("close_telegram") }, + { Command::Lock , qsl("lock_telegram") }, + { Command::Minimize , qsl("minimize_telegram") }, + { Command::Quit , qsl("quit_telegram") }, + + { Command::MediaPlay , qsl("media_play") }, + { Command::MediaPause , qsl("media_pause") }, + { Command::MediaPlayPause, qsl("media_playpause") }, + { Command::MediaStop , qsl("media_stop") }, + { Command::MediaPrevious , qsl("media_previous") }, + { Command::MediaNext , qsl("media_next") }, + + { Command::Search , qsl("search") }, + + { Command::ChatPrevious , qsl("previous_chat") }, + { Command::ChatNext , qsl("next_chat") }, +}; + +class Manager { +public: + void fill(); + void clear(); + + std::optional lookup(int shortcutId) const; + void toggleMedia(bool toggled); + + const QStringList &errors() const; + +private: + void fillDefaults(); + void writeDefaultFile(); + bool readCustomFile(); + + void set(const QString &keys, Command command); + void remove(const QString &keys); + void unregister(base::unique_qptr shortcut); + + QStringList _errors; + + base::flat_map> _shortcuts; + base::flat_map _commandByShortcutId; + + base::flat_set _mediaShortcuts; + +}; + +QString DefaultFilePath() { + return cWorkingDir() + qsl("tdata/shortcuts-default.json"); +} + +QString CustomFilePath() { + return cWorkingDir() + qsl("tdata/shortcuts-custom.json"); +} + +bool DefaultFileIsValid() { + QFile file(DefaultFilePath()); + if (!file.open(QIODevice::ReadOnly)) { + return false; + } + auto error = QJsonParseError{ 0, QJsonParseError::NoError }; + const auto document = QJsonDocument::fromJson( + base::parse::stripComments(file.readAll()), + &error); + file.close(); + + if (error.error != QJsonParseError::NoError || !document.isArray()) { + return false; + } + const auto shortcuts = document.array(); + if (shortcuts.isEmpty() || !(*shortcuts.constBegin()).isObject()) { + return false; + } + const auto versionObject = (*shortcuts.constBegin()).toObject(); + const auto version = versionObject.constFind(qsl("version")); + if (version == versionObject.constEnd() + || !(*version).isString() + || (*version).toString() != QString::number(AppVersion)) { + return false; + } + return true; +} + +void WriteDefaultCustomFile() { + const auto path = CustomFilePath(); + auto input = QFile(":/misc/default_shortcuts-custom.json"); + auto output = QFile(path); + if (input.open(QIODevice::ReadOnly) && output.open(QIODevice::WriteOnly)) { + output.write(input.readAll()); + } +} + +void Manager::fill() { + fillDefaults(); + + if (!DefaultFileIsValid()) { + writeDefaultFile(); + } + if (!readCustomFile()) { + WriteDefaultCustomFile(); + } +} + +void Manager::clear() { + _errors.clear(); + _shortcuts.clear(); + _commandByShortcutId.clear(); + _mediaShortcuts.clear(); +} + +const QStringList &Manager::errors() const { + return _errors; +} + +std::optional Manager::lookup(int shortcutId) const { + const auto i = _commandByShortcutId.find(shortcutId); + return (i != end(_commandByShortcutId)) + ? base::make_optional(i->second) + : std::nullopt; +} + +void Manager::toggleMedia(bool toggled) { + for (const auto shortcut : _mediaShortcuts) { + shortcut->setEnabled(toggled); + } +} + +bool Manager::readCustomFile() { + // read custom shortcuts from file if it exists or write an empty custom shortcuts file + QFile file(CustomFilePath()); + if (!file.exists()) { + return false; + } + const auto guard = gsl::finally([&] { + if (!_errors.isEmpty()) { + _errors.push_front(qsl("While reading file '%1'..." + ).arg(file.fileName())); + } + }); + if (!file.open(QIODevice::ReadOnly)) { + _errors.push_back(qsl("Could not read the file!")); + return true; + } + auto error = QJsonParseError{ 0, QJsonParseError::NoError }; + const auto document = QJsonDocument::fromJson( + base::parse::stripComments(file.readAll()), + &error); + file.close(); + + if (error.error != QJsonParseError::NoError) { + _errors.push_back(qsl("Failed to parse! Error: %2" + ).arg(error.errorString())); + return true; + } else if (!document.isArray()) { + _errors.push_back(qsl("Failed to parse! Error: array expected")); + return true; + } + const auto shortcuts = document.array(); + auto limit = kCountLimit; + for (auto i = shortcuts.constBegin(), e = shortcuts.constEnd(); i != e; ++i) { + if (!(*i).isObject()) { + _errors.push_back(qsl("Bad entry! Error: object expected")); + continue; + } + const auto entry = (*i).toObject(); + const auto keys = entry.constFind(qsl("keys")); + const auto command = entry.constFind(qsl("command")); + if (keys == entry.constEnd() + || command == entry.constEnd() + || !(*keys).isString() + || (!(*command).isString() && !(*command).isNull())) { + _errors.push_back(qsl("Bad entry! " + "{\"keys\": \"...\", \"command\": [ \"...\" | null ]} " + "expected.")); + } else if ((*command).isNull()) { + remove((*keys).toString()); + } else { + const auto name = (*command).toString(); + const auto i = CommandByName.find(name); + if (i != end(CommandByName)) { + set((*keys).toString(), i->second); + } else { + LOG(("Shortcut Warning: " + "could not find shortcut command handler '%1'" + ).arg(name)); + } + } + if (!--limit) { + _errors.push_back(qsl("Too many entries! Limit is %1" + ).arg(kCountLimit)); + break; + } + } + return true; +} + +void Manager::fillDefaults() { + set(qsl("ctrl+w"), Command::Close); + set(qsl("ctrl+f4"), Command::Close); + set(qsl("ctrl+l"), Command::Lock); + set(qsl("ctrl+m"), Command::Minimize); + set(qsl("ctrl+q"), Command::Quit); + + set(qsl("media play"), Command::MediaPlay); + set(qsl("media pause"), Command::MediaPause); + set(qsl("toggle media play/pause"), Command::MediaPlayPause); + set(qsl("media stop"), Command::MediaStop); + set(qsl("media previous"), Command::MediaPrevious); + set(qsl("media next"), Command::MediaNext); + + set(qsl("ctrl+f"), Command::Search); + set(qsl("search"), Command::Search); + set(qsl("find"), Command::Search); + + set(qsl("ctrl+pgdown"), Command::ChatNext); + set(qsl("alt+down"), Command::ChatNext); + set(qsl("ctrl+pgup"), Command::ChatPrevious); + set(qsl("alt+up"), Command::ChatPrevious); + if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) { + set(qsl("meta+tab"), Command::ChatNext); + set(qsl("meta+shift+tab"), Command::ChatPrevious); + set(qsl("meta+backtab"), Command::ChatPrevious); + } else { + set(qsl("ctrl+tab"), Command::ChatNext); + set(qsl("ctrl+shift+tab"), Command::ChatPrevious); + set(qsl("ctrl+backtab"), Command::ChatPrevious); + } +} + +void Manager::writeDefaultFile() { + auto file = QFile(DefaultFilePath()); + if (!file.open(QIODevice::WriteOnly)) { + return; + } + const char *defaultHeader = R"HEADER( +// This is a list of default shortcuts for Telegram Desktop +// Please don't modify it, its content is not used in any way +// You can place your own shortcuts in the 'shortcuts-custom.json' file + +)HEADER"; + file.write(defaultHeader); + + auto shortcuts = QJsonArray(); + auto version = QJsonObject(); + version.insert(qsl("version"), QString::number(AppVersion)); + shortcuts.push_back(version); + + for (const auto &[sequence, shortcut] : _shortcuts) { + const auto i = _commandByShortcutId.find(shortcut->id()); + if (i != end(_commandByShortcutId)) { + const auto j = CommandNames.find(i->second); + if (j != end(CommandNames)) { + QJsonObject entry; + entry.insert(qsl("keys"), sequence.toString().toLower()); + entry.insert(qsl("command"), j->second); + shortcuts.append(entry); + } + } + } + + auto document = QJsonDocument(); + document.setArray(shortcuts); + file.write(document.toJson(QJsonDocument::Indented)); +} + +void Manager::set(const QString &keys, Command command) { + if (keys.isEmpty()) { + return; + } + + const auto result = QKeySequence(keys, QKeySequence::PortableText); + if (result.isEmpty()) { + _errors.push_back(qsl("Could not derive key sequence '%1'!" + ).arg(keys)); + return; + } + auto shortcut = base::make_unique_q( + result, + Messenger::Instance().getActiveWindow(), + nullptr, + nullptr, + Qt::ApplicationShortcut); + if (AutoRepeatCommands.contains(command)) { + shortcut->setAutoRepeat(false); + } + const auto isMediaShortcut = MediaCommands.contains(command); + if (isMediaShortcut) { + shortcut->setEnabled(false); + } + const auto id = shortcut->id(); + if (!id) { + _errors.push_back(qsl("Could not create shortcut '%1'!").arg(keys)); + return; + } + auto i = _shortcuts.find(result); + if (i == end(_shortcuts)) { + i = _shortcuts.emplace(result, std::move(shortcut)).first; + } else { + unregister(std::exchange(i->second, std::move(shortcut))); + } + _commandByShortcutId.emplace(id, command); + if (isMediaShortcut) { + _mediaShortcuts.emplace(i->second.get()); + } +} + +void Manager::remove(const QString &keys) { + if (keys.isEmpty()) { + return; + } + + const auto result = QKeySequence(keys, QKeySequence::PortableText); + if (result.isEmpty()) { + _errors.push_back(qsl("Could not derive key sequence '%1'!" + ).arg(keys)); + return; + } + const auto i = _shortcuts.find(result); + if (i != end(_shortcuts)) { + unregister(std::move(i->second)); + _shortcuts.erase(i); + } +} + +void Manager::unregister(base::unique_qptr shortcut) { + if (shortcut) { + _commandByShortcutId.erase(shortcut->id()); + _mediaShortcuts.erase(shortcut.get()); + } +} + +Manager Data; + +} // namespace + +Request::Request(Command command) : _command(command) { +} + +bool Request::check(Command command, int priority) { + if (_command == command && priority > _handlerPriority) { + _handlerPriority = priority; + return true; + } + return false; +} + +bool Request::handle(FnMut handler) { + _handler = std::move(handler); + return true; +} + +bool Launch(Command command) { + auto request = Request(command); + RequestsStream.fire(&request); + return request._handler ? request._handler() : false; +} + +rpl::producer> Requests() { + return RequestsStream.events(); +} + +void Start() { + Assert(Global::started()); + + Data.fill(); +} + +const QStringList &Errors() { + return Data.errors(); +} + +bool HandleEvent(not_null event) { + if (const auto command = Data.lookup(event->shortcutId())) { + return Launch(*command); + } + return false; +} + +void EnableMediaShortcuts() { + Data.toggleMedia(true); + Platform::SetWatchingMediaKeys(true); +} + +void DisableMediaShortcuts() { + Data.toggleMedia(false); + Platform::SetWatchingMediaKeys(false); +} + +void Finish() { + Data.clear(); +} + +} // namespace Shortcuts diff --git a/Telegram/SourceFiles/core/shortcuts.h b/Telegram/SourceFiles/core/shortcuts.h new file mode 100644 index 000000000..8f59c2e85 --- /dev/null +++ b/Telegram/SourceFiles/core/shortcuts.h @@ -0,0 +1,64 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +namespace Shortcuts { + +enum class Command { + Close, + Lock, + Minimize, + Quit, + + MediaPlay, + MediaPause, + MediaPlayPause, + MediaStop, + MediaPrevious, + MediaNext, + + Search, + + ChatPrevious, + ChatNext, +}; + +bool Launch(Command command); + +class Request { +public: + bool check(Command command, int priority = 0); + bool handle(FnMut handler); + +private: + explicit Request(Command command); + + Command _command; + int _handlerPriority = -1; + FnMut _handler; + + friend bool Launch(Command command); + +}; + +rpl::producer> Requests(); + +void Start(); +void Finish(); + +bool HandleEvent(not_null event); + +const QStringList &Errors(); + +// Media shortcuts are not enabled by default, because other +// applications also use them. They are enabled only when +// the in-app player is active and disabled back after. +void EnableMediaShortcuts(); +void DisableMediaShortcuts(); + +} // namespace Shortcuts diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp index 8f2bb86be..cc9aa20f5 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_section.cpp @@ -10,9 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/admin_log/history_admin_log_inner.h" #include "history/admin_log/history_admin_log_filter.h" #include "profile/profile_back_button.h" -#include "styles/style_history.h" -#include "styles/style_window.h" -#include "styles/style_info.h" +#include "core/shortcuts.h" #include "ui/widgets/scroll_area.h" #include "ui/widgets/shadow.h" #include "ui/widgets/buttons.h" @@ -25,6 +23,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/confirm_box.h" #include "base/timer.h" #include "lang/lang_keys.h" +#include "styles/style_history.h" +#include "styles/style_window.h" +#include "styles/style_info.h" namespace AdminLog { @@ -262,6 +263,8 @@ Widget::Widget(QWidget *parent, not_null controller, not_nu connect(_scroll, &Ui::ScrollArea::scrolled, this, [this] { onScroll(); }); _whatIsThis->setClickedCallback([=] { Ui::show(Box(lang(lng_admin_log_about_text))); }); + + setupShortcuts(); } void Widget::showFilter() { @@ -317,12 +320,17 @@ void Widget::setInternalState(const QRect &geometry, not_null m restoreState(memento); } -bool Widget::cmd_search() { - if (!inFocusChain()) { - return false; - } - _fixedBar->showSearch(); - return true; +void Widget::setupShortcuts() { + Shortcuts::Requests( + ) | rpl::start_with_next([=](not_null request) { + using Command = Shortcuts::Command; + if (isActiveWindow() && !Ui::isLayerShown() && inFocusChain()) { + request->check(Command::Search, 1) && request->handle([=] { + _fixedBar->showSearch(); + return true; + }); + } + }, lifetime()); } std::unique_ptr Widget::createMemento() { diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_section.h b/Telegram/SourceFiles/history/admin_log/history_admin_log_section.h index abdb6c240..e066a61af 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_section.h +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_section.h @@ -87,8 +87,6 @@ public: void applyFilter(FilterValue &&value); - bool cmd_search() override; - protected: void resizeEvent(QResizeEvent *e) override; void paintEvent(QPaintEvent *e) override; @@ -104,6 +102,7 @@ private: void updateAdaptiveLayout(); void saveState(not_null memento); void restoreState(not_null memento); + void setupShortcuts(); object_ptr _scroll; QPointer _inner; diff --git a/Telegram/SourceFiles/history/feed/history_feed_section.cpp b/Telegram/SourceFiles/history/feed/history_feed_section.cpp index ee39ec781..b15ba1b7c 100644 --- a/Telegram/SourceFiles/history/feed/history_feed_section.cpp +++ b/Telegram/SourceFiles/history/feed/history_feed_section.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_service.h" #include "history/history_inner_widget.h" #include "core/event_filter.h" +#include "core/shortcuts.h" #include "lang/lang_keys.h" #include "ui/widgets/buttons.h" #include "ui/widgets/shadow.h" @@ -134,6 +135,7 @@ Widget::Widget( }, lifetime()); setupScrollDownButton(); + setupShortcuts(); } void Widget::setupScrollDownButton() { @@ -295,13 +297,17 @@ void Widget::setInternalState( restoreState(memento); } -bool Widget::cmd_search() { - if (!inFocusChain()) { - return false; - } - - App::main()->searchInChat(_feed); - return true; +void Widget::setupShortcuts() { + Shortcuts::Requests( + ) | rpl::start_with_next([=](not_null request) { + using Command = Shortcuts::Command; + if (isActiveWindow() && !Ui::isLayerShown() && inFocusChain()) { + request->check(Command::Search, 1) && request->handle([=] { + App::main()->searchInChat(_feed); + return true; + }); + } + }, lifetime()); } HistoryView::Context Widget::listContext() { diff --git a/Telegram/SourceFiles/history/feed/history_feed_section.h b/Telegram/SourceFiles/history/feed/history_feed_section.h index 07077dd36..cb0be4845 100644 --- a/Telegram/SourceFiles/history/feed/history_feed_section.h +++ b/Telegram/SourceFiles/history/feed/history_feed_section.h @@ -68,8 +68,6 @@ public: bool wheelEventFromFloatPlayer(QEvent *e) override; QRect rectForFloatPlayer() const override; - bool cmd_search() override; - // HistoryView::ListDelegate interface. HistoryView::Context listContext() override; void listScrollTo(int top) override; @@ -122,6 +120,8 @@ private: void confirmDeleteSelected(); void clearSelected(); + void setupShortcuts(); + not_null _feed; object_ptr _scroll; QPointer _inner; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 4bc312c44..d300a9197 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -72,6 +72,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "inline_bots/inline_results_widget.h" #include "chat_helpers/emoji_suggestions_widget.h" #include "core/crash_reports.h" +#include "core/shortcuts.h" #include "support/support_common.h" #include "support/support_autocomplete.h" #include "dialogs/dialogs_key.h" @@ -778,6 +779,7 @@ HistoryWidget::HistoryWidget( }, lifetime()); orderWidgets(); + setupShortcuts(); } void HistoryWidget::supportInitAutocomplete() { @@ -1582,17 +1584,30 @@ void HistoryWidget::notify_migrateUpdated(PeerData *peer) { } } -bool HistoryWidget::cmd_search() { - if (!inFocusChain() || !_history) return false; - - App::main()->searchInChat(_history); - return true; +void HistoryWidget::setupShortcuts() { + Shortcuts::Requests( + ) | rpl::start_with_next([=](not_null request) { + using Command = Shortcuts::Command; + if (isActiveWindow() && !Ui::isLayerShown() && _history) { + if (inFocusChain()) { + request->check(Command::Search) && request->handle([=] { + App::main()->searchInChat(_history); + return true; + }); + } + request->check(Command::ChatPrevious) && request->handle([=] { + return showPreviousChat(); + }); + request->check(Command::ChatNext) && request->handle([=] { + return showNextChat(); + }); + } + }, lifetime()); } -bool HistoryWidget::cmd_next_chat() { - if (!_history) { - return false; - } +bool HistoryWidget::showNextChat() { + Expects(_history != nullptr); + const auto next = App::main()->chatListEntryAfter( Dialogs::RowDescriptor( _history, @@ -1611,10 +1626,9 @@ bool HistoryWidget::cmd_next_chat() { return jumpToDialogRow(to); } -bool HistoryWidget::cmd_previous_chat() { - if (!_history) { - return false; - } +bool HistoryWidget::showPreviousChat() { + Expects(_history != nullptr); + const auto previous = App::main()->chatListEntryBefore( Dialogs::RowDescriptor( _history, diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 417ec9dcc..358c5eef2 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -354,10 +354,6 @@ public: void notify_userIsBotChanged(UserData *user); void notify_migrateUpdated(PeerData *peer); - bool cmd_search(); - bool cmd_next_chat(); - bool cmd_previous_chat(); - ~HistoryWidget(); protected: @@ -570,6 +566,10 @@ private: } bool jumpToDialogRow(const Dialogs::RowDescriptor &to); + void setupShortcuts(); + bool showNextChat(); + bool showPreviousChat(); + MsgId _replyToId = 0; Text _replyToName; int _replyToNameVersion = 0; diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp index a68ea6a46..0aeb8d402 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -17,9 +17,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/storage_shared_media.h" #include "mainwidget.h" #include "mainwindow.h" -#include "shortcuts.h" #include "auth_session.h" #include "lang/lang_keys.h" +#include "core/shortcuts.h" #include "ui/special_buttons.h" #include "ui/unread_badge.h" #include "ui/widgets/buttons.h" diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index ee9b36b6e..95c316778 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -61,7 +61,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/download_path_box.h" #include "boxes/connection_box.h" #include "storage/localstorage.h" -#include "shortcuts.h" #include "media/media_audio.h" #include "media/player/media_player_panel.h" #include "media/player/media_player_widget.h" @@ -79,6 +78,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/dc_options.h" #include "core/file_utilities.h" #include "core/update_checker.h" +#include "core/shortcuts.h" #include "calls/calls_instance.h" #include "calls/calls_top_bar.h" #include "export/export_settings.h" @@ -621,24 +621,6 @@ void MainWidget::notify_historyMuteUpdated(History *history) { _dialogs->notify_historyMuteUpdated(history); } -bool MainWidget::cmd_search() { - if (Ui::isLayerShown() || !isActiveWindow()) return false; - if (_mainSection) { - return _mainSection->cmd_search(); - } - return _history->cmd_search(); -} - -bool MainWidget::cmd_next_chat() { - if (Ui::isLayerShown() || !isActiveWindow()) return false; - return _history->cmd_next_chat(); -} - -bool MainWidget::cmd_previous_chat() { - if (Ui::isLayerShown() || !isActiveWindow()) return false; - return _history->cmd_previous_chat(); -} - void MainWidget::noHider(HistoryHider *destroyed) { if (_hider == destroyed) { _hider = nullptr; @@ -1208,7 +1190,7 @@ void MainWidget::closeBothPlayers() { Media::Player::instance()->stop(AudioMsgId::Type::Voice); Media::Player::instance()->stop(AudioMsgId::Type::Song); - Shortcuts::disableMediaShortcuts(); + Shortcuts::DisableMediaShortcuts(); } void MainWidget::createPlayer() { @@ -1230,7 +1212,7 @@ void MainWidget::createPlayer() { if (_a_show.animating()) { _player->show(anim::type::instant); _player->setVisible(false); - Shortcuts::enableMediaShortcuts(); + Shortcuts::EnableMediaShortcuts(); } else { _player->hide(anim::type::instant); } @@ -1240,7 +1222,7 @@ void MainWidget::createPlayer() { _player->show(anim::type::normal); _playerHeight = _contentScrollAddToY = _player->contentHeight(); updateControlsGeometry(); - Shortcuts::enableMediaShortcuts(); + Shortcuts::EnableMediaShortcuts(); } } } diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 0a8f90acd..1bfc00940 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -314,10 +314,6 @@ public: void notify_migrateUpdated(PeerData *peer); void notify_historyMuteUpdated(History *history); - bool cmd_search(); - bool cmd_next_chat(); - bool cmd_previous_chat(); - ~MainWidget(); signals: diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index b1efaba00..c2336a1f2 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -20,7 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_cloud_manager.h" #include "lang/lang_instance.h" #include "lang/lang_keys.h" -#include "shortcuts.h" +#include "core/shortcuts.h" #include "messenger.h" #include "auth_session.h" #include "application.h" diff --git a/Telegram/SourceFiles/media/player/media_player_instance.cpp b/Telegram/SourceFiles/media/player/media_player_instance.cpp index 9b87a148b..bd28ae83d 100644 --- a/Telegram/SourceFiles/media/player/media_player_instance.cpp +++ b/Telegram/SourceFiles/media/player/media_player_instance.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item.h" #include "data/data_media_types.h" #include "window/window_controller.h" +#include "core/shortcuts.h" #include "messenger.h" #include "mainwindow.h" #include "auth_session.h" @@ -75,6 +76,8 @@ Instance::Instance() Messenger::Instance().authSessionChanged(), handleAuthSessionChange); handleAuthSessionChange(); + + setupShortcuts(); } AudioMsgId::Type Instance::getActiveType() const { @@ -494,5 +497,36 @@ void Instance::handleLogout() { _usePanelPlayer.notify(false, true); } +void Instance::setupShortcuts() { + Shortcuts::Requests( + ) | rpl::start_with_next([=](not_null request) { + using Command = Shortcuts::Command; + request->check(Command::MediaPlay) && request->handle([=] { + play(); + return true; + }); + request->check(Command::MediaPause) && request->handle([=] { + pause(); + return true; + }); + request->check(Command::MediaPlayPause) && request->handle([=] { + playPause(); + return true; + }); + request->check(Command::MediaStop) && request->handle([=] { + stop(); + return true; + }); + request->check(Command::MediaPrevious) && request->handle([=] { + previous(); + return true; + }); + request->check(Command::MediaNext) && request->handle([=] { + next(); + return true; + }); + }, _lifetime); +} + } // namespace Player } // namespace Media diff --git a/Telegram/SourceFiles/media/player/media_player_instance.h b/Telegram/SourceFiles/media/player/media_player_instance.h index e1aed71cc..c9f7eeace 100644 --- a/Telegram/SourceFiles/media/player/media_player_instance.h +++ b/Telegram/SourceFiles/media/player/media_player_instance.h @@ -127,6 +127,8 @@ private: Instance(); friend void start(); + void setupShortcuts(); + using SharedMediaType = Storage::SharedMediaType; using SliceKey = SparseIdsMergedSlice::Key; struct Data { @@ -202,6 +204,8 @@ private: base::Observable _trackChangedNotifier; base::Observable _repeatChangedNotifier; + rpl::lifetime _lifetime; + }; } // namespace Clip diff --git a/Telegram/SourceFiles/messenger.cpp b/Telegram/SourceFiles/messenger.cpp index ba4ceea4b..458f22f39 100644 --- a/Telegram/SourceFiles/messenger.cpp +++ b/Telegram/SourceFiles/messenger.cpp @@ -12,13 +12,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "base/timer.h" #include "core/update_checker.h" +#include "core/shortcuts.h" #include "storage/localstorage.h" #include "platform/platform_specific.h" #include "mainwindow.h" #include "dialogs/dialogs_entry.h" #include "history/history.h" #include "application.h" -#include "shortcuts.h" #include "auth_session.h" #include "apiwrap.h" #include "calls/calls_instance.h" @@ -143,8 +143,7 @@ Messenger::Messenger(not_null launcher) DEBUG_LOG(("Application Info: window created...")); - Shortcuts::start(); - + startShortcuts(); App::initMedia(); Local::ReadMapState state = Local::readMap(QByteArray()); @@ -172,11 +171,8 @@ Messenger::Messenger(not_null launcher) _window->updateIsActive(Global::OnlineFocusTimeout()); - if (!Shortcuts::errors().isEmpty()) { - const QStringList &errors(Shortcuts::errors()); - for (QStringList::const_iterator i = errors.cbegin(), e = errors.cend(); i != e; ++i) { - LOG(("Shortcuts Error: %1").arg(*i)); - } + for (const auto &error : Shortcuts::Errors()) { + LOG(("Shortcuts Error: %1").arg(error)); } } @@ -252,8 +248,10 @@ bool Messenger::eventFilter(QObject *object, QEvent *e) { } break; case QEvent::Shortcut: { - DEBUG_LOG(("Shortcut event caught: %1").arg(static_cast(e)->key().toString())); - if (Shortcuts::launch(static_cast(e)->shortcutId())) { + const auto event = static_cast(e); + DEBUG_LOG(("Shortcut event caught: %1" + ).arg(event->key().toString())); + if (Shortcuts::HandleEvent(event)) { return true; } } break; @@ -1039,7 +1037,7 @@ Messenger::~Messenger() { _mtproto.reset(); _mtprotoForKeysDestroy.reset(); - Shortcuts::finish(); + Shortcuts::Finish(); Ui::Emoji::Clear(); @@ -1217,3 +1215,29 @@ void Messenger::quitDelayed() { _private->quitTimer.callOnce(kQuitPreventTimeoutMs); } } + +void Messenger::startShortcuts() { + Shortcuts::Start(); + + Shortcuts::Requests( + ) | rpl::start_with_next([=](not_null request) { + using Command = Shortcuts::Command; + request->check(Command::Quit) && request->handle([] { + App::quit(); + return true; + }); + request->check(Command::Lock) && request->handle([=] { + if (!passcodeLocked() && Global::LocalPasscode()) { + lockByPasscode(); + return true; + } + return false; + }); + request->check(Command::Minimize) && request->handle([=] { + return minimizeActiveWindow(); + }); + request->check(Command::Close) && request->handle([=] { + return closeActiveWindow(); + }); + }, _lifetime); +} diff --git a/Telegram/SourceFiles/messenger.h b/Telegram/SourceFiles/messenger.h index 2f8ddadf0..2e56e5a1c 100644 --- a/Telegram/SourceFiles/messenger.h +++ b/Telegram/SourceFiles/messenger.h @@ -220,6 +220,7 @@ public slots: private: void destroyMtpKeys(MTP::AuthKeysList &&keys); void startLocalStorage(); + void startShortcuts(); friend void App::quit(); static void QuitAttempt(); @@ -277,4 +278,6 @@ private: }; std::vector _leaveSubscriptions; + rpl::lifetime _lifetime; + }; diff --git a/Telegram/SourceFiles/shortcuts.cpp b/Telegram/SourceFiles/shortcuts.cpp deleted file mode 100644 index 34b62ea5d..000000000 --- a/Telegram/SourceFiles/shortcuts.cpp +++ /dev/null @@ -1,446 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "shortcuts.h" - -#include "mainwindow.h" -#include "mainwidget.h" -#include "messenger.h" -#include "media/player/media_player_instance.h" -#include "platform/platform_specific.h" -#include "base/parse_helper.h" - -namespace ShortcutCommands { - -using Handler = bool(*)(); - -bool lock_telegram() { - if (!Messenger::Instance().passcodeLocked() - && Global::LocalPasscode()) { - Messenger::Instance().lockByPasscode(); - return true; - } - return false; -} - -bool minimize_telegram() { - return Messenger::Instance().minimizeActiveWindow(); -} - -bool close_telegram() { - return Messenger::Instance().closeActiveWindow(); -} - -bool quit_telegram() { - App::quit(); - return true; -} - -//void start_stop_recording() { - -//} - -//void cancel_recording() { - -//} - -bool media_play() { - Media::Player::instance()->play(); - return true; -} - -bool media_pause() { - Media::Player::instance()->pause(AudioMsgId::Type::Song); - return true; -} - -bool media_playpause() { - Media::Player::instance()->playPause(); - return true; -} - -bool media_stop() { - Media::Player::instance()->stop(); - return true; -} - -bool media_previous() { - Media::Player::instance()->previous(); - return true; -} - -bool media_next() { - Media::Player::instance()->next(); - return true; -} - -bool search() { - if (auto m = App::main()) { - return m->cmd_search(); - } - return false; -} - -bool previous_chat() { - if (auto m = App::main()) { - return m->cmd_previous_chat(); - } - return false; -} - -bool next_chat() { - if (auto m = App::main()) { - return m->cmd_next_chat(); - } - return false; -} - -// other commands here - -} // namespace ShortcutCommands - -inline bool qMapLessThanKey(const ShortcutCommands::Handler &a, const ShortcutCommands::Handler &b) { - return a < b; -} - -namespace Shortcuts { - -struct DataStruct; -DataStruct *DataPtr = nullptr; - -namespace { - -void createCommand(const QString &command, ShortcutCommands::Handler handler); -QKeySequence setShortcut(const QString &keys, const QString &command); -void destroyShortcut(QShortcut *shortcut); - -} // namespace - -struct DataStruct { - DataStruct() { - Assert(DataPtr == nullptr); - DataPtr = this; - - if (autoRepeatCommands.isEmpty()) { - autoRepeatCommands.insert(qsl("media_previous")); - autoRepeatCommands.insert(qsl("media_next")); - autoRepeatCommands.insert(qsl("next_chat")); - autoRepeatCommands.insert(qsl("previous_chat")); - } - - if (mediaCommands.isEmpty()) { - mediaCommands.insert(qsl("media_play")); - mediaCommands.insert(qsl("media_playpause")); - mediaCommands.insert(qsl("media_play")); - mediaCommands.insert(qsl("media_stop")); - mediaCommands.insert(qsl("media_previous")); - mediaCommands.insert(qsl("media_next")); - } - -#define DeclareAlias(keys, command) setShortcut(qsl(keys), qsl(#command)) -#define DeclareCommand(keys, command) createCommand(qsl(#command), ShortcutCommands::command); DeclareAlias(keys, command) - - DeclareCommand("ctrl+w", close_telegram); - DeclareAlias("ctrl+f4", close_telegram); - DeclareCommand("ctrl+l", lock_telegram); - DeclareCommand("ctrl+m", minimize_telegram); - DeclareCommand("ctrl+q", quit_telegram); - - //DeclareCommand("ctrl+r", start_stop_recording); - //DeclareCommand("ctrl+shift+r", cancel_recording); - //DeclareCommand("media record", start_stop_recording); - - DeclareCommand("media play", media_play); - DeclareCommand("media pause", media_pause); - DeclareCommand("toggle media play/pause", media_playpause); - DeclareCommand("media stop", media_stop); - DeclareCommand("media previous", media_previous); - DeclareCommand("media next", media_next); - - DeclareCommand("ctrl+f", search); - DeclareAlias("search", search); - DeclareAlias("find", search); - - DeclareCommand("ctrl+pgdown", next_chat); - DeclareAlias("alt+down", next_chat); - DeclareCommand("ctrl+pgup", previous_chat); - DeclareAlias("alt+up", previous_chat); - if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) { - DeclareAlias("meta+tab", next_chat); - DeclareAlias("meta+shift+tab", previous_chat); - DeclareAlias("meta+backtab", previous_chat); - } else { - DeclareAlias("ctrl+tab", next_chat); - DeclareAlias("ctrl+shift+tab", previous_chat); - DeclareAlias("ctrl+backtab", previous_chat); - } - - // other commands here - -#undef DeclareCommand -#undef DeclareAlias - } - QStringList errors; - - QMap commands; - QMap commandnames; - - QMap sequences; - QMap handlers; - - QSet mediaShortcuts; - QSet autoRepeatCommands; - QSet mediaCommands; - -}; - -namespace { - -void createCommand(const QString &command, ShortcutCommands::Handler handler) { - Assert(DataPtr != nullptr); - Assert(!command.isEmpty()); - - DataPtr->commands.insert(command, handler); - DataPtr->commandnames.insert(handler, command); -} - -QKeySequence setShortcut(const QString &keys, const QString &command) { - Assert(DataPtr != nullptr); - Assert(!command.isEmpty()); - if (keys.isEmpty()) return QKeySequence(); - - QKeySequence seq(keys, QKeySequence::PortableText); - if (seq.isEmpty()) { - DataPtr->errors.push_back(qsl("Could not derive key sequence '%1'!").arg(keys)); - } else { - auto it = DataPtr->commands.constFind(command); - if (it == DataPtr->commands.cend()) { - LOG(("Warning: could not find shortcut command handler '%1'").arg(command)); - } else { - auto shortcut = std::make_unique(seq, Messenger::Instance().getActiveWindow(), nullptr, nullptr, Qt::ApplicationShortcut); - if (!DataPtr->autoRepeatCommands.contains(command)) { - shortcut->setAutoRepeat(false); - } - auto isMediaShortcut = DataPtr->mediaCommands.contains(command); - if (isMediaShortcut) { - shortcut->setEnabled(false); - } - int shortcutId = shortcut->id(); - if (!shortcutId) { - DataPtr->errors.push_back(qsl("Could not create shortcut '%1'!").arg(keys)); - } else { - auto seqIt = DataPtr->sequences.find(seq); - if (seqIt == DataPtr->sequences.cend()) { - seqIt = DataPtr->sequences.insert(seq, shortcut.release()); - } else { - auto oldShortcut = seqIt.value(); - seqIt.value() = shortcut.release(); - destroyShortcut(oldShortcut); - } - DataPtr->handlers.insert(shortcutId, it.value()); - if (isMediaShortcut) { - DataPtr->mediaShortcuts.insert(seqIt.value()); - } - } - } - } - return seq; -} - -QKeySequence removeShortcut(const QString &keys) { - Assert(DataPtr != nullptr); - if (keys.isEmpty()) return QKeySequence(); - - QKeySequence seq(keys, QKeySequence::PortableText); - if (seq.isEmpty()) { - DataPtr->errors.push_back(qsl("Could not derive key sequence '%1'!").arg(keys)); - } else { - auto seqIt = DataPtr->sequences.find(seq); - if (seqIt != DataPtr->sequences.cend()) { - auto shortcut = seqIt.value(); - DataPtr->sequences.erase(seqIt); - destroyShortcut(shortcut); - } - } - return seq; -} - -void destroyShortcut(QShortcut *shortcut) { - Assert(DataPtr != nullptr); - - DataPtr->handlers.remove(shortcut->id()); - DataPtr->mediaShortcuts.remove(shortcut); - delete shortcut; -} - -} // namespace - -void start() { - Assert(Global::started()); - - new DataStruct(); - - // write default shortcuts to a file if they are not there already - bool defaultValid = false; - QFile defaultFile(cWorkingDir() + qsl("tdata/shortcuts-default.json")); - if (defaultFile.open(QIODevice::ReadOnly)) { - QJsonParseError error = { 0, QJsonParseError::NoError }; - QJsonDocument doc = QJsonDocument::fromJson(base::parse::stripComments(defaultFile.readAll()), &error); - defaultFile.close(); - - if (error.error == QJsonParseError::NoError && doc.isArray()) { - QJsonArray shortcuts(doc.array()); - if (!shortcuts.isEmpty() && (*shortcuts.constBegin()).isObject()) { - QJsonObject versionObject((*shortcuts.constBegin()).toObject()); - QJsonObject::const_iterator version = versionObject.constFind(qsl("version")); - if (version != versionObject.constEnd() && (*version).isString() && (*version).toString() == QString::number(AppVersion)) { - defaultValid = true; - } - } - } - } - if (!defaultValid && defaultFile.open(QIODevice::WriteOnly)) { - const char *defaultHeader = "\ -// This is a list of default shortcuts for Telegram Desktop\n\ -// Please don't modify it, its content is not used in any way\n\ -// You can place your own shortcuts in the 'shortcuts-custom.json' file\n\n"; - defaultFile.write(defaultHeader); - - QJsonArray shortcuts; - - QJsonObject version; - version.insert(qsl("version"), QString::number(AppVersion)); - shortcuts.push_back(version); - - for (auto i = DataPtr->sequences.cbegin(), e = DataPtr->sequences.cend(); i != e; ++i) { - auto h = DataPtr->handlers.constFind(i.value()->id()); - if (h != DataPtr->handlers.cend()) { - auto n = DataPtr->commandnames.constFind(h.value()); - if (n != DataPtr->commandnames.cend()) { - QJsonObject entry; - entry.insert(qsl("keys"), i.key().toString().toLower()); - entry.insert(qsl("command"), n.value()); - shortcuts.append(entry); - } - } - } - - QJsonDocument doc; - doc.setArray(shortcuts); - defaultFile.write(doc.toJson(QJsonDocument::Indented)); - defaultFile.close(); - } - - // read custom shortcuts from file if it exists or write an empty custom shortcuts file - QFile customFile(cWorkingDir() + qsl("tdata/shortcuts-custom.json")); - if (customFile.exists()) { - if (customFile.open(QIODevice::ReadOnly)) { - QJsonParseError error = { 0, QJsonParseError::NoError }; - QJsonDocument doc = QJsonDocument::fromJson(base::parse::stripComments(customFile.readAll()), &error); - customFile.close(); - - if (error.error != QJsonParseError::NoError) { - DataPtr->errors.push_back(qsl("Failed to parse! Error: %2").arg(error.errorString())); - } else if (!doc.isArray()) { - DataPtr->errors.push_back(qsl("Failed to parse! Error: array expected")); - } else { - QJsonArray shortcuts = doc.array(); - int limit = ShortcutsCountLimit; - for (QJsonArray::const_iterator i = shortcuts.constBegin(), e = shortcuts.constEnd(); i != e; ++i) { - if (!(*i).isObject()) { - DataPtr->errors.push_back(qsl("Bad entry! Error: object expected")); - } else { - QKeySequence seq; - QJsonObject entry((*i).toObject()); - QJsonObject::const_iterator keys = entry.constFind(qsl("keys")), command = entry.constFind(qsl("command")); - if (keys == entry.constEnd() || command == entry.constEnd() || !(*keys).isString() || (!(*command).isString() && !(*command).isNull())) { - DataPtr->errors.push_back(qsl("Bad entry! {\"keys\": \"...\", \"command\": [ \"...\" | null ]} expected")); - } else if ((*command).isNull()) { - seq = removeShortcut((*keys).toString()); - } else { - seq = setShortcut((*keys).toString(), (*command).toString()); - } - if (!--limit) { - DataPtr->errors.push_back(qsl("Too many entries! Limit is %1").arg(ShortcutsCountLimit)); - break; - } - } - } - } - } else { - DataPtr->errors.push_back(qsl("Could not read the file!")); - } - if (!DataPtr->errors.isEmpty()) { - DataPtr->errors.push_front(qsl("While reading file '%1'...").arg(customFile.fileName())); - } - } else if (customFile.open(QIODevice::WriteOnly)) { - const char *customContent = "\ -// This is a list of your own shortcuts for Telegram Desktop\n\ -// You can see full list of commands in the 'shortcuts-default.json' file\n\ -// Place a null value instead of a command string to switch the shortcut off\n\n\ -[\n\ - // {\n\ - // \"command\": \"close_telegram\",\n\ - // \"keys\": \"ctrl+f4\"\n\ - // },\n\ - // {\n\ - // \"command\": \"quit_telegram\",\n\ - // \"keys\": \"ctrl+q\"\n\ - // }\n\ -]\n"; - customFile.write(customContent); - customFile.close(); - } -} - -const QStringList &errors() { - Assert(DataPtr != nullptr); - return DataPtr->errors; -} - -bool launch(int shortcutId) { - Assert(DataPtr != nullptr); - - auto it = DataPtr->handlers.constFind(shortcutId); - if (it == DataPtr->handlers.cend()) { - return false; - } - return (*it.value())(); -} - -bool launch(const QString &command) { - Assert(DataPtr != nullptr); - - auto it = DataPtr->commands.constFind(command); - if (it == DataPtr->commands.cend()) { - return false; - } - return (*it.value())(); -} - -void enableMediaShortcuts() { - if (!DataPtr) return; - for_const (auto shortcut, DataPtr->mediaShortcuts) { - shortcut->setEnabled(true); - } - Platform::SetWatchingMediaKeys(true); -} - -void disableMediaShortcuts() { - if (!DataPtr) return; - for_const (auto shortcut, DataPtr->mediaShortcuts) { - shortcut->setEnabled(false); - } - Platform::SetWatchingMediaKeys(false); -} - -void finish() { - delete DataPtr; - DataPtr = nullptr; -} - -} // namespace Shortcuts diff --git a/Telegram/SourceFiles/shortcuts.h b/Telegram/SourceFiles/shortcuts.h deleted file mode 100644 index f53e59356..000000000 --- a/Telegram/SourceFiles/shortcuts.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace Shortcuts { - -void start(); -const QStringList &errors(); - -bool launch(int shortcutId); -bool launch(const QString &command); - -// Media shortcuts are not enabled by default, because other -// applications also use them. They are enabled only when -// the in-app player is active and disabled back after. -void enableMediaShortcuts(); -void disableMediaShortcuts(); - -void finish(); - -} // namespace Shortcuts diff --git a/Telegram/SourceFiles/support/support_common.cpp b/Telegram/SourceFiles/support/support_common.cpp index a137b0ce4..2eac396d8 100644 --- a/Telegram/SourceFiles/support/support_common.cpp +++ b/Telegram/SourceFiles/support/support_common.cpp @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "support/support_common.h" -#include "shortcuts.h" +#include "core/shortcuts.h" namespace Support { @@ -36,10 +36,10 @@ Qt::KeyboardModifiers SkipSwitchModifiers() { void PerformSwitch(SwitchSettings value) { switch (value) { case SwitchSettings::Next: - Shortcuts::launch("next_chat"); + Shortcuts::Launch(Shortcuts::Command::ChatNext); break; case SwitchSettings::Previous: - Shortcuts::launch("previous_chat"); + Shortcuts::Launch(Shortcuts::Command::ChatPrevious); break; default: break; diff --git a/Telegram/SourceFiles/window/section_widget.h b/Telegram/SourceFiles/window/section_widget.h index 0c269c8ce..72382fc2f 100644 --- a/Telegram/SourceFiles/window/section_widget.h +++ b/Telegram/SourceFiles/window/section_widget.h @@ -122,11 +122,6 @@ public: return nullptr; } - // Global shortcut handler. For now that ugly :( - virtual bool cmd_search() { - return false; - } - static void PaintBackground(QWidget *widget, QPaintEvent *event); protected: diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index 253c827af..6b7bdd279 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -122,6 +122,8 @@ <(src_loc)/core/media_active_cache.h <(src_loc)/core/mime_type.cpp <(src_loc)/core/mime_type.h +<(src_loc)/core/shortcuts.cpp +<(src_loc)/core/shortcuts.h <(src_loc)/core/single_timer.cpp <(src_loc)/core/single_timer.h <(src_loc)/core/tl_help.h @@ -766,8 +768,6 @@ <(src_loc)/qt_static_plugins.cpp <(src_loc)/settings.cpp <(src_loc)/settings.h -<(src_loc)/shortcuts.cpp -<(src_loc)/shortcuts.h <(emoji_suggestions_loc)/emoji_suggestions.cpp <(emoji_suggestions_loc)/emoji_suggestions.h