Moved out dock menu from obj-c implementation to Qt implementation.

This allows to remove
the `NSApplicationDelegate::applicationDockMenu` patch for Qt.
This commit is contained in:
23rd
2026-03-07 06:34:21 +03:00
committed by John Preston
parent e0d28a580c
commit ccb563eff1
4 changed files with 110 additions and 121 deletions
+2
View File
@@ -1373,6 +1373,8 @@ PRIVATE
media/system_media_controls_manager.cpp
menu/menu_antispam_validator.cpp
menu/menu_antispam_validator.h
menu/menu_dock.cpp
menu/menu_dock.h
menu/menu_item_download_files.cpp
menu/menu_item_download_files.h
menu/menu_item_rate_transcribe_session.cpp
+83
View File
@@ -0,0 +1,83 @@
/*
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 "menu/menu_dock.h"
#include "core/application.h"
#include "core/core_settings.h"
#include "data/data_user.h"
#include "lang/lang_keys.h"
#include "main/main_account.h"
#include "main/main_domain.h"
#include "main/main_session.h"
#include "media/audio/media_audio.h"
#include "media/player/media_player_instance.h"
#include "ui/text/text_utilities.h"
#include <QtWidgets/QMenu>
namespace Menu {
void RefreshDockMenu(QMenu *menu) {
menu->clear();
if (!Core::IsAppLaunched()) {
return;
}
const auto accounts = Core::App().domain().orderedAccounts();
if (accounts.size() > 1) {
menu->addSeparator();
const auto profilesHeader = menu->addAction(
tr::lng_mac_menu_profiles(tr::now));
profilesHeader->setEnabled(false);
constexpr auto kMaxLength = 30;
for (const auto &account : accounts) {
if (account->sessionExists()) {
const auto name = account->session().user()->name();
menu->addAction(
(name.size() > kMaxLength)
? (name.mid(0, kMaxLength) + Ui::kQEllipsis)
: name,
[account] {
Core::App().ensureSeparateWindowFor(account);
});
}
}
menu->addSeparator();
}
menu->addAction(
Core::App().settings().desktopNotify()
? tr::lng_disable_notifications_from_tray(tr::now)
: tr::lng_enable_notifications_from_tray(tr::now),
[] {
auto &settings = Core::App().settings();
settings.setDesktopNotify(!settings.desktopNotify());
});
using namespace Media::Player;
const auto type = instance()->getActiveType();
const auto state = instance()->getState(type);
if (!IsStoppedOrStopping(state.state)) {
menu->addSeparator();
const auto previous = menu->addAction(
tr::lng_mac_menu_player_previous(tr::now),
[] { instance()->previous(); });
previous->setEnabled(instance()->previousAvailable(type));
menu->addAction(
IsPausedOrPausing(state.state)
? tr::lng_mac_menu_player_resume(tr::now)
: tr::lng_mac_menu_player_pause(tr::now),
[] { instance()->playPause(); });
const auto next = menu->addAction(
tr::lng_mac_menu_player_next(tr::now),
[] { instance()->next(); });
next->setEnabled(instance()->nextAvailable(type));
}
}
} // namespace Menu
+16
View File
@@ -0,0 +1,16 @@
/*
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
class QMenu;
namespace Menu {
void RefreshDockMenu(QMenu *menu);
} // namespace Menu
@@ -9,28 +9,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwindow.h"
#include "mainwidget.h"
#include "main/main_account.h"
#include "main/main_domain.h"
#include "main/main_session.h"
#include "data/data_user.h"
#include "calls/calls_instance.h"
#include "core/sandbox.h"
#include "core/application.h"
#include "core/core_settings.h"
#include "core/crash_reports.h"
#include "menu/menu_dock.h"
#include "storage/localstorage.h"
#include "media/audio/media_audio.h"
#include "media/player/media_player_instance.h"
#include "window/window_controller.h"
#include "base/platform/mac/base_utilities_mac.h"
#include "base/platform/base_platform_info.h"
#include "lang/lang_keys.h"
#include "base/timer.h"
#include "styles/style_window.h"
#include "platform/platform_specific.h"
#include <QtGui/QWindow>
#include <QtWidgets/QApplication>
#include <QtWidgets/QMenu>
#if __has_include(<QtCore/QOperatingSystemVersion>)
#include <QtCore/QOperatingSystemVersion>
#endif // __has_include(<QtCore/QOperatingSystemVersion>)
@@ -49,47 +45,16 @@ namespace {
constexpr auto kIgnoreActivationTimeoutMs = 500;
NSMenuItem *CreateMenuItem(
QString title,
rpl::lifetime &lifetime,
Fn<void()> callback,
bool enabled = true) {
id block = [^{
Core::Sandbox::Instance().customEnterFromEventLoop(callback);
} copy];
NSMenuItem *item = [[NSMenuItem alloc]
initWithTitle:Q2NSString(title)
action:@selector(invoke)
keyEquivalent:@""];
[item setTarget:block];
[item setEnabled:enabled];
lifetime.add([=] {
[block release];
void SetupDockMenu() {
static const auto DockMenu = std::make_unique<QMenu>();
QObject::connect(DockMenu.get(), &QMenu::aboutToShow, [] {
Menu::RefreshDockMenu(DockMenu.get());
});
return [item autorelease];
DockMenu->setAsDockMenu();
}
} // namespace
@interface RpMenu : NSMenu {
}
- (rpl::lifetime &) lifetime;
@end // @interface Menu
@implementation RpMenu {
rpl::lifetime _lifetime;
}
- (rpl::lifetime &) lifetime {
return _lifetime;
}
@end // @implementation Menu
@interface qVisualize : NSObject {
}
@@ -144,8 +109,6 @@ NSMenuItem *CreateMenuItem(
- (void) ignoreApplicationActivationRightNow;
- (NSMenu *) applicationDockMenu:(NSApplication *)sender;
@end // @interface ApplicationDelegate
ApplicationDelegate *_sharedDelegate = nil;
@@ -220,83 +183,6 @@ ApplicationDelegate *_sharedDelegate = nil;
_ignoreActivationStop.callOnce(kIgnoreActivationTimeoutMs);
}
- (NSMenu *) applicationDockMenu:(NSApplication *)sender {
if (!Core::IsAppLaunched()) {
return nil;
}
RpMenu* dockMenu = [[[RpMenu alloc] initWithTitle: @""] autorelease];
[dockMenu setAutoenablesItems:false];
const auto accounts = Core::App().domain().orderedAccounts();
if (accounts.size() > 1) {
[dockMenu addItem:[NSMenuItem separatorItem]];
NSMenuItem *profilesHeader = [[NSMenuItem alloc]
initWithTitle:@"" action:nil keyEquivalent:@""];
NSDictionary *attributes = @{
NSFontAttributeName: [NSFont
menuFontOfSize:[NSFont smallSystemFontSize]],
NSForegroundColorAttributeName: [NSColor secondaryLabelColor]
};
NSAttributedString *attrTitle = [[NSAttributedString alloc]
initWithString:Q2NSString(tr::lng_mac_menu_profiles(tr::now))
attributes:attributes];
[profilesHeader setAttributedTitle:attrTitle];
[attrTitle release];
[profilesHeader setEnabled:NO];
[dockMenu addItem:[profilesHeader autorelease]];
constexpr auto kMaxLength = 30;
for (const auto &account : accounts) {
if (account->sessionExists()) {
auto name = account->session().user()->name();
[dockMenu addItem:CreateMenuItem(
(name.size() > kMaxLength)
? (name.mid(0, kMaxLength) + Ui::kQEllipsis)
: name,
[dockMenu lifetime],
[account] {
Core::App().ensureSeparateWindowFor(account);
})];
}
}
[dockMenu addItem:[NSMenuItem separatorItem]];
}
auto notifyCallback = [] {
auto &settings = Core::App().settings();
settings.setDesktopNotify(!settings.desktopNotify());
};
[dockMenu addItem:CreateMenuItem(
Core::App().settings().desktopNotify()
? tr::lng_disable_notifications_from_tray(tr::now)
: tr::lng_enable_notifications_from_tray(tr::now),
[dockMenu lifetime],
std::move(notifyCallback))];
using namespace Media::Player;
const auto state = instance()->getState(instance()->getActiveType());
if (!IsStoppedOrStopping(state.state)) {
[dockMenu addItem:[NSMenuItem separatorItem]];
[dockMenu addItem:CreateMenuItem(
tr::lng_mac_menu_player_previous(tr::now),
[dockMenu lifetime],
[] { instance()->previous(); },
instance()->previousAvailable(instance()->getActiveType()))];
[dockMenu addItem:CreateMenuItem(
IsPausedOrPausing(state.state)
? tr::lng_mac_menu_player_resume(tr::now)
: tr::lng_mac_menu_player_pause(tr::now),
[dockMenu lifetime],
[] { instance()->playPause(); })];
[dockMenu addItem:CreateMenuItem(
tr::lng_mac_menu_player_next(tr::now),
[dockMenu lifetime],
[] { instance()->next(); },
instance()->nextAvailable(instance()->getActiveType()))];
}
return dockMenu;
}
@end // @implementation ApplicationDelegate
namespace Platform {
@@ -348,6 +234,8 @@ void objc_start() {
addObserver: _sharedDelegate
selector: @selector(receiveWakeNote:)
name: NSWorkspaceDidWakeNotification object: NULL];
crl::on_main([=] { SetupDockMenu(); });
}
void objc_ignoreApplicationActivationRightNow() {