// basically the same like allowClientActivation(), this time allowing // a window to be fully raised upon its own request (XRaiseWindow), // if refused, it will be raised only on top of windows belonging // to the same application bool Workspace::allowFullClientRaising(const Client* c, Time time) { int level = c->rules()->checkFSP(options->focusStealingPreventionLevel()); if (session_saving && level <= 2) { // <= normal return true; } Client* ac = mostRecentlyActivatedClient(); if (level == 0) // none return true; if (level == 4) // extreme return false; if (ac == NULL || ac->isDesktop()) { kDebug(1212) << "Raising: No client active, allowing"; return true; // no active client -> always allow } // TODO window urgency -> return true? if (Client::belongToSameApplication(c, ac, true)) { kDebug(1212) << "Raising: Belongs to active application"; return true; } if (level == 3) // high return false; Time user_time = ac->userTime(); kDebug(1212) << "Raising, compared:" << time << ":" << user_time << ":" << (timestampCompare(time, user_time) >= 0) << endl; return timestampCompare(time, user_time) >= 0; // time >= user_time }
// focus_in -> the window got FocusIn event // ignore_desktop - call comes from _NET_ACTIVE_WINDOW message, don't refuse just because of window // is on a different desktop bool Workspace::allowClientActivation(const Client* c, Time time, bool focus_in, bool ignore_desktop) { // options->focusStealingPreventionLevel : // 0 - none - old KWin behaviour, new windows always get focus // 1 - low - focus stealing prevention is applied normally, when unsure, activation is allowed // 2 - normal - focus stealing prevention is applied normally, when unsure, activation is not allowed, // this is the default // 3 - high - new window gets focus only if it belongs to the active application, // or when no window is currently active // 4 - extreme - no window gets focus without user intervention if (time == -1U) time = c->userTime(); int level = c->rules()->checkFSP(options->focusStealingPreventionLevel()); if (session_saving && level <= 2) { // <= normal return true; } Client* ac = mostRecentlyActivatedClient(); if (focus_in) { if (should_get_focus.contains(const_cast< Client* >(c))) return true; // FocusIn was result of KWin's action // Before getting FocusIn, the active Client already // got FocusOut, and therefore got deactivated. ac = last_active_client; } if (time == 0) // explicitly asked not to get focus return false; if (level == 0) // none return true; if (level == 4) // extreme return false; if (!ignore_desktop && !c->isOnCurrentDesktop()) return false; // allow only with level == 0 if (ac == NULL || ac->isDesktop()) { kDebug(1212) << "Activation: No client active, allowing"; return true; // no active client -> always allow } // TODO window urgency -> return true? if (Client::belongToSameApplication(c, ac, true)) { kDebug(1212) << "Activation: Belongs to active application"; return true; } if (level == 3) // high return false; if (time == -1U) { // no time known kDebug(1212) << "Activation: No timestamp at all"; if (level == 1) // low return true; // no timestamp at all, don't activate - because there's also creation timestamp // done on CreateNotify, this case should happen only in case application // maps again already used window, i.e. this won't happen after app startup return false; } // level == 2 // normal Time user_time = ac->userTime(); kDebug(1212) << "Activation, compared:" << c << ":" << time << ":" << user_time << ":" << (timestampCompare(time, user_time) >= 0) << endl; return timestampCompare(time, user_time) >= 0; // time >= user_time }
void Group::startupIdChanged() { KStartupInfoId asn_id; KStartupInfoData asn_data; bool asn_valid = workspace()->checkStartupNotification(leader_wid, asn_id, asn_data); if (!asn_valid) return; if (asn_id.timestamp() != 0 && user_time != -1U && timestampCompare(asn_id.timestamp(), user_time) > 0) { user_time = asn_id.timestamp(); } else if (asn_data.timestamp() != -1U && user_time != -1U && timestampCompare(asn_data.timestamp(), user_time) > 0) { user_time = asn_data.timestamp(); } }
void Group::updateUserTime( Time time ) { // copy of Client::updateUserTime if( time == CurrentTime ) time = GET_QT_X_TIME(); if( time != -1U && ( user_time == CurrentTime || timestampCompare( time, user_time ) > 0 )) // time > user_time user_time = time; }
/*! Updates the user time (time of last action in the active window). This is called inside kwin for every action with the window that qualifies for user interaction (clicking on it, activate it externally, etc.). */ void Client::updateUserTime( Time time ) { // copied in Group::updateUserTime if( time == CurrentTime ) time = xTime(); if( time != -1U && ( user_time == CurrentTime || timestampCompare( time, user_time ) > 0 )) // time > user_time user_time = time; group()->updateUserTime( user_time ); }
Time Client::userTime() const { Time time = user_time; if( time == 0 ) // doesn't want focus after showing return 0; assert( group() != NULL ); if( time == -1U || ( group()->userTime() != -1U && timestampCompare( group()->userTime(), time ) > 0 )) time = group()->userTime(); return time; }
/*! Updates the user time (time of last action in the active window). This is called inside kwin for every action with the window that qualifies for user interaction (clicking on it, activate it externally, etc.). */ void Client::updateUserTime(Time time) { // copied in Group::updateUserTime if (time == CurrentTime) time = xTime(); if (time != -1U && (user_time == CurrentTime || timestampCompare(time, user_time) > 0)) { // time > user_time user_time = time; shade_below = NULL; // do not hover re-shade a window after it got interaction } group()->updateUserTime(user_time); }
Time Client::readUserTimeMapTimestamp( const TDEStartupInfoId* asn_id, const TDEStartupInfoData* asn_data, bool session ) const { Time time = info->userTime(); // kdDebug( 1212 ) << "User timestamp, initial:" << time << endl; // newer ASN timestamp always replaces user timestamp, unless user timestamp is 0 // helps e.g. with konqy reusing if( asn_data != NULL && time != 0 ) { // prefer timestamp from ASN id (timestamp from data is obsolete way) if( asn_id->timestamp() != 0 && ( time == -1U || timestampCompare( asn_id->timestamp(), time ) > 0 )) { time = asn_id->timestamp(); } else if( asn_data->timestamp() != -1U && ( time == -1U || timestampCompare( asn_data->timestamp(), time ) > 0 )) { time = asn_data->timestamp(); } } // kdDebug( 1212 ) << "User timestamp, ASN:" << time << endl; if( time == -1U ) { // The window doesn't have any timestamp. // If it's the first window for its application // (i.e. there's no other window from the same app), // use the _TDE_NET_WM_USER_CREATION_TIME trick. // Otherwise, refuse activation of a window // from already running application if this application // is not the active one (unless focus stealing prevention is turned off). Client* act = workspace()->mostRecentlyActivatedClient(); if( act != NULL && !belongToSameApplication( act, this, true )) { bool first_window = true; if( isTransient()) { if( act->hasTransient( this, true )) ; // is transient for currently active window, even though it's not // the same app (e.g. kcookiejar dialog) -> allow activation else if( groupTransient() && findClientInList( mainClients(), SameApplicationActiveHackPredicate( this )) == NULL ) ; // standalone transient else first_window = false; } else { if( workspace()->findClient( SameApplicationActiveHackPredicate( this ))) first_window = false; } // don't refuse if focus stealing prevention is turned off if( !first_window && rules()->checkFSP( options->focusStealingPreventionLevel ) > 0 ) { // kdDebug( 1212 ) << "User timestamp, already exists:" << 0 << endl; return 0; // refuse activation } } // Creation time would just mess things up during session startup, // as possibly many apps are started up at the same time. // If there's no active window yet, no timestamp will be needed, // as plain Workspace::allowClientActivation() will return true // in such case. And if there's already active window, // it's better not to activate the new one. // Unless it was the active window at the time // of session saving and there was no user interaction yet, // this check will be done in manage(). if( session ) return -1U; if( ignoreFocusStealing() && act != NULL ) time = act->userTime(); else time = readUserCreationTime(); } // kdDebug( 1212 ) << "User timestamp, final:" << this << ":" << time << endl; return time; }