Activity association for windows.
ok'd by fredrikh. this code is buggy right now, but I promise to squash the bugs by the 19th :) svn path=/trunk/KDE/kdebase/workspace/; revision=1125614
This commit is contained in:
parent
b8637bf4fb
commit
a9ad071575
12 changed files with 409 additions and 4 deletions
|
@ -45,6 +45,7 @@ include_directories(
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/effects
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tabbox
|
||||
${KDEBASE_WORKSPACE_SOURCE_DIR}/libs/kephal
|
||||
${KDEBASE_WORKSPACE_SOURCE_DIR}/libs/kworkspace
|
||||
)
|
||||
|
||||
|
||||
|
@ -129,7 +130,7 @@ qt4_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.KWin.xml workspace.h KWin::Works
|
|||
|
||||
kde4_add_kdeinit_executable( kwin ${kwin_KDEINIT_SRCS})
|
||||
|
||||
target_link_libraries(kdeinit_kwin ${KDE4_KDEUI_LIBS} ${KDE4_PLASMA_LIBS} ${QT_QTXML_LIBRARY} kephal kdecorations kwineffects ${X11_LIBRARIES})
|
||||
target_link_libraries(kdeinit_kwin ${KDE4_KDEUI_LIBS} ${KDE4_PLASMA_LIBS} ${QT_QTXML_LIBRARY} kephal kworkspace kdecorations kwineffects ${X11_LIBRARIES})
|
||||
|
||||
if(OPENGL_FOUND)
|
||||
add_subdirectory(opengltest)
|
||||
|
|
|
@ -400,7 +400,7 @@ void Workspace::handleTakeActivity( Client* c, Time /*timestamp*/, int flags )
|
|||
*/
|
||||
void Workspace::clientHidden( Client* c )
|
||||
{
|
||||
assert( !c->isShown( true ) || !c->isOnCurrentDesktop());
|
||||
assert( !c->isShown( true ) || !c->isOnCurrentDesktop() || !c->isOnCurrentActivity());
|
||||
activateNextClient( c );
|
||||
}
|
||||
|
||||
|
@ -431,7 +431,7 @@ bool Workspace::activateNextClient( Client* c )
|
|||
{
|
||||
Client* ci = focus_chain[ currentDesktop() ].at( i );
|
||||
if( c == ci || !ci->isShown( false )
|
||||
|| !ci->isOnCurrentDesktop())
|
||||
|| !ci->isOnCurrentDesktop() || !ci->isOnCurrentActivity())
|
||||
continue;
|
||||
if( options->separateScreenFocus )
|
||||
{
|
||||
|
@ -478,7 +478,7 @@ void Workspace::setCurrentScreen( int new_screen )
|
|||
--i )
|
||||
{
|
||||
Client* ci = focus_chain[ currentDesktop() ].at( i );
|
||||
if( !ci->isShown( false ) || !ci->isOnCurrentDesktop())
|
||||
if( !ci->isShown( false ) || !ci->isOnCurrentDesktop() || !ci->isOnCurrentActivity())
|
||||
continue;
|
||||
if( !ci->screen() == new_screen )
|
||||
continue;
|
||||
|
|
92
client.cpp
92
client.cpp
|
@ -1090,6 +1090,14 @@ void Client::updateVisibility()
|
|||
internalHide( Allowed );
|
||||
return;
|
||||
}
|
||||
if( !isOnCurrentActivity())
|
||||
{
|
||||
if( compositing() && options->hiddenPreviews != HiddenPreviewsNever )
|
||||
internalKeep( Allowed );
|
||||
else
|
||||
internalHide( Allowed );
|
||||
return;
|
||||
}
|
||||
bool belongs_to_desktop = false;
|
||||
for( ClientList::ConstIterator it = group()->members().constBegin();
|
||||
it != group()->members().constEnd();
|
||||
|
@ -1476,6 +1484,52 @@ void Client::setDesktop( int desktop )
|
|||
clientGroup()->updateStates( this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the client is on @p activity.
|
||||
* If you remove it from its last activity, then it's on all activities.
|
||||
*
|
||||
* Note: If it was on all activities and you try to remove it from one, nothing will happen;
|
||||
* I don't think that's an important enough use case to handle here.
|
||||
*/
|
||||
void Client::setOnActivity( const QString &activity, bool enable )
|
||||
{
|
||||
if( activityList.contains(activity) == enable ) //nothing to do
|
||||
return;
|
||||
KActivityConsumer c;
|
||||
QStringList allActivities = c.availableActivities();
|
||||
if( !allActivities.contains(activity) ) //bogus ID
|
||||
return;
|
||||
//check whether we should set it to all activities
|
||||
QStringList newActivitiesList = activityList;
|
||||
if (enable)
|
||||
newActivitiesList.append(activity);
|
||||
else
|
||||
newActivitiesList.removeOne(activity);
|
||||
if( newActivitiesList.size() == allActivities.size() || newActivitiesList.isEmpty() )
|
||||
{
|
||||
setOnAllActivities(true);
|
||||
return;
|
||||
}
|
||||
activityList = newActivitiesList;
|
||||
/* FIXME I don't think I need the transients but what about the rest?
|
||||
if(( was_desk == NET::OnAllDesktops ) != ( desktop == NET::OnAllDesktops ))
|
||||
{ // onAllDesktops changed
|
||||
if( isShown( true ))
|
||||
Notify::raise( isOnAllDesktops() ? Notify::OnAllDesktops : Notify::NotOnAllDesktops );
|
||||
workspace()->updateOnAllDesktopsOfTransients( this );
|
||||
}
|
||||
if( decoration != NULL )
|
||||
decoration->desktopChange();
|
||||
*/
|
||||
workspace()->updateFocusChains( this, Workspace::FocusChainMakeFirst );
|
||||
updateVisibility();
|
||||
updateWindowRules();
|
||||
|
||||
// Update states of all other windows in this group
|
||||
if( clientGroup() )
|
||||
clientGroup()->updateStates( this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the virtual desktop within the workspace() the client window
|
||||
* is located in, 0 if it isn't located on any special desktop (not mapped yet),
|
||||
|
@ -1487,6 +1541,17 @@ int Client::desktop() const
|
|||
return desk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of activities the client window is on.
|
||||
* if it's on all activities, the list will be empty.
|
||||
* Don't use this, use isOnActivity() and friends (from class Toplevel)
|
||||
* FIXME do I need to consider if it's not mapped yet?
|
||||
*/
|
||||
QStringList Client::activities() const
|
||||
{
|
||||
return activityList;
|
||||
}
|
||||
|
||||
void Client::setOnAllDesktops( bool b )
|
||||
{
|
||||
if(( b && isOnAllDesktops() ) ||
|
||||
|
@ -1502,6 +1567,33 @@ void Client::setOnAllDesktops( bool b )
|
|||
clientGroup()->updateStates( this );
|
||||
}
|
||||
|
||||
/**
|
||||
* if @p b is true, sets on all activities.
|
||||
* if it's false, sets it to only be on the current activity
|
||||
*/
|
||||
void Client::setOnAllActivities( bool b )
|
||||
{
|
||||
if( b == isOnAllActivities() )
|
||||
return;
|
||||
if( b ) {
|
||||
activityList.clear();
|
||||
//FIXME update transients
|
||||
} else {
|
||||
KActivityConsumer c;
|
||||
setOnActivity(c.currentActivity(), true);
|
||||
//FIXME update transients
|
||||
return;
|
||||
}
|
||||
|
||||
//FIXME c&p'd from setOnActivity, I probably need more code and should probably factor it out
|
||||
workspace()->updateFocusChains( this, Workspace::FocusChainMakeFirst );
|
||||
updateVisibility();
|
||||
updateWindowRules();
|
||||
// Update states of all other windows in this group
|
||||
if( clientGroup() )
|
||||
clientGroup()->updateStates( this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs activation and/or raising of the window
|
||||
*/
|
||||
|
|
5
client.h
5
client.h
|
@ -143,6 +143,10 @@ class Client
|
|||
void setDesktop( int );
|
||||
void setOnAllDesktops( bool set );
|
||||
|
||||
virtual QStringList activities() const;
|
||||
void setOnActivity( const QString &activity, bool enable );
|
||||
void setOnAllActivities( bool set );
|
||||
|
||||
/// Is not minimized and not hidden. I.e. normally visible on some virtual desktop.
|
||||
bool isShown( bool shaded_is_shown ) const;
|
||||
bool isHiddenInternal() const; // For compositing
|
||||
|
@ -506,6 +510,7 @@ class Client
|
|||
KDecoration* decoration;
|
||||
Bridge* bridge;
|
||||
int desk;
|
||||
QStringList activityList;
|
||||
bool buttonDown;
|
||||
bool moveResizeMode;
|
||||
bool move_faked_activity;
|
||||
|
|
|
@ -67,6 +67,7 @@ void Deleted::copyToDeleted( Toplevel* c )
|
|||
assert( dynamic_cast< Deleted* >( c ) == NULL );
|
||||
Toplevel::copyToDeleted( c );
|
||||
desk = c->desktop();
|
||||
activityList = c->activities();
|
||||
contentsRect = QRect( c->clientPos(), c->clientSize());
|
||||
transparent_rect = c->transparentRect();
|
||||
if( WinInfo* cinfo = dynamic_cast< WinInfo* >( info ))
|
||||
|
@ -111,6 +112,11 @@ int Deleted::desktop() const
|
|||
return desk;
|
||||
}
|
||||
|
||||
QStringList Deleted::activities() const
|
||||
{
|
||||
return activityList;
|
||||
}
|
||||
|
||||
QPoint Deleted::clientPos() const
|
||||
{
|
||||
return contentsRect.topLeft();
|
||||
|
|
|
@ -37,6 +37,7 @@ class Deleted
|
|||
void unrefWindow( bool delay = false );
|
||||
void discard( allowed_t );
|
||||
virtual int desktop() const;
|
||||
virtual QStringList activities() const;
|
||||
virtual QPoint clientPos() const;
|
||||
virtual QSize clientSize() const;
|
||||
virtual QRect transparentRect() const;
|
||||
|
@ -58,6 +59,7 @@ class Deleted
|
|||
int delete_refcount;
|
||||
double window_opacity;
|
||||
int desk;
|
||||
QStringList activityList;
|
||||
QRect contentsRect; // for clientPos()/clientSize()
|
||||
QRect transparent_rect;
|
||||
|
||||
|
|
21
toplevel.h
21
toplevel.h
|
@ -28,6 +28,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <kdecoration.h>
|
||||
#include <kdebug.h>
|
||||
|
||||
#include "kactivityconsumer.h"
|
||||
|
||||
#include "utils.h"
|
||||
#include "workspace.h"
|
||||
|
||||
|
@ -90,9 +92,13 @@ class Toplevel
|
|||
bool isDNDIcon() const;
|
||||
|
||||
virtual int desktop() const = 0;
|
||||
virtual QStringList activities() const = 0;
|
||||
bool isOnDesktop( int d ) const;
|
||||
bool isOnActivity( const QString &activity ) const;
|
||||
bool isOnCurrentDesktop() const;
|
||||
bool isOnCurrentActivity() const;
|
||||
bool isOnAllDesktops() const;
|
||||
bool isOnAllActivities() const;
|
||||
|
||||
QByteArray windowRole() const;
|
||||
QByteArray sessionId();
|
||||
|
@ -386,16 +392,31 @@ inline bool Toplevel::isOnAllDesktops() const
|
|||
return desktop() == NET::OnAllDesktops;
|
||||
}
|
||||
|
||||
inline bool Toplevel::isOnAllActivities() const
|
||||
{
|
||||
return activities().isEmpty();
|
||||
}
|
||||
|
||||
inline bool Toplevel::isOnDesktop( int d ) const
|
||||
{
|
||||
return desktop() == d || /*desk == 0 ||*/ isOnAllDesktops();
|
||||
}
|
||||
|
||||
inline bool Toplevel::isOnActivity( const QString &activity ) const
|
||||
{
|
||||
return activities().isEmpty() || activities().contains(activity);
|
||||
}
|
||||
|
||||
inline bool Toplevel::isOnCurrentDesktop() const
|
||||
{
|
||||
return isOnDesktop( workspace()->currentDesktop());
|
||||
}
|
||||
|
||||
inline bool Toplevel::isOnCurrentActivity() const
|
||||
{
|
||||
return isOnActivity( KActivityConsumer().currentActivity());
|
||||
}
|
||||
|
||||
inline QByteArray Toplevel::resourceName() const
|
||||
{
|
||||
return resource_name; // it is always lowercase
|
||||
|
|
|
@ -112,6 +112,11 @@ int Unmanaged::desktop() const
|
|||
return NET::OnAllDesktops; // TODO for some window types should be the current desktop?
|
||||
}
|
||||
|
||||
QStringList Unmanaged::activities() const
|
||||
{
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QPoint Unmanaged::clientPos() const
|
||||
{
|
||||
return QPoint( 0, 0 ); // unmanaged windows don't have decorations
|
||||
|
|
|
@ -39,6 +39,7 @@ class Unmanaged
|
|||
bool track( Window w );
|
||||
static void deleteUnmanaged( Unmanaged* c, allowed_t );
|
||||
virtual int desktop() const;
|
||||
virtual QStringList activities() const;
|
||||
virtual QPoint clientPos() const;
|
||||
virtual QSize clientSize() const;
|
||||
virtual QRect transparentRect() const;
|
||||
|
|
|
@ -33,6 +33,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "tile.h"
|
||||
#include "tilinglayout.h"
|
||||
|
||||
#include "kactivityinfo.h"
|
||||
|
||||
#include <fixx11h.h>
|
||||
#include <QPushButton>
|
||||
#include <QSlider>
|
||||
|
@ -237,6 +239,7 @@ void Workspace::discardPopup()
|
|||
delete popup;
|
||||
popup = NULL;
|
||||
desk_popup = NULL;
|
||||
activity_popup = NULL;
|
||||
switch_to_tab_popup = NULL;
|
||||
add_tabs_popup = NULL;
|
||||
}
|
||||
|
@ -268,6 +271,17 @@ void Workspace::clientPopupAboutToShow()
|
|||
{
|
||||
initDesktopPopup();
|
||||
}
|
||||
QStringList act = activityController_.availableActivities();
|
||||
kDebug() << "activities:" << act.size();
|
||||
if ( act.size() < 2 )
|
||||
{
|
||||
delete activity_popup;
|
||||
activity_popup = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
initActivityPopup();
|
||||
}
|
||||
|
||||
mResizeOpAction->setEnabled( active_popup_client->isResizable() );
|
||||
mMoveOpAction->setEnabled( active_popup_client->isMovableAcrossScreens() );
|
||||
|
@ -455,6 +469,29 @@ void Workspace::initDesktopPopup()
|
|||
action->setText( i18n("To &Desktop") );
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates activity popup.
|
||||
I'm going with checkable ones instead of "copy to" and "move to" menus; I *think* it's an easier way.
|
||||
Oh, and an 'all' option too of course
|
||||
*/
|
||||
void Workspace::initActivityPopup()
|
||||
{
|
||||
if (activity_popup)
|
||||
return;
|
||||
|
||||
activity_popup = new QMenu( popup );
|
||||
activity_popup->setFont(KGlobalSettings::menuFont());
|
||||
connect( activity_popup, SIGNAL( triggered(QAction*) ),
|
||||
this, SLOT( slotToggleOnActivity(QAction*) ) );
|
||||
connect( activity_popup, SIGNAL( aboutToShow() ),
|
||||
this, SLOT( activityPopupAboutToShow() ) );
|
||||
|
||||
QAction *action = activity_popup->menuAction();
|
||||
// set it as the first item
|
||||
popup->insertAction( trans_popup ? trans_popup->menuAction() : mMoveOpAction, action);
|
||||
action->setText( i18n("Ac&tivities") ); //FIXME is that a good string?
|
||||
}
|
||||
|
||||
/*!
|
||||
Adjusts the desktop popup to the current values and the location of
|
||||
the popup client.
|
||||
|
@ -489,6 +526,37 @@ void Workspace::desktopPopupAboutToShow()
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Adjusts the activity popup to the current values and the location of
|
||||
the popup client.
|
||||
*/
|
||||
void Workspace::activityPopupAboutToShow()
|
||||
{
|
||||
if ( !activity_popup )
|
||||
return;
|
||||
|
||||
activity_popup->clear();
|
||||
QAction *action = activity_popup->addAction( i18n("&All Activities") );
|
||||
action->setData( 0 );
|
||||
action->setCheckable( true );
|
||||
|
||||
if ( active_popup_client && active_popup_client->isOnAllActivities() )
|
||||
action->setChecked( true );
|
||||
activity_popup->addSeparator();
|
||||
|
||||
foreach (const QString &activity, activityController_.availableActivities()) {
|
||||
QString name = KActivityInfo::name(activity);
|
||||
name.replace('&', "&&");
|
||||
action = activity_popup->addAction( name );
|
||||
action->setData( activity );
|
||||
action->setCheckable( true );
|
||||
|
||||
if ( active_popup_client &&
|
||||
!active_popup_client->isOnAllActivities() && active_popup_client->isOnActivity(activity) )
|
||||
action->setChecked( true );
|
||||
}
|
||||
}
|
||||
|
||||
void Workspace::closeActivePopup()
|
||||
{
|
||||
if( active_popup )
|
||||
|
@ -1505,6 +1573,26 @@ void Workspace::slotSendToDesktop( QAction *action )
|
|||
|
||||
}
|
||||
|
||||
/*!
|
||||
Toggles whether the popup client is on the \a activity
|
||||
|
||||
Internal slot for the window operation menu
|
||||
*/
|
||||
void Workspace::slotToggleOnActivity( QAction *action )
|
||||
{
|
||||
QString activity = action->data().toString();
|
||||
if ( !active_popup_client )
|
||||
return;
|
||||
if ( activity.isEmpty() )
|
||||
{ // the 'on_all_activities' menu entry
|
||||
active_popup_client->setOnAllActivities( !active_popup_client->isOnAllActivities());
|
||||
return;
|
||||
}
|
||||
|
||||
toggleClientOnActivity( active_popup_client, activity, false );
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
Switches to the nearest window in given direction
|
||||
*/
|
||||
|
|
172
workspace.cpp
172
workspace.cpp
|
@ -125,6 +125,7 @@ Workspace::Workspace( bool restore )
|
|||
, advanced_popup( 0 )
|
||||
, trans_popup( 0 )
|
||||
, desk_popup( 0 )
|
||||
, activity_popup( 0 )
|
||||
, add_tabs_popup( 0 )
|
||||
, switch_to_tab_popup( 0 )
|
||||
, keys( 0 )
|
||||
|
@ -240,6 +241,8 @@ Workspace::Workspace( bool restore )
|
|||
connect( Kephal::Screens::self(), SIGNAL( screenRemoved(int) ), SLOT( desktopResized() ));
|
||||
connect( Kephal::Screens::self(), SIGNAL( screenResized(Kephal::Screen*, QSize, QSize) ), SLOT( desktopResized() ));
|
||||
connect( Kephal::Screens::self(), SIGNAL( screenMoved(Kephal::Screen*, QPoint, QPoint) ), SLOT( desktopResized() ));
|
||||
|
||||
connect( &activityController_, SIGNAL( currentActivityChanged(QString) ), SLOT( updateCurrentActivity(QString) ));
|
||||
}
|
||||
|
||||
void Workspace::init()
|
||||
|
@ -1514,6 +1517,135 @@ bool Workspace::setCurrentDesktop( int new_desktop )
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current activity when it changes
|
||||
* do *not* call this directly; it does not set the activity.
|
||||
*
|
||||
* Shows/Hides windows according to the stacking order
|
||||
*/
|
||||
void Workspace::updateCurrentActivity(const QString &new_activity)
|
||||
{
|
||||
|
||||
//closeActivePopup();
|
||||
++block_focus;
|
||||
// TODO: Q_ASSERT( block_stacking_updates == 0 ); // Make sure stacking_order is up to date
|
||||
StackingUpdatesBlocker blocker( this );
|
||||
|
||||
if ( new_activity != activity_ )
|
||||
{
|
||||
++block_showing_desktop; //FIXME should I be using that?
|
||||
// Optimized Desktop switching: unmapping done from back to front
|
||||
// mapping done from front to back => less exposure events
|
||||
//Notify::raise((Notify::Event) (Notify::DesktopChange+new_desktop));
|
||||
|
||||
ObscuringWindows obs_wins;
|
||||
|
||||
QString old_activity = activity_;
|
||||
activity_ = new_activity;
|
||||
|
||||
for( ClientList::ConstIterator it = stacking_order.constBegin();
|
||||
it != stacking_order.constEnd();
|
||||
++it )
|
||||
if( !(*it)->isOnActivity( new_activity ) && (*it) != movingClient )
|
||||
{
|
||||
if( (*it)->isShown( true ) && (*it)->isOnActivity( old_activity ))
|
||||
obs_wins.create( *it );
|
||||
(*it)->updateVisibility();
|
||||
}
|
||||
|
||||
// Now propagate the change, after hiding, before showing
|
||||
//rootInfo->setCurrentDesktop( currentDesktop() );
|
||||
|
||||
/* TODO someday enable dragging windows to other activities
|
||||
if( movingClient && !movingClient->isOnDesktop( new_desktop ))
|
||||
{
|
||||
int old_desktop = movingClient->desktop();
|
||||
movingClient->setDesktop( new_desktop );
|
||||
if( tilingEnabled() )
|
||||
{
|
||||
notifyWindowDesktopChanged( movingClient, old_desktop );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
for( int i = stacking_order.size() - 1; i >= 0 ; --i )
|
||||
if( stacking_order.at( i )->isOnActivity( new_activity ))
|
||||
stacking_order.at( i )->updateVisibility();
|
||||
|
||||
--block_showing_desktop;
|
||||
//FIXME not sure if I should do this either
|
||||
if( showingDesktop() ) // Do this only after desktop change to avoid flicker
|
||||
resetShowingDesktop( false );
|
||||
}
|
||||
|
||||
// Restore the focus on this desktop
|
||||
--block_focus;
|
||||
Client* c = 0;
|
||||
|
||||
//FIXME below here is a lot of focuschain stuff, probably all wrong now
|
||||
if( options->focusPolicyIsReasonable() )
|
||||
{ // Search in focus chain
|
||||
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 )
|
||||
{
|
||||
for( int i = focus_chain[currentDesktop()].size() - 1; i >= 0; --i )
|
||||
{
|
||||
if( focus_chain[currentDesktop()].at( i )->isShown( false ) &&
|
||||
focus_chain[currentDesktop()].at( i )->isOnCurrentDesktop() )
|
||||
{
|
||||
c = focus_chain[currentDesktop()].at( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If "unreasonable focus policy" and active_client is on_all_desktops and
|
||||
// under mouse (Hence == old_active_client), conserve focus.
|
||||
// (Thanks to Volker Schatz <V.Schatz at thphys.uni-heidelberg.de>)
|
||||
else if( active_client && active_client->isShown( true ) && active_client->isOnCurrentDesktop() )
|
||||
c = active_client;
|
||||
|
||||
if( c == NULL && !desktops.isEmpty() )
|
||||
c = findDesktop( true, currentDesktop() );
|
||||
|
||||
if( c != active_client )
|
||||
setActiveClient( NULL, Allowed );
|
||||
|
||||
if ( c )
|
||||
requestFocus( c );
|
||||
else if( !desktops.isEmpty() )
|
||||
requestFocus( findDesktop( true, currentDesktop() ));
|
||||
else
|
||||
focusToNull();
|
||||
|
||||
updateCurrentTopMenu();
|
||||
|
||||
// Update focus chain:
|
||||
// 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(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] = currentDesktop();
|
||||
|
||||
//QString s = "desktop_focus_chain[] = { ";
|
||||
//for( uint i = 0; i < desktop_focus_chain.size(); i++ )
|
||||
// s += QString::number( desktop_focus_chain[i] ) + ", ";
|
||||
//kDebug( 1212 ) << s << "}\n";
|
||||
|
||||
// Not for the very first time, only if something changed and there are more than 1 desktops
|
||||
|
||||
//if( effects != NULL && old_desktop != 0 && old_desktop != new_desktop )
|
||||
// static_cast<EffectsHandlerImpl*>( effects )->desktopChanged( old_desktop );
|
||||
if( compositing())
|
||||
addRepaintFull();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called only from D-Bus
|
||||
*/
|
||||
|
@ -1631,6 +1763,46 @@ void Workspace::sendClientToDesktop( Client* c, int desk, bool dont_activate )
|
|||
updateClientArea();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds/removes client \a c to/from \a desk.
|
||||
*
|
||||
* Takes care of transients as well.
|
||||
*/
|
||||
void Workspace::toggleClientOnActivity( Client* c, const QString &activity, bool dont_activate )
|
||||
{
|
||||
//int old_desktop = c->desktop();
|
||||
bool was_on_activity = c->isOnActivity(activity);
|
||||
bool was_on_all = c->isOnAllActivities();
|
||||
//note: all activities === no activities
|
||||
bool enable = was_on_all || !was_on_activity;
|
||||
c->setOnActivity( activity, enable );
|
||||
if( c->isOnActivity(activity) == was_on_activity && c->isOnAllActivities() == was_on_all ) // No change
|
||||
return;
|
||||
|
||||
if( c->isOnActivity( activityController_.currentActivity() ))
|
||||
{
|
||||
if( c->wantsTabFocus() && options->focusPolicyIsReasonable() &&
|
||||
!was_on_activity && // for stickyness changes
|
||||
//FIXME not sure if the line above refers to the correct activity
|
||||
!dont_activate )
|
||||
requestFocus( c );
|
||||
else
|
||||
restackClientUnderActive( c );
|
||||
}
|
||||
else
|
||||
raiseClient( c );
|
||||
|
||||
//notifyWindowDesktopChanged( c, old_desktop );
|
||||
//FIXME does tiling break?
|
||||
|
||||
ClientList transients_stacking_order = ensureStackingOrder( c->transients() );
|
||||
for( ClientList::ConstIterator it = transients_stacking_order.constBegin();
|
||||
it != transients_stacking_order.constEnd();
|
||||
++it )
|
||||
toggleClientOnActivity( *it, activity, dont_activate );
|
||||
updateClientArea();
|
||||
}
|
||||
|
||||
int Workspace::numScreens() const
|
||||
{
|
||||
if( !options->xineramaEnabled )
|
||||
|
|
12
workspace.h
12
workspace.h
|
@ -32,6 +32,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <QDateTime>
|
||||
#include <kmanagerselection.h>
|
||||
|
||||
#include "kactivitycontroller.h"
|
||||
|
||||
#include "plugins.h"
|
||||
#include "utils.h"
|
||||
#include "kdecoration.h"
|
||||
|
@ -312,8 +314,11 @@ class Workspace : public QObject, public KDecorationDefines
|
|||
QSize desktopGridSize_;
|
||||
int* desktopGrid_;
|
||||
int currentDesktop_;
|
||||
QString activity_;
|
||||
bool desktopLayoutDynamicity_;
|
||||
|
||||
KActivityController activityController_;
|
||||
|
||||
bool tilingEnabled_;
|
||||
// Each tilingLayout is for one virtual desktop.
|
||||
// The length is always one more than the number of
|
||||
|
@ -373,6 +378,7 @@ class Workspace : public QObject, public KDecorationDefines
|
|||
bool only_normal = true ) const;
|
||||
Client* findDesktop( bool topmost, int desktop ) const;
|
||||
void sendClientToDesktop( Client* c, int desktop, bool dont_activate );
|
||||
void toggleClientOnActivity( Client* c, const QString &activity, bool dont_activate );
|
||||
void windowToPreviousDesktop( Client* c );
|
||||
void windowToNextDesktop( Client* c );
|
||||
void sendClientToScreen( Client* c, int screen );
|
||||
|
@ -722,8 +728,10 @@ class Workspace : public QObject, public KDecorationDefines
|
|||
void slotAddToTabGroup( QAction* ); // Add client to a group
|
||||
void slotSwitchToTab( QAction* ); // Change the tab
|
||||
void desktopPopupAboutToShow();
|
||||
void activityPopupAboutToShow();
|
||||
void clientPopupAboutToShow();
|
||||
void slotSendToDesktop( QAction* );
|
||||
void slotToggleOnActivity( QAction* );
|
||||
void clientPopupActivated( QAction* );
|
||||
void configureWM();
|
||||
void desktopResized();
|
||||
|
@ -747,6 +755,8 @@ class Workspace : public QObject, public KDecorationDefines
|
|||
void resetCursorPosTime();
|
||||
void delayedCheckUnredirect();
|
||||
|
||||
void updateCurrentActivity(const QString &activity);
|
||||
|
||||
protected:
|
||||
bool keyPressMouseEmulation( XKeyEvent& ev );
|
||||
|
||||
|
@ -758,6 +768,7 @@ class Workspace : public QObject, public KDecorationDefines
|
|||
void initShortcuts();
|
||||
void readShortcuts();
|
||||
void initDesktopPopup();
|
||||
void initActivityPopup();
|
||||
void discardPopup();
|
||||
void setupWindowShortcut( Client* c );
|
||||
void checkCursorPos();
|
||||
|
@ -930,6 +941,7 @@ class Workspace : public QObject, public KDecorationDefines
|
|||
QMenu* trans_popup;
|
||||
QActionGroup* trans_popup_group;
|
||||
QMenu* desk_popup;
|
||||
QMenu* activity_popup;
|
||||
QMenu* add_tabs_popup; // Menu to add the group to other group
|
||||
QMenu* switch_to_tab_popup; // Menu to change tab
|
||||
|
||||
|
|
Loading…
Reference in a new issue