some bugfixes, added a window operations menu, some simple shading animation

svn path=/trunk/kdebase/kwin/; revision=34662
This commit is contained in:
Matthias Ettrich 1999-11-22 01:57:51 +00:00
parent eb5e8e031d
commit 367d4fd0d7
10 changed files with 493 additions and 260 deletions

View file

@ -54,6 +54,7 @@ BeClient::BeClient( Workspace *ws, WId w, QWidget *parent, const char *name )
g->addRowSpacing(1, 2);
g->setRowStretch( 2, 10 );
g->addWidget( windowWrapper(), 2, 1 );
g->addItem( new QSpacerItem( 0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding ) );
g->addColSpacing(0, 2);
g->addColSpacing(2, 2);
g->addRowSpacing(3, 2);
@ -80,7 +81,7 @@ void BeClient::resizeEvent( QResizeEvent* e)
{
Client::resizeEvent( e );
doShape();
if ( isVisibleToTLW() ) {
if ( isVisibleToTLW() && !testWFlags( WNorthWestGravity ) ) {
// manual clearing without the titlebar (we selected WResizeNoErase )
QPainter p( this );
QRect t = titlebar->geometry();
@ -208,3 +209,8 @@ void BeClient::mouseDoubleClickEvent( QMouseEvent * e )
workspace()->requestFocus( this );
}
void BeClient::windowWrapperShowEvent( QShowEvent* )
{
doShape();
}

View file

@ -14,6 +14,7 @@ public:
~BeClient();
protected:
void resizeEvent( QResizeEvent* );
void windowWrapperShowEvent( QShowEvent* );
void paintEvent( QPaintEvent* );
void mousePressEvent( QMouseEvent * );
void mouseReleaseEvent( QMouseEvent * );

View file

@ -96,6 +96,8 @@ WindowWrapper::WindowWrapper( WId w, Client *parent, const char* name)
win = w;
setMouseTracking( TRUE );
setBackgroundColor( colorGroup().background() );
// we don't want the window to be destroyed when we are destroyed
XAddToSaveSet(qt_xdisplay(), win );
@ -733,7 +735,7 @@ void Client::mousePressEvent( QMouseEvent * e)
invertedMoveOffset = rect().bottomRight() - e->pos();
}
else if ( e->button() == RightButton ) {
workspace()->showPopup( e->globalPos(), this );
workspace()->clientPopup( this ) ->popup( e->globalPos() );
}
}
@ -1112,11 +1114,25 @@ void Client::closeWindow()
}
}
void Client::maximize( MaximizeMode /*m*/)
void Client::maximize( MaximizeMode m)
{
if ( isShade() )
setShade( FALSE );
if ( geom_restore.isNull() ) {
geom_restore = geometry();
setGeometry( workspace()->geometry() );
switch ( m ) {
case MaximizeVertical:
setGeometry( QRect( QPoint( x(), workspace()->geometry().top() ),
adjustedSize( QSize( width(), workspace()->geometry().height()) ) ) );
break;
case MaximizeHorizontal:
setGeometry( QRect( QPoint( workspace()->geometry().left(), y() ),
adjustedSize( QSize( workspace()->geometry().width(), height() ) ) ) );
break;
default:
setGeometry( QRect( workspace()->geometry().topLeft(), adjustedSize(workspace()->geometry().size()) ) );
}
maximizeChange( TRUE );
}
else {
@ -1161,6 +1177,12 @@ bool Client::eventFilter( QObject *o, QEvent * e)
break;
case QEvent::MouseButtonRelease:
break;
case QEvent::Show:
windowWrapperShowEvent( (QShowEvent*)e );
break;
case QEvent::Hide:
windowWrapperHideEvent( (QHideEvent*)e );
break;
default:
break;
}
@ -1326,12 +1348,34 @@ void Client::setShade( bool s )
shaded = s;
if (shaded ) {
int h = height();
QSize s( sizeForWindowSize( QSize( windowWrapper()->width(), 0), TRUE ) );
windowWrapper()->hide();
repaint( FALSE ); // force direct repaint
setWFlags( WNorthWestGravity );
int step = QMAX( 15, QABS( h - s.height() ) / 20 )+1;
while ( h > s.height() + step ) {
h -= step;
resize ( s.width(), h );
QApplication::syncX();
}
clearWFlags( WNorthWestGravity );
resize (s );
} else {
int h = height();
QSize s( sizeForWindowSize( windowWrapper()->size() ) );
resize ( s );
setWFlags( WNorthWestGravity );
int step = QMAX( 15, QABS( h - s.height() ) / 30 )+1;
while ( h < s.height() - step ) {
h += step;
resize ( s.width(), h );
// assume a border
// we do not have time to wait for X to send us paint events
repaint( 0, h - step-5, width(), step+5, TRUE);
QApplication::syncX();
}
clearWFlags( WNorthWestGravity );
resize ( s );
windowWrapper()->show();
layout()->activate();
repaint();
@ -1372,14 +1416,20 @@ void Client::setSticky( bool b )
if ( is_sticky == b )
return;
is_sticky = b;
if ( !is_sticky ) {
desk = workspace()->currentDesktop();
KWM::moveToDesktop( win, desk );//##### compatibility
}
if ( !is_sticky )
setDesktop( workspace()->currentDesktop() );
stickyChange( is_sticky );
}
void Client::setDesktop( int desktop)
{
if ( isOnDesktop( desktop ) )
return;
desk = desktop;
KWM::moveToDesktop( win, desk );//##### compatibility
}
void Client::getIcons()
{
icon_pix = KWM::icon( win, 32, 32 ); // TODO sizes from workspace
@ -1427,10 +1477,10 @@ void Client::setMask( const QRegion & reg)
}
NoBorderClient::NoBorderClient( Workspace *ws, WId w, QWidget *parent=0, const char *name=0 )
: Client( ws, w, parent, name )
{
setBackgroundColor( yellow );
QHBoxLayout* h = new QHBoxLayout( this );
h->addWidget( windowWrapper() );
}

View file

@ -102,6 +102,7 @@ public:
void setActive( bool );
int desktop() const;
void setDesktop( int );
bool isOnDesktop( int d ) const;
bool isShade() const;
@ -151,6 +152,8 @@ protected:
void mouseReleaseEvent( QMouseEvent * );
void mouseMoveEvent( QMouseEvent * );
void resizeEvent( QResizeEvent * );
virtual void windowWrapperShowEvent( QShowEvent* ){}
virtual void windowWrapperHideEvent( QHideEvent* ){}
void enterEvent( QEvent * );
void leaveEvent( QEvent * );
void showEvent( QShowEvent* );

View file

@ -6,3 +6,7 @@
keys->insertItem(i18n("Switch to desktop 6"), "Switch to desktop 6" ,"CTRL+F6");
keys->insertItem(i18n("Switch to desktop 7"), "Switch to desktop 7" ,"CTRL+F7");
keys->insertItem(i18n("Switch to desktop 8"), "Switch to desktop 8" ,"CTRL+F8");
keys->insertItem(i18n("Window operations menu"), "Pop-up window operations menu" ,"ALT+F3");
keys->insertItem(i18n("Window close"),"Window close" ,"ALT+F4");

View file

@ -188,6 +188,8 @@ StdClient::StdClient( Workspace *ws, WId w, QWidget *parent, const char *name )
QGridLayout* g = new QGridLayout( this, 0, 0, 2 );
g->setRowStretch( 1, 10 );
g->addWidget( windowWrapper(), 1, 1 );
g->addItem( new QSpacerItem( 0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding ) );
g->addColSpacing(0, 2);
g->addColSpacing(2, 2);
g->addRowSpacing(2, 2);
@ -197,7 +199,7 @@ StdClient::StdClient( Workspace *ws, WId w, QWidget *parent, const char *name )
button[1] = new QToolButton( this );
button[2] = new QToolButton( this );
button[3] = new QToolButton( this );
button[4] = new QToolButton( this );
button[4] = new ThreeButtonButton( this );
button[5] = new QToolButton( this );
QHBoxLayout* hb = new QHBoxLayout;
@ -225,6 +227,11 @@ StdClient::StdClient( Workspace *ws, WId w, QWidget *parent, const char *name )
button[0]->setIconSet(isActive() ? *menu_pix : *dis_menu_pix);
else
button[0]->setIconSet( miniIcon() );
connect( button[0], SIGNAL( pressed() ), this, SLOT( menuButtonPressed() ) );
button[0]->setPopupDelay( 0 );
button[0]->setPopup( workspace()->clientPopup( this ) );
button[1]->setIconSet(isSticky() ? isActive() ? *pindown_pix : *dis_pindown_pix :
isActive() ? *pinup_pix : *dis_pinup_pix );
connect( button[1], SIGNAL( clicked() ), this, ( SLOT( toggleSticky() ) ) );
@ -234,7 +241,7 @@ StdClient::StdClient( Workspace *ws, WId w, QWidget *parent, const char *name )
button[3]->setIconSet(isActive() ? *minimize_pix : *dis_minimize_pix);
connect( button[3], SIGNAL( clicked() ), this, ( SLOT( iconify() ) ) );
button[4]->setIconSet(isActive() ? *maximize_pix : *dis_maximize_pix);
connect( button[4], SIGNAL( clicked() ), this, ( SLOT( maximize() ) ) );
connect( button[4], SIGNAL( clicked(int) ), this, ( SLOT( maxButtonClicked(int) ) ) );
button[5]->setIconSet(isActive() ? *close_pix : *dis_close_pix);
connect( button[5], SIGNAL( clicked() ), this, ( SLOT( closeWindow() ) ) );
@ -267,7 +274,7 @@ void StdClient::resizeEvent( QResizeEvent* e)
QRegion r = rr.subtract( QRect( t.x()+1, 0, t.width()-2, 1 ) );
setMask( r );
if ( isVisibleToTLW() ) {
if ( isVisibleToTLW() && !testWFlags( WNorthWestGravity )) {
// manual clearing without the titlebar (we selected WResizeNoErase )
QPainter p( this );
r = rr.subtract( t );
@ -347,3 +354,27 @@ void StdClient::iconChange()
button[0]->repaint( FALSE );
}
/*!
Indicates that the menu button has been clicked
*/
void StdClient::menuButtonPressed()
{
(void ) workspace()->clientPopup( this ); //trigger the popup menu
}
void StdClient::maxButtonClicked( int button )
{
switch ( button ){
case MidButton:
maximize( MaximizeVertical );
break;
case RightButton:
maximize( MaximizeHorizontal );
break;
default: //LeftButton:
maximize( MaximizeFull );
break;
}
}

View file

@ -1,7 +1,7 @@
#ifndef STDCLIENT_H
#define STDCLIENT_H
#include "client.h"
class QToolButton;
#include <qtoolbutton.h>
class QLabel;
class QSpacerItem;
@ -23,10 +23,60 @@ protected:
void stickyChange( bool );
void activeChange( bool );
private slots:
void menuButtonPressed();
void maxButtonClicked( int );
private:
QToolButton* button[6];
QSpacerItem* titlebar;
};
/*
Like QToolButton, but provides a clicked(int) signals that
has the last pressed mouse button as argument
*/
class ThreeButtonButton: public QToolButton
{
Q_OBJECT
public:
ThreeButtonButton ( QWidget *parent = 0, const char* name = 0)
: QToolButton( parent, name )
{
connect( this, SIGNAL( clicked() ), this, SLOT( handleClicked() ) );
}
~ThreeButtonButton ()
{}
signals:
void clicked( int );
protected:
void mousePressEvent( QMouseEvent* e )
{
last_button = e->button();
QMouseEvent me ( e->type(), e->pos(), e->globalPos(), LeftButton, e->state() );
QToolButton::mousePressEvent( &me );
}
void mouseReleaseEvent( QMouseEvent* e )
{
QMouseEvent me ( e->type(), e->pos(), e->globalPos(), LeftButton, e->state() );
QToolButton::mouseReleaseEvent( &me );
}
private slots:
void handleClicked()
{
emit clicked( last_button );
}
private:
int last_button;
};
#endif

View file

@ -183,6 +183,7 @@ SystemClient::SystemClient( Workspace *ws, WId w, QWidget *parent,
QGridLayout* g = new QGridLayout(this, 0, 0, 2);
g->setRowStretch(1, 10);
g->addWidget(windowWrapper(), 1, 1 );
g->addItem( new QSpacerItem( 0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding ) );
g->addRowSpacing(2, 6);
button[0] = new SystemButton(this, "close", close_bits);
@ -224,7 +225,7 @@ void SystemClient::resizeEvent( QResizeEvent* e)
{
Client::resizeEvent( e );
if ( isVisibleToTLW() ) {
if ( isVisibleToTLW() && !testWFlags( WNorthWestGravity )) {
QPainter p( this );
QRect t = titlebar->geometry();
t.setTop( 0 );

View file

@ -106,10 +106,6 @@ Workspace::Workspace()
XChangeProperty(qt_xdisplay(), qt_xrootwin(), atoms->kwm_running, atoms->kwm_running, 32,
PropModeAppend, (unsigned char*) &data, 1);
init();
control_grab = FALSE;
tab_grab = FALSE;
tab_box = new TabBox( this );
keys = 0;
grabKey(XK_Tab, Mod1Mask);
grabKey(XK_Tab, Mod1Mask | ShiftMask);
@ -117,6 +113,11 @@ Workspace::Workspace()
grabKey(XK_Tab, ControlMask | ShiftMask);
createKeybindings();
init();
control_grab = FALSE;
tab_grab = FALSE;
tab_box = new TabBox( this );
}
Workspace::Workspace( WId rootwin )
@ -148,6 +149,9 @@ void Workspace::init()
desktop_client = 0;
current_desktop = 0;
number_of_desktops = 0;
popup = 0;
desk_popup = 0;
popup_client = 0;
setNumberOfDesktops( 4 ); // TODO options
setCurrentDesktop( 1 );
@ -184,7 +188,6 @@ void Workspace::init()
}
XFree((void *) wins);
XUngrabServer( qt_xdisplay() );
popup = 0;
propagateClients();
//CT initialize the cascading info
@ -803,48 +806,64 @@ void Workspace::clientHidden( Client* c )
}
void Workspace::showPopup( const QPoint& pos, Client* c)
QPopupMenu* Workspace::clientPopup( Client* c )
{
// experimental!!!
popup_client = c;
if ( !popup ) {
popup = new QPopupMenu;
popup->setCheckable( TRUE );
connect( popup, SIGNAL( aboutToShow() ), this, SLOT( clientPopupAboutToShow() ) );
connect( popup, SIGNAL( activated(int) ), this, SLOT( clientPopupActivated(int) ) );
// 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 );
deco->insertItem("System style", 102 );
connect( deco, SIGNAL( activated(int) ), this, SLOT( setDecorationStyle(int) ) );
deco->insertItem( i18n( "KDE Classic" ), 1 );
deco->insertItem( i18n( "Be-like style" ), 2);
deco->insertItem( i18n( "System style" ), 3 );
popup->insertItem("Decoration", deco );
}
popup_client = c;
// TODO customize popup for the client
int ret = popup->exec( pos );
KConfig *config = KGlobal::config();
config->setGroup("style");
switch( ret ) {
case 100:
config->writeEntry("Plugin", "standard");
setDecoration( 0 );
break;
case 101:
config->writeEntry("Plugin", "be");
setDecoration( 1 );
break;
case 102:
config->writeEntry("Plugin", "system");
setDecoration( 2 );
break;
default:
break;
}
config->sync();
popup_client = 0;
ret = 0;
desk_popup = new QPopupMenu( popup );
desk_popup->setCheckable( TRUE );
connect( desk_popup, SIGNAL( activated(int) ), this, SLOT( sendToDesktop(int) ) );
connect( desk_popup, SIGNAL( aboutToShow() ), this, SLOT( desktopPopupAboutToShow() ) );
popupIdMove = popup->insertItem( i18n("&Move") );
popupIdSize = popup->insertItem( i18n("&Size") );
popupIdMinimize = popup->insertItem( i18n("&Mi&nimize") );
popupIdMaximize = popup->insertItem( i18n("Ma&ximize") );
// popupIdFullscreen = popup->insertItem( i18n("&Fullscreen") );
popupIdFullscreen = 0;
popupIdShade = popup->insertItem( i18n("Sh&ade") );
popup->insertSeparator();
popup->insertItem(i18n("&Decoration"), deco );
popup->insertItem(i18n("&To desktop"), desk_popup );
popup->insertSeparator();
QString k = KAccel::keyToString( keys->currentKey( "Window close" ), true );
popupIdClose = popup->insertItem(i18n("&Close")+'\t'+k );
}
return popup;
}
void Workspace::clientPopupActivated( int id )
{
if ( !popup_client )
return;
if ( id == popupIdClose )
popup_client->closeWindow();
else if ( id == popupIdMaximize )
popup_client->maximize();
else if ( id == popupIdMinimize )
popup_client->iconify();
else if ( id == popupIdFullscreen )
popup_client->fullScreen();
else if ( id == popupIdShade )
popup_client->setShade( !popup_client->isShade() );
}
/*!
Places the client \a c according to the workspace's layout policy
@ -878,166 +897,166 @@ void Workspace::randomPlacement(Client* c){
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 );
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 );
}
/*!
Place the client \a c according to a really smart placement algorithm :-)
*/
void Workspace::smartPlacement(Client* c){
/*
* SmartPlacement by Cristian Tibirna (tibirna@kde.org)
* adapted for kwm (16-19jan98) and for kwin (16Nov1999) using (with
* permission) ideas from fvwm, authored by
* Anthony Martin (amartin@engr.csulb.edu).
*/
/*
* SmartPlacement by Cristian Tibirna (tibirna@kde.org)
* adapted for kwm (16-19jan98) and for kwin (16Nov1999) using (with
* permission) ideas from fvwm, authored by
* Anthony Martin (amartin@engr.csulb.edu).
*/
const int none = 0, h_wrong = -1, w_wrong = -2; // overlap types
long int overlap, min_overlap;
int x_optimal, y_optimal;
int possible;
const int none = 0, h_wrong = -1, w_wrong = -2; // overlap types
long int overlap, min_overlap;
int x_optimal, y_optimal;
int possible;
int cxl, cxr, cyt, cyb; //temp coords
int xl, xr, yt, yb; //temp coords
int cxl, cxr, cyt, cyb; //temp coords
int xl, xr, yt, yb; //temp coords
// get the maximum allowed windows space
QRect maxRect = clientArea();
int x = maxRect.left(), y = maxRect.top();
x_optimal = x; y_optimal = y;
// get the maximum allowed windows space
QRect maxRect = clientArea();
int x = maxRect.left(), y = maxRect.top();
x_optimal = x; y_optimal = y;
//client gabarit
int ch = c->height(), cw = c->width();
//client gabarit
int ch = c->height(), cw = c->width();
bool first_pass = true; //CT lame flag. Don't like it. What else would do?
bool first_pass = true; //CT lame flag. Don't like it. What else would do?
//loop over possible positions
do {
//test if enough room in x and y directions
if ( y + ch > maxRect.bottom() )
overlap = h_wrong; // this throws the algorithm to an exit
else if( x + cw > maxRect.right() )
overlap = w_wrong;
else {
overlap = none; //initialize
//loop over possible positions
do {
//test if enough room in x and y directions
if ( y + ch > maxRect.bottom() )
overlap = h_wrong; // this throws the algorithm to an exit
else if( x + cw > maxRect.right() )
overlap = w_wrong;
else {
overlap = none; //initialize
cxl = x; cxr = x + cw;
cyt = y; cyb = y + ch;
QValueList<Client*>::ConstIterator l;
for(l = clients.begin(); l != clients.end() ; ++l ) {
if((*l)->isOnDesktop(currentDesktop()) && (*l) != desktop_client &&
!(*l)->isIconified() && (*l) != c ) {
cxl = x; cxr = x + cw;
cyt = y; cyb = y + ch;
QValueList<Client*>::ConstIterator l;
for(l = clients.begin(); l != clients.end() ; ++l ) {
if((*l)->isOnDesktop(currentDesktop()) && (*l) != desktop_client &&
!(*l)->isIconified() && (*l) != c ) {
xl = (*l)->x(); yt = (*l)->y();
xr = xl + (*l)->height(); yb = yt + (*l)->width();
xl = (*l)->x(); yt = (*l)->y();
xr = xl + (*l)->height(); yb = yt + (*l)->width();
//if windows overlap, calc the overall overlapping
if((cxl < xr) && (cxr > xl) &&
(cyt < yb) && (cyb > yt)) {
xl = QMAX(cxl, xl); xr = QMIN(cxr, xr);
yt = QMAX(cyt, yt); yb = QMIN(cyb, yb);
overlap += (xr - xl) * (yb - yt);
}
//if windows overlap, calc the overall overlapping
if((cxl < xr) && (cxr > xl) &&
(cyt < yb) && (cyb > yt)) {
xl = QMAX(cxl, xl); xr = QMIN(cxr, xr);
yt = QMAX(cyt, yt); yb = QMIN(cyb, yb);
overlap += (xr - xl) * (yb - yt);
}
}
}
}
}
}
//CT first time we get no overlap we stop.
if (overlap == none) {
x_optimal = x;
y_optimal = y;
break;
}
if (first_pass) {
first_pass = false;
min_overlap = overlap;
}
//CT save the best position and the minimum overlap up to now
else if ( overlap >= none && overlap < min_overlap) {
min_overlap = overlap;
x_optimal = x;
y_optimal = y;
}
// really need to loop? test if there's any overlap
if ( overlap > none ) {
possible = maxRect.right();
if ( possible - cw > x) possible -= cw;
// compare to the position of each client on the current desk
QValueList<Client*>::ConstIterator l;
for(l = clients.begin(); l != clients.end() ; ++l) {
if ( (*l)->isOnDesktop(currentDesktop()) && (*l) != desktop_client &&
!(*l)->isIconified() && (*l) != c ) {
xl = (*l)->x(); yt = (*l)->y();
xr = xl + (*l)->height(); yb = yt + (*l)->width();
// if not enough room above or under the current tested client
// determine the first non-overlapped x position
if( y < yb && yt < ch + y ) {
if( yb > x )
possible = possible < yb ? possible : yb;
if( xl - cw > x )
possible = possible < xl - cw ? possible : xl - cw;
}
//CT first time we get no overlap we stop.
if (overlap == none) {
x_optimal = x;
y_optimal = y;
break;
}
x = possible;
}
}
// ... else ==> not enough x dimension (overlap was wrong on horizontal)
else if ( overlap == w_wrong ) {
x = maxRect.left();
possible = maxRect.bottom();
if ( possible - ch > y ) possible -= ch;
//test the position of each window on current desk
QValueList<Client*>::ConstIterator l;
for( l = clients.begin(); l != clients.end() ; ++l ) {
if( (*l)->isOnDesktop( currentDesktop() ) && (*l) != desktop_client &&
(*l) != c && !c->isIconified() ) {
xl = (*l)->x(); yt = (*l)->y();
xr = xl + (*l)->height(); yb = yt + (*l)->width();
if( yb > y)
possible = possible < yb ? possible : yb;
if( yt - ch > y )
possible = possible < yt - ch ? possible : yt - ch;
if (first_pass) {
first_pass = false;
min_overlap = overlap;
}
//CT save the best position and the minimum overlap up to now
else if ( overlap >= none && overlap < min_overlap) {
min_overlap = overlap;
x_optimal = x;
y_optimal = y;
}
y = possible;
}
}
}
while( overlap != none && overlap != h_wrong );
// place the window
c->move( x_optimal, y_optimal );
// really need to loop? test if there's any overlap
if ( overlap > none ) {
possible = maxRect.right();
if ( possible - cw > x) possible -= cw;
// compare to the position of each client on the current desk
QValueList<Client*>::ConstIterator l;
for(l = clients.begin(); l != clients.end() ; ++l) {
if ( (*l)->isOnDesktop(currentDesktop()) && (*l) != desktop_client &&
!(*l)->isIconified() && (*l) != c ) {
xl = (*l)->x(); yt = (*l)->y();
xr = xl + (*l)->height(); yb = yt + (*l)->width();
// if not enough room above or under the current tested client
// determine the first non-overlapped x position
if( y < yb && yt < ch + y ) {
if( yb > x )
possible = possible < yb ? possible : yb;
if( xl - cw > x )
possible = possible < xl - cw ? possible : xl - cw;
}
}
x = possible;
}
}
// ... else ==> not enough x dimension (overlap was wrong on horizontal)
else if ( overlap == w_wrong ) {
x = maxRect.left();
possible = maxRect.bottom();
if ( possible - ch > y ) possible -= ch;
//test the position of each window on current desk
QValueList<Client*>::ConstIterator l;
for( l = clients.begin(); l != clients.end() ; ++l ) {
if( (*l)->isOnDesktop( currentDesktop() ) && (*l) != desktop_client &&
(*l) != c && !c->isIconified() ) {
xl = (*l)->x(); yt = (*l)->y();
xr = xl + (*l)->height(); yb = yt + (*l)->width();
if( yb > y)
possible = possible < yb ? possible : yb;
if( yt - ch > y )
possible = possible < yt - ch ? possible : yt - ch;
}
y = possible;
}
}
}
while( overlap != none && overlap != h_wrong );
// place the window
c->move( x_optimal, y_optimal );
}
@ -1045,67 +1064,67 @@ void Workspace::smartPlacement(Client* c){
Place windows in a cascading order, remembering positions for each desktop
*/
void Workspace::cascadePlacement (Client* c, bool re_init) {
/* cascadePlacement by Cristian Tibirna (tibirna@kde.org) (30Jan98)
/* cascadePlacement by Cristian Tibirna (tibirna@kde.org) (30Jan98)
*/
// work coords
int xp, yp;
int xp, yp;
//CT how do I get from the 'Client' class the size that NW squarish "handle"
int delta_x = 24;
int delta_y = 24;
//CT how do I get from the 'Client' class the size that NW squarish "handle"
int delta_x = 24;
int delta_y = 24;
int d = currentDesktop() - 1;
int d = currentDesktop() - 1;
// get the maximum allowed windows space and desk's origin
// (CT 20Nov1999 - is this common to all desktops?)
QRect maxRect = clientArea();
// get the maximum allowed windows space and desk's origin
// (CT 20Nov1999 - is this common to all desktops?)
QRect maxRect = clientArea();
// initialize often used vars: width and height of c; we gain speed
int ch = c->height();
int cw = c->width();
int H = maxRect.bottom();
int W = maxRect.right();
int X = maxRect.left();
int Y = maxRect.top();
int ch = c->height();
int cw = c->width();
int H = maxRect.bottom();
int W = maxRect.right();
int X = maxRect.left();
int Y = maxRect.top();
//initialize if needed
if (re_init) {
cci[d].pos = QPoint(X, Y);
cci[d].col = cci[d].row = 0;
}
xp = cci[d].pos.x();
yp = cci[d].pos.y();
//here to touch in case people vote for resize on placement
if ((yp + ch ) > H) yp = Y;
if ((xp + cw ) > W)
if (!yp) {
smartPlacement(c);
return;
if (re_init) {
cci[d].pos = QPoint(X, Y);
cci[d].col = cci[d].row = 0;
}
else xp = X;
xp = cci[d].pos.x();
yp = cci[d].pos.y();
//here to touch in case people vote for resize on placement
if ((yp + ch ) > H) yp = Y;
if ((xp + cw ) > W)
if (!yp) {
smartPlacement(c);
return;
}
else xp = X;
//if this isn't the first window
if ( cci[d].pos.x() != X && cci[d].pos.y() != Y ) {
if ( xp != X && yp == Y ) xp = delta_x * (++(cci[d].col));
if ( yp != Y && xp == X ) yp = delta_y * (++(cci[d].row));
if ( cci[d].pos.x() != X && cci[d].pos.y() != Y ) {
if ( xp != X && yp == Y ) xp = delta_x * (++(cci[d].col));
if ( yp != Y && xp == X ) yp = delta_y * (++(cci[d].row));
// last resort: if still doesn't fit, smart place it
if ( ((xp + cw) > W - X) || ((yp + ch) > H - Y) ) {
smartPlacement(c);
return;
// last resort: if still doesn't fit, smart place it
if ( ((xp + cw) > W - X) || ((yp + ch) > H - Y) ) {
smartPlacement(c);
return;
}
}
}
// place the window
c->move( QPoint( xp, yp ) );
// place the window
c->move( QPoint( xp, yp ) );
// new position
cci[d].pos = QPoint( xp + delta_x, yp + delta_y );
// new position
cci[d].pos = QPoint( xp + delta_x, yp + delta_y );
}
@ -1270,7 +1289,7 @@ void Workspace::makeFullScreen( Client* )
// experimental
void Workspace::setDecoration( int deco )
void Workspace::setDecorationStyle( int deco )
{
if ( !popup_client )
return;
@ -1283,15 +1302,19 @@ void Workspace::setDecoration( int deco )
c->hide();
c->releaseWindow();
KWM::moveToDesktop( w, c->desktop() );
KConfig* config = KGlobal::config();
switch ( deco ) {
case 1:
c = new BeClient( this, w);
break;
case 2:
c = new SystemClient(this, w);
break;
c = new BeClient( this, w);
config->writeEntry("Plugin", "Be");
break;
case 3:
c = new SystemClient(this, w);
config->writeEntry("Plugin", "system");
break;
default:
c = new StdClient( this, w );
config->writeEntry("Plugin", "standard");
}
clients.append( c );
stacking_order.append( c );
@ -1430,6 +1453,9 @@ void Workspace::createKeybindings(){
keys->connectItem( "Switch to desktop 7", this, SLOT( slotSwitchDesktop7() ));
keys->connectItem( "Switch to desktop 8", this, SLOT( slotSwitchDesktop8() ));
keys->connectItem( "Pop-up window operations menu", this, SLOT( slotWindowOperations() ) );
keys->connectItem( "Window close", this, SLOT( slotWindowClose() ) );
keys->readSettings();
}
@ -1457,3 +1483,50 @@ void Workspace::slotSwitchDesktop7(){
void Workspace::slotSwitchDesktop8(){
setCurrentDesktop(8);
}
void Workspace::desktopPopupAboutToShow()
{
if ( !desk_popup )
return;
desk_popup->clear();
int id;
for ( int i = 1; i <= numberOfDesktops(); i++ ) {
id = desk_popup->insertItem( QString("&")+QString::number(i ), i );
if ( popup_client && popup_client->desktop() == i )
desk_popup->setItemChecked( id, TRUE );
}
}
void Workspace::clientPopupAboutToShow()
{
if ( !popup_client || !popup )
return;
popup->setItemChecked( popupIdMaximize, popup_client->isMaximized() );
popup->setItemChecked( popupIdShade, popup_client->isShade() );
}
void Workspace::sendToDesktop( int desk )
{
if ( !popup_client )
return;
if ( popup_client->isOnDesktop( desk ) )
return;
popup_client->setDesktop( desk );
popup_client->hide();
}
void Workspace::slotWindowOperations()
{
if ( !active_client )
return;
QPopupMenu* p = clientPopup( active_client );
p->popup( active_client->mapToGlobal( active_client->windowWrapper()->geometry().topLeft() ) );
}
void Workspace::slotWindowClose()
{
if ( !popup_client )
return;
popup_client->closeWindow();
}

View file

@ -4,6 +4,7 @@
#include <qwidget.h>
#include <qapplication.h>
#include <qpopupmenu.h>
#include <qguardedptr.h>
#include <qvaluelist.h>
#include <X11/Xlib.h>
@ -73,7 +74,6 @@ public:
void clientHidden( Client* );
int currentDesktop() const;
void setCurrentDesktop( int new_desktop );
int numberOfDesktops() const;
void setNumberOfDesktops( int n );
@ -90,7 +90,7 @@ public:
Client* topClientOnDesktop( int fromLayer = 0, int toLayer = 0) const;
void showPopup( const QPoint&, Client* );
QPopupMenu* clientPopup( Client* );
void setDesktopClient( Client* );
@ -99,6 +99,7 @@ public:
bool iconifyMeansWithdraw( Client* );
public slots:
void setCurrentDesktop( int new_desktop );
// keybindings
void slotSwitchDesktop1();
void slotSwitchDesktop2();
@ -109,6 +110,16 @@ public slots:
void slotSwitchDesktop7();
void slotSwitchDesktop8();
void slotWindowOperations();
void slotWindowClose();
private slots:
void setDecorationStyle( int );
void desktopPopupAboutToShow();
void clientPopupAboutToShow();
void sendToDesktop( int );
void clientPopupActivated( int );
protected:
bool keyPress( XKeyEvent key );
@ -128,7 +139,11 @@ private:
bool tab_grab;
TabBox* tab_box;
void freeKeyboard(bool pass);
QGuardedPtr<Client> popup_client;
QPopupMenu *popup;
int popupIdMove, popupIdSize, popupIdMinimize,popupIdMaximize,
popupIdShade, popupIdFullscreen,popupIdClose;
QPopupMenu *desk_popup;
Client* should_get_focus;
void raiseTransientsOf( ClientList& safeset, Client* c );
@ -142,7 +157,6 @@ private:
int number_of_desktops;
Client* findClientWidthId( WId w ) const;
Client* popup_client;
QWidget* desktop_widget;
//experimental