diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index 1c8a1cbb5..eaad0ce2e 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -23,6 +23,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/localstorage.h" #include "window/window_controller.h" #include "window/window_session_controller.h" +#include "base/platform/base_platform_info.h" +#include "base/platform/linux/base_xcb_utilities_linux.h" +#include "base/call_delayed.h" #include "ui/widgets/input_fields.h" #include "facades.h" #include "app.h" @@ -40,6 +43,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include +#include + extern "C" { #undef signals #include @@ -74,6 +79,64 @@ base::flat_map TrayIconImageBack; QIcon TrayIcon; QString TrayIconThemeName, TrayIconName; +bool XCBSkipTaskbar(QWindow *window, bool set) { + const auto connection = base::Platform::XCB::GetConnectionFromQt(); + if (!connection) { + return false; + } + + const auto root = base::Platform::XCB::GetRootWindowFromQt(); + if (!root.has_value()) { + return false; + } + + const auto stateAtom = base::Platform::XCB::GetAtom( + connection, + "_NET_WM_STATE"); + + if (!stateAtom.has_value()) { + return false; + } + + const auto skipTaskbarAtom = base::Platform::XCB::GetAtom( + connection, + "_NET_WM_STATE_SKIP_TASKBAR"); + + if (!skipTaskbarAtom.has_value()) { + return false; + } + + xcb_client_message_event_t xev; + xev.response_type = XCB_CLIENT_MESSAGE; + xev.type = *stateAtom; + xev.sequence = 0; + xev.window = window->winId(); + xev.format = 32; + xev.data.data32[0] = set ? 1 : 0; + xev.data.data32[1] = *skipTaskbarAtom; + xev.data.data32[2] = 0; + xev.data.data32[3] = 0; + xev.data.data32[4] = 0; + + xcb_send_event( + connection, + false, + *root, + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT + | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, + reinterpret_cast(&xev)); + + return true; +} + +bool SkipTaskbar(QWindow *window, bool set) { + if (!IsWayland()) { + return XCBSkipTaskbar(window, set); + } + + return false; +} + QString GetPanelIconName(int counter, bool muted) { return (counter > 0) ? (muted @@ -618,6 +681,10 @@ void MainWindow::handleSNIHostRegistered() { trayIcon = nullptr; psSetupTrayIcon(); + + SkipTaskbar( + windowHandle(), + Global::WorkMode().value() == dbiwmTrayOnly); } void MainWindow::handleSNIOwnerChanged( @@ -649,6 +716,10 @@ void MainWindow::handleSNIOwnerChanged( } else { LOG(("System tray is not available.")); } + + SkipTaskbar( + windowHandle(), + (Global::WorkMode().value() == dbiwmTrayOnly) && trayAvailable()); } void MainWindow::handleAppMenuOwnerChanged( @@ -724,6 +795,8 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) { } else { psSetupTrayIcon(); } + + SkipTaskbar(windowHandle(), mode == dbiwmTrayOnly); } void MainWindow::unreadCounterChangedHook() { @@ -820,9 +893,6 @@ void MainWindow::createGlobalMenu() { void MainWindow::updateGlobalMenuHook() { } -void MainWindow::handleVisibleChangedHook(bool visible) { -} - #else // DESKTOP_APP_DISABLE_DBUS_INTEGRATION void MainWindow::createGlobalMenu() { @@ -1113,7 +1183,19 @@ void MainWindow::updateGlobalMenuHook() { ForceDisabled(psClearFormat, !markdownEnabled); } +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION + void MainWindow::handleVisibleChangedHook(bool visible) { + if (visible) { + base::call_delayed(1, this, [=] { + SkipTaskbar( + windowHandle(), + (Global::WorkMode().value() == dbiwmTrayOnly) + && trayAvailable()); + }); + } + +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION if (_appMenuSupported && !_mainMenuPath.path().isEmpty()) { if (visible) { RegisterAppMenu(winId(), _mainMenuPath); @@ -1121,9 +1203,8 @@ void MainWindow::handleVisibleChangedHook(bool visible) { UnregisterAppMenu(winId()); } } -} - #endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION +} MainWindow::~MainWindow() { #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index f07b61349..554f7fd1a 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -502,6 +502,25 @@ bool UnsetXCBFrameExtents(QWindow *window) { return true; } +bool XCBSkipTaskbarSupported() { + const auto connection = base::Platform::XCB::GetConnectionFromQt(); + if (!connection) { + return false; + } + + const auto skipTaskbarAtom = base::Platform::XCB::GetAtom( + connection, + "_NET_WM_STATE_SKIP_TASKBAR"); + + if (!skipTaskbarAtom.has_value()) { + return false; + } + + return ranges::contains( + base::Platform::XCB::GetWMSupported(connection), + *skipTaskbarAtom); +} + Window::Control GtkKeywordToWindowControl(const QString &keyword) { if (keyword == qstr("minimize")) { return Window::Control::Minimize; @@ -769,6 +788,10 @@ bool TrayIconSupported() { : false; } +bool SkipTaskbarSupported() { + return !IsWayland() && XCBSkipTaskbarSupported(); +} + bool StartSystemMove(QWindow *window) { if (IsWayland()) { return StartWaylandMove(window); diff --git a/Telegram/SourceFiles/platform/mac/specific_mac.h b/Telegram/SourceFiles/platform/mac/specific_mac.h index 419ea4241..af04f1320 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac.h +++ b/Telegram/SourceFiles/platform/mac/specific_mac.h @@ -42,6 +42,10 @@ inline bool TrayIconSupported() { return true; } +inline bool SkipTaskbarSupported() { + return false; +} + inline bool SetWindowExtents(QWindow *window, const QMargins &extents) { return false; } diff --git a/Telegram/SourceFiles/platform/platform_specific.h b/Telegram/SourceFiles/platform/platform_specific.h index 0227a3174..45fafaefa 100644 --- a/Telegram/SourceFiles/platform/platform_specific.h +++ b/Telegram/SourceFiles/platform/platform_specific.h @@ -40,6 +40,7 @@ bool OpenSystemSettings(SystemSettingsType type); void IgnoreApplicationActivationRightNow(); bool AutostartSupported(); bool TrayIconSupported(); +bool SkipTaskbarSupported(); QImage GetImageFromClipboard(); bool StartSystemMove(QWindow *window); bool StartSystemResize(QWindow *window, Qt::Edges edges); diff --git a/Telegram/SourceFiles/platform/win/specific_win.h b/Telegram/SourceFiles/platform/win/specific_win.h index 92114eda5..6e4ae4b54 100644 --- a/Telegram/SourceFiles/platform/win/specific_win.h +++ b/Telegram/SourceFiles/platform/win/specific_win.h @@ -38,6 +38,10 @@ inline bool TrayIconSupported() { return true; } +inline bool SkipTaskbarSupported() { + return true; +} + inline bool SetWindowExtents(QWindow *window, const QMargins &extents) { return false; } diff --git a/Telegram/SourceFiles/settings/settings_advanced.cpp b/Telegram/SourceFiles/settings/settings_advanced.cpp index 3471c0d34..b9c1f7105 100644 --- a/Telegram/SourceFiles/settings/settings_advanced.cpp +++ b/Telegram/SourceFiles/settings/settings_advanced.cpp @@ -352,7 +352,7 @@ void SetupSystemIntegrationContent(not_null container) { return (workMode == dbiwmWindowOnly) || (workMode == dbiwmWindowAndTray); }; - const auto taskbar = Platform::IsWindows() + const auto taskbar = Platform::SkipTaskbarSupported() ? addCheckbox( tr::lng_settings_workmode_window(), taskbarEnabled())