Implement possibility to hide taskbar icon on Linux

This commit is contained in:
Ilya Fedin 2020-10-16 07:02:05 +04:00 committed by John Preston
parent 49e96d857a
commit 8f5b136003
6 changed files with 119 additions and 6 deletions

View file

@ -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 <QtDBus/QDBusError>
#include <QtDBus/QDBusMetaType>
#include <xcb/xcb.h>
extern "C" {
#undef signals
#include <gio/gio.h>
@ -74,6 +79,64 @@ base::flat_map<int, QImage> 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<const char*>(&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

View file

@ -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);

View file

@ -42,6 +42,10 @@ inline bool TrayIconSupported() {
return true;
}
inline bool SkipTaskbarSupported() {
return false;
}
inline bool SetWindowExtents(QWindow *window, const QMargins &extents) {
return false;
}

View file

@ -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);

View file

@ -38,6 +38,10 @@ inline bool TrayIconSupported() {
return true;
}
inline bool SkipTaskbarSupported() {
return true;
}
inline bool SetWindowExtents(QWindow *window, const QMargins &extents) {
return false;
}

View file

@ -352,7 +352,7 @@ void SetupSystemIntegrationContent(not_null<Ui::VerticalLayout*> container) {
return (workMode == dbiwmWindowOnly)
|| (workMode == dbiwmWindowAndTray);
};
const auto taskbar = Platform::IsWindows()
const auto taskbar = Platform::SkipTaskbarSupported()
? addCheckbox(
tr::lng_settings_workmode_window(),
taskbarEnabled())