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=1125614icc-effect-5.14.5
parent
b8637bf4fb
commit
a9ad071575
|
@ -45,6 +45,7 @@ include_directories(
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/effects
|
${CMAKE_CURRENT_SOURCE_DIR}/effects
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/tabbox
|
${CMAKE_CURRENT_SOURCE_DIR}/tabbox
|
||||||
${KDEBASE_WORKSPACE_SOURCE_DIR}/libs/kephal
|
${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})
|
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)
|
if(OPENGL_FOUND)
|
||||||
add_subdirectory(opengltest)
|
add_subdirectory(opengltest)
|
||||||
|
|
|
@ -400,7 +400,7 @@ void Workspace::handleTakeActivity( Client* c, Time /*timestamp*/, int flags )
|
||||||
*/
|
*/
|
||||||
void Workspace::clientHidden( Client* c )
|
void Workspace::clientHidden( Client* c )
|
||||||
{
|
{
|
||||||
assert( !c->isShown( true ) || !c->isOnCurrentDesktop());
|
assert( !c->isShown( true ) || !c->isOnCurrentDesktop() || !c->isOnCurrentActivity());
|
||||||
activateNextClient( c );
|
activateNextClient( c );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,7 +431,7 @@ bool Workspace::activateNextClient( Client* c )
|
||||||
{
|
{
|
||||||
Client* ci = focus_chain[ currentDesktop() ].at( i );
|
Client* ci = focus_chain[ currentDesktop() ].at( i );
|
||||||
if( c == ci || !ci->isShown( false )
|
if( c == ci || !ci->isShown( false )
|
||||||
|| !ci->isOnCurrentDesktop())
|
|| !ci->isOnCurrentDesktop() || !ci->isOnCurrentActivity())
|
||||||
continue;
|
continue;
|
||||||
if( options->separateScreenFocus )
|
if( options->separateScreenFocus )
|
||||||
{
|
{
|
||||||
|
@ -478,7 +478,7 @@ void Workspace::setCurrentScreen( int new_screen )
|
||||||
--i )
|
--i )
|
||||||
{
|
{
|
||||||
Client* ci = focus_chain[ currentDesktop() ].at( i );
|
Client* ci = focus_chain[ currentDesktop() ].at( i );
|
||||||
if( !ci->isShown( false ) || !ci->isOnCurrentDesktop())
|
if( !ci->isShown( false ) || !ci->isOnCurrentDesktop() || !ci->isOnCurrentActivity())
|
||||||
continue;
|
continue;
|
||||||
if( !ci->screen() == new_screen )
|
if( !ci->screen() == new_screen )
|
||||||
continue;
|
continue;
|
||||||
|
|
92
client.cpp
92
client.cpp
|
@ -1090,6 +1090,14 @@ void Client::updateVisibility()
|
||||||
internalHide( Allowed );
|
internalHide( Allowed );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if( !isOnCurrentActivity())
|
||||||
|
{
|
||||||
|
if( compositing() && options->hiddenPreviews != HiddenPreviewsNever )
|
||||||
|
internalKeep( Allowed );
|
||||||
|
else
|
||||||
|
internalHide( Allowed );
|
||||||
|
return;
|
||||||
|
}
|
||||||
bool belongs_to_desktop = false;
|
bool belongs_to_desktop = false;
|
||||||
for( ClientList::ConstIterator it = group()->members().constBegin();
|
for( ClientList::ConstIterator it = group()->members().constBegin();
|
||||||
it != group()->members().constEnd();
|
it != group()->members().constEnd();
|
||||||
|
@ -1476,6 +1484,52 @@ void Client::setDesktop( int desktop )
|
||||||
clientGroup()->updateStates( this );
|
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
|
* 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),
|
* 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;
|
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 )
|
void Client::setOnAllDesktops( bool b )
|
||||||
{
|
{
|
||||||
if(( b && isOnAllDesktops() ) ||
|
if(( b && isOnAllDesktops() ) ||
|
||||||
|
@ -1502,6 +1567,33 @@ void Client::setOnAllDesktops( bool b )
|
||||||
clientGroup()->updateStates( this );
|
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
|
* Performs activation and/or raising of the window
|
||||||
*/
|
*/
|
||||||
|
|
5
client.h
5
client.h
|
@ -143,6 +143,10 @@ class Client
|
||||||
void setDesktop( int );
|
void setDesktop( int );
|
||||||
void setOnAllDesktops( bool set );
|
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.
|
/// Is not minimized and not hidden. I.e. normally visible on some virtual desktop.
|
||||||
bool isShown( bool shaded_is_shown ) const;
|
bool isShown( bool shaded_is_shown ) const;
|
||||||
bool isHiddenInternal() const; // For compositing
|
bool isHiddenInternal() const; // For compositing
|
||||||
|
@ -506,6 +510,7 @@ class Client
|
||||||
KDecoration* decoration;
|
KDecoration* decoration;
|
||||||
Bridge* bridge;
|
Bridge* bridge;
|
||||||
int desk;
|
int desk;
|
||||||
|
QStringList activityList;
|
||||||
bool buttonDown;
|
bool buttonDown;
|
||||||
bool moveResizeMode;
|
bool moveResizeMode;
|
||||||
bool move_faked_activity;
|
bool move_faked_activity;
|
||||||
|
|
|
@ -67,6 +67,7 @@ void Deleted::copyToDeleted( Toplevel* c )
|
||||||
assert( dynamic_cast< Deleted* >( c ) == NULL );
|
assert( dynamic_cast< Deleted* >( c ) == NULL );
|
||||||
Toplevel::copyToDeleted( c );
|
Toplevel::copyToDeleted( c );
|
||||||
desk = c->desktop();
|
desk = c->desktop();
|
||||||
|
activityList = c->activities();
|
||||||
contentsRect = QRect( c->clientPos(), c->clientSize());
|
contentsRect = QRect( c->clientPos(), c->clientSize());
|
||||||
transparent_rect = c->transparentRect();
|
transparent_rect = c->transparentRect();
|
||||||
if( WinInfo* cinfo = dynamic_cast< WinInfo* >( info ))
|
if( WinInfo* cinfo = dynamic_cast< WinInfo* >( info ))
|
||||||
|
@ -111,6 +112,11 @@ int Deleted::desktop() const
|
||||||
return desk;
|
return desk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList Deleted::activities() const
|
||||||
|
{
|
||||||
|
return activityList;
|
||||||
|
}
|
||||||
|
|
||||||
QPoint Deleted::clientPos() const
|
QPoint Deleted::clientPos() const
|
||||||
{
|
{
|
||||||
return contentsRect.topLeft();
|
return contentsRect.topLeft();
|
||||||
|
|
|
@ -37,6 +37,7 @@ class Deleted
|
||||||
void unrefWindow( bool delay = false );
|
void unrefWindow( bool delay = false );
|
||||||
void discard( allowed_t );
|
void discard( allowed_t );
|
||||||
virtual int desktop() const;
|
virtual int desktop() const;
|
||||||
|
virtual QStringList activities() const;
|
||||||
virtual QPoint clientPos() const;
|
virtual QPoint clientPos() const;
|
||||||
virtual QSize clientSize() const;
|
virtual QSize clientSize() const;
|
||||||
virtual QRect transparentRect() const;
|
virtual QRect transparentRect() const;
|
||||||
|
@ -58,6 +59,7 @@ class Deleted
|
||||||
int delete_refcount;
|
int delete_refcount;
|
||||||
double window_opacity;
|
double window_opacity;
|
||||||
int desk;
|
int desk;
|
||||||
|
QStringList activityList;
|
||||||
QRect contentsRect; // for clientPos()/clientSize()
|
QRect contentsRect; // for clientPos()/clientSize()
|
||||||
QRect transparent_rect;
|
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 <kdecoration.h>
|
||||||
#include <kdebug.h>
|
#include <kdebug.h>
|
||||||
|
|
||||||
|
#include "kactivityconsumer.h"
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "workspace.h"
|
#include "workspace.h"
|
||||||
|
|
||||||
|
@ -90,9 +92,13 @@ class Toplevel
|
||||||
bool isDNDIcon() const;
|
bool isDNDIcon() const;
|
||||||
|
|
||||||
virtual int desktop() const = 0;
|
virtual int desktop() const = 0;
|
||||||
|
virtual QStringList activities() const = 0;
|
||||||
bool isOnDesktop( int d ) const;
|
bool isOnDesktop( int d ) const;
|
||||||
|
bool isOnActivity( const QString &activity ) const;
|
||||||
bool isOnCurrentDesktop() const;
|
bool isOnCurrentDesktop() const;
|
||||||
|
bool isOnCurrentActivity() const;
|
||||||
bool isOnAllDesktops() const;
|
bool isOnAllDesktops() const;
|
||||||
|
bool isOnAllActivities() const;
|
||||||
|
|
||||||
QByteArray windowRole() const;
|
QByteArray windowRole() const;
|
||||||
QByteArray sessionId();
|
QByteArray sessionId();
|
||||||
|
@ -386,16 +392,31 @@ inline bool Toplevel::isOnAllDesktops() const
|
||||||
return desktop() == NET::OnAllDesktops;
|
return desktop() == NET::OnAllDesktops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool Toplevel::isOnAllActivities() const
|
||||||
|
{
|
||||||
|
return activities().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
inline bool Toplevel::isOnDesktop( int d ) const
|
inline bool Toplevel::isOnDesktop( int d ) const
|
||||||
{
|
{
|
||||||
return desktop() == d || /*desk == 0 ||*/ isOnAllDesktops();
|
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
|
inline bool Toplevel::isOnCurrentDesktop() const
|
||||||
{
|
{
|
||||||
return isOnDesktop( workspace()->currentDesktop());
|
return isOnDesktop( workspace()->currentDesktop());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool Toplevel::isOnCurrentActivity() const
|
||||||
|
{
|
||||||
|
return isOnActivity( KActivityConsumer().currentActivity());
|
||||||
|
}
|
||||||
|
|
||||||
inline QByteArray Toplevel::resourceName() const
|
inline QByteArray Toplevel::resourceName() const
|
||||||
{
|
{
|
||||||
return resource_name; // it is always lowercase
|
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?
|
return NET::OnAllDesktops; // TODO for some window types should be the current desktop?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList Unmanaged::activities() const
|
||||||
|
{
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
QPoint Unmanaged::clientPos() const
|
QPoint Unmanaged::clientPos() const
|
||||||
{
|
{
|
||||||
return QPoint( 0, 0 ); // unmanaged windows don't have decorations
|
return QPoint( 0, 0 ); // unmanaged windows don't have decorations
|
||||||
|
|
|
@ -39,6 +39,7 @@ class Unmanaged
|
||||||
bool track( Window w );
|
bool track( Window w );
|
||||||
static void deleteUnmanaged( Unmanaged* c, allowed_t );
|
static void deleteUnmanaged( Unmanaged* c, allowed_t );
|
||||||
virtual int desktop() const;
|
virtual int desktop() const;
|
||||||
|
virtual QStringList activities() const;
|
||||||
virtual QPoint clientPos() const;
|
virtual QPoint clientPos() const;
|
||||||
virtual QSize clientSize() const;
|
virtual QSize clientSize() const;
|
||||||
virtual QRect transparentRect() 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 "tile.h"
|
||||||
#include "tilinglayout.h"
|
#include "tilinglayout.h"
|
||||||
|
|
||||||
|
#include "kactivityinfo.h"
|
||||||
|
|
||||||
#include <fixx11h.h>
|
#include <fixx11h.h>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QSlider>
|
#include <QSlider>
|
||||||
|
@ -237,6 +239,7 @@ void Workspace::discardPopup()
|
||||||
delete popup;
|
delete popup;
|
||||||
popup = NULL;
|
popup = NULL;
|
||||||
desk_popup = NULL;
|
desk_popup = NULL;
|
||||||
|
activity_popup = NULL;
|
||||||
switch_to_tab_popup = NULL;
|
switch_to_tab_popup = NULL;
|
||||||
add_tabs_popup = NULL;
|
add_tabs_popup = NULL;
|
||||||
}
|
}
|
||||||
|
@ -268,6 +271,17 @@ void Workspace::clientPopupAboutToShow()
|
||||||
{
|
{
|
||||||
initDesktopPopup();
|
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() );
|
mResizeOpAction->setEnabled( active_popup_client->isResizable() );
|
||||||
mMoveOpAction->setEnabled( active_popup_client->isMovableAcrossScreens() );
|
mMoveOpAction->setEnabled( active_popup_client->isMovableAcrossScreens() );
|
||||||
|
@ -455,6 +469,29 @@ void Workspace::initDesktopPopup()
|
||||||
action->setText( i18n("To &Desktop") );
|
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
|
Adjusts the desktop popup to the current values and the location of
|
||||||
the popup client.
|
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()
|
void Workspace::closeActivePopup()
|
||||||
{
|
{
|
||||||
if( active_popup )
|
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
|
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 )
|
, advanced_popup( 0 )
|
||||||
, trans_popup( 0 )
|
, trans_popup( 0 )
|
||||||
, desk_popup( 0 )
|
, desk_popup( 0 )
|
||||||
|
, activity_popup( 0 )
|
||||||
, add_tabs_popup( 0 )
|
, add_tabs_popup( 0 )
|
||||||
, switch_to_tab_popup( 0 )
|
, switch_to_tab_popup( 0 )
|
||||||
, keys( 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( screenRemoved(int) ), SLOT( desktopResized() ));
|
||||||
connect( Kephal::Screens::self(), SIGNAL( screenResized(Kephal::Screen*, QSize, QSize) ), 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( Kephal::Screens::self(), SIGNAL( screenMoved(Kephal::Screen*, QPoint, QPoint) ), SLOT( desktopResized() ));
|
||||||
|
|
||||||
|
connect( &activityController_, SIGNAL( currentActivityChanged(QString) ), SLOT( updateCurrentActivity(QString) ));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::init()
|
void Workspace::init()
|
||||||
|
@ -1514,6 +1517,135 @@ bool Workspace::setCurrentDesktop( int new_desktop )
|
||||||
return true;
|
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
|
* Called only from D-Bus
|
||||||
*/
|
*/
|
||||||
|
@ -1631,6 +1763,46 @@ void Workspace::sendClientToDesktop( Client* c, int desk, bool dont_activate )
|
||||||
updateClientArea();
|
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
|
int Workspace::numScreens() const
|
||||||
{
|
{
|
||||||
if( !options->xineramaEnabled )
|
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 <QDateTime>
|
||||||
#include <kmanagerselection.h>
|
#include <kmanagerselection.h>
|
||||||
|
|
||||||
|
#include "kactivitycontroller.h"
|
||||||
|
|
||||||
#include "plugins.h"
|
#include "plugins.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "kdecoration.h"
|
#include "kdecoration.h"
|
||||||
|
@ -312,8 +314,11 @@ class Workspace : public QObject, public KDecorationDefines
|
||||||
QSize desktopGridSize_;
|
QSize desktopGridSize_;
|
||||||
int* desktopGrid_;
|
int* desktopGrid_;
|
||||||
int currentDesktop_;
|
int currentDesktop_;
|
||||||
|
QString activity_;
|
||||||
bool desktopLayoutDynamicity_;
|
bool desktopLayoutDynamicity_;
|
||||||
|
|
||||||
|
KActivityController activityController_;
|
||||||
|
|
||||||
bool tilingEnabled_;
|
bool tilingEnabled_;
|
||||||
// Each tilingLayout is for one virtual desktop.
|
// Each tilingLayout is for one virtual desktop.
|
||||||
// The length is always one more than the number of
|
// 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;
|
bool only_normal = true ) const;
|
||||||
Client* findDesktop( bool topmost, int desktop ) const;
|
Client* findDesktop( bool topmost, int desktop ) const;
|
||||||
void sendClientToDesktop( Client* c, int desktop, bool dont_activate );
|
void sendClientToDesktop( Client* c, int desktop, bool dont_activate );
|
||||||
|
void toggleClientOnActivity( Client* c, const QString &activity, bool dont_activate );
|
||||||
void windowToPreviousDesktop( Client* c );
|
void windowToPreviousDesktop( Client* c );
|
||||||
void windowToNextDesktop( Client* c );
|
void windowToNextDesktop( Client* c );
|
||||||
void sendClientToScreen( Client* c, int screen );
|
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 slotAddToTabGroup( QAction* ); // Add client to a group
|
||||||
void slotSwitchToTab( QAction* ); // Change the tab
|
void slotSwitchToTab( QAction* ); // Change the tab
|
||||||
void desktopPopupAboutToShow();
|
void desktopPopupAboutToShow();
|
||||||
|
void activityPopupAboutToShow();
|
||||||
void clientPopupAboutToShow();
|
void clientPopupAboutToShow();
|
||||||
void slotSendToDesktop( QAction* );
|
void slotSendToDesktop( QAction* );
|
||||||
|
void slotToggleOnActivity( QAction* );
|
||||||
void clientPopupActivated( QAction* );
|
void clientPopupActivated( QAction* );
|
||||||
void configureWM();
|
void configureWM();
|
||||||
void desktopResized();
|
void desktopResized();
|
||||||
|
@ -747,6 +755,8 @@ class Workspace : public QObject, public KDecorationDefines
|
||||||
void resetCursorPosTime();
|
void resetCursorPosTime();
|
||||||
void delayedCheckUnredirect();
|
void delayedCheckUnredirect();
|
||||||
|
|
||||||
|
void updateCurrentActivity(const QString &activity);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool keyPressMouseEmulation( XKeyEvent& ev );
|
bool keyPressMouseEmulation( XKeyEvent& ev );
|
||||||
|
|
||||||
|
@ -758,6 +768,7 @@ class Workspace : public QObject, public KDecorationDefines
|
||||||
void initShortcuts();
|
void initShortcuts();
|
||||||
void readShortcuts();
|
void readShortcuts();
|
||||||
void initDesktopPopup();
|
void initDesktopPopup();
|
||||||
|
void initActivityPopup();
|
||||||
void discardPopup();
|
void discardPopup();
|
||||||
void setupWindowShortcut( Client* c );
|
void setupWindowShortcut( Client* c );
|
||||||
void checkCursorPos();
|
void checkCursorPos();
|
||||||
|
@ -930,6 +941,7 @@ class Workspace : public QObject, public KDecorationDefines
|
||||||
QMenu* trans_popup;
|
QMenu* trans_popup;
|
||||||
QActionGroup* trans_popup_group;
|
QActionGroup* trans_popup_group;
|
||||||
QMenu* desk_popup;
|
QMenu* desk_popup;
|
||||||
|
QMenu* activity_popup;
|
||||||
QMenu* add_tabs_popup; // Menu to add the group to other group
|
QMenu* add_tabs_popup; // Menu to add the group to other group
|
||||||
QMenu* switch_to_tab_popup; // Menu to change tab
|
QMenu* switch_to_tab_popup; // Menu to change tab
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue