From 0ba12a0837c66ee6bc3daff34ada2655a9ad10a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Thu, 4 Dec 2003 13:54:10 +0000 Subject: [PATCH] Perform whole new window managing with X server grab, in order to prevent "smart" apps from doing stupid things before they get MapNotify. This avoids the recent Java+OracleInstaller strange problem too. The patch may look huge, but it's only adding two KWin wrappers for X(Un)GrabServer() and uncommenting the calls in Client::manage(). svn path=/trunk/kdebase/kwin/; revision=271152 --- atoms.cpp | 4 ---- bridge.cpp | 8 ++++++++ bridge.h | 1 + client.cpp | 5 ++--- clients/PORTING | 1 + clients/test/test.cpp | 12 ++++++------ geometry.cpp | 4 ++-- kcmkwin/kwindecoration/preview.cpp | 4 ++++ kcmkwin/kwindecoration/preview.h | 1 + killwindow.cpp | 4 ++-- lib/kdecoration.cpp | 10 ++++++++++ lib/kdecoration.h | 11 ++++++++++- lib/kdecoration_p.h | 1 + manage.cpp | 4 ++-- utils.cpp | 14 ++++++++++++++ utils.h | 2 ++ workspace.cpp | 4 ++++ 17 files changed, 70 insertions(+), 20 deletions(-) diff --git a/atoms.cpp b/atoms.cpp index 397c63c28f..16c2d19986 100644 --- a/atoms.cpp +++ b/atoms.cpp @@ -65,10 +65,6 @@ Atoms::Atoms() Atom fake; atoms[n] = &fake; names[n++] = (char *) "_DT_SM_WINDOW_INFO"; - - Atom dummy; - atoms[n] = &dummy; - names[n++] = (char *) "_ICEWM_WINOPTHINT"; XInternAtoms( qt_xdisplay(), names, n, FALSE, atoms_return ); for (int i = 0; i < n; i++ ) diff --git a/bridge.cpp b/bridge.cpp index 08f3feb9ad..2888d3dc19 100644 --- a/bridge.cpp +++ b/bridge.cpp @@ -170,4 +170,12 @@ QRegion Bridge::unobscuredRegion( const QRegion& r ) const return reg; } +void Bridge::grabXServer( bool grab ) + { + if( grab ) + KWinInternal::grabXServer(); + else + KWinInternal::ungrabXServer(); + } + } // namespace diff --git a/bridge.h b/bridge.h index a5a1667c6d..eb6d7c1028 100644 --- a/bridge.h +++ b/bridge.h @@ -62,6 +62,7 @@ class Bridge : public KDecorationBridge virtual QWidget* initialParentWidget() const; virtual Qt::WFlags initialWFlags() const; virtual void helperShowHide( bool show ); + virtual void grabXServer( bool grab ); private: Client* c; }; diff --git a/client.cpp b/client.cpp index 54146a8702..9735326f97 100644 --- a/client.cpp +++ b/client.cpp @@ -590,8 +590,7 @@ void Client::animateMinimizeOrUnminimize( bool minimize ) tf = (after.top() - before.top())/step; bf = (after.bottom() - before.bottom())/step; - - XGrabServer( qt_xdisplay() ); + grabXServer(); QRect area = before; QRect area2; @@ -642,7 +641,7 @@ void Client::animateMinimizeOrUnminimize( bool minimize ) p.drawPixmap( area2.x(), area2.y(), pm2 ); p.end(); - XUngrabServer( qt_xdisplay() ); + ungrabXServer(); } diff --git a/clients/PORTING b/clients/PORTING index 5cc1815206..4fd3b0bb3c 100644 --- a/clients/PORTING +++ b/clients/PORTING @@ -37,3 +37,4 @@ porting: - animateIconifyOrDeiconify() -> animateMinimize() - just drop it if it's empty - pay special attention to SLOT() names and cases where you need to use 'widget()' instead of 'this' - buttons should use setCursor() if they don't want cursor set by mousePosition() + - X(un)GrabServer() -> (un)grabXServer() diff --git a/clients/test/test.cpp b/clients/test/test.cpp index 4d4de0a8bf..9f2a47c682 100644 --- a/clients/test/test.cpp +++ b/clients/test/test.cpp @@ -195,7 +195,7 @@ bool Decoration::animateMinimize(bool iconify) QPoint p3(int(cx + dw + dx), int(midy + dch)); QPoint p4(int(cx - dx), p3.y()); - XGrabServer(qt_xdisplay()); + grabXServer(); p.drawLine(p1, p2); p.drawLine(p2, p3); @@ -211,7 +211,7 @@ bool Decoration::animateMinimize(bool iconify) p.drawLine(p3, p4); p.drawLine(p4, p1); - XUngrabServer(qt_xdisplay()); + ungrabXServer(); // FRAME qApp->processEvents(); // FRAME ??? @@ -254,14 +254,14 @@ bool Decoration::animateMinimize(bool iconify) r.setWidth(r.width() - 2 * dx); r.setHeight(r.height() - 2 * dy); - XGrabServer(qt_xdisplay()); + grabXServer(); p.drawRect(r); p.flush(); usleep(200); p.drawRect(r); - XUngrabServer(qt_xdisplay()); + ungrabXServer(); // FRAME qApp->processEvents(); } @@ -289,7 +289,7 @@ bool Decoration::animateMinimize(bool iconify) ); #endif - XGrabServer(qt_xdisplay()); + grabXServer(); p.drawLine(wingeom.bottomRight(), icongeom.bottomRight()); p.drawLine(wingeom.bottomLeft(), icongeom.bottomLeft()); @@ -307,7 +307,7 @@ bool Decoration::animateMinimize(bool iconify) p.drawLine(wingeom.topLeft(), icongeom.topLeft()); p.drawLine(wingeom.topRight(), icongeom.topRight()); - XUngrabServer(qt_xdisplay()); + ungrabXServer(); } break; } diff --git a/geometry.cpp b/geometry.cpp index 1d2187cc91..07acb619d9 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -1513,7 +1513,7 @@ bool Client::startMoveResize() if ( ( isMove() && options->moveMode != Options::Opaque ) || ( isResize() && options->resizeMode != Options::Opaque ) ) { - XGrabServer( qt_xdisplay() ); + grabXServer(); kapp->sendPostedEvents(); // we have server grab -> nothing should cause paint events // unfortunately, that's not completely true, Qt may generate @@ -1549,7 +1549,7 @@ void Client::leaveMoveResize() } if ( ( isMove() && options->moveMode != Options::Opaque ) || ( isResize() && options->resizeMode != Options::Opaque ) ) - XUngrabServer( qt_xdisplay() ); + ungrabXServer(); XUngrabKeyboard( qt_xdisplay(), qt_x_time ); XUngrabPointer( qt_xdisplay(), qt_x_time ); workspace()->setClientIsMoving(0); diff --git a/kcmkwin/kwindecoration/preview.cpp b/kcmkwin/kwindecoration/preview.cpp index b9d9540107..fb714b4915 100644 --- a/kcmkwin/kwindecoration/preview.cpp +++ b/kcmkwin/kwindecoration/preview.cpp @@ -383,6 +383,10 @@ void KDecorationPreviewBridge::helperShowHide( bool ) { } +void KDecorationPreviewBridge::grabXServer( bool ) + { + } + KDecorationPreviewOptions::KDecorationPreviewOptions() { d = new KDecorationOptionsPrivate; diff --git a/kcmkwin/kwindecoration/preview.h b/kcmkwin/kwindecoration/preview.h index 5044dcc114..6ea78d0c56 100644 --- a/kcmkwin/kwindecoration/preview.h +++ b/kcmkwin/kwindecoration/preview.h @@ -105,6 +105,7 @@ class KDecorationPreviewBridge virtual QWidget* initialParentWidget() const; virtual Qt::WFlags initialWFlags() const; virtual void helperShowHide( bool show ); + virtual void grabXServer( bool grab ); private: KDecorationPreview* preview; bool active; diff --git a/killwindow.cpp b/killwindow.cpp index 88f6235c39..bd39e48bc8 100644 --- a/killwindow.cpp +++ b/killwindow.cpp @@ -52,7 +52,7 @@ void KillWindow::start() int escape_pressed = 0; int button_released = 0; - XGrabServer(qt_xdisplay()); + grabXServer(); while (!return_pressed && !escape_pressed && !button_released) { @@ -101,7 +101,7 @@ void KillWindow::start() workspace->killWindowId( child ); } - XUngrabServer(qt_xdisplay()); + ungrabXServer(); XUngrabKeyboard(qt_xdisplay(), CurrentTime); XUngrabPointer(qt_xdisplay(), CurrentTime); diff --git a/lib/kdecoration.cpp b/lib/kdecoration.cpp index c87c80b326..f9149acb50 100644 --- a/lib/kdecoration.cpp +++ b/lib/kdecoration.cpp @@ -289,6 +289,16 @@ void KDecoration::helperShowHide( bool show ) void KDecoration::reset( unsigned long ) { } + +void KDecoration::grabXServer() + { + bridge_->grabXServer( true ); + } + +void KDecoration::ungrabXServer() + { + bridge_->grabXServer( false ); + } KDecoration::MousePosition KDecoration::mousePosition( const QPoint& p ) const { diff --git a/lib/kdecoration.h b/lib/kdecoration.h index c1f1cab9ec..579cd4dec7 100644 --- a/lib/kdecoration.h +++ b/lib/kdecoration.h @@ -547,7 +547,8 @@ class KDecoration virtual bool drawbound( const QRect& geom, bool clear ); /** * This function may be reimplemented to provide custom minimize/restore animations - * The reimplementation is allowed to perform X server grabs if necessary, but no + * The reimplementation is allowed to perform X server grabs if necessary + * (only using the functions provided by this API, no direct Xlib calls), but no * futher event processing is allowed (i.e. no kapp->processEvents()). * @a False should be returned if the default implementation should be used. * Note that you should not use this function to force disabling of the animation. @@ -612,6 +613,14 @@ class KDecoration * Returns the factory that created this decoration. */ KDecorationFactory* factory() const; + /** + * Performs X server grab. It is safe to call it several times in a row. + */ + void grabXServer(); + /** + * Ungrabs X server (if the number of ungrab attempts matches the number of grab attempts). + */ + void ungrabXServer(); public slots: // requests from decoration diff --git a/lib/kdecoration_p.h b/lib/kdecoration_p.h index 24cabd9c93..7d720eead6 100644 --- a/lib/kdecoration_p.h +++ b/lib/kdecoration_p.h @@ -100,6 +100,7 @@ class KDecorationBridge : public KDecorationDefines virtual QWidget* initialParentWidget() const = 0; virtual Qt::WFlags initialWFlags() const = 0; virtual void helperShowHide( bool ) = 0; + virtual void grabXServer( bool grab ) = 0; }; #endif diff --git a/manage.cpp b/manage.cpp index 87e42c1e08..1fa01196b2 100644 --- a/manage.cpp +++ b/manage.cpp @@ -39,7 +39,7 @@ bool Client::manage( Window w, bool isMapped ) if( !XGetWindowAttributes(qt_xdisplay(), w, &attr)) return false; -// XGrabServer( qt_xdisplay()); // FRAME + grabXServer(); // from this place on, manage() mustn't return false block_geometry = 1; @@ -488,7 +488,7 @@ bool Client::manage( Window w, bool isMapped ) delete session; -// XUngrabServer( qt_xdisplay()); //FRAME + ungrabXServer(); return true; } diff --git a/utils.cpp b/utils.cpp index 1f04b84db8..102c7f355c 100644 --- a/utils.cpp +++ b/utils.cpp @@ -19,6 +19,7 @@ License. See the file "COPYING" for the exact licensing terms. #include "atoms.h" #include +#include #include #include @@ -231,7 +232,20 @@ void updateXTime() qt_x_time = ev.xproperty.time; } +static int server_grab_count = 0; +void grabXServer() + { + if( ++server_grab_count == 1 ) + XGrabServer( qt_xdisplay()); + } + +void ungrabXServer() + { + assert( server_grab_count > 0 ); + if( --server_grab_count == 0 ) + XUngrabServer( qt_xdisplay()); + } } // namespace diff --git a/utils.h b/utils.h index ee172287fb..fbfe4edbe0 100644 --- a/utils.h +++ b/utils.h @@ -143,6 +143,8 @@ class KWinSelectionOwner QCString getStringProperty(WId w, Atom prop, char separator=0); void updateXTime(); +void grabXServer(); +void ungrabXServer(); // the docs say it's UrgencyHint, but it's often #defined as XUrgencyHint #ifndef UrgencyHint diff --git a/workspace.cpp b/workspace.cpp index 68e93c15bc..717783ad05 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -298,6 +298,7 @@ void Workspace::init() topmenu_height = 0; managing_topmenus = false; topmenu_space = NULL; +// TODO grabXServer(); - where exactly put this? topmenu selection claiming down belong must be before { // begin updates blocker block StackingUpdatesBlocker blocker( this ); @@ -366,11 +367,13 @@ void Workspace::init() // and maybe in rare cases also if the selected client doesn't // want focus workspaceInit = false; +// TODO ungrabXServer() } Workspace::~Workspace() { blockStackingUpdates( true ); +// TODO grabXServer(); // use stacking_order, so that kwin --replace keeps stacking order for( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); @@ -400,6 +403,7 @@ Workspace::~Workspace() delete topmenu_watcher; delete topmenu_selection; delete topmenu_space; +// TODO ungrabXServer(); _self = 0; }