Commit fc5b0be8 authored by Matthias Ettrich's avatar Matthias Ettrich

Say hello to kwin. WARNING: NOT USABLE YET. See README.

svn path=/trunk/kdebase/kwin/; revision=27871
parent da56a661
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>
#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);
}
#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
#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 );
}
#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
This diff is collapsed.
#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
File added
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
#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>