From 3b57952b03573c38ab2eed87b88d41ade4e2ab4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Wed, 28 Aug 2002 15:17:31 +0000 Subject: [PATCH] Take care of #46042. [...resisted to say here something about Motif >;> ] svn path=/trunk/kdebase/kwin/; revision=174310 --- client.cpp | 45 +++++++++++++++++++++++--- client.h | 8 ++++- clients/b2/b2client.cpp | 2 +- clients/default/kdedefault.cpp | 2 +- clients/icewm/icewm.cpp | 2 +- clients/keramik/keramik.cpp | 2 +- clients/kstep/nextclient.cpp | 2 ++ clients/kwmtheme/kwmthemeclient.cpp | 2 +- clients/laptop/laptopclient.cpp | 2 ++ clients/modernsystem/modernsys.cpp | 2 +- clients/quartz/quartz.cpp | 2 +- clients/redmond/redmond.cpp | 2 ++ clients/riscos/Manager.cpp | 7 ++-- clients/system/systemclient.cpp | 6 +++- clients/web/Web.cpp | 2 +- workspace.cpp | 50 ++++++++++++++++++++++------- workspace.h | 19 +++++++++++ 17 files changed, 130 insertions(+), 27 deletions(-) diff --git a/client.cpp b/client.cpp index fe1eba12ac..e14364a9ab 100644 --- a/client.cpp +++ b/client.cpp @@ -518,6 +518,10 @@ Client::Client( Workspace *ws, WId w, QWidget *parent, const char *name, WFlags stays_on_top = FALSE; is_shape = FALSE; may_move = TRUE; + may_resize = TRUE; + may_minimize = TRUE; + may_maximize = TRUE; + may_close = TRUE; is_fullscreen = FALSE; skip_taskbar = FALSE; @@ -535,6 +539,15 @@ Client::Client( Workspace *ws, WId w, QWidget *parent, const char *name, WFlags cmap = None; + bool mresize, mmove, mminimize, mmaximize, mclose; + if( Motif::funcFlags( win, mresize, mmove, mminimize, mmaximize, mclose )) { + may_resize = mresize; + may_move = mmove; + may_minimize = mminimize; + may_maximize = mmaximize; + may_close = mclose; + } + Window ww; if ( !XGetTransientForHint( qt_xdisplay(), (Window) win, &ww ) ) transient_for = None; @@ -641,12 +654,20 @@ bool Client::manage( bool isMapped, bool doNotShow, bool isInitial ) if ( !stays_on_top ) is_fullscreen = TRUE; may_move = FALSE; // don't let fullscreen windows be moved around + may_resize = FALSE; + may_minimize = FALSE; + may_maximize = FALSE; + may_close = FALSE; } if ( isDesktop() ) { // desktops are treated slightly special geom = workspace()->geometry(); may_move = FALSE; + may_resize = FALSE; + may_minimize = FALSE; + may_maximize = FALSE; + may_close = FALSE; isMapped = TRUE; } @@ -1462,7 +1483,7 @@ QSize Client::sizeForWindowSize( const QSize& wsize, bool ignore_height) const */ bool Client::isResizable() const { - if ( !isMovable() ) + if ( !isMovable() || !may_resize ) return FALSE; if ( ( xSizeHint.flags & PMaxSize) == 0 || (xSizeHint.flags & PMinSize ) == 0 ) @@ -1478,7 +1499,7 @@ bool Client::isMaximizable() const { if ( isMaximized() ) return TRUE; - return isResizable() && !isTool(); + return isResizable() && !isTool() && may_maximize; } /* @@ -1487,7 +1508,16 @@ bool Client::isMaximizable() const bool Client::isMinimizable() const { return ( !isTransient() || !workspace()->findClient( transientFor() ) ) - && wantsTabFocus(); + && wantsTabFocus() && may_minimize; +} + +/* + Returns whether the window may be closed (have a close button) + */ +bool Client::isCloseable() const +{ + return may_close && !isDesktop() && !isDock() && !isTopMenu() && !isToolbar() + && windowType() != NET::Override; } @@ -1909,6 +1939,8 @@ void Client::iconify() */ void Client::closeWindow() { + if( !isCloseable()) + return; Events::raise( Events::Close ); if ( Pdeletewindow ){ sendClientMessage( win, atoms->wm_protocols, atoms->wm_delete_window); @@ -2987,11 +3019,16 @@ bool Client::isTopMenu() const } -bool Client::isTool() const +bool Client::isToolbar() const { return windowType() == NET::Tool; } +bool Client::isTool() const +{ + return isToolbar(); +} + /*! diff --git a/client.h b/client.h index 7beb2dbe24..c9d350ed80 100644 --- a/client.h +++ b/client.h @@ -154,10 +154,12 @@ public: bool isMovable() const; bool isDesktop() const; bool isDock() const; - bool isTool() const; + bool isTool() const; // KDE4 remove me + bool isToolbar() const; bool isTopMenu() const; bool isResizable() const; + bool isCloseable() const; // may have a close button void takeFocus( bool force = FALSE ); @@ -323,6 +325,10 @@ private: uint input :1; // does the window want input in its wm_hints uint store_settings : 1; uint skip_pager : 1; + uint may_resize : 1; + uint may_maximize : 1; + uint may_minimize : 1; + uint may_close : 1; void getWMHints(); void getWindowProtocols(); QPixmap icon_pix; diff --git a/clients/b2/b2client.cpp b/clients/b2/b2client.cpp index b39dcff383..22cbe676b9 100644 --- a/clients/b2/b2client.cpp +++ b/clients/b2/b2client.cpp @@ -495,7 +495,7 @@ void B2Client::addButtons(const QString& s, const QString tips[], } break; case 'X': // Close button - if (!button[BtnClose]) { + if (isCloseable() && !button[BtnClose]) { button[BtnClose]= new B2Button(this, tb, tips[BtnClose]); button[BtnClose]->setPixmaps(P_CLOSE); connect(button[BtnClose], SIGNAL(clicked()), diff --git a/clients/default/kdedefault.cpp b/clients/default/kdedefault.cpp index 2bfdc4080b..0333273ec3 100644 --- a/clients/default/kdedefault.cpp +++ b/clients/default/kdedefault.cpp @@ -723,7 +723,7 @@ void KDEDefaultClient::addClientButtons( const QString& s, bool isLeft ) // Close button case 'X': - if (!button[BtnClose]) + if (!button[BtnClose] && isCloseable()) { button[BtnClose] = new KDEDefaultButton(this, "close", largeButtons, isLeft, true, close_bits, diff --git a/clients/icewm/icewm.cpp b/clients/icewm/icewm.cpp index 526f2b0d5e..6c79ca4ea9 100644 --- a/clients/icewm/icewm.cpp +++ b/clients/icewm/icewm.cpp @@ -815,7 +815,7 @@ void IceWMClient::addClientButtons( const QString& s ) break; case 'x': - if ( validPixmaps(closePix) && !button[BtnClose] ) + if ( validPixmaps(closePix) && !button[BtnClose] && isCloseable()) { button[BtnClose] = new IceWMButton(this, "close", &closePix, false, i18n("Close")); diff --git a/clients/keramik/keramik.cpp b/clients/keramik/keramik.cpp index d5e70a0643..3d4a27e742 100644 --- a/clients/keramik/keramik.cpp +++ b/clients/keramik/keramik.cpp @@ -866,7 +866,7 @@ void KeramikClient::addButtons( QBoxLayout *layout, const QString &s ) // Close button case 'X' : - if ( !button[CloseButton] ) { + if ( !button[CloseButton] && isCloseable() ) { button[CloseButton] = new KeramikButton( this, "close", CloseButton, i18n("Close") ); connect( button[CloseButton], SIGNAL( clicked() ), SLOT( closeWindow() ) ); layout->addWidget( button[CloseButton] ); diff --git a/clients/kstep/nextclient.cpp b/clients/kstep/nextclient.cpp index 5de3a52c2d..f2b9508405 100644 --- a/clients/kstep/nextclient.cpp +++ b/clients/kstep/nextclient.cpp @@ -392,12 +392,14 @@ void NextClient::addButtons(QBoxLayout* titleLayout, const QString& spec) break; case 'X': + if( isCloseable()) { button[CLOSE_IDX] = new NextButton(this, "close", close_bits, 10, 10, i18n("Close")); titleLayout->addWidget( button[CLOSE_IDX] ); connect( button[CLOSE_IDX], SIGNAL(clicked()), this, SLOT(closeWindow()) ); + } break; case '_': diff --git a/clients/kwmtheme/kwmthemeclient.cpp b/clients/kwmtheme/kwmthemeclient.cpp index 6f148ecd91..62a152f8b0 100644 --- a/clients/kwmtheme/kwmthemeclient.cpp +++ b/clients/kwmtheme/kwmthemeclient.cpp @@ -317,7 +317,7 @@ KWMThemeClient::KWMThemeClient( Workspace *ws, WId w, QWidget *parent, hb->addWidget(maxBtn); maxBtn->setFixedSize(20, 20); } - else if(val == "Close"){ + else if((val == "Close") && isCloseable()){ btn = new MyButton(this, "close", i18n("Close")); btn->setPixmap(*closePix); connect(btn, SIGNAL(clicked()), this, SLOT(closeWindow())); diff --git a/clients/laptop/laptopclient.cpp b/clients/laptop/laptopclient.cpp index 7fbb6e9c21..a1d9fe1c51 100644 --- a/clients/laptop/laptopclient.cpp +++ b/clients/laptop/laptopclient.cpp @@ -370,6 +370,8 @@ LaptopClient::LaptopClient( Workspace *ws, WId w, QWidget *parent, button[BtnIconify]->hide(); if ( !isMaximizable() ) button[BtnMax]->hide(); + if ( !isCloseable() ) + button[BtnClose]->hide(); hiddenItems = false; bufferDirty = true; diff --git a/clients/modernsystem/modernsys.cpp b/clients/modernsystem/modernsys.cpp index 51a798ccac..3f57b3e2f6 100644 --- a/clients/modernsystem/modernsys.cpp +++ b/clients/modernsystem/modernsys.cpp @@ -336,7 +336,7 @@ ModernSys::ModernSys( Workspace *ws, WId w, QWidget *parent, hb->addSpacing(int(c - '0')); continue; } - else if (c == 'X') { + else if (c == 'X' && isCloseable()) { hb->addWidget(button[BtnClose]); button[BtnClose]->show(); } diff --git a/clients/quartz/quartz.cpp b/clients/quartz/quartz.cpp index 0cc9b2d5a7..9cd8637ae0 100644 --- a/clients/quartz/quartz.cpp +++ b/clients/quartz/quartz.cpp @@ -533,7 +533,7 @@ void QuartzClient::addClientButtons( const QString& s, bool isLeft ) // Close button case 'X': - if (!button[BtnClose]) + if (!button[BtnClose] && isCloseable()) { button[BtnClose] = new QuartzButton(this, "close", largeButtons, isLeft, true, close_bits, i18n("Close")); diff --git a/clients/redmond/redmond.cpp b/clients/redmond/redmond.cpp index 838985b29a..bdc6b54f68 100644 --- a/clients/redmond/redmond.cpp +++ b/clients/redmond/redmond.cpp @@ -445,6 +445,8 @@ GalliumClient::GalliumClient( Workspace *ws, WId w, QWidget *parent, button[BtnIconify]->hide(); if ( !isMaximizable() ) button[BtnMax]->hide(); + if ( !isCloseable() ) + button[BtnClose]->hide(); hiddenItems = false; diff --git a/clients/riscos/Manager.cpp b/clients/riscos/Manager.cpp index 1a9c562e04..9c0592e67f 100644 --- a/clients/riscos/Manager.cpp +++ b/clients/riscos/Manager.cpp @@ -701,8 +701,11 @@ Manager::createButton(int type, QWidget * parent) break; case Button::Close: - - b = new CloseButton(parent); + + if (isCloseable()) + { + b = new CloseButton(parent); + } break; diff --git a/clients/system/systemclient.cpp b/clients/system/systemclient.cpp index 807ad21074..e2c396f7c5 100644 --- a/clients/system/systemclient.cpp +++ b/clients/system/systemclient.cpp @@ -337,7 +337,11 @@ SystemClient::SystemClient( Workspace *ws, WId w, QWidget *parent, hb->setResizeMode(QLayout::FreeResize); g->addLayout( hb, 0, 1 ); hb->addSpacing(3); - hb->addWidget( button[0]); + if (isCloseable()) { + hb->addWidget( button[0]); + } else + button[0]->hide(); + titlebar = new QSpacerItem(10, 14, QSizePolicy::Expanding, QSizePolicy::Minimum); hb->addSpacing(3); diff --git a/clients/web/Web.cpp b/clients/web/Web.cpp index af7292d8b6..c62ceb8ba2 100644 --- a/clients/web/Web.cpp +++ b/clients/web/Web.cpp @@ -354,7 +354,7 @@ WebClient::_createButton(const QString & s, QWidget * parent) connect(this, SIGNAL(maxChange(bool)), b, SLOT(slotMaximizeChange(bool))); } - else if ("Close" == s) + else if ("Close" == s && isCloseable()) { b = new WebButtonClose(parent); connect(b, SIGNAL(closeWindow()), this, SLOT(closeWindow())); diff --git a/workspace.cpp b/workspace.cpp index a6203f87ac..5cdf8ec7b1 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -179,13 +179,6 @@ int Shape::shapeEvent() bool Motif::noBorder( WId w ) { - struct MwmHints { - ulong flags; - ulong functions; - ulong decorations; - long input_mode; - ulong status; - }; Atom type; int format; unsigned long length, after; @@ -199,7 +192,7 @@ bool Motif::noBorder( WId w ) } bool result = FALSE; if ( hints ) { - if ( hints->flags & (1L << 1 ) ) { // // MWM_HINTS_DECORATIONS; + if ( hints->flags & MWM_HINTS_DECORATIONS ) { if ( hints->decorations == 0 ) result = TRUE; } @@ -208,8 +201,43 @@ bool Motif::noBorder( WId w ) return result; } - - +bool Motif::funcFlags( WId w, bool& resize, bool& move, bool& minimize, + bool& maximize, bool& close ) +{ + Atom type; + int format; + unsigned long length, after; + unsigned char* data; + MwmHints* hints = 0; + if ( XGetWindowProperty( qt_xdisplay(), w, atoms->motif_wm_hints, 0, 5, + FALSE, atoms->motif_wm_hints, &type, &format, + &length, &after, &data ) == Success ) { + if ( data ) + hints = (MwmHints*) data; + } + if ( hints ) { + // To quote from Metacity 'We support those MWM hints deemed non-stupid' + if ( hints->flags & MWM_HINTS_FUNCTIONS ) { + // if MWM_FUNC_ALL is set, other flags say what to turn _off_ + bool set_value = (( hints->functions & MWM_FUNC_ALL ) == 0 ); + resize = move = minimize = maximize = close = !set_value; + if( hints->functions & MWM_FUNC_RESIZE ) + resize = set_value; + if( hints->functions & MWM_FUNC_MOVE ) + move = set_value; + if( hints->functions & MWM_FUNC_MINIMIZE ) + minimize = set_value; + if( hints->functions & MWM_FUNC_MAXIMIZE ) + maximize = set_value; + if( hints->functions & MWM_FUNC_CLOSE ) + close = set_value; + XFree( data ); + return true; + } + XFree( data ); + } + return false; +} /*! Creates a new client for window \a w, depending on certain hints @@ -397,7 +425,6 @@ void Workspace::init() NET::CloseWindow | NET::DesktopNames | NET::KDESystemTrayWindows | - NET::CloseWindow | NET::WMName | NET::WMVisibleName | NET::WMDesktop | @@ -2949,6 +2976,7 @@ void Workspace::clientPopupAboutToShow() popup->setItemEnabled( Options::IconifyOp, active_client->isMinimizable() ); popup->setItemEnabled( Options::ToggleStoreSettingsOp, !active_client->isTransient() ); popup->setItemChecked( Options::ToggleStoreSettingsOp, active_client->storeSettings() ); + popup->setItemChecked( Options::CloseOp, active_client->isCloseable() ); } diff --git a/workspace.h b/workspace.h index 6c0404e30e..cc42aed0d5 100644 --- a/workspace.h +++ b/workspace.h @@ -89,6 +89,25 @@ public: class Motif { public: static bool noBorder( WId w ); + static bool funcFlags( WId w, bool& resize, bool& move, bool& minimize, + bool& maximize, bool& close ); + struct MwmHints { + ulong flags; + ulong functions; + ulong decorations; + long input_mode; + ulong status; + }; + enum { MWM_HINTS_FUNCTIONS = (1L << 0), + MWM_HINTS_DECORATIONS = (1L << 1), + + MWM_FUNC_ALL = (1L << 0), + MWM_FUNC_RESIZE = (1L << 1), + MWM_FUNC_MOVE = (1L << 2), + MWM_FUNC_MINIMIZE = (1L << 3), + MWM_FUNC_MAXIMIZE = (1L << 4), + MWM_FUNC_CLOSE = (1L << 5) + }; }; class WorkspacePrivate;