From 2d2ffd014846cbd89a53522a4bcef3f15dd043b7 Mon Sep 17 00:00:00 2001
From: Alexander Golubev <fatzer2@gmail.com>
Date: Sun, 22 Mar 2026 09:28:31 +0300
Subject: 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 <fatzer2@gmail.com>
---
 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 <cstdlib>
 
@@ -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<TQRect> 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 );
-- 
cgit v1.2.3

