71 #include "workspace.h"
76 namespace KWinInternal
83 void Workspace::updateClientLayer( Client* c )
87 if( c->layer() == c->belongsToLayer())
89 StackingUpdatesBlocker blocker(
this );
91 for( ClientList::ConstIterator it = c->transients().begin();
92 it != c->transients().end();
94 updateClientLayer( *it );
97 void Workspace::updateStackingOrder(
bool propagate_new_clients )
99 if( block_stacking_updates > 0 )
101 blocked_propagating_new_clients = blocked_propagating_new_clients || propagate_new_clients;
104 ClientList new_stacking_order = constrainedStackingOrder();
105 bool changed = ( new_stacking_order != stacking_order );
106 stacking_order = new_stacking_order;
108 kdDebug() <<
"stacking:" << changed << endl;
109 if( changed || propagate_new_clients )
111 for( ClientList::ConstIterator it = stacking_order.begin();
112 it != stacking_order.end();
114 kdDebug() << (
void*)(*it) << *it <<
":" << (*it)->layer() << endl;
117 if( changed || propagate_new_clients )
119 propagateClients( propagate_new_clients );
121 active_client->updateMouseGrab();
129 void Workspace::propagateClients(
bool propagate_new_clients )
137 Window *dock_shadow_stack, *window_stack;
138 int i, numDocks, pos, topmenu_space_pos;
143 dock_shadow_stack =
new Window[ stacking_order.count() * 2 ];
150 window_stack =
new Window[ stacking_order.count() * 2 + 1 + 1 + 8 ];
153 topmenu_space_pos = 1;
161 for (
int i = 0; i < ACTIVE_BORDER_COUNT; ++i)
163 if (active_windows[i] != None)
165 window_stack[pos++] = active_windows[i];
170 window_stack[pos++] = supportWindow->winId();
171 for( ClientList::ConstIterator it = stacking_order.fromLast();
172 it != stacking_order.end();
176 t = (*it)->windowType();
180 window_stack[pos++] = (*it)->frameId();
181 if ((shadow = (*it)->shadowId()) != None)
182 dock_shadow_stack[i++] = shadow;
186 for (i = 0; i < numDocks; i++)
188 window_stack[pos++] = dock_shadow_stack[i];
189 window_stack[pos++] = (*it)->frameId();
192 topmenu_space_pos = pos;
195 window_stack[pos++] = (*it)->frameId();
196 if ((shadow = (*it)->shadowId()) != None)
199 window_stack[pos++] = shadow;
202 if( topmenu_space != NULL )
205 i > topmenu_space_pos;
208 new_stack[ i ] = new_stack[ i - 1 ];
209 new_stack[ topmenu_space_pos ] = topmenu_space->winId();
211 window_stack[ i ] = window_stack[ i - 1 ];
212 window_stack[ topmenu_space_pos ] = topmenu_space->winId();
218 assert( new_stack[ 0 ] = supportWindow->winId());
220 XRestackWindows(tqt_xdisplay(), new_stack, pos);
223 XRestackWindows(tqt_xdisplay(), window_stack, pos);
224 delete [] dock_shadow_stack;
225 delete [] window_stack;
227 if ( propagate_new_clients )
229 cl =
new Window[ desktops.count() + clients.count()];
232 for ( ClientList::ConstIterator it = desktops.begin(); it != desktops.end(); ++it )
233 cl[pos++] = (*it)->window();
234 for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it )
235 cl[pos++] = (*it)->window();
236 rootInfo->setClientList( cl, pos );
240 cl =
new Window[ stacking_order.count()];
242 for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it)
243 cl[pos++] = (*it)->window();
244 rootInfo->setClientListStacking( cl, pos );
255 Client* Workspace::topClientOnDesktop(
int desktop,
bool unconstrained,
bool only_normal )
const
258 ClientList::ConstIterator begin, end;
261 begin = stacking_order.fromLast();
262 end = stacking_order.end();
266 begin = unconstrained_stacking_order.fromLast();
267 end = unconstrained_stacking_order.end();
269 for( ClientList::ConstIterator it = begin;
273 if( (*it)->isOnDesktop( desktop ) && (*it)->isShown(
false ))
277 if( (*it)->wantsTabFocus() && !(*it)->isSpecialWindow())
284 Client* Workspace::findDesktop(
bool topmost,
int desktop )
const
289 for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it)
291 if ( (*it)->isOnDesktop( desktop ) && (*it)->isDesktop()
292 && (*it)->isShown(
true ))
298 for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it)
300 if ( (*it)->isOnDesktop( desktop ) && (*it)->isDesktop()
301 && (*it)->isShown(
true ))
308 void Workspace::raiseOrLowerClient( Client *c)
311 Client* topmost = NULL;
313 if ( most_recently_raised && stacking_order.contains( most_recently_raised ) &&
314 most_recently_raised->isShown(
true ) && c->isOnCurrentDesktop())
315 topmost = most_recently_raised;
317 topmost = topClientOnDesktop( c->isOnAllDesktops() ? currentDesktop() : c->desktop());
326 void Workspace::lowerClient( Client* c )
333 c->cancelAutoRaise();
335 StackingUpdatesBlocker blocker(
this );
337 unconstrained_stacking_order.remove( c );
338 unconstrained_stacking_order.prepend( c );
339 if( c->isTransient())
342 ClientList mainclients = ensureStackingOrder( c->mainClients());
343 for( ClientList::ConstIterator it = mainclients.fromLast();
344 it != mainclients.end();
349 if ( c == most_recently_raised )
350 most_recently_raised = 0;
353 void Workspace::lowerClientWithinApplication( Client* c )
360 c->cancelAutoRaise();
362 StackingUpdatesBlocker blocker(
this );
364 unconstrained_stacking_order.remove( c );
365 bool lowered =
false;
367 for( ClientList::Iterator it = unconstrained_stacking_order.begin();
368 it != unconstrained_stacking_order.end();
370 if( Client::belongToSameApplication( *it, c ))
372 unconstrained_stacking_order.insert( it, c );
377 unconstrained_stacking_order.prepend( c );
381 void Workspace::raiseClient( Client* c )
388 c->cancelAutoRaise();
390 StackingUpdatesBlocker blocker(
this );
392 if( c->isTransient())
394 ClientList mainclients = ensureStackingOrder( c->mainClients());
395 for( ClientList::ConstIterator it = mainclients.begin();
396 it != mainclients.end();
401 unconstrained_stacking_order.remove( c );
402 unconstrained_stacking_order.append( c );
403 if (options->shadowEnabled(c->isActive()))
406 c->drawDelayedShadow();
409 if( !c->isSpecialWindow())
411 most_recently_raised = c;
412 pending_take_activity = NULL;
416 void Workspace::raiseClientWithinApplication( Client* c )
423 c->cancelAutoRaise();
425 StackingUpdatesBlocker blocker(
this );
429 for( ClientList::Iterator it = unconstrained_stacking_order.fromLast();
430 it != unconstrained_stacking_order.end();
435 if( Client::belongToSameApplication( *it, c ))
437 unconstrained_stacking_order.remove( c );
439 unconstrained_stacking_order.insert( it, c );
445 void Workspace::raiseClientRequest( Client* c, NET::RequestSource src, Time timestamp )
447 if( src == NET::FromTool || allowFullClientRaising( c, timestamp ))
451 raiseClientWithinApplication( c );
452 c->demandAttention();
456 void Workspace::lowerClientRequest( Client* c, NET::RequestSource src, Time )
462 if( src == NET::FromTool || !c->hasUserTimeSupport())
465 lowerClientWithinApplication( c );
468 void Workspace::restackClientUnderActive( Client* c )
472 if( !active_client || active_client == c )
478 assert( unconstrained_stacking_order.contains( active_client ));
479 if( Client::belongToSameApplication( active_client, c ))
481 unconstrained_stacking_order.remove( c );
482 unconstrained_stacking_order.insert( unconstrained_stacking_order.find( active_client ), c );
486 for( ClientList::Iterator it = unconstrained_stacking_order.begin();
487 it != unconstrained_stacking_order.end();
490 if( Client::belongToSameApplication( active_client, *it ))
494 unconstrained_stacking_order.remove( c );
495 unconstrained_stacking_order.insert( it, c );
501 assert( unconstrained_stacking_order.contains( c ));
502 for(
int desktop = 1;
503 desktop <= numberOfDesktops();
506 if( c->wantsTabFocus() && c->isOnDesktop( desktop ) && focus_chain[ desktop ].contains( active_client ))
508 if( Client::belongToSameApplication( active_client, c ))
510 focus_chain[ desktop ].remove( c );
511 focus_chain[ desktop ].insert( focus_chain[ desktop ].find( active_client ), c );
515 focus_chain[ desktop ].remove( c );
516 for( ClientList::Iterator it = focus_chain[ desktop ].fromLast();
517 it != focus_chain[ desktop ].end();
520 if( Client::belongToSameApplication( active_client, *it ))
522 focus_chain[ desktop ].insert( it, c );
530 if( c->wantsTabFocus() && global_focus_chain.contains( active_client ))
532 if( Client::belongToSameApplication( active_client, c ))
534 global_focus_chain.remove( c );
535 global_focus_chain.insert( global_focus_chain.find( active_client ), c );
539 global_focus_chain.remove( c );
540 for( ClientList::Iterator it = global_focus_chain.fromLast();
541 it != global_focus_chain.end();
544 if( Client::belongToSameApplication( active_client, *it ))
546 global_focus_chain.insert( it, c );
552 updateStackingOrder();
555 void Workspace::circulateDesktopApplications()
557 if ( desktops.count() > 1 )
559 bool change_active = activeClient()->isDesktop();
560 raiseClient( findDesktop(
false, currentDesktop()));
562 activateClient( findDesktop(
true, currentDesktop()));
565 if( desktops.count() > 0 && activeClient() == NULL && should_get_focus.count() == 0 )
566 activateClient( findDesktop(
true, currentDesktop()));
573 ClientList Workspace::constrainedStackingOrder()
575 ClientList layer[ NumLayers ];
578 kdDebug() <<
"stacking1:" << endl;
581 TQMap< Group*, Layer > minimum_layer;
582 for( ClientList::ConstIterator it = unconstrained_stacking_order.begin();
583 it != unconstrained_stacking_order.end();
586 Layer l = (*it)->layer();
590 if( minimum_layer.contains( (*it)->group())
591 && minimum_layer[ (*it)->group() ] == ActiveLayer
592 && ( l == NormalLayer || l == AboveLayer ))
594 l = minimum_layer[ (*it)->group() ];
596 minimum_layer[ (*it)->group() ] = l;
597 layer[ l ].append( *it );
600 for( Layer lay = FirstLayer;
603 stacking += layer[ lay ];
605 kdDebug() <<
"stacking2:" << endl;
606 for( ClientList::ConstIterator it = stacking.begin();
607 it != stacking.end();
609 kdDebug() << (
void*)(*it) << *it <<
":" << (*it)->layer() << endl;
613 for( ClientList::Iterator it = stacking.fromLast();
614 it != stacking.end();
617 if( !(*it)->isTransient())
622 ClientList::Iterator it2 = stacking.end();
623 if( (*it)->groupTransient())
625 if( (*it)->group()->members().count() > 0 )
627 for( it2 = stacking.fromLast();
628 it2 != stacking.end();
633 it2 = stacking.end();
636 if( (*it2)->hasTransient( *it,
true ) && keepTransientAbove( *it2, *it ))
643 for( it2 = stacking.fromLast();
644 it2 != stacking.end();
649 it2 = stacking.end();
652 if( *it2 == (*it)->transientFor() && keepTransientAbove( *it2, *it ))
657 if( it2 == stacking.end())
662 Client* current = *it;
663 ClientList::Iterator remove_it = it;
665 stacking.remove( remove_it );
666 if( !current->transients().isEmpty())
669 stacking.insert( it2, current );
672 kdDebug() <<
"stacking3:" << endl;
673 for( ClientList::ConstIterator it = stacking.begin();
674 it != stacking.end();
676 kdDebug() << (
void*)(*it) << *it <<
":" << (*it)->layer() << endl;
677 kdDebug() <<
"\n\n" << endl;
682 void Workspace::blockStackingUpdates(
bool block )
686 if( block_stacking_updates == 0 )
687 blocked_propagating_new_clients =
false;
688 ++block_stacking_updates;
691 if( --block_stacking_updates == 0 )
692 updateStackingOrder( blocked_propagating_new_clients );
696 ClientList Workspace::ensureStackingOrder(
const ClientList& list )
const
699 if( list.count() < 2 )
702 ClientList result = list;
703 for( ClientList::ConstIterator it = stacking_order.begin();
704 it != stacking_order.end();
706 if( result.remove( *it ) != 0 )
707 result.append( *it );
713 bool Workspace::keepTransientAbove(
const Client* mainwindow,
const Client*
transient )
719 if( mainwindow->isTopMenu() && transient->groupTransient())
722 if( transient->isSplash() && mainwindow->isDialog())
728 if( transient->isDialog() && !transient->isModal() && transient->groupTransient())
732 if( mainwindow->isDock())
741 void Client::restackWindow( Window ,
int detail, NET::RequestSource src, Time timestamp,
bool send_event )
747 workspace()->raiseClientRequest(
this, src, timestamp );
751 workspace()->lowerClientRequest(
this, src, timestamp );
758 sendSyntheticConfigureNotify();
761 void Client::setKeepAbove(
bool b )
763 b = rules()->checkKeepAbove( b );
764 if( b && !rules()->checkKeepBelow(
false ))
765 setKeepBelow(
false );
768 if(
bool( info->state() & NET::KeepAbove ) !=
keepAbove())
769 info->setState(
keepAbove() ? NET::KeepAbove : 0, NET::KeepAbove );
773 info->setState(
keepAbove() ? NET::KeepAbove : 0, NET::KeepAbove );
774 if( decoration != NULL )
775 decoration->emitKeepAboveChanged(
keepAbove());
776 workspace()->updateClientLayer(
this );
780 void Client::setKeepBelow(
bool b )
782 b = rules()->checkKeepBelow( b );
783 if( b && !rules()->checkKeepAbove(
false ))
784 setKeepAbove(
false );
785 if ( b == keepBelow())
787 if(
bool( info->state() & NET::KeepBelow ) != keepBelow())
788 info->setState( keepBelow() ? NET::KeepBelow : 0, NET::KeepBelow );
792 info->setState( keepBelow() ? NET::KeepBelow : 0, NET::KeepBelow );
793 if( decoration != NULL )
794 decoration->emitKeepBelowChanged( keepBelow());
795 workspace()->updateClientLayer(
this );
799 Layer Client::layer()
const
801 if( in_layer == UnknownLayer )
802 const_cast< Client*
>( this )->in_layer = belongsToLayer();
806 Layer Client::belongsToLayer()
const
812 if( isDock() && keepBelow())
819 if( isDock() && !keepBelow())
825 const Client* ac = workspace()->mostRecentlyActivatedClient();
826 const Client* top = workspace()->topClientOnDesktop(
desktop(),
true,
false );
827 if( isFullScreen() && ac != NULL && top != NULL
828 && ( ac ==
this || this->group() == ac->group())
829 && ( top ==
this || this->group() == top->group()))