No delayed deleting of decorations. They'll have to check themselves

instead, using KDecorationFactory::exists(). Fixes #66205, and it wasn't
really that good idea anyway.

svn path=/trunk/kdebase/kwin/; revision=260988
This commit is contained in:
Luboš Luňák 2003-10-22 08:26:09 +00:00
parent 52cb814d32
commit 43c71a8c72
11 changed files with 61 additions and 26 deletions

View file

@ -225,7 +225,7 @@ void Client::destroyClient()
deleteClient( this, Allowed );
}
void Client::updateDecoration( bool check_workspace_pos, bool force, bool delay_delete )
void Client::updateDecoration( bool check_workspace_pos, bool force )
{
if( !force && (( decoration == NULL && noBorder())
|| ( decoration != NULL && !noBorder())))
@ -233,7 +233,7 @@ void Client::updateDecoration( bool check_workspace_pos, bool force, bool delay_
bool do_show = false;
++block_geometry;
if( force )
destroyDecoration( delay_delete );
destroyDecoration();
if( !noBorder())
{
decoration = workspace()->createDecoration( bridge );
@ -255,7 +255,7 @@ void Client::updateDecoration( bool check_workspace_pos, bool force, bool delay_
do_show = true;
}
else
destroyDecoration( delay_delete );
destroyDecoration();
if( check_workspace_pos )
checkWorkspacePosition();
--block_geometry;
@ -265,21 +265,14 @@ void Client::updateDecoration( bool check_workspace_pos, bool force, bool delay_
updateFrameStrut();
}
void Client::destroyDecoration( bool delay_delete )
void Client::destroyDecoration()
{
if( decoration != NULL )
{
// When selecting the noborder operation from the popup menu after clicking on the menu
// button, the decoration should be deleted. But after closing the popup, the flow
// of control is still in the decoration, and the decorations usually do
// "button->setDown( false )". Therefore, delay the actual deleting.
if( delay_delete )
decoration->deleteLater();
else
delete decoration;
delete decoration;
decoration = NULL;
QPoint grav = calculateGravitation( true );
border_left = border_right = border_top = border_bottom = 0;
decoration = NULL;
setMask( QRegion()); // reset shape mask
int save_workarea_diff_x = workarea_diff_x;
int save_workarea_diff_y = workarea_diff_y;
@ -395,7 +388,7 @@ void Client::setUserNoBorder( bool set )
if( user_noborder == set )
return;
user_noborder = set;
updateDecoration( true, false, true ); // delayed deletion of decoration
updateDecoration( true, false );
}
bool Client::grabInput()
@ -948,10 +941,7 @@ void Client::killWindow()
killProcess( false );
// always kill this client at the server
XKillClient(qt_xdisplay(), window() );
// needs to be delayed, because this may be called from the client
// popup menu, and there may be possibly code still touching
// this instance after returning from killWindow()
QTimer::singleShot( 0, this, SLOT( destroyClient()));
destroyClient();
}
// send a ping to the window using _NET_WM_PING if possible

View file

@ -180,7 +180,7 @@ class Client : public QObject, public KDecorationDefines
void setMask( const QRegion& r, int mode = X::Unsorted );
void updateDecoration( bool check_workspace_pos, bool force = false, bool delay_delete = false );
void updateDecoration( bool check_workspace_pos, bool force = false );
void checkBorderSizes();
// shape extensions
@ -349,7 +349,7 @@ class Client : public QObject, public KDecorationDefines
void embedClient( Window w );
void detectNoBorder();
void destroyDecoration( bool delay_delete = false );
void destroyDecoration();
void updateFrameStrut();
void rawShow(); // just shows it

View file

@ -757,7 +757,10 @@ void B2Client::menuButtonPressed()
{
QPoint menupoint = button[BtnMenu]->mapToGlobal(
button[BtnMenu]->rect().bottomLeft());
KDecorationFactory* f = factory();
showWindowMenu(menupoint);
if( !f->exists( this )) // 'this' was destroyed
return;
button[BtnMenu]->setDown(false);
}

View file

@ -1277,7 +1277,10 @@ void KDEDefaultClient::menuButtonPressed()
QPoint menupoint ( button[BtnMenu]->rect().bottomLeft().x()-1,
button[BtnMenu]->rect().bottomLeft().y()+2 );
KDecorationFactory* f = factory();
showWindowMenu( button[BtnMenu]->mapToGlobal( menupoint ));
if( !f->exists( this )) // 'this' was destroyed
return;
button[BtnMenu]->setDown(false);
}

View file

@ -1314,7 +1314,10 @@ void KeramikClient::menuButtonPressed()
{
QPoint menuPoint ( button[MenuButton]->rect().bottomLeft().x() - 6,
button[MenuButton]->rect().bottomLeft().y() + 3 );
KDecorationFactory* f = factory();
showWindowMenu( button[MenuButton]->mapToGlobal( menuPoint ));
if( !f->exists( this )) // 'this' was destroyed
return;
button[MenuButton]->setDown(false);
}

View file

@ -971,7 +971,10 @@ void QuartzClient::menuButtonPressed()
QPoint menupoint ( button[BtnMenu]->rect().bottomLeft().x()-1,
button[BtnMenu]->rect().bottomLeft().y()+2 );
menupoint = button[BtnMenu]->mapToGlobal( menupoint );
showWindowMenu(menupoint);
KDecorationFactory* f = factory();
showWindowMenu(menupoint);
if( !f->exists( this )) // 'this' was destroyed
return;
button[BtnMenu]->setDown(false);
}

View file

@ -819,7 +819,10 @@ void RedmondDeco::menuButtonPressed()
if (!dbl) {
QPoint menupoint(button[BtnMenu]->rect().bottomLeft().x()-3,
button[BtnMenu]->rect().bottomLeft().y()+4);
KDecorationFactory* f = factory();
showWindowMenu(button[BtnMenu]->mapToGlobal(menupoint));
if( !f->exists( this )) // 'this' was destroyed
return;
button[BtnMenu]->setDown(false);
} else {
closeWindow();

View file

@ -653,8 +653,7 @@ void Client::getWmNormalHints()
long msize;
if (XGetWMNormalHints(qt_xdisplay(), window(), &xSizeHint, &msize) == 0 )
xSizeHint.flags = 0;
// set defined values for basesize, minsize, maxsize, aspect and resizeinc,
// even if they're not in flags
// set defined values for the fields, even if they're not in flags
// basesize is just like minsize, except for minsize is not used for aspect ratios
// keep basesize only for aspect ratios, for size increments, keep the base
@ -696,7 +695,7 @@ void Client::getWmNormalHints()
xSizeHint.max_aspect.x = INT_MAX;
xSizeHint.max_aspect.y = 1;
}
if( !xSizeHint.flags & PWinGravity )
if( ! ( xSizeHint.flags & PWinGravity ))
xSizeHint.win_gravity = NorthWestGravity;
if( isManaged())
{ // update to match restrictions
@ -1288,7 +1287,7 @@ void Client::setFullScreen( bool set, bool user )
StackingUpdatesBlocker blocker( workspace());
workspace()->updateClientLayer( this ); // active fullscreens get different layer
info->setState( isFullScreen() ? NET::FullScreen : 0, NET::FullScreen );
updateDecoration( false, false, true ); // delayed deletion of decoration
updateDecoration( false, false );
if( isFullScreen())
setGeometry( workspace()->clientArea( MaximizeFullArea, this ));
else

View file

@ -366,9 +366,26 @@ class KDecoration
*/
QString caption() const;
/**
* This function invokes the window operations menu.
* This function invokes the window operations menu. IMPORTANT: As a result
* of this function, the decoration object that called it may be destroyed
* after the function returns. This means that the decoration object must
* either return immediately after calling showWindowMenu(), or it must
* use KDecorationFactory::exists() to check it's still valid. For example,
* the code handling clicks on the menu button should look similarly like this:
*
* \code
* KDecorationFactory* f = factory(); // needs to be saved before
* showWindowMenu( button[MenuButton]->mapToGlobal( menuPoint ));
* if( !f->exists( this )) // destroyed, return immediately
* return;
* button[MenuButton]->setDown(false);
* \endcode
*/
void showWindowMenu( QPoint pos );
/**
* This function performs the given window operation. This function may destroy
* the current decoration object, just like showWindowMenu().
*/
void performWindowOperation( WindowOperation op );
/**
* If the decoration is non-rectangular, this function needs to be called
@ -571,6 +588,8 @@ class KDecoration
* This function can be called by the decoration to request
* closing of the decorated window. Note that closing the window
* also involves destroying the decoration.
* IMPORTANT: This function may destroy the current decoration object,
* just like showWindowMenu().
*/
void closeWindow();
/**

View file

@ -52,6 +52,11 @@ QValueList< KDecorationDefines::BorderSize > KDecorationFactory::borderSizes() c
return QValueList< BorderSize >() << BorderNormal;
}
bool KDecorationFactory::exists( const KDecoration* deco ) const
{
return _decorations.contains( const_cast< KDecoration* >( deco ));
}
void KDecorationFactory::addDecoration( KDecoration* deco )
{
_decorations.append( deco );

View file

@ -77,6 +77,13 @@ class KDecorationFactory
* configuration settings for the decoration.
*/
const KDecorationOptions* options(); // convenience
/**
* Returns true if the given decoration object still exists. This is necessary
* e.g. when calling KDecoration::showWindowMenu(), which may cause the decoration
* to be destroyed. Note that this function is reliable only if called immediately
* after such actions.
*/
bool exists( const KDecoration* deco ) const;
/**
* @internal
*/