Say hello to kwin. WARNING: NOT USABLE YET. See README.
svn path=/trunk/kdebase/kwin/; revision=27871
This commit is contained in:
commit
311db796c6
18 changed files with 3848 additions and 0 deletions
20
README
Normal file
20
README
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
Fri Aug 20 01:30:50 CEST 1999
|
||||||
|
|
||||||
|
This is the beginning of kwin, kwm next generation.
|
||||||
|
|
||||||
|
WARNING: this thing is hardly usable now, neither ICCCM nor KDE
|
||||||
|
compliant yet!
|
||||||
|
|
||||||
|
All it has is a context menu that allows you to switch between two
|
||||||
|
decoration styles, KDE classic and an experimental style.
|
||||||
|
|
||||||
|
Please don't work on the code, I'll finish it during my summer
|
||||||
|
vacations (four weeks from now on).
|
||||||
|
|
||||||
|
kwin was only commited to allow people like Mosfet to have a look at
|
||||||
|
the Client API (and StdClient) to write nifty new themable decorations.
|
||||||
|
|
||||||
|
Have fun,
|
||||||
|
|
||||||
|
Matthias
|
||||||
|
<ettrich@kde.org>
|
15
atoms.cpp
Normal file
15
atoms.cpp
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#include <qapplication.h>
|
||||||
|
#include "atoms.h"
|
||||||
|
|
||||||
|
Atoms::Atoms()
|
||||||
|
{
|
||||||
|
|
||||||
|
//TODO use XInternAtoms instead to avoid roundtrips
|
||||||
|
wm_protocols = XInternAtom(qt_xdisplay(), "WM_PROTOCOLS", FALSE);
|
||||||
|
wm_delete_window = XInternAtom(qt_xdisplay(), "WM_DELETE_WINDOW", FALSE);
|
||||||
|
wm_take_focus = XInternAtom(qt_xdisplay(), "WM_TAKE_FOCUS", FALSE);
|
||||||
|
|
||||||
|
// compatibility
|
||||||
|
kwm_win_icon = XInternAtom(qt_xdisplay(), "KWM_WIN_ICON", FALSE);
|
||||||
|
|
||||||
|
}
|
19
atoms.h
Normal file
19
atoms.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef ATOMS_H
|
||||||
|
#define ATOMS_H
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
class Atoms {
|
||||||
|
public:
|
||||||
|
Atoms();
|
||||||
|
|
||||||
|
Atom wm_protocols;
|
||||||
|
Atom wm_delete_window;
|
||||||
|
Atom wm_take_focus;
|
||||||
|
Atom kwm_win_icon; // compatibility
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern Atoms* atoms;
|
||||||
|
|
||||||
|
#endif
|
213
beclient.cpp
Normal file
213
beclient.cpp
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
#include "beclient.h"
|
||||||
|
#include <qapplication.h>
|
||||||
|
#include <qcursor.h>
|
||||||
|
#include <qabstractlayout.h>
|
||||||
|
#include <qlayout.h>
|
||||||
|
#include <qtoolbutton.h>
|
||||||
|
#include <qlabel.h>
|
||||||
|
#include <qdrawutil.h>
|
||||||
|
#include "workspace.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static const char * size_xpm[] = {
|
||||||
|
/* width height num_colors chars_per_pixel */
|
||||||
|
"16 16 3 1",
|
||||||
|
/* colors */
|
||||||
|
" s None c None",
|
||||||
|
". c #707070",
|
||||||
|
"X c white",
|
||||||
|
/* pixels */
|
||||||
|
" ",
|
||||||
|
" ....... ",
|
||||||
|
" .XXXXXX ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X .X....... ",
|
||||||
|
" .X .XXXXXXXX ",
|
||||||
|
" .X .X .X ",
|
||||||
|
" .X....X .X ",
|
||||||
|
" .XXXXXX .X ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X........X ",
|
||||||
|
" .XXXXXXXXXX ",
|
||||||
|
" ",
|
||||||
|
" "};
|
||||||
|
|
||||||
|
static QPixmap* size_pix = 0;
|
||||||
|
static bool pixmaps_created = FALSE;
|
||||||
|
|
||||||
|
static void create_pixmaps()
|
||||||
|
{
|
||||||
|
if ( pixmaps_created )
|
||||||
|
return;
|
||||||
|
size_pix = new QPixmap( size_xpm );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BeClient::BeClient( Workspace *ws, WId w, QWidget *parent, const char *name )
|
||||||
|
: Client( ws, w, parent, name, WResizeNoErase )
|
||||||
|
{
|
||||||
|
create_pixmaps();
|
||||||
|
|
||||||
|
QFont f = font();
|
||||||
|
f.setBold( TRUE );
|
||||||
|
setFont( f );
|
||||||
|
|
||||||
|
QGridLayout* g = new QGridLayout( this, 0, 0, 2 );
|
||||||
|
g->addRowSpacing(1, 2);
|
||||||
|
g->setRowStretch( 2, 10 );
|
||||||
|
g->addWidget( windowWrapper(), 2, 1 );
|
||||||
|
g->addColSpacing(0, 2);
|
||||||
|
g->addColSpacing(2, 2);
|
||||||
|
g->addRowSpacing(3, 2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
QHBoxLayout* hb = new QHBoxLayout;
|
||||||
|
g->addLayout( hb, 0, 1 );
|
||||||
|
int fh = QMAX( 16, fontMetrics().lineSpacing());
|
||||||
|
titlebar = new QSpacerItem(40, fh, QSizePolicy::Preferred,
|
||||||
|
QSizePolicy::Minimum );
|
||||||
|
hb->addItem( titlebar );
|
||||||
|
|
||||||
|
hb->addStretch();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BeClient::~BeClient()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BeClient::resizeEvent( QResizeEvent* e)
|
||||||
|
{
|
||||||
|
Client::resizeEvent( e );
|
||||||
|
doShape();
|
||||||
|
if ( isVisibleToTLW() ) {
|
||||||
|
// manual clearing without the titlebar (we selected WResizeNoErase )
|
||||||
|
QPainter p( this );
|
||||||
|
QRect t = titlebar->geometry();
|
||||||
|
t.setTop( 0 );
|
||||||
|
t.setLeft( 0 );
|
||||||
|
QRegion r = rect();
|
||||||
|
r = r.subtract( t );
|
||||||
|
p.setClipRegion( r );
|
||||||
|
p.eraseRect( rect() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!\reimp
|
||||||
|
*/
|
||||||
|
void BeClient::captionChange( const QString& )
|
||||||
|
{
|
||||||
|
doShape();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BeClient::paintEvent( QPaintEvent* )
|
||||||
|
{
|
||||||
|
QPainter p( this );
|
||||||
|
QRect bar ( 0, 0, titlebar->geometry().right()+1, titlebar->geometry().bottom() );
|
||||||
|
qDrawWinPanel( &p, 0, bar.bottom()+2, width(), height() - bar.bottom()-2, colorGroup(), FALSE );
|
||||||
|
qDrawWinPanel( &p, 2, bar.bottom()+4, width()-4, height() - bar.bottom()-6, colorGroup(), TRUE );
|
||||||
|
QRect t = titlebar->geometry();
|
||||||
|
|
||||||
|
bar.setBottom( bar.bottom() + 3 );
|
||||||
|
p.setClipRect( bar );
|
||||||
|
bar.setBottom( bar.bottom() + 2 );
|
||||||
|
if ( isActive() ) {
|
||||||
|
QPalette pal( QColor(248,204,0) );
|
||||||
|
qDrawWinPanel( &p, bar, pal.normal(), FALSE, &pal.brush(QPalette::Normal, QColorGroup::Background ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
qDrawWinPanel( &p, bar, colorGroup(), FALSE, &colorGroup().brush( QColorGroup::Background ) );
|
||||||
|
p.setClipping( FALSE );
|
||||||
|
|
||||||
|
p.drawPixmap( t.right() - 20, t.center().y()-8, *size_pix );
|
||||||
|
p.drawPixmap( t.left() +4, t.center().y()-miniIcon().height()/2, miniIcon() );
|
||||||
|
t.setLeft( t.left() + 20 +10);
|
||||||
|
p.drawText( t, AlignLeft|AlignVCenter, caption() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BeClient::showEvent( QShowEvent* e)
|
||||||
|
{
|
||||||
|
Client::showEvent( e );
|
||||||
|
doShape();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BeClient::doShape()
|
||||||
|
{
|
||||||
|
QFontMetrics fm = fontMetrics();
|
||||||
|
int cap = 20+20+10+10+fm.boundingRect(caption() ).width();
|
||||||
|
titlebar->changeSize( QMIN( width(), cap), QMAX( 16, fm.lineSpacing()),
|
||||||
|
QSizePolicy::Preferred, QSizePolicy::Minimum );
|
||||||
|
layout()->activate(); //#### this is broken!!!!! PAUL!!!!!
|
||||||
|
|
||||||
|
// // // do it manually: #######remove this for Qt-2.01
|
||||||
|
titlebar->setGeometry( QRect( titlebar->geometry().x(), titlebar->geometry().y(),
|
||||||
|
titlebar->sizeHint().width(), titlebar->sizeHint().height() ) );
|
||||||
|
QRegion r( rect() );
|
||||||
|
r = r.subtract( QRect( QPoint( titlebar->geometry().right()+1, 0), QPoint( width(), titlebar->geometry().bottom()) ) );
|
||||||
|
setMask( r );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!\reimp
|
||||||
|
*/
|
||||||
|
void BeClient::activeChange( bool /* act */ )
|
||||||
|
{
|
||||||
|
repaint( 0, 0, width(), titlebar->geometry().bottom()+3, FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!\reimp
|
||||||
|
*/
|
||||||
|
Client::MousePosition BeClient::mousePosition( const QPoint& p ) const
|
||||||
|
{
|
||||||
|
const int range = 16;
|
||||||
|
const int border = 4;
|
||||||
|
|
||||||
|
int ly = titlebar->geometry().bottom();
|
||||||
|
int lx = titlebar->geometry().right();
|
||||||
|
if ( p.x() > titlebar->geometry().right() ) {
|
||||||
|
|
||||||
|
if ( p.y() <= ly + range && p.x() >= width()-range)
|
||||||
|
return TopRight;
|
||||||
|
else if ( p.y() <= ly + border )
|
||||||
|
return Top;
|
||||||
|
} else if ( p.y() < ly ) {
|
||||||
|
if ( p.y() > border && p.x() < lx - border )
|
||||||
|
return Client::mousePosition( p );
|
||||||
|
if ( p.y() < range && p.x() > lx - range )
|
||||||
|
return TopRight;
|
||||||
|
else if ( p.x() > lx-border )
|
||||||
|
return Right;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Client::mousePosition( p );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BeClient::mousePressEvent( QMouseEvent * e )
|
||||||
|
{
|
||||||
|
|
||||||
|
Client::mousePressEvent( e );
|
||||||
|
}
|
||||||
|
|
||||||
|
void BeClient::mouseReleaseEvent( QMouseEvent * e )
|
||||||
|
{
|
||||||
|
workspace()->makeFullScreen( this );
|
||||||
|
Client::mouseReleaseEvent( e );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BeClient::mouseDoubleClickEvent( QMouseEvent * e )
|
||||||
|
{
|
||||||
|
if ( titlebar->geometry().contains( e->pos() ) )
|
||||||
|
setShade( !isShade() );
|
||||||
|
workspace()->requestFocus( this );
|
||||||
|
}
|
37
beclient.h
Normal file
37
beclient.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef BECLIENT_H
|
||||||
|
#define BECLIENT_H
|
||||||
|
#include "client.h"
|
||||||
|
class QToolButton;
|
||||||
|
class QLabel;
|
||||||
|
class QSpacerItem;
|
||||||
|
|
||||||
|
|
||||||
|
class BeClient : public Client
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
BeClient( Workspace *ws, WId w, QWidget *parent=0, const char *name=0 );
|
||||||
|
~BeClient();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void resizeEvent( QResizeEvent* );
|
||||||
|
void paintEvent( QPaintEvent* );
|
||||||
|
void mousePressEvent( QMouseEvent * );
|
||||||
|
void mouseReleaseEvent( QMouseEvent * );
|
||||||
|
void mouseDoubleClickEvent( QMouseEvent * e );
|
||||||
|
|
||||||
|
void captionChange( const QString& name );
|
||||||
|
|
||||||
|
void showEvent( QShowEvent* );
|
||||||
|
void activeChange( bool );
|
||||||
|
|
||||||
|
MousePosition mousePosition( const QPoint& p ) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSpacerItem* titlebar;
|
||||||
|
void doShape();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
1464
client.cpp
Normal file
1464
client.cpp
Normal file
File diff suppressed because it is too large
Load diff
285
client.h
Normal file
285
client.h
Normal file
|
@ -0,0 +1,285 @@
|
||||||
|
#ifndef CLIENT_H
|
||||||
|
#define CLIENT_H
|
||||||
|
|
||||||
|
#include "options.h"
|
||||||
|
#include <qframe.h>
|
||||||
|
#include <qvbox.h>
|
||||||
|
#include <qpixmap.h>
|
||||||
|
#include <X11/X.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
|
||||||
|
class Workspace;
|
||||||
|
class Client;
|
||||||
|
|
||||||
|
class KWM
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static QPixmap miniIcon(Window w, int width=0, int height=0);
|
||||||
|
static QPixmap icon(Window w, int width=0, int height=0);
|
||||||
|
};
|
||||||
|
|
||||||
|
class WindowWrapper : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
WindowWrapper( WId w, Client *parent=0, const char* name=0);
|
||||||
|
~WindowWrapper();
|
||||||
|
|
||||||
|
inline WId window() const;
|
||||||
|
void releaseWindow();
|
||||||
|
void invalidateWindow();
|
||||||
|
QSize sizeHint() const;
|
||||||
|
QSizePolicy sizePolicy() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void resizeEvent( QResizeEvent * );
|
||||||
|
void showEvent( QShowEvent* );
|
||||||
|
void hideEvent( QHideEvent* );
|
||||||
|
void mousePressEvent( QMouseEvent* );
|
||||||
|
void mouseReleaseEvent( QMouseEvent* );
|
||||||
|
void mouseMoveEvent( QMouseEvent* );
|
||||||
|
bool x11Event( XEvent * ); // X11 event
|
||||||
|
|
||||||
|
private:
|
||||||
|
WId win;
|
||||||
|
Time lastMouseEventTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline WId WindowWrapper::window() const
|
||||||
|
{
|
||||||
|
return win;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Client : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Client( Workspace *ws, WId w, QWidget *parent=0, const char *name=0, WFlags f = 0);
|
||||||
|
~Client();
|
||||||
|
|
||||||
|
inline WId window() const;
|
||||||
|
inline WindowWrapper* windowWrapper() const;
|
||||||
|
inline Workspace* workspace() const;
|
||||||
|
void releaseWindow();
|
||||||
|
void invalidateWindow();
|
||||||
|
inline WId transientFor() const;
|
||||||
|
|
||||||
|
virtual bool windowEvent( XEvent * );
|
||||||
|
|
||||||
|
void manage( bool isMapped = FALSE );
|
||||||
|
|
||||||
|
void setMappingState( int s );
|
||||||
|
int mappingState() const;
|
||||||
|
|
||||||
|
void requestActivation();
|
||||||
|
void withdraw();
|
||||||
|
|
||||||
|
QSize adjustedSize( const QSize& ) const;
|
||||||
|
QSize minimumSize() const;
|
||||||
|
int minimumWidth() const;
|
||||||
|
int minimumHeight() const;
|
||||||
|
QSize maximumSize() const;
|
||||||
|
int maximumWidth() const;
|
||||||
|
int maximumHeight() const;
|
||||||
|
|
||||||
|
inline QPixmap icon() const;
|
||||||
|
inline QPixmap miniIcon() const;
|
||||||
|
|
||||||
|
|
||||||
|
// is the window in withdrawn state?
|
||||||
|
bool isWithdrawn(){
|
||||||
|
return state == WithdrawnState;
|
||||||
|
}
|
||||||
|
// is the window in iconic state?
|
||||||
|
bool isIconified(){
|
||||||
|
return state == IconicState;
|
||||||
|
}
|
||||||
|
// is the window in normal state?
|
||||||
|
bool isNormal(){
|
||||||
|
return state == NormalState;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isActive() const;
|
||||||
|
void setActive( bool );
|
||||||
|
|
||||||
|
int desktop() const;
|
||||||
|
bool isOnDesktop( int d ) const;
|
||||||
|
|
||||||
|
bool isShade() const;
|
||||||
|
virtual void setShade( bool );
|
||||||
|
|
||||||
|
inline bool isMaximized() const;
|
||||||
|
enum MaximizeMode { MaximizeVertical, MaximizeHorizontal, MaximizeFull };
|
||||||
|
|
||||||
|
inline bool isSticky() const;
|
||||||
|
void setSticky( bool );
|
||||||
|
|
||||||
|
void takeFocus();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void iconify();
|
||||||
|
void closeWindow();
|
||||||
|
void maximize( MaximizeMode );
|
||||||
|
void maximize();
|
||||||
|
void fullScreen();
|
||||||
|
void toggleSticky();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent( QPaintEvent * );
|
||||||
|
void mousePressEvent( QMouseEvent * );
|
||||||
|
void mouseReleaseEvent( QMouseEvent * );
|
||||||
|
void mouseMoveEvent( QMouseEvent * );
|
||||||
|
void enterEvent( QEvent * );
|
||||||
|
void leaveEvent( QEvent * );
|
||||||
|
void moveEvent( QMoveEvent * );
|
||||||
|
void showEvent( QShowEvent* );
|
||||||
|
void hideEvent( QHideEvent* );
|
||||||
|
bool x11Event( XEvent * ); // X11 event
|
||||||
|
|
||||||
|
bool eventFilter( QObject *, QEvent * );
|
||||||
|
|
||||||
|
|
||||||
|
virtual void init();
|
||||||
|
virtual void captionChange( const QString& name );
|
||||||
|
virtual void iconChange();
|
||||||
|
virtual void activeChange( bool );
|
||||||
|
virtual void maximizeChange( bool );
|
||||||
|
virtual void stickyChange( bool );
|
||||||
|
|
||||||
|
|
||||||
|
enum MousePosition {
|
||||||
|
Nowhere, TopLeft , BottomRight, BottomLeft, TopRight, Top, Bottom, Left, Right, Center
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual MousePosition mousePosition( const QPoint& ) const;
|
||||||
|
virtual void setMouseCursor( MousePosition m );
|
||||||
|
|
||||||
|
// handlers for X11 events
|
||||||
|
bool mapRequest( XMapRequestEvent& e );
|
||||||
|
bool unmapNotify( XUnmapEvent& e );
|
||||||
|
bool configureRequest( XConfigureRequestEvent& e );
|
||||||
|
bool propertyNotify( XPropertyEvent& e );
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSize sizeForWindowSize( const QSize&, bool ignore_height = FALSE ) const;
|
||||||
|
void getWmNormalHints();
|
||||||
|
void fetchName();
|
||||||
|
void gravitate( bool invert );
|
||||||
|
|
||||||
|
|
||||||
|
WId win;
|
||||||
|
WindowWrapper* wwrap;
|
||||||
|
Workspace* wspace;
|
||||||
|
int desk;
|
||||||
|
bool buttonDown;
|
||||||
|
MousePosition mode;
|
||||||
|
QPoint moveOffset;
|
||||||
|
QPoint invertedMoveOffset;
|
||||||
|
QSize clientSize;
|
||||||
|
XSizeHints xSizeHint;
|
||||||
|
void sendSynteticConfigureNotify();
|
||||||
|
int state;
|
||||||
|
bool active;
|
||||||
|
int ignore_unmap;
|
||||||
|
QRect original_geometry;
|
||||||
|
bool shaded;
|
||||||
|
WId transient_for;
|
||||||
|
bool is_sticky;
|
||||||
|
void getIcons();
|
||||||
|
void getWindowProtocols();
|
||||||
|
uint Pdeletewindow :1; // does the window understand the DeleteWindow protocol?
|
||||||
|
uint Ptakefocus :1;// does the window understand the TakeFocus protocol?
|
||||||
|
QPixmap icon_pix;
|
||||||
|
QPixmap miniicon_pix;
|
||||||
|
QRect geom_restore;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline WId Client::window() const
|
||||||
|
{
|
||||||
|
return win;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline WindowWrapper* Client::windowWrapper() const
|
||||||
|
{
|
||||||
|
return wwrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Workspace* Client::workspace() const
|
||||||
|
{
|
||||||
|
return wspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline WId Client::transientFor() const
|
||||||
|
{
|
||||||
|
return transient_for;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int Client::mappingState() const
|
||||||
|
{
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Client::isActive() const
|
||||||
|
{
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the virtual desktop within the workspace() the client window
|
||||||
|
is located in, -1 if it isn't located on any special desktop. This may be
|
||||||
|
if the window wasn't mapped yet or if the window is sticky. Do not use
|
||||||
|
desktop() directly, use isOnDesktop() instead.
|
||||||
|
*/
|
||||||
|
inline int Client::desktop() const
|
||||||
|
{
|
||||||
|
return desk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns whether the client is on visible or iconified on the virtual
|
||||||
|
desktop \a d. This is always TRUE for sticky clients.
|
||||||
|
*/
|
||||||
|
inline bool Client::isOnDesktop( int d ) const
|
||||||
|
{
|
||||||
|
return desk == d || desk == -1 || isSticky();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline QPixmap Client::icon() const
|
||||||
|
{
|
||||||
|
return icon_pix;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QPixmap Client::miniIcon() const
|
||||||
|
{
|
||||||
|
return miniicon_pix;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Is the client maximized?
|
||||||
|
*/
|
||||||
|
inline bool Client::isMaximized() const
|
||||||
|
{
|
||||||
|
return !geom_restore.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Client::isSticky() const
|
||||||
|
{
|
||||||
|
return is_sticky;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class NoBorderClient : public Client
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
NoBorderClient( Workspace *ws, WId w, QWidget *parent=0, const char *name=0 );
|
||||||
|
~NoBorderClient();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
BIN
kwin
Executable file
BIN
kwin
Executable file
Binary file not shown.
18
kwin.pro
Normal file
18
kwin.pro
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
TEMPLATE = app
|
||||||
|
CONFIG = qt warn_on release
|
||||||
|
HEADERS = atoms.h \
|
||||||
|
beclient.h \
|
||||||
|
client.h \
|
||||||
|
main.h \
|
||||||
|
options.h \
|
||||||
|
stdclient.h \
|
||||||
|
tabbox.h \
|
||||||
|
workspace.h
|
||||||
|
SOURCES = atoms.cpp \
|
||||||
|
beclient.cpp \
|
||||||
|
client.cpp \
|
||||||
|
main.cpp \
|
||||||
|
stdclient.cpp \
|
||||||
|
tabbox.cpp \
|
||||||
|
workspace.cpp
|
||||||
|
TARGET = kwin
|
113
main.cpp
Normal file
113
main.cpp
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
#include "main.h"
|
||||||
|
#include "options.h"
|
||||||
|
#include "atoms.h"
|
||||||
|
#include "workspace.h"
|
||||||
|
#include <X11/X.h>
|
||||||
|
#include <X11/Xos.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#define INT8 _X11INT8
|
||||||
|
#define INT32 _X11INT32
|
||||||
|
#include <X11/Xproto.h>
|
||||||
|
#undef INT8
|
||||||
|
#undef INT32
|
||||||
|
|
||||||
|
#define i18n(x) (x)
|
||||||
|
|
||||||
|
Options* options;
|
||||||
|
Atoms* atoms;
|
||||||
|
|
||||||
|
static bool initting = FALSE;
|
||||||
|
int x11ErrorHandler(Display *d, XErrorEvent *e){
|
||||||
|
char msg[80], req[80], number[80];
|
||||||
|
bool ignore_badwindow = FALSE; //maybe temporary
|
||||||
|
|
||||||
|
if (initting &&
|
||||||
|
(
|
||||||
|
e->request_code == X_ChangeWindowAttributes
|
||||||
|
|| e->request_code == X_GrabKey
|
||||||
|
)
|
||||||
|
&& (e->error_code == BadAccess)) {
|
||||||
|
fprintf(stderr, i18n("kwin: it looks like there's already a window manager running. kwin not started\n"));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ignore_badwindow && (e->error_code == BadWindow || e->error_code == BadColor))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
XGetErrorText(d, e->error_code, msg, sizeof(msg));
|
||||||
|
sprintf(number, "%d", e->request_code);
|
||||||
|
XGetErrorDatabaseText(d, "XRequest", number, "<unknown>", req, sizeof(req));
|
||||||
|
|
||||||
|
fprintf(stderr, "kwin: %s(0x%lx): %s\n", req, e->resourceid, msg);
|
||||||
|
|
||||||
|
if (initting) {
|
||||||
|
fprintf(stderr, i18n("kwin: failure during initialisation; aborting\n"));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Application::Application( int &argc, char *argv[] )
|
||||||
|
: QApplication( argc, argv )
|
||||||
|
{
|
||||||
|
initting = TRUE;
|
||||||
|
options = new Options;
|
||||||
|
atoms = new Atoms;
|
||||||
|
|
||||||
|
// install X11 error handler
|
||||||
|
XSetErrorHandler( x11ErrorHandler );
|
||||||
|
|
||||||
|
// create a workspace.
|
||||||
|
workspaces += new Workspace();
|
||||||
|
initting = FALSE;
|
||||||
|
if ( argc > 1 ) {
|
||||||
|
QString s = argv[1];
|
||||||
|
int i = s.toInt();
|
||||||
|
workspaces += new Workspace( (WId ) i );
|
||||||
|
}
|
||||||
|
|
||||||
|
syncX();
|
||||||
|
initting = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Application::~Application()
|
||||||
|
{
|
||||||
|
for ( WorkspaceList::Iterator it = workspaces.begin(); it != workspaces.end(); ++it) {
|
||||||
|
delete (*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Application::x11EventFilter( XEvent *e )
|
||||||
|
{
|
||||||
|
for ( WorkspaceList::Iterator it = workspaces.begin(); it != workspaces.end(); ++it) {
|
||||||
|
if ( (*it)->workspaceEvent( e ) )
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void sighandler(int) {
|
||||||
|
QApplication::exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( int argc, char * argv[] ) {
|
||||||
|
|
||||||
|
if (signal(SIGTERM, sighandler) == SIG_IGN)
|
||||||
|
signal(SIGTERM, SIG_IGN);
|
||||||
|
if (signal(SIGINT, sighandler) == SIG_IGN)
|
||||||
|
signal(SIGINT, SIG_IGN);
|
||||||
|
if (signal(SIGHUP, sighandler) == SIG_IGN)
|
||||||
|
signal(SIGHUP, SIG_IGN);
|
||||||
|
|
||||||
|
Application a( argc, argv );
|
||||||
|
fcntl(ConnectionNumber(qt_xdisplay()), F_SETFD, 1);
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
23
main.h
Normal file
23
main.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef MAIN_H
|
||||||
|
#define MAIN_H
|
||||||
|
|
||||||
|
#include <qapplication.h>
|
||||||
|
#include "workspace.h"
|
||||||
|
|
||||||
|
typedef QValueList<Workspace*> WorkspaceList;
|
||||||
|
class Application : public QApplication
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Application( int &argc, char **argv );
|
||||||
|
~Application();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool x11EventFilter( XEvent * );
|
||||||
|
|
||||||
|
private:
|
||||||
|
WorkspaceList workspaces;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
47
options.h
Normal file
47
options.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef OPTIONS_H
|
||||||
|
#define OPTIONS_H
|
||||||
|
|
||||||
|
|
||||||
|
class Options {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Different focus policies:
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
<li>ClickToFocus - Clicking into a window activates it. This is
|
||||||
|
also the default.
|
||||||
|
|
||||||
|
<li>FocusFollowsMouse - Moving the mouse pointer actively onto a
|
||||||
|
window activates it.
|
||||||
|
|
||||||
|
<li>FocusUnderMouse - The window that happens to be under the
|
||||||
|
mouse pointer becomes active.
|
||||||
|
|
||||||
|
<li>FocusStricklyUnderMouse - Only the window under the mouse
|
||||||
|
pointer is active. If the mouse points nowhere, nothing has the
|
||||||
|
focus. In practice, this is the same as FocusUnderMouse, since
|
||||||
|
kdesktop can take the focus.
|
||||||
|
|
||||||
|
Note that FocusUnderMouse and FocusStricklyUnderMouse are not
|
||||||
|
particulary useful. They are only provided for old-fashined
|
||||||
|
die-hard UNIX people ;-)
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
*/
|
||||||
|
enum FocusPolicy { ClickToFocus, FocusFollowsMouse, FocusUnderMouse, FocusStricklyUnderMouse };
|
||||||
|
FocusPolicy focusPolicy;
|
||||||
|
|
||||||
|
bool focusPolicyIsReasonable() {
|
||||||
|
return focusPolicy == ClickToFocus || focusPolicy == FocusFollowsMouse;
|
||||||
|
}
|
||||||
|
|
||||||
|
Options(){
|
||||||
|
focusPolicy = ClickToFocus;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Options* options;
|
||||||
|
|
||||||
|
#endif
|
334
stdclient.cpp
Normal file
334
stdclient.cpp
Normal file
|
@ -0,0 +1,334 @@
|
||||||
|
#include "stdclient.h"
|
||||||
|
#include <qapplication.h>
|
||||||
|
#include <qcursor.h>
|
||||||
|
#include <qabstractlayout.h>
|
||||||
|
#include <qlayout.h>
|
||||||
|
#include <qtoolbutton.h>
|
||||||
|
#include <qlabel.h>
|
||||||
|
#include <qdrawutil.h>
|
||||||
|
#include "workspace.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const char * close_xpm[] = {
|
||||||
|
/* width height num_colors chars_per_pixel */
|
||||||
|
"16 16 3 1",
|
||||||
|
/* colors */
|
||||||
|
" s None c None",
|
||||||
|
". c white",
|
||||||
|
"X c #707070",
|
||||||
|
/* pixels */
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" .X .X ",
|
||||||
|
" .XX .XX ",
|
||||||
|
" .XX .XX ",
|
||||||
|
" .XX .XX ",
|
||||||
|
" .XX.XX ",
|
||||||
|
" .XXX ",
|
||||||
|
" .XXX ",
|
||||||
|
" .XX.XX ",
|
||||||
|
" .XX .XX ",
|
||||||
|
" .XX .XX ",
|
||||||
|
" .XX .XX ",
|
||||||
|
" .X .X ",
|
||||||
|
" ",
|
||||||
|
" "};
|
||||||
|
|
||||||
|
|
||||||
|
static const char * maximize_xpm[] = {
|
||||||
|
/* width height num_colors chars_per_pixel */
|
||||||
|
"16 16 3 1",
|
||||||
|
/* colors */
|
||||||
|
" s None c None",
|
||||||
|
". c white",
|
||||||
|
"X c #707070",
|
||||||
|
/* pixels */
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ........... ",
|
||||||
|
" .XXXXXXXXXX ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X........X ",
|
||||||
|
" .XXXXXXXXXX ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" "};
|
||||||
|
|
||||||
|
|
||||||
|
static const char * minimize_xpm[] = {
|
||||||
|
/* width height num_colors chars_per_pixel */
|
||||||
|
"16 16 3 1",
|
||||||
|
/* colors */
|
||||||
|
" s None c None",
|
||||||
|
". c white",
|
||||||
|
"X c #707070",
|
||||||
|
/* pixels */
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ... ",
|
||||||
|
" . X ",
|
||||||
|
" .XX ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" "};
|
||||||
|
|
||||||
|
static const char * normalize_xpm[] = {
|
||||||
|
/* width height num_colors chars_per_pixel */
|
||||||
|
"16 16 3 1",
|
||||||
|
/* colors */
|
||||||
|
" s None c None",
|
||||||
|
". c #707070",
|
||||||
|
"X c white",
|
||||||
|
/* pixels */
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ........... ",
|
||||||
|
" .XXXXXXXXXX ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X .X ",
|
||||||
|
" .X........X ",
|
||||||
|
" .XXXXXXXXXX ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" "};
|
||||||
|
|
||||||
|
static const char * pinup_xpm[] = {
|
||||||
|
/* width height num_colors chars_per_pixel */
|
||||||
|
"16 16 4 1",
|
||||||
|
/* colors */
|
||||||
|
" s None c None",
|
||||||
|
". c #707070",
|
||||||
|
"X c white",
|
||||||
|
"o c #a0a0a0",
|
||||||
|
/* pixels */
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" .. . ",
|
||||||
|
" .X. .. ",
|
||||||
|
" .XX...X. ",
|
||||||
|
"XXXXXX.oXoXoX. ",
|
||||||
|
"oooooo.oXoXoX. ",
|
||||||
|
".......oo.o.o. ",
|
||||||
|
" .o...... ",
|
||||||
|
" ... .. ",
|
||||||
|
" .. . ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" "};
|
||||||
|
|
||||||
|
static const char * pindown_xpm[] = {
|
||||||
|
/* width height num_colors chars_per_pixel */
|
||||||
|
"16 16 4 1",
|
||||||
|
/* colors */
|
||||||
|
" s None c None",
|
||||||
|
". c #707070",
|
||||||
|
"X c white",
|
||||||
|
"o c #a0a0a0",
|
||||||
|
/* pixels */
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" .... ",
|
||||||
|
" ..XXXX. ",
|
||||||
|
" ...XXXXXX. ",
|
||||||
|
" .X.XXXooo. ",
|
||||||
|
" .XX.XXooo.. ",
|
||||||
|
" .XX..Xoo... ",
|
||||||
|
" .XXXX..... ",
|
||||||
|
" .XXXoooo.. ",
|
||||||
|
" .Xoooo... ",
|
||||||
|
" .oooo... ",
|
||||||
|
" ...... ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" "};
|
||||||
|
|
||||||
|
static QPixmap* close_pix = 0;
|
||||||
|
static QPixmap* maximize_pix = 0;
|
||||||
|
static QPixmap* minimize_pix = 0;
|
||||||
|
static QPixmap* normalize_pix = 0;
|
||||||
|
static QPixmap* pinup_pix = 0;
|
||||||
|
static QPixmap* pindown_pix = 0;
|
||||||
|
static bool pixmaps_created = FALSE;
|
||||||
|
|
||||||
|
static void create_pixmaps()
|
||||||
|
{
|
||||||
|
if ( pixmaps_created )
|
||||||
|
return;
|
||||||
|
close_pix = new QPixmap( close_xpm );
|
||||||
|
maximize_pix = new QPixmap( maximize_xpm );
|
||||||
|
minimize_pix = new QPixmap( minimize_xpm );
|
||||||
|
normalize_pix = new QPixmap( normalize_xpm );
|
||||||
|
pinup_pix = new QPixmap( pinup_xpm );
|
||||||
|
pindown_pix = new QPixmap( pindown_xpm );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
StdClient::StdClient( Workspace *ws, WId w, QWidget *parent, const char *name )
|
||||||
|
: Client( ws, w, parent, name, WResizeNoErase )
|
||||||
|
{
|
||||||
|
create_pixmaps();
|
||||||
|
|
||||||
|
QFont f = font();
|
||||||
|
f.setBold( TRUE );
|
||||||
|
setFont( f );
|
||||||
|
|
||||||
|
QGridLayout* g = new QGridLayout( this, 0, 0, 2 );
|
||||||
|
g->setRowStretch( 1, 10 );
|
||||||
|
g->addWidget( windowWrapper(), 1, 1 );
|
||||||
|
g->addColSpacing(0, 2);
|
||||||
|
g->addColSpacing(2, 2);
|
||||||
|
g->addRowSpacing(2, 2);
|
||||||
|
|
||||||
|
|
||||||
|
button[0] = new QToolButton( this );
|
||||||
|
button[1] = new QToolButton( this );
|
||||||
|
button[2] = new QToolButton( this );
|
||||||
|
button[3] = new QToolButton( this );
|
||||||
|
button[4] = new QToolButton( this );
|
||||||
|
button[5] = new QToolButton( this );
|
||||||
|
|
||||||
|
QHBoxLayout* hb = new QHBoxLayout;
|
||||||
|
g->addLayout( hb, 0, 1 );
|
||||||
|
hb->addWidget( button[0] );
|
||||||
|
hb->addWidget( button[1] );
|
||||||
|
hb->addWidget( button[2] );
|
||||||
|
|
||||||
|
int fh = fontMetrics().lineSpacing();
|
||||||
|
|
||||||
|
titlebar = new QSpacerItem(10, fh, QSizePolicy::Expanding,
|
||||||
|
QSizePolicy::Minimum );
|
||||||
|
hb->addItem( titlebar );
|
||||||
|
|
||||||
|
hb->addWidget( button[3] );
|
||||||
|
hb->addWidget( button[4] );
|
||||||
|
hb->addWidget( button[5] );
|
||||||
|
|
||||||
|
for ( int i = 0; i < 6; i++) {
|
||||||
|
button[i]->setMouseTracking( TRUE );
|
||||||
|
button[i]->setFixedSize( 20, 20 );
|
||||||
|
}
|
||||||
|
|
||||||
|
button[0]->setIconSet( miniIcon() );
|
||||||
|
button[1]->setIconSet( isSticky()?*pindown_pix:*pinup_pix );
|
||||||
|
connect( button[1], SIGNAL( clicked() ), this, ( SLOT( toggleSticky() ) ) );
|
||||||
|
button[2]->hide();
|
||||||
|
|
||||||
|
button[3]->setIconSet( *minimize_pix );
|
||||||
|
connect( button[3], SIGNAL( clicked() ), this, ( SLOT( iconify() ) ) );
|
||||||
|
button[4]->setIconSet( *maximize_pix );
|
||||||
|
connect( button[4], SIGNAL( clicked() ), this, ( SLOT( maximize() ) ) );
|
||||||
|
button[5]->setIconSet( *close_pix );
|
||||||
|
connect( button[5], SIGNAL( clicked() ), this, ( SLOT( closeWindow() ) ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
StdClient::~StdClient()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void StdClient::resizeEvent( QResizeEvent* e)
|
||||||
|
{
|
||||||
|
Client::resizeEvent( e );
|
||||||
|
|
||||||
|
if ( isVisibleToTLW() ) {
|
||||||
|
// manual clearing without the titlebar (we selected WResizeNoErase )
|
||||||
|
QPainter p( this );
|
||||||
|
QRect t = titlebar->geometry();
|
||||||
|
t.setTop( 0 );
|
||||||
|
QRegion r = rect();
|
||||||
|
r = r.subtract( t );
|
||||||
|
p.setClipRegion( r );
|
||||||
|
p.eraseRect( rect() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!\reimp
|
||||||
|
*/
|
||||||
|
void StdClient::captionChange( const QString& )
|
||||||
|
{
|
||||||
|
repaint( titlebar->geometry(), FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!\reimp
|
||||||
|
*/
|
||||||
|
void StdClient::maximizeChange( bool m )
|
||||||
|
{
|
||||||
|
button[4]->setIconSet( m?*normalize_pix:*maximize_pix );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!\reimp
|
||||||
|
*/
|
||||||
|
void StdClient::stickyChange( bool s)
|
||||||
|
{
|
||||||
|
button[1]->setIconSet( s?*pindown_pix:*pinup_pix );
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdClient::paintEvent( QPaintEvent* )
|
||||||
|
{
|
||||||
|
QPainter p( this );
|
||||||
|
QRect t = titlebar->geometry();
|
||||||
|
t.setTop( 0 );
|
||||||
|
QRegion r = rect();
|
||||||
|
r = r.subtract( t );
|
||||||
|
p.setClipRegion( r );
|
||||||
|
qDrawWinPanel( &p, rect(), colorGroup() );
|
||||||
|
p.setClipping( FALSE );
|
||||||
|
p.fillRect( t, isActive()?darkBlue:gray );
|
||||||
|
qDrawShadePanel( &p, t.x(), t.y(), t.width(), t.height(),
|
||||||
|
colorGroup(), TRUE );
|
||||||
|
|
||||||
|
t.setTop( 2 );
|
||||||
|
t.setLeft( t.left() + 4 );
|
||||||
|
t.setRight( t.right() - 2 );
|
||||||
|
|
||||||
|
p.setPen( colorGroup().light() );
|
||||||
|
p.drawText( t, AlignLeft|AlignVCenter, caption() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void StdClient::mouseDoubleClickEvent( QMouseEvent * e )
|
||||||
|
{
|
||||||
|
if ( titlebar->geometry().contains( e->pos() ) )
|
||||||
|
setShade( !isShade() );
|
||||||
|
workspace()->requestFocus( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void StdClient::init()
|
||||||
|
{
|
||||||
|
button[0]->setIconSet( miniIcon() );
|
||||||
|
|
||||||
|
// ### TODO transient etc.
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdClient::iconChange()
|
||||||
|
{
|
||||||
|
button[0]->setIconSet( miniIcon() );
|
||||||
|
button[0]->repaint( FALSE );
|
||||||
|
}
|
33
stdclient.h
Normal file
33
stdclient.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef STDCLIENT_H
|
||||||
|
#define STDCLIENT_H
|
||||||
|
#include "client.h"
|
||||||
|
class QToolButton;
|
||||||
|
class QLabel;
|
||||||
|
class QSpacerItem;
|
||||||
|
|
||||||
|
class StdClient : public Client
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
StdClient( Workspace *ws, WId w, QWidget *parent=0, const char *name=0 );
|
||||||
|
~StdClient();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void resizeEvent( QResizeEvent* );
|
||||||
|
void paintEvent( QPaintEvent* );
|
||||||
|
|
||||||
|
void mouseDoubleClickEvent( QMouseEvent * );
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void captionChange( const QString& name );
|
||||||
|
void iconChange();
|
||||||
|
void maximizeChange( bool );
|
||||||
|
void stickyChange( bool );
|
||||||
|
|
||||||
|
private:
|
||||||
|
QToolButton* button[6];
|
||||||
|
QSpacerItem* titlebar;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
179
tabbox.cpp
Normal file
179
tabbox.cpp
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
#include "tabbox.h"
|
||||||
|
#include "workspace.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include <qpainter.h>
|
||||||
|
|
||||||
|
const bool options_traverse_all = FALSE; // TODO
|
||||||
|
|
||||||
|
TabBox::TabBox( Workspace *ws, const char *name=0 )
|
||||||
|
: QWidget( 0, name, WStyle_Customize | WStyle_NoBorder )
|
||||||
|
{
|
||||||
|
wspace = ws;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
TabBox::~TabBox()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Sets the current mode to \a mode, either DesktopMode or WindowsMode
|
||||||
|
|
||||||
|
\sa mode()
|
||||||
|
*/
|
||||||
|
void TabBox::setMode( Mode mode )
|
||||||
|
{
|
||||||
|
m = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Resets the tab box to display the active client in WindowsMode, or the
|
||||||
|
current desktop in DesktopMode
|
||||||
|
*/
|
||||||
|
void TabBox::reset()
|
||||||
|
{
|
||||||
|
QFont f = font();
|
||||||
|
f.setBold( TRUE );
|
||||||
|
f.setPointSize( 14 );
|
||||||
|
setFont( f );
|
||||||
|
|
||||||
|
|
||||||
|
// TODO icons etc.
|
||||||
|
setGeometry( qApp->desktop()->width()/4,
|
||||||
|
qApp->desktop()->height()/2-fontMetrics().height()*2,
|
||||||
|
qApp->desktop()->width()/2, fontMetrics().height()*4 );
|
||||||
|
|
||||||
|
if ( mode() == WindowsMode ) {
|
||||||
|
client = workspace()->activeClient();
|
||||||
|
// todo build window list, consider options_traverse_all
|
||||||
|
}
|
||||||
|
else { // DesktopMode
|
||||||
|
desk = wspace->currentDesktop();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Shows the next or previous item, depending on \a next
|
||||||
|
*/
|
||||||
|
void TabBox::nextPrev( bool next)
|
||||||
|
{
|
||||||
|
if ( mode() == WindowsMode ) {
|
||||||
|
Client* sign = client;
|
||||||
|
do {
|
||||||
|
if (client != sign && !sign)
|
||||||
|
sign = client;
|
||||||
|
if ( next )
|
||||||
|
client = workspace()->nextClient(client);
|
||||||
|
else
|
||||||
|
client = workspace()->previousClient(client);
|
||||||
|
} while (client != sign && client &&
|
||||||
|
!options_traverse_all &&
|
||||||
|
!client->isOnDesktop(workspace()->currentDesktop()));
|
||||||
|
|
||||||
|
if (!options_traverse_all && client
|
||||||
|
&& !client->isOnDesktop(workspace()->currentDesktop()))
|
||||||
|
client = 0;
|
||||||
|
}
|
||||||
|
else { // DesktopMode
|
||||||
|
if ( next ) {
|
||||||
|
desk++;
|
||||||
|
if ( desk > wspace->numberOfDesktops() )
|
||||||
|
desk = 1;
|
||||||
|
} else {
|
||||||
|
desk--;
|
||||||
|
if ( desk < 1 )
|
||||||
|
desk = wspace->numberOfDesktops();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
paintContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the currently displayed client ( only works in WindowsMode ).
|
||||||
|
Returns 0 if no client is displayed.
|
||||||
|
*/
|
||||||
|
Client* TabBox::currentClient()
|
||||||
|
{
|
||||||
|
if ( mode() != WindowsMode )
|
||||||
|
return 0;
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the currently displayed virtual desktop ( only works in
|
||||||
|
DesktopMode )
|
||||||
|
Returns -1 if no desktop is displayed.
|
||||||
|
*/
|
||||||
|
int TabBox::currentDesktop()
|
||||||
|
{
|
||||||
|
if ( mode() != DesktopMode )
|
||||||
|
return -1;
|
||||||
|
return desk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Reimplemented to raise the tab box as well
|
||||||
|
*/
|
||||||
|
void TabBox::showEvent( QShowEvent* )
|
||||||
|
{
|
||||||
|
raise();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Paints the tab box
|
||||||
|
*/
|
||||||
|
void TabBox::paintEvent( QPaintEvent* )
|
||||||
|
{
|
||||||
|
{
|
||||||
|
QPainter p( this );
|
||||||
|
style().drawPanel( &p, 0, 0, width(), height(), colorGroup(), FALSE );
|
||||||
|
style().drawPanel( &p, 4, 4, width()-8, height()-8, colorGroup(), TRUE );
|
||||||
|
}
|
||||||
|
paintContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Paints the contents of the tab box. Used in paintEvent() and
|
||||||
|
whenever the contents changes.
|
||||||
|
*/
|
||||||
|
void TabBox::paintContents()
|
||||||
|
{
|
||||||
|
QPainter p( this );
|
||||||
|
QRect r(6, 6, width()-12, height()-12 );
|
||||||
|
p.fillRect( r, colorGroup().brush( QColorGroup::Background ) );
|
||||||
|
if ( mode () == WindowsMode ) {
|
||||||
|
if ( currentClient() ) {
|
||||||
|
QString s;
|
||||||
|
if (!client->isOnDesktop(workspace()->currentDesktop())){
|
||||||
|
//TODO s = KWM::getDesktopName(client->desktop);
|
||||||
|
s.append(": ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client->isIconified())
|
||||||
|
s += QString("(")+client->caption()+")";
|
||||||
|
else
|
||||||
|
s += client->caption();
|
||||||
|
if ( p.fontMetrics().width( s ) > r.width() )
|
||||||
|
p.drawText( r, AlignLeft, s );
|
||||||
|
else
|
||||||
|
p.drawText( r, AlignCenter, s );
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p.drawText( r, AlignCenter, "*** No Tasks ***" );
|
||||||
|
}
|
||||||
|
} else { // DesktopMode
|
||||||
|
QString s;
|
||||||
|
s.setNum( desk );
|
||||||
|
p.drawText( r, AlignCenter, s );
|
||||||
|
}
|
||||||
|
}
|
63
tabbox.h
Normal file
63
tabbox.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
#ifndef TABBOX_H
|
||||||
|
#define TABBOX_H
|
||||||
|
#include <qwidget.h>
|
||||||
|
|
||||||
|
class Workspace;
|
||||||
|
class Client;
|
||||||
|
|
||||||
|
typedef QValueList<Client*> ClientList;
|
||||||
|
|
||||||
|
class TabBox : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
TabBox( Workspace *ws, const char *name=0 );
|
||||||
|
~TabBox();
|
||||||
|
|
||||||
|
Client* currentClient();
|
||||||
|
int currentDesktop();
|
||||||
|
|
||||||
|
enum Mode { DesktopMode, WindowsMode };
|
||||||
|
void setMode( Mode mode );
|
||||||
|
Mode mode() const;
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
void nextPrev( bool next = TRUE);
|
||||||
|
|
||||||
|
Workspace* workspace() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent( QPaintEvent* );
|
||||||
|
void showEvent( QShowEvent* );
|
||||||
|
void paintContents();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Client* client;
|
||||||
|
Mode m;
|
||||||
|
Workspace* wspace;
|
||||||
|
ClientList clients;
|
||||||
|
int desk;
|
||||||
|
// QValueList <QLabel*> labels;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the tab box' workspace
|
||||||
|
*/
|
||||||
|
inline Workspace* TabBox::workspace() const
|
||||||
|
{
|
||||||
|
return wspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the current mode, either DesktopMode or WindowsMode
|
||||||
|
|
||||||
|
\sa setMode()
|
||||||
|
*/
|
||||||
|
inline TabBox::Mode TabBox::mode() const
|
||||||
|
{
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
859
workspace.cpp
Normal file
859
workspace.cpp
Normal file
|
@ -0,0 +1,859 @@
|
||||||
|
#include "workspace.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "stdclient.h"
|
||||||
|
#include "beclient.h"
|
||||||
|
#include "tabbox.h"
|
||||||
|
#include "atoms.h"
|
||||||
|
#include <X11/X.h>
|
||||||
|
#include <X11/Xos.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static Client* clientFactory( Workspace *ws, WId w )
|
||||||
|
{
|
||||||
|
// hack TODO hints
|
||||||
|
char* name = 0;
|
||||||
|
QString s;
|
||||||
|
if ( XFetchName( qt_xdisplay(), (Window) w, &name ) && name ) {
|
||||||
|
s = QString::fromLatin1( name );
|
||||||
|
XFree( name );
|
||||||
|
}
|
||||||
|
if ( s == "desktop") {
|
||||||
|
Client * c = new NoBorderClient( ws, w);
|
||||||
|
ws->setDesktopClient( c );
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StdClient( ws, w );
|
||||||
|
}
|
||||||
|
|
||||||
|
Workspace::Workspace()
|
||||||
|
{
|
||||||
|
root = qt_xrootwin(); // no MDI for now
|
||||||
|
|
||||||
|
(void) QApplication::desktop(); // trigger creation of desktop widget
|
||||||
|
|
||||||
|
// select windowmanager privileges
|
||||||
|
XSelectInput(qt_xdisplay(), root,
|
||||||
|
KeyPressMask |
|
||||||
|
PropertyChangeMask |
|
||||||
|
ColormapChangeMask |
|
||||||
|
SubstructureRedirectMask |
|
||||||
|
SubstructureNotifyMask
|
||||||
|
);
|
||||||
|
|
||||||
|
init();
|
||||||
|
control_grab = FALSE;
|
||||||
|
tab_grab = FALSE;
|
||||||
|
tab_box = new TabBox( this );
|
||||||
|
grabKey(XK_Tab, Mod1Mask);
|
||||||
|
grabKey(XK_Tab, Mod1Mask | ShiftMask);
|
||||||
|
grabKey(XK_Tab, ControlMask);
|
||||||
|
grabKey(XK_Tab, ControlMask | ShiftMask);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Workspace::Workspace( WId rootwin )
|
||||||
|
{
|
||||||
|
qDebug("create MDI workspace for %d", rootwin );
|
||||||
|
root = rootwin;
|
||||||
|
|
||||||
|
// select windowmanager privileges
|
||||||
|
XSelectInput(qt_xdisplay(), root,
|
||||||
|
KeyPressMask |
|
||||||
|
PropertyChangeMask |
|
||||||
|
ColormapChangeMask |
|
||||||
|
SubstructureRedirectMask |
|
||||||
|
SubstructureNotifyMask
|
||||||
|
);
|
||||||
|
|
||||||
|
init();
|
||||||
|
control_grab = FALSE;
|
||||||
|
tab_grab = FALSE;
|
||||||
|
tab_box = new TabBox( this );
|
||||||
|
grabKey(XK_Tab, Mod1Mask);
|
||||||
|
grabKey(XK_Tab, Mod1Mask | ShiftMask);
|
||||||
|
grabKey(XK_Tab, ControlMask);
|
||||||
|
grabKey(XK_Tab, ControlMask | ShiftMask);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspace::init()
|
||||||
|
{
|
||||||
|
tab_box = 0;
|
||||||
|
active_client = 0;
|
||||||
|
should_get_focus = 0;
|
||||||
|
desktop_client = 0;
|
||||||
|
current_desktop = 1;
|
||||||
|
|
||||||
|
unsigned int i, nwins;
|
||||||
|
Window dw1, dw2, *wins;
|
||||||
|
XWindowAttributes attr;
|
||||||
|
|
||||||
|
XGrabServer( qt_xdisplay() );
|
||||||
|
XQueryTree(qt_xdisplay(), root, &dw1, &dw2, &wins, &nwins);
|
||||||
|
for (i = 0; i < nwins; i++) {
|
||||||
|
XGetWindowAttributes(qt_xdisplay(), wins[i], &attr);
|
||||||
|
if (attr.override_redirect )
|
||||||
|
continue;
|
||||||
|
if (attr.map_state != IsUnmapped) {
|
||||||
|
Client* c = clientFactory( this, wins[i] );
|
||||||
|
clients.append( c );
|
||||||
|
if ( c != desktop_client )
|
||||||
|
stacking_order.append( c );
|
||||||
|
focus_chain.append( c );
|
||||||
|
c->manage( TRUE );
|
||||||
|
if ( c == desktop_client )
|
||||||
|
setDesktopClient( c );
|
||||||
|
if ( root != qt_xrootwin() ) {
|
||||||
|
// TODO may use QWidget:.create
|
||||||
|
qDebug(" create a mdi client");
|
||||||
|
XReparentWindow( qt_xdisplay(), c->winId(), root, 0, 0 );
|
||||||
|
c->move(0,0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XFree((void *) wins);
|
||||||
|
XUngrabServer( qt_xdisplay() );
|
||||||
|
popup = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Workspace::~Workspace()
|
||||||
|
{
|
||||||
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
||||||
|
delete (*it);
|
||||||
|
}
|
||||||
|
delete tab_box;
|
||||||
|
delete popup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Handles workspace specific XEvents
|
||||||
|
*/
|
||||||
|
bool Workspace::workspaceEvent( XEvent * e )
|
||||||
|
{
|
||||||
|
Client * c = findClient( e->xany.window );
|
||||||
|
if ( c )
|
||||||
|
return c->windowEvent( e );
|
||||||
|
|
||||||
|
switch (e->type) {
|
||||||
|
case ButtonPress:
|
||||||
|
case ButtonRelease:
|
||||||
|
break;
|
||||||
|
case UnmapNotify:
|
||||||
|
// this is special due to
|
||||||
|
// SubstructureRedirectMask. e->xany.window is the window the
|
||||||
|
// event is reported to. Take care not to confuse Qt.
|
||||||
|
c = findClient( e->xunmap.window );
|
||||||
|
|
||||||
|
if ( c )
|
||||||
|
return c->windowEvent( e );
|
||||||
|
|
||||||
|
if ( e->xunmap.event != e->xunmap.window ) // hide wm typical event from Qt
|
||||||
|
return TRUE;
|
||||||
|
case ReparentNotify:
|
||||||
|
//do not confuse Qt with these events. After all, _we_ are the
|
||||||
|
//window manager who does the reparenting.
|
||||||
|
return true;
|
||||||
|
case DestroyNotify:
|
||||||
|
return destroyClient( findClient( e->xdestroywindow.window ) );
|
||||||
|
case MapRequest:
|
||||||
|
if ( e->xmaprequest.parent == root ) {
|
||||||
|
c = findClient( e->xmaprequest.window );
|
||||||
|
if ( !c ) {
|
||||||
|
c = clientFactory( this, e->xmaprequest.window );
|
||||||
|
if ( root != qt_xrootwin() ) {
|
||||||
|
// TODO may use QWidget:.create
|
||||||
|
XReparentWindow( qt_xdisplay(), c->winId(), root, 0, 0 );
|
||||||
|
}
|
||||||
|
clients.append( c );
|
||||||
|
if ( c != desktop_client )
|
||||||
|
stacking_order.append( c );
|
||||||
|
}
|
||||||
|
bool result = c->windowEvent( e );
|
||||||
|
if ( c == desktop_client )
|
||||||
|
setDesktopClient( c );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ConfigureRequest:
|
||||||
|
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 );
|
||||||
|
|
||||||
|
XWindowAttributes attr;
|
||||||
|
if (XGetWindowAttributes(qt_xdisplay(), e->xconfigurerequest.window, &attr)){
|
||||||
|
// send a synthetic configure notify in any case (even if we didn't change anything)
|
||||||
|
XConfigureEvent c;
|
||||||
|
c.type = ConfigureNotify;
|
||||||
|
c.event = e->xconfigurerequest.window;
|
||||||
|
c.window = e->xconfigurerequest.window;
|
||||||
|
c.x = attr.x;
|
||||||
|
c.y = attr.y;
|
||||||
|
c.width = attr.width;
|
||||||
|
c.height = attr.height;
|
||||||
|
c.border_width = 0;
|
||||||
|
XSendEvent( qt_xdisplay(), c.event, TRUE, NoEventMask, (XEvent*)&c );
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c = findClient( e->xconfigurerequest.window );
|
||||||
|
if ( c )
|
||||||
|
return c->windowEvent( e );
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case KeyPress:
|
||||||
|
return keyPress(e->xkey);
|
||||||
|
break;
|
||||||
|
case KeyRelease:
|
||||||
|
return keyRelease(e->xkey);
|
||||||
|
break;
|
||||||
|
case FocusIn:
|
||||||
|
break;
|
||||||
|
case FocusOut:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Finds the client that embedds the window \a w
|
||||||
|
*/
|
||||||
|
Client* Workspace::findClient( WId w ) const
|
||||||
|
{
|
||||||
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
||||||
|
if ( (*it)->window() == w )
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the workspace's geometry
|
||||||
|
*/
|
||||||
|
QRect Workspace::geometry() const
|
||||||
|
{
|
||||||
|
if ( root == qt_xrootwin() )
|
||||||
|
return QRect( QPoint(0, 0), QApplication::desktop()->size() );
|
||||||
|
else {
|
||||||
|
// todo caching, keep track of configure notify etc.
|
||||||
|
QRect r;
|
||||||
|
XWindowAttributes attr;
|
||||||
|
if (XGetWindowAttributes(qt_xdisplay(), root, &attr)){
|
||||||
|
r.setRect(0, 0, attr.width, attr.height );
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Destroys the client \a c
|
||||||
|
*/
|
||||||
|
bool Workspace::destroyClient( Client* c)
|
||||||
|
{
|
||||||
|
if ( !c )
|
||||||
|
return FALSE;
|
||||||
|
clients.remove( c );
|
||||||
|
stacking_order.remove( c );
|
||||||
|
focus_chain.remove( c );
|
||||||
|
c->invalidateWindow();
|
||||||
|
delete c;
|
||||||
|
clientHidden( c );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Auxiliary function to release a passive keyboard grab
|
||||||
|
*/
|
||||||
|
void Workspace::freeKeyboard(bool pass){
|
||||||
|
if (!pass)
|
||||||
|
XAllowEvents(qt_xdisplay(), AsyncKeyboard, CurrentTime);
|
||||||
|
else
|
||||||
|
XAllowEvents(qt_xdisplay(), ReplayKeyboard, CurrentTime);
|
||||||
|
QApplication::syncX();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Handles alt-tab / control-tab
|
||||||
|
*/
|
||||||
|
bool Workspace::keyPress(XKeyEvent key)
|
||||||
|
{
|
||||||
|
if ( root != qt_xrootwin() )
|
||||||
|
return FALSE;
|
||||||
|
int kc = XKeycodeToKeysym(qt_xdisplay(), key.keycode, 0);
|
||||||
|
int km = key.state & (ControlMask | Mod1Mask | ShiftMask);
|
||||||
|
|
||||||
|
const bool options_alt_tab_mode_is_CDE_style = FALSE; // TODO
|
||||||
|
|
||||||
|
if (!control_grab){
|
||||||
|
|
||||||
|
if( (kc == XK_Tab) &&
|
||||||
|
( km == (Mod1Mask | ShiftMask)
|
||||||
|
|| km == (Mod1Mask)
|
||||||
|
)){
|
||||||
|
if (!tab_grab){
|
||||||
|
if (options_alt_tab_mode_is_CDE_style ){
|
||||||
|
// CDE style raise / lower
|
||||||
|
Client* c = topClientOnDesktop();
|
||||||
|
Client* nc = c;
|
||||||
|
if (km & ShiftMask){
|
||||||
|
do {
|
||||||
|
nc = previousStaticClient(nc);
|
||||||
|
} while (nc && nc != c &&
|
||||||
|
(!nc->isOnDesktop(currentDesktop()) ||
|
||||||
|
nc->isIconified()));
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
do {
|
||||||
|
nc = nextStaticClient(nc);
|
||||||
|
} while (nc && nc != c &&
|
||||||
|
(!nc->isOnDesktop(currentDesktop()) ||
|
||||||
|
nc->isIconified()));
|
||||||
|
if (c && c != nc)
|
||||||
|
;//TODO lowerClient(c);
|
||||||
|
if (nc)
|
||||||
|
activateClient( nc );
|
||||||
|
freeKeyboard(FALSE);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
XGrabKeyboard(qt_xdisplay(),
|
||||||
|
root, FALSE,
|
||||||
|
GrabModeAsync, GrabModeAsync,
|
||||||
|
CurrentTime);
|
||||||
|
tab_grab = TRUE;
|
||||||
|
tab_box->setMode( TabBox::WindowsMode );
|
||||||
|
tab_box->reset();
|
||||||
|
}
|
||||||
|
tab_box->nextPrev( (km & ShiftMask) == 0 );
|
||||||
|
tab_box->show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tab_grab){
|
||||||
|
|
||||||
|
|
||||||
|
if( (kc == XK_Tab) &&
|
||||||
|
( km == (ControlMask | ShiftMask)
|
||||||
|
|| km == (ControlMask)
|
||||||
|
)){
|
||||||
|
//TODO if (!options.ControlTab){
|
||||||
|
// freeKeyboard(TRUE);
|
||||||
|
// return TRUE;
|
||||||
|
// }
|
||||||
|
if (!control_grab){
|
||||||
|
XGrabKeyboard(qt_xdisplay(),
|
||||||
|
root, FALSE,
|
||||||
|
GrabModeAsync, GrabModeAsync,
|
||||||
|
CurrentTime);
|
||||||
|
control_grab = TRUE;
|
||||||
|
tab_box->setMode( TabBox::DesktopMode );
|
||||||
|
tab_box->reset();
|
||||||
|
}
|
||||||
|
tab_box->nextPrev( (km & ShiftMask) == 0 );
|
||||||
|
tab_box->show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (control_grab || tab_grab){
|
||||||
|
if (kc == XK_Escape){
|
||||||
|
XUngrabKeyboard(qt_xdisplay(), CurrentTime);
|
||||||
|
tab_box->hide();
|
||||||
|
tab_grab = FALSE;
|
||||||
|
control_grab = FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeKeyboard(FALSE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Handles alt-tab / control-tab
|
||||||
|
*/
|
||||||
|
bool Workspace::keyRelease(XKeyEvent key)
|
||||||
|
{
|
||||||
|
if ( root != qt_xrootwin() )
|
||||||
|
return FALSE;
|
||||||
|
int i;
|
||||||
|
if (tab_grab){
|
||||||
|
XModifierKeymap* xmk = XGetModifierMapping(qt_xdisplay());
|
||||||
|
for (i=0; i<xmk->max_keypermod; i++)
|
||||||
|
if (xmk->modifiermap[xmk->max_keypermod * Mod1MapIndex + i]
|
||||||
|
== key.keycode){
|
||||||
|
XUngrabKeyboard(qt_xdisplay(), CurrentTime);
|
||||||
|
tab_box->hide();
|
||||||
|
tab_grab = false;
|
||||||
|
if ( tab_box->currentClient() ){
|
||||||
|
|
||||||
|
activateClient( tab_box->currentClient() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (control_grab){
|
||||||
|
XModifierKeymap* xmk = XGetModifierMapping(qt_xdisplay());
|
||||||
|
for (i=0; i<xmk->max_keypermod; i++)
|
||||||
|
if (xmk->modifiermap[xmk->max_keypermod * ControlMapIndex + i]
|
||||||
|
== key.keycode){
|
||||||
|
XUngrabKeyboard(qt_xdisplay(), CurrentTime);
|
||||||
|
tab_box->hide();
|
||||||
|
control_grab = False;
|
||||||
|
if ( tab_box->currentDesktop() != -1 )
|
||||||
|
switchDesktop( tab_box->currentDesktop() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
auxiliary functions to travers all clients according the focus
|
||||||
|
order. Useful for kwm´s Alt-tab feature.
|
||||||
|
*/
|
||||||
|
Client* Workspace::nextClient( Client* c ) const
|
||||||
|
{
|
||||||
|
if ( focus_chain.isEmpty() )
|
||||||
|
return 0;
|
||||||
|
ClientList::ConstIterator it = focus_chain.find( c );
|
||||||
|
if ( it == focus_chain.end() )
|
||||||
|
return focus_chain.last();
|
||||||
|
if ( it == focus_chain.begin() )
|
||||||
|
return focus_chain.last();
|
||||||
|
--it;
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
auxiliary functions to travers all clients according the focus
|
||||||
|
order. Useful for kwm´s Alt-tab feature.
|
||||||
|
*/
|
||||||
|
Client* Workspace::previousClient( Client* c ) const
|
||||||
|
{
|
||||||
|
if ( focus_chain.isEmpty() )
|
||||||
|
return 0;
|
||||||
|
ClientList::ConstIterator it = focus_chain.find( c );
|
||||||
|
if ( it == focus_chain.end() )
|
||||||
|
return focus_chain.first();
|
||||||
|
++it;
|
||||||
|
if ( it == focus_chain.end() )
|
||||||
|
return focus_chain.first();
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
auxiliary functions to travers all clients according the static
|
||||||
|
order. Useful for the CDE-style Alt-tab feature.
|
||||||
|
*/
|
||||||
|
Client* Workspace::nextStaticClient( Client* c ) const
|
||||||
|
{
|
||||||
|
if ( clients.isEmpty() )
|
||||||
|
return 0;
|
||||||
|
ClientList::ConstIterator it = clients.find( c );
|
||||||
|
if ( it == clients.end() )
|
||||||
|
return clients.first();
|
||||||
|
++it;
|
||||||
|
if ( it == clients.end() )
|
||||||
|
return clients.first();
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
/*!
|
||||||
|
auxiliary functions to travers all clients according the static
|
||||||
|
order. Useful for the CDE-style Alt-tab feature.
|
||||||
|
*/
|
||||||
|
Client* Workspace::previousStaticClient( Client* c ) const
|
||||||
|
{
|
||||||
|
if ( clients.isEmpty() )
|
||||||
|
return 0;
|
||||||
|
ClientList::ConstIterator it = clients.find( c );
|
||||||
|
if ( it == clients.end() )
|
||||||
|
return clients.last();
|
||||||
|
if ( it == clients.begin() )
|
||||||
|
return clients.last();
|
||||||
|
--it;
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns topmost visible client within the specified layer range on
|
||||||
|
the current desktop, or 0 if no clients are visible. \a fromLayer has to
|
||||||
|
be smaller than \a toLayer.
|
||||||
|
*/
|
||||||
|
Client* Workspace::topClientOnDesktop( int fromLayer, int toLayer) const
|
||||||
|
{
|
||||||
|
fromLayer = toLayer = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Grabs the keysymbol \a keysym with the given modifiers \a mod
|
||||||
|
plus all possibile combinations of Lock and NumLock
|
||||||
|
*/
|
||||||
|
void Workspace::grabKey(KeySym keysym, unsigned int mod){
|
||||||
|
static int NumLockMask = 0;
|
||||||
|
if (!keysym||!XKeysymToKeycode(qt_xdisplay(), keysym)) return;
|
||||||
|
if (!NumLockMask){
|
||||||
|
XModifierKeymap* xmk = XGetModifierMapping(qt_xdisplay());
|
||||||
|
int i;
|
||||||
|
for (i=0; i<8; i++){
|
||||||
|
if (xmk->modifiermap[xmk->max_keypermod * i] ==
|
||||||
|
XKeysymToKeycode(qt_xdisplay(), XK_Num_Lock))
|
||||||
|
NumLockMask = (1<<i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XGrabKey(qt_xdisplay(),
|
||||||
|
XKeysymToKeycode(qt_xdisplay(), keysym), mod,
|
||||||
|
qt_xrootwin(), TRUE,
|
||||||
|
GrabModeSync, GrabModeSync);
|
||||||
|
XGrabKey(qt_xdisplay(),
|
||||||
|
XKeysymToKeycode(qt_xdisplay(), keysym), mod | LockMask,
|
||||||
|
qt_xrootwin(), TRUE,
|
||||||
|
GrabModeSync, GrabModeSync);
|
||||||
|
XGrabKey(qt_xdisplay(),
|
||||||
|
XKeysymToKeycode(qt_xdisplay(), keysym), mod | NumLockMask,
|
||||||
|
qt_xrootwin(), TRUE,
|
||||||
|
GrabModeSync, GrabModeSync);
|
||||||
|
XGrabKey(qt_xdisplay(),
|
||||||
|
XKeysymToKeycode(qt_xdisplay(), keysym), mod | LockMask | NumLockMask,
|
||||||
|
qt_xrootwin(), TRUE,
|
||||||
|
GrabModeSync, GrabModeSync);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Informs the workspace about the active client, i.e. the client that
|
||||||
|
has the focus (or None if no client has the focus). This functions
|
||||||
|
is called by the client itself that gets focus. It has no other
|
||||||
|
effect than fixing the focus chain and the return value of activeClient()
|
||||||
|
*/
|
||||||
|
void Workspace::setActiveClient( Client* c )
|
||||||
|
{
|
||||||
|
if ( active_client == c )
|
||||||
|
return;
|
||||||
|
if ( active_client )
|
||||||
|
active_client->setActive( FALSE );
|
||||||
|
active_client = c;
|
||||||
|
if ( active_client ) {
|
||||||
|
focus_chain.remove( c );
|
||||||
|
focus_chain.append( c );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Tries to activate the client \a c. This function performs what you
|
||||||
|
expect when clicking the respective entry in a taskbar: showing and
|
||||||
|
raising the client (this may imply switching to the another virtual
|
||||||
|
desktop) and putting the focus onto it. Once X really gave focus to
|
||||||
|
the client window as requested, the client itself will call
|
||||||
|
setActiveClient() and the operation is complete. This may not happen
|
||||||
|
with certain focus policies, though.
|
||||||
|
|
||||||
|
\sa setActiveClient(), requestFocus()
|
||||||
|
*/
|
||||||
|
void Workspace::activateClient( Client* c)
|
||||||
|
{
|
||||||
|
if (!c->isOnDesktop(currentDesktop()) ) {
|
||||||
|
// TODO switch desktop
|
||||||
|
}
|
||||||
|
raiseClient( c );
|
||||||
|
c->show();
|
||||||
|
if ( options->focusPolicyIsReasonable() )
|
||||||
|
requestFocus( c );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Tries to activate the client by asking X for the input focus. This
|
||||||
|
function does not perform any show, raise or desktop switching. See
|
||||||
|
Workspace::activateClient() instead.
|
||||||
|
|
||||||
|
\sa Workspace::activateClient()
|
||||||
|
*/
|
||||||
|
void Workspace::requestFocus( Client* c)
|
||||||
|
{
|
||||||
|
|
||||||
|
//TODO will be different for non-root clients. (subclassing?)
|
||||||
|
if ( !c ) {
|
||||||
|
focusToNull();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( c->isVisible() && !c->isShade() ) {
|
||||||
|
c->takeFocus();
|
||||||
|
should_get_focus = c;
|
||||||
|
} else if ( c->isShade() ) {
|
||||||
|
// client cannot accept focus, but at least the window should be active (window menu, et. al. )
|
||||||
|
focusToNull();
|
||||||
|
c->setActive( TRUE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Informs the workspace that the client \a c has been hidden. If it
|
||||||
|
was the active client, the workspace activates another one.
|
||||||
|
|
||||||
|
\a c may already be destroyed
|
||||||
|
*/
|
||||||
|
void Workspace::clientHidden( Client* c )
|
||||||
|
{
|
||||||
|
if ( c == active_client || ( !active_client && c == should_get_focus ) ) {
|
||||||
|
active_client = 0;
|
||||||
|
should_get_focus = 0;
|
||||||
|
if ( clients.contains( c ) ) {
|
||||||
|
focus_chain.remove( c );
|
||||||
|
focus_chain.prepend( c );
|
||||||
|
}
|
||||||
|
if ( options->focusPolicyIsReasonable() ) {
|
||||||
|
for ( ClientList::ConstIterator it = focus_chain.fromLast(); it != focus_chain.begin(); --it) {
|
||||||
|
if ( (*it)->isVisible() ) {
|
||||||
|
requestFocus( *it );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Workspace::showPopup( const QPoint& pos, Client* c)
|
||||||
|
{
|
||||||
|
// experimental!!!
|
||||||
|
|
||||||
|
if ( !popup ) {
|
||||||
|
popup = new QPopupMenu;
|
||||||
|
|
||||||
|
// I wish I could use qt-2.1 features here..... grmblll
|
||||||
|
QPopupMenu* deco = new QPopupMenu( popup );
|
||||||
|
deco->insertItem("KDE Classic", 100 );
|
||||||
|
deco->insertItem("Be-like style", 101 );
|
||||||
|
|
||||||
|
popup->insertItem("Decoration", deco );
|
||||||
|
}
|
||||||
|
popup_client = c;
|
||||||
|
// TODO customize popup for the client
|
||||||
|
int ret = popup->exec( pos );
|
||||||
|
|
||||||
|
switch( ret ) {
|
||||||
|
case 100:
|
||||||
|
setDecoration( 0 );
|
||||||
|
break;
|
||||||
|
case 101:
|
||||||
|
setDecoration( 1 );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
popup_client = 0;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Places the client \a c according to the workspace's layout policy
|
||||||
|
*/
|
||||||
|
void Workspace::doPlacement( Client* c )
|
||||||
|
{
|
||||||
|
randomPlacement( c );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Place the client \a c according to a simply "random" placement algorithm.
|
||||||
|
*/
|
||||||
|
void Workspace::randomPlacement(Client* c){
|
||||||
|
const int step = 24;
|
||||||
|
static int px = step;
|
||||||
|
static int py = 2 * step;
|
||||||
|
int tx,ty;
|
||||||
|
|
||||||
|
QRect maxRect = geometry(); // TODO
|
||||||
|
|
||||||
|
if (px < maxRect.x())
|
||||||
|
px = maxRect.x();
|
||||||
|
if (py < maxRect.y())
|
||||||
|
py = maxRect.y();
|
||||||
|
|
||||||
|
px += step;
|
||||||
|
py += 2*step;
|
||||||
|
|
||||||
|
if (px > maxRect.width()/2)
|
||||||
|
px = maxRect.x() + step;
|
||||||
|
if (py > maxRect.height()/2)
|
||||||
|
py = maxRect.y() + step;
|
||||||
|
tx = px;
|
||||||
|
ty = py;
|
||||||
|
if (tx + c->width() > maxRect.right()){
|
||||||
|
tx = maxRect.right() - c->width();
|
||||||
|
if (tx < 0)
|
||||||
|
tx = 0;
|
||||||
|
px = maxRect.x();
|
||||||
|
}
|
||||||
|
if (ty + c->height() > maxRect.bottom()){
|
||||||
|
ty = maxRect.bottom() - c->height();
|
||||||
|
if (ty < 0)
|
||||||
|
ty = 0;
|
||||||
|
py = maxRect.y();
|
||||||
|
}
|
||||||
|
c->move( tx, ty );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Raises the client \a c taking layers, transient windows and window
|
||||||
|
groups into account.
|
||||||
|
*/
|
||||||
|
void Workspace::raiseClient( Client* c )
|
||||||
|
{
|
||||||
|
if ( !c )
|
||||||
|
return;
|
||||||
|
if ( c == desktop_client )
|
||||||
|
return; // deny
|
||||||
|
|
||||||
|
Window* new_stack = new Window[ stacking_order.count()+1];
|
||||||
|
|
||||||
|
stacking_order.remove( c );
|
||||||
|
stacking_order.append( c );
|
||||||
|
|
||||||
|
ClientList saveset;
|
||||||
|
saveset.append( c );
|
||||||
|
raiseTransientsOf(saveset, c );
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
|
||||||
|
new_stack[i++] = (*it)->winId();
|
||||||
|
}
|
||||||
|
XRaiseWindow(qt_xdisplay(), new_stack[0]);
|
||||||
|
XRestackWindows(qt_xdisplay(), new_stack, i);
|
||||||
|
delete [] new_stack;
|
||||||
|
|
||||||
|
if ( c->transientFor() )
|
||||||
|
raiseClient( findClient( c->transientFor() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Private auxiliary function used in raiseClient()
|
||||||
|
*/
|
||||||
|
void Workspace::raiseTransientsOf( ClientList& safeset, Client* c )
|
||||||
|
{
|
||||||
|
ClientList local = stacking_order;
|
||||||
|
for ( ClientList::ConstIterator it = local.begin(); it != local.end(); ++it) {
|
||||||
|
if ( (*it)->transientFor() == c->window() && !safeset.contains( *it ) ) {
|
||||||
|
safeset.append( *it );
|
||||||
|
stacking_order.remove( *it );
|
||||||
|
stacking_order.append( *it );
|
||||||
|
raiseTransientsOf( safeset, *it );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Puts the focus on a dummy winodw
|
||||||
|
*/
|
||||||
|
void Workspace::focusToNull(){
|
||||||
|
static Window w = 0;
|
||||||
|
int mask;
|
||||||
|
XSetWindowAttributes attr;
|
||||||
|
if (w == 0) {
|
||||||
|
mask = CWOverrideRedirect;
|
||||||
|
attr.override_redirect = 1;
|
||||||
|
w = XCreateWindow(qt_xdisplay(), qt_xrootwin(), 0, 0, 1, 1, 0, CopyFromParent,
|
||||||
|
InputOnly, CopyFromParent, mask, &attr);
|
||||||
|
XMapWindow(qt_xdisplay(), w);
|
||||||
|
}
|
||||||
|
XSetInputFocus(qt_xdisplay(), w, RevertToPointerRoot, CurrentTime );
|
||||||
|
//colormapFocus(0); TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspace::setDesktopClient( Client* c)
|
||||||
|
{
|
||||||
|
desktop_client = c;
|
||||||
|
if ( desktop_client ) {
|
||||||
|
desktop_client->lower();
|
||||||
|
desktop_client->setGeometry( geometry() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspace::switchDesktop( int new_desktop ){
|
||||||
|
if (new_desktop == current_desktop )
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
optimized Desktop switching: unmapping done from back to front
|
||||||
|
mapping done from front to back => less exposure events
|
||||||
|
*/
|
||||||
|
|
||||||
|
for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
|
||||||
|
if ( (*it)->isVisible() && !(*it)->isOnDesktop( new_desktop ) ) {
|
||||||
|
(*it)->hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it) {
|
||||||
|
if ( (*it)->isOnDesktop( new_desktop ) ) {
|
||||||
|
(*it)->show();
|
||||||
|
//XMapWindow( qt_xdisplay(), (*it)->winId() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
current_desktop = new_desktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Workspace::makeFullScreen( Client* )
|
||||||
|
{
|
||||||
|
// not yet implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// experimental
|
||||||
|
void Workspace::setDecoration( int deco )
|
||||||
|
{
|
||||||
|
if ( !popup_client )
|
||||||
|
return;
|
||||||
|
Client* c = popup_client;
|
||||||
|
WId w = c->window();
|
||||||
|
clients.remove( c );
|
||||||
|
stacking_order.remove( c );
|
||||||
|
focus_chain.remove( c );
|
||||||
|
bool mapped = c->isVisible();
|
||||||
|
c->hide();
|
||||||
|
c->releaseWindow();
|
||||||
|
switch ( deco ) {
|
||||||
|
case 1:
|
||||||
|
c = new BeClient( this, w);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
c = new StdClient( this, w );
|
||||||
|
}
|
||||||
|
clients.append( c );
|
||||||
|
stacking_order.append( c );
|
||||||
|
c->manage( mapped );
|
||||||
|
activateClient( c );
|
||||||
|
}
|
||||||
|
|
126
workspace.h
Normal file
126
workspace.h
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
#ifndef WORKSPACE_H
|
||||||
|
#define WORKSPACE_H
|
||||||
|
|
||||||
|
#include <qwidget.h>
|
||||||
|
#include <qapplication.h>
|
||||||
|
#include <qpopupmenu.h>
|
||||||
|
#include <qvaluelist.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
class Client;
|
||||||
|
class TabBox;
|
||||||
|
|
||||||
|
typedef QValueList<Client*> ClientList;
|
||||||
|
|
||||||
|
class Workspace : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Workspace();
|
||||||
|
Workspace( WId rootwin );
|
||||||
|
virtual ~Workspace();
|
||||||
|
|
||||||
|
virtual bool workspaceEvent( XEvent * );
|
||||||
|
|
||||||
|
Client* findClient( WId w ) const;
|
||||||
|
|
||||||
|
QRect geometry() const;
|
||||||
|
|
||||||
|
bool destroyClient( Client* );
|
||||||
|
|
||||||
|
WId rootWin() const;
|
||||||
|
|
||||||
|
Client* activeClient() const;
|
||||||
|
void setActiveClient( Client* );
|
||||||
|
void activateClient( Client* );
|
||||||
|
void requestFocus( Client* c);
|
||||||
|
|
||||||
|
void doPlacement( Client* c );
|
||||||
|
void raiseClient( Client* c );
|
||||||
|
|
||||||
|
void clientHidden( Client* );
|
||||||
|
|
||||||
|
int currentDesktop() const;
|
||||||
|
int numberOfDesktops() const;
|
||||||
|
|
||||||
|
void grabKey(KeySym keysym, unsigned int mod);
|
||||||
|
|
||||||
|
Client* nextClient(Client*) const;
|
||||||
|
Client* previousClient(Client*) const;
|
||||||
|
Client* nextStaticClient(Client*) const;
|
||||||
|
Client* previousStaticClient(Client*) const;
|
||||||
|
|
||||||
|
//#### TODO right layers as default
|
||||||
|
Client* topClientOnDesktop( int fromLayer = 0, int toLayer = 0) const;
|
||||||
|
|
||||||
|
|
||||||
|
void showPopup( const QPoint&, Client* );
|
||||||
|
|
||||||
|
void setDesktopClient( Client* );
|
||||||
|
void switchDesktop( int new_desktop );
|
||||||
|
|
||||||
|
void makeFullScreen( Client* );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool keyPress( XKeyEvent key );
|
||||||
|
bool keyRelease( XKeyEvent key );
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init();
|
||||||
|
WId root;
|
||||||
|
ClientList clients;
|
||||||
|
ClientList stacking_order;
|
||||||
|
ClientList focus_chain;
|
||||||
|
Client* active_client;
|
||||||
|
bool control_grab;
|
||||||
|
bool tab_grab;
|
||||||
|
TabBox* tab_box;
|
||||||
|
void freeKeyboard(bool pass);
|
||||||
|
QPopupMenu *popup;
|
||||||
|
Client* should_get_focus;
|
||||||
|
|
||||||
|
void raiseTransientsOf( ClientList& safeset, Client* c );
|
||||||
|
void randomPlacement(Client* c);
|
||||||
|
|
||||||
|
void focusToNull();
|
||||||
|
Client* desktop_client;
|
||||||
|
int current_desktop;
|
||||||
|
|
||||||
|
Client* popup_client;
|
||||||
|
|
||||||
|
//experimental
|
||||||
|
void setDecoration( int deco );
|
||||||
|
};
|
||||||
|
|
||||||
|
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 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue