more experimental stuff

svn path=/trunk/kdebase/kwin/; revision=29737
This commit is contained in:
Matthias Ettrich 1999-09-27 16:02:44 +00:00
parent fd7f3549ac
commit 75f321c4c0
8 changed files with 216 additions and 44 deletions

View file

@ -4,8 +4,8 @@ LDFLAGS = $(all_libraries) $(KDE_RPATH)
bin_PROGRAMS = kwin bin_PROGRAMS = kwin
kwin_SOURCES = atoms.cpp beclient.cpp client.cpp main.cpp stdclient.cpp workspace.cpp tabbox.cpp kwin_SOURCES = atoms.cpp beclient.cpp client.cpp main.cpp stdclient.cpp workspace.cpp tabbox.cpp options.cpp
kwin_LDADD = $(LIB_KDECORE) kwin_LDADD = $(LIB_KDECORE)
METASOURCES = AUTO METASOURCES = AUTO

View file

@ -1,8 +1,10 @@
#include <qapplication.h> #include <qapplication.h>
#include <qcursor.h> #include <qcursor.h>
#include <qbitmap.h> #include <qbitmap.h>
#include <qimage.h>
#include <qwmatrix.h> #include <qwmatrix.h>
#include <qlayout.h> #include <qlayout.h>
#include <qpainter.h>
#include "workspace.h" #include "workspace.h"
#include "client.h" #include "client.h"
#include "atoms.h" #include "atoms.h"
@ -14,6 +16,32 @@
extern Atom qt_wm_state; extern Atom qt_wm_state;
static QImage* imgClient = 0;
static QPixmap* pmBackground = 0;
static QImage* imgBackground = 0;
static QRect* visible_bound = 0;
void Client::drawbound( const QRect& geom )
{
if ( visible_bound )
*visible_bound = geom;
else
visible_bound = new QRect( geom );
QPainter p ( workspace()->desktopWidget() );
p.setPen( QPen( Qt::white, 5 ) );
p.setRasterOp( Qt::XorROP );
p.drawRect( geom );
}
void Client::clearbound()
{
if ( !visible_bound )
return;
drawbound( *visible_bound );
delete visible_bound;
visible_bound = 0;
}
static void sendClientMessage(Window w, Atom a, long x){ static void sendClientMessage(Window w, Atom a, long x){
XEvent ev; XEvent ev;
@ -361,6 +389,7 @@ bool WindowWrapper::x11Event( XEvent * e)
} }
/*! /*!
\class Client client.h \class Client client.h
@ -392,6 +421,7 @@ Client::Client( Workspace *ws, WId w, QWidget *parent, const char *name, WFlags
mode = Nowhere; mode = Nowhere;
buttonDown = FALSE; buttonDown = FALSE;
moveResizeMode = FALSE;
setMouseTracking( TRUE ); setMouseTracking( TRUE );
active = FALSE; active = FALSE;
@ -400,7 +430,7 @@ Client::Client( Workspace *ws, WId w, QWidget *parent, const char *name, WFlags
is_sticky = FALSE; is_sticky = FALSE;
ignore_unmap = 0; ignore_unmap = 0;
getIcons(); getIcons();
getWindowProtocols(); getWindowProtocols();
getWmNormalHints(); // get xSizeHint getWmNormalHints(); // get xSizeHint
@ -824,6 +854,30 @@ void Client::mouseReleaseEvent( QMouseEvent * e)
{ {
if ( e->button() == LeftButton ) { if ( e->button() == LeftButton ) {
buttonDown = FALSE; buttonDown = FALSE;
if ( moveResizeMode ) {
clearbound();
if ( isMove() && options->moveMode == Options::HalfTransparent ) {
QPainter p ( workspace()->desktopWidget() );
if ( !mask.isNull() ) {
QRegion r( mask );
r.translate( x(), y() );
p.setClipRegion( r );
}
p.drawImage( x(), y(), *imgClient);
}
delete imgClient;
imgClient = 0;
delete imgBackground;
imgBackground = 0;
delete pmBackground;
pmBackground = 0;
if ( ( isMove() && options->moveMode != Options::Opaque )
|| ( isResize() && options->resizeMode != Options::Opaque ) )
XUngrabServer( qt_xdisplay() );
setGeometry( geom );
moveResizeMode = FALSE;
releaseMouse();
}
} }
} }
@ -838,6 +892,39 @@ void Client::mouseMoveEvent( QMouseEvent * e)
return; return;
} }
QRect oldGeom( geom );
if ( !moveResizeMode )
{
QPoint p( e->pos() - moveOffset );
if ( QABS( p.x() >= 4) || QABS( p.y() ) >= 4 ) {
moveResizeMode = TRUE;
grabMouse( cursor() ); // to keep the right cursor
if ( ( isMove() && options->moveMode != Options::Opaque )
|| ( isResize() && options->resizeMode != Options::Opaque ) )
XGrabServer( qt_xdisplay() );
if ( isMove() && options->moveMode == Options::HalfTransparent ) {
imgClient = new QImage( QPixmap::grabWidget( this ).convertToImage() );
// TODO SLOW!!!
pmBackground = new QPixmap( QPixmap::grabWindow( qt_xrootwin() ));
imgBackground = new QImage( pmBackground->convertToImage() );
QRect ww( windowWrapper()->geometry() );
ww.moveBy( x(), y() );
ww = ww.intersect( workspace()->geometry() );
ww.moveBy( -x(), -y() );
bitBlt( imgClient,
ww.x(),
ww.y(),
imgBackground,
x()+ww.x(), y()+ww.y(), ww.width(), ww.height() );
oldGeom.setRect(0,0,0,0);
}
}
else
return;
}
if ( mode != Center && shaded ) { if ( mode != Center && shaded ) {
wwrap->show(); wwrap->show();
workspace()->requestFocus( this ); workspace()->requestFocus( this );
@ -846,22 +933,6 @@ void Client::mouseMoveEvent( QMouseEvent * e)
QPoint globalPos = e->pos() + geometry().topLeft(); QPoint globalPos = e->pos() + geometry().topLeft();
// TODO for MDI this has to be based on the parent window!
// QPoint p = parentWidget()->mapFromGlobal( e->globalPos() );
// if ( !parentWidget()->rect().contains(p) ) {
// if ( p.x() < 0 )
// p.rx() = 0;
// if ( p.y() < 0 )
// p.ry() = 0;
// if ( p.x() > parentWidget()->width() )
// p.rx() = parentWidget()->width();
// if ( p.y() > parentWidget()->height() )
// p.ry() = parentWidget()->height();
// }
// if ( testWState(WState_ConfigPending) )
// return;
QPoint p = globalPos + invertedMoveOffset; QPoint p = globalPos + invertedMoveOffset;
@ -872,7 +943,7 @@ void Client::mouseMoveEvent( QMouseEvent * e)
QPoint mp( geometry().right() - mpsize.width() + 1, QPoint mp( geometry().right() - mpsize.width() + 1,
geometry().bottom() - mpsize.height() + 1 ); geometry().bottom() - mpsize.height() + 1 );
QRect geom = geometry(); geom = geometry();
switch ( mode ) { switch ( mode ) {
case TopLeft: case TopLeft:
geom = QRect( mp, geometry().bottomRight() ) ; geom = QRect( mp, geometry().bottomRight() ) ;
@ -905,12 +976,74 @@ void Client::mouseMoveEvent( QMouseEvent * e)
break; break;
} }
if ( geom.size() != size() ) { if ( isResize() && geom.size() != size() ) {
geom.setSize( adjustedSize( geom.size() ) ); if (options->resizeMode == Options::Opaque ) {
setGeometry( geom ); geom.setSize( adjustedSize( geom.size() ) );
setGeometry( geom );
} else if ( options->resizeMode == Options::Transparent ) {
clearbound();
drawbound( geom );
}
}
else if ( isMove() && geom.topLeft() != geometry().topLeft() ) {
switch ( options->moveMode ) {
case Options::Opaque:
move( geom.topLeft() );
break;
case Options::Transparent:
clearbound();
drawbound( geom );
break;
case Options::HalfTransparent:
{
QPainter p ( workspace()->desktopWidget() );
QRegion now( geom );
if ( !mask.isNull() ) {
QRegion r( mask );
r.translate( geom.x(), geom.y() );
now = r;
}
if ( !oldGeom.isEmpty() ) {
QRegion r( oldGeom );
r = r.subtract( now );
p.setClipRegion( r );
p.drawPixmap( oldGeom.x(), oldGeom.y(),
*pmBackground,
oldGeom.x(), oldGeom.y(),
oldGeom.width(), oldGeom.height() );
}
p.setClipRegion( now );
QImage img ( *imgClient );
img.detach();
QRect visibleRect = QRect( 0, 0,
workspace()->geometry().width(),
workspace()->geometry().height() ).intersect( geom );
for ( int i=visibleRect.top(); i<=visibleRect.bottom(); i++ ) {
uint *p = (uint *)imgBackground->scanLine(i);
uint *end = p + visibleRect.right();
p += visibleRect.left();
uint *pimg = (uint *)img.scanLine(i - geom.top() );
pimg += visibleRect.left() - geom.left();
while ( p <= end ) {
int r = (*p&0x00ff0000) >> 16;
int r2 = (*pimg&0x00ff0000) >> 16;
int g = (*p&0x0000ff00) >> 8;
int g2 = (*pimg&0x0000ff00) >> 8;
int b = (*p&0x000000ff );
int b2 = (*pimg&0x000000ff );
*pimg = ( ( (r+2*r2)/3 ) << 16 )
+ ( ( (g+2*g2)/3 ) << 8 )
+ ( (b+2*b2)/3 );
p++;
pimg++;
}
}
p.drawImage( geom.x(), geom.y(), img );
}
break;
}
} }
else if ( geom.topLeft() != geometry().topLeft() )
move( geom.topLeft() );
} }
@ -1451,6 +1584,15 @@ void Client::takeFocus()
} }
/*!\reimp
*/
void Client::setMask( const QRegion & reg)
{
mask = reg;
QWidget::setMask( reg );
}
NoBorderClient::NoBorderClient( Workspace *ws, WId w, QWidget *parent=0, const char *name=0 ) NoBorderClient::NoBorderClient( Workspace *ws, WId w, QWidget *parent=0, const char *name=0 )
: Client( ws, w, parent, name ) : Client( ws, w, parent, name )
{ {

View file

@ -119,6 +119,12 @@ public:
void takeFocus(); void takeFocus();
void setMask( const QRegion & );
// transparent stuff
virtual void drawbound( const QRect& geom );
virtual void clearbound();
public slots: public slots:
void iconify(); void iconify();
void closeWindow(); void closeWindow();
@ -175,6 +181,13 @@ private:
Workspace* wspace; Workspace* wspace;
int desk; int desk;
bool buttonDown; bool buttonDown;
bool moveResizeMode;
bool isMove() const {
return moveResizeMode && mode == Center;
}
bool isResize() const {
return !isMove();
}
MousePosition mode; MousePosition mode;
QPoint moveOffset; QPoint moveOffset;
QPoint invertedMoveOffset; QPoint invertedMoveOffset;
@ -185,6 +198,7 @@ private:
bool active; bool active;
int ignore_unmap; int ignore_unmap;
QRect original_geometry; QRect original_geometry;
QRect geom; //### TODO
bool shaded; bool shaded;
WId transient_for; WId transient_for;
bool is_sticky; bool is_sticky;
@ -195,6 +209,7 @@ private:
QPixmap icon_pix; QPixmap icon_pix;
QPixmap miniicon_pix; QPixmap miniicon_pix;
QRect geom_restore; QRect geom_restore;
QRegion mask;
}; };
inline WId Client::window() const inline WId Client::window() const

BIN
kwin Executable file

Binary file not shown.

View file

@ -12,6 +12,7 @@ SOURCES = atoms.cpp \
beclient.cpp \ beclient.cpp \
client.cpp \ client.cpp \
main.cpp \ main.cpp \
options.cpp \
stdclient.cpp \ stdclient.cpp \
tabbox.cpp \ tabbox.cpp \
workspace.cpp workspace.cpp

View file

@ -8,38 +8,40 @@ public:
/*! /*!
Different focus policies: Different focus policies:
<ul> <ul>
<li>ClickToFocus - Clicking into a window activates it. This is <li>ClickToFocus - Clicking into a window activates it. This is
also the default. also the default.
<li>FocusFollowsMouse - Moving the mouse pointer actively onto a <li>FocusFollowsMouse - Moving the mouse pointer actively onto a
window activates it. window activates it.
<li>FocusUnderMouse - The window that happens to be under the <li>FocusUnderMouse - The window that happens to be under the
mouse pointer becomes active. mouse pointer becomes active.
<li>FocusStricklyUnderMouse - Only the window under the mouse <li>FocusStricklyUnderMouse - Only the window under the mouse
pointer is active. If the mouse points nowhere, nothing has the pointer is active. If the mouse points nowhere, nothing has the
focus. In practice, this is the same as FocusUnderMouse, since focus. In practice, this is the same as FocusUnderMouse, since
kdesktop can take the focus. kdesktop can take the focus.
Note that FocusUnderMouse and FocusStricklyUnderMouse are not Note that FocusUnderMouse and FocusStricklyUnderMouse are not
particulary useful. They are only provided for old-fashined particulary useful. They are only provided for old-fashined
die-hard UNIX people ;-) die-hard UNIX people ;-)
</ul> </ul>
*/ */
enum FocusPolicy { ClickToFocus, FocusFollowsMouse, FocusUnderMouse, FocusStricklyUnderMouse }; enum FocusPolicy { ClickToFocus, FocusFollowsMouse, FocusUnderMouse, FocusStricklyUnderMouse };
FocusPolicy focusPolicy; FocusPolicy focusPolicy;
enum MoveResizeMode { Transparent, Opaque, HalfTransparent };
MoveResizeMode resizeMode;
MoveResizeMode moveMode;
bool focusPolicyIsReasonable() { bool focusPolicyIsReasonable() {
return focusPolicy == ClickToFocus || focusPolicy == FocusFollowsMouse; return focusPolicy == ClickToFocus || focusPolicy == FocusFollowsMouse;
} }
Options(){ Options();
focusPolicy = ClickToFocus;
}
}; };
extern Options* options; extern Options* options;

View file

@ -36,6 +36,7 @@ Workspace::Workspace()
root = qt_xrootwin(); // no MDI for now root = qt_xrootwin(); // no MDI for now
(void) QApplication::desktop(); // trigger creation of desktop widget (void) QApplication::desktop(); // trigger creation of desktop widget
desktop_widget = new QWidget(0, "desktop_widget", Qt::WType_Desktop | Qt::WPaintUnclipped );
// select windowmanager privileges // select windowmanager privileges
XSelectInput(qt_xdisplay(), root, XSelectInput(qt_xdisplay(), root,
@ -162,9 +163,12 @@ bool Workspace::workspaceEvent( XEvent * e )
case DestroyNotify: case DestroyNotify:
return destroyClient( findClient( e->xdestroywindow.window ) ); return destroyClient( findClient( e->xdestroywindow.window ) );
case MapRequest: case MapRequest:
qDebug("map request");
if ( e->xmaprequest.parent == root ) { if ( e->xmaprequest.parent == root ) {
qDebug("map request on root window");
c = findClient( e->xmaprequest.window ); c = findClient( e->xmaprequest.window );
if ( !c ) { if ( !c ) {
qDebug("didn't find a client, make a new one");
c = clientFactory( this, e->xmaprequest.window ); c = clientFactory( this, e->xmaprequest.window );
if ( root != qt_xrootwin() ) { if ( root != qt_xrootwin() ) {
// TODO may use QWidget:.create // TODO may use QWidget:.create
@ -640,33 +644,33 @@ void Workspace::clientHidden( Client* c )
void Workspace::showPopup( const QPoint& pos, Client* c) void Workspace::showPopup( const QPoint& pos, Client* c)
{ {
// experimental!!! // experimental!!!
if ( !popup ) { if ( !popup ) {
popup = new QPopupMenu; popup = new QPopupMenu;
// I wish I could use qt-2.1 features here..... grmblll // I wish I could use qt-2.1 features here..... grmblll
QPopupMenu* deco = new QPopupMenu( popup ); QPopupMenu* deco = new QPopupMenu( popup );
deco->insertItem("KDE Classic", 100 ); deco->insertItem("KDE Classic", 100 );
deco->insertItem("Be-like style", 101 ); deco->insertItem("Be-like style", 101 );
popup->insertItem("Decoration", deco ); popup->insertItem("Decoration", deco );
} }
popup_client = c; popup_client = c;
// TODO customize popup for the client // TODO customize popup for the client
int ret = popup->exec( pos ); int ret = popup->exec( pos );
switch( ret ) { switch( ret ) {
case 100: case 100:
setDecoration( 0 ); setDecoration( 0 );
break; break;
case 101: case 101:
setDecoration( 1 ); setDecoration( 1 );
break; break;
default: default:
break; break;
} }
popup_client = 0; popup_client = 0;
ret = 0; ret = 0;
} }
@ -803,7 +807,7 @@ void Workspace::switchDesktop( int new_desktop ){
if (new_desktop == current_desktop ) if (new_desktop == current_desktop )
return; return;
/* /*
optimized Desktop switching: unmapping done from back to front optimized Desktop switching: unmapping done from back to front
mapping done from front to back => less exposure events mapping done from front to back => less exposure events
*/ */
@ -857,3 +861,8 @@ void Workspace::setDecoration( int deco )
activateClient( c ); activateClient( c );
} }
QWidget* Workspace::desktopWidget()
{
return desktop_widget;
}

View file

@ -42,6 +42,8 @@ public:
int currentDesktop() const; int currentDesktop() const;
int numberOfDesktops() const; int numberOfDesktops() const;
QWidget* desktopWidget();
void grabKey(KeySym keysym, unsigned int mod); void grabKey(KeySym keysym, unsigned int mod);
@ -87,7 +89,8 @@ private:
int current_desktop; int current_desktop;
Client* popup_client; Client* popup_client;
QWidget* desktop_widget;
//experimental //experimental
void setDecoration( int deco ); void setDecoration( int deco );
}; };