--- kdebase-3.2/kwin/activation.cpp-- 2004-02-26 13:12:33.000000000 +0100 +++ kdebase-3.2/kwin/activation.cpp 2004-03-03 10:10:13.000000000 +0100 @@ -25,6 +25,7 @@ License. See the file "COPYING" for the #include "notifications.h" #include "atoms.h" +#include "group.h" extern Time qt_x_time; @@ -419,7 +420,7 @@ bool Workspace::allowClientActivation( c // or when no window is currently active // 4 - extreme - no window gets focus without user intervention if( session_saving - && options->focusStealingPreventionLevel <= 3 ) // <= normal + && options->focusStealingPreventionLevel <= 2 ) // <= normal { return true; } @@ -434,7 +435,7 @@ bool Workspace::allowClientActivation( c } if( options->focusStealingPreventionLevel == 0 ) // none return true; - if( options->focusStealingPreventionLevel == 5 ) // extreme + if( options->focusStealingPreventionLevel == 4 ) // extreme return false; if( ac == NULL || ac->isDesktop()) { @@ -451,7 +452,7 @@ bool Workspace::allowClientActivation( c kdDebug( 1212 ) << "Activation: Belongs to active application" << endl; return true; } - if( options->focusStealingPreventionLevel == 4 ) // high + if( options->focusStealingPreventionLevel == 3 ) // high return false; if( time == -1U ) // no time known if( session_active ) @@ -480,14 +481,14 @@ bool Workspace::allowClientActivation( c bool Workspace::allowFullClientRaising( const Client* c ) { if( session_saving - && options->focusStealingPreventionLevel <= 3 ) // <= normal + && options->focusStealingPreventionLevel <= 2 ) // <= normal { return true; } Client* ac = mostRecentlyActivatedClient(); if( options->focusStealingPreventionLevel == 0 ) // none return true; - if( options->focusStealingPreventionLevel == 5 ) // extreme + if( options->focusStealingPreventionLevel == 4 ) // extreme return false; if( ac == NULL || ac->isDesktop()) { @@ -502,7 +503,7 @@ bool Workspace::allowFullClientRaising( kdDebug( 1212 ) << "Raising: Belongs to active application" << endl; return true; } - if( options->focusStealingPreventionLevel == 4 ) // high + if( options->focusStealingPreventionLevel == 3 ) // high return false; if( !c->hasUserTimeSupport()) { @@ -579,7 +580,7 @@ void Workspace::unfakeActivity( Client* externally, etc.). */ void Client::updateUserTime( Time time ) - { + { // copied in Group::updateUserTime if( time == CurrentTime ) time = qt_x_time; if( time != -1U @@ -688,6 +689,16 @@ Time Client::readUserTimeMapTimestamp( c return time; } +Time Client::userTime() const + { + Time time = user_time; + assert( group() != NULL ); + if( time == -1U + || ( group()->userTime() != -1U + && timestampCompare( group()->userTime(), time ) > 0 )) + time = group()->userTime(); + return time; + } /*! Sets the client's active state to \a act. @@ -734,7 +745,7 @@ void Client::setActive( bool act) void Client::startupIdChanged() { KStartupInfoData asn_data; - bool asn_valid = workspace()->checkStartupNotification( this, asn_data ); + bool asn_valid = workspace()->checkStartupNotification( window(), asn_data ); if( !asn_valid ) return; if( asn_data.desktop() != 0 ) @@ -756,5 +767,30 @@ void Client::updateUrgency() if( urgency ) demandAttention(); } + +//**************************************** +// Group +//**************************************** +void Group::startupIdChanged() + { + KStartupInfoData asn_data; + bool asn_valid = workspace()->checkStartupNotification( leader_wid, asn_data ); + if( !asn_valid ) + return; + if( asn_data.timestamp() != -1U && user_time != -1U + &×tampCompare( asn_data.timestamp(), user_time ) > 0 ) + user_time = asn_data.timestamp(); + } + +void Group::updateUserTime( Time time ) + { // copy of Client::updateUserTime + if( time == CurrentTime ) + time = qt_x_time; + if( time != -1U + && ( user_time == CurrentTime + || timestampCompare( time, user_time ) > 0 )) // time > user_time + user_time = time; + } + } // namespace --- kdebase-3.2/kwin/client.cpp-- 2004-02-26 13:12:33.000000000 +0100 +++ kdebase-3.2/kwin/client.cpp 2004-03-03 10:10:17.000000000 +0100 @@ -903,6 +903,11 @@ void Client::closeWindow() { if( !isCloseable()) return; + // Update user time, needed for whole group, because the window may create a confirming dialog, + // and this window's user time wouldn't apply to it + // This is needed even for apps without support for user timestamp (e.g. nedit), so updating + // user timestamp in apps on WM_DELETE_WINDOW is not an option (and I'm not sure if it would be right) + group()->updateUserTime(); if ( Pdeletewindow ) { Notify::raise( Notify::Close ); @@ -1060,6 +1065,8 @@ void Client::toggleOnAllDesktops() void Client::setDesktop( int desktop ) { + if( desktop != NET::OnAllDesktops ) // do range check + desktop = KMAX( 1, KMIN( workspace()->numberOfDesktops(), desktop )); if( desk == desktop ) return; int was_desk = desk; --- kdebase-3.2/kwin/client.h-- 2004-02-26 13:12:33.000000000 +0100 +++ kdebase-3.2/kwin/client.h 2004-03-03 10:10:17.000000000 +0100 @@ -734,14 +734,6 @@ inline bool Client::isManaged() const return mapping_state != WithdrawnState; } -inline -Time Client::userTime() const - { - assert( user_time != CurrentTime ); - assert( user_time != -1U ); - return user_time; - } - inline QCString Client::windowRole() const { return window_role; --- kdebase-3.2/kwin/events.cpp-- 2004-02-26 13:12:33.000000000 +0100 +++ kdebase-3.2/kwin/events.cpp 2004-03-03 10:10:23.000000000 +0100 @@ -19,6 +19,7 @@ License. See the file "COPYING" for the #include "workspace.h" #include "atoms.h" #include "tabbox.h" +#include "group.h" #include <qwhatsthis.h> #include <kkeynative.h> @@ -1448,5 +1449,20 @@ void Client::keyPressEvent( uint key_cod QCursor::setPos( pos ); } +// **************************************** +// Group +// **************************************** + +bool Group::groupEvent( XEvent* e ) + { + unsigned long dirty[ 2 ]; + leader_info->event( e, dirty, 2 ); // pass through the NET stuff + if ( ( dirty[ WinInfo::PROTOCOLS ] & NET::WMIcon) != 0 ) + getIcons(); + if(( dirty[ WinInfo::PROTOCOLS2 ] & NET::WM2StartupId ) != 0 ) + startupIdChanged(); + return false; + } + } // namespace --- kdebase-3.2/kwin/group.cpp-- 2004-02-26 13:12:33.000000000 +0100 +++ kdebase-3.2/kwin/group.cpp 2004-03-03 10:10:27.000000000 +0100 @@ -21,7 +21,10 @@ License. See the file "COPYING" for the #include "workspace.h" #include "client.h" + #include <assert.h> +#include <kstartupinfo.h> + /* TODO @@ -37,13 +40,27 @@ namespace KWinInternal //******************************************** Group::Group( Window leader_P, Workspace* workspace_P ) - : leader_client( workspace_P->findClient( WindowMatchPredicate( leader_P ))), + : leader_client( NULL ), leader_wid( leader_P ), - workspace_( workspace_P ) - { + _workspace( workspace_P ), + leader_info( NULL ), + user_time( -1U ) + { + if( leader_P != None ) + { + leader_client = workspace_P->findClient( WindowMatchPredicate( leader_P )); + unsigned long properties[ 2 ] = { 0, NET::WM2StartupId }; + leader_info = new NETWinInfo( qt_xdisplay(), leader_P, workspace()->rootWin(), + properties, 2 ); + } workspace()->addGroup( this, Allowed ); } +Group::~Group() + { + delete leader_info; + } + QPixmap Group::icon() const { if( leader_client != NULL ) @@ -107,6 +124,10 @@ void Group::lostLeader() } } +void Group::getIcons() + { + // TODO - also needs adding the flag to NETWinInfo + } //*************************************** // Workspace --- kdebase-3.2/kwin/group.h-- 2004-02-26 13:12:33.000000000 +0100 +++ kdebase-3.2/kwin/group.h 2004-03-03 10:10:27.000000000 +0100 @@ -14,6 +14,7 @@ License. See the file "COPYING" for the #include "utils.h" #include <X11/X.h> +#include <netwm.h> namespace KWinInternal { @@ -25,6 +26,7 @@ class Group { public: Group( Window leader, Workspace* workspace ); + ~Group(); Window leader() const; const Client* leaderClient() const; Client* leaderClient(); @@ -36,11 +38,18 @@ class Group void gotLeader( Client* leader ); void lostLeader(); Workspace* workspace(); + bool groupEvent( XEvent* e ); + void updateUserTime( Time time = CurrentTime ); + Time userTime() const; private: + void getIcons(); + void startupIdChanged(); ClientList _members; Client* leader_client; Window leader_wid; - Workspace* workspace_; + Workspace* _workspace; + NETWinInfo* leader_info; + Time user_time; }; inline Window Group::leader() const @@ -65,7 +74,12 @@ inline const ClientList& Group::members( inline Workspace* Group::workspace() { - return workspace_; + return _workspace; + } + +inline Time Group::userTime() const + { + return user_time; } } // namespace --- kdebase-3.2/kwin/layers.cpp-- 2004-02-26 13:12:33.000000000 +0100 +++ kdebase-3.2/kwin/layers.cpp 2004-03-03 10:10:32.000000000 +0100 @@ -350,29 +350,22 @@ void Workspace::raiseClientWithinApplica StackingUpdatesBlocker blocker( this ); // ignore mainwindows - bool raised = false; - bool is_above_active = false; - bool was_active = false; // first try to put it above the top-most window of the application for( ClientList::Iterator it = unconstrained_stacking_order.fromLast(); it != unconstrained_stacking_order.end(); --it ) { - if( (*it)->isActive()) - was_active = true; - if( Client::belongToSameApplication( *it, c ) && (*it) != c ) + if( *it == c ) // don't lower it just because it asked to be raised + return; + if( Client::belongToSameApplication( *it, c )) { unconstrained_stacking_order.remove( c ); ++it; // insert after the found one unconstrained_stacking_order.insert( it, c ); - raised = true; - break; + return; } - if( *it == c && !was_active ) // if it is already above the active one for some reason, - is_above_active = true; // don't put it lower just because it asked to be raised } - if( !raised && !is_above_active ) - restackClientUnderActive( c ); + restackClientUnderActive( c ); } void Workspace::raiseClientRequest( Client* c ) --- kdebase-3.2/kwin/manage.cpp-- 2004-02-26 13:12:33.000000000 +0100 +++ kdebase-3.2/kwin/manage.cpp 2004-03-03 10:10:36.000000000 +0100 @@ -18,6 +18,7 @@ License. See the file "COPYING" for the #include "client.h" #include <kstartupinfo.h> +#include <kglobal.h> #include <X11/extensions/shape.h> #include "notifications.h" @@ -127,7 +128,7 @@ bool Client::manage( Window w, bool isMa keep_above = keep_below = false; KStartupInfoData asn_data; - bool asn_valid = workspace()->checkStartupNotification( this, asn_data ); + bool asn_valid = workspace()->checkStartupNotification( window(), asn_data ); workspace()->updateClientLayer( this ); @@ -180,6 +181,8 @@ bool Client::manage( Window w, bool isMa } if ( desk == 0 ) // assume window wants to be visible on the current desktop desk = workspace()->currentDesktop(); + if( desk != NET::OnAllDesktops ) // do range check + desk = KMAX( 1, KMIN( workspace()->numberOfDesktops(), desk )); info->setDesktop( desk ); workspace()->updateOnAllDesktopsOfTransients( this ); // SELI // onAllDesktopsChange(); decoration doesn't exist here yet @@ -426,7 +429,7 @@ bool Client::manage( Window w, bool isMa } else { - if( workspace()->allowClientActivation( this, user_time, false, session && session->active )) + if( workspace()->allowClientActivation( this, userTime(), false, session && session->active )) { workspace()->raiseClient( this ); rawShow(); --- kdebase-3.2/kwin/workspace.cpp-- 2004-03-03 10:06:03.000000000 +0100 +++ kdebase-3.2/kwin/workspace.cpp 2004-03-03 10:10:40.000000000 +0100 @@ -787,7 +787,7 @@ void Workspace::loadDesktopSettings() groupname.sprintf("Desktops-screen-%d", screen_number); c.setGroup(groupname); - int n = c.readNumEntry("Number", 2); + int n = c.readNumEntry("Number", 4); number_of_desktops = n; delete workarea; workarea = new QRect[ n + 1 ]; @@ -1155,6 +1155,7 @@ void Workspace::sendClientToDesktop( Cli bool was_on_desktop = c->isOnDesktop( desk ) || c->isOnAllDesktops(); c->setDesktop( desk ); + desk = c->desktop(); // Client did range checking if ( c->isOnDesktop( currentDesktop() ) ) { @@ -1936,9 +1937,9 @@ QString Workspace::desktopName( int desk return QString::fromUtf8( rootInfo->desktopName( desk ) ); } -bool Workspace::checkStartupNotification( const Client* c, KStartupInfoData& data ) +bool Workspace::checkStartupNotification( Window w, KStartupInfoData& data ) { - return startup->checkStartup( c->window(), data ) == KStartupInfo::Match; + return startup->checkStartup( w, data ) == KStartupInfo::Match; } /*! --- kdebase-3.2/kwin/workspace.h-- 2004-02-26 13:12:33.000000000 +0100 +++ kdebase-3.2/kwin/workspace.h 2004-03-03 10:10:40.000000000 +0100 @@ -218,7 +218,7 @@ class Workspace : public QObject, public // only called from Client::destroyClient() or Client::releaseWindow() void removeClient( Client*, allowed_t ); - bool checkStartupNotification( const Client* c, KStartupInfoData& data ); + bool checkStartupNotification( Window w, KStartupInfoData& data ); void focusToNull(); // SELI public?