From a30c061abbc407b0caa78feb2099bdfb31419cba Mon Sep 17 00:00:00 2001 From: Matthias Ettrich Date: Fri, 12 Nov 1999 03:11:19 +0000 Subject: [PATCH] shape windows support, some fixes for configure-request handling svn path=/trunk/kdebase/kwin/; revision=33553 --- client.cpp | 24 ++++++++++++++--- client.h | 11 ++++++++ workspace.cpp | 74 ++++++++++++++++++++++++++++++++------------------- workspace.h | 8 +++++- 4 files changed, 86 insertions(+), 31 deletions(-) diff --git a/client.cpp b/client.cpp index 3a491f4d1a..66bf0b9335 100644 --- a/client.cpp +++ b/client.cpp @@ -13,6 +13,7 @@ #include #include #include +#include extern Atom qt_wm_state; @@ -30,6 +31,7 @@ void Client::drawbound( const QRect& geom ) p.setRasterOp( Qt::XorROP ); p.drawRect( geom ); } + void Client::clearbound() { if ( !visible_bound ) @@ -39,6 +41,16 @@ void Client::clearbound() visible_bound = 0; } +void Client::updateShape() +{ + if ( shape() ) + XShapeCombineShape(qt_xdisplay(), winId(), ShapeBounding, + windowWrapper()->x(), windowWrapper()->y(), + window(), ShapeBounding, ShapeSet); + else + XShapeCombineMask( qt_xdisplay(), winId(), ShapeBounding, 0, 0, + None, ShapeSet); +} static void sendClientMessage(Window w, Atom a, long x){ XEvent ev; @@ -116,7 +128,6 @@ WindowWrapper::WindowWrapper( WId w, Client *parent, const char* name) StructureNotifyMask ); - // install a passive grab to catch mouse button events XGrabButton(qt_xdisplay(), AnyButton, AnyModifier, winId(), FALSE, ButtonPressMask, GrabModeSync, GrabModeSync, @@ -145,7 +156,9 @@ void WindowWrapper::resizeEvent( QResizeEvent * ) if ( win ) { XMoveResizeWindow( qt_xdisplay(), win, 0, 0, width(), height() ); -} + if ( ((Client*)parentWidget())->shape() ) + ((Client*)parentWidget())->updateShape(); + } } void WindowWrapper::showEvent( QShowEvent* ) @@ -262,7 +275,7 @@ Client::Client( Workspace *ws, WId w, QWidget *parent, const char *name, WFlags active = FALSE; shaded = FALSE; transient_for = None; - is_sticky = FALSE; + is_shape = FALSE; getIcons(); getWindowProtocols(); @@ -325,6 +338,11 @@ void Client::manage( bool isMapped ) placementDone = TRUE; } + if ( (is_shape = Shape::hasShape( win )) ) { + updateShape(); + } + + // ### TODO check XGetWMHints() for initial mapping state, icon, etc. pp. // assume window wants to be visible on the current desktop desk = KWM::desktop( win ); //workspace()->currentDesktop(); diff --git a/client.h b/client.h index e68ac546c1..2f087ea3ff 100644 --- a/client.h +++ b/client.h @@ -118,6 +118,11 @@ public: // transparent stuff virtual void drawbound( const QRect& geom ); virtual void clearbound(); + + + // shape extensions + bool shape() const; + void updateShape(); public slots: void iconify(); @@ -196,6 +201,7 @@ private: bool shaded; WId transient_for; bool is_sticky; + bool is_shape; void getIcons(); void getWindowProtocols(); uint Pdeletewindow :1; // does the window understand the DeleteWindow protocol? @@ -283,6 +289,11 @@ inline bool Client::isSticky() const } +inline bool Client::shape() const +{ + return is_shape; +} + class NoBorderClient : public Client { Q_OBJECT diff --git a/workspace.cpp b/workspace.cpp index f4620a8815..01d1d5ae51 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -14,6 +14,31 @@ #include #include #include +#include + +// used to store the return values of +// XShapeQueryExtension. +// Necessary since shaped window are an extension to X +static int kwin_has_shape = 0; +static int kwin_shape_event = 0; + +// does the window w need a shape combine mask around it? +bool Shape::hasShape( WId w){ + int xws, yws, xbs, ybs; + unsigned wws, hws, wbs, hbs; + int boundingShaped, clipShaped; + if (!kwin_has_shape) + return FALSE; + XShapeQueryExtents(qt_xdisplay(), w, + &boundingShaped, &xws, &yws, &wws, &hws, + &clipShaped, &xbs, &ybs, &wbs, &hbs); + return boundingShaped != 0; +} + +int Shape::shapeEvent() +{ + return kwin_shape_event; +} static Client* clientFactory( Workspace *ws, WId w ) @@ -37,17 +62,21 @@ static Client* clientFactory( Workspace *ws, WId w ) c->setSticky( TRUE ); return c; } + + if ( Shape::hasShape( w ) ){ + return new NoBorderClient( ws, w ); + } KConfig *config = KGlobal::config(); config->setGroup("style"); // well, it will be soon ;-) QString tmpStr = config->readEntry("Plugin", "standard"); - if(tmpStr == "standard") - return new StdClient( ws, w ); - else if(tmpStr == "system") - return new SystemClient( ws, w ); + if(tmpStr == "system") + return new SystemClient( ws, w ); else if(tmpStr == "be") - return new BeClient( ws, w ); + return new BeClient( ws, w ); + else + return new StdClient( ws, w ); } Workspace::Workspace() @@ -66,6 +95,9 @@ Workspace::Workspace() SubstructureNotifyMask ); + int dummy; + kwin_has_shape = XShapeQueryExtension(qt_xdisplay(), &kwin_shape_event, &dummy); + init(); control_grab = FALSE; tab_grab = FALSE; @@ -227,7 +259,10 @@ bool Workspace::workspaceEvent( XEvent * e ) } break; case ConfigureRequest: - if ( e->xconfigurerequest.parent == root ) { + c = findClient( e->xconfigurerequest.window ); + if ( c ) + return c->windowEvent( e ); + else if ( e->xconfigurerequest.parent == root ) { XWindowChanges wc; unsigned int value_mask = 0; wc.border_width = 0; @@ -239,29 +274,9 @@ bool Workspace::workspaceEvent( XEvent * e ) wc.stack_mode = Above; value_mask = e->xconfigurerequest.value_mask | CWBorderWidth; XConfigureWindow( qt_xdisplay(), e->xconfigurerequest.window, value_mask, & wc ); - - XWindowAttributes attr; - if (XGetWindowAttributes(qt_xdisplay(), e->xconfigurerequest.window, &attr)){ - // send a synthetic configure notify in any case (even if we didn't change anything) - XConfigureEvent c; - c.type = ConfigureNotify; - c.event = e->xconfigurerequest.window; - c.window = e->xconfigurerequest.window; - c.x = attr.x; - c.y = attr.y; - c.width = attr.width; - c.height = attr.height; - c.border_width = 0; - XSendEvent( qt_xdisplay(), c.event, TRUE, NoEventMask, (XEvent*)&c ); - } + return TRUE; } - else { - c = findClient( e->xconfigurerequest.window ); - if ( c ) - return c->windowEvent( e ); - } - break; case KeyPress: return keyPress(e->xkey); @@ -277,6 +292,11 @@ bool Workspace::workspaceEvent( XEvent * e ) return clientMessage(e->xclient); break; default: + if ( e->type == Shape::shapeEvent() ) { + c = findClient( ((XShapeEvent *)e)->window ); + if ( c ) + c->updateShape(); + } break; } return FALSE; diff --git a/workspace.h b/workspace.h index d20aa7de4e..c0a3fd98ba 100644 --- a/workspace.h +++ b/workspace.h @@ -15,6 +15,12 @@ class KGlobalAccel; typedef QValueList ClientList; typedef QValueList WIdList; +class Shape { +public: + static bool hasShape( WId w); + static int shapeEvent(); +}; + class Workspace : public QObject { Q_OBJECT @@ -105,7 +111,7 @@ private: void setDecoration( int deco ); void propagateClients( bool onlyStacking = FALSE); - + WIdList dockwins; bool addDockwin( WId w ); bool removeDockwin( WId w );