From 2da86558cccee4f3e5ea44fabf2aa48ae9a70a8f Mon Sep 17 00:00:00 2001 From: Alexander Golubev Date: Sun, 22 Mar 2026 09:28:31 +0300 Subject: [PATCH] TQDesktopWidget: backport changes from Qt4 The class was little changed during lifetime of Qt4, so it was possible to relatively easy backport them. This changeset is based on Qt4.8.7. The changes include: * This fixes several issues on "old-school multihead" X11 setups (with several screens per display i.e. when DISPLAY has form ":x.y" also known as "TDE_MULTIHEAD" or "Zaphod mode"). In particular: * fix graphical drag&drop problems across displays. * fix menus being displayed outside of the screen. * add screenCountChanged() signal * emit resized() signal See-also: https://github.com/qt/qt/blob/v4.8.7/src/gui/kernel/qdesktopwidget_x11.cpp Signed-off-by: Alexander Golubev --- src/kernel/tqdesktopwidget.h | 1 + src/kernel/tqdesktopwidget_x11.cpp | 71 ++++++++++++++++++++++-------- 2 files changed, 53 insertions(+), 19 deletions(-) diff --git a/src/kernel/tqdesktopwidget.h b/src/kernel/tqdesktopwidget.h index 201267708..4126e3c65 100644 --- a/src/kernel/tqdesktopwidget.h +++ b/src/kernel/tqdesktopwidget.h @@ -82,6 +82,7 @@ public: signals: void resized( int ); void workAreaResized( int ); + void screenCountChanged( int ); protected: void resizeEvent( TQResizeEvent *e ); diff --git a/src/kernel/tqdesktopwidget_x11.cpp b/src/kernel/tqdesktopwidget_x11.cpp index 6e167bfe5..71bf11d95 100644 --- a/src/kernel/tqdesktopwidget_x11.cpp +++ b/src/kernel/tqdesktopwidget_x11.cpp @@ -39,6 +39,7 @@ #include "tqdesktopwidget.h" #include "tqapplication.h" #include "tqobjectlist.h" +#include "tqvaluevector.h" #include "tqt_x11_p.h" #include @@ -56,7 +57,6 @@ void tqt_desktopwidget_update_workarea() tqt_desktopwidget_workarea_dirty = true; } - class TQSingleDesktopWidget : public TQWidget { public: @@ -118,14 +118,19 @@ TQDesktopWidgetPrivate::~TQDesktopWidgetPrivate() void TQDesktopWidgetPrivate::init() { // get the screen count - int newScreenCount; + int newScreenCount = ScreenCount(TQPaintDevice::x11AppDisplay()); #ifndef TQT_NO_XINERAMA XineramaScreenInfo *xinerama_screeninfo = 0; - int unused; - use_xinerama = (XineramaQueryExtension(TQPaintDevice::x11AppDisplay(), - &unused, &unused) && - XineramaIsActive(TQPaintDevice::x11AppDisplay())); + + // we ignore the Xinerama extension when the display is using + // traditional multi-screen (with multiple root windows) + if (newScreenCount == 1) { + int unused; + use_xinerama = ( XineramaQueryExtension(TQPaintDevice::x11AppDisplay(), + &unused, &unused) + && XineramaIsActive(TQPaintDevice::x11AppDisplay())); + } if (use_xinerama) { xinerama_screeninfo = @@ -148,7 +153,7 @@ void TQDesktopWidgetPrivate::init() // get the geometry of each screen int i, j, x, y, w, h; - for ( i = 0, j = 0; i < newScreenCount; i++ ) { + for (i = 0, j = 0; i < newScreenCount; i++, j++) { #ifndef TQT_NO_XINERAMA if (use_xinerama) { @@ -165,18 +170,18 @@ void TQDesktopWidgetPrivate::init() h = HeightOfScreen(ScreenOfDisplay(TQPaintDevice::x11AppDisplay(), i)); } - workareas[i] = TQRect(); rects[j].setRect(x, y, w, h); - // overlapping? - if (j > 0 && rects[j-1].intersects(rects[j])) { - // pick the bigger one, ignore the other + if (use_xinerama && j > 0 && rects[j-1].intersects(rects[j])) { + // merge a "cloned" screen with the previous, hiding all crtcs + // that are currently showing a sub-rect of the previous screen if ((rects[j].width()*rects[j].height()) > (rects[j-1].width()*rects[j-1].height())) - rects[j-1] = rects[j]; + rects[j-1] = rects[j]; + j--; } - else - j++; + + workareas[i] = TQRect(); } if (screens) { @@ -274,26 +279,37 @@ const TQRect& TQDesktopWidget::availableGeometry( int screen ) const if ( d->workareas[screen].isValid() ) return d->workareas[screen]; - if ( ! isVirtualDesktop() && tqt_net_supports( tqt_net_workarea ) ) { + if ( tqt_net_supports( tqt_net_workarea ) ) { + int x11Screen = isVirtualDesktop() ? + DefaultScreen(TQPaintDevice::x11AppDisplay()) : screen; Atom ret; int format, e; unsigned char *data = 0; unsigned long nitems, after; e = XGetWindowProperty( TQPaintDevice::x11AppDisplay(), - TQPaintDevice::x11AppRootWindow( screen ), + TQPaintDevice::x11AppRootWindow( x11Screen ), tqt_net_workarea, 0, 4, False, XA_CARDINAL, &ret, &format, &nitems, &after, &data ); + TQRect workArea; if ( e == Success && ret == XA_CARDINAL && format == 32 && nitems == 4 ) { long *workarea = (long *) data; - d->workareas[screen].setRect( workarea[0], workarea[1], - workarea[2], workarea[3] ); + workArea = TQRect(workarea[0], workarea[1], workarea[2], workarea[3]); } else { - d->workareas[screen] = screenGeometry(screen); + workArea = screenGeometry(screen); + } + + if (isVirtualDesktop()) { + // intersect the workarea (which spawns all Xinerama screens) with the rect for the + // requested screen + workArea &= screenGeometry(screen); } + + d->workareas[screen] = workArea; + if ( data ) XFree( data ); } else { @@ -352,6 +368,23 @@ int TQDesktopWidget::screenNumber( const TQPoint &point ) const void TQDesktopWidget::resizeEvent( TQResizeEvent *event ) { + int oldScreenCount = d->screenCount; + TQValueVector oldRects(oldScreenCount); + for (int i = 0; i < oldScreenCount; ++i) { + oldRects[i] = d->rects[i]; + } + + d->init(); + + for (int i = 0; i < TQMIN(oldScreenCount, d->screenCount); ++i) { + if (oldRects.at(i) != d->rects[i]) + emit resized(i); + } + + if (oldScreenCount != d->screenCount) { + emit screenCountChanged(d->screenCount); + } + d->init(); tqt_desktopwidget_workarea_dirty = true; TQWidget::resizeEvent( event );