2000-03-24 22:23:02 +00:00
|
|
|
|
/*****************************************************************
|
|
|
|
|
kwin - the KDE window manager
|
|
|
|
|
|
|
|
|
|
Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
|
|
|
|
|
******************************************************************/
|
2001-03-19 15:35:07 +00:00
|
|
|
|
|
2000-07-29 07:59:24 +00:00
|
|
|
|
//#define QT_CLEAN_NAMESPACE
|
2001-03-19 15:35:07 +00:00
|
|
|
|
#define select kwin_hide_select
|
|
|
|
|
|
2002-01-24 21:52:11 +00:00
|
|
|
|
#include <config.h>
|
1999-11-11 01:27:37 +00:00
|
|
|
|
#include <kconfig.h>
|
|
|
|
|
#include <kglobal.h>
|
2000-06-03 01:19:08 +00:00
|
|
|
|
#include <kglobalsettings.h>
|
1999-11-13 01:51:22 +00:00
|
|
|
|
#include <kglobalaccel.h>
|
2002-01-19 04:55:32 +00:00
|
|
|
|
#include <kkeynative.h>
|
1999-11-13 01:51:22 +00:00
|
|
|
|
#include <klocale.h>
|
1999-12-22 17:16:23 +00:00
|
|
|
|
#include <stdlib.h>
|
1999-12-01 22:09:32 +00:00
|
|
|
|
#include <qwhatsthis.h>
|
2000-05-04 23:12:29 +00:00
|
|
|
|
#include <qdatastream.h>
|
2000-10-17 15:55:40 +00:00
|
|
|
|
#include <qregexp.h>
|
2001-06-26 23:30:52 +00:00
|
|
|
|
#include <qclipboard.h>
|
2001-11-30 08:04:17 +00:00
|
|
|
|
#include <kapplication.h>
|
2000-05-04 23:12:29 +00:00
|
|
|
|
#include <dcopclient.h>
|
2000-08-30 14:27:30 +00:00
|
|
|
|
#include <kprocess.h>
|
2001-05-05 18:28:41 +00:00
|
|
|
|
#include <kiconloader.h>
|
2001-05-24 21:01:09 +00:00
|
|
|
|
#include <kstartupinfo.h>
|
2001-09-05 20:48:16 +00:00
|
|
|
|
#include <qdesktopwidget.h>
|
2002-06-29 06:31:33 +00:00
|
|
|
|
#include "placement.h"
|
1999-08-19 23:26:42 +00:00
|
|
|
|
#include "workspace.h"
|
|
|
|
|
#include "client.h"
|
|
|
|
|
#include "tabbox.h"
|
2002-04-05 19:54:21 +00:00
|
|
|
|
#include "popupinfo.h"
|
1999-08-19 23:26:42 +00:00
|
|
|
|
#include "atoms.h"
|
1999-12-24 01:36:47 +00:00
|
|
|
|
#include "plugins.h"
|
2000-05-07 20:38:11 +00:00
|
|
|
|
#include "events.h"
|
2000-06-19 10:45:45 +00:00
|
|
|
|
#include "killwindow.h"
|
2001-08-18 23:06:16 +00:00
|
|
|
|
#include <netwm.h>
|
1999-08-19 23:26:42 +00:00
|
|
|
|
#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-12-06 00:43:55 +00:00
|
|
|
|
#include <X11/keysymdef.h>
|
1999-11-12 03:11:19 +00:00
|
|
|
|
#include <X11/extensions/shape.h>
|
2000-05-17 23:02:42 +00:00
|
|
|
|
#include <X11/cursorfont.h>
|
2002-02-28 22:11:43 +00:00
|
|
|
|
#include <sys/time.h>
|
1999-11-12 03:11:19 +00:00
|
|
|
|
|
2000-05-07 20:17:33 +00:00
|
|
|
|
const int XIconicState = IconicState;
|
|
|
|
|
#undef IconicState
|
|
|
|
|
|
|
|
|
|
#include <kwin.h>
|
2001-02-10 00:27:26 +00:00
|
|
|
|
#include <kdebug.h>
|
2000-03-24 22:23:02 +00:00
|
|
|
|
|
2001-03-19 15:35:07 +00:00
|
|
|
|
// Possible protoypes for select() were hidden as `kwin_hide_select.
|
|
|
|
|
// Undo the hiding definition and defines an acceptable prototype.
|
2002-03-02 21:05:35 +00:00
|
|
|
|
// This is how Qt does this. It should work where Qt works.
|
2001-03-28 12:44:31 +00:00
|
|
|
|
#ifdef HAVE_SYS_SELECT_H
|
2001-03-19 15:35:07 +00:00
|
|
|
|
#include <sys/select.h>
|
|
|
|
|
#endif
|
|
|
|
|
#undef select
|
|
|
|
|
extern "C" int select(int,void*,void*,void*,struct timeval*);
|
|
|
|
|
|
2001-02-20 01:20:38 +00:00
|
|
|
|
namespace KWinInternal {
|
2001-02-06 18:32:07 +00:00
|
|
|
|
|
2000-06-08 17:05:51 +00:00
|
|
|
|
// NET WM Protocol handler class
|
|
|
|
|
class RootInfo : public NETRootInfo
|
|
|
|
|
{
|
|
|
|
|
public:
|
2001-02-20 01:20:38 +00:00
|
|
|
|
RootInfo( KWinInternal::Workspace* ws, Display *dpy, Window w, const char *name, unsigned long pr, int scr= -1)
|
2001-02-16 18:05:27 +00:00
|
|
|
|
: NETRootInfo( dpy, w, name, pr, scr ) {
|
|
|
|
|
workspace = ws;
|
2000-06-08 17:05:51 +00:00
|
|
|
|
}
|
|
|
|
|
~RootInfo() {}
|
|
|
|
|
|
2000-06-24 19:09:50 +00:00
|
|
|
|
void changeNumberOfDesktops(int n) { workspace->setNumberOfDesktops( n ); }
|
|
|
|
|
void changeCurrentDesktop(int d) { workspace->setCurrentDesktop( d ); }
|
2000-06-21 17:43:44 +00:00
|
|
|
|
void changeActiveWindow(Window w) {
|
2001-02-20 01:20:38 +00:00
|
|
|
|
KWinInternal::Client* c = workspace->findClient( (WId) w );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( c )
|
|
|
|
|
workspace->activateClient( c );
|
2000-06-08 17:05:51 +00:00
|
|
|
|
}
|
2000-06-21 17:43:44 +00:00
|
|
|
|
void closeWindow(Window w) {
|
2001-02-20 01:20:38 +00:00
|
|
|
|
KWinInternal::Client* c = workspace->findClient( (WId) w );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( c ) {
|
|
|
|
|
c->closeWindow();
|
|
|
|
|
}
|
2000-06-08 17:05:51 +00:00
|
|
|
|
}
|
2002-07-05 20:00:02 +00:00
|
|
|
|
void moveResize(Window w, int x_root, int y_root, unsigned long direction) {
|
|
|
|
|
KWinInternal::Client* c = workspace->findClient( (WId) w );
|
|
|
|
|
if ( c ) {
|
|
|
|
|
c->NETMoveResize( x_root, y_root, (Direction)direction);
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-06-21 17:43:44 +00:00
|
|
|
|
|
2000-06-08 17:05:51 +00:00
|
|
|
|
private:
|
2001-02-20 01:20:38 +00:00
|
|
|
|
KWinInternal::Workspace* workspace;
|
2000-06-08 17:05:51 +00:00
|
|
|
|
};
|
|
|
|
|
|
2001-04-03 14:40:34 +00:00
|
|
|
|
class WorkspacePrivate
|
|
|
|
|
{
|
|
|
|
|
public:
|
2001-09-05 20:40:04 +00:00
|
|
|
|
WorkspacePrivate()
|
|
|
|
|
: startup(0), electric_have_borders(false),
|
2001-11-03 00:05:33 +00:00
|
|
|
|
electric_current_border(0),
|
2001-08-27 05:42:32 +00:00
|
|
|
|
electric_top_border(None),
|
|
|
|
|
electric_bottom_border(None),
|
|
|
|
|
electric_left_border(None),
|
|
|
|
|
electric_right_border(None),
|
|
|
|
|
electric_time_first(0),
|
2001-08-27 23:56:15 +00:00
|
|
|
|
electric_time_last(0),
|
2001-11-29 23:59:54 +00:00
|
|
|
|
movingClient(0),
|
|
|
|
|
layoutOrientation(Qt::Vertical),
|
|
|
|
|
layoutX(-1),
|
|
|
|
|
layoutY(2)
|
2001-08-27 05:42:32 +00:00
|
|
|
|
{ };
|
2001-05-24 21:01:09 +00:00
|
|
|
|
~WorkspacePrivate() {};
|
|
|
|
|
KStartupInfo* startup;
|
2001-08-27 05:42:32 +00:00
|
|
|
|
bool electric_have_borders;
|
2001-11-03 00:05:33 +00:00
|
|
|
|
int electric_current_border;
|
2001-08-27 05:42:32 +00:00
|
|
|
|
WId electric_top_border;
|
|
|
|
|
WId electric_bottom_border;
|
|
|
|
|
WId electric_left_border;
|
|
|
|
|
WId electric_right_border;
|
2001-11-03 00:05:33 +00:00
|
|
|
|
int electricLeft;
|
|
|
|
|
int electricRight;
|
|
|
|
|
int electricTop;
|
|
|
|
|
int electricBottom;
|
2001-08-27 05:42:32 +00:00
|
|
|
|
Time electric_time_first;
|
|
|
|
|
Time electric_time_last;
|
2001-09-06 19:44:06 +00:00
|
|
|
|
QPoint electric_push_point;
|
2001-08-27 23:56:15 +00:00
|
|
|
|
Client *movingClient;
|
2001-11-29 23:59:54 +00:00
|
|
|
|
Qt::Orientation layoutOrientation;
|
|
|
|
|
int layoutX;
|
|
|
|
|
int layoutY;
|
2002-06-29 06:31:33 +00:00
|
|
|
|
Placement *initPositioning;
|
2001-04-03 14:40:34 +00:00
|
|
|
|
};
|
|
|
|
|
|
2001-02-20 01:20:38 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using namespace KWinInternal;
|
|
|
|
|
|
|
|
|
|
extern int kwin_screen_number;
|
2000-06-08 17:05:51 +00:00
|
|
|
|
|
2000-07-14 19:56:47 +00:00
|
|
|
|
QString Workspace::desktopName( int desk )
|
|
|
|
|
{
|
|
|
|
|
return QString::fromUtf8( rootInfo->desktopName( desk ) );
|
|
|
|
|
}
|
2000-06-08 17:05:51 +00:00
|
|
|
|
|
2002-02-28 22:11:43 +00:00
|
|
|
|
extern Time qt_x_time;
|
2000-06-23 16:26:44 +00:00
|
|
|
|
extern void kwin_updateTime();
|
1999-11-28 21:41:15 +00:00
|
|
|
|
|
1999-11-12 03:11:19 +00:00
|
|
|
|
// 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;
|
1999-11-29 02:49:20 +00:00
|
|
|
|
static bool block_focus = FALSE;
|
2001-03-30 11:15:15 +00:00
|
|
|
|
static Window null_focus_window = 0;
|
1999-11-12 03:11:19 +00:00
|
|
|
|
// does the window w need a shape combine mask around it?
|
|
|
|
|
bool Shape::hasShape( WId w){
|
2000-06-08 17:05:51 +00:00
|
|
|
|
int xws, yws, xbs, ybs;
|
2000-12-14 11:35:12 +00:00
|
|
|
|
unsigned int wws, hws, wbs, hbs;
|
2002-03-17 13:31:35 +00:00
|
|
|
|
int boundingShaped = 0, clipShaped = 0;
|
2000-06-08 17:05:51 +00:00
|
|
|
|
if (!kwin_has_shape)
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return FALSE;
|
2000-06-08 17:05:51 +00:00
|
|
|
|
XShapeQueryExtents(qt_xdisplay(), w,
|
2001-02-16 18:05:27 +00:00
|
|
|
|
&boundingShaped, &xws, &yws, &wws, &hws,
|
|
|
|
|
&clipShaped, &xbs, &ybs, &wbs, &hbs);
|
2000-06-08 17:05:51 +00:00
|
|
|
|
return boundingShaped != 0;
|
1999-11-12 03:11:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Shape::shapeEvent()
|
|
|
|
|
{
|
|
|
|
|
return kwin_shape_event;
|
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
2000-04-06 18:29:04 +00:00
|
|
|
|
bool Motif::noBorder( WId w )
|
|
|
|
|
{
|
|
|
|
|
struct MwmHints {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
ulong flags;
|
|
|
|
|
ulong functions;
|
|
|
|
|
ulong decorations;
|
|
|
|
|
long input_mode;
|
|
|
|
|
ulong status;
|
2000-04-06 18:29:04 +00:00
|
|
|
|
};
|
|
|
|
|
Atom type;
|
|
|
|
|
int format;
|
|
|
|
|
unsigned long length, after;
|
|
|
|
|
unsigned char* data;
|
|
|
|
|
MwmHints* hints = 0;
|
|
|
|
|
if ( XGetWindowProperty( qt_xdisplay(), w, atoms->motif_wm_hints, 0, 5,
|
2001-02-16 18:05:27 +00:00
|
|
|
|
FALSE, atoms->motif_wm_hints, &type, &format,
|
|
|
|
|
&length, &after, &data ) == Success ) {
|
|
|
|
|
if ( data )
|
|
|
|
|
hints = (MwmHints*) data;
|
2000-04-06 18:29:04 +00:00
|
|
|
|
}
|
|
|
|
|
bool result = FALSE;
|
|
|
|
|
if ( hints ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( hints->flags & (1L << 1 ) ) { // // MWM_HINTS_DECORATIONS;
|
|
|
|
|
if ( hints->decorations == 0 )
|
|
|
|
|
result = TRUE;
|
|
|
|
|
}
|
|
|
|
|
XFree( data );
|
2000-04-06 18:29:04 +00:00
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
2000-05-07 20:17:33 +00:00
|
|
|
|
|
2000-06-23 16:26:44 +00:00
|
|
|
|
/*!
|
2000-06-22 14:12:13 +00:00
|
|
|
|
Creates a new client for window \a w, depending on certain hints
|
|
|
|
|
(like Motif hints and the NET_WM_TYPE.
|
2000-06-23 16:26:44 +00:00
|
|
|
|
|
|
|
|
|
Shaped windows always get a NoBorderClient.
|
2000-06-22 14:12:13 +00:00
|
|
|
|
*/
|
|
|
|
|
Client* Workspace::clientFactory( WId w )
|
|
|
|
|
{
|
2000-06-08 17:05:51 +00:00
|
|
|
|
NETWinInfo ni( qt_xdisplay(), w, root, NET::WMWindowType );
|
2000-05-07 20:17:33 +00:00
|
|
|
|
|
2000-07-08 12:08:41 +00:00
|
|
|
|
if ( (ni.windowType() == NET::Normal || ni.windowType() == NET::Unknown)
|
2001-02-16 18:05:27 +00:00
|
|
|
|
&& Motif::noBorder( w ) )
|
|
|
|
|
return new NoBorderClient( this, w );
|
2000-06-22 14:12:13 +00:00
|
|
|
|
|
2000-06-08 17:05:51 +00:00
|
|
|
|
switch ( ni.windowType() ) {
|
2002-07-05 20:05:22 +00:00
|
|
|
|
// when adding new window types, add a fallback for them in PluginMgr::createClient()
|
2000-07-12 18:08:24 +00:00
|
|
|
|
case NET::Desktop:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
{
|
|
|
|
|
XLowerWindow( qt_xdisplay(), w );
|
|
|
|
|
Client * c = new NoBorderClient( this, w);
|
|
|
|
|
c->setSticky( TRUE );
|
|
|
|
|
return c;
|
|
|
|
|
}
|
2000-06-21 17:43:44 +00:00
|
|
|
|
|
2000-07-12 18:08:24 +00:00
|
|
|
|
case NET::Dock:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
{
|
|
|
|
|
Client * c = new NoBorderClient( this, w );
|
|
|
|
|
c->setSticky( TRUE );
|
|
|
|
|
return c;
|
|
|
|
|
}
|
2000-06-21 17:43:44 +00:00
|
|
|
|
|
2002-07-05 20:05:22 +00:00
|
|
|
|
case NET::TopMenu:
|
2002-07-25 20:08:09 +00:00
|
|
|
|
{
|
|
|
|
|
Client* c = new NoBorderClient( this, w );
|
|
|
|
|
c->setStaysOnTop( true );
|
|
|
|
|
return c;
|
|
|
|
|
}
|
2002-06-25 07:42:01 +00:00
|
|
|
|
|
2000-07-12 12:46:58 +00:00
|
|
|
|
case NET::Override:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return new NoBorderClient( this, w);
|
2000-06-21 17:43:44 +00:00
|
|
|
|
|
2002-07-05 20:05:22 +00:00
|
|
|
|
case NET::Menu:
|
|
|
|
|
{
|
|
|
|
|
Window dummy1;
|
|
|
|
|
int x, y;
|
|
|
|
|
unsigned int width, height, dummy2, dummy3;
|
|
|
|
|
XGetGeometry( qt_xdisplay(), w, &dummy1, &x, &y, &width, &height,
|
|
|
|
|
&dummy2, &dummy3 );
|
|
|
|
|
// ugly hack to support the times when NET::Menu meant NET::TopMenu
|
|
|
|
|
// if it's as wide as the screen, not very high and has its upper-left
|
|
|
|
|
// corner a bit above the screen's upper-left cornet, it's a topmenu
|
2002-07-25 20:08:09 +00:00
|
|
|
|
if( x == 0 && y < 0 && y > -10 && height < 100 && int(width) == geometry().width()) {
|
|
|
|
|
Client* c = new NoBorderClient( this, w);
|
|
|
|
|
c->setStaysOnTop( true );
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2002-07-05 20:05:22 +00:00
|
|
|
|
}
|
|
|
|
|
case NET::Tool:
|
2002-07-25 20:08:09 +00:00
|
|
|
|
break;
|
2000-06-08 17:05:51 +00:00
|
|
|
|
default:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
break;
|
2000-06-08 17:05:51 +00:00
|
|
|
|
}
|
1999-11-14 06:34:28 +00:00
|
|
|
|
|
1999-11-12 03:11:19 +00:00
|
|
|
|
if ( Shape::hasShape( w ) ){
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return new NoBorderClient( this, w );
|
1999-11-12 03:11:19 +00:00
|
|
|
|
}
|
2002-07-05 20:05:22 +00:00
|
|
|
|
return ( mgr->createClient( this, w, ni.windowType()) );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-04-22 06:51:07 +00:00
|
|
|
|
Workspace *Workspace::_self = 0;
|
|
|
|
|
|
2000-05-04 23:12:29 +00:00
|
|
|
|
// Rikkus: This class is too complex. It needs splitting further.
|
|
|
|
|
// It's a nightmare to understand, especially with so few comments :(
|
2000-06-22 14:12:13 +00:00
|
|
|
|
|
|
|
|
|
// Matthias: Feel free to ask me questions about it. Feel free to add
|
|
|
|
|
// comments. I dissagree that further splittings makes it easier. 2500
|
|
|
|
|
// lines are not too much. It's the task that is complex, not the
|
|
|
|
|
// code.
|
2000-03-24 22:23:02 +00:00
|
|
|
|
Workspace::Workspace( bool restore )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
: QObject (0, "workspace"),
|
|
|
|
|
DCOPObject ("KWinInterface"),
|
2000-05-04 23:12:29 +00:00
|
|
|
|
current_desktop (0),
|
|
|
|
|
number_of_desktops(0),
|
|
|
|
|
desktop_widget (0),
|
|
|
|
|
active_client (0),
|
2001-02-03 12:30:46 +00:00
|
|
|
|
last_active_client (0),
|
2000-05-04 23:12:29 +00:00
|
|
|
|
should_get_focus (0),
|
2000-10-02 12:02:15 +00:00
|
|
|
|
most_recently_raised (0),
|
2000-05-04 23:12:29 +00:00
|
|
|
|
control_grab (false),
|
2001-02-16 18:05:27 +00:00
|
|
|
|
tab_grab (false),
|
2000-05-04 23:12:29 +00:00
|
|
|
|
mouse_emulation (false),
|
2000-06-02 00:20:41 +00:00
|
|
|
|
focus_change (true),
|
2001-02-16 18:05:27 +00:00
|
|
|
|
tab_box (0),
|
2002-04-05 19:54:21 +00:00
|
|
|
|
popupinfo (0),
|
2001-02-16 18:05:27 +00:00
|
|
|
|
popup (0),
|
|
|
|
|
desk_popup (0),
|
|
|
|
|
keys (0),
|
|
|
|
|
root (0)
|
1999-08-19 23:26:42 +00:00
|
|
|
|
{
|
2001-04-22 06:51:07 +00:00
|
|
|
|
_self = this;
|
2001-04-03 14:40:34 +00:00
|
|
|
|
d = new WorkspacePrivate;
|
2001-02-20 01:20:38 +00:00
|
|
|
|
mgr = new PluginMgr;
|
2000-03-22 12:36:07 +00:00
|
|
|
|
root = qt_xrootwin();
|
2000-08-30 14:27:30 +00:00
|
|
|
|
default_colormap = DefaultColormap(qt_xdisplay(), qt_xscreen() );
|
|
|
|
|
installed_colormap = default_colormap;
|
2000-03-24 22:23:02 +00:00
|
|
|
|
session.setAutoDelete( TRUE );
|
|
|
|
|
|
|
|
|
|
if ( restore )
|
2000-05-04 23:12:29 +00:00
|
|
|
|
loadSessionInfo();
|
2001-02-01 01:13:44 +00:00
|
|
|
|
|
2001-01-27 19:24:15 +00:00
|
|
|
|
loadFakeSessionInfo();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
|
|
|
|
(void) QApplication::desktop(); // trigger creation of desktop widget
|
2000-05-04 23:12:29 +00:00
|
|
|
|
|
|
|
|
|
desktop_widget =
|
|
|
|
|
new QWidget(
|
2001-02-16 18:05:27 +00:00
|
|
|
|
0,
|
|
|
|
|
"desktop_widget",
|
|
|
|
|
Qt::WType_Desktop | Qt::WPaintUnclipped
|
2000-05-04 23:12:29 +00:00
|
|
|
|
);
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
2001-05-24 21:01:09 +00:00
|
|
|
|
// call this before XSelectInput() on the root window
|
|
|
|
|
d->startup = new KStartupInfo( false, this );
|
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
// select windowmanager privileges
|
|
|
|
|
XSelectInput(qt_xdisplay(), root,
|
2001-02-16 18:05:27 +00:00
|
|
|
|
KeyPressMask |
|
|
|
|
|
PropertyChangeMask |
|
|
|
|
|
ColormapChangeMask |
|
|
|
|
|
SubstructureRedirectMask |
|
|
|
|
|
SubstructureNotifyMask
|
|
|
|
|
);
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
1999-11-12 03:11:19 +00:00
|
|
|
|
int dummy;
|
2000-05-04 23:12:29 +00:00
|
|
|
|
kwin_has_shape =
|
|
|
|
|
XShapeQueryExtension(qt_xdisplay(), &kwin_shape_event, &dummy);
|
1999-11-14 06:34:28 +00:00
|
|
|
|
|
1999-11-13 03:44:09 +00:00
|
|
|
|
// compatibility
|
|
|
|
|
long data = 1;
|
1999-11-14 06:34:28 +00:00
|
|
|
|
|
2000-05-04 23:12:29 +00:00
|
|
|
|
XChangeProperty(
|
|
|
|
|
qt_xdisplay(),
|
|
|
|
|
qt_xrootwin(),
|
2000-06-08 17:05:51 +00:00
|
|
|
|
atoms->kwin_running,
|
|
|
|
|
atoms->kwin_running,
|
2000-05-04 23:12:29 +00:00
|
|
|
|
32,
|
|
|
|
|
PropModeAppend,
|
|
|
|
|
(unsigned char*) &data,
|
|
|
|
|
1
|
|
|
|
|
);
|
|
|
|
|
|
2002-01-19 04:55:32 +00:00
|
|
|
|
initShortcuts();
|
1999-11-22 01:57:51 +00:00
|
|
|
|
tab_box = new TabBox( this );
|
2002-04-05 19:54:21 +00:00
|
|
|
|
popupinfo = new PopupInfo( );
|
2000-07-11 14:49:52 +00:00
|
|
|
|
|
2000-07-11 14:38:17 +00:00
|
|
|
|
init();
|
1999-11-07 08:46:36 +00:00
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
2001-04-22 06:51:07 +00:00
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
void Workspace::init()
|
|
|
|
|
{
|
2001-11-03 00:05:33 +00:00
|
|
|
|
QRect r = QApplication::desktop()->geometry();
|
|
|
|
|
d->electricTop = r.top();
|
|
|
|
|
d->electricBottom = r.bottom();
|
|
|
|
|
d->electricLeft = r.left();
|
|
|
|
|
d->electricRight = r.right();
|
|
|
|
|
d->electric_current_border = 0;
|
|
|
|
|
|
|
|
|
|
if (options->electricBorders() == Options::ElectricAlways)
|
2001-08-27 05:42:32 +00:00
|
|
|
|
createBorderWindows();
|
|
|
|
|
|
2000-06-08 17:05:51 +00:00
|
|
|
|
supportWindow = new QWidget;
|
2000-06-21 17:43:44 +00:00
|
|
|
|
|
|
|
|
|
unsigned long protocols =
|
2001-02-16 18:05:27 +00:00
|
|
|
|
NET::Supported |
|
|
|
|
|
NET::SupportingWMCheck |
|
|
|
|
|
NET::ClientList |
|
|
|
|
|
NET::ClientListStacking |
|
|
|
|
|
NET::NumberOfDesktops |
|
|
|
|
|
NET::CurrentDesktop |
|
|
|
|
|
NET::ActiveWindow |
|
|
|
|
|
NET::WorkArea |
|
|
|
|
|
NET::CloseWindow |
|
|
|
|
|
NET::DesktopNames |
|
|
|
|
|
NET::KDESystemTrayWindows |
|
|
|
|
|
NET::CloseWindow |
|
|
|
|
|
NET::WMName |
|
|
|
|
|
NET::WMVisibleName |
|
|
|
|
|
NET::WMDesktop |
|
|
|
|
|
NET::WMWindowType |
|
|
|
|
|
NET::WMState |
|
|
|
|
|
NET::WMStrut |
|
|
|
|
|
NET::WMIconGeometry |
|
|
|
|
|
NET::WMIcon |
|
|
|
|
|
NET::WMPid |
|
2002-07-05 20:00:02 +00:00
|
|
|
|
NET::WMMoveResize |
|
2001-02-16 18:05:27 +00:00
|
|
|
|
NET::WMKDESystemTrayWinFor |
|
|
|
|
|
NET::WMKDEFrameStrut
|
|
|
|
|
;
|
2000-12-17 03:23:34 +00:00
|
|
|
|
|
2000-06-08 17:05:51 +00:00
|
|
|
|
rootInfo = new RootInfo( this, qt_xdisplay(), supportWindow->winId(), "KWin", protocols, qt_xscreen() );
|
2000-07-12 18:08:24 +00:00
|
|
|
|
|
|
|
|
|
loadDesktopSettings();
|
1999-11-07 01:43:06 +00:00
|
|
|
|
setCurrentDesktop( 1 );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
2002-06-29 06:31:33 +00:00
|
|
|
|
// now we know how many desktops we'll, thus, we initialise the positioning object
|
|
|
|
|
d->initPositioning = new Placement(this);
|
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
unsigned int i, nwins;
|
2000-10-15 14:19:15 +00:00
|
|
|
|
Window root_return, parent_return, *wins;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
XWindowAttributes attr;
|
|
|
|
|
|
2001-01-25 19:17:17 +00:00
|
|
|
|
connect(&resetTimer, SIGNAL(timeout()), this,
|
2001-02-16 18:05:27 +00:00
|
|
|
|
SLOT(slotResetAllClients()));
|
2001-06-04 14:01:00 +00:00
|
|
|
|
connect(&reconfigureTimer, SIGNAL(timeout()), this,
|
|
|
|
|
SLOT(slotReconfigure()));
|
2001-01-25 19:17:17 +00:00
|
|
|
|
|
2001-02-20 01:20:38 +00:00
|
|
|
|
connect(mgr, SIGNAL(resetAllClients()), this,
|
2001-02-16 18:05:27 +00:00
|
|
|
|
SLOT(slotResetAllClients()));
|
2000-06-24 06:48:53 +00:00
|
|
|
|
connect(kapp, SIGNAL(appearanceChanged()), this,
|
2002-03-16 09:26:49 +00:00
|
|
|
|
SLOT(slotReconfigure()));
|
2001-11-30 08:04:17 +00:00
|
|
|
|
connect(kapp, SIGNAL(settingsChanged(int)), this,
|
|
|
|
|
SLOT(slotSettingsChanged(int)));
|
1999-12-24 01:36:47 +00:00
|
|
|
|
|
2001-02-03 12:30:46 +00:00
|
|
|
|
connect(&focusEnsuranceTimer, SIGNAL(timeout()), this,
|
2001-02-16 18:05:27 +00:00
|
|
|
|
SLOT(focusEnsurance()));
|
2001-02-10 00:27:26 +00:00
|
|
|
|
|
2000-10-15 14:19:15 +00:00
|
|
|
|
XQueryTree(qt_xdisplay(), root, &root_return, &parent_return, &wins, &nwins);
|
1999-08-19 23:26:42 +00:00
|
|
|
|
for (i = 0; i < nwins; i++) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
XGetWindowAttributes(qt_xdisplay(), wins[i], &attr);
|
|
|
|
|
if (attr.override_redirect )
|
|
|
|
|
continue;
|
|
|
|
|
if (attr.map_state != IsUnmapped) {
|
|
|
|
|
if ( addSystemTrayWin( wins[i] ) )
|
|
|
|
|
continue;
|
|
|
|
|
Client* c = clientFactory( wins[i] );
|
2002-03-03 13:56:55 +00:00
|
|
|
|
addClient( c );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c->manage( TRUE );
|
2002-03-03 21:13:03 +00:00
|
|
|
|
if ( !c->wantsTabFocus() )
|
|
|
|
|
focus_chain.remove( c );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( root != qt_xrootwin() ) {
|
|
|
|
|
// TODO may use QWidget:.create
|
|
|
|
|
XReparentWindow( qt_xdisplay(), c->winId(), root, 0, 0 );
|
|
|
|
|
c->move(0,0);
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
2000-10-15 14:19:15 +00:00
|
|
|
|
if ( wins )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
XFree((void *) wins);
|
1999-11-07 01:43:06 +00:00
|
|
|
|
propagateClients();
|
1999-11-20 06:27:07 +00:00
|
|
|
|
|
2000-04-28 02:52:09 +00:00
|
|
|
|
updateClientArea();
|
2001-08-27 05:42:32 +00:00
|
|
|
|
raiseElectricBorders();
|
2002-06-29 06:31:33 +00:00
|
|
|
|
|
2002-06-28 20:28:33 +00:00
|
|
|
|
// NETWM spec says we have to set it to (0,0) if we don't support it
|
|
|
|
|
rootInfo->setDesktopViewport( 1, NETPoint());
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Workspace::~Workspace()
|
|
|
|
|
{
|
2002-03-02 21:03:49 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = desktops.fromLast(); it != desktops.end(); --it) {
|
|
|
|
|
WId win = (*it)->window();
|
|
|
|
|
delete (*it);
|
2001-02-16 18:05:27 +00:00
|
|
|
|
XMapWindow( qt_xdisplay(), win );
|
|
|
|
|
XLowerWindow( qt_xdisplay(), win );
|
1999-11-07 02:07:03 +00:00
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
storeFakeSessionInfo( *it );
|
|
|
|
|
WId win = (*it)->window();
|
|
|
|
|
delete (*it);
|
|
|
|
|
XMapWindow( qt_xdisplay(), win );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
2000-09-14 06:03:47 +00:00
|
|
|
|
delete desktop_widget;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
delete tab_box;
|
2002-04-05 19:54:21 +00:00
|
|
|
|
delete popupinfo;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
delete popup;
|
1999-11-13 03:44:09 +00:00
|
|
|
|
if ( root == qt_xrootwin() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
XDeleteProperty(qt_xdisplay(), qt_xrootwin(), atoms->kwin_running);
|
2001-01-14 20:16:04 +00:00
|
|
|
|
|
|
|
|
|
writeFakeSessionInfo();
|
1999-12-03 19:04:03 +00:00
|
|
|
|
KGlobal::config()->sync();
|
2000-06-21 17:43:44 +00:00
|
|
|
|
|
2000-06-08 17:05:51 +00:00
|
|
|
|
delete rootInfo;
|
|
|
|
|
delete supportWindow;
|
2001-02-20 01:20:38 +00:00
|
|
|
|
delete mgr;
|
2002-07-06 20:16:36 +00:00
|
|
|
|
delete d->startup;
|
|
|
|
|
delete d->initPositioning;
|
2001-04-03 14:40:34 +00:00
|
|
|
|
delete d;
|
2001-04-22 06:51:07 +00:00
|
|
|
|
_self = 0;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-11-17 17:25:26 +00:00
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
/*!
|
|
|
|
|
Handles workspace specific XEvents
|
|
|
|
|
*/
|
|
|
|
|
bool Workspace::workspaceEvent( XEvent * e )
|
|
|
|
|
{
|
2002-04-15 13:06:01 +00:00
|
|
|
|
if ( mouse_emulation && (e->type == ButtonPress || e->type == ButtonRelease ) ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
mouse_emulation = FALSE;
|
2002-02-28 22:11:43 +00:00
|
|
|
|
XUngrabKeyboard( qt_xdisplay(), qt_x_time );
|
1999-12-06 00:43:55 +00:00
|
|
|
|
}
|
1999-12-07 21:54:52 +00:00
|
|
|
|
|
2000-11-17 16:39:47 +00:00
|
|
|
|
if ( e->type == PropertyNotify || e->type == ClientMessage ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( netCheck( e ) )
|
|
|
|
|
return TRUE;
|
2000-11-17 16:39:47 +00:00
|
|
|
|
}
|
2000-12-14 11:35:12 +00:00
|
|
|
|
|
2001-02-10 00:27:26 +00:00
|
|
|
|
|
2001-02-03 12:30:46 +00:00
|
|
|
|
if ( e->type == FocusIn )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
focusEnsuranceTimer.stop();
|
2001-02-03 12:30:46 +00:00
|
|
|
|
else if ( e->type == FocusOut )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
focusEnsuranceTimer.start(50);
|
2001-02-10 00:27:26 +00:00
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
Client * c = findClient( e->xany.window );
|
|
|
|
|
if ( c )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return c->windowEvent( e );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
|
|
|
|
switch (e->type) {
|
|
|
|
|
case ButtonPress:
|
2001-07-12 17:16:04 +00:00
|
|
|
|
if ( tab_grab || control_grab ) {
|
2002-02-28 22:11:43 +00:00
|
|
|
|
XUngrabKeyboard(qt_xdisplay(), qt_x_time);
|
|
|
|
|
XUngrabPointer( qt_xdisplay(), qt_x_time);
|
2001-07-12 17:16:04 +00:00
|
|
|
|
tab_box->hide();
|
2002-01-19 04:55:32 +00:00
|
|
|
|
keys->setEnabled( true );
|
2001-07-12 17:16:04 +00:00
|
|
|
|
tab_grab = control_grab = false;
|
2001-07-27 12:48:30 +00:00
|
|
|
|
return TRUE;
|
2001-07-12 17:16:04 +00:00
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
case ButtonRelease:
|
2000-04-26 01:45:10 +00:00
|
|
|
|
case MotionNotify:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
break;
|
2002-03-02 01:34:31 +00:00
|
|
|
|
|
2002-02-28 22:11:43 +00:00
|
|
|
|
case CreateNotify:
|
2002-03-02 01:34:31 +00:00
|
|
|
|
if ( e->xcreatewindow.parent == root &&
|
|
|
|
|
!QWidget::find( e->xcreatewindow.window) ) {
|
|
|
|
|
timeval tv;
|
|
|
|
|
gettimeofday( &tv, NULL );
|
|
|
|
|
unsigned long now = tv.tv_sec * 10 + tv.tv_usec / 100000;
|
|
|
|
|
XChangeProperty(qt_xdisplay(), e->xcreatewindow.window,
|
|
|
|
|
atoms->kde_net_user_time, XA_CARDINAL,
|
|
|
|
|
32, PropModeReplace, (unsigned char *)&now, 1);
|
|
|
|
|
}
|
|
|
|
|
break;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
case UnmapNotify:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
// this is special due to
|
|
|
|
|
// SubstructureNotifyMask. e->xany.window is the window the
|
|
|
|
|
// event is reported to. Take care not to confuse Qt.
|
|
|
|
|
c = findClient( e->xunmap.window );
|
2000-03-21 20:02:27 +00:00
|
|
|
|
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( c )
|
|
|
|
|
return c->windowEvent( e );
|
1999-11-11 01:22:41 +00:00
|
|
|
|
|
2001-02-16 18:05:27 +00:00
|
|
|
|
// check for system tray windows
|
2002-04-02 12:36:24 +00:00
|
|
|
|
if ( removeSystemTrayWin( e->xunmap.window ) ) {
|
|
|
|
|
// If the system tray gets destroyed, the system tray
|
|
|
|
|
// icons automatically get unmapped, reparented and mapped
|
|
|
|
|
// again to the closest non-client ancestor due to
|
|
|
|
|
// QXEmbed's SaveSet feature. Unfortunatly with kicker
|
|
|
|
|
// this closest ancestor is not the root window, but our
|
|
|
|
|
// decoration, so we reparent explicitely back to the root
|
|
|
|
|
// window.
|
|
|
|
|
XEvent ev;
|
|
|
|
|
WId w = e->xunmap.window;
|
|
|
|
|
if ( XCheckTypedWindowEvent (qt_xdisplay(), w,
|
|
|
|
|
ReparentNotify, &ev) ){
|
|
|
|
|
if ( ev.xreparent.parent != root ) {
|
|
|
|
|
XReparentWindow( qt_xdisplay(), w, root, 0, 0 );
|
|
|
|
|
addSystemTrayWin( w );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2000-03-21 20:02:27 +00:00
|
|
|
|
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return ( e->xunmap.event != e->xunmap.window ); // hide wm typical event from Qt
|
2000-12-17 03:23:34 +00:00
|
|
|
|
|
1999-11-15 00:52:05 +00:00
|
|
|
|
case MapNotify:
|
2000-10-04 15:19:44 +00:00
|
|
|
|
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return ( e->xmap.event != e->xmap.window ); // hide wm typical event from Qt
|
2000-12-17 03:23:34 +00:00
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
case ReparentNotify:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c = findClient( e->xreparent.window );
|
|
|
|
|
if ( c )
|
|
|
|
|
(void) c->windowEvent( e );
|
2000-12-17 03:23:34 +00:00
|
|
|
|
|
2001-02-16 18:05:27 +00:00
|
|
|
|
//do not confuse Qt with these events. After all, _we_ are the
|
|
|
|
|
//window manager who does the reparenting.
|
|
|
|
|
return TRUE;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
case DestroyNotify:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( removeSystemTrayWin( e->xdestroywindow.window ) )
|
|
|
|
|
return TRUE;
|
|
|
|
|
return destroyClient( findClient( e->xdestroywindow.window ) );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
case MapRequest:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
kwin_updateTime();
|
2001-05-24 21:01:09 +00:00
|
|
|
|
checkStartOnDesktop( e->xmaprequest.window );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c = findClient( e->xmaprequest.window );
|
|
|
|
|
if ( !c ) {
|
2002-04-02 12:36:24 +00:00
|
|
|
|
if ( e->xmaprequest.parent == root ) { //###TODO store previously destroyed client ids
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( addSystemTrayWin( e->xmaprequest.window ) )
|
|
|
|
|
return TRUE;
|
|
|
|
|
c = clientFactory( e->xmaprequest.window );
|
|
|
|
|
if ( root != qt_xrootwin() ) {
|
|
|
|
|
// TODO may use QWidget:.create
|
|
|
|
|
XReparentWindow( qt_xdisplay(), c->winId(), root, 0, 0 );
|
|
|
|
|
}
|
2002-03-03 13:56:55 +00:00
|
|
|
|
addClient( c );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( c ) {
|
2002-03-03 16:56:41 +00:00
|
|
|
|
bool b = c->windowEvent( e );
|
2002-03-03 21:13:03 +00:00
|
|
|
|
if ( !c->wantsTabFocus() )
|
|
|
|
|
focus_chain.remove( c );
|
|
|
|
|
return b;
|
2001-02-16 18:05:27 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
1999-12-01 22:09:32 +00:00
|
|
|
|
case EnterNotify:
|
2001-08-27 05:42:32 +00:00
|
|
|
|
if ( QWhatsThis::inWhatsThisMode() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
{
|
|
|
|
|
QWidget* w = QWidget::find( e->xcrossing.window );
|
2001-09-10 06:12:58 +00:00
|
|
|
|
if ( w )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
QWhatsThis::leaveWhatsThisMode();
|
|
|
|
|
}
|
2001-08-27 05:42:32 +00:00
|
|
|
|
|
|
|
|
|
if (d->electric_have_borders &&
|
|
|
|
|
(e->xcrossing.window == d->electric_top_border ||
|
|
|
|
|
e->xcrossing.window == d->electric_left_border ||
|
|
|
|
|
e->xcrossing.window == d->electric_bottom_border ||
|
|
|
|
|
e->xcrossing.window == d->electric_right_border))
|
|
|
|
|
{
|
|
|
|
|
// the user entered an electric border
|
|
|
|
|
electricBorder(e);
|
|
|
|
|
}
|
2001-02-16 18:05:27 +00:00
|
|
|
|
break;
|
1999-12-01 22:09:32 +00:00
|
|
|
|
case LeaveNotify:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( !QWhatsThis::inWhatsThisMode() )
|
|
|
|
|
break;
|
|
|
|
|
c = findClientWidthId( e->xcrossing.window );
|
|
|
|
|
if ( c && e->xcrossing.detail != NotifyInferior )
|
|
|
|
|
QWhatsThis::leaveWhatsThisMode();
|
|
|
|
|
break;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
case ConfigureRequest:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
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;
|
|
|
|
|
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 );
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
case KeyPress:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( mouse_emulation )
|
|
|
|
|
return keyPressMouseEmulation( e->xkey );
|
|
|
|
|
return keyPress(e->xkey);
|
2000-03-21 20:02:27 +00:00
|
|
|
|
case KeyRelease:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( mouse_emulation )
|
|
|
|
|
return FALSE;
|
|
|
|
|
return keyRelease(e->xkey);
|
|
|
|
|
break;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
case FocusIn:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
break;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
case FocusOut:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
break;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
default:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( e->type == Shape::shapeEvent() ) {
|
|
|
|
|
c = findClient( ((XShapeEvent *)e)->window );
|
|
|
|
|
if ( c )
|
|
|
|
|
c->updateShape();
|
|
|
|
|
}
|
|
|
|
|
break;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
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) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( (*it) == c )
|
|
|
|
|
return TRUE;
|
1999-11-07 08:46:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( (*it)->window() == w )
|
|
|
|
|
return *it;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
2002-03-02 21:03:49 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = desktops.begin(); it != desktops.end(); ++it) {
|
|
|
|
|
if ( (*it)->window() == w )
|
|
|
|
|
return *it;
|
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-15 00:52:05 +00:00
|
|
|
|
/*!
|
|
|
|
|
Finds the client with window id \a w
|
|
|
|
|
*/
|
|
|
|
|
Client* Workspace::findClientWidthId( WId w ) const
|
|
|
|
|
{
|
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( (*it)->winId() == w )
|
|
|
|
|
return *it;
|
1999-11-15 00:52:05 +00:00
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-14 06:34:28 +00:00
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
/*!
|
|
|
|
|
Returns the workspace's geometry
|
1999-11-14 06:34:28 +00:00
|
|
|
|
|
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() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return QRect( QPoint(0, 0), QApplication::desktop()->size() );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
else {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
// 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-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-14 09:21:16 +00:00
|
|
|
|
|
|
|
|
|
void Workspace::removeClient( Client* c) {
|
|
|
|
|
clients.remove( c );
|
|
|
|
|
stacking_order.remove( c );
|
|
|
|
|
focus_chain.remove( c );
|
|
|
|
|
propagateClients();
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
/*
|
|
|
|
|
Destroys the client \a c
|
|
|
|
|
*/
|
|
|
|
|
bool Workspace::destroyClient( Client* c)
|
|
|
|
|
{
|
|
|
|
|
if ( !c )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return FALSE;
|
2001-03-14 09:21:16 +00:00
|
|
|
|
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if (c == active_client && popup)
|
2002-03-11 05:02:50 +00:00
|
|
|
|
popup->close();
|
|
|
|
|
|
2001-06-18 20:18:32 +00:00
|
|
|
|
storeFakeSessionInfo( c );
|
2001-11-07 01:09:29 +00:00
|
|
|
|
|
2001-03-14 09:21:16 +00:00
|
|
|
|
if (clients.contains(c))
|
2001-12-09 04:17:36 +00:00
|
|
|
|
removeClient(c);
|
2001-03-14 09:21:16 +00:00
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
c->invalidateWindow();
|
|
|
|
|
clientHidden( c );
|
2002-03-02 21:03:49 +00:00
|
|
|
|
if ( desktops.contains(c) )
|
|
|
|
|
desktops.remove(c);
|
2000-10-02 12:02:15 +00:00
|
|
|
|
if ( c == most_recently_raised )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
most_recently_raised = 0;
|
2000-10-02 12:02:15 +00:00
|
|
|
|
if ( c == should_get_focus )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
should_get_focus = 0;
|
2000-10-02 12:02:15 +00:00
|
|
|
|
if ( c == active_client )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
active_client = 0;
|
2001-02-03 12:30:46 +00:00
|
|
|
|
if ( c == last_active_client )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
last_active_client = 0;
|
2000-05-06 18:59:43 +00:00
|
|
|
|
delete c;
|
2001-11-07 01:09:29 +00:00
|
|
|
|
|
|
|
|
|
if (tab_grab)
|
|
|
|
|
tab_box->repaint();
|
|
|
|
|
|
2000-04-26 21:28:51 +00:00
|
|
|
|
updateClientArea();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Handles alt-tab / control-tab
|
|
|
|
|
*/
|
2001-03-28 12:44:31 +00:00
|
|
|
|
|
2001-07-09 03:10:16 +00:00
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
|
|
bool areKeySymXsDepressed( bool bAll, int nKeySyms, ... )
|
|
|
|
|
{
|
2001-12-09 04:17:36 +00:00
|
|
|
|
va_list args;
|
|
|
|
|
char keymap[32];
|
2001-07-09 03:10:16 +00:00
|
|
|
|
|
2001-12-09 04:17:36 +00:00
|
|
|
|
kdDebug(125) << "areKeySymXsDepressed: " << (bAll ? "all of " : "any of ") << nKeySyms << endl;
|
2001-07-09 03:10:16 +00:00
|
|
|
|
|
2001-12-09 04:17:36 +00:00
|
|
|
|
va_start( args, nKeySyms );
|
|
|
|
|
XQueryKeymap( qt_xdisplay(), keymap );
|
2001-07-09 03:10:16 +00:00
|
|
|
|
|
2001-12-09 04:17:36 +00:00
|
|
|
|
for( int iKeySym = 0; iKeySym < nKeySyms; iKeySym++ ) {
|
|
|
|
|
uint keySymX = va_arg( args, uint );
|
|
|
|
|
uchar keyCodeX = XKeysymToKeycode( qt_xdisplay(), keySymX );
|
|
|
|
|
int i = keyCodeX / 8;
|
|
|
|
|
char mask = 1 << (keyCodeX - (i * 8));
|
2001-07-09 03:10:16 +00:00
|
|
|
|
|
2001-12-09 04:17:36 +00:00
|
|
|
|
kdDebug(125) << iKeySym << ": keySymX=0x" << QString::number( keySymX, 16 )
|
|
|
|
|
<< " i=" << i << " mask=0x" << QString::number( mask, 16 )
|
|
|
|
|
<< " keymap[i]=0x" << QString::number( keymap[i], 16 ) << endl;
|
2001-07-09 03:10:16 +00:00
|
|
|
|
|
2001-12-09 04:17:36 +00:00
|
|
|
|
// Abort if bad index value,
|
|
|
|
|
if( i < 0 || i >= 32 )
|
|
|
|
|
return false;
|
2001-07-09 03:10:16 +00:00
|
|
|
|
|
2001-12-09 04:17:36 +00:00
|
|
|
|
// If ALL keys passed need to be depressed,
|
|
|
|
|
if( bAll ) {
|
|
|
|
|
if( (keymap[i] & mask) == 0 )
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
// If we are looking for ANY key press, and this key is depressed,
|
|
|
|
|
if( keymap[i] & mask )
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-07-09 03:10:16 +00:00
|
|
|
|
|
2001-12-09 04:17:36 +00:00
|
|
|
|
// If we were looking for ANY key press, then none was found, return false,
|
|
|
|
|
// If we were looking for ALL key presses, then all were found, return true.
|
|
|
|
|
return bAll;
|
2001-07-09 03:10:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-01-19 04:55:32 +00:00
|
|
|
|
bool areModKeysDepressed( const KShortcut& cut )
|
2001-07-09 03:10:16 +00:00
|
|
|
|
{
|
2001-12-09 04:17:36 +00:00
|
|
|
|
|
2002-03-04 12:37:56 +00:00
|
|
|
|
uint rgKeySyms[10];
|
2002-01-19 04:55:32 +00:00
|
|
|
|
int nKeySyms = 0;
|
|
|
|
|
int mod = cut.seq(0).key(0).modFlags();
|
2001-12-09 04:17:36 +00:00
|
|
|
|
|
2002-01-19 04:55:32 +00:00
|
|
|
|
if ( mod & KKey::SHIFT ) {
|
|
|
|
|
rgKeySyms[nKeySyms++] = XK_Shift_L;
|
|
|
|
|
rgKeySyms[nKeySyms++] = XK_Shift_R;
|
|
|
|
|
}
|
|
|
|
|
if ( mod & KKey::CTRL ) {
|
|
|
|
|
rgKeySyms[nKeySyms++] = XK_Control_L;
|
|
|
|
|
rgKeySyms[nKeySyms++] = XK_Control_R;
|
|
|
|
|
}
|
|
|
|
|
if( mod & KKey::ALT ) {
|
|
|
|
|
rgKeySyms[nKeySyms++] = XK_Alt_L;
|
|
|
|
|
rgKeySyms[nKeySyms++] = XK_Alt_R;
|
|
|
|
|
}
|
|
|
|
|
if( mod & KKey::WIN ) {
|
2002-03-11 05:02:50 +00:00
|
|
|
|
// HACK: it would take a lot of code to determine whether the Win key
|
2002-03-04 12:37:56 +00:00
|
|
|
|
// is associated with Super or Meta, so check for both
|
|
|
|
|
rgKeySyms[nKeySyms++] = XK_Super_L;
|
|
|
|
|
rgKeySyms[nKeySyms++] = XK_Super_R;
|
2002-01-19 04:55:32 +00:00
|
|
|
|
rgKeySyms[nKeySyms++] = XK_Meta_L;
|
|
|
|
|
rgKeySyms[nKeySyms++] = XK_Meta_R;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Is there a better way to push all 8 integer onto the stack?
|
|
|
|
|
return areKeySymXsDepressed( false, nKeySyms,
|
|
|
|
|
rgKeySyms[0], rgKeySyms[1], rgKeySyms[2], rgKeySyms[3],
|
|
|
|
|
rgKeySyms[4], rgKeySyms[5], rgKeySyms[6], rgKeySyms[7] );
|
2001-07-09 03:10:16 +00:00
|
|
|
|
}
|
2001-03-28 12:44:31 +00:00
|
|
|
|
|
2001-03-19 20:05:36 +00:00
|
|
|
|
void Workspace::slotWalkThroughWindows()
|
1999-08-19 23:26:42 +00:00
|
|
|
|
{
|
|
|
|
|
if ( root != qt_xrootwin() )
|
2001-03-19 20:05:36 +00:00
|
|
|
|
return;
|
2002-01-19 04:55:32 +00:00
|
|
|
|
if ( tab_grab || control_grab )
|
2001-03-19 20:05:36 +00:00
|
|
|
|
return;
|
2001-08-07 11:15:12 +00:00
|
|
|
|
if ( options->altTabStyle == Options::CDE || !options->focusPolicyIsReasonable() ) {
|
2002-02-28 22:11:43 +00:00
|
|
|
|
//XUngrabKeyboard(qt_xdisplay(), qt_x_time); // need that because of accelerator raw mode
|
2001-03-19 20:05:36 +00:00
|
|
|
|
// CDE style raise / lower
|
|
|
|
|
CDEWalkThroughWindows( true );
|
2001-08-07 11:15:12 +00:00
|
|
|
|
} else {
|
2002-01-19 04:55:32 +00:00
|
|
|
|
if ( areModKeysDepressed( cutWalkThroughWindows ) ) {
|
2001-03-28 12:44:31 +00:00
|
|
|
|
if ( startKDEWalkThroughWindows() )
|
2001-12-09 04:17:36 +00:00
|
|
|
|
KDEWalkThroughWindows( true );
|
2001-03-19 20:05:36 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
// if the shortcut has no modifiers, don't show the tabbox, but
|
|
|
|
|
// simply go to the next window; if the shortcut has no modifiers,
|
|
|
|
|
// the only sane thing to do is to release the key immediately
|
|
|
|
|
// anyway, so the tabbox wouldn't appear anyway
|
|
|
|
|
// it's done this way without grabbing because with grabbing
|
|
|
|
|
// the keyboard wasn't ungrabbed and I really have no idea why
|
|
|
|
|
// <l.lunak@kde.org>
|
|
|
|
|
KDEOneStepThroughWindows( true );
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
2001-03-19 20:05:36 +00:00
|
|
|
|
void Workspace::slotWalkBackThroughWindows()
|
2001-03-28 12:44:31 +00:00
|
|
|
|
{
|
2001-03-19 20:05:36 +00:00
|
|
|
|
if ( root != qt_xrootwin() )
|
2001-12-09 04:17:36 +00:00
|
|
|
|
return;
|
2001-03-19 20:05:36 +00:00
|
|
|
|
if( tab_grab || control_grab )
|
2001-12-09 04:17:36 +00:00
|
|
|
|
return;
|
2001-03-28 12:44:31 +00:00
|
|
|
|
if ( options->altTabStyle == Options::CDE || !options->focusPolicyIsReasonable() ) {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
// CDE style raise / lower
|
|
|
|
|
CDEWalkThroughWindows( true );
|
2001-03-28 12:44:31 +00:00
|
|
|
|
} else {
|
2002-01-19 04:55:32 +00:00
|
|
|
|
if ( areModKeysDepressed( cutWalkThroughWindowsReverse ) ) {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
if ( startKDEWalkThroughWindows() )
|
|
|
|
|
KDEWalkThroughWindows( false );
|
|
|
|
|
} else {
|
|
|
|
|
KDEOneStepThroughWindows( false );
|
|
|
|
|
}
|
2001-03-19 20:05:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
2001-03-19 20:05:36 +00:00
|
|
|
|
void Workspace::slotWalkThroughDesktops()
|
2001-03-28 12:44:31 +00:00
|
|
|
|
{
|
2001-03-19 20:05:36 +00:00
|
|
|
|
if ( root != qt_xrootwin() )
|
2001-12-09 04:17:36 +00:00
|
|
|
|
return;
|
2001-03-19 20:05:36 +00:00
|
|
|
|
if( tab_grab || control_grab )
|
2001-12-09 04:17:36 +00:00
|
|
|
|
return;
|
2002-01-19 04:55:32 +00:00
|
|
|
|
if ( areModKeysDepressed( cutWalkThroughDesktops ) ) {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
if ( startWalkThroughDesktops() )
|
|
|
|
|
walkThroughDesktops( true );
|
2001-03-28 12:44:31 +00:00
|
|
|
|
} else {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
oneStepThroughDesktops( true );
|
2001-03-19 20:05:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2001-02-16 18:05:27 +00:00
|
|
|
|
|
2001-03-19 20:05:36 +00:00
|
|
|
|
void Workspace::slotWalkBackThroughDesktops()
|
2001-03-28 12:44:31 +00:00
|
|
|
|
{
|
2001-03-19 20:05:36 +00:00
|
|
|
|
if ( root != qt_xrootwin() )
|
|
|
|
|
return;
|
|
|
|
|
if( tab_grab || control_grab )
|
2001-12-09 04:17:36 +00:00
|
|
|
|
return;
|
2002-01-19 04:55:32 +00:00
|
|
|
|
if ( areModKeysDepressed( cutWalkThroughDesktopsReverse ) ) {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
if ( startWalkThroughDesktops() )
|
|
|
|
|
walkThroughDesktops( false );
|
2001-03-28 12:44:31 +00:00
|
|
|
|
} else {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
oneStepThroughDesktops( false );
|
2001-03-19 20:05:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-10 04:10:42 +00:00
|
|
|
|
void Workspace::slotWalkThroughDesktopList()
|
|
|
|
|
{
|
|
|
|
|
if ( root != qt_xrootwin() )
|
2001-12-09 04:17:36 +00:00
|
|
|
|
return;
|
2001-06-10 04:10:42 +00:00
|
|
|
|
if( tab_grab || control_grab )
|
2001-12-09 04:17:36 +00:00
|
|
|
|
return;
|
2002-01-19 04:55:32 +00:00
|
|
|
|
if ( areModKeysDepressed( cutWalkThroughDesktopList ) ) {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
if ( startWalkThroughDesktopList() )
|
|
|
|
|
walkThroughDesktops( true );
|
2001-06-10 04:10:42 +00:00
|
|
|
|
} else {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
oneStepThroughDesktopList( true );
|
2001-06-10 04:10:42 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Workspace::slotWalkBackThroughDesktopList()
|
|
|
|
|
{
|
|
|
|
|
if ( root != qt_xrootwin() )
|
|
|
|
|
return;
|
|
|
|
|
if( tab_grab || control_grab )
|
2001-12-09 04:17:36 +00:00
|
|
|
|
return;
|
2002-01-19 04:55:32 +00:00
|
|
|
|
if ( areModKeysDepressed( cutWalkThroughDesktopListReverse ) ) {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
if ( startWalkThroughDesktopList() )
|
|
|
|
|
walkThroughDesktops( false );
|
2001-06-10 04:10:42 +00:00
|
|
|
|
} else {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
oneStepThroughDesktopList( false );
|
2001-06-10 04:10:42 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-28 12:44:31 +00:00
|
|
|
|
bool Workspace::startKDEWalkThroughWindows()
|
2001-03-19 20:05:36 +00:00
|
|
|
|
{
|
|
|
|
|
if ( XGrabPointer( qt_xdisplay(), root, TRUE,
|
2001-12-09 04:17:36 +00:00
|
|
|
|
(uint)(ButtonPressMask | ButtonReleaseMask |
|
|
|
|
|
ButtonMotionMask | EnterWindowMask |
|
|
|
|
|
LeaveWindowMask | PointerMotionMask),
|
|
|
|
|
GrabModeAsync, GrabModeAsync,
|
2002-02-28 22:11:43 +00:00
|
|
|
|
None, None, qt_x_time ) != GrabSuccess ) {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
return FALSE;
|
2001-03-19 20:05:36 +00:00
|
|
|
|
}
|
2001-06-18 20:18:32 +00:00
|
|
|
|
if ( XGrabKeyboard(qt_xdisplay(),
|
2001-12-09 04:17:36 +00:00
|
|
|
|
root, FALSE,
|
|
|
|
|
GrabModeAsync, GrabModeAsync,
|
2002-02-28 22:11:43 +00:00
|
|
|
|
qt_x_time) != GrabSuccess ) {
|
|
|
|
|
XUngrabPointer( qt_xdisplay(), qt_x_time);
|
2001-12-09 04:17:36 +00:00
|
|
|
|
return FALSE;
|
2001-06-18 20:18:32 +00:00
|
|
|
|
}
|
2001-03-19 20:05:36 +00:00
|
|
|
|
tab_grab = TRUE;
|
2002-01-19 04:55:32 +00:00
|
|
|
|
keys->setEnabled( false );
|
2001-03-19 20:05:36 +00:00
|
|
|
|
tab_box->setMode( TabBox::WindowsMode );
|
|
|
|
|
tab_box->reset();
|
2001-03-28 12:44:31 +00:00
|
|
|
|
return TRUE;
|
2001-03-19 20:05:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-06-10 04:10:42 +00:00
|
|
|
|
bool Workspace::startWalkThroughDesktops( int mode )
|
2001-03-19 20:05:36 +00:00
|
|
|
|
{
|
|
|
|
|
if ( XGrabPointer( qt_xdisplay(), root, TRUE,
|
2001-12-09 04:17:36 +00:00
|
|
|
|
(uint)(ButtonPressMask | ButtonReleaseMask |
|
|
|
|
|
ButtonMotionMask | EnterWindowMask |
|
|
|
|
|
LeaveWindowMask | PointerMotionMask),
|
|
|
|
|
GrabModeAsync, GrabModeAsync,
|
2002-02-28 22:11:43 +00:00
|
|
|
|
None, None, qt_x_time ) != GrabSuccess ) {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
return FALSE;
|
2001-03-19 20:05:36 +00:00
|
|
|
|
}
|
2001-06-18 20:18:32 +00:00
|
|
|
|
if ( XGrabKeyboard(qt_xdisplay(),
|
2001-12-09 04:17:36 +00:00
|
|
|
|
root, FALSE,
|
|
|
|
|
GrabModeAsync, GrabModeAsync,
|
2002-02-28 22:11:43 +00:00
|
|
|
|
qt_x_time) != GrabSuccess ) {
|
|
|
|
|
XUngrabPointer( qt_xdisplay(), qt_x_time);
|
2001-12-09 04:17:36 +00:00
|
|
|
|
return FALSE;
|
2001-06-18 20:18:32 +00:00
|
|
|
|
}
|
2001-03-19 20:05:36 +00:00
|
|
|
|
control_grab = TRUE;
|
2002-01-19 04:55:32 +00:00
|
|
|
|
keys->setEnabled( false );
|
2001-06-10 04:10:42 +00:00
|
|
|
|
tab_box->setMode( (TabBox::Mode) mode );
|
2001-03-19 20:05:36 +00:00
|
|
|
|
tab_box->reset();
|
2001-03-28 12:44:31 +00:00
|
|
|
|
return TRUE;
|
2001-03-19 20:05:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-06-10 04:10:42 +00:00
|
|
|
|
bool Workspace::startWalkThroughDesktops()
|
|
|
|
|
{
|
|
|
|
|
return startWalkThroughDesktops( TabBox::DesktopMode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Workspace::startWalkThroughDesktopList()
|
|
|
|
|
{
|
|
|
|
|
return startWalkThroughDesktops( TabBox::DesktopListMode );
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-19 20:05:36 +00:00
|
|
|
|
void Workspace::KDEWalkThroughWindows( bool forward )
|
|
|
|
|
{
|
|
|
|
|
tab_box->nextPrev( forward );
|
|
|
|
|
tab_box->delayedShow();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Workspace::walkThroughDesktops( bool forward )
|
|
|
|
|
{
|
|
|
|
|
tab_box->nextPrev( forward );
|
|
|
|
|
tab_box->delayedShow();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Workspace::CDEWalkThroughWindows( bool forward )
|
2002-07-26 06:26:35 +00:00
|
|
|
|
{
|
2001-03-19 20:05:36 +00:00
|
|
|
|
Client* c = topClientOnDesktop();
|
|
|
|
|
Client* nc = c;
|
|
|
|
|
if ( !forward ){
|
|
|
|
|
do {
|
|
|
|
|
nc = previousStaticClient(nc);
|
|
|
|
|
} while (nc && nc != c &&
|
|
|
|
|
(!nc->isOnDesktop(currentDesktop()) ||
|
|
|
|
|
nc->isIconified() || !nc->wantsTabFocus() ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
do {
|
|
|
|
|
nc = nextStaticClient(nc);
|
|
|
|
|
} while (nc && nc != c &&
|
|
|
|
|
(!nc->isOnDesktop(currentDesktop()) ||
|
|
|
|
|
nc->isIconified() || !nc->wantsTabFocus() ) );
|
|
|
|
|
if (c && c != nc)
|
|
|
|
|
lowerClient( c );
|
|
|
|
|
if (nc) {
|
|
|
|
|
if ( options->focusPolicyIsReasonable() )
|
|
|
|
|
activateClient( nc );
|
|
|
|
|
else
|
|
|
|
|
raiseClient( nc );
|
|
|
|
|
}
|
2002-07-26 06:26:35 +00:00
|
|
|
|
}
|
2001-03-28 12:44:31 +00:00
|
|
|
|
|
2001-03-19 20:05:36 +00:00
|
|
|
|
void Workspace::KDEOneStepThroughWindows( bool forward )
|
|
|
|
|
{
|
|
|
|
|
tab_box->setMode( TabBox::WindowsMode );
|
|
|
|
|
tab_box->reset();
|
|
|
|
|
tab_box->nextPrev( forward );
|
|
|
|
|
if ( tab_box->currentClient() ){
|
|
|
|
|
activateClient( tab_box->currentClient() );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-10 04:10:42 +00:00
|
|
|
|
void Workspace::oneStepThroughDesktops( bool forward, int mode )
|
2001-03-19 20:05:36 +00:00
|
|
|
|
{
|
2001-06-10 04:10:42 +00:00
|
|
|
|
tab_box->setMode( (TabBox::Mode) mode );
|
2001-03-19 20:05:36 +00:00
|
|
|
|
tab_box->reset();
|
|
|
|
|
tab_box->nextPrev( forward );
|
|
|
|
|
if ( tab_box->currentDesktop() != -1 )
|
|
|
|
|
setCurrentDesktop( tab_box->currentDesktop() );
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-10 04:10:42 +00:00
|
|
|
|
void Workspace::oneStepThroughDesktops( bool forward )
|
|
|
|
|
{
|
|
|
|
|
oneStepThroughDesktops( forward, TabBox::DesktopMode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Workspace::oneStepThroughDesktopList( bool forward )
|
|
|
|
|
{
|
|
|
|
|
oneStepThroughDesktops( forward, TabBox::DesktopListMode );
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-19 20:05:36 +00:00
|
|
|
|
/*!
|
|
|
|
|
Handles holding alt-tab / control-tab
|
|
|
|
|
*/
|
2002-01-19 04:55:32 +00:00
|
|
|
|
bool Workspace::keyPress(XKeyEvent& ev)
|
2001-03-19 20:05:36 +00:00
|
|
|
|
{
|
|
|
|
|
if ( root != qt_xrootwin() )
|
|
|
|
|
return FALSE;
|
2001-06-03 22:29:12 +00:00
|
|
|
|
|
2002-01-19 04:55:32 +00:00
|
|
|
|
KKeyNative keyX( (XEvent*)&ev );
|
2001-12-29 04:19:24 +00:00
|
|
|
|
uint keyQt = keyX.keyCodeQt();
|
|
|
|
|
|
2002-01-19 04:55:32 +00:00
|
|
|
|
kdDebug(125) << "Workspace::keyPress( " << keyX.key().toString() << " )" << endl;
|
2001-09-06 22:54:31 +00:00
|
|
|
|
if (d->movingClient)
|
|
|
|
|
{
|
2002-03-03 12:39:31 +00:00
|
|
|
|
d->movingClient->keyPressEvent(keyQt);
|
2001-09-06 22:54:31 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2001-06-03 22:29:12 +00:00
|
|
|
|
|
2001-11-30 08:04:17 +00:00
|
|
|
|
if (tab_grab){
|
2002-01-19 04:55:32 +00:00
|
|
|
|
bool forward = cutWalkThroughWindows.contains( keyX );
|
|
|
|
|
bool backward = cutWalkThroughWindowsReverse.contains( keyX );
|
2001-12-29 04:19:24 +00:00
|
|
|
|
if (forward || backward){
|
2002-01-19 04:55:32 +00:00
|
|
|
|
kdDebug(125) << "== " << cutWalkThroughWindows.toString()
|
|
|
|
|
<< " or " << cutWalkThroughWindowsReverse.toString() << endl;
|
2001-12-29 04:19:24 +00:00
|
|
|
|
KDEWalkThroughWindows( forward );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
}
|
2000-12-17 21:57:52 +00:00
|
|
|
|
}
|
2001-12-29 04:19:24 +00:00
|
|
|
|
else if (control_grab){
|
2002-01-19 04:55:32 +00:00
|
|
|
|
bool forward = cutWalkThroughDesktops.contains( keyX ) ||
|
|
|
|
|
cutWalkThroughDesktopList.contains( keyX );
|
|
|
|
|
bool backward = cutWalkThroughDesktopsReverse.contains( keyX ) ||
|
|
|
|
|
cutWalkThroughDesktopListReverse.contains( keyX );
|
2001-12-29 04:19:24 +00:00
|
|
|
|
if (forward || backward)
|
|
|
|
|
walkThroughDesktops(forward);
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (control_grab || tab_grab){
|
2001-12-29 04:19:24 +00:00
|
|
|
|
if ((keyQt & 0xffff) == Qt::Key_Escape){
|
2002-02-28 22:11:43 +00:00
|
|
|
|
XUngrabKeyboard(qt_xdisplay(), qt_x_time);
|
|
|
|
|
XUngrabPointer( qt_xdisplay(), qt_x_time);
|
2001-02-16 18:05:27 +00:00
|
|
|
|
tab_box->hide();
|
2002-01-19 04:55:32 +00:00
|
|
|
|
keys->setEnabled( true );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
tab_grab = FALSE;
|
|
|
|
|
control_grab = FALSE;
|
|
|
|
|
}
|
2001-06-18 20:18:32 +00:00
|
|
|
|
return TRUE;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
2001-03-19 20:05:36 +00:00
|
|
|
|
Handles alt-tab / control-tab releasing
|
1999-08-19 23:26:42 +00:00
|
|
|
|
*/
|
2002-01-19 04:55:32 +00:00
|
|
|
|
bool Workspace::keyRelease(XKeyEvent& ev)
|
1999-08-19 23:26:42 +00:00
|
|
|
|
{
|
|
|
|
|
if ( root != qt_xrootwin() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return FALSE;
|
2001-03-19 20:05:36 +00:00
|
|
|
|
if( !tab_grab && !control_grab )
|
|
|
|
|
return FALSE;
|
2002-01-19 04:55:32 +00:00
|
|
|
|
unsigned int mk = ev.state &
|
2001-12-29 04:19:24 +00:00
|
|
|
|
(KKeyNative::modX(KKey::SHIFT) |
|
|
|
|
|
KKeyNative::modX(KKey::CTRL) |
|
|
|
|
|
KKeyNative::modX(KKey::ALT) |
|
|
|
|
|
KKeyNative::modX(KKey::WIN));
|
2002-01-19 04:55:32 +00:00
|
|
|
|
// ev.state is state before the key release, so just checking mk being 0 isn't enough
|
2001-03-19 20:05:36 +00:00
|
|
|
|
// using XQueryPointer() also doesn't seem to work well, so the check that all
|
2001-12-29 04:19:24 +00:00
|
|
|
|
// modifiers are released: only one modifier is active and the currently released
|
2001-03-19 20:05:36 +00:00
|
|
|
|
// key is this modifier - if yes, release the grab
|
|
|
|
|
int mod_index = -1;
|
|
|
|
|
for( int i = ShiftMapIndex;
|
|
|
|
|
i <= Mod5MapIndex;
|
|
|
|
|
++i )
|
|
|
|
|
if(( mk & ( 1 << i )) != 0 ) {
|
|
|
|
|
if( mod_index >= 0 )
|
|
|
|
|
return FALSE;
|
|
|
|
|
mod_index = i;
|
|
|
|
|
}
|
|
|
|
|
bool release = false;
|
|
|
|
|
if( mod_index == -1 )
|
|
|
|
|
release = true;
|
|
|
|
|
else {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
XModifierKeymap* xmk = XGetModifierMapping(qt_xdisplay());
|
2001-03-19 20:05:36 +00:00
|
|
|
|
for (int i=0; i<xmk->max_keypermod; i++)
|
|
|
|
|
if (xmk->modifiermap[xmk->max_keypermod * mod_index + i]
|
2002-01-19 04:55:32 +00:00
|
|
|
|
== ev.keycode)
|
2001-03-19 20:05:36 +00:00
|
|
|
|
release = true;
|
|
|
|
|
XFreeModifiermap(xmk);
|
|
|
|
|
}
|
|
|
|
|
if( !release )
|
|
|
|
|
return FALSE;
|
|
|
|
|
if (tab_grab){
|
2002-02-28 22:11:43 +00:00
|
|
|
|
XUngrabPointer( qt_xdisplay(), qt_x_time);
|
|
|
|
|
XUngrabKeyboard(qt_xdisplay(), qt_x_time);
|
2001-02-16 18:05:27 +00:00
|
|
|
|
tab_box->hide();
|
2002-01-19 04:55:32 +00:00
|
|
|
|
keys->setEnabled( true );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
tab_grab = false;
|
|
|
|
|
if ( tab_box->currentClient() ){
|
|
|
|
|
activateClient( tab_box->currentClient() );
|
|
|
|
|
}
|
2000-12-17 21:57:52 +00:00
|
|
|
|
}
|
2001-03-19 20:05:36 +00:00
|
|
|
|
if (control_grab){
|
2002-02-28 22:11:43 +00:00
|
|
|
|
XUngrabPointer( qt_xdisplay(), qt_x_time);
|
|
|
|
|
XUngrabKeyboard(qt_xdisplay(), qt_x_time);
|
2001-02-16 18:05:27 +00:00
|
|
|
|
tab_box->hide();
|
2002-01-19 04:55:32 +00:00
|
|
|
|
keys->setEnabled( true );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
control_grab = False;
|
2002-04-05 19:54:21 +00:00
|
|
|
|
if ( tab_box->currentDesktop() != -1 ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
setCurrentDesktop( tab_box->currentDesktop() );
|
2002-04-05 19:54:21 +00:00
|
|
|
|
// popupinfo->showInfo( desktopName(currentDesktop()) ); // AK - not sure
|
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2001-07-09 03:10:16 +00:00
|
|
|
|
//#undef XMODMASK
|
2001-03-19 20:05:36 +00:00
|
|
|
|
|
2001-06-10 04:10:42 +00:00
|
|
|
|
int Workspace::nextDesktop( int iDesktop ) const
|
|
|
|
|
{
|
2001-12-09 04:17:36 +00:00
|
|
|
|
int i = desktop_focus_chain.find( iDesktop );
|
|
|
|
|
if( i >= 0 && i+1 < (int)desktop_focus_chain.size() )
|
|
|
|
|
return desktop_focus_chain[i+1];
|
|
|
|
|
else if( desktop_focus_chain.size() > 0 )
|
|
|
|
|
return desktop_focus_chain[ 0 ];
|
|
|
|
|
else
|
|
|
|
|
return 1;
|
2001-06-10 04:10:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Workspace::previousDesktop( int iDesktop ) const
|
|
|
|
|
{
|
2001-12-09 04:17:36 +00:00
|
|
|
|
int i = desktop_focus_chain.find( iDesktop );
|
|
|
|
|
if( i-1 >= 0 )
|
|
|
|
|
return desktop_focus_chain[i-1];
|
|
|
|
|
else if( desktop_focus_chain.size() > 0 )
|
|
|
|
|
return desktop_focus_chain[desktop_focus_chain.size()-1];
|
|
|
|
|
else
|
|
|
|
|
return numberOfDesktops();
|
2001-06-10 04:10:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-03-02 21:03:49 +00:00
|
|
|
|
void Workspace::circulateDesktopApplications()
|
|
|
|
|
{
|
|
|
|
|
if ( desktops.count() <= 1 )
|
2002-03-03 13:56:55 +00:00
|
|
|
|
return;
|
2002-03-02 21:03:49 +00:00
|
|
|
|
Client* first = desktops.first();
|
|
|
|
|
desktops.remove( first );
|
|
|
|
|
desktops.append( first );
|
|
|
|
|
Window* new_stack = new Window[ desktops.count() + 1 ];
|
|
|
|
|
int i = 0;
|
|
|
|
|
for ( ClientList::ConstIterator it = desktops.fromLast(); it != desktops.end(); --it)
|
2002-03-03 13:56:55 +00:00
|
|
|
|
new_stack[i++] = (*it)->winId();
|
2002-03-02 21:03:49 +00:00
|
|
|
|
XRestackWindows(qt_xdisplay(), new_stack, i);
|
|
|
|
|
delete [] new_stack;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Workspace::addClient( Client* c )
|
|
|
|
|
{
|
|
|
|
|
if ( c->isDesktop() ) {
|
2002-03-03 13:56:55 +00:00
|
|
|
|
if ( !desktops.isEmpty() ) {
|
|
|
|
|
Client* first = desktops.first();
|
|
|
|
|
Window stack[2];
|
|
|
|
|
stack[0] = first->winId();
|
|
|
|
|
stack[1] = c->winId();
|
|
|
|
|
XRestackWindows( qt_xdisplay(), stack, 2 );
|
|
|
|
|
desktops.prepend( c );
|
|
|
|
|
circulateDesktopApplications();
|
|
|
|
|
} else {
|
|
|
|
|
c->lower();
|
|
|
|
|
desktops.append( c );
|
|
|
|
|
}
|
2002-03-02 21:03:49 +00:00
|
|
|
|
} else {
|
2002-03-03 13:56:55 +00:00
|
|
|
|
if ( c->wantsTabFocus() )
|
|
|
|
|
focus_chain.append( c );
|
|
|
|
|
clients.append( c );
|
|
|
|
|
stacking_order.append( c );
|
2002-03-02 21:03:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
/*!
|
|
|
|
|
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() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return 0;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
ClientList::ConstIterator it = focus_chain.find( c );
|
|
|
|
|
if ( it == focus_chain.end() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return focus_chain.last();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
if ( it == focus_chain.begin() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return focus_chain.last();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
--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() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return 0;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
ClientList::ConstIterator it = focus_chain.find( c );
|
|
|
|
|
if ( it == focus_chain.end() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return focus_chain.first();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
++it;
|
|
|
|
|
if ( it == focus_chain.end() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return focus_chain.first();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
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
|
|
|
|
|
{
|
2002-07-26 06:26:35 +00:00
|
|
|
|
if ( !c || clients.isEmpty() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return 0;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
ClientList::ConstIterator it = clients.find( c );
|
|
|
|
|
if ( it == clients.end() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return clients.first();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
++it;
|
|
|
|
|
if ( it == clients.end() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return clients.first();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
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
|
|
|
|
|
{
|
2002-07-26 06:26:35 +00:00
|
|
|
|
if ( !c || clients.isEmpty() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return 0;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
ClientList::ConstIterator it = clients.find( c );
|
|
|
|
|
if ( it == clients.end() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return clients.last();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
if ( it == clients.begin() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return clients.last();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
--it;
|
|
|
|
|
return *it;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-06-23 16:26:44 +00:00
|
|
|
|
/*!
|
2000-07-13 17:59:12 +00:00
|
|
|
|
Returns topmost visible client. Windows on the dock, the desktop
|
|
|
|
|
or of any other special kind are excluded.
|
1999-08-19 23:26:42 +00:00
|
|
|
|
*/
|
2000-06-22 18:08:35 +00:00
|
|
|
|
Client* Workspace::topClientOnDesktop() const
|
1999-08-19 23:26:42 +00:00
|
|
|
|
{
|
2000-10-04 15:19:44 +00:00
|
|
|
|
if ( most_recently_raised && stacking_order.contains( most_recently_raised ) &&
|
2001-02-16 18:05:27 +00:00
|
|
|
|
most_recently_raised->isVisible() )
|
|
|
|
|
return most_recently_raised;
|
2000-10-04 15:19:44 +00:00
|
|
|
|
|
2000-06-22 18:08:35 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( !(*it)->isDesktop() && (*it)->isVisible() && (*it)->wantsTabFocus() )
|
|
|
|
|
return *it;
|
2000-06-22 18:08:35 +00:00
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
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 )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if( popup )
|
|
|
|
|
popup->close();
|
2001-09-06 09:21:19 +00:00
|
|
|
|
if ( active_client ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
active_client->setActive( FALSE );
|
2001-12-09 04:17:36 +00:00
|
|
|
|
if ( active_client->isFullScreen() && active_client->staysOnTop()
|
|
|
|
|
&& c && c->mainClient() != active_client->mainClient() ) {
|
|
|
|
|
active_client->setStaysOnTop( FALSE );
|
|
|
|
|
lowerClient( active_client );
|
|
|
|
|
}
|
2001-09-06 09:21:19 +00:00
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
active_client = c;
|
2001-02-03 12:30:46 +00:00
|
|
|
|
last_active_client = active_client;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
if ( active_client ) {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
if ( active_client->isFullScreen() && !active_client->staysOnTop() ) {
|
|
|
|
|
active_client->setStaysOnTop( TRUE );
|
|
|
|
|
raiseClient( active_client );
|
|
|
|
|
}
|
|
|
|
|
focus_chain.remove( c );
|
|
|
|
|
if ( c->wantsTabFocus() )
|
|
|
|
|
focus_chain.append( c );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
2000-07-11 12:15:58 +00:00
|
|
|
|
|
2000-07-10 15:54:17 +00:00
|
|
|
|
// toplevel menubar handling
|
|
|
|
|
Client* main = 0;
|
|
|
|
|
if ( active_client )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
main = active_client->mainClient();
|
2000-07-10 15:54:17 +00:00
|
|
|
|
|
|
|
|
|
// show the new menu bar first...
|
|
|
|
|
Client* menubar = 0;
|
2002-05-23 23:57:47 +00:00
|
|
|
|
bool has_full_screen = false;
|
2000-07-10 15:54:17 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
2002-07-05 20:05:22 +00:00
|
|
|
|
if ( (*it)->isTopMenu() && (*it)->mainClient() == main ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
menubar = *it;
|
2002-05-23 23:57:47 +00:00
|
|
|
|
}
|
|
|
|
|
if ( (*it)->isVisible() && (*it)->isFullScreen() &&
|
|
|
|
|
!(*it)->isDesktop() && (*it)->staysOnTop() ) {
|
|
|
|
|
has_full_screen = true;
|
2001-02-16 18:05:27 +00:00
|
|
|
|
}
|
2000-07-10 15:54:17 +00:00
|
|
|
|
}
|
2002-05-23 23:57:47 +00:00
|
|
|
|
if ( !menubar && !has_full_screen)
|
2002-04-08 23:43:19 +00:00
|
|
|
|
{
|
2002-05-23 23:57:47 +00:00
|
|
|
|
// Find the menubar of the desktop
|
2002-07-07 18:54:20 +00:00
|
|
|
|
if ( !desktops.isEmpty() ) {
|
2002-04-08 23:43:19 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
2002-07-07 18:54:20 +00:00
|
|
|
|
if ( (*it)->isTopMenu() && (*it)->mainClient()->isDesktop() ) {
|
2002-04-08 23:43:19 +00:00
|
|
|
|
menubar = *it;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-07-07 18:54:20 +00:00
|
|
|
|
#if 0 // I don't like this - why to show a menubar belonging to another application?
|
|
|
|
|
// either show the app's menubar, or the desktop's one, otherwise none at all
|
2002-04-08 23:43:19 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
2002-07-07 18:54:20 +00:00
|
|
|
|
if ( (*it)->isTopMenu() && (*it)->mainClient() == (*it)
|
|
|
|
|
&& (*it)->isOnDesktop( currentDesktop())) {
|
2002-04-08 23:43:19 +00:00
|
|
|
|
menubar = *it;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-02-16 18:05:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-07-07 18:54:20 +00:00
|
|
|
|
#endif
|
2000-07-10 15:54:17 +00:00
|
|
|
|
}
|
2000-07-11 12:15:58 +00:00
|
|
|
|
|
2000-07-10 15:54:17 +00:00
|
|
|
|
if ( menubar ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
menubar->show();
|
|
|
|
|
menubar->raise(); // better for FocusFollowsMouse than raiseClient(menubar)
|
2001-08-27 05:42:32 +00:00
|
|
|
|
raiseElectricBorders();
|
2000-07-10 15:54:17 +00:00
|
|
|
|
}
|
2000-07-11 12:15:58 +00:00
|
|
|
|
|
2000-07-10 15:54:17 +00:00
|
|
|
|
// ... then hide the other ones. Avoids flickers.
|
2002-07-05 20:08:17 +00:00
|
|
|
|
// Leave the desktop menubars always visible. Helps visually when the app doesn't show
|
|
|
|
|
// its menubar immediately.
|
2000-07-10 15:54:17 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
2002-07-05 20:08:17 +00:00
|
|
|
|
if ( (*it)->isTopMenu() && (*it) != menubar && !(*it)->mainClient()->isDesktop() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
(*it)->hide();
|
2000-07-10 15:54:17 +00:00
|
|
|
|
}
|
2000-06-21 17:43:44 +00:00
|
|
|
|
|
2000-06-08 17:05:51 +00:00
|
|
|
|
rootInfo->setActiveWindow( active_client? active_client->window() : 0 );
|
2000-08-30 14:27:30 +00:00
|
|
|
|
updateColormap();
|
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.
|
|
|
|
|
|
2001-01-13 14:57:16 +00:00
|
|
|
|
\sa stActiveClient(), requestFocus()
|
1999-08-19 23:26:42 +00:00
|
|
|
|
*/
|
2000-09-11 20:54:00 +00:00
|
|
|
|
void Workspace::activateClient( Client* c, bool force )
|
1999-08-19 23:26:42 +00:00
|
|
|
|
{
|
|
|
|
|
raiseClient( c );
|
2000-05-07 20:38:11 +00:00
|
|
|
|
if ( c->isIconified() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
Events::raise( Events::DeIconify );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
c->show();
|
1999-11-28 20:10:58 +00:00
|
|
|
|
iconifyOrDeiconifyTransientsOf( c );
|
2000-08-31 17:15:10 +00:00
|
|
|
|
if ( options->focusPolicyIsReasonable() ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
requestFocus( c, force );
|
2000-08-31 17:15:10 +00:00
|
|
|
|
}
|
2001-01-13 14:57:16 +00:00
|
|
|
|
|
|
|
|
|
if (!c->isOnDesktop(currentDesktop()) ) {
|
|
|
|
|
setCurrentDesktop( c->desktop() );
|
2002-04-05 19:54:21 +00:00
|
|
|
|
// popupinfo->showInfo( desktopName(currentDesktop()) ); // AK - not sure
|
2001-01-13 14:57:16 +00:00
|
|
|
|
}
|
2002-02-28 22:11:43 +00:00
|
|
|
|
c->updateUserTime();
|
2001-09-06 09:21:19 +00:00
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-11-28 20:10:58 +00:00
|
|
|
|
void Workspace::iconifyOrDeiconifyTransientsOf( Client* c )
|
|
|
|
|
{
|
1999-11-28 20:17:57 +00:00
|
|
|
|
if ( c->isIconified() || c->isShade() ) {
|
2002-07-05 20:05:22 +00:00
|
|
|
|
bool exclude_topmenu = !c->isIconified();
|
2001-02-16 18:05:27 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
|
|
|
|
if ( (*it)->transientFor() == c->window()
|
|
|
|
|
&& !(*it)->isIconified()
|
|
|
|
|
&& !(*it)->isShade()
|
2002-07-05 20:05:22 +00:00
|
|
|
|
&& ( !exclude_topmenu || !(*it)->isTopMenu() ) ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
(*it)->setMappingState( XIconicState );
|
|
|
|
|
(*it)->hide();
|
|
|
|
|
iconifyOrDeiconifyTransientsOf( (*it) );
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-11-28 20:10:58 +00:00
|
|
|
|
} else {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
|
|
|
|
if ( (*it)->transientFor() == c->window() && !(*it)->isVisible() ) {
|
|
|
|
|
(*it)->show();
|
|
|
|
|
iconifyOrDeiconifyTransientsOf( (*it) );
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-11-28 20:10:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
2000-01-10 03:47:30 +00:00
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Sets the client \a c's transient windows' sticky property to \a sticky.
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::setStickyTransientsOf( Client* c, bool sticky )
|
|
|
|
|
{
|
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( (*it)->transientFor() == c->window() && (*it)->isSticky() != sticky )
|
|
|
|
|
(*it)->setSticky( sticky );
|
2000-01-10 03:47:30 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-28 20:55:52 +00:00
|
|
|
|
/*!
|
|
|
|
|
Returns whether a client with the specified \a caption exists, or not.
|
|
|
|
|
*/
|
|
|
|
|
bool Workspace::hasCaption( const QString& caption )
|
|
|
|
|
{
|
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( (*it)->caption() == caption )
|
|
|
|
|
return TRUE;
|
1999-11-28 20:55:52 +00:00
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
/*!
|
|
|
|
|
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()
|
|
|
|
|
*/
|
2000-09-11 20:54:00 +00:00
|
|
|
|
void Workspace::requestFocus( Client* c, bool force )
|
1999-08-19 23:26:42 +00:00
|
|
|
|
{
|
2001-02-01 01:13:44 +00:00
|
|
|
|
if (!focusChangeEnabled() && ( c != active_client) )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
2000-07-14 19:56:47 +00:00
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
//TODO will be different for non-root clients. (subclassing?)
|
|
|
|
|
if ( !c ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
focusToNull();
|
|
|
|
|
return;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
1999-11-29 14:19:32 +00:00
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
if ( c->isVisible() && !c->isShade() ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c->takeFocus( force );
|
|
|
|
|
should_get_focus = c;
|
|
|
|
|
focus_chain.remove( c );
|
|
|
|
|
if ( c->wantsTabFocus() )
|
|
|
|
|
focus_chain.append( c );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
} else if ( c->isShade() ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
// client cannot accept focus, but at least the window should be active (window menu, et. al. )
|
|
|
|
|
focusToNull();
|
|
|
|
|
if ( c->wantsInput() )
|
|
|
|
|
c->setActive( TRUE );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-08-30 14:27:30 +00:00
|
|
|
|
/*!
|
|
|
|
|
Updates the current colormap according to the currently active client
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::updateColormap()
|
|
|
|
|
{
|
|
|
|
|
Colormap cmap = default_colormap;
|
|
|
|
|
if ( activeClient() && activeClient()->colormap() != None )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
cmap = activeClient()->colormap();
|
2000-08-30 14:27:30 +00:00
|
|
|
|
if ( cmap != installed_colormap ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
XInstallColormap(qt_xdisplay(), cmap );
|
|
|
|
|
installed_colormap = cmap;
|
2000-08-30 14:27:30 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
/*!
|
|
|
|
|
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 )
|
|
|
|
|
{
|
2000-07-08 13:35:59 +00:00
|
|
|
|
if ( c != active_client && ( active_client || c != should_get_focus ) )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
2000-07-09 20:29:53 +00:00
|
|
|
|
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if( popup )
|
|
|
|
|
popup->close();
|
2000-07-08 13:35:59 +00:00
|
|
|
|
active_client = 0;
|
|
|
|
|
should_get_focus = 0;
|
2001-03-12 18:03:17 +00:00
|
|
|
|
c->setActive( FALSE ); // clear the state in the client
|
2000-09-19 18:57:15 +00:00
|
|
|
|
if (!block_focus ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( c->wantsTabFocus() && focus_chain.contains( c ) ) {
|
|
|
|
|
focus_chain.remove( c );
|
|
|
|
|
focus_chain.prepend( c );
|
|
|
|
|
}
|
|
|
|
|
if ( options->focusPolicyIsReasonable() && !focus_chain.isEmpty() ) {
|
|
|
|
|
for (ClientList::ConstIterator it = focus_chain.fromLast();
|
|
|
|
|
it != focus_chain.end();
|
|
|
|
|
--it) {
|
|
|
|
|
if ((*it)->isVisible()) {
|
|
|
|
|
requestFocus(*it);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-03-03 13:56:55 +00:00
|
|
|
|
if ( !c->isDesktop() && !desktops.isEmpty() )
|
|
|
|
|
requestFocus( desktops.last() );
|
|
|
|
|
else
|
|
|
|
|
focusToNull();
|
2002-03-02 21:03:49 +00:00
|
|
|
|
} else {
|
2002-03-03 13:56:55 +00:00
|
|
|
|
// if blocking focus, move focus to the desktop later if needed
|
|
|
|
|
// in order to avoid flickering
|
|
|
|
|
focusToNull();
|
2002-03-02 21:03:49 +00:00
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-08-06 07:45:29 +00:00
|
|
|
|
// KDE4 - remove the unused argument
|
|
|
|
|
QPopupMenu* Workspace::clientPopup( Client* )
|
1999-08-19 23:26:42 +00:00
|
|
|
|
{
|
|
|
|
|
if ( !popup ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
popup = new QPopupMenu;
|
|
|
|
|
popup->setCheckable( TRUE );
|
|
|
|
|
popup->setFont(KGlobalSettings::menuFont());
|
|
|
|
|
connect( popup, SIGNAL( aboutToShow() ), this, SLOT( clientPopupAboutToShow() ) );
|
|
|
|
|
connect( popup, SIGNAL( activated(int) ), this, SLOT( clientPopupActivated(int) ) );
|
2000-03-24 22:23:02 +00:00
|
|
|
|
|
2001-05-10 17:54:57 +00:00
|
|
|
|
// PluginMenu *deco = new PluginMenu(mgr, popup);
|
|
|
|
|
// deco->setFont(KGlobalSettings::menuFont());
|
1999-09-27 16:02:44 +00:00
|
|
|
|
|
2001-12-29 04:19:24 +00:00
|
|
|
|
popup->insertItem( SmallIconSet( "move" ), i18n("&Move")+'\t'+keys->shortcut("Window Move").toString(), Options::MoveOp );
|
|
|
|
|
popup->insertItem( i18n("&Size")+'\t'+keys->shortcut("Window Resize").toString(), Options::ResizeOp );
|
|
|
|
|
popup->insertItem( i18n("Mi&nimize")+'\t'+keys->shortcut("Window Minimize").toString(), Options::IconifyOp );
|
|
|
|
|
popup->insertItem( i18n("Ma&ximize")+'\t'+keys->shortcut("Window Maximize").toString(), Options::MaximizeOp );
|
|
|
|
|
popup->insertItem( i18n("Sh&ade")+'\t'+keys->shortcut("Window Shade").toString(), Options::ShadeOp );
|
2001-09-21 09:32:44 +00:00
|
|
|
|
popup->insertItem( SmallIconSet( "attach" ), i18n("Always &on Top"), Options::StaysOnTopOp );
|
2001-05-05 18:28:41 +00:00
|
|
|
|
popup->insertItem( SmallIconSet( "filesave" ), i18n("Sto&re Settings"), Options::ToggleStoreSettingsOp );
|
2000-03-21 20:02:27 +00:00
|
|
|
|
|
2001-02-16 18:05:27 +00:00
|
|
|
|
popup->insertSeparator();
|
2000-03-21 20:02:27 +00:00
|
|
|
|
|
2002-04-07 02:22:25 +00:00
|
|
|
|
popup->insertItem(SmallIconSet( "configure" ), i18n("Configur&e..."), this, SLOT( configureWM() ));
|
2000-03-21 20:02:27 +00:00
|
|
|
|
|
2001-02-16 18:05:27 +00:00
|
|
|
|
popup->insertSeparator();
|
2000-03-21 20:02:27 +00:00
|
|
|
|
|
2002-05-29 21:28:57 +00:00
|
|
|
|
popup->insertItem( SmallIconSet( "fileclose" ), i18n("&Close")+'\t'+keys->shortcut("Window Close").toString(), Options::CloseOp );
|
1999-11-22 01:57:51 +00:00
|
|
|
|
}
|
|
|
|
|
return popup;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-11 19:49:38 +00:00
|
|
|
|
void Workspace::initDesktopPopup()
|
|
|
|
|
{
|
|
|
|
|
if (desk_popup)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
desk_popup = new QPopupMenu( popup );
|
|
|
|
|
desk_popup->setCheckable( TRUE );
|
|
|
|
|
desk_popup->setFont(KGlobalSettings::menuFont());
|
2002-06-29 06:31:33 +00:00
|
|
|
|
connect( desk_popup, SIGNAL( activated(int) ),
|
2002-06-11 19:49:38 +00:00
|
|
|
|
this, SLOT( sendToDesktop(int) ) );
|
2002-06-29 06:31:33 +00:00
|
|
|
|
connect( desk_popup, SIGNAL( aboutToShow() ),
|
2002-06-11 19:49:38 +00:00
|
|
|
|
this, SLOT( desktopPopupAboutToShow() ) );
|
|
|
|
|
|
|
|
|
|
popup->insertItem(i18n("To &Desktop"), desk_popup, -1, 8 );
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-06 07:45:29 +00:00
|
|
|
|
// KDE4 remove me
|
|
|
|
|
void Workspace::showWindowMenuAt( unsigned long, int, int )
|
2000-11-12 20:25:21 +00:00
|
|
|
|
{
|
2002-08-06 07:45:29 +00:00
|
|
|
|
slotWindowOperations();
|
2000-11-12 20:25:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-11-29 02:06:41 +00:00
|
|
|
|
void Workspace::performWindowOperation( Client* c, Options::WindowOperation op ) {
|
|
|
|
|
if ( !c )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
1999-11-29 14:19:32 +00:00
|
|
|
|
|
2002-07-05 20:00:02 +00:00
|
|
|
|
if (op == Options::MoveOp)
|
2002-03-03 13:56:55 +00:00
|
|
|
|
QCursor::setPos( c->geometry().center() );
|
2002-07-05 20:00:02 +00:00
|
|
|
|
if (op == Options::ResizeOp)
|
|
|
|
|
QCursor::setPos( c->geometry().bottomRight());
|
1999-11-29 02:06:41 +00:00
|
|
|
|
switch ( op ) {
|
1999-12-06 00:43:55 +00:00
|
|
|
|
case Options::MoveOp:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c->performMouseCommand( Options::MouseMove, QCursor::pos() );
|
|
|
|
|
break;
|
1999-12-06 00:43:55 +00:00
|
|
|
|
case Options::ResizeOp:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c->performMouseCommand( Options::MouseResize, QCursor::pos() );
|
|
|
|
|
break;
|
1999-11-29 02:06:41 +00:00
|
|
|
|
case Options::CloseOp:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c->closeWindow();
|
|
|
|
|
break;
|
1999-11-29 02:06:41 +00:00
|
|
|
|
case Options::MaximizeOp:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c->maximize();
|
|
|
|
|
break;
|
1999-11-29 02:06:41 +00:00
|
|
|
|
case Options::IconifyOp:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c->iconify();
|
|
|
|
|
break;
|
1999-11-29 02:06:41 +00:00
|
|
|
|
case Options::ShadeOp:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c->setShade( !c->isShade() );
|
|
|
|
|
break;
|
2000-10-29 14:06:12 +00:00
|
|
|
|
case Options::StickyOp:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c->setSticky( !c->isSticky() );
|
|
|
|
|
break;
|
2000-06-28 13:20:42 +00:00
|
|
|
|
case Options::StaysOnTopOp:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c->setStaysOnTop( !c->staysOnTop() );
|
|
|
|
|
raiseClient( c );
|
|
|
|
|
break;
|
2001-01-14 20:16:04 +00:00
|
|
|
|
case Options::ToggleStoreSettingsOp:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c->setStoreSettings( !c->storeSettings() );
|
|
|
|
|
break;
|
2001-02-27 07:19:52 +00:00
|
|
|
|
case Options::HMaximizeOp:
|
|
|
|
|
c->maximize(Client::MaximizeHorizontal);
|
|
|
|
|
break;
|
|
|
|
|
case Options::VMaximizeOp:
|
|
|
|
|
c->maximize(Client::MaximizeVertical);
|
|
|
|
|
break;
|
|
|
|
|
case Options::LowerOp:
|
|
|
|
|
lowerClient(c);
|
|
|
|
|
break;
|
1999-11-29 02:06:41 +00:00
|
|
|
|
default:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
break;
|
1999-11-29 02:06:41 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-29 14:19:32 +00:00
|
|
|
|
void Workspace::clientPopupActivated( int id )
|
1999-11-29 02:06:41 +00:00
|
|
|
|
{
|
2002-08-06 07:45:29 +00:00
|
|
|
|
performWindowOperation( active_client, (Options::WindowOperation) id );
|
1999-11-22 01:57:51 +00:00
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
|
|
|
|
/*!
|
2002-06-29 06:31:33 +00:00
|
|
|
|
Asks the internal positioning object to place a client
|
1999-11-16 08:53:02 +00:00
|
|
|
|
*/
|
2002-06-29 06:31:33 +00:00
|
|
|
|
void Workspace::place(Client* c)
|
|
|
|
|
{
|
|
|
|
|
d->initPositioning->place(c);
|
1999-11-20 06:27:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-08-27 23:56:15 +00:00
|
|
|
|
/*!
|
|
|
|
|
Marks the client as being moved around by the user.
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::setClientIsMoving( Client *c )
|
|
|
|
|
{
|
2001-09-06 22:54:31 +00:00
|
|
|
|
Q_ASSERT(!c || !d->movingClient); // Catch attempts to move a second
|
2001-08-27 23:56:15 +00:00
|
|
|
|
// window while still moving the first one.
|
|
|
|
|
d->movingClient = c;
|
|
|
|
|
if (d->movingClient)
|
|
|
|
|
focus_change = false;
|
|
|
|
|
else
|
|
|
|
|
focus_change = true;
|
|
|
|
|
}
|
2000-06-22 14:12:13 +00:00
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Cascades all clients on the current desktop
|
|
|
|
|
*/
|
2000-06-08 17:05:51 +00:00
|
|
|
|
void Workspace::cascadeDesktop()
|
1999-12-03 21:08:07 +00:00
|
|
|
|
{
|
2002-04-07 06:55:48 +00:00
|
|
|
|
ClientList::Iterator it(stacking_order.begin());
|
|
|
|
|
bool re_init_cascade_at_first_client = true;
|
|
|
|
|
for (; it != stacking_order.end(); ++it) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if((!(*it)->isOnDesktop(currentDesktop())) ||
|
|
|
|
|
((*it)->isIconified()) ||
|
|
|
|
|
((*it)->isSticky()) ||
|
|
|
|
|
(!(*it)->isMovable()) )
|
|
|
|
|
continue;
|
2002-06-29 06:31:33 +00:00
|
|
|
|
d->initPositioning->placeCascaded(*it, re_init_cascade_at_first_client);
|
2002-04-07 06:55:48 +00:00
|
|
|
|
//CT is an if faster than an attribution??
|
|
|
|
|
if (re_init_cascade_at_first_client)
|
|
|
|
|
re_init_cascade_at_first_client = false;
|
2001-01-14 20:16:04 +00:00
|
|
|
|
}
|
2000-06-08 17:05:51 +00:00
|
|
|
|
}
|
1999-12-03 21:08:07 +00:00
|
|
|
|
|
2000-06-23 16:26:44 +00:00
|
|
|
|
/*!
|
2000-06-22 14:12:13 +00:00
|
|
|
|
Unclutters the current desktop by smart-placing all clients
|
|
|
|
|
again.
|
|
|
|
|
*/
|
2000-06-08 17:05:51 +00:00
|
|
|
|
void Workspace::unclutterDesktop()
|
|
|
|
|
{
|
2001-01-14 20:16:04 +00:00
|
|
|
|
ClientList::Iterator it(clients.fromLast());
|
|
|
|
|
for (; it != clients.end(); --it) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if((!(*it)->isOnDesktop(currentDesktop())) ||
|
|
|
|
|
((*it)->isIconified()) ||
|
|
|
|
|
((*it)->isSticky()) ||
|
|
|
|
|
(!(*it)->isMovable()) )
|
|
|
|
|
continue;
|
2002-06-29 06:31:33 +00:00
|
|
|
|
d->initPositioning->placeSmart(*it);
|
2001-01-14 20:16:04 +00:00
|
|
|
|
}
|
1999-12-03 21:08:07 +00:00
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
2000-06-08 17:05:51 +00:00
|
|
|
|
|
2001-06-04 14:01:00 +00:00
|
|
|
|
void Workspace::reconfigure()
|
|
|
|
|
{
|
|
|
|
|
reconfigureTimer.start(200, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-06-22 21:57:39 +00:00
|
|
|
|
/*!
|
|
|
|
|
Reread settings
|
|
|
|
|
*/
|
2001-06-04 14:01:00 +00:00
|
|
|
|
void Workspace::slotReconfigure()
|
2000-06-22 21:57:39 +00:00
|
|
|
|
{
|
2001-11-16 23:21:43 +00:00
|
|
|
|
kdDebug(1212) << "Workspace::slotReconfigure()" << endl;
|
2001-06-04 14:01:00 +00:00
|
|
|
|
reconfigureTimer.stop();
|
2000-06-22 21:57:39 +00:00
|
|
|
|
KGlobal::config()->reparseConfiguration();
|
|
|
|
|
options->reload();
|
2001-03-19 20:05:36 +00:00
|
|
|
|
tab_box->reconfigure();
|
2002-04-05 19:54:21 +00:00
|
|
|
|
popupinfo->reconfigure();
|
2002-01-19 04:55:32 +00:00
|
|
|
|
readShortcuts();
|
2001-11-16 23:21:43 +00:00
|
|
|
|
|
2001-02-21 18:29:24 +00:00
|
|
|
|
mgr->updatePlugin();
|
2001-08-27 05:42:32 +00:00
|
|
|
|
|
2001-11-03 00:05:33 +00:00
|
|
|
|
if (options->electricBorders() == Options::ElectricAlways)
|
2001-08-27 05:42:32 +00:00
|
|
|
|
createBorderWindows();
|
|
|
|
|
else
|
|
|
|
|
destroyBorderWindows();
|
2002-02-27 23:02:40 +00:00
|
|
|
|
|
2000-12-17 21:57:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-07-15 01:12:41 +00:00
|
|
|
|
/*!
|
|
|
|
|
avoids managing a window with title \a title
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::doNotManage( QString title )
|
|
|
|
|
{
|
|
|
|
|
doNotManageList.append( title );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Hack for java applets
|
|
|
|
|
*/
|
|
|
|
|
bool Workspace::isNotManaged( const QString& title )
|
|
|
|
|
{
|
|
|
|
|
for ( QStringList::Iterator it = doNotManageList.begin(); it != doNotManageList.end(); ++it ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
QRegExp r( (*it) );
|
2001-09-30 21:22:20 +00:00
|
|
|
|
if (r.search(title) != -1) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
doNotManageList.remove( it );
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2000-07-15 01:12:41 +00:00
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2000-07-08 12:08:41 +00:00
|
|
|
|
/*!
|
2000-06-28 13:20:42 +00:00
|
|
|
|
Lowers the client \a c taking stays-on-top flags, layers,
|
|
|
|
|
transient windows and window groups into account.
|
Preliminary support for avoiding covering clients such as kicker
which want to be permanently visible.
I've used an XAtom called '_NET_AVOID_SPEC'. This of course can change
if need be. I think it's correct according to the wm spec, but the
wm spec seems to be empty on gnome.org, so who knows.
Windows can choose to be avoided by setting an XTextProperty
with one value, which can be either 'N', 'S', 'E', or 'W', according
to which screen edge they are anchored to.
kwin then sets its 'clientArea' rect appropriately, so that (in
theory at least) clients will not enter this area in some circumstances,
such as when being mapped for the first time.
You can see that this actually works if you start lots of konsoles. They
don't appear over the panel. I don't know what happens if you move the
panel, but I presume things will be screwed up, because I haven't
looked at that yet.
If you maximise a window, it'll still fill the screen, because the
implementation of maximise in kwin/client.cpp doesn't take account
of the workspace's clientArea rect. This is easy to fix, but I've
been awake for too long, so I'll do it after 42 winks.
svn path=/trunk/kdebase/kwin/; revision=46772
2000-04-16 09:06:03 +00:00
|
|
|
|
*/
|
2000-10-02 12:02:15 +00:00
|
|
|
|
void Workspace::lowerClient( Client* c )
|
Preliminary support for avoiding covering clients such as kicker
which want to be permanently visible.
I've used an XAtom called '_NET_AVOID_SPEC'. This of course can change
if need be. I think it's correct according to the wm spec, but the
wm spec seems to be empty on gnome.org, so who knows.
Windows can choose to be avoided by setting an XTextProperty
with one value, which can be either 'N', 'S', 'E', or 'W', according
to which screen edge they are anchored to.
kwin then sets its 'clientArea' rect appropriately, so that (in
theory at least) clients will not enter this area in some circumstances,
such as when being mapped for the first time.
You can see that this actually works if you start lots of konsoles. They
don't appear over the panel. I don't know what happens if you move the
panel, but I presume things will be screwed up, because I haven't
looked at that yet.
If you maximise a window, it'll still fill the screen, because the
implementation of maximise in kwin/client.cpp doesn't take account
of the workspace's clientArea rect. This is easy to fix, but I've
been awake for too long, so I'll do it after 42 winks.
svn path=/trunk/kdebase/kwin/; revision=46772
2000-04-16 09:06:03 +00:00
|
|
|
|
{
|
2000-05-03 06:30:37 +00:00
|
|
|
|
if ( !c )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
Preliminary support for avoiding covering clients such as kicker
which want to be permanently visible.
I've used an XAtom called '_NET_AVOID_SPEC'. This of course can change
if need be. I think it's correct according to the wm spec, but the
wm spec seems to be empty on gnome.org, so who knows.
Windows can choose to be avoided by setting an XTextProperty
with one value, which can be either 'N', 'S', 'E', or 'W', according
to which screen edge they are anchored to.
kwin then sets its 'clientArea' rect appropriately, so that (in
theory at least) clients will not enter this area in some circumstances,
such as when being mapped for the first time.
You can see that this actually works if you start lots of konsoles. They
don't appear over the panel. I don't know what happens if you move the
panel, but I presume things will be screwed up, because I haven't
looked at that yet.
If you maximise a window, it'll still fill the screen, because the
implementation of maximise in kwin/client.cpp doesn't take account
of the workspace's clientArea rect. This is easy to fix, but I've
been awake for too long, so I'll do it after 42 winks.
svn path=/trunk/kdebase/kwin/; revision=46772
2000-04-16 09:06:03 +00:00
|
|
|
|
|
2002-03-02 21:03:49 +00:00
|
|
|
|
if ( c->isDesktop() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return; // deny
|
Preliminary support for avoiding covering clients such as kicker
which want to be permanently visible.
I've used an XAtom called '_NET_AVOID_SPEC'. This of course can change
if need be. I think it's correct according to the wm spec, but the
wm spec seems to be empty on gnome.org, so who knows.
Windows can choose to be avoided by setting an XTextProperty
with one value, which can be either 'N', 'S', 'E', or 'W', according
to which screen edge they are anchored to.
kwin then sets its 'clientArea' rect appropriately, so that (in
theory at least) clients will not enter this area in some circumstances,
such as when being mapped for the first time.
You can see that this actually works if you start lots of konsoles. They
don't appear over the panel. I don't know what happens if you move the
panel, but I presume things will be screwed up, because I haven't
looked at that yet.
If you maximise a window, it'll still fill the screen, because the
implementation of maximise in kwin/client.cpp doesn't take account
of the workspace's clientArea rect. This is easy to fix, but I've
been awake for too long, so I'll do it after 42 winks.
svn path=/trunk/kdebase/kwin/; revision=46772
2000-04-16 09:06:03 +00:00
|
|
|
|
|
2000-05-03 06:30:37 +00:00
|
|
|
|
ClientList saveset;
|
Preliminary support for avoiding covering clients such as kicker
which want to be permanently visible.
I've used an XAtom called '_NET_AVOID_SPEC'. This of course can change
if need be. I think it's correct according to the wm spec, but the
wm spec seems to be empty on gnome.org, so who knows.
Windows can choose to be avoided by setting an XTextProperty
with one value, which can be either 'N', 'S', 'E', or 'W', according
to which screen edge they are anchored to.
kwin then sets its 'clientArea' rect appropriately, so that (in
theory at least) clients will not enter this area in some circumstances,
such as when being mapped for the first time.
You can see that this actually works if you start lots of konsoles. They
don't appear over the panel. I don't know what happens if you move the
panel, but I presume things will be screwed up, because I haven't
looked at that yet.
If you maximise a window, it'll still fill the screen, because the
implementation of maximise in kwin/client.cpp doesn't take account
of the workspace's clientArea rect. This is easy to fix, but I've
been awake for too long, so I'll do it after 42 winks.
svn path=/trunk/kdebase/kwin/; revision=46772
2000-04-16 09:06:03 +00:00
|
|
|
|
|
2000-05-03 06:30:37 +00:00
|
|
|
|
if ( c->transientFor() ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
/* search for a non-transient managed window, which this client
|
|
|
|
|
is transient to (possibly over many ways) */
|
|
|
|
|
saveset.append( c );
|
|
|
|
|
Client* t = findClient( c->transientFor() );
|
|
|
|
|
Client* tmp;
|
|
|
|
|
while ( t && !saveset.contains( t ) && t->transientFor() ) {
|
|
|
|
|
tmp = findClient( t->transientFor() );
|
|
|
|
|
if ( !tmp )
|
|
|
|
|
break;
|
|
|
|
|
saveset.append( t );
|
|
|
|
|
t = tmp;
|
|
|
|
|
}
|
2002-03-02 21:03:49 +00:00
|
|
|
|
if ( t && !saveset.contains( t ) ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
lowerClient( t );
|
|
|
|
|
return;
|
|
|
|
|
}
|
Preliminary support for avoiding covering clients such as kicker
which want to be permanently visible.
I've used an XAtom called '_NET_AVOID_SPEC'. This of course can change
if need be. I think it's correct according to the wm spec, but the
wm spec seems to be empty on gnome.org, so who knows.
Windows can choose to be avoided by setting an XTextProperty
with one value, which can be either 'N', 'S', 'E', or 'W', according
to which screen edge they are anchored to.
kwin then sets its 'clientArea' rect appropriately, so that (in
theory at least) clients will not enter this area in some circumstances,
such as when being mapped for the first time.
You can see that this actually works if you start lots of konsoles. They
don't appear over the panel. I don't know what happens if you move the
panel, but I presume things will be screwed up, because I haven't
looked at that yet.
If you maximise a window, it'll still fill the screen, because the
implementation of maximise in kwin/client.cpp doesn't take account
of the workspace's clientArea rect. This is easy to fix, but I've
been awake for too long, so I'll do it after 42 winks.
svn path=/trunk/kdebase/kwin/; revision=46772
2000-04-16 09:06:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-05-03 06:30:37 +00:00
|
|
|
|
saveset.clear();
|
|
|
|
|
saveset.append( c );
|
|
|
|
|
lowerTransientsOf(saveset, c );
|
|
|
|
|
stacking_order.remove(c);
|
|
|
|
|
stacking_order.prepend(c);
|
Preliminary support for avoiding covering clients such as kicker
which want to be permanently visible.
I've used an XAtom called '_NET_AVOID_SPEC'. This of course can change
if need be. I think it's correct according to the wm spec, but the
wm spec seems to be empty on gnome.org, so who knows.
Windows can choose to be avoided by setting an XTextProperty
with one value, which can be either 'N', 'S', 'E', or 'W', according
to which screen edge they are anchored to.
kwin then sets its 'clientArea' rect appropriately, so that (in
theory at least) clients will not enter this area in some circumstances,
such as when being mapped for the first time.
You can see that this actually works if you start lots of konsoles. They
don't appear over the panel. I don't know what happens if you move the
panel, but I presume things will be screwed up, because I haven't
looked at that yet.
If you maximise a window, it'll still fill the screen, because the
implementation of maximise in kwin/client.cpp doesn't take account
of the workspace's clientArea rect. This is easy to fix, but I've
been awake for too long, so I'll do it after 42 winks.
svn path=/trunk/kdebase/kwin/; revision=46772
2000-04-16 09:06:03 +00:00
|
|
|
|
|
2000-09-27 12:21:04 +00:00
|
|
|
|
stacking_order = constrainedStackingOrder( stacking_order );
|
|
|
|
|
Window* new_stack = new Window[ stacking_order.count() + 1 ];
|
2000-05-03 06:30:37 +00:00
|
|
|
|
int i = 0;
|
2002-03-02 21:03:49 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it)
|
2001-02-16 18:05:27 +00:00
|
|
|
|
new_stack[i++] = (*it)->winId();
|
2000-05-03 06:30:37 +00:00
|
|
|
|
XRestackWindows(qt_xdisplay(), new_stack, i);
|
|
|
|
|
delete [] new_stack;
|
2000-06-28 13:20:42 +00:00
|
|
|
|
|
2000-05-03 06:30:37 +00:00
|
|
|
|
propagateClients( TRUE );
|
2000-10-04 15:19:44 +00:00
|
|
|
|
|
2000-10-02 12:02:15 +00:00
|
|
|
|
if ( c == most_recently_raised )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
most_recently_raised = 0;
|
2000-07-13 20:38:10 +00:00
|
|
|
|
|
Preliminary support for avoiding covering clients such as kicker
which want to be permanently visible.
I've used an XAtom called '_NET_AVOID_SPEC'. This of course can change
if need be. I think it's correct according to the wm spec, but the
wm spec seems to be empty on gnome.org, so who knows.
Windows can choose to be avoided by setting an XTextProperty
with one value, which can be either 'N', 'S', 'E', or 'W', according
to which screen edge they are anchored to.
kwin then sets its 'clientArea' rect appropriately, so that (in
theory at least) clients will not enter this area in some circumstances,
such as when being mapped for the first time.
You can see that this actually works if you start lots of konsoles. They
don't appear over the panel. I don't know what happens if you move the
panel, but I presume things will be screwed up, because I haven't
looked at that yet.
If you maximise a window, it'll still fill the screen, because the
implementation of maximise in kwin/client.cpp doesn't take account
of the workspace's clientArea rect. This is easy to fix, but I've
been awake for too long, so I'll do it after 42 winks.
svn path=/trunk/kdebase/kwin/; revision=46772
2000-04-16 09:06:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-07-08 12:08:41 +00:00
|
|
|
|
/*!
|
2000-06-28 13:20:42 +00:00
|
|
|
|
Raises the client \a c taking layers, stays-on-top flags,
|
|
|
|
|
transient windows and window groups into account.
|
1999-08-19 23:26:42 +00:00
|
|
|
|
*/
|
|
|
|
|
void Workspace::raiseClient( Client* c )
|
|
|
|
|
{
|
|
|
|
|
if ( !c )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
2000-07-10 11:15:48 +00:00
|
|
|
|
|
2000-05-08 19:37:54 +00:00
|
|
|
|
ClientList saveset;
|
2000-05-26 13:54:50 +00:00
|
|
|
|
|
2002-03-02 21:03:49 +00:00
|
|
|
|
if ( c->isDesktop() ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
saveset.clear();
|
|
|
|
|
saveset.append( c );
|
|
|
|
|
raiseTransientsOf(saveset, c );
|
|
|
|
|
return; // deny
|
2000-05-08 19:37:54 +00:00
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
2000-10-02 12:02:15 +00:00
|
|
|
|
most_recently_raised = c;
|
2000-10-04 15:19:44 +00:00
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
stacking_order.remove( c );
|
|
|
|
|
stacking_order.append( c );
|
|
|
|
|
|
1999-11-13 02:35:15 +00:00
|
|
|
|
if ( c->transientFor() ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
saveset.append( c );
|
|
|
|
|
Client* t = findClient( c->transientFor() );
|
|
|
|
|
Client* tmp;
|
|
|
|
|
while ( t && !saveset.contains( t ) && t->transientFor() ) {
|
|
|
|
|
tmp = findClient( t->transientFor() );
|
|
|
|
|
if ( !tmp )
|
|
|
|
|
break;
|
|
|
|
|
saveset.append( t );
|
|
|
|
|
t = tmp;
|
|
|
|
|
}
|
2002-03-02 21:03:49 +00:00
|
|
|
|
if ( t && !saveset.contains( t ) ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
raiseClient( t );
|
|
|
|
|
most_recently_raised = c;
|
|
|
|
|
return;
|
|
|
|
|
}
|
1999-11-13 02:35:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
saveset.clear();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
saveset.append( c );
|
|
|
|
|
raiseTransientsOf(saveset, c );
|
2000-07-08 12:08:41 +00:00
|
|
|
|
|
2000-09-27 12:21:04 +00:00
|
|
|
|
stacking_order = constrainedStackingOrder( stacking_order );
|
2000-09-25 15:30:51 +00:00
|
|
|
|
|
|
|
|
|
/* workaround to help broken full-screen applications to keep (modal) dialogs visible
|
|
|
|
|
*/
|
|
|
|
|
if ( c->isTransient() && c->mainClient() == c ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
bool has_full_screen = false;
|
|
|
|
|
for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
|
|
|
|
|
if ( (*it) == c )
|
|
|
|
|
break;
|
|
|
|
|
if ( (*it)->isVisible() && (*it)->isFullScreen() &&
|
|
|
|
|
!(*it)->isDesktop() && (*it)->staysOnTop() ) {
|
|
|
|
|
has_full_screen = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( has_full_screen ) {
|
|
|
|
|
stacking_order.remove( c );
|
|
|
|
|
stacking_order.append( c );
|
|
|
|
|
saveset.clear();
|
|
|
|
|
saveset.append( c );
|
|
|
|
|
raiseTransientsOf( saveset, c);
|
|
|
|
|
}
|
2000-09-25 15:30:51 +00:00
|
|
|
|
}
|
|
|
|
|
/* end workaround */
|
|
|
|
|
|
2000-09-27 12:21:04 +00:00
|
|
|
|
Window* new_stack = new Window[ stacking_order.count() + 1 ];
|
1999-08-19 23:26:42 +00:00
|
|
|
|
int i = 0;
|
2002-03-02 21:03:49 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it)
|
2001-02-16 18:05:27 +00:00
|
|
|
|
new_stack[i++] = (*it)->winId();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
XRestackWindows(qt_xdisplay(), new_stack, i);
|
|
|
|
|
delete [] new_stack;
|
|
|
|
|
|
1999-11-14 06:34:28 +00:00
|
|
|
|
|
1999-11-07 01:43:06 +00:00
|
|
|
|
propagateClients( TRUE );
|
2000-08-13 17:07:26 +00:00
|
|
|
|
|
2000-08-09 10:02:56 +00:00
|
|
|
|
if ( tab_box->isVisible() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
tab_box->raise();
|
2000-10-02 12:02:15 +00:00
|
|
|
|
|
2002-04-05 19:54:21 +00:00
|
|
|
|
if ( popupinfo->isVisible() )
|
|
|
|
|
popupinfo->raise();
|
|
|
|
|
|
2001-08-27 05:42:32 +00:00
|
|
|
|
raiseElectricBorders();
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-02-28 22:11:43 +00:00
|
|
|
|
void Workspace::stackClientUnderActive( Client* c )
|
|
|
|
|
{
|
|
|
|
|
if ( !active_client || !c || active_client == c )
|
2002-03-02 01:34:31 +00:00
|
|
|
|
return;
|
2002-02-28 22:11:43 +00:00
|
|
|
|
|
|
|
|
|
ClientList::Iterator it = stacking_order.find( active_client );
|
|
|
|
|
if ( it == stacking_order.end() )
|
2002-03-02 01:34:31 +00:00
|
|
|
|
return;
|
2002-02-28 22:11:43 +00:00
|
|
|
|
stacking_order.remove( c );
|
|
|
|
|
stacking_order.insert( it, c );
|
|
|
|
|
stacking_order = constrainedStackingOrder( stacking_order );
|
|
|
|
|
Window* new_stack = new Window[ stacking_order.count() + 1 ];
|
|
|
|
|
int i = 0;
|
|
|
|
|
for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
|
|
|
|
|
new_stack[i++] = (*it)->winId();
|
|
|
|
|
}
|
|
|
|
|
XRestackWindows(qt_xdisplay(), new_stack, i);
|
|
|
|
|
delete [] new_stack;
|
|
|
|
|
|
|
|
|
|
propagateClients( TRUE );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-04-02 16:17:06 +00:00
|
|
|
|
void Workspace::raiseOrLowerClient( Client *c)
|
|
|
|
|
{
|
|
|
|
|
if (!c) return;
|
|
|
|
|
|
|
|
|
|
if (c == most_recently_raised)
|
|
|
|
|
{
|
|
|
|
|
lowerClient(c);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
raiseClient(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( (*it)->transientFor() == c->window() && !safeset.contains( *it ) ) {
|
|
|
|
|
safeset.append( *it );
|
|
|
|
|
stacking_order.remove( *it );
|
|
|
|
|
stacking_order.append( *it );
|
|
|
|
|
raiseTransientsOf( safeset, *it );
|
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-03 06:30:37 +00:00
|
|
|
|
/*!
|
|
|
|
|
Private auxiliary function used in lowerClient()
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::lowerTransientsOf( ClientList& safeset, Client* c )
|
|
|
|
|
{
|
|
|
|
|
ClientList local = stacking_order;
|
2000-06-28 13:20:42 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = local.fromLast(); it!=local.end(); --it) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ((*it)->transientFor() == c->window() && !safeset.contains(*it)) {
|
|
|
|
|
safeset.append( *it );
|
|
|
|
|
lowerTransientsOf( safeset, *it );
|
|
|
|
|
stacking_order.remove( *it );
|
|
|
|
|
stacking_order.prepend( *it );
|
|
|
|
|
}
|
2000-05-03 06:30:37 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-06-28 13:20:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Returns a stacking order based upon \a list that fulfills certain contained.
|
2000-07-08 12:08:41 +00:00
|
|
|
|
|
2000-06-28 13:20:42 +00:00
|
|
|
|
Currently it obeyes the staysOnTop flag only.
|
2000-07-08 12:08:41 +00:00
|
|
|
|
|
2000-06-28 13:20:42 +00:00
|
|
|
|
\sa Client::staysOnTop()
|
|
|
|
|
*/
|
|
|
|
|
ClientList Workspace::constrainedStackingOrder( const ClientList& list )
|
|
|
|
|
{
|
|
|
|
|
ClientList result;
|
|
|
|
|
ClientList::ConstIterator it;
|
|
|
|
|
for ( it = list.begin(); it!=list.end(); ++it) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( !(*it)->staysOnTop() && !(*it)->mainClient()->staysOnTop())
|
|
|
|
|
result.append( *it );
|
2000-06-28 13:20:42 +00:00
|
|
|
|
}
|
|
|
|
|
for ( it = list.begin(); it!=list.end(); ++it) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( (*it)->staysOnTop() || (*it)->mainClient()->staysOnTop() )
|
|
|
|
|
result.append( *it );
|
2000-06-28 13:20:42 +00:00
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-19 23:26:42 +00:00
|
|
|
|
/*!
|
2000-06-22 14:12:13 +00:00
|
|
|
|
Puts the focus on a dummy window
|
2001-03-30 11:15:15 +00:00
|
|
|
|
Just using XSetInputFocus() with None would block keyboard input
|
1999-08-19 23:26:42 +00:00
|
|
|
|
*/
|
|
|
|
|
void Workspace::focusToNull(){
|
|
|
|
|
int mask;
|
|
|
|
|
XSetWindowAttributes attr;
|
2001-03-30 11:15:15 +00:00
|
|
|
|
if (null_focus_window == 0) {
|
1999-08-19 23:26:42 +00:00
|
|
|
|
mask = CWOverrideRedirect;
|
|
|
|
|
attr.override_redirect = 1;
|
2001-03-30 11:15:15 +00:00
|
|
|
|
null_focus_window = XCreateWindow(qt_xdisplay(), qt_xrootwin(), -1,-1, 1, 1, 0, CopyFromParent,
|
2001-02-16 18:05:27 +00:00
|
|
|
|
InputOnly, CopyFromParent, mask, &attr);
|
2001-03-30 11:15:15 +00:00
|
|
|
|
XMapWindow(qt_xdisplay(), null_focus_window);
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
2002-02-28 22:11:43 +00:00
|
|
|
|
XSetInputFocus(qt_xdisplay(), null_focus_window, RevertToPointerRoot, qt_x_time );
|
2001-05-09 20:06:46 +00:00
|
|
|
|
if( !block_focus )
|
|
|
|
|
setActiveClient( NULL );
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-22 14:12:13 +00:00
|
|
|
|
|
2001-03-14 10:16:08 +00:00
|
|
|
|
/*!
|
|
|
|
|
Refreshes all the client windows
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::refresh() {
|
2002-03-02 21:03:49 +00:00
|
|
|
|
QWidget w( 0, 0, WX11BypassWM );
|
|
|
|
|
w.setGeometry( QApplication::desktop()->geometry() );
|
|
|
|
|
w.show();
|
|
|
|
|
w.hide();
|
|
|
|
|
QApplication::flushX();
|
2001-03-14 10:16:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-04-03 12:50:32 +00:00
|
|
|
|
/*!
|
|
|
|
|
During virt. desktop switching, desktop areas covered by windows that are
|
|
|
|
|
going to be hidden are first obscured by new windows with no background
|
|
|
|
|
( i.e. transparent ) placed right below the windows. These invisible windows
|
|
|
|
|
are removed after the switch is complete.
|
|
|
|
|
Reduces desktop ( wallpaper ) repaints during desktop switching
|
|
|
|
|
*/
|
|
|
|
|
class ObscuringWindows
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
~ObscuringWindows();
|
|
|
|
|
void create( Client* c );
|
|
|
|
|
private:
|
|
|
|
|
QValueList<Window> obscuring_windows;
|
|
|
|
|
static QValueList<Window>* cached;
|
|
|
|
|
static unsigned int max_cache_size;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
QValueList<Window>* ObscuringWindows::cached = NULL;
|
|
|
|
|
unsigned int ObscuringWindows::max_cache_size = 0;
|
|
|
|
|
|
|
|
|
|
void ObscuringWindows::create( Client* c )
|
|
|
|
|
{
|
|
|
|
|
if( cached == NULL )
|
|
|
|
|
cached = new QValueList<Window>;
|
|
|
|
|
Window obs_win;
|
|
|
|
|
XWindowChanges chngs;
|
|
|
|
|
int mask = CWSibling | CWStackMode;
|
|
|
|
|
if( cached->count() > 0 ) {
|
|
|
|
|
cached->remove( obs_win = cached->first());
|
|
|
|
|
chngs.x = c->x();
|
|
|
|
|
chngs.y = c->y();
|
|
|
|
|
chngs.width = c->width();
|
|
|
|
|
chngs.height = c->height();
|
|
|
|
|
mask |= CWX | CWY | CWWidth | CWHeight;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
XSetWindowAttributes a;
|
|
|
|
|
a.background_pixmap = None;
|
|
|
|
|
a.override_redirect = True;
|
|
|
|
|
obs_win = XCreateWindow( qt_xdisplay(), qt_xrootwin(), c->x(), c->y(),
|
|
|
|
|
c->width(), c->height(), 0, CopyFromParent, InputOutput,
|
|
|
|
|
CopyFromParent, CWBackPixmap | CWOverrideRedirect, &a );
|
|
|
|
|
}
|
|
|
|
|
chngs.sibling = c->winId();
|
|
|
|
|
chngs.stack_mode = Below;
|
|
|
|
|
XConfigureWindow( qt_xdisplay(), obs_win, mask, &chngs );
|
|
|
|
|
XMapWindow( qt_xdisplay(), obs_win );
|
|
|
|
|
obscuring_windows.append( obs_win );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ObscuringWindows::~ObscuringWindows()
|
|
|
|
|
{
|
|
|
|
|
max_cache_size = QMAX( max_cache_size, obscuring_windows.count() + 4 ) - 1;
|
|
|
|
|
for( QValueList<Window>::ConstIterator it = obscuring_windows.begin();
|
|
|
|
|
it != obscuring_windows.end();
|
|
|
|
|
++it ) {
|
|
|
|
|
XUnmapWindow( qt_xdisplay(), *it );
|
|
|
|
|
if( cached->count() < max_cache_size )
|
|
|
|
|
cached->prepend( *it );
|
|
|
|
|
else
|
|
|
|
|
XDestroyWindow( qt_xdisplay(), *it );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-14 10:16:08 +00:00
|
|
|
|
|
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 ){
|
2000-05-30 05:52:11 +00:00
|
|
|
|
if (new_desktop < 1 || new_desktop > number_of_desktops )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
2000-09-19 18:57:15 +00:00
|
|
|
|
Client* old_active_client = active_client;
|
2000-06-01 05:32:06 +00:00
|
|
|
|
active_client = 0;
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if( popup )
|
|
|
|
|
popup->close();
|
1999-11-29 02:49:20 +00:00
|
|
|
|
block_focus = TRUE;
|
2000-10-17 13:09:59 +00:00
|
|
|
|
|
2001-11-15 23:02:40 +00:00
|
|
|
|
// ClientList mapList;
|
|
|
|
|
// ClientList unmapList;
|
1999-11-29 14:19:32 +00:00
|
|
|
|
|
2000-05-30 05:52:11 +00:00
|
|
|
|
if (new_desktop != current_desktop) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
/*
|
|
|
|
|
optimized Desktop switching: unmapping done from back to front
|
|
|
|
|
mapping done from front to back => less exposure events
|
|
|
|
|
*/
|
|
|
|
|
Events::raise((Events::Event) (Events::DesktopChange+new_desktop));
|
2001-04-25 16:15:54 +00:00
|
|
|
|
|
2001-04-03 12:50:32 +00:00
|
|
|
|
ObscuringWindows obs_wins;
|
2001-04-25 16:15:54 +00:00
|
|
|
|
|
2001-08-27 23:56:15 +00:00
|
|
|
|
if (d->movingClient && !d->movingClient->isSticky())
|
|
|
|
|
{
|
|
|
|
|
d->movingClient->setDesktop(-1); // All desktops
|
|
|
|
|
}
|
|
|
|
|
|
2001-02-16 18:05:27 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it) {
|
|
|
|
|
if ( (*it)->isVisible() && !(*it)->isOnDesktop( new_desktop ) ) {
|
2001-04-03 12:50:32 +00:00
|
|
|
|
obs_wins.create( *it );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
(*it)->hide();
|
2001-11-15 23:02:40 +00:00
|
|
|
|
// unmapList += (*it);
|
2001-02-16 18:05:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
current_desktop = new_desktop;
|
|
|
|
|
rootInfo->setCurrentDesktop( current_desktop ); // propagate befor the shows below
|
|
|
|
|
|
|
|
|
|
for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
|
|
|
|
|
if ( (*it)->isOnDesktop( new_desktop ) && !(*it)->isIconified() ) {
|
|
|
|
|
(*it)->show();
|
2001-11-15 23:02:40 +00:00
|
|
|
|
// mapList += (*it);
|
2001-02-16 18:05:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2001-08-27 23:56:15 +00:00
|
|
|
|
|
|
|
|
|
if (d->movingClient && !d->movingClient->isSticky())
|
|
|
|
|
{
|
|
|
|
|
d->movingClient->setDesktop(new_desktop);
|
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
2000-06-24 19:09:50 +00:00
|
|
|
|
current_desktop = new_desktop;
|
2001-10-09 06:53:26 +00:00
|
|
|
|
|
2000-06-24 19:09:50 +00:00
|
|
|
|
rootInfo->setCurrentDesktop( current_desktop );
|
1999-11-25 16:38:11 +00:00
|
|
|
|
|
1999-11-29 02:49:20 +00:00
|
|
|
|
// restore the focus on this desktop
|
|
|
|
|
block_focus = FALSE;
|
2000-06-01 05:32:06 +00:00
|
|
|
|
Client* c = 0;
|
|
|
|
|
|
|
|
|
|
if ( options->focusPolicyIsReasonable()) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
// Search in focus chain
|
|
|
|
|
|
|
|
|
|
if ( focus_chain.contains( old_active_client ) && old_active_client->isVisible() ) {
|
|
|
|
|
c = old_active_client;
|
|
|
|
|
active_client = c; // the requestFocus below will fail, as the client is already active
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( !c ) {
|
|
|
|
|
for( ClientList::ConstIterator it = focus_chain.fromLast(); it != focus_chain.end(); --it) {
|
|
|
|
|
if ( (*it)->isVisible() && !(*it)->isSticky() ) {
|
|
|
|
|
c = *it;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( !c ) {
|
|
|
|
|
for( ClientList::ConstIterator it = focus_chain.fromLast(); it != focus_chain.end(); --it) {
|
|
|
|
|
if ( (*it)->isVisible() ) {
|
|
|
|
|
c = *it;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-05-09 20:06:46 +00:00
|
|
|
|
/* if (!c) { // this is useless - these windows don't accept focus
|
2001-02-16 18:05:27 +00:00
|
|
|
|
// Search top-most visible window
|
|
|
|
|
for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
|
|
|
|
|
if ( (*it)->isVisible() ) {
|
|
|
|
|
c = *it;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-05-09 20:06:46 +00:00
|
|
|
|
}*/
|
1999-11-20 13:51:29 +00:00
|
|
|
|
}
|
1999-11-25 16:38:11 +00:00
|
|
|
|
|
2001-12-09 04:17:36 +00:00
|
|
|
|
//if "unreasonable focus policy"
|
|
|
|
|
// and active_client is sticky and under mouse (hence == old_active_client),
|
|
|
|
|
// conserve focus (thanks to Volker Schatz <V.Schatz at thphys.uni-heidelberg.de>)
|
|
|
|
|
else if( old_active_client && old_active_client->isVisible() )
|
|
|
|
|
c= old_active_client;
|
|
|
|
|
|
2000-09-27 12:21:04 +00:00
|
|
|
|
if ( c ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
requestFocus( c );
|
|
|
|
|
// don't let the panel cover fullscreen windows on desktop switches
|
|
|
|
|
if ( c->isFullScreen() && !c->isDesktop() && c->staysOnTop() )
|
|
|
|
|
raiseClient( c );
|
2000-09-27 12:21:04 +00:00
|
|
|
|
} else {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
focusToNull();
|
2000-09-27 12:21:04 +00:00
|
|
|
|
}
|
2002-03-02 21:03:49 +00:00
|
|
|
|
if( !desktops.isEmpty() ) {
|
2001-03-30 11:15:15 +00:00
|
|
|
|
Window w_tmp;
|
|
|
|
|
int i_tmp;
|
|
|
|
|
XGetInputFocus( qt_xdisplay(), &w_tmp, &i_tmp );
|
|
|
|
|
if( w_tmp == null_focus_window )
|
2002-03-02 21:03:49 +00:00
|
|
|
|
requestFocus( desktops.last() );
|
2001-03-30 11:15:15 +00:00
|
|
|
|
}
|
2001-06-10 04:10:42 +00:00
|
|
|
|
|
|
|
|
|
// Update focus chain:
|
|
|
|
|
// If input: chain = { 1, 2, 3, 4 } and current_desktop = 3,
|
|
|
|
|
// Output: chain = { 3, 1, 2, 4 }.
|
2001-08-02 18:31:37 +00:00
|
|
|
|
// kdDebug(1212) << QString("Switching to desktop #%1, at focus_chain index %2\n")
|
2001-12-09 04:17:36 +00:00
|
|
|
|
// .arg(current_desktop).arg(desktop_focus_chain.find( current_desktop ));
|
2001-06-10 04:10:42 +00:00
|
|
|
|
for( int i = desktop_focus_chain.find( current_desktop ); i > 0; i-- )
|
|
|
|
|
desktop_focus_chain[i] = desktop_focus_chain[i-1];
|
|
|
|
|
desktop_focus_chain[0] = current_desktop;
|
|
|
|
|
|
2001-11-15 23:02:40 +00:00
|
|
|
|
// QString s = "desktop_focus_chain[] = { ";
|
|
|
|
|
// for( uint i = 0; i < desktop_focus_chain.size(); i++ )
|
|
|
|
|
// s += QString::number(desktop_focus_chain[i]) + ", ";
|
2001-08-02 18:31:37 +00:00
|
|
|
|
// kdDebug(1212) << s << "}\n";
|
1999-08-19 23:26:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-06-09 05:00:46 +00:00
|
|
|
|
void Workspace::nextDesktop()
|
|
|
|
|
{
|
|
|
|
|
int desktop = currentDesktop() + 1;
|
|
|
|
|
setCurrentDesktop(desktop > numberOfDesktops() ? 1 : desktop);
|
2002-04-05 19:54:21 +00:00
|
|
|
|
popupinfo->showInfo( desktopName(currentDesktop()) );
|
2001-06-09 05:00:46 +00:00
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
2001-06-09 05:00:46 +00:00
|
|
|
|
void Workspace::previousDesktop()
|
|
|
|
|
{
|
|
|
|
|
int desktop = currentDesktop() - 1;
|
|
|
|
|
setCurrentDesktop(desktop ? desktop : numberOfDesktops());
|
2002-04-05 19:54:21 +00:00
|
|
|
|
popupinfo->showInfo( desktopName(currentDesktop()) );
|
2001-06-09 05:00:46 +00:00
|
|
|
|
}
|
1999-08-19 23:26:42 +00:00
|
|
|
|
|
2000-06-23 16:26:44 +00:00
|
|
|
|
/*!
|
2000-06-22 14:12:13 +00:00
|
|
|
|
Returns the workspace's desktop widget. The desktop widget is
|
|
|
|
|
sometimes required by clients to draw on it, for example outlines on
|
|
|
|
|
moving or resizing.
|
|
|
|
|
*/
|
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 )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
2002-02-27 16:17:45 +00:00
|
|
|
|
int old_number_of_desktops = number_of_desktops;
|
1999-11-07 01:43:06 +00:00
|
|
|
|
number_of_desktops = n;
|
2001-12-09 04:17:36 +00:00
|
|
|
|
|
2000-06-08 17:05:51 +00:00
|
|
|
|
rootInfo->setNumberOfDesktops( number_of_desktops );
|
2000-07-12 18:08:24 +00:00
|
|
|
|
saveDesktopSettings();
|
2002-02-28 21:04:36 +00:00
|
|
|
|
|
2002-02-27 16:17:45 +00:00
|
|
|
|
// if the number of desktops decreased, move all
|
|
|
|
|
// windows that would be hidden to the last visible desktop
|
|
|
|
|
if( old_number_of_desktops > number_of_desktops ) {
|
2002-02-28 21:04:36 +00:00
|
|
|
|
for( ClientList::ConstIterator it = clients.begin();
|
|
|
|
|
it != clients.end();
|
|
|
|
|
++it) {
|
|
|
|
|
if( !(*it)->isSticky() && (*it)->desktop() > numberOfDesktops())
|
|
|
|
|
sendClientToDesktop( *it, numberOfDesktops());
|
|
|
|
|
}
|
2002-02-27 16:17:45 +00:00
|
|
|
|
}
|
|
|
|
|
if( currentDesktop() > numberOfDesktops())
|
2002-02-28 21:04:36 +00:00
|
|
|
|
setCurrentDesktop( numberOfDesktops());
|
2001-06-10 04:10:42 +00:00
|
|
|
|
|
|
|
|
|
// Resize and reset the desktop focus chain.
|
|
|
|
|
desktop_focus_chain.resize( n );
|
|
|
|
|
for( int i = 0; i < (int)desktop_focus_chain.size(); i++ )
|
2001-12-09 04:17:36 +00:00
|
|
|
|
desktop_focus_chain[i] = i+1;
|
1999-11-07 01:43:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Handles client messages sent to the workspace
|
|
|
|
|
*/
|
2000-06-08 17:05:51 +00:00
|
|
|
|
bool Workspace::netCheck( XEvent* e )
|
1999-11-07 01:43:06 +00:00
|
|
|
|
{
|
2000-06-08 17:05:51 +00:00
|
|
|
|
unsigned int dirty = rootInfo->event( e );
|
2000-06-21 17:43:44 +00:00
|
|
|
|
|
2000-07-12 18:08:24 +00:00
|
|
|
|
if ( dirty & NET::DesktopNames )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
saveDesktopSettings();
|
2000-06-21 17:43:44 +00:00
|
|
|
|
|
2000-11-17 16:39:47 +00:00
|
|
|
|
return dirty != 0;
|
1999-11-07 01:43:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-04-02 22:12:54 +00:00
|
|
|
|
/*!
|
|
|
|
|
Called when a newly mapped client is ready ( has properties set correctly )
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::clientReady( Client* )
|
|
|
|
|
{
|
|
|
|
|
propagateClients();
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-07 01:43:06 +00:00
|
|
|
|
/*!
|
|
|
|
|
Propagates the managed clients to the world
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::propagateClients( bool onlyStacking )
|
|
|
|
|
{
|
2000-11-16 19:08:05 +00:00
|
|
|
|
Window *cl; // MW we should not assume WId and Window to be compatible
|
2001-02-16 18:05:27 +00:00
|
|
|
|
// when passig pointers around.
|
2000-11-16 19:08:05 +00:00
|
|
|
|
|
1999-11-07 01:43:06 +00:00
|
|
|
|
int i;
|
|
|
|
|
if ( !onlyStacking ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
cl = new Window[ clients.count()];
|
|
|
|
|
i = 0;
|
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it )
|
|
|
|
|
cl[i++] = (*it)->window();
|
|
|
|
|
rootInfo->setClientList( cl, i );
|
|
|
|
|
delete [] cl;
|
1999-11-07 01:43:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-11-16 19:08:05 +00:00
|
|
|
|
cl = new Window[ stacking_order.count()];
|
1999-11-07 01:43:06 +00:00
|
|
|
|
i = 0;
|
2000-10-30 09:58:08 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it)
|
2001-02-16 18:05:27 +00:00
|
|
|
|
cl[i++] = (*it)->window();
|
2000-11-16 19:08:05 +00:00
|
|
|
|
rootInfo->setClientListStacking( cl, i );
|
1999-11-07 01:43:06 +00:00
|
|
|
|
delete [] cl;
|
|
|
|
|
}
|
1999-11-11 01:22:41 +00:00
|
|
|
|
|
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
|
|
|
|
|
/*!
|
2000-06-28 07:51:45 +00:00
|
|
|
|
Check whether \a w is a system tray window. If so, add it to the respective
|
1999-12-06 00:43:55 +00:00
|
|
|
|
datastructures and propagate it to the world.
|
|
|
|
|
*/
|
2000-06-28 07:51:45 +00:00
|
|
|
|
bool Workspace::addSystemTrayWin( WId w )
|
1999-11-11 01:22:41 +00:00
|
|
|
|
{
|
2000-06-28 07:51:45 +00:00
|
|
|
|
if ( systemTrayWins.contains( w ) )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return TRUE;
|
2000-06-21 17:43:44 +00:00
|
|
|
|
|
2000-06-28 07:51:45 +00:00
|
|
|
|
NETWinInfo ni( qt_xdisplay(), w, root, NET::WMKDESystemTrayWinFor );
|
|
|
|
|
WId trayWinFor = ni.kdeSystemTrayWinFor();
|
|
|
|
|
if ( !trayWinFor )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return FALSE;
|
2000-06-28 07:51:45 +00:00
|
|
|
|
systemTrayWins.append( SystemTrayWindow( w, trayWinFor ) );
|
1999-11-11 01:22:41 +00:00
|
|
|
|
XSelectInput( qt_xdisplay(), w,
|
2001-02-16 18:05:27 +00:00
|
|
|
|
StructureNotifyMask
|
|
|
|
|
);
|
2000-06-08 17:05:51 +00:00
|
|
|
|
XAddToSaveSet( qt_xdisplay(), w );
|
2000-06-28 07:51:45 +00:00
|
|
|
|
propagateSystemTrayWins();
|
1999-11-11 01:22:41 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2000-06-28 13:20:42 +00:00
|
|
|
|
/*!
|
2000-06-28 07:51:45 +00:00
|
|
|
|
Check whether \a w is a system tray window. If so, remove it from
|
|
|
|
|
the respective datastructures and propagate this to the world.
|
1999-12-06 00:43:55 +00:00
|
|
|
|
*/
|
2000-06-28 07:51:45 +00:00
|
|
|
|
bool Workspace::removeSystemTrayWin( WId w )
|
1999-11-11 01:22:41 +00:00
|
|
|
|
{
|
2000-06-28 07:51:45 +00:00
|
|
|
|
if ( !systemTrayWins.contains( w ) )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return FALSE;
|
2000-06-28 07:51:45 +00:00
|
|
|
|
systemTrayWins.remove( w );
|
|
|
|
|
propagateSystemTrayWins();
|
1999-11-11 01:22:41 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
|
1999-11-11 01:22:41 +00:00
|
|
|
|
/*!
|
2000-06-28 07:51:45 +00:00
|
|
|
|
Propagates the systemTrayWins to the world
|
1999-11-11 01:22:41 +00:00
|
|
|
|
*/
|
2000-06-28 07:51:45 +00:00
|
|
|
|
void Workspace::propagateSystemTrayWins()
|
1999-11-11 01:22:41 +00:00
|
|
|
|
{
|
2000-11-16 19:08:05 +00:00
|
|
|
|
Window *cl = new Window[ systemTrayWins.count()];
|
|
|
|
|
|
1999-11-11 01:22:41 +00:00
|
|
|
|
int i = 0;
|
2000-06-28 07:51:45 +00:00
|
|
|
|
for ( SystemTrayWindowList::ConstIterator it = systemTrayWins.begin(); it != systemTrayWins.end(); ++it ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
cl[i++] = (*it).win;
|
1999-11-11 01:22:41 +00:00
|
|
|
|
}
|
2000-06-21 17:43:44 +00:00
|
|
|
|
|
2000-11-16 19:08:05 +00:00
|
|
|
|
rootInfo->setKDESystemTrayWindows( cl, i );
|
1999-11-11 01:22:41 +00:00
|
|
|
|
delete [] cl;
|
|
|
|
|
}
|
1999-11-13 01:51:22 +00:00
|
|
|
|
|
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
/*!
|
|
|
|
|
Create the global accel object \c keys.
|
|
|
|
|
*/
|
2002-01-19 04:55:32 +00:00
|
|
|
|
void Workspace::initShortcuts(){
|
2001-11-16 23:21:43 +00:00
|
|
|
|
keys = new KGlobalAccel( this );
|
1999-11-13 01:51:22 +00:00
|
|
|
|
#include "kwinbindings.cpp"
|
2002-01-19 04:55:32 +00:00
|
|
|
|
readShortcuts();
|
2001-12-29 04:19:24 +00:00
|
|
|
|
}
|
2001-03-28 12:44:31 +00:00
|
|
|
|
|
2002-01-19 04:55:32 +00:00
|
|
|
|
void Workspace::readShortcuts(){
|
1999-11-13 01:51:22 +00:00
|
|
|
|
keys->readSettings();
|
2001-12-29 04:19:24 +00:00
|
|
|
|
|
2002-01-19 04:55:32 +00:00
|
|
|
|
cutWalkThroughDesktops = keys->shortcut("Walk Through Desktops");
|
|
|
|
|
cutWalkThroughDesktopsReverse = keys->shortcut("Walk Through Desktops (Reverse)");
|
|
|
|
|
cutWalkThroughDesktopList = keys->shortcut("Walk Through Desktop List");
|
|
|
|
|
cutWalkThroughDesktopListReverse = keys->shortcut("Walk Through Desktop List (Reverse)");
|
|
|
|
|
cutWalkThroughWindows = keys->shortcut("Walk Through Windows");
|
|
|
|
|
cutWalkThroughWindowsReverse = keys->shortcut("Walk Through Windows (Reverse)");
|
2001-12-29 04:19:24 +00:00
|
|
|
|
|
2001-11-16 23:21:43 +00:00
|
|
|
|
keys->updateConnections();
|
2000-08-28 06:16:34 +00:00
|
|
|
|
}
|
2001-01-11 23:41:07 +00:00
|
|
|
|
|
|
|
|
|
void Workspace::slotSwitchDesktopNext(){
|
2002-02-28 21:04:36 +00:00
|
|
|
|
int d = currentDesktop() + 1;
|
|
|
|
|
if ( d > numberOfDesktops() ) {
|
|
|
|
|
if ( options->rollOverDesktops ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
d = 1;
|
2002-02-28 21:04:36 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-11 23:41:07 +00:00
|
|
|
|
setCurrentDesktop(d);
|
2002-04-05 19:54:21 +00:00
|
|
|
|
popupinfo->showInfo( desktopName(currentDesktop()) );
|
2001-01-11 23:41:07 +00:00
|
|
|
|
}
|
2001-12-29 04:19:24 +00:00
|
|
|
|
|
2001-01-11 23:41:07 +00:00
|
|
|
|
void Workspace::slotSwitchDesktopPrevious(){
|
|
|
|
|
int d = currentDesktop() - 1;
|
2002-02-28 21:04:36 +00:00
|
|
|
|
if ( d <= 0 ) {
|
|
|
|
|
if ( options->rollOverDesktops )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
d = numberOfDesktops();
|
2002-02-28 21:04:36 +00:00
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
}
|
2001-01-11 23:41:07 +00:00
|
|
|
|
setCurrentDesktop(d);
|
2002-04-05 19:54:21 +00:00
|
|
|
|
popupinfo->showInfo( desktopName(currentDesktop()) );
|
2001-01-11 23:41:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-11-29 23:59:54 +00:00
|
|
|
|
void Workspace::setDesktopLayout(int o, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
d->layoutOrientation = (Qt::Orientation) o;
|
|
|
|
|
d->layoutX = x;
|
|
|
|
|
d->layoutY = y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Workspace::calcDesktopLayout(int &x, int &y)
|
|
|
|
|
{
|
|
|
|
|
x = d->layoutX;
|
|
|
|
|
y = d->layoutY;
|
|
|
|
|
if ((x == -1) && (y > 0))
|
|
|
|
|
x = (numberOfDesktops()+y-1) / y;
|
|
|
|
|
else if ((y == -1) && (x > 0))
|
|
|
|
|
y = (numberOfDesktops()+x-1) / x;
|
|
|
|
|
|
|
|
|
|
if (x == -1)
|
|
|
|
|
x = 1;
|
|
|
|
|
if (y == -1)
|
|
|
|
|
y = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Workspace::slotSwitchDesktopRight()
|
|
|
|
|
{
|
|
|
|
|
int x,y;
|
|
|
|
|
calcDesktopLayout(x,y);
|
|
|
|
|
int dt = currentDesktop()-1;
|
|
|
|
|
if (d->layoutOrientation == Qt::Vertical)
|
|
|
|
|
{
|
|
|
|
|
dt += y;
|
2002-02-28 21:04:36 +00:00
|
|
|
|
if ( dt >= numberOfDesktops() ) {
|
|
|
|
|
if ( options->rollOverDesktops )
|
|
|
|
|
dt -= numberOfDesktops();
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
}
|
2001-11-29 23:59:54 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int d = (dt % x) + 1;
|
2002-02-28 21:04:36 +00:00
|
|
|
|
if ( d >= x ) {
|
|
|
|
|
if ( options->rollOverDesktops )
|
|
|
|
|
d -= x;
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
}
|
2001-12-09 04:17:36 +00:00
|
|
|
|
dt = dt - (dt % x) + d;
|
2001-11-29 23:59:54 +00:00
|
|
|
|
}
|
|
|
|
|
setCurrentDesktop(dt+1);
|
2002-04-05 19:54:21 +00:00
|
|
|
|
popupinfo->showInfo( desktopName(currentDesktop()) );
|
2000-07-04 17:07:58 +00:00
|
|
|
|
}
|
2001-11-29 23:59:54 +00:00
|
|
|
|
|
2000-07-04 17:07:58 +00:00
|
|
|
|
void Workspace::slotSwitchDesktopLeft(){
|
2001-11-29 23:59:54 +00:00
|
|
|
|
int x,y;
|
|
|
|
|
calcDesktopLayout(x,y);
|
|
|
|
|
int dt = currentDesktop()-1;
|
|
|
|
|
if (d->layoutOrientation == Qt::Vertical)
|
|
|
|
|
{
|
|
|
|
|
dt -= y;
|
2002-02-28 21:04:36 +00:00
|
|
|
|
if ( dt < 0 ) {
|
|
|
|
|
if ( options->rollOverDesktops )
|
|
|
|
|
dt += numberOfDesktops();
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
}
|
2001-11-29 23:59:54 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int d = (dt % x) - 1;
|
2002-02-28 21:04:36 +00:00
|
|
|
|
if ( d < 0 ) {
|
|
|
|
|
if ( options->rollOverDesktops )
|
|
|
|
|
d += x;
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
}
|
2001-12-09 04:17:36 +00:00
|
|
|
|
dt = dt - (dt % x) + d;
|
2001-11-29 23:59:54 +00:00
|
|
|
|
}
|
|
|
|
|
setCurrentDesktop(dt+1);
|
2002-04-05 19:54:21 +00:00
|
|
|
|
popupinfo->showInfo( desktopName(currentDesktop()) );
|
2001-01-11 23:41:07 +00:00
|
|
|
|
}
|
2001-11-29 23:59:54 +00:00
|
|
|
|
|
2001-01-11 23:41:07 +00:00
|
|
|
|
void Workspace::slotSwitchDesktopUp(){
|
2001-11-29 23:59:54 +00:00
|
|
|
|
int x,y;
|
|
|
|
|
calcDesktopLayout(x,y);
|
|
|
|
|
int dt = currentDesktop()-1;
|
|
|
|
|
if (d->layoutOrientation == Qt::Horizontal)
|
|
|
|
|
{
|
|
|
|
|
dt -= x;
|
2002-02-28 21:04:36 +00:00
|
|
|
|
if ( dt < 0 ) {
|
|
|
|
|
if ( options->rollOverDesktops )
|
|
|
|
|
dt += numberOfDesktops();
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
}
|
2001-11-29 23:59:54 +00:00
|
|
|
|
}
|
2001-01-11 23:41:07 +00:00
|
|
|
|
else
|
2001-11-29 23:59:54 +00:00
|
|
|
|
{
|
|
|
|
|
int d = (dt % y) - 1;
|
2002-02-28 21:04:36 +00:00
|
|
|
|
if ( d < 0 ) {
|
|
|
|
|
if ( options->rollOverDesktops )
|
|
|
|
|
d += y;
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
}
|
2001-12-09 04:17:36 +00:00
|
|
|
|
dt = dt - (dt % y) + d;
|
2001-11-29 23:59:54 +00:00
|
|
|
|
}
|
|
|
|
|
setCurrentDesktop(dt+1);
|
2002-04-05 19:54:21 +00:00
|
|
|
|
popupinfo->showInfo( desktopName(currentDesktop()) );
|
2001-01-11 23:41:07 +00:00
|
|
|
|
}
|
2001-11-29 23:59:54 +00:00
|
|
|
|
|
2001-01-11 23:41:07 +00:00
|
|
|
|
void Workspace::slotSwitchDesktopDown(){
|
2001-11-29 23:59:54 +00:00
|
|
|
|
int x,y;
|
|
|
|
|
calcDesktopLayout(x,y);
|
|
|
|
|
int dt = currentDesktop()-1;
|
|
|
|
|
if (d->layoutOrientation == Qt::Horizontal)
|
|
|
|
|
{
|
|
|
|
|
dt += x;
|
2002-02-28 21:04:36 +00:00
|
|
|
|
if ( dt >= numberOfDesktops() ) {
|
|
|
|
|
if ( options->rollOverDesktops )
|
|
|
|
|
dt -= numberOfDesktops();
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
}
|
2001-11-29 23:59:54 +00:00
|
|
|
|
}
|
2001-01-11 23:41:07 +00:00
|
|
|
|
else
|
2001-11-29 23:59:54 +00:00
|
|
|
|
{
|
|
|
|
|
int d = (dt % y) + 1;
|
2002-02-28 21:04:36 +00:00
|
|
|
|
if ( d >= y ) {
|
|
|
|
|
if ( options->rollOverDesktops )
|
|
|
|
|
d -= y;
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
}
|
2001-12-09 04:17:36 +00:00
|
|
|
|
dt = dt - (dt % y) + d;
|
2001-11-29 23:59:54 +00:00
|
|
|
|
}
|
|
|
|
|
setCurrentDesktop(dt+1);
|
2002-04-05 19:54:21 +00:00
|
|
|
|
popupinfo->showInfo( desktopName(currentDesktop()) );
|
2000-07-04 17:07:58 +00:00
|
|
|
|
}
|
1999-12-06 00:43:55 +00:00
|
|
|
|
|
2001-06-10 04:10:42 +00:00
|
|
|
|
void Workspace::slotSwitchToDesktop( int i )
|
|
|
|
|
{
|
2002-04-01 02:54:00 +00:00
|
|
|
|
setCurrentDesktop( i );
|
2002-04-05 19:54:21 +00:00
|
|
|
|
popupinfo->showInfo( desktopName(currentDesktop()) );
|
2001-06-10 04:10:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Workspace::slotWindowToDesktop( int i )
|
|
|
|
|
{
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if( i >= 1 && i <= numberOfDesktops() && active_client
|
|
|
|
|
&& !active_client->isDesktop()
|
|
|
|
|
&& !active_client->isDock()
|
|
|
|
|
&& !active_client->isTopMenu())
|
|
|
|
|
sendClientToDesktop( active_client, i );
|
2001-06-10 04:10:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
/*!
|
|
|
|
|
Maximizes the popup client
|
|
|
|
|
*/
|
1999-11-29 02:18:29 +00:00
|
|
|
|
void Workspace::slotWindowMaximize()
|
|
|
|
|
{
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if ( active_client )
|
|
|
|
|
active_client->maximize( Client::MaximizeFull );
|
1999-11-29 02:18:29 +00:00
|
|
|
|
}
|
1999-12-06 00:43:55 +00:00
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Maximizes the popup client vertically
|
|
|
|
|
*/
|
1999-11-29 02:18:29 +00:00
|
|
|
|
void Workspace::slotWindowMaximizeVertical()
|
|
|
|
|
{
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if ( active_client )
|
|
|
|
|
active_client->maximize( Client::MaximizeVertical );
|
1999-11-29 02:18:29 +00:00
|
|
|
|
}
|
1999-12-06 00:43:55 +00:00
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Maximizes the popup client horiozontally
|
|
|
|
|
*/
|
1999-11-29 02:18:29 +00:00
|
|
|
|
void Workspace::slotWindowMaximizeHorizontal()
|
|
|
|
|
{
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if ( active_client )
|
|
|
|
|
active_client->maximize( Client::MaximizeHorizontal );
|
1999-11-29 02:18:29 +00:00
|
|
|
|
}
|
1999-12-06 00:43:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Iconifies the popup client
|
|
|
|
|
*/
|
1999-11-29 02:18:29 +00:00
|
|
|
|
void Workspace::slotWindowIconify()
|
|
|
|
|
{
|
2002-08-06 07:45:29 +00:00
|
|
|
|
performWindowOperation( active_client, Options::IconifyOp );
|
1999-11-29 02:18:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
Remove "Window iconify all" since we now how "Toggle Show Desktop".
Index: kwinbindings.cpp
===================================================================
RCS file: /home/kde/kdebase/kwin/kwinbindings.cpp,v
retrieving revision 1.24
diff -u -3 -d -p -r1.24 kwinbindings.cpp
--- kwinbindings.cpp 2001/06/26 23:30:52 1.24
+++ kwinbindings.cpp 2001/06/29 04:29:14
@@ -22,7 +22,7 @@
keys->insertItem(i18n("Window Maximize Vertical"), "Window maximize vertical", KKey(), KKey("Meta+Bar"));
keys->insertItem(i18n("Window Maximize Horizontal"), "Window maximize horizontal", KKey(), KKey("Meta+Equal"));
keys->insertItem(i18n("Window Iconify"), "Window iconify", KKey(), KKey("Meta+Minus"));
- keys->insertItem(i18n("Window Iconify (All)"), "Window iconify all", KKey(), KKey("Meta+Ctrl+Minus"));
+ //keys->insertItem(i18n("Window Iconify (All)"), "Window iconify all", KKey(), KKey("Meta+Ctrl+Minus"));
keys->insertItem(i18n("Window Shade"), "Window shade", KKey(), KKey("Meta+Underscore"));
keys->insertItem(i18n("Window Move"), "Window move", 0);
keys->insertItem(i18n("Window Resize"), "Window resize", 0);
@@ -113,6 +113,6 @@ This belongs in taskbar rather than here
#endif
keys->insertItem(i18n("Mouse Emulation"), "Mouse emulation", KKey("ALT+F12"), KKey());
keys->insertItem(i18n("Kill Window"), "Kill Window", KKey("CTRL+ALT+Escape"), KKey("Meta+Ctrl+Delete"));
- keys->insertItem(i18n("Window Screenshot"), "Screenshot of active window", KKey("Print"), KKey());
- keys->insertItem(i18n("Desktop Screenshot"), "Screenshot of desktop", KKey("CTRL+PrtSc"), KKey());
+ keys->insertItem(i18n("Window Screenshot"), "Screenshot of active window", KKey("Print"), KKey("Alt+Print"));
+ keys->insertItem(i18n("Desktop Screenshot"), "Screenshot of desktop", KKey("CTRL+Print"), KKey("Meta+Print"));
Index: workspace.cpp
===================================================================
RCS file: /home/kde/kdebase/kwin/workspace.cpp,v
retrieving revision 1.263
diff -u -3 -d -p -r1.263 workspace.cpp
--- workspace.cpp 2001/06/29 00:16:26 1.263
+++ workspace.cpp 2001/06/29 04:29:24
@@ -2553,7 +2553,7 @@ void Workspace::createKeybindings(){
keys->connectItem( "Window maximize horizontal", this, SLOT( slotWindowMaximizeHorizontal() ) );
keys->connectItem( "Window maximize vertical", this, SLOT( slotWindowMaximizeVertical() ) );
keys->connectItem( "Window iconify", this, SLOT( slotWindowIconify() ) );
- keys->connectItem( "Window iconify all", this, SLOT( slotWindowIconifyAll() ) );
+ //keys->connectItem( "Window iconify all", this, SLOT( slotWindowIconifyAll() ) );
keys->connectItem( "Window shade", this, SLOT( slotWindowShade() ) );
keys->connectItem( "Window move", this, SLOT( slotWindowMove() ) );
keys->connectItem( "Window resize", this, SLOT( slotWindowResize() ) );
@@ -2744,6 +2744,7 @@ void Workspace::slotWindowIconify()
performWindowOperation( popup_client, Options::IconifyOp );
}
+// This should probably be removed now that there is a "Show Desktop" binding.
void Workspace::slotWindowIconifyAll()
{
int iDesktop = currentDesktop();
svn path=/trunk/kdebase/kwin/; revision=104351
2001-06-29 04:30:25 +00:00
|
|
|
|
// This should probably be removed now that there is a "Show Desktop" binding.
|
2001-06-07 18:17:24 +00:00
|
|
|
|
void Workspace::slotWindowIconifyAll()
|
|
|
|
|
{
|
|
|
|
|
int iDesktop = currentDesktop();
|
|
|
|
|
|
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
|
|
|
|
if( (*it)->isOnDesktop( iDesktop ) && !(*it)->isIconified() )
|
|
|
|
|
performWindowOperation( *it, Options::IconifyOp );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
/*!
|
|
|
|
|
Shades/unshades the popup client respectively
|
|
|
|
|
*/
|
1999-11-29 02:49:20 +00:00
|
|
|
|
void Workspace::slotWindowShade()
|
|
|
|
|
{
|
2002-08-06 07:45:29 +00:00
|
|
|
|
performWindowOperation( active_client, Options::ShadeOp );
|
1999-11-29 02:49:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-07-30 16:15:17 +00:00
|
|
|
|
/*!
|
|
|
|
|
Raises the popup client
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::slotWindowRaise()
|
|
|
|
|
{
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if ( active_client )
|
|
|
|
|
raiseClient( active_client );
|
2000-07-30 16:15:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Lowers the popup client
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::slotWindowLower()
|
|
|
|
|
{
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if ( active_client )
|
|
|
|
|
lowerClient( active_client );
|
2000-07-30 16:15:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-04-02 16:17:06 +00:00
|
|
|
|
/*!
|
|
|
|
|
Does a toggle-raise-and-lower on the popup client;
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::slotWindowRaiseOrLower()
|
|
|
|
|
{
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if ( active_client )
|
|
|
|
|
raiseOrLowerClient( active_client );
|
2001-04-02 16:17:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-05-11 21:38:00 +00:00
|
|
|
|
/*!
|
|
|
|
|
Move window to next desktop
|
|
|
|
|
*/
|
2002-01-19 04:55:32 +00:00
|
|
|
|
void Workspace::slotWindowToNextDesktop(){
|
2001-05-11 21:38:00 +00:00
|
|
|
|
int d = currentDesktop() + 1;
|
|
|
|
|
if ( d > numberOfDesktops() )
|
|
|
|
|
d = 1;
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if (active_client && !active_client->isDesktop()
|
|
|
|
|
&& !active_client->isDock() && !active_client->isTopMenu())
|
|
|
|
|
sendClientToDesktop(active_client,d);
|
2001-05-11 21:38:00 +00:00
|
|
|
|
setCurrentDesktop(d);
|
2002-04-05 19:54:21 +00:00
|
|
|
|
popupinfo->showInfo( desktopName(currentDesktop()) );
|
2001-05-11 21:38:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Move window to previous desktop
|
|
|
|
|
*/
|
2002-01-19 04:55:32 +00:00
|
|
|
|
void Workspace::slotWindowToPreviousDesktop(){
|
2001-05-11 21:38:00 +00:00
|
|
|
|
int d = currentDesktop() - 1;
|
|
|
|
|
if ( d <= 0 )
|
|
|
|
|
d = numberOfDesktops();
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if (active_client && !active_client->isDesktop()
|
|
|
|
|
&& !active_client->isDock() && !active_client->isTopMenu())
|
|
|
|
|
sendClientToDesktop(active_client,d);
|
2001-05-11 21:38:00 +00:00
|
|
|
|
setCurrentDesktop(d);
|
2002-04-05 19:54:21 +00:00
|
|
|
|
popupinfo->showInfo( desktopName(currentDesktop()) );
|
2001-05-11 21:38:00 +00:00
|
|
|
|
}
|
1999-12-06 00:43:55 +00:00
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Invokes keyboard mouse emulation
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::slotMouseEmulation()
|
|
|
|
|
{
|
2000-08-13 17:07:26 +00:00
|
|
|
|
|
2000-08-09 10:02:56 +00:00
|
|
|
|
if ( mouse_emulation ) {
|
2002-02-28 22:11:43 +00:00
|
|
|
|
XUngrabKeyboard(qt_xdisplay(), qt_x_time);
|
2001-02-16 18:05:27 +00:00
|
|
|
|
mouse_emulation = FALSE;
|
|
|
|
|
return;
|
2000-08-13 17:07:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
if ( XGrabKeyboard(qt_xdisplay(),
|
2001-02-16 18:05:27 +00:00
|
|
|
|
root, FALSE,
|
|
|
|
|
GrabModeAsync, GrabModeAsync,
|
2002-02-28 22:11:43 +00:00
|
|
|
|
qt_x_time) == GrabSuccess ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
mouse_emulation = TRUE;
|
|
|
|
|
mouse_emulation_state = 0;
|
|
|
|
|
mouse_emulation_window = 0;
|
1999-12-06 00:43:55 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-06-08 17:05:51 +00:00
|
|
|
|
/*!
|
|
|
|
|
Kill Window feature, similar to xkill
|
|
|
|
|
*/
|
2000-05-17 23:02:42 +00:00
|
|
|
|
void Workspace::slotKillWindow()
|
|
|
|
|
{
|
2000-06-08 17:05:51 +00:00
|
|
|
|
KillWindow kill( this );
|
|
|
|
|
kill.start();
|
2000-05-17 23:02:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-08 17:05:51 +00:00
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Kills the window at position \a x, \a y
|
|
|
|
|
*/
|
2000-05-17 23:02:42 +00:00
|
|
|
|
void Workspace::killWindowAtPosition(int x, int y)
|
|
|
|
|
{
|
2000-05-29 22:38:43 +00:00
|
|
|
|
ClientList::ConstIterator it(stacking_order.fromLast());
|
2001-01-14 20:16:04 +00:00
|
|
|
|
for ( ; it != stacking_order.end(); --it) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
Client *client = (*it);
|
|
|
|
|
if ( client->frameGeometry().contains(QPoint(x, y)) &&
|
|
|
|
|
client->isOnDesktop( currentDesktop() ) &&
|
2002-07-05 20:05:22 +00:00
|
|
|
|
!client->isTopMenu() && !client->isDesktop() &&
|
2001-02-16 18:05:27 +00:00
|
|
|
|
!client->isIconified() ) {
|
|
|
|
|
client->killWindow();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2000-05-17 23:02:42 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-26 23:30:52 +00:00
|
|
|
|
/*!
|
|
|
|
|
Takes a screenshot of the current window and puts it in the clipboard.
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::slotGrabWindow()
|
|
|
|
|
{
|
|
|
|
|
if ( active_client ) {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
QPixmap p = QPixmap::grabWindow( active_client->winId() );
|
|
|
|
|
QClipboard *cb = QApplication::clipboard();
|
|
|
|
|
cb->setPixmap( p );
|
2001-06-26 23:30:52 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
2001-12-09 04:17:36 +00:00
|
|
|
|
slotGrabDesktop();
|
2001-06-26 23:30:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Takes a screenshot of the whole desktop and puts it in the clipboard.
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::slotGrabDesktop()
|
|
|
|
|
{
|
|
|
|
|
QPixmap p = QPixmap::grabWindow( qt_xrootwin() );
|
|
|
|
|
QClipboard *cb = QApplication::clipboard();
|
|
|
|
|
cb->setPixmap( p );
|
|
|
|
|
}
|
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
/*!
|
|
|
|
|
Adjusts the desktop popup to the current values and the location of
|
|
|
|
|
the popup client.
|
|
|
|
|
*/
|
1999-11-22 01:57:51 +00:00
|
|
|
|
void Workspace::desktopPopupAboutToShow()
|
|
|
|
|
{
|
1999-11-25 16:38:11 +00:00
|
|
|
|
if ( !desk_popup )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
2002-06-11 19:49:38 +00:00
|
|
|
|
|
1999-11-22 01:57:51 +00:00
|
|
|
|
desk_popup->clear();
|
2001-09-21 09:32:44 +00:00
|
|
|
|
desk_popup->insertItem( i18n("&All Desktops"), 0 );
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if ( active_client && active_client->isSticky() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
desk_popup->setItemChecked( 0, TRUE );
|
2000-03-12 06:18:14 +00:00
|
|
|
|
desk_popup->insertSeparator( -1 );
|
1999-11-22 01:57:51 +00:00
|
|
|
|
int id;
|
2000-11-14 14:12:54 +00:00
|
|
|
|
const int BASE = 10;
|
1999-11-22 01:57:51 +00:00
|
|
|
|
for ( int i = 1; i <= numberOfDesktops(); i++ ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
QString basic_name("%1 %2");
|
|
|
|
|
if (i<BASE) {
|
|
|
|
|
basic_name.prepend('&');
|
|
|
|
|
}
|
2002-05-29 21:31:32 +00:00
|
|
|
|
id = desk_popup->insertItem(
|
|
|
|
|
basic_name
|
|
|
|
|
.arg(i)
|
|
|
|
|
.arg( desktopName(i).replace( QRegExp("&"), "&&" )),
|
|
|
|
|
i
|
|
|
|
|
);
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if ( active_client &&
|
|
|
|
|
!active_client->isSticky() && active_client->desktop() == i )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
desk_popup->setItemChecked( id, TRUE );
|
1999-11-22 01:57:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
The client popup menu will become visible soon.
|
1999-12-07 21:54:52 +00:00
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
Adjust the items according to the respective popup client.
|
|
|
|
|
*/
|
1999-11-22 01:57:51 +00:00
|
|
|
|
void Workspace::clientPopupAboutToShow()
|
|
|
|
|
{
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if ( !active_client || !popup )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
2002-06-29 06:31:33 +00:00
|
|
|
|
|
2002-06-11 19:49:38 +00:00
|
|
|
|
if ( numberOfDesktops() == 1 )
|
|
|
|
|
{
|
|
|
|
|
delete desk_popup;
|
|
|
|
|
desk_popup = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
initDesktopPopup();
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-06 07:45:29 +00:00
|
|
|
|
popup->setItemEnabled( Options::ResizeOp, active_client->isResizable() );
|
|
|
|
|
popup->setItemEnabled( Options::MoveOp, active_client->isMovable() );
|
|
|
|
|
popup->setItemEnabled( Options::MaximizeOp, active_client->isMaximizable() );
|
|
|
|
|
popup->setItemChecked( Options::MaximizeOp, active_client->isMaximized() );
|
|
|
|
|
popup->setItemChecked( Options::ShadeOp, active_client->isShade() );
|
|
|
|
|
popup->setItemChecked( Options::StaysOnTopOp, active_client->staysOnTop() );
|
|
|
|
|
popup->setItemEnabled( Options::IconifyOp, active_client->isMinimizable() );
|
|
|
|
|
popup->setItemEnabled( Options::ToggleStoreSettingsOp, !active_client->isTransient() );
|
|
|
|
|
popup->setItemChecked( Options::ToggleStoreSettingsOp, active_client->storeSettings() );
|
1999-11-22 01:57:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
|
|
|
|
|
/*!
|
2000-06-23 18:56:59 +00:00
|
|
|
|
Sends client \a c to desktop \a desk.
|
2000-06-24 17:58:10 +00:00
|
|
|
|
|
2000-06-23 18:56:59 +00:00
|
|
|
|
Takes care of transients as well.
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::sendClientToDesktop( Client* c, int desk )
|
|
|
|
|
{
|
2002-02-28 15:39:40 +00:00
|
|
|
|
if ( c->isSticky() && desk != NETWinInfo::OnAllDesktops )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c->setSticky( FALSE );
|
2000-06-23 18:56:59 +00:00
|
|
|
|
|
|
|
|
|
if ( c->isOnDesktop( desk ) )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
2000-06-23 18:56:59 +00:00
|
|
|
|
|
|
|
|
|
c->setDesktop( desk );
|
2002-02-28 15:39:40 +00:00
|
|
|
|
if( desk == NETWinInfo::OnAllDesktops )
|
2002-02-28 21:04:36 +00:00
|
|
|
|
c->setSticky( true );
|
2002-07-01 04:22:02 +00:00
|
|
|
|
else
|
|
|
|
|
//CT 01Jul2002 - the old position is most probably inappropriate on the new desktop
|
|
|
|
|
// thus we place the client again, before we show it, but only if it's not OnAllDesktops
|
|
|
|
|
place(c);
|
2000-09-29 15:54:18 +00:00
|
|
|
|
|
2001-05-23 20:39:28 +00:00
|
|
|
|
if ( c->isOnDesktop( currentDesktop() ) ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c->show();
|
2001-05-23 20:39:28 +00:00
|
|
|
|
if ( c->wantsTabFocus() && options->focusPolicyIsReasonable() ) {
|
|
|
|
|
requestFocus( c );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
c->hide();
|
2001-05-23 20:39:28 +00:00
|
|
|
|
raiseClient( c );
|
|
|
|
|
focus_chain.remove( c );
|
|
|
|
|
if ( c->wantsTabFocus() )
|
|
|
|
|
focus_chain.append( c );
|
|
|
|
|
}
|
2000-06-23 18:56:59 +00:00
|
|
|
|
|
2002-07-01 04:22:02 +00:00
|
|
|
|
|
2000-06-23 18:56:59 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( (*it)->transientFor() == c->window() ) {
|
|
|
|
|
sendClientToDesktop( *it, desk );
|
|
|
|
|
}
|
2000-06-23 18:56:59 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Sends the popup client to desktop \a desk
|
2000-06-24 17:58:10 +00:00
|
|
|
|
|
2000-06-23 18:56:59 +00:00
|
|
|
|
Internal slot for the window operation menu
|
1999-12-06 00:43:55 +00:00
|
|
|
|
*/
|
1999-11-22 01:57:51 +00:00
|
|
|
|
void Workspace::sendToDesktop( int desk )
|
|
|
|
|
{
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if ( !active_client )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
1999-11-22 18:34:46 +00:00
|
|
|
|
if ( desk == 0 ) {
|
2002-08-06 07:45:29 +00:00
|
|
|
|
active_client->setSticky( !active_client->isSticky() );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
1999-11-22 18:34:46 +00:00
|
|
|
|
}
|
2000-06-24 17:58:10 +00:00
|
|
|
|
|
2002-08-06 07:45:29 +00:00
|
|
|
|
sendClientToDesktop( active_client, desk );
|
1999-11-25 16:38:11 +00:00
|
|
|
|
|
1999-11-22 01:57:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Shows the window operations popup menu for the activeClient()
|
|
|
|
|
*/
|
1999-11-22 01:57:51 +00:00
|
|
|
|
void Workspace::slotWindowOperations()
|
|
|
|
|
{
|
2002-03-03 23:28:04 +00:00
|
|
|
|
if ( !active_client )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
2002-08-06 07:45:29 +00:00
|
|
|
|
if ( active_client->isDesktop()
|
|
|
|
|
|| active_client->isDock()
|
|
|
|
|
|| active_client->isTopMenu())
|
2002-03-03 23:28:04 +00:00
|
|
|
|
return;
|
|
|
|
|
|
1999-11-22 01:57:51 +00:00
|
|
|
|
QPopupMenu* p = clientPopup( active_client );
|
2002-08-06 07:45:29 +00:00
|
|
|
|
// Client* c = active_client;
|
2001-02-01 01:13:44 +00:00
|
|
|
|
p->exec( active_client->mapToGlobal( active_client->windowWrapper()->geometry().topLeft() ) );
|
2002-08-06 07:45:29 +00:00
|
|
|
|
// if ( hasClient( c ) )
|
|
|
|
|
// requestFocus( c );
|
1999-11-22 01:57:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Closes the popup client
|
|
|
|
|
*/
|
1999-11-22 01:57:51 +00:00
|
|
|
|
void Workspace::slotWindowClose()
|
|
|
|
|
{
|
2002-04-05 19:54:21 +00:00
|
|
|
|
if ( tab_box->isVisible() || popupinfo->isVisible() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
2002-08-06 07:45:29 +00:00
|
|
|
|
performWindowOperation( active_client, Options::CloseOp );
|
1999-11-22 01:57:51 +00:00
|
|
|
|
}
|
1999-11-25 16:38:11 +00:00
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
/*!
|
|
|
|
|
Starts keyboard move mode for the popup client
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::slotWindowMove()
|
|
|
|
|
{
|
2002-08-06 07:45:29 +00:00
|
|
|
|
performWindowOperation( active_client, Options::MoveOp );
|
1999-12-06 00:43:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Starts keyboard resize mode for the popup client
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::slotWindowResize()
|
|
|
|
|
{
|
2002-08-06 07:45:29 +00:00
|
|
|
|
performWindowOperation( active_client, Options::ResizeOp );
|
1999-12-06 00:43:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
1999-11-25 16:38:11 +00:00
|
|
|
|
Client \a c is moved around to position \a pos. This gives the
|
|
|
|
|
workspace the opportunity to interveniate and to implement
|
|
|
|
|
snap-to-windows functionality.
|
|
|
|
|
*/
|
|
|
|
|
QPoint Workspace::adjustClientPosition( Client* c, QPoint pos )
|
|
|
|
|
{
|
2000-11-02 08:33:00 +00:00
|
|
|
|
//CT 16mar98, 27May98 - magics: BorderSnapZone, WindowSnapZone
|
|
|
|
|
//CT adapted for kwin on 25Nov1999
|
2000-11-02 18:15:39 +00:00
|
|
|
|
//aleXXX 02Nov2000 added second snapping mode
|
2000-11-02 08:33:00 +00:00
|
|
|
|
if (options->windowSnapZone || options->borderSnapZone )
|
|
|
|
|
{
|
2000-11-02 18:15:39 +00:00
|
|
|
|
bool sOWO=options->snapOnlyWhenOverlapping;
|
2002-02-28 00:43:23 +00:00
|
|
|
|
QRect maxRect = clientArea(MovementArea, pos+c->rect().center());
|
2000-11-02 08:33:00 +00:00
|
|
|
|
int xmin = maxRect.left();
|
2001-02-16 18:05:27 +00:00
|
|
|
|
int xmax = maxRect.right()+1; //desk size
|
2000-11-02 08:33:00 +00:00
|
|
|
|
int ymin = maxRect.top();
|
|
|
|
|
int ymax = maxRect.bottom()+1;
|
|
|
|
|
|
|
|
|
|
int cx(pos.x());
|
|
|
|
|
int cy(pos.y());
|
|
|
|
|
int cw(c->width());
|
|
|
|
|
int ch(c->height());
|
|
|
|
|
int rx(cx+cw);
|
2001-02-16 18:05:27 +00:00
|
|
|
|
int ry(cy+ch); //these don't change
|
2000-11-02 08:33:00 +00:00
|
|
|
|
|
2001-02-16 18:05:27 +00:00
|
|
|
|
int nx(cx), ny(cy); //buffers
|
2000-11-02 08:33:00 +00:00
|
|
|
|
int deltaX(xmax);
|
2001-02-16 18:05:27 +00:00
|
|
|
|
int deltaY(ymax); //minimum distance to other clients
|
2000-11-02 08:33:00 +00:00
|
|
|
|
|
|
|
|
|
int lx, ly, lrx, lry; //coords and size for the comparison client, l
|
|
|
|
|
|
|
|
|
|
// border snap
|
|
|
|
|
int snap = options->borderSnapZone; //snap trigger
|
|
|
|
|
if (snap)
|
|
|
|
|
{
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ((sOWO?(cx<xmin):true) && (QABS(xmin-cx)<snap))
|
|
|
|
|
{
|
|
|
|
|
deltaX = xmin-cx;
|
|
|
|
|
nx = xmin;
|
|
|
|
|
}
|
|
|
|
|
if ((sOWO?(rx>xmax):true) && (QABS(rx-xmax)<snap) && (QABS(xmax-rx) < deltaX))
|
|
|
|
|
{
|
|
|
|
|
deltaX = rx-xmax;
|
|
|
|
|
nx = xmax - cw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((sOWO?(cy<ymin):true) && (QABS(ymin-cy)<snap))
|
|
|
|
|
{
|
|
|
|
|
deltaY = ymin-cy;
|
|
|
|
|
ny = ymin;
|
|
|
|
|
}
|
|
|
|
|
if ((sOWO?(ry>ymax):true) && (QABS(ry-ymax)<snap) && (QABS(ymax-ry) < deltaY))
|
|
|
|
|
{
|
|
|
|
|
deltaY =ry-ymax;
|
|
|
|
|
ny = ymax - ch;
|
|
|
|
|
}
|
1999-11-25 23:12:32 +00:00
|
|
|
|
}
|
1999-11-28 20:10:58 +00:00
|
|
|
|
|
2000-11-02 08:33:00 +00:00
|
|
|
|
// windows snap
|
|
|
|
|
snap = options->windowSnapZone;
|
|
|
|
|
if (snap)
|
|
|
|
|
{
|
2001-02-16 18:05:27 +00:00
|
|
|
|
QValueList<Client *>::ConstIterator l;
|
|
|
|
|
for (l = clients.begin();l != clients.end();++l )
|
|
|
|
|
{
|
2002-03-03 13:56:55 +00:00
|
|
|
|
if ((*l)->isOnDesktop(currentDesktop()) &&
|
2001-06-03 09:30:19 +00:00
|
|
|
|
!(*l)->isIconified()
|
|
|
|
|
#if 0
|
2001-12-09 04:17:36 +00:00
|
|
|
|
&& (*l)->transientFor() == None
|
2001-06-03 09:30:19 +00:00
|
|
|
|
#endif
|
2001-12-09 04:17:36 +00:00
|
|
|
|
&& (*l) != c )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
{
|
|
|
|
|
lx = (*l)->x();
|
|
|
|
|
ly = (*l)->y();
|
|
|
|
|
lrx = lx + (*l)->width();
|
|
|
|
|
lry = ly + (*l)->height();
|
|
|
|
|
|
|
|
|
|
if ( (( cy <= lry ) && ( cy >= ly )) ||
|
|
|
|
|
(( ry >= ly ) && ( ry <= lry )) ||
|
|
|
|
|
(( cy <= ly ) && ( ry >= lry )) )
|
|
|
|
|
{
|
|
|
|
|
if ((sOWO?(cx<lrx):true) && (QABS(lrx-cx)<snap) && ( QABS(lrx -cx) < deltaX) )
|
|
|
|
|
{
|
|
|
|
|
deltaX = QABS( lrx - cx );
|
|
|
|
|
nx = lrx;
|
|
|
|
|
}
|
|
|
|
|
if ((sOWO?(rx>lx):true) && (QABS(rx-lx)<snap) && ( QABS( rx - lx )<deltaX) )
|
|
|
|
|
{
|
|
|
|
|
deltaX = QABS(rx - lx);
|
|
|
|
|
nx = lx - cw;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (( cx <= lrx ) && ( cx >= lx )) ||
|
|
|
|
|
(( rx >= lx ) && ( rx <= lrx )) ||
|
|
|
|
|
(( cx <= lx ) && ( rx >= lrx )) )
|
|
|
|
|
{
|
|
|
|
|
if ((sOWO?(cy<lry):true) && (QABS(lry-cy)<snap) && (QABS( lry -cy ) < deltaY))
|
|
|
|
|
{
|
|
|
|
|
deltaY = QABS( lry - cy );
|
|
|
|
|
ny = lry;
|
|
|
|
|
}
|
|
|
|
|
//if ( (QABS( ry-ly ) < snap) && (QABS( ry - ly ) < deltaY ))
|
|
|
|
|
if ((sOWO?(ry>ly):true) && (QABS(ry-ly)<snap) && (QABS( ry - ly ) < deltaY ))
|
|
|
|
|
{
|
|
|
|
|
deltaY = QABS( ry - ly );
|
|
|
|
|
ny = ly - ch;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-11-25 23:12:32 +00:00
|
|
|
|
}
|
2000-11-02 08:33:00 +00:00
|
|
|
|
pos = QPoint(nx, ny);
|
|
|
|
|
}
|
|
|
|
|
return pos;
|
1999-11-25 16:38:11 +00:00
|
|
|
|
}
|
1999-12-06 00:43:55 +00:00
|
|
|
|
|
|
|
|
|
|
2000-06-21 17:43:44 +00:00
|
|
|
|
/*!
|
|
|
|
|
Returns the child window under the mouse and activates the
|
|
|
|
|
respective client if necessary.
|
|
|
|
|
|
|
|
|
|
Auxiliary function for the mouse emulation system.
|
|
|
|
|
*/
|
|
|
|
|
WId Workspace::getMouseEmulationWindow()
|
|
|
|
|
{
|
|
|
|
|
Window root;
|
|
|
|
|
Window child = qt_xrootwin();
|
|
|
|
|
int root_x, root_y, lx, ly;
|
|
|
|
|
uint state;
|
|
|
|
|
Window w;
|
|
|
|
|
Client * c = 0;
|
|
|
|
|
do {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
w = child;
|
|
|
|
|
if (!c)
|
|
|
|
|
c = findClientWidthId( w );
|
|
|
|
|
XQueryPointer( qt_xdisplay(), w, &root, &child,
|
|
|
|
|
&root_x, &root_y, &lx, &ly, &state );
|
2000-06-21 17:43:44 +00:00
|
|
|
|
} while ( child != None && child != w );
|
|
|
|
|
|
|
|
|
|
if ( c && !c->isActive() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
activateClient( c );
|
2000-06-21 17:43:44 +00:00
|
|
|
|
return (WId) w;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Sends a faked mouse event to the specified window. Returns the new button state.
|
|
|
|
|
*/
|
|
|
|
|
unsigned int Workspace::sendFakedMouseEvent( QPoint pos, WId w, MouseEmulation type, int button, unsigned int state )
|
|
|
|
|
{
|
|
|
|
|
if ( !w )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return state;
|
2000-06-21 17:43:44 +00:00
|
|
|
|
QWidget* widget = QWidget::find( w );
|
|
|
|
|
if ( (!widget || widget->inherits("QToolButton") ) && !findClient( w ) ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
int x, y;
|
|
|
|
|
Window xw;
|
|
|
|
|
XTranslateCoordinates( qt_xdisplay(), qt_xrootwin(), w, pos.x(), pos.y(), &x, &y, &xw );
|
|
|
|
|
if ( type == EmuMove ) { // motion notify events
|
|
|
|
|
XMotionEvent e;
|
|
|
|
|
e.type = MotionNotify;
|
|
|
|
|
e.window = w;
|
|
|
|
|
e.root = qt_xrootwin();
|
|
|
|
|
e.subwindow = w;
|
2002-02-28 22:11:43 +00:00
|
|
|
|
e.time = qt_x_time;
|
2001-02-16 18:05:27 +00:00
|
|
|
|
e.x = x;
|
|
|
|
|
e.y = y;
|
|
|
|
|
e.x_root = pos.x();
|
|
|
|
|
e.y_root = pos.y();
|
|
|
|
|
e.state = state;
|
|
|
|
|
e.is_hint = NotifyNormal;
|
|
|
|
|
XSendEvent( qt_xdisplay(), w, TRUE, ButtonMotionMask, (XEvent*)&e );
|
|
|
|
|
} else {
|
|
|
|
|
XButtonEvent e;
|
|
|
|
|
e.type = type == EmuRelease ? ButtonRelease : ButtonPress;
|
|
|
|
|
e.window = w;
|
|
|
|
|
e.root = qt_xrootwin();
|
|
|
|
|
e.subwindow = w;
|
2002-02-28 22:11:43 +00:00
|
|
|
|
e.time = qt_x_time;
|
2001-02-16 18:05:27 +00:00
|
|
|
|
e.x = x;
|
|
|
|
|
e.y = y;
|
|
|
|
|
e.x_root = pos.x();
|
|
|
|
|
e.y_root = pos.y();
|
|
|
|
|
e.state = state;
|
|
|
|
|
e.button = button;
|
|
|
|
|
XSendEvent( qt_xdisplay(), w, TRUE, ButtonPressMask, (XEvent*)&e );
|
|
|
|
|
|
|
|
|
|
if ( type == EmuPress ) {
|
|
|
|
|
switch ( button ) {
|
|
|
|
|
case 2:
|
|
|
|
|
state |= Button2Mask;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
state |= Button3Mask;
|
|
|
|
|
break;
|
|
|
|
|
default: // 1
|
|
|
|
|
state |= Button1Mask;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
switch ( button ) {
|
|
|
|
|
case 2:
|
|
|
|
|
state &= ~Button2Mask;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
state &= ~Button3Mask;
|
|
|
|
|
break;
|
|
|
|
|
default: // 1
|
|
|
|
|
state &= ~Button1Mask;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-06-21 17:43:44 +00:00
|
|
|
|
}
|
|
|
|
|
return state;
|
|
|
|
|
}
|
|
|
|
|
|
1999-12-07 21:54:52 +00:00
|
|
|
|
/*!
|
1999-12-06 00:43:55 +00:00
|
|
|
|
Handles keypress event during mouse emulation
|
|
|
|
|
*/
|
2002-01-19 04:55:32 +00:00
|
|
|
|
bool Workspace::keyPressMouseEmulation( XKeyEvent& ev )
|
1999-12-06 00:43:55 +00:00
|
|
|
|
{
|
|
|
|
|
if ( root != qt_xrootwin() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return FALSE;
|
2002-01-19 04:55:32 +00:00
|
|
|
|
int kc = XKeycodeToKeysym(qt_xdisplay(), ev.keycode, 0);
|
|
|
|
|
int km = ev.state & (ControlMask | Mod1Mask | ShiftMask);
|
1999-12-07 21:54:52 +00:00
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
bool is_control = km & ControlMask;
|
|
|
|
|
bool is_alt = km & Mod1Mask;
|
2000-06-21 17:43:44 +00:00
|
|
|
|
bool is_shift = km & ShiftMask;
|
1999-12-06 00:43:55 +00:00
|
|
|
|
int delta = is_control?1:is_alt?32:8;
|
|
|
|
|
QPoint pos = QCursor::pos();
|
1999-12-07 21:54:52 +00:00
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
switch ( kc ) {
|
|
|
|
|
case XK_Left:
|
|
|
|
|
case XK_KP_Left:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
pos.rx() -= delta;
|
|
|
|
|
break;
|
1999-12-06 00:43:55 +00:00
|
|
|
|
case XK_Right:
|
|
|
|
|
case XK_KP_Right:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
pos.rx() += delta;
|
|
|
|
|
break;
|
1999-12-06 00:43:55 +00:00
|
|
|
|
case XK_Up:
|
|
|
|
|
case XK_KP_Up:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
pos.ry() -= delta;
|
|
|
|
|
break;
|
1999-12-06 00:43:55 +00:00
|
|
|
|
case XK_Down:
|
|
|
|
|
case XK_KP_Down:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
pos.ry() += delta;
|
|
|
|
|
break;
|
2000-06-21 17:43:44 +00:00
|
|
|
|
case XK_F1:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( !mouse_emulation_state )
|
|
|
|
|
mouse_emulation_window = getMouseEmulationWindow();
|
|
|
|
|
if ( (mouse_emulation_state & Button1Mask) == 0 )
|
|
|
|
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button1, mouse_emulation_state );
|
|
|
|
|
if ( !is_shift )
|
|
|
|
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
|
|
|
|
|
break;
|
2000-06-21 17:43:44 +00:00
|
|
|
|
case XK_F2:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( !mouse_emulation_state )
|
|
|
|
|
mouse_emulation_window = getMouseEmulationWindow();
|
|
|
|
|
if ( (mouse_emulation_state & Button2Mask) == 0 )
|
|
|
|
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button2, mouse_emulation_state );
|
|
|
|
|
if ( !is_shift )
|
|
|
|
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button2, mouse_emulation_state );
|
|
|
|
|
break;
|
2000-06-21 17:43:44 +00:00
|
|
|
|
case XK_F3:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( !mouse_emulation_state )
|
|
|
|
|
mouse_emulation_window = getMouseEmulationWindow();
|
|
|
|
|
if ( (mouse_emulation_state & Button3Mask) == 0 )
|
|
|
|
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button3, mouse_emulation_state );
|
|
|
|
|
if ( !is_shift )
|
|
|
|
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button3, mouse_emulation_state );
|
|
|
|
|
break;
|
1999-12-06 00:43:55 +00:00
|
|
|
|
case XK_Return:
|
|
|
|
|
case XK_space:
|
|
|
|
|
case XK_KP_Enter:
|
2001-01-14 20:16:04 +00:00
|
|
|
|
case XK_KP_Space: {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( !mouse_emulation_state ) {
|
|
|
|
|
// nothing was pressed, fake a LMB click
|
|
|
|
|
mouse_emulation_window = getMouseEmulationWindow();
|
|
|
|
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button1, mouse_emulation_state );
|
|
|
|
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
|
|
|
|
|
} else { // release all
|
|
|
|
|
if ( mouse_emulation_state & Button1Mask )
|
|
|
|
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
|
|
|
|
|
if ( mouse_emulation_state & Button2Mask )
|
|
|
|
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button2, mouse_emulation_state );
|
|
|
|
|
if ( mouse_emulation_state & Button3Mask )
|
|
|
|
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button3, mouse_emulation_state );
|
|
|
|
|
}
|
2001-01-14 20:16:04 +00:00
|
|
|
|
}
|
|
|
|
|
// fall through
|
1999-12-06 00:43:55 +00:00
|
|
|
|
case XK_Escape:
|
2002-02-28 22:11:43 +00:00
|
|
|
|
XUngrabKeyboard(qt_xdisplay(), qt_x_time);
|
2001-02-16 18:05:27 +00:00
|
|
|
|
mouse_emulation = FALSE;
|
|
|
|
|
return TRUE;
|
1999-12-06 00:43:55 +00:00
|
|
|
|
default:
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return FALSE;
|
1999-12-06 00:43:55 +00:00
|
|
|
|
}
|
1999-12-07 21:54:52 +00:00
|
|
|
|
|
1999-12-06 00:43:55 +00:00
|
|
|
|
QCursor::setPos( pos );
|
2000-06-21 17:43:44 +00:00
|
|
|
|
if ( mouse_emulation_state )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuMove, 0, mouse_emulation_state );
|
1999-12-06 00:43:55 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2001-01-25 19:17:17 +00:00
|
|
|
|
void Workspace::slotResetAllClientsDelayed()
|
|
|
|
|
{
|
|
|
|
|
resetTimer.start(200, true);
|
|
|
|
|
}
|
1999-12-24 01:36:47 +00:00
|
|
|
|
|
2000-03-24 22:23:02 +00:00
|
|
|
|
/*!
|
|
|
|
|
Puts a new decoration frame around every client. Used to react on
|
|
|
|
|
style changes.
|
|
|
|
|
*/
|
1999-12-24 01:36:47 +00:00
|
|
|
|
void Workspace::slotResetAllClients()
|
|
|
|
|
{
|
2002-02-27 23:02:40 +00:00
|
|
|
|
QWidget curtain( 0, 0, WX11BypassWM );
|
|
|
|
|
curtain.setBackgroundMode( NoBackground );
|
|
|
|
|
curtain.setGeometry( QApplication::desktop()->geometry() );
|
|
|
|
|
curtain.show();
|
|
|
|
|
|
2001-01-25 19:17:17 +00:00
|
|
|
|
resetTimer.stop();
|
2000-07-15 00:46:38 +00:00
|
|
|
|
ClientList stack = stacking_order;
|
|
|
|
|
Client* active = activeClient();
|
|
|
|
|
block_focus = TRUE;
|
|
|
|
|
Client* prev = 0;
|
|
|
|
|
for (ClientList::Iterator it = stack.fromLast(); it != stack.end(); --it) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
Client *oldClient = (*it);
|
|
|
|
|
Client::MaximizeMode oldMaxMode = oldClient->maximizeMode();
|
2002-02-28 21:04:36 +00:00
|
|
|
|
oldClient->hide();
|
2001-02-16 18:05:27 +00:00
|
|
|
|
WId w = oldClient->window();
|
2002-02-28 21:04:36 +00:00
|
|
|
|
XUnmapWindow( qt_xdisplay(), w );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
oldClient->releaseWindow();
|
|
|
|
|
// Replace oldClient with newClient in all lists
|
|
|
|
|
Client *newClient = clientFactory (w);
|
|
|
|
|
if ( oldClient == active )
|
|
|
|
|
active = newClient;
|
|
|
|
|
ClientList::Iterator jt = clients.find (oldClient);
|
|
|
|
|
(*jt) = newClient;
|
|
|
|
|
jt = stacking_order.find (oldClient);
|
|
|
|
|
(*jt) = newClient;
|
|
|
|
|
jt = focus_chain.find (oldClient);
|
|
|
|
|
(*jt) = newClient;
|
|
|
|
|
newClient->cloneMode(oldClient);
|
|
|
|
|
delete oldClient;
|
|
|
|
|
bool showIt = newClient->manage( TRUE, TRUE, FALSE );
|
2002-02-28 21:04:36 +00:00
|
|
|
|
Window stack[2];
|
|
|
|
|
stack[0] = prev ? prev->winId() : curtain.winId();
|
|
|
|
|
stack[1] = newClient->winId();
|
|
|
|
|
XRestackWindows( qt_xdisplay(), stack, 2 );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if ( showIt )
|
|
|
|
|
newClient->show();
|
2002-02-27 23:02:40 +00:00
|
|
|
|
|
|
|
|
|
if( oldMaxMode != Client::MaximizeRestore ) {
|
2001-11-19 15:35:26 +00:00
|
|
|
|
newClient->maximize(Client::MaximizeRestore); // needed
|
2002-02-28 21:04:36 +00:00
|
|
|
|
newClient->maximize(oldMaxMode);
|
|
|
|
|
}
|
2001-02-16 18:05:27 +00:00
|
|
|
|
prev = newClient;
|
1999-12-24 01:36:47 +00:00
|
|
|
|
}
|
2000-07-15 00:46:38 +00:00
|
|
|
|
block_focus = FALSE;
|
|
|
|
|
if ( active )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
requestFocus( active );
|
2002-03-02 21:03:49 +00:00
|
|
|
|
else if( !desktops.isEmpty() )
|
|
|
|
|
requestFocus( desktops.last() );
|
2001-03-30 11:15:15 +00:00
|
|
|
|
else
|
|
|
|
|
focusToNull();
|
2001-03-23 09:28:40 +00:00
|
|
|
|
|
2002-03-08 07:14:30 +00:00
|
|
|
|
// Emit a DCOP signal to allow other apps to know when the kwin client
|
2001-03-23 09:28:40 +00:00
|
|
|
|
// has been changed by via the titlebar decoration selection.
|
2002-03-08 07:14:30 +00:00
|
|
|
|
emit dcopResetAllClients();
|
1999-12-24 01:36:47 +00:00
|
|
|
|
}
|
2000-03-24 22:23:02 +00:00
|
|
|
|
|
2001-11-30 08:04:17 +00:00
|
|
|
|
void Workspace::slotSettingsChanged(int category)
|
|
|
|
|
{
|
|
|
|
|
kdDebug(1212) << "Workspace::slotSettingsChanged()" << endl;
|
2001-12-29 04:19:24 +00:00
|
|
|
|
if( category == (int) KApplication::SETTINGS_SHORTCUTS )
|
2002-01-19 04:55:32 +00:00
|
|
|
|
readShortcuts();
|
2001-11-30 08:04:17 +00:00
|
|
|
|
}
|
2001-03-19 15:35:07 +00:00
|
|
|
|
|
2001-03-28 12:44:31 +00:00
|
|
|
|
/*
|
2001-03-19 15:35:07 +00:00
|
|
|
|
* Legacy session management
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef NO_LEGACY_SESSION_MANAGEMENT
|
2001-03-28 12:44:31 +00:00
|
|
|
|
#define WM_SAVE_YOURSELF_TIMEOUT 4000
|
2001-03-19 15:35:07 +00:00
|
|
|
|
|
2001-03-20 20:48:40 +00:00
|
|
|
|
typedef QMap<WId,int> WindowMap;
|
|
|
|
|
#define HAS_ERROR 0
|
|
|
|
|
#define HAS_WMCOMMAND 1
|
|
|
|
|
#define HAS_WMSAVEYOURSELF 2
|
2001-03-19 15:35:07 +00:00
|
|
|
|
|
2001-03-20 20:48:40 +00:00
|
|
|
|
static WindowMap *windowMapPtr = 0;
|
2001-03-19 15:35:07 +00:00
|
|
|
|
|
|
|
|
|
static int winsErrorHandler(Display *, XErrorEvent *ev)
|
|
|
|
|
{
|
2001-03-20 20:48:40 +00:00
|
|
|
|
if (windowMapPtr) {
|
|
|
|
|
WindowMap::Iterator it = windowMapPtr->find(ev->resourceid);
|
|
|
|
|
if (it != windowMapPtr->end())
|
|
|
|
|
it.data() = HAS_ERROR;
|
2001-03-19 15:35:07 +00:00
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Stores legacy session management data
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::storeLegacySession( KConfig* config )
|
|
|
|
|
{
|
2001-03-20 20:48:40 +00:00
|
|
|
|
// Setup error handler
|
|
|
|
|
WindowMap wins;
|
|
|
|
|
windowMapPtr = &wins;
|
|
|
|
|
XErrorHandler oldHandler = XSetErrorHandler(winsErrorHandler);
|
|
|
|
|
// Compute set of leader windows that need legacy session management
|
|
|
|
|
// and determine which style (WM_COMMAND or WM_SAVE_YOURSELF)
|
2001-03-19 15:35:07 +00:00
|
|
|
|
for (ClientList::Iterator it = clients.begin(); it != clients.end(); ++it) {
|
|
|
|
|
Client* c = (*it);
|
|
|
|
|
WId leader = c->wmClientLeader();
|
2001-03-20 20:48:40 +00:00
|
|
|
|
if (!wins.contains(leader) && c->sessionId().isEmpty()) {
|
|
|
|
|
int wtype = HAS_WMCOMMAND;
|
|
|
|
|
int nprotocols = 0;
|
|
|
|
|
Atom *protocols = 0;
|
|
|
|
|
XGetWMProtocols(qt_xdisplay(), leader, &protocols, &nprotocols);
|
|
|
|
|
for (int i=0; i<nprotocols; i++)
|
|
|
|
|
if (protocols[i] == atoms->wm_save_yourself) {
|
|
|
|
|
wtype = HAS_WMSAVEYOURSELF;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
XFree((void*) protocols);
|
|
|
|
|
wins.insert(leader, wtype);
|
|
|
|
|
}
|
2001-03-19 15:35:07 +00:00
|
|
|
|
}
|
2001-03-20 20:48:40 +00:00
|
|
|
|
// Open fresh display for sending WM_SAVE_YOURSELF
|
2001-03-19 15:35:07 +00:00
|
|
|
|
XSync(qt_xdisplay(), False);
|
|
|
|
|
Display *newdisplay = XOpenDisplay(DisplayString(qt_xdisplay()));
|
|
|
|
|
if (!newdisplay) return;
|
|
|
|
|
WId root = DefaultRootWindow(newdisplay);
|
2001-03-28 12:44:31 +00:00
|
|
|
|
XGrabKeyboard(newdisplay, root, False,
|
2001-03-19 15:35:07 +00:00
|
|
|
|
GrabModeAsync, GrabModeAsync, CurrentTime);
|
|
|
|
|
XGrabPointer(newdisplay, root, False, Button1Mask|Button2Mask|Button3Mask,
|
|
|
|
|
GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
|
2001-03-20 20:48:40 +00:00
|
|
|
|
// Send WM_SAVE_YOURSELF messages
|
2001-03-19 15:35:07 +00:00
|
|
|
|
XEvent ev;
|
|
|
|
|
int awaiting_replies = 0;
|
2001-03-20 20:48:40 +00:00
|
|
|
|
for (WindowMap::Iterator it = wins.begin(); it != wins.end(); ++it) {
|
|
|
|
|
if ( it.data() == HAS_WMSAVEYOURSELF ) {
|
2001-03-19 15:35:07 +00:00
|
|
|
|
WId w = it.key();
|
|
|
|
|
awaiting_replies += 1;
|
|
|
|
|
memset(&ev, 0, sizeof(ev));
|
|
|
|
|
ev.xclient.type = ClientMessage;
|
|
|
|
|
ev.xclient.window = w;
|
|
|
|
|
ev.xclient.message_type = atoms->wm_protocols;
|
|
|
|
|
ev.xclient.format = 32;
|
|
|
|
|
ev.xclient.data.l[0] = atoms->wm_save_yourself;
|
2002-02-28 22:11:43 +00:00
|
|
|
|
ev.xclient.data.l[1] = qt_x_time;
|
2001-03-19 15:35:07 +00:00
|
|
|
|
XSelectInput(newdisplay, w, PropertyChangeMask|StructureNotifyMask);
|
|
|
|
|
XSendEvent(newdisplay, w, False, 0, &ev);
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-03-20 20:48:40 +00:00
|
|
|
|
// Wait for change in WM_COMMAND with timeout
|
2001-03-19 15:35:07 +00:00
|
|
|
|
XFlush(newdisplay);
|
|
|
|
|
QTime start = QTime::currentTime();
|
|
|
|
|
while (awaiting_replies > 0) {
|
|
|
|
|
if (XPending(newdisplay)) {
|
|
|
|
|
/* Process pending event */
|
|
|
|
|
XNextEvent(newdisplay, &ev);
|
2001-03-20 20:48:40 +00:00
|
|
|
|
if ( ( ev.xany.type == UnmapNotify ) ||
|
|
|
|
|
( ev.xany.type == PropertyNotify && ev.xproperty.atom == XA_WM_COMMAND ) ) {
|
|
|
|
|
WindowMap::Iterator it = wins.find( ev.xany.window );
|
|
|
|
|
if ( it != wins.end() && it.data() != HAS_WMCOMMAND ) {
|
|
|
|
|
awaiting_replies -= 1;
|
|
|
|
|
if ( it.data() != HAS_ERROR )
|
|
|
|
|
it.data() = HAS_WMCOMMAND;
|
|
|
|
|
}
|
2001-03-19 15:35:07 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* Check timeout */
|
|
|
|
|
int msecs = start.elapsed();
|
|
|
|
|
if (msecs >= WM_SAVE_YOURSELF_TIMEOUT)
|
|
|
|
|
break;
|
|
|
|
|
/* Wait for more events */
|
|
|
|
|
fd_set fds;
|
|
|
|
|
FD_ZERO(&fds);
|
2001-03-20 20:48:40 +00:00
|
|
|
|
int fd = ConnectionNumber(newdisplay);
|
2001-03-19 15:35:07 +00:00
|
|
|
|
FD_SET(fd, &fds);
|
2001-03-20 20:48:40 +00:00
|
|
|
|
struct timeval tmwait;
|
2001-03-19 15:35:07 +00:00
|
|
|
|
tmwait.tv_sec = (WM_SAVE_YOURSELF_TIMEOUT - msecs) / 1000;
|
|
|
|
|
tmwait.tv_usec = ((WM_SAVE_YOURSELF_TIMEOUT - msecs) % 1000) * 1000;
|
|
|
|
|
::select(fd+1, &fds, NULL, &fds, &tmwait);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Terminate work in new display
|
|
|
|
|
XAllowEvents(newdisplay, ReplayPointer, CurrentTime);
|
|
|
|
|
XAllowEvents(newdisplay, ReplayKeyboard, CurrentTime);
|
|
|
|
|
XSync(newdisplay, False);
|
|
|
|
|
XCloseDisplay(newdisplay);
|
|
|
|
|
// Write LegacySession data
|
|
|
|
|
config->setGroup("LegacySession" );
|
|
|
|
|
int count = 0;
|
2001-03-20 20:48:40 +00:00
|
|
|
|
for (WindowMap::Iterator it = wins.begin(); it != wins.end(); ++it) {
|
|
|
|
|
if (it.data() != HAS_ERROR) {
|
|
|
|
|
WId w = it.key();
|
|
|
|
|
QCString wmCommand = Client::staticWmCommand(w);
|
|
|
|
|
QCString wmClientMachine = Client::staticWmClientMachine(w);
|
|
|
|
|
if ( !wmCommand.isEmpty() && !wmClientMachine.isEmpty() ) {
|
|
|
|
|
count++;
|
|
|
|
|
QString n = QString::number(count);
|
|
|
|
|
config->writeEntry( QString("command")+n, wmCommand.data() );
|
|
|
|
|
config->writeEntry( QString("clientMachine")+n, wmClientMachine.data() );
|
|
|
|
|
}
|
2001-03-19 15:35:07 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
config->writeEntry( "count", count );
|
|
|
|
|
// Restore old error handler
|
|
|
|
|
XSync(qt_xdisplay(), False);
|
|
|
|
|
XSetErrorHandler(oldHandler);
|
|
|
|
|
// Process a few events to update the client list.
|
|
|
|
|
// All events should be there because of the XSync above.
|
|
|
|
|
kapp->processEvents(10);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Restores legacy session management data (i.e. restart applications)
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::restoreLegacySession( KConfig* config )
|
|
|
|
|
{
|
|
|
|
|
if (config) {
|
|
|
|
|
config->setGroup("LegacySession" );
|
|
|
|
|
int count = config->readNumEntry( "count" );
|
|
|
|
|
for ( int i = 1; i <= count; i++ ) {
|
|
|
|
|
QString n = QString::number(i);
|
|
|
|
|
QCString wmCommand = config->readEntry( QString("command")+n ).latin1();
|
|
|
|
|
QCString wmClientMachine = config->readEntry( QString("clientMachine")+n ).latin1();
|
|
|
|
|
if ( !wmCommand.isEmpty() && !wmClientMachine.isEmpty() ) {
|
2002-06-29 15:05:20 +00:00
|
|
|
|
KProcess proc;
|
|
|
|
|
proc.setUseShell(true);
|
2001-03-19 15:35:07 +00:00
|
|
|
|
if ( wmClientMachine != "localhost" )
|
|
|
|
|
proc << "xon" << wmClientMachine;
|
|
|
|
|
proc << QString::fromLatin1( wmCommand );
|
2002-06-29 15:05:20 +00:00
|
|
|
|
proc.start(KProcess::DontCare);
|
2001-03-19 15:35:07 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-24 22:23:02 +00:00
|
|
|
|
/*!
|
|
|
|
|
Stores the current session in the config file
|
2000-06-23 16:26:44 +00:00
|
|
|
|
|
2000-06-22 14:12:13 +00:00
|
|
|
|
\sa loadSessionInfo()
|
2000-03-24 22:23:02 +00:00
|
|
|
|
*/
|
|
|
|
|
void Workspace::storeSession( KConfig* config )
|
|
|
|
|
{
|
2001-03-19 15:35:07 +00:00
|
|
|
|
#ifndef NO_LEGACY_SESSION_MANAGEMENT
|
|
|
|
|
storeLegacySession(config);
|
|
|
|
|
#endif
|
2000-03-24 22:23:02 +00:00
|
|
|
|
config->setGroup("Session" );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
int count = 0;
|
2000-03-24 22:23:02 +00:00
|
|
|
|
for (ClientList::Iterator it = clients.begin(); it != clients.end(); ++it) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
Client* c = (*it);
|
|
|
|
|
QCString sessionId = c->sessionId();
|
|
|
|
|
QCString wmCommand = c->wmCommand();
|
2001-03-19 15:35:07 +00:00
|
|
|
|
if ( sessionId.isEmpty() )
|
|
|
|
|
#ifndef NO_LEGACY_SESSION_MANAGEMENT
|
|
|
|
|
// This is the only connection between the determination of legacy
|
|
|
|
|
// session managed applications (storeLegacySession) and the
|
|
|
|
|
// recollection of the window geometries (this function).
|
|
|
|
|
if ( wmCommand.isEmpty() )
|
2001-03-28 12:44:31 +00:00
|
|
|
|
#endif
|
2001-03-19 15:35:07 +00:00
|
|
|
|
continue;
|
|
|
|
|
count++;
|
|
|
|
|
QString n = QString::number(count);
|
|
|
|
|
config->writeEntry( QString("sessionId")+n, sessionId.data() );
|
|
|
|
|
config->writeEntry( QString("windowRole")+n, c->windowRole().data() );
|
|
|
|
|
config->writeEntry( QString("wmCommand")+n, wmCommand.data() );
|
|
|
|
|
config->writeEntry( QString("wmClientMachine")+n, c->wmClientMachine().data() );
|
|
|
|
|
config->writeEntry( QString("resourceName")+n, c->resourceName().data() );
|
|
|
|
|
config->writeEntry( QString("resourceClass")+n, c->resourceClass().data() );
|
2002-03-02 01:34:31 +00:00
|
|
|
|
config->writeEntry( QString("geometry")+n, QRect( c->gravitate(TRUE), c->windowWrapper()->size() ) );
|
2001-03-19 15:35:07 +00:00
|
|
|
|
config->writeEntry( QString("restore")+n, c->geometryRestore() );
|
|
|
|
|
config->writeEntry( QString("maximize")+n, (int) c->maximizeMode() );
|
|
|
|
|
config->writeEntry( QString("desktop")+n, c->desktop() );
|
|
|
|
|
config->writeEntry( QString("iconified")+n, c->isIconified() );
|
|
|
|
|
config->writeEntry( QString("sticky")+n, c->isSticky() );
|
|
|
|
|
config->writeEntry( QString("shaded")+n, c->isShade() );
|
|
|
|
|
config->writeEntry( QString("staysOnTop")+n, c->staysOnTop() );
|
|
|
|
|
config->writeEntry( QString("skipTaskbar")+n, c->skipTaskbar() );
|
2001-05-02 20:37:30 +00:00
|
|
|
|
config->writeEntry( QString("skipPager")+n, c->skipPager() );
|
2000-03-24 22:23:02 +00:00
|
|
|
|
}
|
|
|
|
|
config->writeEntry( "count", count );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-06-22 14:12:13 +00:00
|
|
|
|
/*!
|
|
|
|
|
Loads the session information from the config file.
|
2000-06-23 16:26:44 +00:00
|
|
|
|
|
2000-06-22 14:12:13 +00:00
|
|
|
|
\sa storeSession()
|
|
|
|
|
*/
|
2000-03-24 22:23:02 +00:00
|
|
|
|
void Workspace::loadSessionInfo()
|
|
|
|
|
{
|
|
|
|
|
session.clear();
|
|
|
|
|
KConfig* config = kapp->sessionConfig();
|
|
|
|
|
config->setGroup("Session" );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
int count = config->readNumEntry( "count" );
|
2001-01-14 20:16:04 +00:00
|
|
|
|
for ( int i = 1; i <= count; i++ ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
QString n = QString::number(i);
|
|
|
|
|
SessionInfo* info = new SessionInfo;
|
|
|
|
|
session.append( info );
|
|
|
|
|
info->sessionId = config->readEntry( QString("sessionId")+n ).latin1();
|
|
|
|
|
info->windowRole = config->readEntry( QString("windowRole")+n ).latin1();
|
|
|
|
|
info->wmCommand = config->readEntry( QString("wmCommand")+n ).latin1();
|
2001-03-19 15:35:07 +00:00
|
|
|
|
info->wmClientMachine = config->readEntry( QString("wmClientMachine")+n ).latin1();
|
|
|
|
|
info->resourceName = config->readEntry( QString("resourceName")+n ).latin1();
|
|
|
|
|
info->resourceClass = config->readEntry( QString("resourceClass")+n ).latin1();
|
2001-02-16 18:05:27 +00:00
|
|
|
|
info->geometry = config->readRectEntry( QString("geometry")+n );
|
|
|
|
|
info->restore = config->readRectEntry( QString("restore")+n );
|
|
|
|
|
info->maximize = config->readNumEntry( QString("maximize")+n, 0 );
|
|
|
|
|
info->desktop = config->readNumEntry( QString("desktop")+n, 0 );
|
|
|
|
|
info->iconified = config->readBoolEntry( QString("iconified")+n, FALSE );
|
|
|
|
|
info->sticky = config->readBoolEntry( QString("sticky")+n, FALSE );
|
|
|
|
|
info->shaded = config->readBoolEntry( QString("shaded")+n, FALSE );
|
|
|
|
|
info->staysOnTop = config->readBoolEntry( QString("staysOnTop")+n, FALSE );
|
2001-12-09 04:17:36 +00:00
|
|
|
|
info->skipTaskbar = config->readBoolEntry( QString("skipTaskbar")+n, FALSE );
|
|
|
|
|
info->skipPager = config->readBoolEntry( QString("skipPager")+n, FALSE );
|
2001-01-14 20:16:04 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Workspace::loadFakeSessionInfo()
|
|
|
|
|
{
|
|
|
|
|
fakeSession.clear();
|
|
|
|
|
KConfig *config = KGlobal::config();
|
|
|
|
|
config->setGroup("FakeSession" );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
int count = config->readNumEntry( "count" );
|
2000-03-24 22:23:02 +00:00
|
|
|
|
for ( int i = 1; i <= count; i++ ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
QString n = QString::number(i);
|
|
|
|
|
SessionInfo* info = new SessionInfo;
|
|
|
|
|
fakeSession.append( info );
|
|
|
|
|
info->resourceName = config->readEntry( QString("resourceName")+n ).latin1();
|
|
|
|
|
info->resourceClass = config->readEntry( QString("resourceClass")+n ).latin1();
|
2001-03-19 15:35:07 +00:00
|
|
|
|
info->wmClientMachine = config->readEntry( QString("clientMachine")+n ).latin1();
|
2001-02-16 18:05:27 +00:00
|
|
|
|
info->geometry = config->readRectEntry( QString("geometry")+n );
|
|
|
|
|
info->restore = config->readRectEntry( QString("restore")+n );
|
|
|
|
|
info->maximize = config->readNumEntry( QString("maximize")+n, 0 );
|
|
|
|
|
info->desktop = config->readNumEntry( QString("desktop")+n, 0 );
|
|
|
|
|
info->iconified = config->readBoolEntry( QString("iconified")+n, FALSE );
|
|
|
|
|
info->sticky = config->readBoolEntry( QString("sticky")+n, FALSE );
|
|
|
|
|
info->shaded = config->readBoolEntry( QString("shaded")+n, FALSE );
|
|
|
|
|
info->staysOnTop = config->readBoolEntry( QString("staysOnTop")+n, FALSE );
|
2001-12-09 04:17:36 +00:00
|
|
|
|
info->skipTaskbar = config->readBoolEntry( QString("skipTaskbar")+n, FALSE );
|
|
|
|
|
info->skipPager = config->readBoolEntry( QString("skipPager")+n, FALSE );
|
2001-01-14 20:16:04 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Workspace::storeFakeSessionInfo( Client* c )
|
|
|
|
|
{
|
|
|
|
|
if ( !c->storeSettings() )
|
2001-02-16 18:05:27 +00:00
|
|
|
|
return;
|
2001-01-14 20:16:04 +00:00
|
|
|
|
SessionInfo* info = new SessionInfo;
|
|
|
|
|
fakeSession.append( info );
|
|
|
|
|
info->resourceName = c->resourceName();
|
|
|
|
|
info->resourceClass = c->resourceClass();
|
2001-03-19 15:35:07 +00:00
|
|
|
|
info->wmClientMachine = c->wmClientMachine();
|
2002-03-02 01:34:31 +00:00
|
|
|
|
info->geometry = QRect( c->gravitate(TRUE), c->windowWrapper()->size() ) ;
|
2001-01-14 20:16:04 +00:00
|
|
|
|
info->restore = c->geometryRestore();
|
|
|
|
|
info->maximize = (int)c->maximizeMode();
|
|
|
|
|
info->desktop = c->desktop();
|
|
|
|
|
info->iconified = c->isIconified();
|
|
|
|
|
info->sticky = c->isSticky();
|
|
|
|
|
info->shaded = c->isShade();
|
|
|
|
|
info->staysOnTop = c->staysOnTop();
|
2001-03-12 21:32:13 +00:00
|
|
|
|
info->skipTaskbar = c->skipTaskbar();
|
2001-05-02 20:37:30 +00:00
|
|
|
|
info->skipPager = c->skipPager();
|
2001-01-14 20:16:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Workspace::writeFakeSessionInfo()
|
|
|
|
|
{
|
|
|
|
|
KConfig *config = KGlobal::config();
|
|
|
|
|
config->setGroup("FakeSession" );
|
|
|
|
|
int count = 0;
|
|
|
|
|
for ( SessionInfo* info = fakeSession.first(); info; info = fakeSession.next() ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
count++;
|
|
|
|
|
QString n = QString::number(count);
|
|
|
|
|
config->writeEntry( QString("resourceName")+n, info->resourceName.data() );
|
|
|
|
|
config->writeEntry( QString("resourceClass")+n, info->resourceClass.data() );
|
2001-03-19 15:35:07 +00:00
|
|
|
|
config->writeEntry( QString("clientMachine")+n, info->wmClientMachine.data() );
|
2001-02-16 18:05:27 +00:00
|
|
|
|
config->writeEntry( QString("geometry")+n, info->geometry );
|
|
|
|
|
config->writeEntry( QString("restore")+n, info->restore );
|
|
|
|
|
config->writeEntry( QString("maximize")+n, info->maximize );
|
|
|
|
|
config->writeEntry( QString("desktop")+n, info->desktop );
|
|
|
|
|
config->writeEntry( QString("iconified")+n, info->iconified );
|
|
|
|
|
config->writeEntry( QString("sticky")+n, info->sticky );
|
|
|
|
|
config->writeEntry( QString("shaded")+n, info->shaded );
|
|
|
|
|
config->writeEntry( QString("staysOnTop")+n, info->staysOnTop );
|
2001-06-18 20:18:32 +00:00
|
|
|
|
config->writeEntry( QString("skipTaskbar")+n, info->skipTaskbar );
|
|
|
|
|
config->writeEntry( QString("skipPager")+n, info->skipPager );
|
2000-03-24 22:23:02 +00:00
|
|
|
|
}
|
2001-01-14 20:16:04 +00:00
|
|
|
|
config->writeEntry( "count", count );
|
2000-03-24 22:23:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-23 16:26:44 +00:00
|
|
|
|
/*!
|
2001-03-19 15:35:07 +00:00
|
|
|
|
Returns a SessionInfo for client \a c. The returned session
|
2000-06-22 14:12:13 +00:00
|
|
|
|
info is removed from the storage. It's up to the caller to delete it.
|
2000-06-23 16:26:44 +00:00
|
|
|
|
|
2001-03-19 15:35:07 +00:00
|
|
|
|
This function is called when a new window is mapped and must be managed.
|
|
|
|
|
We try to find a matching entry in the session. We also try to find
|
|
|
|
|
a matching entry in the fakeSession to see if the user had seclected the
|
2001-03-28 12:44:31 +00:00
|
|
|
|
``store settings'' menu entry.
|
2001-03-19 15:35:07 +00:00
|
|
|
|
|
2000-06-22 14:12:13 +00:00
|
|
|
|
May return 0 if there's no session info for the client.
|
|
|
|
|
*/
|
2000-03-24 22:23:02 +00:00
|
|
|
|
SessionInfo* Workspace::takeSessionInfo( Client* c )
|
|
|
|
|
{
|
2001-03-19 15:35:07 +00:00
|
|
|
|
SessionInfo *realInfo = 0;
|
|
|
|
|
SessionInfo *fakeInfo = 0;
|
|
|
|
|
QCString sessionId = c->sessionId();
|
|
|
|
|
QCString windowRole = c->windowRole();
|
|
|
|
|
QCString wmCommand = c->wmCommand();
|
|
|
|
|
QCString wmClientMachine = c->wmClientMachine();
|
|
|
|
|
QCString resourceName = c->resourceName();
|
|
|
|
|
QCString resourceClass = c->resourceClass();
|
2001-03-28 12:44:31 +00:00
|
|
|
|
|
2001-03-19 15:35:07 +00:00
|
|
|
|
// First search ``session''
|
|
|
|
|
if (! sessionId.isEmpty() ) {
|
|
|
|
|
// look for a real session managed client (algorithm suggested by ICCCM)
|
2001-03-28 12:44:31 +00:00
|
|
|
|
for (SessionInfo* info = session.first(); info && !realInfo; info = session.next() )
|
2001-03-19 15:35:07 +00:00
|
|
|
|
if ( info->sessionId == sessionId ) {
|
|
|
|
|
if ( ! windowRole.isEmpty() ) {
|
|
|
|
|
if ( info->windowRole == windowRole )
|
|
|
|
|
realInfo = session.take();
|
|
|
|
|
} else {
|
2001-03-28 12:44:31 +00:00
|
|
|
|
if ( info->windowRole.isEmpty() &&
|
|
|
|
|
info->resourceName == resourceName &&
|
2001-03-19 15:35:07 +00:00
|
|
|
|
info->resourceClass == resourceClass )
|
|
|
|
|
realInfo = session.take();
|
|
|
|
|
}
|
2001-02-16 18:05:27 +00:00
|
|
|
|
}
|
2001-03-19 15:35:07 +00:00
|
|
|
|
} else {
|
|
|
|
|
// look for a sessioninfo with matching features.
|
2001-03-28 12:44:31 +00:00
|
|
|
|
for (SessionInfo* info = session.first(); info && !realInfo; info = session.next() )
|
|
|
|
|
if ( info->resourceName == resourceName &&
|
2001-03-19 15:35:07 +00:00
|
|
|
|
info->resourceClass == resourceClass &&
|
|
|
|
|
info->wmClientMachine == wmClientMachine )
|
|
|
|
|
if ( wmCommand.isEmpty() || info->wmCommand == wmCommand )
|
|
|
|
|
realInfo = session.take();
|
|
|
|
|
}
|
2001-03-28 12:44:31 +00:00
|
|
|
|
|
2001-03-19 15:35:07 +00:00
|
|
|
|
// Now search ``fakeSession''
|
|
|
|
|
for (SessionInfo* info = fakeSession.first(); info && !fakeInfo; info = fakeSession.next() )
|
2001-03-28 12:44:31 +00:00
|
|
|
|
if ( info->resourceName == resourceName &&
|
2001-03-19 15:35:07 +00:00
|
|
|
|
info->resourceClass == resourceClass &&
|
2001-03-28 12:44:31 +00:00
|
|
|
|
info->wmClientMachine == wmClientMachine )
|
2001-03-19 15:35:07 +00:00
|
|
|
|
fakeInfo = fakeSession.take();
|
2001-03-28 12:44:31 +00:00
|
|
|
|
|
2001-03-19 15:35:07 +00:00
|
|
|
|
// Reconciliate
|
|
|
|
|
if (fakeInfo)
|
|
|
|
|
c->setStoreSettings( TRUE );
|
|
|
|
|
if (fakeInfo && realInfo)
|
|
|
|
|
delete fakeInfo;
|
|
|
|
|
if (realInfo)
|
|
|
|
|
return realInfo;
|
|
|
|
|
if (fakeInfo)
|
|
|
|
|
return fakeInfo;
|
2000-03-24 22:23:02 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
Preliminary support for avoiding covering clients such as kicker
which want to be permanently visible.
I've used an XAtom called '_NET_AVOID_SPEC'. This of course can change
if need be. I think it's correct according to the wm spec, but the
wm spec seems to be empty on gnome.org, so who knows.
Windows can choose to be avoided by setting an XTextProperty
with one value, which can be either 'N', 'S', 'E', or 'W', according
to which screen edge they are anchored to.
kwin then sets its 'clientArea' rect appropriately, so that (in
theory at least) clients will not enter this area in some circumstances,
such as when being mapped for the first time.
You can see that this actually works if you start lots of konsoles. They
don't appear over the panel. I don't know what happens if you move the
panel, but I presume things will be screwed up, because I haven't
looked at that yet.
If you maximise a window, it'll still fill the screen, because the
implementation of maximise in kwin/client.cpp doesn't take account
of the workspace's clientArea rect. This is easy to fix, but I've
been awake for too long, so I'll do it after 42 winks.
svn path=/trunk/kdebase/kwin/; revision=46772
2000-04-16 09:06:03 +00:00
|
|
|
|
|
2000-06-22 14:12:13 +00:00
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Updates the current client area according to the current clients.
|
2000-06-23 16:26:44 +00:00
|
|
|
|
|
2000-06-22 14:12:13 +00:00
|
|
|
|
If the area changes, the new area is propagate to the world.
|
2000-06-22 18:08:35 +00:00
|
|
|
|
|
|
|
|
|
The client area is the area that is available for clients (that
|
|
|
|
|
which is not taken by windows like panels, the top-of-screen menu
|
|
|
|
|
etc).
|
2000-06-23 16:26:44 +00:00
|
|
|
|
|
2000-06-22 14:12:13 +00:00
|
|
|
|
\sa clientArea()
|
|
|
|
|
*/
|
2000-05-26 13:54:50 +00:00
|
|
|
|
void Workspace::updateClientArea()
|
Preliminary support for avoiding covering clients such as kicker
which want to be permanently visible.
I've used an XAtom called '_NET_AVOID_SPEC'. This of course can change
if need be. I think it's correct according to the wm spec, but the
wm spec seems to be empty on gnome.org, so who knows.
Windows can choose to be avoided by setting an XTextProperty
with one value, which can be either 'N', 'S', 'E', or 'W', according
to which screen edge they are anchored to.
kwin then sets its 'clientArea' rect appropriately, so that (in
theory at least) clients will not enter this area in some circumstances,
such as when being mapped for the first time.
You can see that this actually works if you start lots of konsoles. They
don't appear over the panel. I don't know what happens if you move the
panel, but I presume things will be screwed up, because I haven't
looked at that yet.
If you maximise a window, it'll still fill the screen, because the
implementation of maximise in kwin/client.cpp doesn't take account
of the workspace's clientArea rect. This is easy to fix, but I've
been awake for too long, so I'll do it after 42 winks.
svn path=/trunk/kdebase/kwin/; revision=46772
2000-04-16 09:06:03 +00:00
|
|
|
|
{
|
2000-06-08 17:05:51 +00:00
|
|
|
|
QRect all = QApplication::desktop()->geometry();
|
|
|
|
|
QRect a = all;
|
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
a = a.intersect( (*it)->adjustedClientArea( all ) );
|
2000-05-26 13:54:50 +00:00
|
|
|
|
}
|
2000-06-21 17:43:44 +00:00
|
|
|
|
|
2000-06-08 17:05:51 +00:00
|
|
|
|
if ( area != a ) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
area = a;
|
|
|
|
|
NETRect r;
|
|
|
|
|
r.pos.x = area.x();
|
|
|
|
|
r.pos.y = area.y();
|
|
|
|
|
r.size.width = area.width();
|
|
|
|
|
r.size.height = area.height();
|
|
|
|
|
for( int i = 1; i <= numberOfDesktops(); i++)
|
2001-02-10 00:27:26 +00:00
|
|
|
|
{
|
2001-02-16 18:05:27 +00:00
|
|
|
|
rootInfo->setWorkArea( i, r );
|
2001-02-10 00:27:26 +00:00
|
|
|
|
}
|
2000-12-17 21:57:52 +00:00
|
|
|
|
|
2001-02-16 18:05:27 +00:00
|
|
|
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
|
|
|
|
if ( (*it)->isMaximized() )
|
|
|
|
|
(*it)->maximize( Client::MaximizeAdjust );
|
|
|
|
|
}
|
Preliminary support for avoiding covering clients such as kicker
which want to be permanently visible.
I've used an XAtom called '_NET_AVOID_SPEC'. This of course can change
if need be. I think it's correct according to the wm spec, but the
wm spec seems to be empty on gnome.org, so who knows.
Windows can choose to be avoided by setting an XTextProperty
with one value, which can be either 'N', 'S', 'E', or 'W', according
to which screen edge they are anchored to.
kwin then sets its 'clientArea' rect appropriately, so that (in
theory at least) clients will not enter this area in some circumstances,
such as when being mapped for the first time.
You can see that this actually works if you start lots of konsoles. They
don't appear over the panel. I don't know what happens if you move the
panel, but I presume things will be screwed up, because I haven't
looked at that yet.
If you maximise a window, it'll still fill the screen, because the
implementation of maximise in kwin/client.cpp doesn't take account
of the workspace's clientArea rect. This is easy to fix, but I've
been awake for too long, so I'll do it after 42 winks.
svn path=/trunk/kdebase/kwin/; revision=46772
2000-04-16 09:06:03 +00:00
|
|
|
|
}
|
2000-05-04 23:12:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-22 14:12:13 +00:00
|
|
|
|
|
2000-06-23 16:26:44 +00:00
|
|
|
|
/*!
|
2000-06-22 18:08:35 +00:00
|
|
|
|
returns the area available for clients. This is the desktop
|
|
|
|
|
geometry minus windows on the dock. Placement algorithms should
|
2000-06-23 16:26:44 +00:00
|
|
|
|
refer to this rather than geometry().
|
|
|
|
|
|
2000-06-22 18:08:35 +00:00
|
|
|
|
\sa geometry()
|
2000-06-22 14:12:13 +00:00
|
|
|
|
*/
|
2002-02-28 00:43:23 +00:00
|
|
|
|
QRect Workspace::clientArea(clientAreaOption opt, const QPoint& p)
|
2000-05-06 18:59:43 +00:00
|
|
|
|
{
|
2001-05-12 00:33:43 +00:00
|
|
|
|
QRect rect = QApplication::desktop()->geometry();
|
2001-08-18 23:06:16 +00:00
|
|
|
|
QDesktopWidget *desktop = KApplication::desktop();
|
2001-06-03 09:04:03 +00:00
|
|
|
|
|
|
|
|
|
switch (opt) {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
case MaximizeArea:
|
|
|
|
|
if (options->xineramaMaximizeEnabled)
|
2002-02-28 00:43:23 +00:00
|
|
|
|
rect = desktop->screenGeometry(desktop->screenNumber(p));
|
2001-12-09 04:17:36 +00:00
|
|
|
|
break;
|
|
|
|
|
case PlacementArea:
|
|
|
|
|
if (options->xineramaPlacementEnabled)
|
2002-02-28 00:43:23 +00:00
|
|
|
|
rect = desktop->screenGeometry(desktop->screenNumber(p));
|
2001-12-09 04:17:36 +00:00
|
|
|
|
break;
|
|
|
|
|
case MovementArea:
|
|
|
|
|
if (options->xineramaMovementEnabled)
|
2002-02-28 00:43:23 +00:00
|
|
|
|
rect = desktop->screenGeometry(desktop->screenNumber(p));
|
2001-12-09 04:17:36 +00:00
|
|
|
|
break;
|
2001-05-12 00:33:43 +00:00
|
|
|
|
}
|
2002-02-28 00:43:23 +00:00
|
|
|
|
|
|
|
|
|
if (area.isNull())
|
2001-12-09 04:17:36 +00:00
|
|
|
|
return rect;
|
2002-02-28 00:43:23 +00:00
|
|
|
|
|
2001-05-12 00:33:43 +00:00
|
|
|
|
return area.intersect(rect);
|
2000-05-06 18:59:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-02-28 00:43:23 +00:00
|
|
|
|
QRect Workspace::clientArea(const QPoint& p)
|
2001-06-03 09:30:19 +00:00
|
|
|
|
{
|
2002-02-28 00:43:23 +00:00
|
|
|
|
int screenNum = QApplication::desktop()->screenNumber(p);
|
|
|
|
|
QRect rect = QApplication::desktop()->screenGeometry(screenNum);
|
|
|
|
|
|
|
|
|
|
if (area.isNull())
|
|
|
|
|
return rect;
|
|
|
|
|
|
|
|
|
|
return area.intersect(rect);
|
2001-06-03 09:30:19 +00:00
|
|
|
|
}
|
2000-06-28 13:20:42 +00:00
|
|
|
|
|
2000-07-12 18:08:24 +00:00
|
|
|
|
void Workspace::loadDesktopSettings()
|
|
|
|
|
{
|
|
|
|
|
KConfig c("kdeglobals");
|
2001-02-06 18:32:07 +00:00
|
|
|
|
|
|
|
|
|
QCString groupname;
|
|
|
|
|
if (kwin_screen_number == 0)
|
2001-02-16 18:05:27 +00:00
|
|
|
|
groupname = "Desktops";
|
2001-02-06 18:32:07 +00:00
|
|
|
|
else
|
2001-02-16 18:05:27 +00:00
|
|
|
|
groupname.sprintf("Desktops-screen-%d", kwin_screen_number);
|
2001-02-06 18:32:07 +00:00
|
|
|
|
c.setGroup(groupname);
|
|
|
|
|
|
2000-07-13 17:59:12 +00:00
|
|
|
|
int n = c.readNumEntry("Number", 4);
|
2000-07-12 18:08:24 +00:00
|
|
|
|
number_of_desktops = n;
|
|
|
|
|
rootInfo->setNumberOfDesktops( number_of_desktops );
|
2001-06-10 04:10:42 +00:00
|
|
|
|
desktop_focus_chain.resize( n );
|
2000-07-12 18:08:24 +00:00
|
|
|
|
for(int i = 1; i <= n; i++) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
QString s = c.readEntry(QString("Name_%1").arg(i),
|
|
|
|
|
i18n("Desktop %1").arg(i));
|
|
|
|
|
rootInfo->setDesktopName( i, s.utf8().data() );
|
2001-06-10 04:10:42 +00:00
|
|
|
|
desktop_focus_chain[i-1] = i;
|
2000-07-12 18:08:24 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Workspace::saveDesktopSettings()
|
|
|
|
|
{
|
|
|
|
|
KConfig c("kdeglobals");
|
2001-02-06 18:32:07 +00:00
|
|
|
|
|
|
|
|
|
QCString groupname;
|
|
|
|
|
if (kwin_screen_number == 0)
|
2001-02-16 18:05:27 +00:00
|
|
|
|
groupname = "Desktops";
|
2001-02-06 18:32:07 +00:00
|
|
|
|
else
|
2001-02-16 18:05:27 +00:00
|
|
|
|
groupname.sprintf("Desktops-screen-%d", kwin_screen_number);
|
2001-02-06 18:32:07 +00:00
|
|
|
|
c.setGroup(groupname);
|
|
|
|
|
|
2000-07-12 18:08:24 +00:00
|
|
|
|
c.writeEntry("Number", number_of_desktops );
|
|
|
|
|
for(int i = 1; i <= number_of_desktops; i++) {
|
2001-02-16 18:05:27 +00:00
|
|
|
|
QString s = desktopName( i );
|
|
|
|
|
QString defaultvalue = i18n("Desktop %1").arg(i);
|
|
|
|
|
if ( s.isEmpty() ) {
|
|
|
|
|
s = defaultvalue;
|
|
|
|
|
rootInfo->setDesktopName( i, s.utf8().data() );
|
|
|
|
|
}
|
2001-01-14 20:16:04 +00:00
|
|
|
|
|
2001-02-16 18:05:27 +00:00
|
|
|
|
if (s != defaultvalue) {
|
|
|
|
|
c.writeEntry( QString("Name_%1").arg(i), s );
|
|
|
|
|
} else {
|
|
|
|
|
QString currentvalue = c.readEntry(QString("Name_%1").arg(i));
|
|
|
|
|
if (currentvalue != defaultvalue)
|
|
|
|
|
c.writeEntry( QString("Name_%1").arg(i), "" );
|
|
|
|
|
}
|
2000-07-12 18:08:24 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-02-03 12:30:46 +00:00
|
|
|
|
/*!
|
|
|
|
|
Checks whether focus is in nirvana, and activates a client instead.
|
|
|
|
|
*/
|
|
|
|
|
void Workspace::focusEnsurance()
|
|
|
|
|
{
|
|
|
|
|
Window focus;
|
|
|
|
|
int revert;
|
|
|
|
|
XGetInputFocus( qt_xdisplay(), &focus, &revert );
|
|
|
|
|
if ( focus == None || focus == PointerRoot ) {
|
2001-12-09 04:17:36 +00:00
|
|
|
|
|
|
|
|
|
Window root_return;
|
|
|
|
|
Window child = root;
|
|
|
|
|
int root_x, root_y, lx, ly;
|
|
|
|
|
uint state;
|
|
|
|
|
if ( ! XQueryPointer( qt_xdisplay(), root, &root_return, &child,
|
|
|
|
|
&root_x, &root_y, &lx, &ly, &state ) )
|
|
|
|
|
return; // cursor is on another screen, so do not play with focus
|
|
|
|
|
|
|
|
|
|
if ( !last_active_client )
|
|
|
|
|
last_active_client = topClientOnDesktop();
|
|
|
|
|
if ( last_active_client && last_active_client->isVisible() ) {
|
2002-02-28 22:11:43 +00:00
|
|
|
|
qt_x_time = CurrentTime;
|
2001-12-09 04:17:36 +00:00
|
|
|
|
requestFocus( last_active_client );
|
|
|
|
|
}
|
2001-02-03 12:30:46 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-05-10 17:54:57 +00:00
|
|
|
|
void Workspace::configureWM()
|
|
|
|
|
{
|
|
|
|
|
QStringList args;
|
2002-07-11 20:54:54 +00:00
|
|
|
|
args << "kwindecoration" << "kwinactions" << "kwinfocus" << "kwinmoving" << "kwinadvanced";
|
2001-05-10 17:54:57 +00:00
|
|
|
|
KApplication::kdeinitExec( "kcmshell", args );
|
|
|
|
|
}
|
|
|
|
|
|
2001-05-24 21:01:09 +00:00
|
|
|
|
void Workspace::checkStartOnDesktop( WId w )
|
|
|
|
|
{
|
|
|
|
|
KStartupInfoData data;
|
|
|
|
|
if( d->startup->checkStartup( w, data ) != KStartupInfo::Match || data.desktop() == 0 )
|
|
|
|
|
return;
|
2001-07-12 13:50:19 +00:00
|
|
|
|
NETWinInfo info( qt_xdisplay(), w, root, NET::WMDesktop );
|
2001-05-24 21:01:09 +00:00
|
|
|
|
if( info.desktop() == 0 )
|
|
|
|
|
info.setDesktop( data.desktop());
|
|
|
|
|
}
|
2001-06-03 09:30:19 +00:00
|
|
|
|
|
2001-08-27 05:42:32 +00:00
|
|
|
|
// Electric Borders
|
|
|
|
|
//========================================================================//
|
|
|
|
|
// Electric Border Window management. Electric borders allow a user
|
|
|
|
|
// to change the virtual desktop by moving the mouse pointer to the
|
|
|
|
|
// borders. Technically this is done with input only windows. Since
|
|
|
|
|
// electric borders can be switched on and off, we have these two
|
|
|
|
|
// functions to create and destroy them.
|
|
|
|
|
void Workspace::createBorderWindows()
|
|
|
|
|
{
|
|
|
|
|
if ( d->electric_have_borders )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
d->electric_have_borders = true;
|
2001-11-03 00:05:33 +00:00
|
|
|
|
d->electric_current_border = 0;
|
2001-08-27 05:42:32 +00:00
|
|
|
|
|
|
|
|
|
QRect r = QApplication::desktop()->geometry();
|
|
|
|
|
|
|
|
|
|
XSetWindowAttributes attributes;
|
|
|
|
|
unsigned long valuemask;
|
|
|
|
|
attributes.override_redirect = True;
|
|
|
|
|
attributes.event_mask = (EnterWindowMask | LeaveWindowMask |
|
2001-12-09 04:17:36 +00:00
|
|
|
|
VisibilityChangeMask);
|
2001-08-27 05:42:32 +00:00
|
|
|
|
valuemask= (CWOverrideRedirect | CWEventMask | CWCursor );
|
|
|
|
|
attributes.cursor = XCreateFontCursor(qt_xdisplay(),
|
2001-12-09 04:17:36 +00:00
|
|
|
|
XC_sb_up_arrow);
|
2001-08-27 05:42:32 +00:00
|
|
|
|
d->electric_top_border = XCreateWindow (qt_xdisplay(), qt_xrootwin(),
|
2001-12-09 04:17:36 +00:00
|
|
|
|
0,0,
|
|
|
|
|
r.width(),1,
|
|
|
|
|
0,
|
|
|
|
|
CopyFromParent, InputOnly,
|
|
|
|
|
CopyFromParent,
|
|
|
|
|
valuemask, &attributes);
|
2001-08-27 05:42:32 +00:00
|
|
|
|
XMapWindow(qt_xdisplay(), d->electric_top_border);
|
|
|
|
|
|
|
|
|
|
attributes.cursor = XCreateFontCursor(qt_xdisplay(),
|
2001-12-09 04:17:36 +00:00
|
|
|
|
XC_sb_down_arrow);
|
2001-08-27 05:42:32 +00:00
|
|
|
|
d->electric_bottom_border = XCreateWindow (qt_xdisplay(), qt_xrootwin(),
|
2001-12-09 04:17:36 +00:00
|
|
|
|
0,r.height()-1,
|
|
|
|
|
r.width(),1,
|
|
|
|
|
0,
|
|
|
|
|
CopyFromParent, InputOnly,
|
|
|
|
|
CopyFromParent,
|
|
|
|
|
valuemask, &attributes);
|
2001-08-27 05:42:32 +00:00
|
|
|
|
XMapWindow(qt_xdisplay(), d->electric_bottom_border);
|
|
|
|
|
|
|
|
|
|
attributes.cursor = XCreateFontCursor(qt_xdisplay(),
|
2001-12-09 04:17:36 +00:00
|
|
|
|
XC_sb_left_arrow);
|
2001-08-27 05:42:32 +00:00
|
|
|
|
d->electric_left_border = XCreateWindow (qt_xdisplay(), qt_xrootwin(),
|
2001-12-09 04:17:36 +00:00
|
|
|
|
0,0,
|
|
|
|
|
1,r.height(),
|
|
|
|
|
0,
|
|
|
|
|
CopyFromParent, InputOnly,
|
|
|
|
|
CopyFromParent,
|
|
|
|
|
valuemask, &attributes);
|
2001-08-27 05:42:32 +00:00
|
|
|
|
XMapWindow(qt_xdisplay(), d->electric_left_border);
|
|
|
|
|
|
|
|
|
|
attributes.cursor = XCreateFontCursor(qt_xdisplay(),
|
2001-12-09 04:17:36 +00:00
|
|
|
|
XC_sb_right_arrow);
|
2001-08-27 05:42:32 +00:00
|
|
|
|
d->electric_right_border = XCreateWindow (qt_xdisplay(), qt_xrootwin(),
|
2001-12-09 04:17:36 +00:00
|
|
|
|
r.width()-1,0,
|
|
|
|
|
1,r.height(),
|
|
|
|
|
0,
|
|
|
|
|
CopyFromParent, InputOnly,
|
|
|
|
|
CopyFromParent,
|
|
|
|
|
valuemask, &attributes);
|
2001-08-27 05:42:32 +00:00
|
|
|
|
XMapWindow(qt_xdisplay(), d->electric_right_border);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Electric Border Window management. Electric borders allow a user
|
|
|
|
|
// to change the virtual desktop by moving the mouse pointer to the
|
|
|
|
|
// borders. Technically this is done with input only windows. Since
|
|
|
|
|
// electric borders can be switched on and off, we have these two
|
|
|
|
|
// functions to create and destroy them.
|
|
|
|
|
void Workspace::destroyBorderWindows()
|
|
|
|
|
{
|
|
|
|
|
if( !d->electric_have_borders)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
d->electric_have_borders = false;
|
|
|
|
|
|
|
|
|
|
if(d->electric_top_border)
|
|
|
|
|
XDestroyWindow(qt_xdisplay(),d->electric_top_border);
|
|
|
|
|
if(d->electric_bottom_border)
|
|
|
|
|
XDestroyWindow(qt_xdisplay(),d->electric_bottom_border);
|
|
|
|
|
if(d->electric_left_border)
|
|
|
|
|
XDestroyWindow(qt_xdisplay(),d->electric_left_border);
|
|
|
|
|
if(d->electric_right_border)
|
|
|
|
|
XDestroyWindow(qt_xdisplay(),d->electric_right_border);
|
|
|
|
|
|
|
|
|
|
d->electric_top_border = None;
|
|
|
|
|
d->electric_bottom_border = None;
|
|
|
|
|
d->electric_left_border = None;
|
|
|
|
|
d->electric_right_border = None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Do we have a proper timediff function??
|
2001-11-03 00:05:33 +00:00
|
|
|
|
static int TimeDiff(unsigned long a, unsigned long b)
|
2001-08-27 05:42:32 +00:00
|
|
|
|
{
|
|
|
|
|
if (a > b)
|
|
|
|
|
return a-b;
|
|
|
|
|
else
|
|
|
|
|
return b-a;
|
|
|
|
|
}
|
|
|
|
|
|
2001-11-03 00:05:33 +00:00
|
|
|
|
void Workspace::clientMoved(const QPoint &pos, unsigned long now)
|
2001-08-27 05:42:32 +00:00
|
|
|
|
{
|
2001-11-03 00:05:33 +00:00
|
|
|
|
if ((pos.x() != d->electricLeft) &&
|
|
|
|
|
(pos.x() != d->electricRight) &&
|
|
|
|
|
(pos.y() != d->electricTop) &&
|
|
|
|
|
(pos.y() != d->electricBottom))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (options->electricBorders() == Options::ElectricDisabled)
|
|
|
|
|
return;
|
|
|
|
|
|
2001-09-06 19:44:06 +00:00
|
|
|
|
int treshold_set = options->electricBorderDelay(); // set timeout
|
|
|
|
|
int treshold_reset = 250; // reset timeout
|
|
|
|
|
int distance_reset = 10; // Mouse should not move more than this many pixels
|
2001-11-03 00:05:33 +00:00
|
|
|
|
|
|
|
|
|
int border = 0;
|
|
|
|
|
if (pos.x() == d->electricLeft)
|
|
|
|
|
border = 1;
|
|
|
|
|
else if (pos.x() == d->electricRight)
|
|
|
|
|
border = 2;
|
|
|
|
|
else if (pos.y() == d->electricTop)
|
|
|
|
|
border = 3;
|
|
|
|
|
else if (pos.y() == d->electricBottom)
|
|
|
|
|
border = 4;
|
2001-08-27 05:42:32 +00:00
|
|
|
|
|
|
|
|
|
if ((d->electric_current_border == border) &&
|
2001-09-06 19:44:06 +00:00
|
|
|
|
(TimeDiff(d->electric_time_last, now) < treshold_reset) &&
|
2001-11-03 00:05:33 +00:00
|
|
|
|
((pos-d->electric_push_point).manhattanLength() < distance_reset))
|
2001-08-27 05:42:32 +00:00
|
|
|
|
{
|
|
|
|
|
d->electric_time_last = now;
|
|
|
|
|
|
|
|
|
|
if (TimeDiff(d->electric_time_first, now) > treshold_set)
|
|
|
|
|
{
|
|
|
|
|
d->electric_current_border = 0;
|
|
|
|
|
|
|
|
|
|
QRect r = QApplication::desktop()->geometry();
|
|
|
|
|
int offset;
|
2001-09-05 20:40:04 +00:00
|
|
|
|
|
2002-03-03 16:29:29 +00:00
|
|
|
|
int desk_before = currentDesktop();
|
2001-12-09 04:17:36 +00:00
|
|
|
|
switch(border)
|
2001-11-03 00:05:33 +00:00
|
|
|
|
{
|
|
|
|
|
case 1:
|
2001-08-27 05:42:32 +00:00
|
|
|
|
slotSwitchDesktopLeft();
|
2002-03-03 16:29:29 +00:00
|
|
|
|
if (currentDesktop() != desk_before) {
|
|
|
|
|
offset = r.width() / 5;
|
|
|
|
|
QCursor::setPos(r.width() - offset, pos.y());
|
|
|
|
|
}
|
2001-11-03 00:05:33 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 2:
|
2001-08-27 05:42:32 +00:00
|
|
|
|
slotSwitchDesktopRight();
|
2002-03-03 16:29:29 +00:00
|
|
|
|
if (currentDesktop() != desk_before) {
|
|
|
|
|
offset = r.width() / 5;
|
|
|
|
|
QCursor::setPos(offset, pos.y());
|
|
|
|
|
}
|
2001-11-03 00:05:33 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
|
slotSwitchDesktopUp();
|
2002-03-03 16:29:29 +00:00
|
|
|
|
if (currentDesktop() != desk_before) {
|
|
|
|
|
offset = r.height() / 5;
|
|
|
|
|
QCursor::setPos(pos.x(), r.height() - offset);
|
|
|
|
|
}
|
2001-11-03 00:05:33 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
|
slotSwitchDesktopDown();
|
2002-03-03 16:29:29 +00:00
|
|
|
|
if (currentDesktop() != desk_before) {
|
|
|
|
|
offset = r.height() / 5;
|
|
|
|
|
QCursor::setPos(pos.x(), offset);
|
|
|
|
|
}
|
2001-11-03 00:05:33 +00:00
|
|
|
|
break;
|
2001-08-27 05:42:32 +00:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
d->electric_current_border = border;
|
|
|
|
|
d->electric_time_first = now;
|
|
|
|
|
d->electric_time_last = now;
|
2001-11-03 00:05:33 +00:00
|
|
|
|
d->electric_push_point = pos;
|
2001-08-27 05:42:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int mouse_warp = 1;
|
|
|
|
|
|
|
|
|
|
// reset the pointer to find out wether the user is really pushing
|
2001-11-03 00:05:33 +00:00
|
|
|
|
switch( border)
|
|
|
|
|
{
|
|
|
|
|
case 1: QCursor::setPos(pos.x()+mouse_warp, pos.y()); break;
|
|
|
|
|
case 2: QCursor::setPos(pos.x()-mouse_warp, pos.y()); break;
|
|
|
|
|
case 3: QCursor::setPos(pos.x(), pos.y()+mouse_warp); break;
|
|
|
|
|
case 4: QCursor::setPos(pos.x(), pos.y()-mouse_warp); break;
|
2001-08-27 05:42:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-11-03 00:05:33 +00:00
|
|
|
|
// this function is called when the user entered an electric border
|
|
|
|
|
// with the mouse. It may switch to another virtual desktop
|
|
|
|
|
void Workspace::electricBorder(XEvent *e)
|
|
|
|
|
{
|
|
|
|
|
Time now = e->xcrossing.time;
|
|
|
|
|
QPoint p(e->xcrossing.x_root, e->xcrossing.y_root);
|
|
|
|
|
|
|
|
|
|
clientMoved(p, now);
|
|
|
|
|
}
|
|
|
|
|
|
2001-08-27 05:42:32 +00:00
|
|
|
|
// electric borders (input only windows) have to be always on the
|
|
|
|
|
// top. For that reason kwm calls this function always after some
|
|
|
|
|
// windows have been raised.
|
|
|
|
|
void Workspace::raiseElectricBorders(){
|
|
|
|
|
|
|
|
|
|
if(d->electric_have_borders){
|
|
|
|
|
XRaiseWindow(qt_xdisplay(), d->electric_top_border);
|
|
|
|
|
XRaiseWindow(qt_xdisplay(), d->electric_left_border);
|
|
|
|
|
XRaiseWindow(qt_xdisplay(), d->electric_bottom_border);
|
|
|
|
|
XRaiseWindow(qt_xdisplay(), d->electric_right_border);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-06-09 00:20:21 +00:00
|
|
|
|
#include "workspace.moc"
|