With windows that have are listed for the focus stealing prevention

workaround, don't make their user timestamp newer than the active window's
one (unless a real user activity takes place in them).
As they are belong to the active application and just fail to say so,
this makes sure they won't prevent that application from getting focus
by having newer timestamp. E.g. Alt+F2, typing URL, kio_uiserver dialog
shows (has workaround), SSL certificate dialog shows (shown by kdesktop),
and it wouldn't get focus, because kio_uiserver's timestamp would be later.

svn path=/trunk/kdebase/kwin/; revision=298357
This commit is contained in:
Luboš Luňák 2004-03-24 19:05:49 +00:00
parent 1c302cb000
commit 854e9cc05a
7 changed files with 44 additions and 8 deletions

View file

@ -278,7 +278,15 @@ void Workspace::activateClient( Client* c, bool force )
if( options->focusPolicyIsReasonable()) if( options->focusPolicyIsReasonable())
requestFocus( c, force ); requestFocus( c, force );
c->updateUserTime(); // Don't update user time for clients that have focus stealing workaround.
// As they usually belong to the current active window but fail to provide
// this information, updating their user time would make the user time
// of the currently active window old, and reject further activation for it.
// E.g. typing URL in minicli which will show kio_uiserver dialog (with workaround),
// and then kdesktop shows dialog about SSL certificate.
// This needs also avoiding user creation time in Client::readUserTimeMapTimestamp().
if( !c->ignoreFocusStealing())
c->updateUserTime();
} }
/*! /*!
@ -445,7 +453,7 @@ bool Workspace::allowClientActivation( const Client* c, Time time, bool focus_in
kdDebug( 1212 ) << "Activation: No client active, allowing" << endl; kdDebug( 1212 ) << "Activation: No client active, allowing" << endl;
return true; // no active client -> always allow return true; // no active client -> always allow
} }
if( options->ignoreFocusStealingClasses.contains(QString::fromLatin1(c->resourceClass()))) if( c->ignoreFocusStealing())
return true; return true;
if( time == 0 ) // explicitly asked not to get focus if( time == 0 ) // explicitly asked not to get focus
return false; return false;
@ -472,7 +480,7 @@ bool Workspace::allowClientActivation( const Client* c, Time time, bool focus_in
} }
// options->focusStealingPreventionLevel == 2 // normal // options->focusStealingPreventionLevel == 2 // normal
Time user_time = ac->userTime(); Time user_time = ac->userTime();
kdDebug( 1212 ) << "Activation, compared:" << time << ":" << user_time kdDebug( 1212 ) << "Activation, compared:" << c << ":" << time << ":" << user_time
<< ":" << ( timestampCompare( time, user_time ) >= 0 ) << endl; << ":" << ( timestampCompare( time, user_time ) >= 0 ) << endl;
return timestampCompare( time, user_time ) >= 0; // time >= user_time return timestampCompare( time, user_time ) >= 0; // time >= user_time
} }
@ -498,7 +506,7 @@ bool Workspace::allowFullClientRaising( const Client* c )
kdDebug( 1212 ) << "Raising: No client active, allowing" << endl; kdDebug( 1212 ) << "Raising: No client active, allowing" << endl;
return true; // no active client -> always allow return true; // no active client -> always allow
} }
if( options->ignoreFocusStealingClasses.contains(QString::fromLatin1(c->resourceClass()))) if( c->ignoreFocusStealing())
return true; return true;
// TODO window urgency -> return true? // TODO window urgency -> return true?
if( Client::belongToSameApplication( c, ac, true )) if( Client::belongToSameApplication( c, ac, true ))
@ -686,9 +694,12 @@ Time Client::readUserTimeMapTimestamp( const KStartupInfoData* asn_data,
// this check will be done in Workspace::allowClientActiovationTimestamp(). // this check will be done in Workspace::allowClientActiovationTimestamp().
if( session && !session->fake ) if( session && !session->fake )
return -1U; return -1U;
time = readUserCreationTime(); if( ignoreFocusStealing() && act != NULL )
time = act->userTime();
else
time = readUserCreationTime();
} }
kdDebug( 1212 ) << "User timestamp, final:" << time << endl; kdDebug( 1212 ) << "User timestamp, final:" << this << ":" << time << endl;
return time; return time;
} }

View file

@ -124,6 +124,7 @@ Client::Client( Workspace *ws )
user_noborder = false; user_noborder = false;
not_obscured = false; not_obscured = false;
urgency = false; urgency = false;
ignore_focus_stealing = false;
Pdeletewindow = 0; Pdeletewindow = 0;
Ptakefocus = 0; Ptakefocus = 0;

View file

@ -259,6 +259,7 @@ class Client : public QObject, public KDecorationDefines
void updateUserTime( Time time = CurrentTime ); void updateUserTime( Time time = CurrentTime );
Time userTime() const; Time userTime() const;
bool hasUserTimeSupport() const; bool hasUserTimeSupport() const;
bool ignoreFocusStealing() const;
// does 'delete c;' // does 'delete c;'
static void deleteClient( Client* c, allowed_t ); static void deleteClient( Client* c, allowed_t );
@ -445,6 +446,7 @@ private slots:
uint user_noborder : 1; uint user_noborder : 1;
uint not_obscured : 1; uint not_obscured : 1;
uint urgency : 1; // XWMHints, UrgencyHint uint urgency : 1; // XWMHints, UrgencyHint
uint ignore_focus_stealing : 1; // don't apply focus stealing prevention to this client
void getWMHints(); void getWMHints();
void readIcons(); void readIcons();
void getWindowProtocols(); void getWindowProtocols();
@ -484,6 +486,7 @@ private slots:
int border_left, border_right, border_top, border_bottom; int border_left, border_right, border_top, border_bottom;
QRegion _mask; QRegion _mask;
friend struct FetchNameInternalPredicate; friend struct FetchNameInternalPredicate;
friend struct CheckIgnoreFocusStealingProcedure;
void show() { assert( false ); } // SELI remove after Client is no longer QWidget void show() { assert( false ); } // SELI remove after Client is no longer QWidget
void hide() { assert( false ); } void hide() { assert( false ); }
}; };
@ -823,6 +826,13 @@ inline bool Client::hasUserTimeSupport() const
{ {
return info->userTime() != -1U; return info->userTime() != -1U;
} }
inline bool Client::ignoreFocusStealing() const
{
return ignore_focus_stealing;
}
KWIN_PROCEDURE( CheckIgnoreFocusStealingProcedure, cl->ignore_focus_stealing = options->checkIgnoreFocusStealing( cl ));
inline Window Client::moveResizeGrabWindow() const inline Window Client::moveResizeGrabWindow() const
{ {

View file

@ -103,6 +103,7 @@ bool Client::manage( Window w, bool isMapped )
XFree( classHint.res_name ); XFree( classHint.res_name );
XFree( classHint.res_class ); XFree( classHint.res_class );
} }
ignore_focus_stealing = options->checkIgnoreFocusStealing( this );
detectNoBorder(); detectNoBorder();
fetchName(); fetchName();

View file

@ -10,6 +10,7 @@ License. See the file "COPYING" for the exact licensing terms.
******************************************************************/ ******************************************************************/
#include "options.h" #include "options.h"
#include <qpalette.h> #include <qpalette.h>
#include <qpixmap.h> #include <qpixmap.h>
#include <kapplication.h> #include <kapplication.h>
@ -18,6 +19,8 @@ License. See the file "COPYING" for the exact licensing terms.
#include <kglobalsettings.h> #include <kglobalsettings.h>
#include <qtooltip.h> #include <qtooltip.h>
#include "client.h"
namespace KWinInternal namespace KWinInternal
{ {
@ -242,4 +245,9 @@ int Options::electricBorderDelay()
return electric_border_delay; return electric_border_delay;
} }
bool Options::checkIgnoreFocusStealing( const Client* c )
{
return ignoreFocusStealingClasses.contains(QString::fromLatin1(c->resourceClass()));
}
} // namespace } // namespace

View file

@ -21,6 +21,8 @@ License. See the file "COPYING" for the exact licensing terms.
namespace KWinInternal namespace KWinInternal
{ {
class Client;
class Options : public KDecorationOptions class Options : public KDecorationOptions
{ {
public: public:
@ -184,8 +186,8 @@ class Options : public KDecorationOptions
* List of window classes to ignore PPosition size hint * List of window classes to ignore PPosition size hint
*/ */
QStringList ignorePositionClasses; QStringList ignorePositionClasses;
// List of window classes for which not to use focus stealing prevention
QStringList ignoreFocusStealingClasses; bool checkIgnoreFocusStealing( const Client* c );
WindowOperation operationTitlebarDblClick() { return OpTitlebarDblClick; } WindowOperation operationTitlebarDblClick() { return OpTitlebarDblClick; }
@ -265,6 +267,8 @@ class Options : public KDecorationOptions
bool show_geometry_tip; bool show_geometry_tip;
bool topmenus; bool topmenus;
bool desktop_topmenu; bool desktop_topmenu;
// List of window classes for which not to use focus stealing prevention
QStringList ignoreFocusStealingClasses;
}; };
extern Options* options; extern Options* options;

View file

@ -734,6 +734,7 @@ void Workspace::slotReconfigure()
tab_box->reconfigure(); tab_box->reconfigure();
popupinfo->reconfigure(); popupinfo->reconfigure();
readShortcuts(); readShortcuts();
forEachClient( CheckIgnoreFocusStealingProcedure());
if( mgr->reset( changed )) if( mgr->reset( changed ))
{ // decorations need to be recreated { // decorations need to be recreated