[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    [patch] Grab windows anywhere, not just titlebar
From:       Stefan Monov <logixoul () gmail ! com>
Date:       2007-11-07 17:12:31
Message-ID: 200711071912.32141.logixoul () gmail ! com
[Download RAW message or body]

Hi,

So I saw Frederik's commit 731583:
"Make it possible to move the krunner window by clicking on an empty part
of it and dragging the mouse."

I have always thought it would be great if all KDE windows behaved like that 
(btw Mac OS X does it), so I did some copy-paste-fu and here we have a 
patch -- attached.

It makes all KMainWindows and KDialogs grabable. cool =)

Unfortunately it doesn't work when you grab:
- the space on the right of menubars
- a groupbox
- a widgetstack
- the space on the right of breadcrumb bars
- etc.

Inherent disadvantages:
- introduces inconsistency with non-kde apps
- anything else?

Would be nice if the code was shared instead of copy-pasted.

It will also let us do away with the titlebar bevel in Oxygen, which we 
introduced to make it clear where the grabable titlebar ends (though it 
clashes badly with the artistic vision).

Comments? Improvements?
How to make it work on menubars?
Too late for such a big change in 4.0?
Compatibility with other WMs, OSes?

Cheers,
Stefan

ps: hmm, looks like a dot commenter had the same idea ;)

["grabwin.diff" (text/x-diff)]

Index: dialogs/kdialog.cpp
===================================================================
--- dialogs/kdialog.cpp	(revision 733851)
+++ dialogs/kdialog.cpp	(working copy)
@@ -38,6 +38,8 @@
 #include <QTimer>
 #include <QVBoxLayout>
 #include <QWhatsThis>
+#include <QMouseEvent>
+#include <QX11Info>
 
 #include <kconfiggroup.h>
 #include <kglobalsettings.h>
@@ -55,6 +57,7 @@
 #ifdef Q_WS_X11
 #include <qx11info_x11.h>
 #include <netwm.h>
+#include <X11/Xlib.h>
 #endif
 
 int KDialogPrivate::mMarginSize = 9;
@@ -427,6 +430,20 @@
   QDialog::keyPressEvent( event );
 }
 
+void KDialog::mousePressEvent(QMouseEvent *e)
+{
+    // We have to release the mouse grab before initiating the move operation.
+    // Ideally we would call releaseMouse() to do this, but when we only have an
+    // implicit passive grab, Qt is unaware of it, and will refuse to release it.
+    XUngrabPointer(x11Info().display(), CurrentTime);
+
+    // Ask the window manager to start an interactive move operation.
+    NETRootInfo rootInfo(x11Info().display(), NET::WMMoveResize);
+    rootInfo.moveResizeRequest(winId(), e->globalX(), e->globalY(), NET::Move);
+
+    e->accept();
+}
+
 int KDialog::marginHint()
 {
     return KDialogPrivate::mMarginSize;
Index: dialogs/kdialog.h
===================================================================
--- dialogs/kdialog.h	(revision 733851)
+++ dialogs/kdialog.h	(working copy)
@@ -772,6 +772,7 @@
      * @internal
      */
     virtual void keyPressEvent( QKeyEvent* );
+    virtual void mousePressEvent( QMouseEvent *e );
 
   protected Q_SLOTS:
     /**
Index: widgets/kmainwindow.cpp
===================================================================
--- widgets/kmainwindow.cpp	(revision 733851)
+++ widgets/kmainwindow.cpp	(working copy)
@@ -43,6 +43,8 @@
 #include <QtGui/QSessionManager>
 #include <QtGui/QStyle>
 #include <QtGui/QWidget>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QX11Info>
 #if 0
 #include <qdom.h>
 #endif
@@ -65,6 +67,7 @@
 #if defined Q_WS_X11
 #include <qx11info_x11.h>
 #include <netwm.h>
+#include <X11/Xlib.h>
 #endif
 
 #include <stdlib.h>
@@ -901,6 +904,20 @@
             }
         }
         break;
+    case QEvent::MouseButtonPress:
+        {
+            QMouseEvent *event = static_cast<QMouseEvent*>(ev);
+            // We have to release the mouse grab before initiating the move operation.
+            // Ideally we would call releaseMouse() to do this, but when we only have an
+            // implicit passive grab, Qt is unaware of it, and will refuse to release it.
+            XUngrabPointer(x11Info().display(), CurrentTime);
+
+            // Ask the window manager to start an interactive move operation.
+            NETRootInfo rootInfo(x11Info().display(), NET::WMMoveResize);
+            rootInfo.moveResizeRequest(winId(), event->globalX(), event->globalY(), NET::Move);
+            event->accept();
+        }
+        break;
     case QEvent::ChildRemoved:
         {
             QChildEvent *event = static_cast<QChildEvent*>(ev);


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic