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
This commit is contained in:
Luboš Luňák 2003-12-04 13:54:10 +00:00
parent e7d3ffaceb
commit 0ba12a0837
17 changed files with 70 additions and 20 deletions

View file

@ -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++ )

View file

@ -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

View file

@ -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;
};

View file

@ -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();
}

View file

@ -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()

View file

@ -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;
}

View file

@ -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);

View file

@ -383,6 +383,10 @@ void KDecorationPreviewBridge::helperShowHide( bool )
{
}
void KDecorationPreviewBridge::grabXServer( bool )
{
}
KDecorationPreviewOptions::KDecorationPreviewOptions()
{
d = new KDecorationOptionsPrivate;

View file

@ -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;

View file

@ -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);

View file

@ -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
{

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -19,6 +19,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "atoms.h"
#include <kxerrorhandler.h>
#include <assert.h>
#include <X11/Xlib.h>
#include <X11/extensions/shape.h>
@ -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

View file

@ -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

View file

@ -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;
}