Understand more about edge-based clients and act appropriately, passing

info along to kdesktop too.

This is funky now :)

svn path=/trunk/kdebase/kwin/; revision=48377
This commit is contained in:
Rik Hemsley 2000-05-04 23:12:29 +00:00
parent d19c42bd26
commit 297651e2c3
10 changed files with 275 additions and 165 deletions

View file

@ -6,10 +6,12 @@ SUBDIRS = pics clients
bin_PROGRAMS = kwin
lib_LTLIBRARIES = kwin.la
kwin_la_SOURCES = atoms.cpp client.cpp main.cpp stdclient.cpp workspace.cpp tabbox.cpp options.cpp plugins.cpp
kwin_la_SOURCES = atoms.cpp client.cpp main.cpp stdclient.cpp workspace.cpp tabbox.cpp options.cpp plugins.cpp KWinInterface.skel
kwin_la_LIBADD = $(LIB_KDEUI)
kwin_la_LDFLAGS = $(all_libraries) -module -avoid-version
include_HEADERS = KWinInterface.h
kwin_SOURCES = dummy.cpp
kwin_LDADD = kwin.la
kwin_LDFLAGS = $(all_libraries) $(KDE_RPATH) -export-dynamic -rdynamic

View file

@ -361,65 +361,7 @@ Client::Client( Workspace *ws, WId w, QWidget *parent, const char *name, WFlags
if ( mainClient()->isSticky() )
setSticky( TRUE );
// Find out if we should be avoided.
// If this atom isn't set, set it now.
Atom avoidAtom = XInternAtom(qt_xdisplay(), "_NET_AVOID_SPEC", False);
XTextProperty avoidProp;
Status avoidStatus =
XGetTextProperty(qt_xdisplay(), w, &avoidProp, avoidAtom);
if (0 != avoidStatus) {
qDebug("XGetTextProperty worked for atom _NET_AVOID_SPEC");
char ** avoidList;
int avoidListCount;
Status convertStatus =
XTextPropertyToStringList(&avoidProp, &avoidList, &avoidListCount);
if (0 != convertStatus) {
qDebug("XTextPropertyToStringList succeded");
avoid_ = true;
if (avoidListCount != 1) {
qDebug("Extra values in avoidance list. Ignoring.");
}
char * itemZero = avoidList[0];
qDebug("Anchoring to border %s", itemZero);
switch (*itemZero) {
case 'N':
anchorEdge_ = AnchorNorth;
break;
case 'S':
anchorEdge_ = AnchorSouth;
break;
case 'E':
anchorEdge_ = AnchorEast;
break;
case 'W':
anchorEdge_ = AnchorWest;
break;
default:
anchorEdge_ = AnchorNorth;
break;
}
XFreeStringList(avoidList);
} else
qDebug("XTextPropertyToStringList failed");
}
updateAvoidPolicy();
}
/*!
@ -1950,6 +1892,69 @@ QCString Client::sessionId()
return result;
}
void Client::updateAvoidPolicy()
{
// Find out if we should be avoided.
// If this atom isn't set, set it now.
Atom avoidAtom = XInternAtom(qt_xdisplay(), "_NET_AVOID_SPEC", False);
XTextProperty avoidProp;
Status avoidStatus =
XGetTextProperty(qt_xdisplay(), win, &avoidProp, avoidAtom);
if (0 != avoidStatus) {
qDebug("XGetTextProperty worked for atom _NET_AVOID_SPEC");
char ** avoidList;
int avoidListCount;
Status convertStatus =
XTextPropertyToStringList(&avoidProp, &avoidList, &avoidListCount);
if (0 != convertStatus) {
qDebug("XTextPropertyToStringList succeded");
avoid_ = true;
if (avoidListCount != 1) {
qDebug("Extra values in avoidance list. Ignoring.");
}
char * itemZero = avoidList[0];
qDebug("Anchoring to border %s", itemZero);
switch (*itemZero) {
case 'N':
anchorEdge_ = AnchorNorth;
break;
case 'S':
anchorEdge_ = AnchorSouth;
break;
case 'E':
anchorEdge_ = AnchorEast;
break;
case 'W':
anchorEdge_ = AnchorWest;
break;
default:
avoid_ = false;
break;
}
XFreeStringList(avoidList);
} else
qDebug("XTextPropertyToStringList failed");
}
}
NoBorderClient::NoBorderClient( Workspace *ws, WId w, QWidget *parent, const char *name )
: Client( ws, w, parent, name )
{

View file

@ -63,6 +63,7 @@ public:
bool isTransient() const;
Client* mainClient();
void updateAvoidPolicy();
bool avoid() const { return avoid_; }
int anchorEdge() const { return anchorEdge_; }

View file

@ -152,16 +152,7 @@ Manager::updateDisplay()
void
Manager::setShade(bool)
{
#if 0
// Hmm. This does screwy things to the layout.
if (b)
resizeBar_->hide();
else
resizeBar_->show();
#endif
// And this is screwed. My window ends up the wrong size when unshaded.
// Client::setShade(b);
// Wait for parent class version to work.
}
void
@ -178,7 +169,6 @@ Manager::paintEvent(QPaintEvent * e)
if (intersectsLeft || intersectsRight) {
QPainter p(this);
// ??? p.setPen(options->color(Options::Frame, isActive()));
p.setPen(Qt::black);
if (intersectsLeft)

View file

@ -2,12 +2,10 @@ This theme emulates the look and feel of the RISC OS 'window manager'.
Actually, RISC OS doesn't have a window manager in the same way X
does, but if you imagine it does, this is an emulation of that ;)
I've optimised it for speed, so you should find it quite nippy.
Particularly the fact that the left and right borders are single-pixel
gives a large speedup on my Matrox card when dragging windows.
I've requested save-under in the window decorations for that extra
speed kick, plus double-buffered the title bar and resize bar.
The look is obviously quite different, but coming anywhere close to
the unique look of RISC OS would be quite blatantly obvious, so to
avoid copyright issues, the look of this theme is unique. You may
consider it to be RISC OS grown up ;)
Functions that will be implemented but are currently missing:
Transparent resize.
@ -49,9 +47,11 @@ Titlebar:
Left button: Raise, focus and move window
Middle button: Menu
Middle button: Move window
Right button: Move window
Right button: Menu
Note: Buttons are this way around for compatibility with
other kwin themes.
Button Three:

View file

@ -88,6 +88,50 @@ TitleBar::~TitleBar()
{
}
void
TitleBar::resizeEvent(QResizeEvent * e)
{
int sizeProblem = 0;
if (width() < 80) sizeProblem = 3;
else if (width() < 100) sizeProblem = 2;
else if (width() < 120) sizeProblem = 1;
switch (sizeProblem) {
case 1:
lower_ ->hide();
iconify_ ->show();
maximise_ ->hide();
close_ ->show();
break;
case 2:
lower_ ->hide();
iconify_ ->hide();
maximise_ ->hide();
close_ ->show();
break;
case 3:
lower_ ->hide();
iconify_ ->hide();
maximise_ ->hide();
close_ ->hide();
break;
case 0:
default:
lower_ ->show();
iconify_ ->show();
maximise_ ->show();
close_ ->show();
break;
}
QWidget::resizeEvent(e);
}
} // End namespace
// vim:ts=2:sw=2:tw=78

View file

@ -46,6 +46,10 @@ class TitleBar : public QWidget
void updateText();
void updateMaximise(bool);
protected:
void resizeEvent(QResizeEvent *);
private:
LowerButton * lower_;

View file

@ -63,16 +63,17 @@ TitleText::mousePressEvent(QMouseEvent * e)
switch (e->button()) {
case MidButton:
client_->workspace()->clientPopup(client_)->popup(e->globalPos());
clientPosToMousePos_ = e->globalPos() - client_->pos();
break;
case LeftButton:
clientPosToMousePos_ = e->globalPos() - client_->pos();
client_->workspace()->raiseClient(client_);
client_->workspace()->requestFocus(client_);
break;
case RightButton:
clientPosToMousePos_ = e->globalPos() - client_->pos();
client_->workspace()->clientPopup(client_)->popup(e->globalPos());
break;
default:

View file

@ -9,7 +9,10 @@ Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
#include <klocale.h>
#include <stdlib.h>
#include <qwhatsthis.h>
#include <qdatastream.h>
#include <kwin.h>
#include <kapp.h>
#include <dcopclient.h>
#include "workspace.h"
#include "client.h"
@ -142,16 +145,40 @@ Client* Workspace::clientFactory( Workspace *ws, WId w )
return(mgr.allocateClient(ws, w));
}
// Rikkus: This class is too complex. It needs splitting further.
// It's a nightmare to understand, especially with so few comments :(
Workspace::Workspace( bool restore )
: QObject (0, "workspace"),
DCOPObject ("KWinInterface"),
current_desktop (0),
number_of_desktops(0),
desktop_widget (0),
desktop_client (0),
active_client (0),
should_get_focus (0),
control_grab (false),
tab_grab (false),
mouse_emulation (false),
tab_box (0),
popup (0),
desk_popup (0),
keys (0),
root (0)
{
root = qt_xrootwin();
session.setAutoDelete( TRUE );
if ( restore )
loadSessionInfo();
loadSessionInfo();
(void) QApplication::desktop(); // trigger creation of desktop widget
desktop_widget = new QWidget(0, "desktop_widget", Qt::WType_Desktop | Qt::WPaintUnclipped );
desktop_widget =
new QWidget(
0,
"desktop_widget",
Qt::WType_Desktop | Qt::WPaintUnclipped
);
// select windowmanager privileges
XSelectInput(qt_xdisplay(), root,
@ -163,14 +190,23 @@ Workspace::Workspace( bool restore )
);
int dummy;
kwin_has_shape = XShapeQueryExtension(qt_xdisplay(), &kwin_shape_event, &dummy);
kwin_has_shape =
XShapeQueryExtension(qt_xdisplay(), &kwin_shape_event, &dummy);
// compatibility
long data = 1;
XChangeProperty(qt_xdisplay(), qt_xrootwin(), atoms->kwm_running, atoms->kwm_running, 32,
PropModeAppend, (unsigned char*) &data, 1);
keys = 0;
XChangeProperty(
qt_xdisplay(),
qt_xrootwin(),
atoms->kwm_running,
atoms->kwm_running,
32,
PropModeAppend,
(unsigned char*) &data,
1
);
grabKey(XK_Tab, Mod1Mask);
grabKey(XK_Tab, Mod1Mask | ShiftMask);
grabKey(XK_Tab, ControlMask);
@ -179,23 +215,11 @@ Workspace::Workspace( bool restore )
init();
control_grab = FALSE;
tab_grab = FALSE;
mouse_emulation = FALSE;
tab_box = new TabBox( this );
}
void Workspace::init()
{
tab_box = 0;
active_client = 0;
should_get_focus = 0;
desktop_client = 0;
current_desktop = 0;
number_of_desktops = 0;
popup = 0;
desk_popup = 0;
popup_client = 0;
KConfig* config = KGlobal::config();
config->setGroup("Desktops");
if (!config->hasKey("NumberOfDesktops"))
@ -2218,6 +2242,8 @@ Workspace::updateClientArea()
for (ClientList::ConstIterator it(clients.begin()); it != clients.end(); ++it)
{
(*it)->updateAvoidPolicy();
if ((*it)->avoid()) {
switch (AnchorEdge((*it)->anchorEdge())) {
@ -2252,8 +2278,46 @@ Workspace::updateClientArea()
}
}
}
DCOPClient * client = kapp->dcopClient();
if (!client->isAttached())
client->attach();
QByteArray param;
QDataStream str(param, IO_WriteOnly);
str << clientArea_;
client->send("kdesktop", "KDesktopIface", "clientAreaUpdated(QRect)", param);
// Useful when you want to see whether the client area has been
// updated correctly...
// qDebug("clientArea now == l: %d, r: %d, t: %d, b: %d", clientArea_.left(), clientArea_.right(), clientArea_.top(), clientArea_.bottom());
qDebug("clientArea now == l: %d, r: %d, t: %d, b: %d", clientArea_.left(), clientArea_.top(), clientArea_.right(), clientArea_.bottom());
}
WId Workspace::rootWin() const
{
return root;
}
Client* Workspace::activeClient() const
{
return active_client;
}
int Workspace::currentDesktop() const
{
return current_desktop;
}
int Workspace::numberOfDesktops() const
{
return number_of_desktops;
}
const ClientList& Workspace::stackingOrder() const
{
return stacking_order;
}

View file

@ -15,6 +15,8 @@ Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
#include <X11/Xlib.h>
#include "options.h"
#include "plugins.h"
#include "KWinInterface.h"
class Client;
class TabBox;
@ -74,7 +76,7 @@ public:
static bool noBorder( WId w );
};
class Workspace : public QObject
class Workspace : public QObject, virtual public KWinInterface
{
Q_OBJECT
public:
@ -94,7 +96,12 @@ public:
WId rootWin() const;
/**
* Returns the active client, i.e. the client that has the focus (or None
* if no client has the focus)
*/
Client* activeClient() const;
void setActiveClient( Client* );
void activateClient( Client* );
void requestFocus( Client* c);
@ -106,7 +113,14 @@ public:
void clientHidden( Client* );
/**
* Returns the current virtual desktop of this workspace
*/
int currentDesktop() const;
/**
* Returns the number of virtual desktops of this workspace
*/
int numberOfDesktops() const;
void setNumberOfDesktops( int n );
@ -118,6 +132,11 @@ public:
Client* previousClient(Client*) const;
Client* nextStaticClient(Client*) const;
Client* previousStaticClient(Client*) const;
/**
* Returns the list of clients sorted in stacking order, with topmost client
* at the last position
*/
const ClientList& stackingOrder() const;
//#### TODO right layers as default
@ -142,7 +161,12 @@ public:
SessionInfo* takeSessionInfo( Client* );
void updateClientArea();
/**
* When the area that is available for clients (that which is not
* taken by windows like panels, the top-of-screen menu etc) may
* have changed, this will recalculate the available space.
*/
virtual void updateClientArea();
public slots:
void setCurrentDesktop( int new_desktop );
@ -185,22 +209,8 @@ protected:
private:
void init();
KGlobalAccel *keys;
void createKeybindings();
WId root;
ClientList clients;
ClientList stacking_order;
ClientList focus_chain;
Client* active_client;
bool control_grab;
bool tab_grab;
bool mouse_emulation;
TabBox* tab_box;
void freeKeyboard(bool pass);
QGuardedPtr<Client> popup_client;
QPopupMenu *popup;
QPopupMenu *desk_popup;
Client* should_get_focus;
void raiseTransientsOf( ClientList& safeset, Client* c );
void lowerTransientsOf( ClientList& safeset, Client* c );
@ -212,31 +222,59 @@ private:
void deskCleanup(CleanupType);
void focusToNull();
Client* desktop_client;
int current_desktop;
int number_of_desktops;
Client* findClientWidthId( WId w ) const;
QWidget* desktop_widget;
Client* findClientWidthId( WId w ) const;
void propagateClients( bool onlyStacking = FALSE);
DockWindowList dockwins;
bool addDockwin( WId w );
bool removeDockwin( WId w );
void propagateDockwins();
DockWindow findDockwin( WId w );
QList<SessionInfo> session;
void loadSessionInfo();
//CT needed for cascading+
struct CascadingInfo {
QPoint pos;
int col;
int row;
};
// ------------------
DockWindowList dockwins;
int current_desktop;
int number_of_desktops;
QGuardedPtr<Client> popup_client;
void loadSessionInfo();
QWidget* desktop_widget;
QList<SessionInfo> session;
QValueList<CascadingInfo> cci;
Client* desktop_client;
Client* active_client;
Client* should_get_focus;
ClientList clients;
ClientList stacking_order;
ClientList focus_chain;
bool control_grab;
bool tab_grab;
bool mouse_emulation;
TabBox* tab_box;
QPopupMenu *popup;
QPopupMenu *desk_popup;
KGlobalAccel *keys;
WId root;
// -cascading
Atom kwm_command;
@ -245,43 +283,4 @@ private:
QRect clientArea_;
};
inline WId Workspace::rootWin() const
{
return root;
}
/*!
Returns the active client, i.e. the client that has the focus (or None if no
client has the focus)
*/
inline Client* Workspace::activeClient() const
{
return active_client;
}
/*!
Returns the current virtual desktop of this workspace
*/
inline int Workspace::currentDesktop() const
{
return current_desktop;
}
/*!
Returns the number of virtual desktops of this workspace
*/
inline int Workspace::numberOfDesktops() const
{
return number_of_desktops;
}
/*!
Returns the list of clients sorted in stacking order, with topmost client
at the last position
*/
inline const ClientList& Workspace::stackingOrder() const
{
return stacking_order;
}
#endif