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
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)
METASOURCES = AUTO
METASOURCES = AUTO

View file

@ -1,8 +1,10 @@
#include <qapplication.h>
#include <qcursor.h>
#include <qbitmap.h>
#include <qimage.h>
#include <qwmatrix.h>
#include <qlayout.h>
#include <qpainter.h>
#include "workspace.h"
#include "client.h"
#include "atoms.h"
@ -14,6 +16,32 @@
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){
XEvent ev;
@ -361,6 +389,7 @@ bool WindowWrapper::x11Event( XEvent * e)
}
/*!
\class Client client.h
@ -392,6 +421,7 @@ Client::Client( Workspace *ws, WId w, QWidget *parent, const char *name, WFlags
mode = Nowhere;
buttonDown = FALSE;
moveResizeMode = FALSE;
setMouseTracking( TRUE );
active = FALSE;
@ -400,7 +430,7 @@ Client::Client( Workspace *ws, WId w, QWidget *parent, const char *name, WFlags
is_sticky = FALSE;
ignore_unmap = 0;
getIcons();
getWindowProtocols();
getWmNormalHints(); // get xSizeHint
@ -824,6 +854,30 @@ void Client::mouseReleaseEvent( QMouseEvent * e)
{
if ( e->button() == LeftButton ) {
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;
}
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 ) {
wwrap->show();
workspace()->requestFocus( this );
@ -846,22 +933,6 @@ void Client::mouseMoveEvent( QMouseEvent * e)
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;
@ -872,7 +943,7 @@ void Client::mouseMoveEvent( QMouseEvent * e)
QPoint mp( geometry().right() - mpsize.width() + 1,
geometry().bottom() - mpsize.height() + 1 );
QRect geom = geometry();
geom = geometry();
switch ( mode ) {
case TopLeft:
geom = QRect( mp, geometry().bottomRight() ) ;
@ -905,12 +976,74 @@ void Client::mouseMoveEvent( QMouseEvent * e)
break;
}
if ( geom.size() != size() ) {
geom.setSize( adjustedSize( geom.size() ) );
setGeometry( geom );
if ( isResize() && geom.size() != size() ) {
if (options->resizeMode == Options::Opaque ) {
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 )
: Client( ws, w, parent, name )
{

View file

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

BIN
kwin Executable file

Binary file not shown.

View file

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

View file

@ -8,38 +8,40 @@ 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;
enum MoveResizeMode { Transparent, Opaque, HalfTransparent };
MoveResizeMode resizeMode;
MoveResizeMode moveMode;
bool focusPolicyIsReasonable() {
return focusPolicy == ClickToFocus || focusPolicy == FocusFollowsMouse;
}
Options(){
focusPolicy = ClickToFocus;
}
Options();
};
extern Options* options;

View file

@ -36,6 +36,7 @@ Workspace::Workspace()
root = qt_xrootwin(); // no MDI for now
(void) QApplication::desktop(); // trigger creation of desktop widget
desktop_widget = new QWidget(0, "desktop_widget", Qt::WType_Desktop | Qt::WPaintUnclipped );
// select windowmanager privileges
XSelectInput(qt_xdisplay(), root,
@ -162,9 +163,12 @@ bool Workspace::workspaceEvent( XEvent * e )
case DestroyNotify:
return destroyClient( findClient( e->xdestroywindow.window ) );
case MapRequest:
qDebug("map request");
if ( e->xmaprequest.parent == root ) {
qDebug("map request on root window");
c = findClient( e->xmaprequest.window );
if ( !c ) {
qDebug("didn't find a client, make a new one");
c = clientFactory( this, e->xmaprequest.window );
if ( root != qt_xrootwin() ) {
// TODO may use QWidget:.create
@ -640,33 +644,33 @@ void Workspace::clientHidden( Client* c )
void Workspace::showPopup( const QPoint& pos, Client* c)
{
// experimental!!!
// experimental!!!
if ( !popup ) {
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 );
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;
break;
default:
break;
}
popup_client = 0;
ret = 0;
}
@ -803,7 +807,7 @@ 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
*/
@ -857,3 +861,8 @@ void Workspace::setDecoration( int deco )
activateClient( c );
}
QWidget* Workspace::desktopWidget()
{
return desktop_widget;
}

View file

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