@ -1,4 +1,4 @@
/* Ручная проверка EWMH на настоящем X11/XWayland: настройки рабочих столов пользователя не меняются . */
/* Ручная проверка overlay на X11/XWayland: нет родительского окна и привязки WM к одному рабочему столу . */
# include "../src/message_notification.h"
# include "../../../lib/debug_config.h"
# include <QtTest>
@ -9,19 +9,36 @@ class NotificationDesktopTest : public QObject {
Q_OBJECT
Display * m_display = nullptr ;
qint64 desktop ( Window window , const char * property = " _NET_WM_DESKTOP " ) {
bool isDesktopOverlay ( Window window ) {
XWindowAttributes attributes { } ;
if ( ! XGetWindowAttributes ( m_display , window , & attributes ) ) {
DEBUG_ERROR ( DEBUG_CATEGORY_DEBUG , " notification desktop test: no attributes window=0x%lx " , window ) ;
return false ;
}
Window root = 0 , parent = 0 ;
Window * children = nullptr ;
unsigned int childCount = 0 ;
if ( ! XQueryTree ( m_display , window , & root , & parent , & children , & childCount ) ) {
DEBUG_ERROR ( DEBUG_CATEGORY_DEBUG , " notification desktop test: no parent info window=0x%lx " , window ) ;
return false ;
}
if ( children ) XFree ( children ) ;
Atom type = None ;
int format = 0 ;
unsigned long count = 0 , remaining = 0 ;
unsigned char * data = nullptr ;
const Atom atom = XInternAtom ( m_display , property , False ) ;
const int status = XGetWindowProperty ( m_display , window , atom , 0 , 1 , False ,
XA_CARDINAL , & type , & format , & count , & remaining , & data ) ;
qint64 value = - 1 ;
if ( status = = Success & & type = = XA_CARDINAL & & format = = 32 & & count = = 1 & & data )
value = * reinterpret_cast < const unsigned long * > ( data ) & 0xffffffffUL ;
const Atom atom = XInternAtom ( m_display , " _NET_CLIENT_LIST " , False ) ;
const int status = XGetWindowProperty ( m_display , root , atom , 0 , 4096 , False ,
XA_WINDOW , & type , & format , & count , & remaining , & data ) ;
bool managed = false ;
if ( status = = Success & & type = = XA_WINDOW & & format = = 32 & & data ) {
const auto * windows = reinterpret_cast < const Window * > ( data ) ;
for ( unsigned long i = 0 ; i < count ; + + i ) if ( windows [ i ] = = window ) { managed = true ; break ; }
}
if ( data ) XFree ( data ) ;
return value ;
DEBUG_INFO ( DEBUG_CATEGORY_DEBUG , " notification desktop test: window=0x%lx mapped=%d override_redirect=%d root_parent=%d managed=%d " ,
window , attributes . map_state , int ( attributes . override_redirect ) , int ( parent = = root ) , int ( managed ) ) ;
return attributes . map_state = = IsViewable & & attributes . override_redirect & & parent = = root & & ! managed ;
}
private slots :
@ -38,36 +55,18 @@ private slots:
notification . showMessage ( " 42 " , " Alice " , " Desktop test " , { } ) ;
const Window window = Window ( notification . winId ( ) ) ;
QTest : : qWait ( 200 ) ; // Проверяем состояние после обработки MapRequest оконным менеджером.
DEBUG_INFO ( DEBUG_CATEGORY_DEBUG , " notification desktop test: mapped desktop=%lld root_current=%lld root_count=%lld " ,
( long long ) desktop ( window ) , ( long long ) desktop ( DefaultRootWindow ( m_display ) , " _NET_CURRENT_DESKTOP " ) ,
( long long ) desktop ( DefaultRootWindow ( m_display ) , " _NET_NUMBER_OF_DESKTOPS " ) ) ;
QTRY_COMPARE_WITH_TIMEOUT ( desktop ( window ) , qint64 ( 0xffffffffUL ) , 2000 ) ;
QVERIFY ( isDesktopOverlay ( window ) ) ;
QVERIFY ( ! notification . parentWidget ( ) ) ;
QVERIFY ( notification . windowFlags ( ) & Qt : : WindowDoesNotAcceptFocus ) ;
DEBUG_INFO ( DEBUG_CATEGORY_DEBUG , " notification desktop test: first show window=0x%lx desktop=all " , window ) ;
// Переносим только своё окно на стол 0; активный стол пользователя может изменяться во время проверки.
const qint64 singleDesktop = 0 ;
XEvent event { } ;
event . xclient . type = ClientMessage ;
event . xclient . window = window ;
event . xclient . message_type = XInternAtom ( m_display , " _NET_WM_DESKTOP " , False ) ;
event . xclient . format = 32 ;
event . xclient . data . l [ 0 ] = long ( singleDesktop ) ;
event . xclient . data . l [ 1 ] = 1 ;
QVERIFY ( XSendEvent ( m_display , DefaultRootWindow ( m_display ) , False ,
SubstructureRedirectMask | SubstructureNotifyMask , & event ) ) ;
XFlush ( m_display ) ;
QTRY_COMPARE_WITH_TIMEOUT ( desktop ( window ) , singleDesktop , 2000 ) ;
notification . showMessage ( " dm:7 " , " Bob " , " Desktop test " , { } ) ;
QTRY_COMPARE_WITH_TIMEOUT ( desktop ( window ) , qint64 ( 0xffffffffUL ) , 2000 ) ;
DEBUG_INFO ( DEBUG_CATEGORY_DEBUG , " notification desktop test: updated visible window desktop=all " ) ;
QCOMPARE ( Window ( notification . winId ( ) ) , window ) ;
QVERIFY ( isDesktopOverlay ( window ) ) ;
notification . dismiss ( " test-reshow " ) ;
QTest : : qWait ( 50 ) ;
notification . showMessage ( " 43 " , " Charlie " , " Desktop test " , { } ) ;
QTRY_COMPARE_WITH_TIMEOUT ( desktop ( Window ( notification . winId ( ) ) ) , qint64 ( 0xffffffffUL ) , 20 00 ) ;
DEBUG_INFO ( DEBUG_CATEGORY_DEBUG , " notification desktop test: withdrawn window shown again desktop=all " ) ;
QTest : : qWait ( 200 ) ;
QVERIFY ( isDesktopOverlay ( Window ( notification . winId ( ) ) ) ) ;
notification . dismiss ( " test-complete " ) ;
}
} ;