1999-11-11 01:27:37 +00:00
|
|
|
|
#include <kconfig.h>
|
|
|
|
|
#include <kglobal.h>
|
1999-11-13 01:51:22 +00:00
|
|
|
|
#include <kglobalaccel.h>
|
|
|
|
|
#include <klocale.h>
|
1999-11-11 01:27:37 +00:00
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
#include "workspace.h"
|
|
|
|
|
#include "client.h"
|
|
|
|
|
#include "stdclient.h"
|
|
|
|
|
#include "beclient.h"
|
1999-10-11 02:00:06 +00:00
|
|
|
|
#include "systemclient.h"
|
1999-08-19 23:26:42 +00:00
|
|
|
|
#include "tabbox.h"
|
|
|
|
|
#include "atoms.h"
|
|
|
|
|
#include <X11/X.h>
|
|
|
|
|
#include <X11/Xos.h>
|
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
|
#include <X11/Xatom.h>
|
|
|
|
|
#include <X11/keysym.h>
|
1999-11-12 03:11:19 +00:00
|
|
|
|
#include <X11/extensions/shape.h>
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static Client* clientFactory( Workspace *ws, WId w )
|
|
|
|
|
{
|
|
|
|
|
// hack TODO hints
|
|
|
|
|
char* name = 0;
|
|
|
|
|
QString s;
|
|
|
|
|
if ( XFetchName( qt_xdisplay(), (Window) w, &name ) && name ) {
|
|
|
|
|
s = QString::fromLatin1( name );
|
|
|
|
|
XFree( name );
|
|
|
|
|
}
|
1999-11-07 02:07:03 +00:00
|
|
|
|
if ( s == "THE DESKTOP" ) {
|
|
|
|
|
XLowerWindow( qt_xdisplay(), w );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
Client * c = new NoBorderClient( ws, w);
|
1999-11-07 02:07:03 +00:00
|
|
|
|
c->setSticky( TRUE );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
ws->setDesktopClient( c );
|
|
|
|
|
return c;
|
|
|
|
|
}
|
1999-10-09 09:55:16 +00:00
|
|
|
|
if ( s == "Kicker" ) {
|
|
|
|
|
Client * c = new NoBorderClient( ws, w);
|
1999-11-07 01:43:06 +00:00
|
|
|
|
c->setSticky( TRUE );
|
1999-10-09 09:55:16 +00:00
|
|
|
|
return c;
|
|
|
|
|
}
|
1999-11-12 03:11:19 +00:00
|
|
|
|
|
|
|
|
|
if ( Shape::hasShape( w ) ){
|
|
|
|
|
return new NoBorderClient( ws, w );
|
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
1999-11-11 01:27:37 +00:00
|
|
|
|
KConfig *config = KGlobal::config();
|
|
|
|
|
config->setGroup("style");
|
|
|
|
|
// well, it will be soon ;-)
|
|
|
|
|
QString tmpStr = config->readEntry("Plugin", "standard");
|
1999-11-12 03:11:19 +00:00
|
|
|
|
if(tmpStr == "system")
|
|
|
|
|
return new SystemClient( ws, w );
|
1999-11-11 01:27:37 +00:00
|
|
|
|
else if(tmpStr == "be")
|
1999-11-12 03:11:19 +00:00
|
|
|
|
return new BeClient( ws, w );
|
|
|
|
|
else
|
|
|
|
|
return new StdClient( ws, w );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Workspace::Workspace()
|
|
|
|
|
{
|
|
|
|
|
root = qt_xrootwin(); // no MDI for now
|
|
|
|
|
|
|
|
|
|
(void) QApplication::desktop(); // trigger creation of desktop widget
|
1999-09-27 16:02:44 +00:00
|
|
|
|
desktop_widget = new QWidget(0, "desktop_widget", Qt::WType_Desktop | Qt::WPaintUnclipped );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
|
|
|
|
// select windowmanager privileges
|
|
|
|
|
XSelectInput(qt_xdisplay(), root,
|
|
|
|
|
KeyPressMask |
|
|
|
|
|
PropertyChangeMask |
|
|
|
|
|
ColormapChangeMask |
|
|
|
|
|
SubstructureRedirectMask |
|
|
|
|
|
SubstructureNotifyMask
|
|
|
|
|
);
|
|
|
|
|
|
1999-11-12 03:11:19 +00:00
|
|
|
|
int dummy;
|
|
|
|
|
kwin_has_shape = XShapeQueryExtension(qt_xdisplay(), &kwin_shape_event, &dummy);
|
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
init();
|
|
|
|
|
control_grab = FALSE;
|
|
|
|
|
tab_grab = FALSE;
|
|
|
|
|
tab_box = new TabBox( this );
|
1999-11-13 01:51:22 +00:00
|
|
|
|
keys = 0;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
grabKey(XK_Tab, Mod1Mask);
|
|
|
|
|
grabKey(XK_Tab, Mod1Mask | ShiftMask);
|
|
|
|
|
grabKey(XK_Tab, ControlMask);
|
|
|
|
|
grabKey(XK_Tab, ControlMask | ShiftMask);
|
1999-11-13 01:51:22 +00:00
|
|
|
|
createKeybindings();
|
|
|
|
|
|
1999-11-07 08:46:36 +00:00
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
|
|
|
|
Workspace::Workspace( WId rootwin )
|
|
|
|
|
{
|
|
|
|
|
qDebug("create MDI workspace for %d", rootwin );
|
|
|
|
|
root = rootwin;
|
|
|
|
|
|
|
|
|
|
// select windowmanager privileges
|
|
|
|
|
XSelectInput(qt_xdisplay(), root,
|
|
|
|
|
KeyPressMask |
|
|
|
|
|
PropertyChangeMask |
|
|
|
|
|
ColormapChangeMask |
|
|
|
|
|
SubstructureRedirectMask |
|
|
|
|
|
SubstructureNotifyMask
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
control_grab = FALSE;
|
|
|
|
|
tab_grab = FALSE;
|
1999-11-13 01:51:22 +00:00
|
|
|
|
tab_box = 0;
|
|
|
|
|
keys = 0;
|
|
|
|
|
init();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Workspace::init()
|
|
|
|
|
{
|
|
|
|
|
tab_box = 0;
|
|
|
|
|
active_client = 0;
|
|
|
|
|
should_get_focus = 0;
|
|
|
|
|
desktop_client = 0;
|
1999-11-07 01:43:06 +00:00
|
|
|
|
current_desktop = 0;
|
|
|
|
|
number_of_desktops = 0;
|
|
|
|
|
setNumberOfDesktops( 4 ); // TODO options
|
|
|
|
|
setCurrentDesktop( 1 );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
|
|
|
|
unsigned int i, nwins;
|
|
|
|
|
Window dw1, dw2, *wins;
|
|
|
|
|
XWindowAttributes attr;
|
|
|
|
|
|
|
|
|
|
XGrabServer( qt_xdisplay() );
|
|
|
|
|
XQueryTree(qt_xdisplay(), root, &dw1, &dw2, &wins, &nwins);
|
|
|
|
|
for (i = 0; i < nwins; i++) {
|
|
|
|
|
XGetWindowAttributes(qt_xdisplay(), wins[i], &attr);
|
|
|
|
|
if (attr.override_redirect )
|
|
|
|
|
continue;
|
|
|
|
|
if (attr.map_state != IsUnmapped) {
|
1999-11-11 01:22:41 +00:00
|
|
|
|
if ( addDockwin( wins[i] ) )
|
|
|
|
|
continue;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
Client* c = clientFactory( this, wins[i] );
|
1999-11-07 02:07:03 +00:00
|
|
|
|
if ( c != desktop_client ) {
|
|
|
|
|
clients.append( c );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
stacking_order.append( c );
|
1999-11-07 02:07:03 +00:00
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
focus_chain.append( c );
|
|
|
|
|
c->manage( TRUE );
|
|
|
|
|
if ( c == desktop_client )
|
|
|
|
|
setDesktopClient( c );
|
|
|
|
|
if ( root != qt_xrootwin() ) {
|
|
|
|
|
// TODO may use QWidget:.create
|
|
|
|
|
qDebug(" create a mdi client");
|
|
|
|
|
XReparentWindow( qt_xdisplay(), c->winId(), root, 0, 0 );
|
|
|
|
|
c->move(0,0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
XFree((void *) wins);
|
|
|
|
|
XUngrabServer( qt_xdisplay() );
|
|
|
|
|
popup = 0;
|
1999-11-07 01:43:06 +00:00
|
|
|
|
propagateClients();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Workspace::~Workspace()
|
|
|
|
|
{
|
1999-11-07 02:07:03 +00:00
|
|
|
|
if ( desktop_client ) {
|
|
|
|
|
WId win = desktop_client->window();
|
|
|
|
|
delete desktop_client;
|
|
|
|
|
XMapWindow( qt_xdisplay(), win );
|
|
|
|
|
XLowerWindow( qt_xdisplay(), win );
|
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
1999-11-02 15:17:15 +00:00
|
|
|
|
WId win = (*it)->window();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
delete (*it);
|
1999-11-02 15:17:15 +00:00
|
|
|
|
XMapWindow( qt_xdisplay(), win );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
delete tab_box;
|
|
|
|
|
delete popup;
|
1999-11-13 01:51:22 +00:00
|
|
|
|
delete keys;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Handles workspace specific XEvents
|
|
|
|
|
*/
|
|
|
|
|
bool Workspace::workspaceEvent( XEvent * e )
|
|
|
|
|
{
|
|
|
|
|
Client * c = findClient( e->xany.window );
|
|
|
|
|
if ( c )
|
|
|
|
|
return c->windowEvent( e );
|
|
|
|
|
|
|
|
|
|
switch (e->type) {
|
|
|
|
|
case ButtonPress:
|
|
|
|
|
case ButtonRelease:
|
|
|
|
|
break;
|
|
|
|
|
case UnmapNotify:
|
|
|
|
|
// this is special due to
|
|
|
|
|
// SubstructureRedirectMask. e->xany.window is the window the
|
|
|
|
|
// event is reported to. Take care not to confuse Qt.
|
|
|
|
|
c = findClient( e->xunmap.window );
|
|
|
|
|
|
|
|
|
|
if ( c )
|
|
|
|
|
return c->windowEvent( e );
|
1999-11-11 01:22:41 +00:00
|
|
|
|
|
|
|
|
|
// check for dock windows
|
|
|
|
|
if ( removeDockwin( e->xunmap.window ) )
|
|
|
|
|
return TRUE;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
|
|
|
|
if ( e->xunmap.event != e->xunmap.window ) // hide wm typical event from Qt
|
|
|
|
|
return TRUE;
|
|
|
|
|
case ReparentNotify:
|
1999-11-02 00:32:31 +00:00
|
|
|
|
c = findClient( e->xreparent.window );
|
|
|
|
|
if ( c )
|
|
|
|
|
(void) c->windowEvent( e );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
//do not confuse Qt with these events. After all, _we_ are the
|
|
|
|
|
//window manager who does the reparenting.
|
1999-11-02 00:32:31 +00:00
|
|
|
|
return TRUE;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
case DestroyNotify:
|
1999-11-11 01:22:41 +00:00
|
|
|
|
if ( removeDockwin( e->xdestroywindow.window ) )
|
|
|
|
|
return TRUE;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
return destroyClient( findClient( e->xdestroywindow.window ) );
|
|
|
|
|
case MapRequest:
|
|
|
|
|
if ( e->xmaprequest.parent == root ) {
|
|
|
|
|
c = findClient( e->xmaprequest.window );
|
|
|
|
|
if ( !c ) {
|
1999-11-11 01:22:41 +00:00
|
|
|
|
if ( addDockwin( e->xmaprequest.window ) )
|
|
|
|
|
return TRUE;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
c = clientFactory( this, e->xmaprequest.window );
|
|
|
|
|
if ( root != qt_xrootwin() ) {
|
|
|
|
|
// TODO may use QWidget:.create
|
|
|
|
|
XReparentWindow( qt_xdisplay(), c->winId(), root, 0, 0 );
|
|
|
|
|
}
|
1999-11-07 02:07:03 +00:00
|
|
|
|
if ( c != desktop_client ) {
|
|
|
|
|
clients.append( c );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
stacking_order.append( c );
|
1999-11-07 02:07:03 +00:00
|
|
|
|
}
|
1999-11-07 01:43:06 +00:00
|
|
|
|
propagateClients();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
bool result = c->windowEvent( e );
|
|
|
|
|
if ( c == desktop_client )
|
|
|
|
|
setDesktopClient( c );
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case ConfigureRequest:
|
1999-11-12 03:11:19 +00:00
|
|
|
|
c = findClient( e->xconfigurerequest.window );
|
|
|
|
|
if ( c )
|
|
|
|
|
return c->windowEvent( e );
|
|
|
|
|
else if ( e->xconfigurerequest.parent == root ) {
|
1999-08-19 23:26:42 +00:00
|
|
|
|
XWindowChanges wc;
|
|
|
|
|
unsigned int value_mask = 0;
|
|
|
|
|
wc.border_width = 0;
|
|
|
|
|
wc.x = e->xconfigurerequest.x;
|
|
|
|
|
wc.y = e->xconfigurerequest.y;
|
|
|
|
|
wc.width = e->xconfigurerequest.width;
|
|
|
|
|
wc.height = e->xconfigurerequest.height;
|
|
|
|
|
wc.sibling = None;
|
|
|
|
|
wc.stack_mode = Above;
|
|
|
|
|
value_mask = e->xconfigurerequest.value_mask | CWBorderWidth;
|
|
|
|
|
XConfigureWindow( qt_xdisplay(), e->xconfigurerequest.window, value_mask, & wc );
|
1999-11-12 03:11:19 +00:00
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case KeyPress:
|
|
|
|
|
return keyPress(e->xkey);
|
|
|
|
|
break;
|
|
|
|
|
case KeyRelease:
|
|
|
|
|
return keyRelease(e->xkey);
|
|
|
|
|
break;
|
|
|
|
|
case FocusIn:
|
|
|
|
|
break;
|
|
|
|
|
case FocusOut:
|
|
|
|
|
break;
|
1999-11-07 01:43:06 +00:00
|
|
|
|
case ClientMessage:
|
|
|
|
|
return clientMessage(e->xclient);
|
|
|
|
|
break;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
default:
|
1999-11-12 03:11:19 +00:00
|
|
|
|
if ( e->type == Shape::shapeEvent() ) {
|
|
|
|
|
c = findClient( ((XShapeEvent *)e)->window );
|
|
|
|
|
if ( c )
|
|
|
|
|
c->updateShape();
|
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-07 08:46:36 +00:00
|
|
|
|
bool Workspace::hasClient(Client* c)
|
|
|
|
|
{
|
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
|
|
|
|
if ( (*it) == c )
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
/*!
|
|
|
|
|
Finds the client that embedds the window \a w
|
|
|
|
|
*/
|
|
|
|
|
Client* Workspace::findClient( WId w ) const
|
|
|
|
|
{
|
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
|
|
|
|
if ( (*it)->window() == w )
|
|
|
|
|
return *it;
|
|
|
|
|
}
|
1999-11-07 02:07:03 +00:00
|
|
|
|
if ( desktop_client && w == desktop_client->window() )
|
|
|
|
|
return desktop_client;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Returns the workspace's geometry
|
1999-11-13 01:51:22 +00:00
|
|
|
|
|
|
|
|
|
\sa clientArea()
|
1999-08-19 23:26:42 +00:00
|
|
|
|
*/
|
|
|
|
|
QRect Workspace::geometry() const
|
|
|
|
|
{
|
|
|
|
|
if ( root == qt_xrootwin() )
|
|
|
|
|
return QRect( QPoint(0, 0), QApplication::desktop()->size() );
|
|
|
|
|
else {
|
|
|
|
|
// todo caching, keep track of configure notify etc.
|
|
|
|
|
QRect r;
|
|
|
|
|
XWindowAttributes attr;
|
|
|
|
|
if (XGetWindowAttributes(qt_xdisplay(), root, &attr)){
|
|
|
|
|
r.setRect(0, 0, attr.width, attr.height );
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-13 01:51:22 +00:00
|
|
|
|
/*!
|
|
|
|
|
Returns the workspace's client area.
|
|
|
|
|
|
|
|
|
|
This is the area within the geometry() where clients can be placed,
|
|
|
|
|
i.e. the full geometry minus space for desktop panels, taskbars,
|
|
|
|
|
etc.
|
|
|
|
|
|
|
|
|
|
Placement algorithms should refer to clientArea.
|
|
|
|
|
|
|
|
|
|
\sa geometry()
|
|
|
|
|
*/
|
|
|
|
|
QRect Workspace::clientArea() const
|
|
|
|
|
{
|
|
|
|
|
return geometry(); // for now
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Destroys the client \a c
|
|
|
|
|
*/
|
|
|
|
|
bool Workspace::destroyClient( Client* c)
|
|
|
|
|
{
|
|
|
|
|
if ( !c )
|
|
|
|
|
return FALSE;
|
|
|
|
|
clients.remove( c );
|
|
|
|
|
stacking_order.remove( c );
|
|
|
|
|
focus_chain.remove( c );
|
|
|
|
|
c->invalidateWindow();
|
|
|
|
|
delete c;
|
|
|
|
|
clientHidden( c );
|
1999-11-07 20:29:26 +00:00
|
|
|
|
if ( c == desktop_client )
|
|
|
|
|
desktop_client = 0;
|
1999-11-07 01:43:06 +00:00
|
|
|
|
propagateClients();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Auxiliary function to release a passive keyboard grab
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::freeKeyboard(bool pass){
|
|
|
|
|
if (!pass)
|
|
|
|
|
XAllowEvents(qt_xdisplay(), AsyncKeyboard, CurrentTime);
|
|
|
|
|
else
|
|
|
|
|
XAllowEvents(qt_xdisplay(), ReplayKeyboard, CurrentTime);
|
|
|
|
|
QApplication::syncX();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Handles alt-tab / control-tab
|
|
|
|
|
*/
|
|
|
|
|
bool Workspace::keyPress(XKeyEvent key)
|
|
|
|
|
{
|
|
|
|
|
if ( root != qt_xrootwin() )
|
|
|
|
|
return FALSE;
|
|
|
|
|
int kc = XKeycodeToKeysym(qt_xdisplay(), key.keycode, 0);
|
|
|
|
|
int km = key.state & (ControlMask | Mod1Mask | ShiftMask);
|
|
|
|
|
|
|
|
|
|
const bool options_alt_tab_mode_is_CDE_style = FALSE; // TODO
|
|
|
|
|
|
|
|
|
|
if (!control_grab){
|
|
|
|
|
|
|
|
|
|
if( (kc == XK_Tab) &&
|
|
|
|
|
( km == (Mod1Mask | ShiftMask)
|
|
|
|
|
|| km == (Mod1Mask)
|
|
|
|
|
)){
|
|
|
|
|
if (!tab_grab){
|
|
|
|
|
if (options_alt_tab_mode_is_CDE_style ){
|
|
|
|
|
// CDE style raise / lower
|
|
|
|
|
Client* c = topClientOnDesktop();
|
|
|
|
|
Client* nc = c;
|
|
|
|
|
if (km & ShiftMask){
|
|
|
|
|
do {
|
|
|
|
|
nc = previousStaticClient(nc);
|
|
|
|
|
} while (nc && nc != c &&
|
|
|
|
|
(!nc->isOnDesktop(currentDesktop()) ||
|
|
|
|
|
nc->isIconified()));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
do {
|
|
|
|
|
nc = nextStaticClient(nc);
|
|
|
|
|
} while (nc && nc != c &&
|
|
|
|
|
(!nc->isOnDesktop(currentDesktop()) ||
|
|
|
|
|
nc->isIconified()));
|
|
|
|
|
if (c && c != nc)
|
|
|
|
|
;//TODO lowerClient(c);
|
|
|
|
|
if (nc)
|
|
|
|
|
activateClient( nc );
|
|
|
|
|
freeKeyboard(FALSE);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
XGrabKeyboard(qt_xdisplay(),
|
|
|
|
|
root, FALSE,
|
|
|
|
|
GrabModeAsync, GrabModeAsync,
|
|
|
|
|
CurrentTime);
|
|
|
|
|
tab_grab = TRUE;
|
|
|
|
|
tab_box->setMode( TabBox::WindowsMode );
|
|
|
|
|
tab_box->reset();
|
|
|
|
|
}
|
|
|
|
|
tab_box->nextPrev( (km & ShiftMask) == 0 );
|
|
|
|
|
tab_box->show();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!tab_grab){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( (kc == XK_Tab) &&
|
|
|
|
|
( km == (ControlMask | ShiftMask)
|
|
|
|
|
|| km == (ControlMask)
|
|
|
|
|
)){
|
|
|
|
|
//TODO if (!options.ControlTab){
|
|
|
|
|
// freeKeyboard(TRUE);
|
|
|
|
|
// return TRUE;
|
|
|
|
|
// }
|
|
|
|
|
if (!control_grab){
|
|
|
|
|
XGrabKeyboard(qt_xdisplay(),
|
|
|
|
|
root, FALSE,
|
|
|
|
|
GrabModeAsync, GrabModeAsync,
|
|
|
|
|
CurrentTime);
|
|
|
|
|
control_grab = TRUE;
|
|
|
|
|
tab_box->setMode( TabBox::DesktopMode );
|
|
|
|
|
tab_box->reset();
|
|
|
|
|
}
|
|
|
|
|
tab_box->nextPrev( (km & ShiftMask) == 0 );
|
|
|
|
|
tab_box->show();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (control_grab || tab_grab){
|
|
|
|
|
if (kc == XK_Escape){
|
|
|
|
|
XUngrabKeyboard(qt_xdisplay(), CurrentTime);
|
|
|
|
|
tab_box->hide();
|
|
|
|
|
tab_grab = FALSE;
|
|
|
|
|
control_grab = FALSE;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
freeKeyboard(FALSE);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Handles alt-tab / control-tab
|
|
|
|
|
*/
|
|
|
|
|
bool Workspace::keyRelease(XKeyEvent key)
|
|
|
|
|
{
|
|
|
|
|
if ( root != qt_xrootwin() )
|
|
|
|
|
return FALSE;
|
|
|
|
|
int i;
|
|
|
|
|
if (tab_grab){
|
|
|
|
|
XModifierKeymap* xmk = XGetModifierMapping(qt_xdisplay());
|
|
|
|
|
for (i=0; i<xmk->max_keypermod; i++)
|
|
|
|
|
if (xmk->modifiermap[xmk->max_keypermod * Mod1MapIndex + i]
|
|
|
|
|
== key.keycode){
|
|
|
|
|
XUngrabKeyboard(qt_xdisplay(), CurrentTime);
|
|
|
|
|
tab_box->hide();
|
|
|
|
|
tab_grab = false;
|
|
|
|
|
if ( tab_box->currentClient() ){
|
|
|
|
|
|
|
|
|
|
activateClient( tab_box->currentClient() );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (control_grab){
|
|
|
|
|
XModifierKeymap* xmk = XGetModifierMapping(qt_xdisplay());
|
|
|
|
|
for (i=0; i<xmk->max_keypermod; i++)
|
|
|
|
|
if (xmk->modifiermap[xmk->max_keypermod * ControlMapIndex + i]
|
|
|
|
|
== key.keycode){
|
|
|
|
|
XUngrabKeyboard(qt_xdisplay(), CurrentTime);
|
|
|
|
|
tab_box->hide();
|
|
|
|
|
control_grab = False;
|
|
|
|
|
if ( tab_box->currentDesktop() != -1 )
|
1999-11-07 01:43:06 +00:00
|
|
|
|
setCurrentDesktop( tab_box->currentDesktop() );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
auxiliary functions to travers all clients according the focus
|
|
|
|
|
order. Useful for kwm<EFBFBD>s Alt-tab feature.
|
|
|
|
|
*/
|
|
|
|
|
Client* Workspace::nextClient( Client* c ) const
|
|
|
|
|
{
|
|
|
|
|
if ( focus_chain.isEmpty() )
|
|
|
|
|
return 0;
|
|
|
|
|
ClientList::ConstIterator it = focus_chain.find( c );
|
|
|
|
|
if ( it == focus_chain.end() )
|
|
|
|
|
return focus_chain.last();
|
|
|
|
|
if ( it == focus_chain.begin() )
|
|
|
|
|
return focus_chain.last();
|
|
|
|
|
--it;
|
|
|
|
|
return *it;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
auxiliary functions to travers all clients according the focus
|
|
|
|
|
order. Useful for kwm<EFBFBD>s Alt-tab feature.
|
|
|
|
|
*/
|
|
|
|
|
Client* Workspace::previousClient( Client* c ) const
|
|
|
|
|
{
|
|
|
|
|
if ( focus_chain.isEmpty() )
|
|
|
|
|
return 0;
|
|
|
|
|
ClientList::ConstIterator it = focus_chain.find( c );
|
|
|
|
|
if ( it == focus_chain.end() )
|
|
|
|
|
return focus_chain.first();
|
|
|
|
|
++it;
|
|
|
|
|
if ( it == focus_chain.end() )
|
|
|
|
|
return focus_chain.first();
|
|
|
|
|
return *it;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
auxiliary functions to travers all clients according the static
|
|
|
|
|
order. Useful for the CDE-style Alt-tab feature.
|
|
|
|
|
*/
|
|
|
|
|
Client* Workspace::nextStaticClient( Client* c ) const
|
|
|
|
|
{
|
|
|
|
|
if ( clients.isEmpty() )
|
|
|
|
|
return 0;
|
|
|
|
|
ClientList::ConstIterator it = clients.find( c );
|
|
|
|
|
if ( it == clients.end() )
|
|
|
|
|
return clients.first();
|
|
|
|
|
++it;
|
|
|
|
|
if ( it == clients.end() )
|
|
|
|
|
return clients.first();
|
|
|
|
|
return *it;
|
|
|
|
|
}
|
|
|
|
|
/*!
|
|
|
|
|
auxiliary functions to travers all clients according the static
|
|
|
|
|
order. Useful for the CDE-style Alt-tab feature.
|
|
|
|
|
*/
|
|
|
|
|
Client* Workspace::previousStaticClient( Client* c ) const
|
|
|
|
|
{
|
|
|
|
|
if ( clients.isEmpty() )
|
|
|
|
|
return 0;
|
|
|
|
|
ClientList::ConstIterator it = clients.find( c );
|
|
|
|
|
if ( it == clients.end() )
|
|
|
|
|
return clients.last();
|
|
|
|
|
if ( it == clients.begin() )
|
|
|
|
|
return clients.last();
|
|
|
|
|
--it;
|
|
|
|
|
return *it;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Returns topmost visible client within the specified layer range on
|
|
|
|
|
the current desktop, or 0 if no clients are visible. \a fromLayer has to
|
|
|
|
|
be smaller than \a toLayer.
|
|
|
|
|
*/
|
|
|
|
|
Client* Workspace::topClientOnDesktop( int fromLayer, int toLayer) const
|
|
|
|
|
{
|
|
|
|
|
fromLayer = toLayer = 0;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Grabs the keysymbol \a keysym with the given modifiers \a mod
|
|
|
|
|
plus all possibile combinations of Lock and NumLock
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::grabKey(KeySym keysym, unsigned int mod){
|
|
|
|
|
static int NumLockMask = 0;
|
|
|
|
|
if (!keysym||!XKeysymToKeycode(qt_xdisplay(), keysym)) return;
|
|
|
|
|
if (!NumLockMask){
|
|
|
|
|
XModifierKeymap* xmk = XGetModifierMapping(qt_xdisplay());
|
|
|
|
|
int i;
|
|
|
|
|
for (i=0; i<8; i++){
|
|
|
|
|
if (xmk->modifiermap[xmk->max_keypermod * i] ==
|
|
|
|
|
XKeysymToKeycode(qt_xdisplay(), XK_Num_Lock))
|
|
|
|
|
NumLockMask = (1<<i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
XGrabKey(qt_xdisplay(),
|
|
|
|
|
XKeysymToKeycode(qt_xdisplay(), keysym), mod,
|
|
|
|
|
qt_xrootwin(), TRUE,
|
|
|
|
|
GrabModeSync, GrabModeSync);
|
|
|
|
|
XGrabKey(qt_xdisplay(),
|
|
|
|
|
XKeysymToKeycode(qt_xdisplay(), keysym), mod | LockMask,
|
|
|
|
|
qt_xrootwin(), TRUE,
|
|
|
|
|
GrabModeSync, GrabModeSync);
|
|
|
|
|
XGrabKey(qt_xdisplay(),
|
|
|
|
|
XKeysymToKeycode(qt_xdisplay(), keysym), mod | NumLockMask,
|
|
|
|
|
qt_xrootwin(), TRUE,
|
|
|
|
|
GrabModeSync, GrabModeSync);
|
|
|
|
|
XGrabKey(qt_xdisplay(),
|
|
|
|
|
XKeysymToKeycode(qt_xdisplay(), keysym), mod | LockMask | NumLockMask,
|
|
|
|
|
qt_xrootwin(), TRUE,
|
|
|
|
|
GrabModeSync, GrabModeSync);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Informs the workspace about the active client, i.e. the client that
|
|
|
|
|
has the focus (or None if no client has the focus). This functions
|
|
|
|
|
is called by the client itself that gets focus. It has no other
|
1999-11-07 01:43:06 +00:00
|
|
|
|
effect than fixing the focus chain and the return value of
|
|
|
|
|
activeClient(). And of course, to propagate the active client to the
|
|
|
|
|
world.
|
1999-08-19 23:26:42 +00:00
|
|
|
|
*/
|
|
|
|
|
void Workspace::setActiveClient( Client* c )
|
|
|
|
|
{
|
|
|
|
|
if ( active_client == c )
|
|
|
|
|
return;
|
|
|
|
|
if ( active_client )
|
|
|
|
|
active_client->setActive( FALSE );
|
|
|
|
|
active_client = c;
|
|
|
|
|
if ( active_client ) {
|
|
|
|
|
focus_chain.remove( c );
|
|
|
|
|
focus_chain.append( c );
|
|
|
|
|
}
|
1999-11-07 01:43:06 +00:00
|
|
|
|
WId w = active_client? active_client->window() : 0;
|
|
|
|
|
XChangeProperty(qt_xdisplay(), qt_xrootwin(),
|
|
|
|
|
atoms->net_active_window, XA_WINDOW, 32,
|
|
|
|
|
PropModeReplace, (unsigned char *)&w, 1);
|
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Tries to activate the client \a c. This function performs what you
|
|
|
|
|
expect when clicking the respective entry in a taskbar: showing and
|
|
|
|
|
raising the client (this may imply switching to the another virtual
|
|
|
|
|
desktop) and putting the focus onto it. Once X really gave focus to
|
|
|
|
|
the client window as requested, the client itself will call
|
|
|
|
|
setActiveClient() and the operation is complete. This may not happen
|
|
|
|
|
with certain focus policies, though.
|
|
|
|
|
|
|
|
|
|
\sa setActiveClient(), requestFocus()
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::activateClient( Client* c)
|
|
|
|
|
{
|
|
|
|
|
if (!c->isOnDesktop(currentDesktop()) ) {
|
|
|
|
|
// TODO switch desktop
|
|
|
|
|
}
|
|
|
|
|
raiseClient( c );
|
|
|
|
|
c->show();
|
|
|
|
|
if ( options->focusPolicyIsReasonable() )
|
|
|
|
|
requestFocus( c );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Tries to activate the client by asking X for the input focus. This
|
|
|
|
|
function does not perform any show, raise or desktop switching. See
|
|
|
|
|
Workspace::activateClient() instead.
|
|
|
|
|
|
|
|
|
|
\sa Workspace::activateClient()
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::requestFocus( Client* c)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//TODO will be different for non-root clients. (subclassing?)
|
|
|
|
|
if ( !c ) {
|
|
|
|
|
focusToNull();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( c->isVisible() && !c->isShade() ) {
|
|
|
|
|
c->takeFocus();
|
|
|
|
|
should_get_focus = c;
|
|
|
|
|
} else if ( c->isShade() ) {
|
|
|
|
|
// client cannot accept focus, but at least the window should be active (window menu, et. al. )
|
|
|
|
|
focusToNull();
|
|
|
|
|
c->setActive( TRUE );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Informs the workspace that the client \a c has been hidden. If it
|
|
|
|
|
was the active client, the workspace activates another one.
|
|
|
|
|
|
|
|
|
|
\a c may already be destroyed
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::clientHidden( Client* c )
|
|
|
|
|
{
|
|
|
|
|
if ( c == active_client || ( !active_client && c == should_get_focus ) ) {
|
|
|
|
|
active_client = 0;
|
|
|
|
|
should_get_focus = 0;
|
|
|
|
|
if ( clients.contains( c ) ) {
|
|
|
|
|
focus_chain.remove( c );
|
|
|
|
|
focus_chain.prepend( c );
|
|
|
|
|
}
|
|
|
|
|
if ( options->focusPolicyIsReasonable() ) {
|
|
|
|
|
for ( ClientList::ConstIterator it = focus_chain.fromLast(); it != focus_chain.begin(); --it) {
|
|
|
|
|
if ( (*it)->isVisible() ) {
|
|
|
|
|
requestFocus( *it );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Workspace::showPopup( const QPoint& pos, Client* c)
|
|
|
|
|
{
|
1999-09-27 16:02:44 +00:00
|
|
|
|
// experimental!!!
|
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
if ( !popup ) {
|
|
|
|
|
popup = new QPopupMenu;
|
|
|
|
|
|
1999-09-27 16:02:44 +00:00
|
|
|
|
// I wish I could use qt-2.1 features here..... grmblll
|
1999-08-19 23:26:42 +00:00
|
|
|
|
QPopupMenu* deco = new QPopupMenu( popup );
|
|
|
|
|
deco->insertItem("KDE Classic", 100 );
|
|
|
|
|
deco->insertItem("Be-like style", 101 );
|
1999-10-11 02:00:06 +00:00
|
|
|
|
deco->insertItem("System style", 102 );
|
1999-09-27 16:02:44 +00:00
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
popup->insertItem("Decoration", deco );
|
|
|
|
|
}
|
|
|
|
|
popup_client = c;
|
|
|
|
|
// TODO customize popup for the client
|
|
|
|
|
int ret = popup->exec( pos );
|
1999-11-11 01:27:37 +00:00
|
|
|
|
KConfig *config = KGlobal::config();
|
|
|
|
|
config->setGroup("style");
|
1999-08-19 23:26:42 +00:00
|
|
|
|
switch( ret ) {
|
|
|
|
|
case 100:
|
1999-11-11 01:27:37 +00:00
|
|
|
|
config->writeEntry("Plugin", "standard");
|
1999-08-19 23:26:42 +00:00
|
|
|
|
setDecoration( 0 );
|
|
|
|
|
break;
|
|
|
|
|
case 101:
|
1999-11-11 01:27:37 +00:00
|
|
|
|
config->writeEntry("Plugin", "be");
|
1999-08-19 23:26:42 +00:00
|
|
|
|
setDecoration( 1 );
|
1999-09-27 16:02:44 +00:00
|
|
|
|
break;
|
1999-10-11 02:00:06 +00:00
|
|
|
|
case 102:
|
1999-11-11 01:27:37 +00:00
|
|
|
|
config->writeEntry("Plugin", "system");
|
1999-10-11 02:00:06 +00:00
|
|
|
|
setDecoration( 2 );
|
|
|
|
|
break;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
1999-11-11 01:29:33 +00:00
|
|
|
|
config->sync();
|
1999-09-27 16:02:44 +00:00
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
popup_client = 0;
|
|
|
|
|
ret = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Places the client \a c according to the workspace's layout policy
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::doPlacement( Client* c )
|
|
|
|
|
{
|
|
|
|
|
randomPlacement( c );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Place the client \a c according to a simply "random" placement algorithm.
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::randomPlacement(Client* c){
|
|
|
|
|
const int step = 24;
|
|
|
|
|
static int px = step;
|
|
|
|
|
static int py = 2 * step;
|
|
|
|
|
int tx,ty;
|
|
|
|
|
|
1999-11-13 01:51:22 +00:00
|
|
|
|
QRect maxRect = clientArea();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
|
|
|
|
if (px < maxRect.x())
|
|
|
|
|
px = maxRect.x();
|
|
|
|
|
if (py < maxRect.y())
|
|
|
|
|
py = maxRect.y();
|
|
|
|
|
|
|
|
|
|
px += step;
|
|
|
|
|
py += 2*step;
|
|
|
|
|
|
|
|
|
|
if (px > maxRect.width()/2)
|
|
|
|
|
px = maxRect.x() + step;
|
|
|
|
|
if (py > maxRect.height()/2)
|
|
|
|
|
py = maxRect.y() + step;
|
|
|
|
|
tx = px;
|
|
|
|
|
ty = py;
|
|
|
|
|
if (tx + c->width() > maxRect.right()){
|
|
|
|
|
tx = maxRect.right() - c->width();
|
|
|
|
|
if (tx < 0)
|
|
|
|
|
tx = 0;
|
|
|
|
|
px = maxRect.x();
|
|
|
|
|
}
|
|
|
|
|
if (ty + c->height() > maxRect.bottom()){
|
|
|
|
|
ty = maxRect.bottom() - c->height();
|
|
|
|
|
if (ty < 0)
|
|
|
|
|
ty = 0;
|
|
|
|
|
py = maxRect.y();
|
|
|
|
|
}
|
|
|
|
|
c->move( tx, ty );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Raises the client \a c taking layers, transient windows and window
|
|
|
|
|
groups into account.
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::raiseClient( Client* c )
|
|
|
|
|
{
|
|
|
|
|
if ( !c )
|
|
|
|
|
return;
|
|
|
|
|
if ( c == desktop_client )
|
|
|
|
|
return; // deny
|
|
|
|
|
|
|
|
|
|
Window* new_stack = new Window[ stacking_order.count()+1];
|
|
|
|
|
|
|
|
|
|
stacking_order.remove( c );
|
|
|
|
|
stacking_order.append( c );
|
|
|
|
|
|
|
|
|
|
ClientList saveset;
|
|
|
|
|
saveset.append( c );
|
|
|
|
|
raiseTransientsOf(saveset, c );
|
|
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
|
|
|
|
|
new_stack[i++] = (*it)->winId();
|
|
|
|
|
}
|
|
|
|
|
XRaiseWindow(qt_xdisplay(), new_stack[0]);
|
|
|
|
|
XRestackWindows(qt_xdisplay(), new_stack, i);
|
|
|
|
|
delete [] new_stack;
|
|
|
|
|
|
1999-11-12 03:58:34 +00:00
|
|
|
|
if ( c->transientFor() ) {
|
|
|
|
|
Client* t = findClient( c->transientFor() );
|
|
|
|
|
Client* t2;
|
|
|
|
|
while (t && t->transientFor() ) {
|
|
|
|
|
t2 = findClient( t->transientFor() );
|
|
|
|
|
if ( t2 == c )
|
|
|
|
|
goto end;
|
1999-11-13 02:02:10 +00:00
|
|
|
|
if ( t2 == t )
|
|
|
|
|
break;
|
1999-11-12 03:58:34 +00:00
|
|
|
|
t = t2;
|
|
|
|
|
}
|
|
|
|
|
raiseClient( t );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
end:
|
1999-11-07 01:43:06 +00:00
|
|
|
|
propagateClients( TRUE );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Private auxiliary function used in raiseClient()
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::raiseTransientsOf( ClientList& safeset, Client* c )
|
|
|
|
|
{
|
|
|
|
|
ClientList local = stacking_order;
|
|
|
|
|
for ( ClientList::ConstIterator it = local.begin(); it != local.end(); ++it) {
|
|
|
|
|
if ( (*it)->transientFor() == c->window() && !safeset.contains( *it ) ) {
|
|
|
|
|
safeset.append( *it );
|
|
|
|
|
stacking_order.remove( *it );
|
|
|
|
|
stacking_order.append( *it );
|
|
|
|
|
raiseTransientsOf( safeset, *it );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Puts the focus on a dummy winodw
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::focusToNull(){
|
|
|
|
|
static Window w = 0;
|
|
|
|
|
int mask;
|
|
|
|
|
XSetWindowAttributes attr;
|
|
|
|
|
if (w == 0) {
|
|
|
|
|
mask = CWOverrideRedirect;
|
|
|
|
|
attr.override_redirect = 1;
|
|
|
|
|
w = XCreateWindow(qt_xdisplay(), qt_xrootwin(), 0, 0, 1, 1, 0, CopyFromParent,
|
|
|
|
|
InputOnly, CopyFromParent, mask, &attr);
|
|
|
|
|
XMapWindow(qt_xdisplay(), w);
|
|
|
|
|
}
|
|
|
|
|
XSetInputFocus(qt_xdisplay(), w, RevertToPointerRoot, CurrentTime );
|
|
|
|
|
//colormapFocus(0); TODO
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Workspace::setDesktopClient( Client* c)
|
|
|
|
|
{
|
|
|
|
|
desktop_client = c;
|
|
|
|
|
if ( desktop_client ) {
|
|
|
|
|
desktop_client->lower();
|
|
|
|
|
desktop_client->setGeometry( geometry() );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-07 01:43:06 +00:00
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Sets the current desktop to \a new_desktop
|
|
|
|
|
|
|
|
|
|
Shows/Hides windows according to the stacking order and finally
|
|
|
|
|
propages the new desktop to the world
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::setCurrentDesktop( int new_desktop ){
|
|
|
|
|
if (new_desktop == current_desktop || new_desktop < 1 || new_desktop > number_of_desktops )
|
1999-08-19 23:26:42 +00:00
|
|
|
|
return;
|
|
|
|
|
|
1999-09-27 16:02:44 +00:00
|
|
|
|
/*
|
1999-08-19 23:26:42 +00:00
|
|
|
|
optimized Desktop switching: unmapping done from back to front
|
|
|
|
|
mapping done from front to back => less exposure events
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
|
|
|
|
|
if ( (*it)->isVisible() && !(*it)->isOnDesktop( new_desktop ) ) {
|
|
|
|
|
(*it)->hide();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it) {
|
|
|
|
|
if ( (*it)->isOnDesktop( new_desktop ) ) {
|
|
|
|
|
(*it)->show();
|
|
|
|
|
//XMapWindow( qt_xdisplay(), (*it)->winId() );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
current_desktop = new_desktop;
|
1999-11-07 01:43:06 +00:00
|
|
|
|
|
|
|
|
|
XChangeProperty(qt_xdisplay(), qt_xrootwin(),
|
|
|
|
|
atoms->net_current_desktop, XA_CARDINAL, 32,
|
|
|
|
|
PropModeReplace, (unsigned char *)¤t_desktop, 1);
|
|
|
|
|
KWM::switchToDesktop( current_desktop ); // ### compatibility
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Workspace::makeFullScreen( Client* )
|
|
|
|
|
{
|
|
|
|
|
// not yet implemented
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// experimental
|
|
|
|
|
void Workspace::setDecoration( int deco )
|
|
|
|
|
{
|
|
|
|
|
if ( !popup_client )
|
|
|
|
|
return;
|
|
|
|
|
Client* c = popup_client;
|
|
|
|
|
WId w = c->window();
|
|
|
|
|
clients.remove( c );
|
|
|
|
|
stacking_order.remove( c );
|
|
|
|
|
focus_chain.remove( c );
|
|
|
|
|
bool mapped = c->isVisible();
|
|
|
|
|
c->hide();
|
|
|
|
|
c->releaseWindow();
|
|
|
|
|
switch ( deco ) {
|
|
|
|
|
case 1:
|
|
|
|
|
c = new BeClient( this, w);
|
1999-10-11 02:00:06 +00:00
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
c = new SystemClient(this, w);
|
|
|
|
|
break;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
default:
|
|
|
|
|
c = new StdClient( this, w );
|
|
|
|
|
}
|
|
|
|
|
clients.append( c );
|
|
|
|
|
stacking_order.append( c );
|
|
|
|
|
c->manage( mapped );
|
|
|
|
|
activateClient( c );
|
|
|
|
|
}
|
|
|
|
|
|
1999-09-27 16:02:44 +00:00
|
|
|
|
|
|
|
|
|
QWidget* Workspace::desktopWidget()
|
|
|
|
|
{
|
|
|
|
|
return desktop_widget;
|
|
|
|
|
}
|
1999-11-07 01:43:06 +00:00
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Sets the number of virtual desktops to \a n
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::setNumberOfDesktops( int n )
|
|
|
|
|
{
|
|
|
|
|
if ( n == number_of_desktops )
|
|
|
|
|
return;
|
|
|
|
|
number_of_desktops = n;
|
|
|
|
|
XChangeProperty(qt_xdisplay(), qt_xrootwin(),
|
|
|
|
|
atoms->net_number_of_desktops, XA_CARDINAL, 32,
|
|
|
|
|
PropModeReplace, (unsigned char *)&number_of_desktops, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Handles client messages sent to the workspace
|
|
|
|
|
*/
|
|
|
|
|
bool Workspace::clientMessage( XClientMessageEvent msg )
|
|
|
|
|
{
|
|
|
|
|
if ( msg.message_type == atoms->net_active_window ) {
|
|
|
|
|
Client * c = findClient( msg.data.l[0] );
|
|
|
|
|
if ( c ) {
|
|
|
|
|
activateClient( c );
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
} else if ( msg.message_type == atoms->net_current_desktop ) {
|
|
|
|
|
setCurrentDesktop( msg.data.l[0] );
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Propagates the managed clients to the world
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::propagateClients( bool onlyStacking )
|
|
|
|
|
{
|
|
|
|
|
WId* cl;
|
|
|
|
|
int i;
|
|
|
|
|
if ( !onlyStacking ) {
|
1999-11-11 01:22:41 +00:00
|
|
|
|
cl = new WId[ clients.count()];
|
1999-11-07 01:43:06 +00:00
|
|
|
|
i = 0;
|
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it ) {
|
|
|
|
|
cl[i++] = (*it)->window();
|
|
|
|
|
}
|
|
|
|
|
XChangeProperty(qt_xdisplay(), qt_xrootwin(),
|
|
|
|
|
atoms->net_client_list, XA_WINDOW, 32,
|
|
|
|
|
PropModeReplace, (unsigned char *)cl, clients.count());
|
|
|
|
|
delete [] cl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cl = new WId[ stacking_order.count()];
|
|
|
|
|
i = 0;
|
|
|
|
|
for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it) {
|
|
|
|
|
cl[i++] = (*it)->window();
|
|
|
|
|
}
|
|
|
|
|
XChangeProperty(qt_xdisplay(), qt_xrootwin(),
|
|
|
|
|
atoms->net_client_list_stacking, XA_WINDOW, 32,
|
|
|
|
|
PropModeReplace, (unsigned char *)cl, stacking_order.count());
|
|
|
|
|
delete [] cl;
|
|
|
|
|
}
|
1999-11-11 01:22:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Workspace::addDockwin( WId w )
|
|
|
|
|
{
|
|
|
|
|
if ( !KWM::isDockWindow( w ) )
|
|
|
|
|
return FALSE;
|
|
|
|
|
dockwins.append( w );
|
|
|
|
|
XSelectInput( qt_xdisplay(), w,
|
|
|
|
|
// FocusChangeMask |
|
|
|
|
|
// PropertyChangeMask |
|
|
|
|
|
StructureNotifyMask
|
|
|
|
|
);
|
|
|
|
|
propagateDockwins();
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Workspace::removeDockwin( WId w )
|
|
|
|
|
{
|
|
|
|
|
if ( !dockwins.contains( w ) )
|
|
|
|
|
return FALSE;
|
|
|
|
|
dockwins.remove( w );
|
|
|
|
|
propagateDockwins();
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Propagates the dockwins to the world
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::propagateDockwins()
|
|
|
|
|
{
|
|
|
|
|
WId* cl = new WId[ dockwins.count()];
|
|
|
|
|
int i = 0;
|
|
|
|
|
for ( WIdList::ConstIterator it = dockwins.begin(); it != dockwins.end(); ++it ) {
|
|
|
|
|
cl[i++] = (*it);
|
|
|
|
|
}
|
|
|
|
|
XChangeProperty(qt_xdisplay(), qt_xrootwin(),
|
|
|
|
|
atoms->net_kde_docking_windows, XA_WINDOW, 32,
|
|
|
|
|
PropModeReplace, (unsigned char *)cl, dockwins.count());
|
|
|
|
|
delete [] cl;
|
|
|
|
|
}
|
1999-11-13 01:51:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Workspace::createKeybindings(){
|
|
|
|
|
keys = new KGlobalAccel();
|
|
|
|
|
|
|
|
|
|
#include "kwinbindings.cpp"
|
|
|
|
|
|
|
|
|
|
keys->connectItem( "Switch to desktop 1", this, SLOT( slotSwitchDesktop1() ));
|
|
|
|
|
keys->connectItem( "Switch to desktop 2", this, SLOT( slotSwitchDesktop2() ));
|
|
|
|
|
keys->connectItem( "Switch to desktop 3", this, SLOT( slotSwitchDesktop3() ));
|
|
|
|
|
keys->connectItem( "Switch to desktop 4", this, SLOT( slotSwitchDesktop4() ));
|
|
|
|
|
keys->connectItem( "Switch to desktop 5", this, SLOT( slotSwitchDesktop5() ));
|
|
|
|
|
keys->connectItem( "Switch to desktop 6", this, SLOT( slotSwitchDesktop6() ));
|
|
|
|
|
keys->connectItem( "Switch to desktop 7", this, SLOT( slotSwitchDesktop7() ));
|
|
|
|
|
keys->connectItem( "Switch to desktop 8", this, SLOT( slotSwitchDesktop8() ));
|
|
|
|
|
|
|
|
|
|
keys->readSettings();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Workspace::slotSwitchDesktop1(){
|
|
|
|
|
setCurrentDesktop(1);
|
|
|
|
|
}
|
|
|
|
|
void Workspace::slotSwitchDesktop2(){
|
|
|
|
|
setCurrentDesktop(2);
|
|
|
|
|
}
|
|
|
|
|
void Workspace::slotSwitchDesktop3(){
|
|
|
|
|
setCurrentDesktop(3);
|
|
|
|
|
}
|
|
|
|
|
void Workspace::slotSwitchDesktop4(){
|
|
|
|
|
setCurrentDesktop(4);
|
|
|
|
|
}
|
|
|
|
|
void Workspace::slotSwitchDesktop5(){
|
|
|
|
|
setCurrentDesktop(5);
|
|
|
|
|
}
|
|
|
|
|
void Workspace::slotSwitchDesktop6(){
|
|
|
|
|
setCurrentDesktop(6);
|
|
|
|
|
}
|
|
|
|
|
void Workspace::slotSwitchDesktop7(){
|
|
|
|
|
setCurrentDesktop(7);
|
|
|
|
|
}
|
|
|
|
|
void Workspace::slotSwitchDesktop8(){
|
|
|
|
|
setCurrentDesktop(8);
|
|
|
|
|
}
|