diff --git a/tools/chatgui/CMakeLists.txt b/tools/chatgui/CMakeLists.txt index b57d8967..445c2f34 100644 --- a/tools/chatgui/CMakeLists.txt +++ b/tools/chatgui/CMakeLists.txt @@ -267,7 +267,6 @@ elseif(UNIX AND NOT APPLE) endif() if(TARGET X11::X11) - target_compile_definitions(chatgui_notifications PRIVATE UTUN_NOTIFICATION_X11) target_link_libraries(chatgui_notifications PRIVATE X11::X11) endif() if(TARGET X11::Xss) diff --git a/tools/chatgui/src/message_notification.cpp b/tools/chatgui/src/message_notification.cpp index 883d7d23..b0731b78 100644 --- a/tools/chatgui/src/message_notification.cpp +++ b/tools/chatgui/src/message_notification.cpp @@ -13,16 +13,13 @@ #include #include -#ifdef UTUN_NOTIFICATION_X11 -#include -#include -#endif - MessageNotification::MessageNotification() : QWidget(nullptr, Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus) , m_activity(new UserActivityMonitor(this)) { setObjectName("messageNotification"); + // X11/XWayland: отдельное overlay-окно не принадлежит рабочему столу главного окна и не забирает фокус. + if (QGuiApplication::platformName() == "xcb") setWindowFlag(Qt::X11BypassWindowManagerHint); setAttribute(Qt::WA_ShowWithoutActivating); setAttribute(Qt::WA_X11NetWmWindowTypeNotification); #ifdef Q_OS_MACOS @@ -61,8 +58,8 @@ MessageNotification::MessageNotification() GUI_DEBUG("notification: first activity target=%s hide_in_ms=%d", qPrintable(m_target), m_hideTimer.interval()); m_hideTimer.start(); }); - GUI_DEBUG("notification: initialized platform=%s hide_after_activity_ms=%d", - qPrintable(QGuiApplication::platformName()), m_hideTimer.interval()); + GUI_DEBUG("notification: initialized platform=%s hide_after_activity_ms=%d all_desktop_overlay=%d", + qPrintable(QGuiApplication::platformName()), m_hideTimer.interval(), int(QGuiApplication::platformName() == "xcb")); if (QGuiApplication::platformName().startsWith("wayland")) GUI_WARN("notification: native Wayland controls desktop, placement and stacking; remapping on current desktop is best effort"); } @@ -104,71 +101,12 @@ void MessageNotification::showMessage(const QString& target, const QString& send x = qBound(area.left(), x, qMax(area.left(), area.right() - width() + 1)); y = qBound(area.top(), y, qMax(area.top(), area.bottom() - height() + 1)); move(x, y); - setDesktopScope(); show(); - setDesktopScope(); // Подтверждаем область после MapRequest, если WM заменил предварительную подсказку. m_activity->start(); GUI_INFO("notification: %s target=%s screen=%s position=%d,%d tray_anchor=%d waiting_for_activity", replacing ? "updated" : "shown", qPrintable(target), qPrintable(screen->name()), x, y, int(!trayGeometry.isEmpty())); } -void MessageNotification::setDesktopScope() { -#ifdef UTUN_NOTIFICATION_X11 - if (QGuiApplication::platformName() != "xcb") return; - Display* display = nullptr; - bool ownDisplay = false; -#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) -#if QT_CONFIG(xcb) - if (auto* native = qGuiApp->nativeInterface()) display = native->display(); -#endif -#endif - if (!display) { display = XOpenDisplay(nullptr); ownDisplay = true; } - if (!display) { GUI_ERROR("notification: cannot open X11 display to select all desktops"); return; } - const Window window = Window(winId()); - QGuiApplication::sync(); // Окно Qt должно существовать на сервере до Xlib-запросов. - XWindowAttributes attributes{}; - if (!XGetWindowAttributes(display, window, &attributes)) { - GUI_ERROR("notification: cannot read X11 window attributes window=0x%lx", window); - if (ownDisplay) XCloseDisplay(display); - return; - } - const Atom desktopAtom = XInternAtom(display, "_NET_WM_DESKTOP", False); - const Atom supportedAtom = XInternAtom(display, "_NET_SUPPORTED", False); - Atom type = None; - int format = 0; - unsigned long count = 0, remaining = 0; - unsigned char* data = nullptr; - const int result = XGetWindowProperty(display, attributes.root, supportedAtom, 0, 4096, False, - XA_ATOM, &type, &format, &count, &remaining, &data); - bool supported = false; - if (result == Success && type == XA_ATOM && format == 32 && data) { - const auto* atoms = reinterpret_cast(data); - for (unsigned long i = 0; i < count; ++i) if (atoms[i] == desktopAtom) { supported = true; break; } - } - if (data) XFree(data); - if (!supported) GUI_WARN("notification: window manager does not advertise desktop selection; all-desktop hint is best effort"); - const unsigned long allDesktops = 0xffffffffUL; - if (!isVisible()) { - XChangeProperty(display, window, desktopAtom, XA_CARDINAL, 32, PropModeReplace, - reinterpret_cast(&allDesktops), 1); - } else { - XEvent event{}; - event.xclient.type = ClientMessage; - event.xclient.window = window; - event.xclient.message_type = desktopAtom; - event.xclient.format = 32; - event.xclient.data.l[0] = long(allDesktops); - event.xclient.data.l[1] = 1; // Запрос обычного приложения, не pager. - if (!XSendEvent(display, attributes.root, False, SubstructureRedirectMask | SubstructureNotifyMask, &event)) - GUI_ERROR("notification: cannot request all desktops window=0x%lx", window); - } - XSync(display, False); - GUI_DEBUG("notification: all-desktop scope requested window=0x%lx mapped=%d wm_supported=%d", - window, int(isVisible()), int(supported)); - if (ownDisplay) XCloseDisplay(display); -#endif -} - void MessageNotification::dismiss(const char* reason) { if (isVisible()) GUI_INFO("notification: hidden target=%s reason=%s", qPrintable(m_target), reason); m_hideTimer.stop(); diff --git a/tools/chatgui/src/message_notification.h b/tools/chatgui/src/message_notification.h index e0ccc6c9..4ad98154 100644 --- a/tools/chatgui/src/message_notification.h +++ b/tools/chatgui/src/message_notification.h @@ -27,7 +27,6 @@ protected: void closeEvent(QCloseEvent* event) override; private: - void setDesktopScope(); QString m_target; QLabel* m_body = nullptr; UserActivityMonitor* m_activity = nullptr;