diff --git a/activation.cpp b/activation.cpp index bb829c321a..067ed9ee7f 100644 --- a/activation.cpp +++ b/activation.cpp @@ -278,7 +278,15 @@ void Workspace::activateClient( Client* c, bool force ) if( options->focusPolicyIsReasonable()) 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; return true; // no active client -> always allow } - if( options->ignoreFocusStealingClasses.contains(QString::fromLatin1(c->resourceClass()))) + if( c->ignoreFocusStealing()) return true; if( time == 0 ) // explicitly asked not to get focus return false; @@ -472,7 +480,7 @@ bool Workspace::allowClientActivation( const Client* c, Time time, bool focus_in } // options->focusStealingPreventionLevel == 2 // normal 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; 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; return true; // no active client -> always allow } - if( options->ignoreFocusStealingClasses.contains(QString::fromLatin1(c->resourceClass()))) + if( c->ignoreFocusStealing()) return true; // TODO window urgency -> return 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(). if( session && !session->fake ) 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; } diff --git a/client.cpp b/client.cpp index 57dfd0bb67..ecc73c5b8a 100644 --- a/client.cpp +++ b/client.cpp @@ -124,6 +124,7 @@ Client::Client( Workspace *ws ) user_noborder = false; not_obscured = false; urgency = false; + ignore_focus_stealing = false; Pdeletewindow = 0; Ptakefocus = 0; diff --git a/client.h b/client.h index d53f82d67c..cab6fe9072 100644 --- a/client.h +++ b/client.h @@ -259,6 +259,7 @@ class Client : public QObject, public KDecorationDefines void updateUserTime( Time time = CurrentTime ); Time userTime() const; bool hasUserTimeSupport() const; + bool ignoreFocusStealing() const; // does 'delete c;' static void deleteClient( Client* c, allowed_t ); @@ -445,6 +446,7 @@ private slots: uint user_noborder : 1; uint not_obscured : 1; uint urgency : 1; // XWMHints, UrgencyHint + uint ignore_focus_stealing : 1; // don't apply focus stealing prevention to this client void getWMHints(); void readIcons(); void getWindowProtocols(); @@ -484,6 +486,7 @@ private slots: int border_left, border_right, border_top, border_bottom; QRegion _mask; friend struct FetchNameInternalPredicate; + friend struct CheckIgnoreFocusStealingProcedure; void show() { assert( false ); } // SELI remove after Client is no longer QWidget void hide() { assert( false ); } }; @@ -823,6 +826,13 @@ inline bool Client::hasUserTimeSupport() const { 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 { diff --git a/manage.cpp b/manage.cpp index 5220f8139a..a978932ce7 100644 --- a/manage.cpp +++ b/manage.cpp @@ -103,6 +103,7 @@ bool Client::manage( Window w, bool isMapped ) XFree( classHint.res_name ); XFree( classHint.res_class ); } + ignore_focus_stealing = options->checkIgnoreFocusStealing( this ); detectNoBorder(); fetchName(); diff --git a/options.cpp b/options.cpp index e87124d83b..129daef6a6 100644 --- a/options.cpp +++ b/options.cpp @@ -10,6 +10,7 @@ License. See the file "COPYING" for the exact licensing terms. ******************************************************************/ #include "options.h" + #include #include #include @@ -18,6 +19,8 @@ License. See the file "COPYING" for the exact licensing terms. #include #include +#include "client.h" + namespace KWinInternal { @@ -242,4 +245,9 @@ int Options::electricBorderDelay() return electric_border_delay; } +bool Options::checkIgnoreFocusStealing( const Client* c ) + { + return ignoreFocusStealingClasses.contains(QString::fromLatin1(c->resourceClass())); + } + } // namespace diff --git a/options.h b/options.h index 5cd88a3f61..4201128d65 100644 --- a/options.h +++ b/options.h @@ -21,6 +21,8 @@ License. See the file "COPYING" for the exact licensing terms. namespace KWinInternal { +class Client; + class Options : public KDecorationOptions { public: @@ -184,8 +186,8 @@ class Options : public KDecorationOptions * List of window classes to ignore PPosition size hint */ 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; } @@ -265,6 +267,8 @@ class Options : public KDecorationOptions bool show_geometry_tip; bool topmenus; bool desktop_topmenu; + // List of window classes for which not to use focus stealing prevention + QStringList ignoreFocusStealingClasses; }; extern Options* options; diff --git a/workspace.cpp b/workspace.cpp index 65221c8b9c..8b72032b76 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -734,6 +734,7 @@ void Workspace::slotReconfigure() tab_box->reconfigure(); popupinfo->reconfigure(); readShortcuts(); + forEachClient( CheckIgnoreFocusStealingProcedure()); if( mgr->reset( changed )) { // decorations need to be recreated