Use a separate focus chain for each virtual desktop - this prevents onalldesktop
windows from usually getting focus after every virtual desktop switch. Thanks for most of the work go to Guido Fiala <gfiala@s.netic.de>. (#33701) svn path=/trunk/KDE/kdebase/workspace/; revision=514057
This commit is contained in:
parent
c4e72833fe
commit
3c6af0ff28
7 changed files with 115 additions and 72 deletions
|
@ -229,9 +229,7 @@ void Workspace::setActiveClient( Client* c, allowed_t )
|
|||
last_active_client = active_client;
|
||||
if ( active_client )
|
||||
{
|
||||
focus_chain.remove( c );
|
||||
if ( c->wantsTabFocus() )
|
||||
focus_chain.append( c );
|
||||
updateFocusChains( active_client, true ); // make it first in focus chain
|
||||
active_client->demandAttention( false );
|
||||
}
|
||||
pending_take_activity = NULL;
|
||||
|
@ -400,27 +398,25 @@ bool Workspace::activateNextClient( Client* c )
|
|||
}
|
||||
if( focusChangeEnabled())
|
||||
{
|
||||
if ( c != NULL && c->wantsTabFocus() && focus_chain.contains( c ) )
|
||||
{
|
||||
focus_chain.remove( c );
|
||||
focus_chain.prepend( c );
|
||||
}
|
||||
if ( options->focusPolicyIsReasonable())
|
||||
{ // search the focus_chain for a client to transfer focus to
|
||||
// if 'c' is transient, transfer focus to the first suitable mainwindow
|
||||
// if 'c' is transient, transfer focus to the first suitable mainwindow
|
||||
Client* get_focus = NULL;
|
||||
const ClientList mainwindows = ( c != NULL ? c->mainClients() : ClientList());
|
||||
for ( int i = focus_chain.size() - 1; i >= 0; --i )
|
||||
for ( int i = focus_chain[ currentDesktop() ].size() - 1;
|
||||
i >= 0;
|
||||
--i )
|
||||
{
|
||||
if( !focus_chain.at( i )->isShown( false ) || !focus_chain.at( i )->isOnCurrentDesktop())
|
||||
if( !focus_chain[ currentDesktop() ].at( i )->isShown( false )
|
||||
|| !focus_chain[ currentDesktop() ].at( i )->isOnCurrentDesktop())
|
||||
continue;
|
||||
if( mainwindows.contains( focus_chain.at( i ) ))
|
||||
if( mainwindows.contains( focus_chain[ currentDesktop() ].at( i ) ))
|
||||
{
|
||||
get_focus = focus_chain.at( i );
|
||||
get_focus = focus_chain[ currentDesktop() ].at( i );
|
||||
break;
|
||||
}
|
||||
if( get_focus == NULL )
|
||||
get_focus = focus_chain.at( i );
|
||||
get_focus = focus_chain[ currentDesktop() ].at( i );
|
||||
}
|
||||
if( get_focus == NULL )
|
||||
get_focus = findDesktop( true, currentDesktop());
|
||||
|
|
|
@ -574,6 +574,7 @@ void Client::minimize( bool avoid_animation )
|
|||
updateAllowedActions();
|
||||
workspace()->updateMinimizedOfTransients( this );
|
||||
updateWindowRules();
|
||||
workspace()->updateFocusChains( this, false ); // make it last in the focus chain
|
||||
}
|
||||
|
||||
void Client::unminimize( bool avoid_animation )
|
||||
|
@ -1132,6 +1133,7 @@ void Client::processKillerExited()
|
|||
|
||||
void Client::setSkipTaskbar( bool b, bool from_outside )
|
||||
{
|
||||
int was_wants_tab_focus = wantsTabFocus();
|
||||
if( from_outside )
|
||||
{
|
||||
b = rules()->checkSkipTaskbar( b );
|
||||
|
@ -1142,6 +1144,8 @@ void Client::setSkipTaskbar( bool b, bool from_outside )
|
|||
skip_taskbar = b;
|
||||
info->setState( b?NET::SkipTaskbar:0, NET::SkipTaskbar );
|
||||
updateWindowRules();
|
||||
if( was_wants_tab_focus != wantsTabFocus())
|
||||
workspace()->updateFocusChains( this, isActive());
|
||||
}
|
||||
|
||||
void Client::setSkipPager( bool b )
|
||||
|
@ -1183,6 +1187,7 @@ void Client::setDesktop( int desktop )
|
|||
}
|
||||
if( decoration != NULL )
|
||||
decoration->desktopChange();
|
||||
workspace()->updateFocusChains( this, true );
|
||||
updateVisibility();
|
||||
updateWindowRules();
|
||||
}
|
||||
|
|
|
@ -366,11 +366,10 @@ bool Workspace::workspaceEvent( XEvent * e )
|
|||
XMapRaised( QX11Info::display(), e->xmaprequest.window );
|
||||
return true;
|
||||
}
|
||||
if ( c )
|
||||
if( c )
|
||||
{
|
||||
c->windowEvent( e );
|
||||
if ( !c->wantsTabFocus())
|
||||
focus_chain.remove( c ); // TODO move focus_chain changes to functions
|
||||
updateFocusChains( c, true );
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
|
23
layers.cpp
23
layers.cpp
|
@ -411,16 +411,23 @@ void Workspace::restackClientUnderActive( Client* c )
|
|||
}
|
||||
}
|
||||
assert( unconstrained_stacking_order.contains( c ));
|
||||
if( c->wantsTabFocus() && focus_chain.contains( active_client ))
|
||||
{
|
||||
// also put in focus_chain after all windows belonging to the active application
|
||||
focus_chain.remove( c );
|
||||
for ( int i = focus_chain.size() - 1; i >= 0 ; i-- )
|
||||
for( int desktop = 1;
|
||||
desktop <= numberOfDesktops();
|
||||
++desktop )
|
||||
{ // do for every virtual desktop to handle the case of onalldesktop windows
|
||||
if( c->wantsTabFocus() && c->isOnDesktop( desktop ) && focus_chain[ desktop ].contains( active_client ))
|
||||
{
|
||||
if( Client::belongToSameApplication( active_client, focus_chain.at( i ) ))
|
||||
// also put in focus_chain[currentDesktop()] after all windows belonging to the active applicationa
|
||||
focus_chain[ desktop ].remove( c );
|
||||
for ( int i = focus_chain[ desktop ].size() - 1;
|
||||
i >= 0;
|
||||
--i )
|
||||
{
|
||||
focus_chain.insert( i, c );
|
||||
break;
|
||||
if( Client::belongToSameApplication( active_client, focus_chain[ desktop ].at( i ) ))
|
||||
{
|
||||
focus_chain[ desktop ].insert( i, c );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
26
tabbox.cpp
26
tabbox.cpp
|
@ -1149,13 +1149,14 @@ int Workspace::previousDesktopFocusChain( int iDesktop ) const
|
|||
*/
|
||||
Client* Workspace::nextFocusChainClient( Client* c ) const
|
||||
{
|
||||
if ( focus_chain.isEmpty() )
|
||||
int desktop = c->isOnAllDesktops() ? currentDesktop() : c->desktop();
|
||||
if ( focus_chain[desktop].isEmpty() )
|
||||
return 0;
|
||||
ClientList::ConstIterator it = focus_chain.find( c );
|
||||
if ( it == focus_chain.end() )
|
||||
return focus_chain.last();
|
||||
if ( it == focus_chain.begin() )
|
||||
return focus_chain.last();
|
||||
ClientList::ConstIterator it = focus_chain[desktop].find( c );
|
||||
if ( it == focus_chain[desktop].end() )
|
||||
return focus_chain[desktop].last();
|
||||
if ( it == focus_chain[desktop].begin() )
|
||||
return focus_chain[desktop].last();
|
||||
--it;
|
||||
return *it;
|
||||
}
|
||||
|
@ -1166,14 +1167,15 @@ Client* Workspace::nextFocusChainClient( Client* c ) const
|
|||
*/
|
||||
Client* Workspace::previousFocusChainClient( Client* c ) const
|
||||
{
|
||||
if ( focus_chain.isEmpty() )
|
||||
int desktop = c->isOnAllDesktops() ? currentDesktop() : c->desktop();
|
||||
if ( focus_chain[desktop].isEmpty() )
|
||||
return 0;
|
||||
ClientList::ConstIterator it = focus_chain.find( c );
|
||||
if ( it == focus_chain.end() )
|
||||
return focus_chain.first();
|
||||
ClientList::ConstIterator it = focus_chain[desktop].find( c );
|
||||
if ( it == focus_chain[desktop].end() )
|
||||
return focus_chain[desktop].first();
|
||||
++it;
|
||||
if ( it == focus_chain.end() )
|
||||
return focus_chain.first();
|
||||
if ( it == focus_chain[desktop].end() )
|
||||
return focus_chain[desktop].first();
|
||||
return *it;
|
||||
}
|
||||
|
||||
|
|
100
workspace.cpp
100
workspace.cpp
|
@ -514,8 +514,7 @@ void Workspace::addClient( Client* c, allowed_t )
|
|||
}
|
||||
else
|
||||
{
|
||||
if ( c->wantsTabFocus() && !focus_chain.contains( c ))
|
||||
focus_chain.append( c );
|
||||
updateFocusChains( c, true );
|
||||
clients.append( c );
|
||||
}
|
||||
if( !unconstrained_stacking_order.contains( c ))
|
||||
|
@ -563,7 +562,10 @@ void Workspace::removeClient( Client* c, allowed_t )
|
|||
desktops.remove( c );
|
||||
unconstrained_stacking_order.remove( c );
|
||||
stacking_order.remove( c );
|
||||
focus_chain.remove( c );
|
||||
for( int i = 1;
|
||||
i <= numberOfDesktops();
|
||||
++i )
|
||||
focus_chain[ i ].remove( c );
|
||||
attention_chain.remove( c );
|
||||
if( c->isTopMenu())
|
||||
removeTopMenu( c );
|
||||
|
@ -590,6 +592,49 @@ void Workspace::removeClient( Client* c, allowed_t )
|
|||
updateClientArea();
|
||||
}
|
||||
|
||||
void Workspace::updateFocusChains( Client* c, bool make_first )
|
||||
{
|
||||
if( !c->wantsTabFocus()) // doesn't want tab focus, remove
|
||||
{
|
||||
for( int i=1;
|
||||
i<= numberOfDesktops();
|
||||
++i )
|
||||
focus_chain[i].remove(c);
|
||||
return;
|
||||
}
|
||||
if(c->desktop() == NET::OnAllDesktops)
|
||||
{ //now on all desktops, add it to focus_chains it is not already in
|
||||
for( int i=1; i<= numberOfDesktops(); i++)
|
||||
{ // make_first works only on current desktop, don't affect all desktops
|
||||
if( make_first && i == currentDesktop())
|
||||
{
|
||||
focus_chain[ i ].remove( c );
|
||||
focus_chain[ i ].append( c );
|
||||
}
|
||||
else if( !focus_chain[ i ].contains( c ))
|
||||
focus_chain[ i ].prepend( c ); // otherwise add as the last one
|
||||
}
|
||||
}
|
||||
else //now only on desktop, remove it anywhere else
|
||||
{
|
||||
for( int i=1; i<= numberOfDesktops(); i++)
|
||||
{
|
||||
if( i == c->desktop())
|
||||
{
|
||||
if( make_first )
|
||||
{
|
||||
focus_chain[ i ].remove( c );
|
||||
focus_chain[ i ].append( c );
|
||||
}
|
||||
else if( !focus_chain[ i ].contains( c ))
|
||||
focus_chain[ i ].prepend( c );
|
||||
}
|
||||
else
|
||||
focus_chain[ i ].remove( c );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Workspace::updateCurrentTopMenu()
|
||||
{
|
||||
if( !managingTopMenus())
|
||||
|
@ -916,6 +961,8 @@ void Workspace::loadDesktopSettings()
|
|||
screenarea = NULL;
|
||||
rootInfo->setNumberOfDesktops( number_of_desktops );
|
||||
desktop_focus_chain.resize( n );
|
||||
// make it +1, so that it can be accessed as [1..numberofdesktops]
|
||||
focus_chain.resize( n + 1 );
|
||||
for(int i = 1; i <= n; i++)
|
||||
{
|
||||
QString s = group.readEntry(QString("Name_%1").arg(i),
|
||||
|
@ -1140,36 +1187,22 @@ bool Workspace::setCurrentDesktop( int new_desktop )
|
|||
if ( options->focusPolicyIsReasonable())
|
||||
{
|
||||
// Search in focus chain
|
||||
|
||||
if ( focus_chain.contains( active_client ) && active_client->isShown( true )
|
||||
&& active_client->isOnCurrentDesktop())
|
||||
if ( movingClient != NULL && active_client == movingClient
|
||||
&& focus_chain[currentDesktop()].contains( active_client )
|
||||
&& active_client->isShown( true ) && active_client->isOnCurrentDesktop())
|
||||
{
|
||||
c = active_client; // the requestFocus below will fail, as the client is already active
|
||||
}
|
||||
|
||||
if ( !c )
|
||||
if( !c )
|
||||
{
|
||||
for( int i = focus_chain.size() - 1;
|
||||
i >= 0;
|
||||
--i )
|
||||
for( int i = focus_chain[ currentDesktop() ].size() - 1;
|
||||
i >= 0;
|
||||
--i )
|
||||
{
|
||||
if ( focus_chain.at( i )->isShown( false ) && !focus_chain.at( i )->isOnAllDesktops() && focus_chain.at( i )->isOnCurrentDesktop())
|
||||
if( focus_chain[ currentDesktop() ].at( i )->isShown( false )
|
||||
&& focus_chain[ currentDesktop() ].at( i )->isOnCurrentDesktop())
|
||||
{
|
||||
c = focus_chain.at( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !c )
|
||||
{
|
||||
for( int i = focus_chain.size() - 1;
|
||||
i >= 0;
|
||||
--i )
|
||||
{
|
||||
if ( focus_chain.at( i )->isShown( false ) && focus_chain.at( i )->isOnCurrentDesktop())
|
||||
{
|
||||
c = focus_chain.at( i );
|
||||
c = focus_chain[ currentDesktop() ].at( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1202,13 +1235,13 @@ bool Workspace::setCurrentDesktop( int new_desktop )
|
|||
updateCurrentTopMenu();
|
||||
|
||||
// Update focus chain:
|
||||
// If input: chain = { 1, 2, 3, 4 } and current_desktop = 3,
|
||||
// If input: chain = { 1, 2, 3, 4 } and currentDesktop() = 3,
|
||||
// Output: chain = { 3, 1, 2, 4 }.
|
||||
// kDebug(1212) << QString("Switching to desktop #%1, at focus_chain index %2\n")
|
||||
// .arg(current_desktop).arg(desktop_focus_chain.find( current_desktop ));
|
||||
for( int i = desktop_focus_chain.indexOf( current_desktop ); i > 0; i-- )
|
||||
// .arg(currentDesktop()).arg(desktop_focus_chain.find( currentDesktop() ));
|
||||
for( int i = desktop_focus_chain.indexOf( currentDesktop() ); i > 0; i-- )
|
||||
desktop_focus_chain[i] = desktop_focus_chain[i-1];
|
||||
desktop_focus_chain[0] = current_desktop;
|
||||
desktop_focus_chain[0] = currentDesktop();
|
||||
|
||||
// QString s = "desktop_focus_chain[] = { ";
|
||||
// for( uint i = 0; i < desktop_focus_chain.size(); i++ )
|
||||
|
@ -1381,6 +1414,7 @@ void Workspace::setNumberOfDesktops( int n )
|
|||
rootInfo->setDesktopViewport( number_of_desktops, *viewports );
|
||||
delete[] viewports;
|
||||
updateClientArea( true );
|
||||
focus_chain.resize( number_of_desktops + 1 );
|
||||
}
|
||||
|
||||
// if the number of desktops decreased, move all
|
||||
|
@ -1402,6 +1436,7 @@ void Workspace::setNumberOfDesktops( int n )
|
|||
rootInfo->setDesktopViewport( number_of_desktops, *viewports );
|
||||
delete[] viewports;
|
||||
updateClientArea( true );
|
||||
focus_chain.resize( number_of_desktops + 1 );
|
||||
}
|
||||
|
||||
saveDesktopSettings();
|
||||
|
@ -1437,9 +1472,6 @@ void Workspace::sendClientToDesktop( Client* c, int desk, bool dont_activate )
|
|||
else
|
||||
{
|
||||
raiseClient( c );
|
||||
focus_chain.remove( c );
|
||||
if ( c->wantsTabFocus() )
|
||||
focus_chain.append( c );
|
||||
}
|
||||
|
||||
ClientList transients_stacking_order = ensureStackingOrder( c->transients());
|
||||
|
|
|
@ -13,6 +13,7 @@ License. See the file "COPYING" for the exact licensing terms.
|
|||
#define KWIN_WORKSPACE_H
|
||||
|
||||
#include <qtimer.h>
|
||||
#include <qvector.h>
|
||||
#include <kshortcut.h>
|
||||
#include <qcursor.h>
|
||||
#include <netwm.h>
|
||||
|
@ -250,6 +251,7 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine
|
|||
bool checkStartupNotification( Window w, KStartupInfoId& id, KStartupInfoData& data );
|
||||
|
||||
void focusToNull(); // SELI public?
|
||||
void updateFocusChains( Client* c, bool make_first );
|
||||
|
||||
bool forcedGlobalMouseGrab() const;
|
||||
void clientShortcutUpdated( Client* c );
|
||||
|
@ -507,7 +509,7 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine
|
|||
|
||||
ClientList unconstrained_stacking_order;
|
||||
ClientList stacking_order;
|
||||
ClientList focus_chain;
|
||||
QVector< ClientList > focus_chain;
|
||||
ClientList should_get_focus; // last is most recent
|
||||
ClientList attention_chain;
|
||||
|
||||
|
|
Loading…
Reference in a new issue