From 367d4fd0d76adad9f8fd0ae845ca0252bd76ca78 Mon Sep 17 00:00:00 2001 From: Matthias Ettrich Date: Mon, 22 Nov 1999 01:57:51 +0000 Subject: [PATCH] some bugfixes, added a window operations menu, some simple shading animation svn path=/trunk/kdebase/kwin/; revision=34662 --- beclient.cpp | 8 +- beclient.h | 1 + client.cpp | 70 ++++++- client.h | 9 +- kwinbindings.cpp | 4 + stdclient.cpp | 37 +++- stdclient.h | 52 ++++- systemclient.cpp | 17 +- workspace.cpp | 531 +++++++++++++++++++++++++++-------------------- workspace.h | 24 ++- 10 files changed, 493 insertions(+), 260 deletions(-) diff --git a/beclient.cpp b/beclient.cpp index c5a328a2e0..f6885b1cf3 100644 --- a/beclient.cpp +++ b/beclient.cpp @@ -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(); +} diff --git a/beclient.h b/beclient.h index daf78129b7..d83fc5252b 100644 --- a/beclient.h +++ b/beclient.h @@ -14,6 +14,7 @@ public: ~BeClient(); protected: void resizeEvent( QResizeEvent* ); + void windowWrapperShowEvent( QShowEvent* ); void paintEvent( QPaintEvent* ); void mousePressEvent( QMouseEvent * ); void mouseReleaseEvent( QMouseEvent * ); diff --git a/client.cpp b/client.cpp index 544d32c618..f85d28de95 100644 --- a/client.cpp +++ b/client.cpp @@ -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 ); @@ -710,7 +712,7 @@ QSize Client::sizeForWindowSize( const QSize& wsize, bool ignore_height) const int wh = 0;; if ( !wwrap->testWState( WState_ForceHide ) ) wh = wwrap->height(); - + return QSize( QMIN( QMAX( width() - ww + w, minimumWidth() ), maximumWidth() ), ignore_height? height()-wh : (QMIN( QMAX( height() - wh + h, minimumHeight() ), @@ -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() ); } diff --git a/client.h b/client.h index 5924357bb1..724ebd4819 100644 --- a/client.h +++ b/client.h @@ -25,7 +25,7 @@ public: void invalidateWindow(); QSize sizeHint() const; QSizePolicy sizePolicy() const; - + void pseudoShow(); protected: @@ -102,6 +102,7 @@ public: void setActive( bool ); int desktop() const; + void setDesktop( int ); bool isOnDesktop( int d ) const; bool isShade() const; @@ -133,7 +134,7 @@ public: void move( const QPoint & p ) { move( p.x(), p.y() ); } - + virtual bool wantsTabFocus() const { return TRUE;} //### just for now @@ -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* ); @@ -218,7 +221,7 @@ private: void getWindowProtocols(); uint Pdeletewindow :1; // does the window understand the DeleteWindow protocol? uint Ptakefocus :1;// does the window understand the TakeFocus protocol? - uint mapped :1; // keeps track of our visiblity within the asynchronous event flow + uint mapped :1; // keeps track of our visiblity within the asynchronous event flow QPixmap icon_pix; QPixmap miniicon_pix; QRect geom_restore; diff --git a/kwinbindings.cpp b/kwinbindings.cpp index 3f63a5228d..35021474c2 100644 --- a/kwinbindings.cpp +++ b/kwinbindings.cpp @@ -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"); diff --git a/stdclient.cpp b/stdclient.cpp index 8e1e3834d1..dfcfe64219 100644 --- a/stdclient.cpp +++ b/stdclient.cpp @@ -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; + } +} diff --git a/stdclient.h b/stdclient.h index 6cab253d06..99068ac362 100644 --- a/stdclient.h +++ b/stdclient.h @@ -1,7 +1,7 @@ #ifndef STDCLIENT_H #define STDCLIENT_H #include "client.h" -class QToolButton; +#include 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 diff --git a/systemclient.cpp b/systemclient.cpp index da600b237c..7a6b765d63 100644 --- a/systemclient.cpp +++ b/systemclient.cpp @@ -13,10 +13,10 @@ static unsigned char iconify_bits[] = { 0x00, 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00 }; - + static unsigned char close_bits[] = { 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00 }; - + static unsigned char maximize_bits[] = { 0x3f, 0x9f, 0xcf, 0x67, 0x33, 0x19, 0x0c, 0x06 }; @@ -25,7 +25,7 @@ static unsigned char unsticky_bits[] = { static unsigned char sticky_bits[] = { 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00}; - + static QPixmap *titlePix=0; static KPixmap *aFramePix=0; static KPixmap *iFramePix=0; @@ -137,9 +137,9 @@ SystemButton::SystemButton(QWidget *parent, const char *name, p.setPen(Qt::black); p.drawRect(0, 0, 16, 16); p.end(); - + resize(16, 16); - + QBitmap mask; mask.resize(16, 16); mask.fill(color1); @@ -173,7 +173,7 @@ void SystemButton::drawButton(QPainter *p) p->setPen(options->color(Options::ButtonFg, isDown())); p->drawPixmap(isDown() ? 5 : 4, isDown() ? 5 : 4, deco); } - + SystemClient::SystemClient( Workspace *ws, WId w, QWidget *parent, const char *name ) : Client( ws, w, parent, name, WResizeNoErase ) @@ -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); @@ -193,7 +194,7 @@ SystemClient::SystemClient( Workspace *ws, WId w, QWidget *parent, button[1]->setBitmap(sticky_bits); button[2] = new SystemButton(this, "iconify", iconify_bits); button[3] = new SystemButton(this, "maximize", maximize_bits); - + connect( button[0], SIGNAL( clicked() ), this, ( SLOT( closeWindow() ) ) ); connect( button[1], SIGNAL( clicked() ), this, ( SLOT( toggleSticky() ) ) ); connect( button[2], SIGNAL( clicked() ), this, ( SLOT( iconify() ) ) ); @@ -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 ); diff --git a/workspace.cpp b/workspace.cpp index d4b4a06b81..327fbde2c3 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -106,17 +106,18 @@ 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); grabKey(XK_Tab, ControlMask); 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 ); - - 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(); + 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_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::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::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::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::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::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::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 ); @@ -1429,6 +1452,9 @@ void Workspace::createKeybindings(){ keys->connectItem( "Switch to desktop 6", this, SLOT( slotSwitchDesktop6() )); 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(); +} diff --git a/workspace.h b/workspace.h index 97733ed7dd..3c261e09d0 100644 --- a/workspace.h +++ b/workspace.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -73,7 +74,6 @@ public: void clientHidden( Client* ); int currentDesktop() const; - void setCurrentDesktop( int new_desktop ); int numberOfDesktops() const; void setNumberOfDesktops( int n ); @@ -90,8 +90,8 @@ public: Client* topClientOnDesktop( int fromLayer = 0, int toLayer = 0) const; - void showPopup( const QPoint&, Client* ); - + QPopupMenu* clientPopup( Client* ); + void setDesktopClient( Client* ); void makeFullScreen( Client* ); @@ -99,6 +99,7 @@ public: bool iconifyMeansWithdraw( Client* ); public slots: + void setCurrentDesktop( int new_desktop ); // keybindings void slotSwitchDesktop1(); void slotSwitchDesktop2(); @@ -108,7 +109,17 @@ public slots: void slotSwitchDesktop6(); 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 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 @@ -164,7 +178,7 @@ private: }; QValueList cci; - // -cascading + // -cascading }; inline WId Workspace::rootWin() const