14 #include "workspace.h"
16 #include <kapplication.h>
17 #include <kstartupinfo.h>
21 #include <tqpopupmenu.h>
24 #include <tqpainter.h>
26 #include <tqclipboard.h>
29 #include <kglobalaccel.h>
30 #include <dcopclient.h>
35 #include "popupinfo.h"
38 #include "placement.h"
39 #include "notifications.h"
43 #include <X11/extensions/shape.h>
44 #include <X11/keysym.h>
45 #include <X11/keysymdef.h>
46 #include <X11/cursorfont.h>
50 namespace KWinInternal
53 extern int screen_number;
55 Workspace *Workspace::_self = 0;
57 KProcess* kompmgr = 0;
58 KSelectionOwner* kompmgr_selection;
60 bool allowKompmgrRestart = TRUE;
61 extern bool disable_kwin_composition_manager;
63 bool supportsCompMgr()
65 if (disable_kwin_composition_manager) {
71 bool damageExt = XQueryExtension(qt_xdisplay(),
"DAMAGE", &i, &i, &i);
72 bool compositeExt = XQueryExtension(qt_xdisplay(),
"Composite", &i, &i, &i);
73 bool xfixesExt = XQueryExtension(qt_xdisplay(),
"XFIXES", &i, &i, &i);
75 return damageExt && compositeExt && xfixesExt;
85 Workspace::Workspace(
bool restore )
86 : DCOPObject (
"KWinInterface"),
87 TQObject (0,
"workspace"),
89 number_of_desktops(0),
92 active_popup_client( NULL ),
94 temporaryRulesMessages(
"_KDE_NET_WM_TEMPORARY_RULES", NULL, false ),
95 rules_updates_disabled( false ),
97 last_active_client (0),
98 next_active_client (0),
99 most_recently_raised (0),
101 pending_take_activity ( NULL ),
102 delayfocus_client (0),
103 showing_desktop( false ),
104 block_showing_desktop( 0 ),
105 was_user_interaction (false),
106 session_saving (false),
107 control_grab (false),
109 mouse_emulation (false),
116 desk_popup_index (0),
118 client_keys ( NULL ),
119 client_keys_dialog ( NULL ),
120 client_keys_client ( NULL ),
121 disable_shortcuts_keys ( NULL ),
122 global_shortcuts_disabled( false ),
123 global_shortcuts_disabled_for_client( false ),
125 workspaceInit (true),
126 startup(0), electric_have_borders(false),
127 electric_current_border(0),
128 electric_top_border(None),
129 electric_bottom_border(None),
130 electric_left_border(None),
131 electric_right_border(None),
132 layoutOrientation(Qt::Vertical),
137 managing_topmenus( false ),
138 topmenu_selection( NULL ),
139 topmenu_watcher( NULL ),
141 topmenu_space( NULL ),
142 set_active_client_recursion( 0 ),
143 block_stacking_updates( 0 ),
144 forced_global_mouse_grab( false )
148 root = qt_xrootwin();
149 default_colormap = DefaultColormap(qt_xdisplay(), qt_xscreen() );
150 installed_colormap = default_colormap;
151 session.setAutoDelete( TRUE );
153 connect( &temporaryRulesMessages, TQT_SIGNAL( gotMessage(
const TQString& )),
154 this, TQT_SLOT( gotTemporaryRulesMessage(
const TQString& )));
155 connect( &rulesUpdatedTimer, TQT_SIGNAL( timeout()),
this, TQT_SLOT( writeWindowRules()));
161 electric_time_first = GET_QT_X_TIME();
162 electric_time_last = GET_QT_X_TIME();
169 (void) TQApplication::desktop();
175 (WFlags)(TQt::WType_Desktop | TQt::WPaintUnclipped)
178 kapp->setGlobalMouseTracking(
true );
180 startup =
new KStartupInfo(
181 KStartupInfo::DisableKWinModule | KStartupInfo::AnnounceSilenceChanges,
this );
184 XSelectInput(qt_xdisplay(), root,
188 SubstructureRedirectMask |
189 SubstructureNotifyMask |
205 (
unsigned char*) &data,
209 client_keys =
new KGlobalAccel(
this );
211 tab_box =
new TabBox(
this );
212 popupinfo =
new PopupInfo(
this );
216 #if (QT_VERSION-0 >= 0x030200) // XRANDR support
217 connect( kapp->desktop(), TQT_SIGNAL( resized(
int )), TQT_SLOT( desktopResized()));
220 if (!supportsCompMgr()) {
221 options->useTranslucency =
false;
225 if (options->useTranslucency)
227 kompmgr =
new KProcess;
228 connect(kompmgr, TQT_SIGNAL(receivedStderr(KProcess*,
char*,
int)), TQT_SLOT(handleKompmgrOutput(KProcess*,
char*,
int)));
229 *kompmgr <<
"kompmgr";
238 p = getpwuid(getuid());
242 home = getenv(
"HOME");
244 const char *configfile =
"/.kompmgr.pid";
245 int n = strlen(home)+strlen(configfile)+1;
246 filename = (
char*)malloc(n*
sizeof(
char));
247 memset(filename,0,n);
248 strcat(filename, home);
249 strcat(filename, configfile);
254 pFile = fopen(filename,
"r");
258 printf(
"[kwin-workspace] Using '%s' as kompmgr pidfile\n\n", filename);
260 fseek (pFile , 0 , SEEK_END);
261 unsigned long lSize = ftell (pFile);
265 size_t result = fread (buffer, 1, lSize, pFile);
267 kompmgrpid = atoi(buffer);
275 kill(kompmgrpid, SIGTERM);
285 void Workspace::init()
287 checkElectricBorders();
293 supportWindow =
new TQWidget;
294 XLowerWindow( qt_xdisplay(), supportWindow->winId());
296 XSetWindowAttributes attr;
297 attr.override_redirect = 1;
298 null_focus_window = XCreateWindow( qt_xdisplay(), qt_xrootwin(), -1,-1, 1, 1, 0, CopyFromParent,
299 InputOnly, CopyFromParent, CWOverrideRedirect, &attr );
300 XMapWindow(qt_xdisplay(), null_focus_window);
302 unsigned long protocols[ 5 ] =
305 NET::SupportingWMCheck |
307 NET::ClientListStacking |
308 NET::DesktopGeometry |
309 NET::NumberOfDesktops |
310 NET::CurrentDesktop |
315 NET::KDESystemTrayWindows |
322 NET::WMIconGeometry |
326 NET::WMKDESystemTrayWinFor |
327 NET::WMFrameExtents |
354 NET::DemandsAttention |
359 NET::WM2AllowedActions |
360 NET::WM2RestackWindow |
361 NET::WM2MoveResizeWindow |
362 NET::WM2ExtendedStrut |
363 NET::WM2KDETemporaryRules |
364 NET::WM2ShowingDesktop |
365 NET::WM2FullPlacement |
366 NET::WM2DesktopLayout |
371 NET::ActionMinimize |
375 NET::ActionMaxHoriz |
376 NET::ActionFullScreen |
377 NET::ActionChangeDesktop |
383 rootInfo =
new RootInfo(
this, qt_xdisplay(), supportWindow->winId(),
"KWin",
384 protocols, 5, qt_xscreen() );
386 loadDesktopSettings();
387 updateDesktopLayout();
389 NETRootInfo client_info( qt_xdisplay(), NET::ActiveWindow | NET::CurrentDesktop );
391 if( !kapp->isSessionRestored())
392 initial_desktop = client_info.currentDesktop();
395 KConfigGroupSaver saver( kapp->sessionConfig(),
"Session" );
396 initial_desktop = kapp->sessionConfig()->readNumEntry(
"desktop", 1 );
398 if( !setCurrentDesktop( initial_desktop ))
399 setCurrentDesktop( 1 );
402 initPositioning =
new Placement(
this);
404 connect(&reconfigureTimer, TQT_SIGNAL(timeout()),
this,
405 TQT_SLOT(slotReconfigure()));
406 connect( &updateToolWindowsTimer, TQT_SIGNAL( timeout()),
this, TQT_SLOT( slotUpdateToolWindows()));
408 connect(kapp, TQT_SIGNAL(appearanceChanged()),
this,
409 TQT_SLOT(slotReconfigure()));
410 connect(kapp, TQT_SIGNAL(settingsChanged(
int)),
this,
411 TQT_SLOT(slotSettingsChanged(
int)));
412 connect(kapp, TQT_SIGNAL( kipcMessage(
int,
int )),
this, TQT_SLOT( kipcMessage(
int,
int )));
414 active_client = NULL;
415 rootInfo->setActiveWindow( None );
417 if( !kapp->isSessionRestored())
421 sprintf( nm,
"_KDE_TOPMENU_OWNER_S%d", DefaultScreen( qt_xdisplay()));
422 Atom topmenu_atom = XInternAtom( qt_xdisplay(), nm, False );
423 topmenu_selection =
new KSelectionOwner( topmenu_atom );
424 topmenu_watcher =
new KSelectionWatcher( topmenu_atom );
428 StackingUpdatesBlocker blocker(
this );
430 if( options->topMenuEnabled() && topmenu_selection->claim(
false ))
431 setupTopMenuHandling();
433 lostTopMenuSelection();
435 unsigned int i, nwins;
436 Window root_return, parent_return, *wins;
437 XQueryTree(qt_xdisplay(), root, &root_return, &parent_return, &wins, &nwins);
438 for (i = 0; i < nwins; i++)
440 XWindowAttributes attr;
441 XGetWindowAttributes(qt_xdisplay(), wins[i], &attr);
442 if (attr.override_redirect )
444 if( topmenu_space && topmenu_space->winId() == wins[ i ] )
446 if (attr.map_state != IsUnmapped)
448 if ( addSystemTrayWin( wins[i] ) )
450 Client* c = createClient( wins[i],
true );
451 if ( c != NULL && root != qt_xrootwin() )
454 XReparentWindow( qt_xdisplay(), c->frameId(), root, 0, 0 );
460 XFree((
void *) wins);
462 updateStackingOrder(
true );
465 raiseElectricBorders();
468 NETPoint* viewports =
new NETPoint[ number_of_desktops ];
469 rootInfo->setDesktopViewport( number_of_desktops, *viewports );
471 TQRect geom = TQApplication::desktop()->geometry();
472 NETSize desktop_geometry;
473 desktop_geometry.width = geom.width();
474 desktop_geometry.height = geom.height();
475 rootInfo->setDesktopGeometry( -1, desktop_geometry );
476 setShowingDesktop(
false );
480 Client* new_active_client = NULL;
481 if( !kapp->isSessionRestored())
484 new_active_client = findClient( WindowMatchPredicate( client_info.activeWindow()));
486 if( new_active_client == NULL
487 && activeClient() == NULL && should_get_focus.count() == 0 )
489 if( new_active_client == NULL )
490 new_active_client = topClientOnDesktop( currentDesktop());
491 if( new_active_client == NULL && !desktops.isEmpty() )
492 new_active_client = findDesktop(
true, currentDesktop());
494 if( new_active_client != NULL )
495 activateClient( new_active_client );
499 workspaceInit =
false;
503 Workspace::~Workspace()
507 blockStackingUpdates(
true );
510 for( ClientList::ConstIterator it = stacking_order.begin();
511 it != stacking_order.end();
515 (*it)->releaseWindow(
true );
519 clients.remove( *it );
520 desktops.remove( *it );
522 delete desktop_widget;
526 if ( root == qt_xrootwin() )
527 XDeleteProperty(qt_xdisplay(), qt_xrootwin(), atoms->kwin_running);
530 KGlobal::config()->sync();
533 delete supportWindow;
538 delete initPositioning;
539 delete topmenu_watcher;
540 delete topmenu_selection;
541 delete topmenu_space;
542 delete client_keys_dialog;
543 while( !rules.isEmpty())
545 delete rules.front();
548 XDestroyWindow( qt_xdisplay(), null_focus_window );
553 Client* Workspace::createClient( Window w,
bool is_mapped )
555 StackingUpdatesBlocker blocker(
this );
556 Client* c =
new Client(
this );
557 if( !c->manage( w, is_mapped ))
559 Client::deleteClient( c, Allowed );
562 addClient( c, Allowed );
566 void Workspace::addClient( Client* c, allowed_t )
570 c->setBMP(c->resourceName() ==
"beep-media-player" || c->decorationId() == None);
572 c->getWindowOpacity();
576 if (!c->hasCustomOpacity())
578 c->setShadowSize(options->dockShadowSize);
579 c->setOpacity(options->translucentDocks, options->dockOpacity);
583 if (c->isMenu() || c->isTopMenu())
585 c->setShadowSize(options->menuShadowSize);
588 Group* grp = findGroup( c->window());
592 if ( c->isDesktop() )
594 desktops.append( c );
595 if( active_client == NULL && should_get_focus.isEmpty() && c->isOnCurrentDesktop())
600 updateFocusChains( c, FocusChainUpdate );
603 if( !unconstrained_stacking_order.contains( c ))
604 unconstrained_stacking_order.append( c );
605 if( !stacking_order.contains( c ))
606 stacking_order.append( c );
610 updateClientLayer( c );
615 if( activeClient() == NULL && should_get_focus.count() == 0 )
616 activateClient( findDesktop(
true, currentDesktop()));
618 c->checkActiveModal();
619 checkTransients( c->window());
620 updateStackingOrder(
true );
621 if( c->isUtility() || c->isMenu() || c->isToolbar())
622 updateToolWindows(
true );
623 checkNonExistentClients();
629 void Workspace::removeClient( Client* c, allowed_t )
631 if (c == active_popup_client)
634 if( client_keys_client == c )
635 setupWindowShortcutDone(
false );
636 if( !c->shortcut().isNull())
637 c->setShortcut( TQString::null );
640 Notify::raise( Notify::TransDelete );
641 if( c->isNormalWindow())
642 Notify::raise( Notify::Delete );
644 Q_ASSERT( clients.contains( c ) || desktops.contains( c ));
646 desktops.remove( c );
647 unconstrained_stacking_order.remove( c );
648 stacking_order.remove( c );
650 i <= numberOfDesktops();
652 focus_chain[ i ].
remove( c );
653 global_focus_chain.remove( c );
654 attention_chain.remove( c );
655 showing_desktop_clients.remove( c );
658 Group* group = findGroup( c->window());
662 if ( c == most_recently_raised )
663 most_recently_raised = 0;
664 should_get_focus.remove( c );
665 Q_ASSERT( c != active_client );
666 if ( c == last_active_client )
667 last_active_client = 0;
668 if( c == pending_take_activity )
669 pending_take_activity = NULL;
670 if( c == delayfocus_client )
673 updateStackingOrder(
true );
681 void Workspace::updateFocusChains( Client* c, FocusChainChange change )
683 if( !c->wantsTabFocus())
686 i<= numberOfDesktops();
688 focus_chain[i].
remove(c);
689 global_focus_chain.remove( c );
692 if(c->desktop() == NET::OnAllDesktops)
694 for(
int i=1; i<= numberOfDesktops(); i++)
696 if( i == currentDesktop()
697 && ( change == FocusChainMakeFirst || change == FocusChainMakeLast ))
699 focus_chain[ i ].remove( c );
700 if( change == FocusChainMakeFirst )
701 focus_chain[ i ].append( c );
703 focus_chain[ i ].prepend( c );
705 else if( !focus_chain[ i ].contains( c ))
707 if( active_client != NULL && active_client != c
708 && !focus_chain[ i ].isEmpty() && focus_chain[ i ].last() == active_client )
709 focus_chain[ i ].insert( focus_chain[ i ].fromLast(), c );
711 focus_chain[ i ].append( c );
717 for(
int i=1; i<= numberOfDesktops(); i++)
719 if( i == c->desktop())
721 if( change == FocusChainMakeFirst )
723 focus_chain[ i ].remove( c );
724 focus_chain[ i ].append( c );
726 else if( change == FocusChainMakeLast )
728 focus_chain[ i ].remove( c );
729 focus_chain[ i ].prepend( c );
731 else if( !focus_chain[ i ].contains( c ))
733 if( active_client != NULL && active_client != c
734 && !focus_chain[ i ].isEmpty() && focus_chain[ i ].last() == active_client )
735 focus_chain[ i ].insert( focus_chain[ i ].fromLast(), c );
737 focus_chain[ i ].append( c );
741 focus_chain[ i ].remove( c );
744 if( change == FocusChainMakeFirst )
746 global_focus_chain.remove( c );
747 global_focus_chain.append( c );
749 else if( change == FocusChainMakeLast )
751 global_focus_chain.remove( c );
752 global_focus_chain.prepend( c );
754 else if( !global_focus_chain.contains( c ))
756 if( active_client != NULL && active_client != c
757 && !global_focus_chain.isEmpty() && global_focus_chain.last() == active_client )
758 global_focus_chain.insert( global_focus_chain.fromLast(), c );
760 global_focus_chain.append( c );
764 void Workspace::updateOverlappingShadows(
unsigned long window)
768 if ((client = findClient(WindowMatchPredicate((WId)window))))
771 client->drawOverlappingShadows(
false);
774 void Workspace::setShadowed(
unsigned long window,
bool shadowed)
778 if ((client = findClient(WindowMatchPredicate((WId)window))))
779 client->setShadowed(shadowed);
782 void Workspace::updateCurrentTopMenu()
784 if( !managingTopMenus())
788 bool block_desktop_menubar =
false;
792 Client* menu_client = active_client;
795 if( menu_client->isFullScreen())
796 block_desktop_menubar =
true;
797 for( ClientList::ConstIterator it = menu_client->transients().begin();
798 it != menu_client->transients().end();
800 if( (*it)->isTopMenu())
805 if( menubar != NULL || !menu_client->isTransient())
807 if( menu_client->isModal() || menu_client->transientFor() == NULL )
809 menu_client = menu_client->transientFor();
813 for( ClientList::ConstIterator it = active_client->group()->members().begin();
814 it != active_client->group()->members().end();
816 if( (*it)->isTopMenu())
823 if( !menubar && !block_desktop_menubar && options->desktopTopMenu())
826 Client* desktop = findDesktop(
true, currentDesktop());
827 if( desktop != NULL )
829 for( ClientList::ConstIterator it = desktop->transients().begin();
830 it != desktop->transients().end();
832 if( (*it)->isTopMenu())
841 if( menubar == NULL )
843 for( ClientList::ConstIterator it = topmenus.begin();
844 it != topmenus.end();
846 if( (*it)->wasOriginallyGroupTransient())
857 if( active_client && !menubar->isOnDesktop( active_client->desktop()))
858 menubar->setDesktop( active_client->desktop());
859 menubar->hideClient(
false );
860 topmenu_space->hide();
864 unconstrained_stacking_order.remove( menubar );
865 unconstrained_stacking_order.append( menubar );
867 else if( !block_desktop_menubar )
869 topmenu_space->show();
873 for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
875 if( (*it)->isTopMenu() && (*it) != menubar )
876 (*it)->hideClient(
true );
881 void Workspace::updateToolWindows(
bool also_hide )
884 if( !options->hideUtilityWindowsForInactive )
886 for( ClientList::ConstIterator it = clients.begin();
889 (*it)->hideClient(
false );
892 const Group* group = NULL;
893 const Client* client = active_client;
896 while( client != NULL )
898 if( !client->isTransient())
900 if( client->groupTransient())
902 group = client->group();
905 client = client->transientFor();
911 ClientList to_show, to_hide;
912 for( ClientList::ConstIterator it = stacking_order.begin();
913 it != stacking_order.end();
916 if( (*it)->isUtility() || (*it)->isMenu() || (*it)->isToolbar())
919 if( !(*it)->isTransient())
921 if( (*it)->group()->members().count() == 1 )
923 else if( client != NULL && (*it)->group() == client->group())
930 if( group != NULL && (*it)->group() == group )
932 else if( client != NULL && client->hasTransient( (*it),
true ))
937 if( !show && also_hide )
939 const ClientList mainclients = (*it)->mainClients();
942 if( mainclients.isEmpty())
944 for( ClientList::ConstIterator it2 = mainclients.begin();
945 it2 != mainclients.end();
948 if( (*it2)->isSpecialWindow())
952 to_hide.append( *it );
955 to_show.append( *it );
958 for( ClientList::ConstIterator it = to_show.fromLast();
962 (*it)->hideClient(
false );
965 for( ClientList::ConstIterator it = to_hide.begin();
968 (*it)->hideClient(
true );
969 updateToolWindowsTimer.stop();
973 updateToolWindowsTimer.start( 50,
true );
977 void Workspace::slotUpdateToolWindows()
979 updateToolWindows(
true );
985 void Workspace::updateColormap()
987 Colormap cmap = default_colormap;
988 if ( activeClient() && activeClient()->colormap() != None )
989 cmap = activeClient()->colormap();
990 if ( cmap != installed_colormap )
992 XInstallColormap(qt_xdisplay(), cmap );
993 installed_colormap = cmap;
997 void Workspace::reconfigure()
999 reconfigureTimer.start(200,
true);
1003 void Workspace::slotSettingsChanged(
int category)
1005 kdDebug(1212) <<
"Workspace::slotSettingsChanged()" << endl;
1006 if( category == (
int) KApplication::SETTINGS_SHORTCUTS )
1013 KWIN_PROCEDURE( CheckBorderSizesProcedure, cl->checkBorderSizes() );
1015 void Workspace::slotReconfigure()
1017 kdDebug(1212) <<
"Workspace::slotReconfigure()" << endl;
1018 reconfigureTimer.stop();
1020 KGlobal::config()->reparseConfiguration();
1021 unsigned long changed = options->updateSettings();
1022 tab_box->reconfigure();
1023 popupinfo->reconfigure();
1024 initPositioning->reinitCascading( 0 );
1026 forEachClient( CheckIgnoreFocusStealingProcedure());
1027 updateToolWindows(
true );
1029 if( mgr->reset( changed ))
1031 #if 0 // This actually seems to make things worse now
1033 curtain.setBackgroundMode( NoBackground );
1034 curtain.setGeometry( TQApplication::desktop()->geometry() );
1037 for( ClientList::ConstIterator it = clients.begin();
1038 it != clients.end();
1041 (*it)->updateDecoration(
true,
true );
1043 mgr->destroyPreviousPlugin();
1047 forEachClient( CheckBorderSizesProcedure());
1050 checkElectricBorders();
1052 if( options->topMenuEnabled() && !managingTopMenus())
1054 if( topmenu_selection->claim(
false ))
1055 setupTopMenuHandling();
1057 lostTopMenuSelection();
1059 else if( !options->topMenuEnabled() && managingTopMenus())
1061 topmenu_selection->release();
1062 lostTopMenuSelection();
1065 if( managingTopMenus())
1067 updateTopMenuGeometry();
1068 updateCurrentTopMenu();
1072 for( ClientList::Iterator it = clients.begin();
1073 it != clients.end();
1076 (*it)->setupWindowRules(
true );
1077 (*it)->applyWindowRules();
1078 discardUsedWindowRules( *it,
false );
1081 if (options->resetKompmgr)
1083 bool tmp = options->useTranslucency;
1089 p = getpwuid(getuid());
1093 home = getenv(
"HOME");
1095 const char *configfile =
"/.kompmgr.pid";
1096 int n = strlen(home)+strlen(configfile)+1;
1097 filename = (
char*)malloc(n*
sizeof(
char));
1098 memset(filename,0,n);
1099 strcat(filename, home);
1100 strcat(filename, configfile);
1105 pFile = fopen(filename,
"r");
1109 printf(
"[kwin-workspace] Using '%s' as kompmgr pidfile\n\n", filename);
1111 fseek (pFile , 0 , SEEK_END);
1112 unsigned long lSize = ftell (pFile);
1116 size_t result = fread (buffer, 1, lSize, pFile);
1118 kompmgrpid = atoi(buffer);
1128 kill(kompmgrpid, SIGUSR2);
1133 TQTimer::singleShot( 200,
this, TQT_SLOT(startKompmgr()) );
1140 kill(kompmgrpid, SIGTERM);
1150 void Workspace::loadDesktopSettings()
1152 KConfig* c = KGlobal::config();
1153 TQCString groupname;
1154 if (screen_number == 0)
1155 groupname =
"Desktops";
1157 groupname.sprintf(
"Desktops-screen-%d", screen_number);
1158 KConfigGroupSaver saver(c,groupname);
1160 int n = c->readNumEntry(
"Number", 4);
1161 number_of_desktops = n;
1163 workarea =
new TQRect[ n + 1 ];
1166 rootInfo->setNumberOfDesktops( number_of_desktops );
1167 desktop_focus_chain.resize( n );
1169 focus_chain.resize( n + 1 );
1170 for(
int i = 1; i <= n; i++)
1172 TQString s = c->readEntry(TQString(
"Name_%1").arg(i),
1173 i18n(
"Desktop %1").arg(i));
1174 rootInfo->setDesktopName( i, s.utf8().data() );
1175 desktop_focus_chain[i-1] = i;
1179 void Workspace::saveDesktopSettings()
1181 KConfig* c = KGlobal::config();
1182 TQCString groupname;
1183 if (screen_number == 0)
1184 groupname =
"Desktops";
1186 groupname.sprintf(
"Desktops-screen-%d", screen_number);
1187 KConfigGroupSaver saver(c,groupname);
1189 c->writeEntry(
"Number", number_of_desktops );
1190 for(
int i = 1; i <= number_of_desktops; i++)
1192 TQString s = desktopName( i );
1193 TQString defaultvalue = i18n(
"Desktop %1").arg(i);
1197 rootInfo->setDesktopName( i, s.utf8().data() );
1200 if (s != defaultvalue)
1202 c->writeEntry( TQString(
"Name_%1").arg(i), s );
1206 TQString currentvalue = c->readEntry(TQString(
"Name_%1").arg(i));
1207 if (currentvalue != defaultvalue)
1208 c->writeEntry( TQString(
"Name_%1").arg(i),
"" );
1213 TQStringList Workspace::configModules(
bool controlCenter)
1216 args <<
"kde-kwindecoration.desktop";
1218 args <<
"kde-kwinoptions.desktop";
1219 else if (kapp->authorizeControlModule(
"kde-kwinoptions.desktop"))
1220 args <<
"kwinactions" <<
"kwinfocus" <<
"kwinmoving" <<
"kwinadvanced" <<
"kwinrules" <<
"kwintranslucency";
1224 void Workspace::configureWM()
1226 KApplication::kdeinitExec(
"kcmshell", configModules(
false) );
1232 void Workspace::doNotManage( TQString title )
1234 doNotManageList.append( title );
1240 bool Workspace::isNotManaged(
const TQString& title )
1242 for ( TQStringList::Iterator it = doNotManageList.begin(); it != doNotManageList.end(); ++it )
1244 TQRegExp r( (*it) );
1245 if (r.search(title) != -1)
1247 doNotManageList.remove( it );
1257 void Workspace::refresh()
1260 w.setGeometry( TQApplication::desktop()->geometry() );
1263 TQApplication::flushX();
1273 class ObscuringWindows
1276 ~ObscuringWindows();
1277 void create( Client* c );
1279 TQValueList<Window> obscuring_windows;
1280 static TQValueList<Window>* cached;
1281 static unsigned int max_cache_size;
1284 TQValueList<Window>* ObscuringWindows::cached = 0;
1285 unsigned int ObscuringWindows::max_cache_size = 0;
1287 void ObscuringWindows::create( Client* c )
1290 cached =
new TQValueList<Window>;
1292 XWindowChanges chngs;
1293 int mask = CWSibling | CWStackMode;
1294 if( cached->count() > 0 )
1296 cached->remove( obs_win = cached->first());
1299 chngs.width = c->width();
1300 chngs.height = c->height();
1301 mask |= CWX | CWY | CWWidth | CWHeight;
1305 XSetWindowAttributes a;
1306 a.background_pixmap = None;
1307 a.override_redirect = True;
1308 obs_win = XCreateWindow( qt_xdisplay(), qt_xrootwin(), c->x(), c->y(),
1309 c->width(), c->height(), 0, CopyFromParent, InputOutput,
1310 CopyFromParent, CWBackPixmap | CWOverrideRedirect, &a );
1312 chngs.sibling = c->frameId();
1313 chngs.stack_mode = Below;
1314 XConfigureWindow( qt_xdisplay(), obs_win, mask, &chngs );
1315 XMapWindow( qt_xdisplay(), obs_win );
1316 obscuring_windows.append( obs_win );
1319 ObscuringWindows::~ObscuringWindows()
1321 max_cache_size = TQMAX( max_cache_size, obscuring_windows.count() + 4 ) - 1;
1322 for( TQValueList<Window>::ConstIterator it = obscuring_windows.begin();
1323 it != obscuring_windows.end();
1326 XUnmapWindow( qt_xdisplay(), *it );
1327 if( cached->count() < max_cache_size )
1328 cached->prepend( *it );
1330 XDestroyWindow( qt_xdisplay(), *it );
1341 bool Workspace::setCurrentDesktop(
int new_desktop )
1343 if (new_desktop < 1 || new_desktop > number_of_desktops )
1349 StackingUpdatesBlocker blocker(
this );
1351 int old_desktop = current_desktop;
1352 if (new_desktop != current_desktop)
1354 ++block_showing_desktop;
1359 Notify::raise((Notify::Event) (Notify::DesktopChange+new_desktop));
1361 ObscuringWindows obs_wins;
1363 current_desktop = new_desktop;
1365 bool desktopHasCompositing = kapp->isCompositionManagerAvailable();
1366 if (!desktopHasCompositing) {
1368 for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it) {
1369 if ( !(*it)->isOnDesktop( new_desktop ) && (*it) != movingClient )
1371 if( (*it)->isShown(
true ) && (*it)->isOnDesktop( old_desktop )) {
1372 obs_wins.create( *it );
1374 (*it)->updateVisibility();
1379 rootInfo->setCurrentDesktop( current_desktop );
1381 if( movingClient && !movingClient->isOnDesktop( new_desktop ))
1382 movingClient->setDesktop( new_desktop );
1384 for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
1385 if ( (*it)->isOnDesktop( new_desktop ) ) {
1386 (*it)->updateVisibility();
1390 if (desktopHasCompositing) {
1393 XSync( qt_xdisplay(),
false);
1394 for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it) {
1395 if ( !(*it)->isOnDesktop( new_desktop ) && (*it) != movingClient )
1397 if( (*it)->isShown(
true ) && (*it)->isOnDesktop( old_desktop )) {
1398 obs_wins.create( *it );
1400 (*it)->updateVisibility();
1405 --block_showing_desktop;
1406 if( showingDesktop())
1407 resetShowingDesktop(
false );
1414 if ( options->focusPolicyIsReasonable())
1417 if ( movingClient != NULL && active_client == movingClient
1418 && focus_chain[currentDesktop()].contains( active_client )
1419 && active_client->isShown(
true ) && active_client->isOnCurrentDesktop())
1425 for( ClientList::ConstIterator it = focus_chain[currentDesktop()].fromLast();
1426 it != focus_chain[currentDesktop()].end();
1429 if ( (*it)->isShown(
false ) && (*it)->isOnCurrentDesktop())
1441 else if( active_client && active_client->isShown(
true ) && active_client->isOnCurrentDesktop())
1444 if( c == NULL && !desktops.isEmpty())
1445 c = findDesktop(
true, currentDesktop());
1447 if( c != active_client )
1448 setActiveClient( NULL, Allowed );
1455 updateCurrentTopMenu();
1462 for(
int i = desktop_focus_chain.find( currentDesktop() ); i > 0; i-- )
1463 desktop_focus_chain[i] = desktop_focus_chain[i-1];
1464 desktop_focus_chain[0] = currentDesktop();
1471 if( old_desktop != 0 )
1472 popupinfo->showInfo( desktopName(currentDesktop()) );
1477 void Workspace::nextDesktop()
1479 int desktop = currentDesktop() + 1;
1480 setCurrentDesktop(desktop > numberOfDesktops() ? 1 : desktop);
1484 void Workspace::previousDesktop()
1486 int desktop = currentDesktop() - 1;
1487 setCurrentDesktop(desktop > 0 ? desktop : numberOfDesktops());
1490 int Workspace::desktopToRight(
int desktop )
const
1493 calcDesktopLayout(x,y);
1495 if (layoutOrientation == Qt::Vertical)
1498 if ( dt >= numberOfDesktops() )
1500 if ( options->rollOverDesktops )
1501 dt -= numberOfDesktops();
1508 int d = (dt % x) + 1;
1511 if ( options->rollOverDesktops )
1516 dt = dt - (dt % x) + d;
1521 int Workspace::desktopToLeft(
int desktop )
const
1524 calcDesktopLayout(x,y);
1526 if (layoutOrientation == Qt::Vertical)
1531 if ( options->rollOverDesktops )
1532 dt += numberOfDesktops();
1539 int d = (dt % x) - 1;
1542 if ( options->rollOverDesktops )
1547 dt = dt - (dt % x) + d;
1552 int Workspace::desktopUp(
int desktop )
const
1555 calcDesktopLayout(x,y);
1557 if (layoutOrientation == Qt::Horizontal)
1562 if ( options->rollOverDesktops )
1563 dt += numberOfDesktops();
1570 int d = (dt % y) - 1;
1573 if ( options->rollOverDesktops )
1578 dt = dt - (dt % y) + d;
1583 int Workspace::desktopDown(
int desktop )
const
1586 calcDesktopLayout(x,y);
1588 if (layoutOrientation == Qt::Horizontal)
1591 if ( dt >= numberOfDesktops() )
1593 if ( options->rollOverDesktops )
1594 dt -= numberOfDesktops();
1601 int d = (dt % y) + 1;
1604 if ( options->rollOverDesktops )
1609 dt = dt - (dt % y) + d;
1618 void Workspace::setNumberOfDesktops(
int n )
1620 if ( n == number_of_desktops )
1622 int old_number_of_desktops = number_of_desktops;
1623 number_of_desktops = n;
1625 if( currentDesktop() > numberOfDesktops())
1626 setCurrentDesktop( numberOfDesktops());
1630 if( old_number_of_desktops < number_of_desktops )
1632 rootInfo->setNumberOfDesktops( number_of_desktops );
1633 NETPoint* viewports =
new NETPoint[ number_of_desktops ];
1634 rootInfo->setDesktopViewport( number_of_desktops, *viewports );
1636 updateClientArea(
true );
1637 focus_chain.resize( number_of_desktops + 1 );
1642 if( old_number_of_desktops > number_of_desktops )
1644 for( ClientList::ConstIterator it = clients.begin();
1645 it != clients.end();
1648 if( !(*it)->isOnAllDesktops() && (*it)->desktop() > numberOfDesktops())
1649 sendClientToDesktop( *it, numberOfDesktops(), true );
1652 if( old_number_of_desktops > number_of_desktops )
1654 rootInfo->setNumberOfDesktops( number_of_desktops );
1655 NETPoint* viewports =
new NETPoint[ number_of_desktops ];
1656 rootInfo->setDesktopViewport( number_of_desktops, *viewports );
1658 updateClientArea(
true );
1659 focus_chain.resize( number_of_desktops + 1 );
1662 saveDesktopSettings();
1665 desktop_focus_chain.resize( n );
1666 for(
int i = 0; i < (int)desktop_focus_chain.size(); i++ )
1667 desktop_focus_chain[i] = i+1;
1675 void Workspace::sendClientToDesktop( Client* c,
int desk,
bool dont_activate )
1677 bool was_on_desktop = c->isOnDesktop( desk ) || c->isOnAllDesktops();
1678 c->setDesktop( desk );
1679 if ( c->desktop() != desk )
1681 desk = c->desktop();
1683 if ( c->isOnDesktop( currentDesktop() ) )
1685 if ( c->wantsTabFocus() && options->focusPolicyIsReasonable()
1690 restackClientUnderActive( c );
1697 ClientList transients_stacking_order = ensureStackingOrder( c->transients());
1698 for( ClientList::ConstIterator it = transients_stacking_order.begin();
1699 it != transients_stacking_order.end();
1701 sendClientToDesktop( *it, desk, dont_activate );
1705 int Workspace::numScreens()
const
1707 if( !options->xineramaEnabled )
1709 return tqApp->desktop()->numScreens();
1712 int Workspace::activeScreen()
const
1714 if( !options->xineramaEnabled )
1716 if( !options->activeMouseScreen )
1718 if( activeClient() != NULL && !activeClient()->isOnScreen( active_screen ))
1719 return tqApp->desktop()->screenNumber( activeClient()->geometry().center());
1720 return active_screen;
1722 return tqApp->desktop()->screenNumber( TQCursor::pos());
1727 void Workspace::checkActiveScreen(
const Client* c )
1729 if( !options->xineramaEnabled )
1733 if( !c->isOnScreen( active_screen ))
1734 active_screen = c->screen();
1739 void Workspace::setActiveScreenMouse( TQPoint mousepos )
1741 if( !options->xineramaEnabled )
1743 active_screen = tqApp->desktop()->screenNumber( mousepos );
1746 TQRect Workspace::screenGeometry(
int screen )
const
1748 if (( !options->xineramaEnabled ) || (kapp->desktop()->numScreens() < 2))
1749 return tqApp->desktop()->geometry();
1750 return tqApp->desktop()->screenGeometry( screen );
1753 int Workspace::screenNumber( TQPoint pos )
const
1755 if( !options->xineramaEnabled )
1757 return tqApp->desktop()->screenNumber( pos );
1760 void Workspace::sendClientToScreen( Client* c,
int screen )
1762 if( c->screen() == screen )
1764 GeometryUpdatesPostponer blocker( c );
1765 TQRect old_sarea = clientArea( MaximizeArea, c );
1766 TQRect sarea = clientArea( MaximizeArea, screen, c->desktop());
1767 c->setGeometry( sarea.x() - old_sarea.x() + c->x(), sarea.y() - old_sarea.y() + c->y(),
1768 c->size().width(), c->size().height());
1769 c->checkWorkspacePosition();
1770 ClientList transients_stacking_order = ensureStackingOrder( c->transients());
1771 for( ClientList::ConstIterator it = transients_stacking_order.begin();
1772 it != transients_stacking_order.end();
1774 sendClientToScreen( *it, screen );
1776 active_screen = screen;
1780 void Workspace::setDesktopLayout(
int,
int,
int )
1784 void Workspace::updateDesktopLayout()
1787 layoutOrientation = ( rootInfo->desktopLayoutOrientation() == NET::OrientationHorizontal
1788 ? Qt::Horizontal : Qt::Vertical );
1789 layoutX = rootInfo->desktopLayoutColumnsRows().width();
1790 layoutY = rootInfo->desktopLayoutColumnsRows().height();
1791 if( layoutX == 0 && layoutY == 0 )
1795 void Workspace::calcDesktopLayout(
int &x,
int &y)
const
1799 if((x <= 0) && (y > 0))
1800 x = (numberOfDesktops()+y-1) / y;
1801 else if((y <=0) && (x > 0))
1802 y = (numberOfDesktops()+x-1) / x;
1814 bool Workspace::addSystemTrayWin( WId w )
1816 if ( systemTrayWins.contains( w ) )
1819 NETWinInfo ni( qt_xdisplay(), w, root, NET::WMKDESystemTrayWinFor );
1820 WId trayWinFor = ni.kdeSystemTrayWinFor();
1823 systemTrayWins.append( SystemTrayWindow( w, trayWinFor ) );
1824 XSelectInput( qt_xdisplay(), w,
1827 XAddToSaveSet( qt_xdisplay(), w );
1828 propagateSystemTrayWins();
1836 bool Workspace::removeSystemTrayWin( WId w,
bool check )
1838 if ( !systemTrayWins.contains( w ) )
1850 Atom* props = XListProperties( qt_xdisplay(), w, &num_props );
1856 if( props[ i ] == atoms->kde_system_tray_embedding )
1864 systemTrayWins.remove( w );
1865 XRemoveFromSaveSet (qt_xdisplay (), w);
1866 propagateSystemTrayWins();
1874 void Workspace::propagateSystemTrayWins()
1876 Window *cl =
new Window[ systemTrayWins.count()];
1879 for ( SystemTrayWindowList::ConstIterator it = systemTrayWins.begin(); it != systemTrayWins.end(); ++it )
1881 cl[i++] = (*it).win;
1884 rootInfo->setKDESystemTrayWindows( cl, i );
1889 void Workspace::killWindowId( Window window_to_kill )
1891 if( window_to_kill == None )
1893 Window window = window_to_kill;
1894 Client* client = NULL;
1897 client = findClient( FrameIdMatchPredicate( window ));
1898 if( client != NULL )
1900 Window parent, root;
1902 unsigned int children_count;
1903 XQueryTree( qt_xdisplay(), window, &root, &parent, &children, &children_count );
1904 if( children != NULL )
1906 if( window == root )
1910 if( client != NULL )
1911 client->killWindow();
1913 XKillClient( qt_xdisplay(), window_to_kill );
1917 void Workspace::sendPingToWindow( Window window, Time timestamp )
1919 rootInfo->sendPing( window, timestamp );
1922 void Workspace::sendTakeActivity( Client* c, Time timestamp,
long flags )
1924 rootInfo->takeActivity( c->window(), timestamp, flags );
1925 pending_take_activity = c;
1932 void Workspace::slotGrabWindow()
1934 if ( active_client )
1936 TQPixmap snapshot = TQPixmap::grabWindow( active_client->frameId() );
1939 if( Shape::available())
1943 XRectangle* rects = XShapeGetRectangles( qt_xdisplay(), active_client->frameId(),
1944 ShapeBounding, &count, &order);
1953 for (
int pos = 0; pos < count; pos++)
1954 contents += TQRegion(rects[pos].x, rects[pos].y,
1955 rects[pos].width, rects[pos].height);
1959 TQRegion bbox(0, 0, snapshot.width(), snapshot.height());
1962 TQRegion maskedAway = bbox - contents;
1963 TQMemArray<TQRect> maskedAwayRects = maskedAway.rects();
1966 TQBitmap mask( snapshot.width(), snapshot.height());
1968 p.fillRect(0, 0, mask.width(), mask.height(), Qt::color1);
1969 for (uint pos = 0; pos < maskedAwayRects.count(); pos++)
1970 p.fillRect(maskedAwayRects[pos], Qt::color0);
1972 snapshot.setMask(mask);
1976 TQClipboard *cb = TQApplication::clipboard();
1977 cb->setPixmap( snapshot );
1986 void Workspace::slotGrabDesktop()
1988 TQPixmap p = TQPixmap::grabWindow( qt_xrootwin() );
1989 TQClipboard *cb = TQApplication::clipboard();
1997 void Workspace::slotMouseEmulation()
2000 if ( mouse_emulation )
2002 XUngrabKeyboard(qt_xdisplay(), GET_QT_X_TIME());
2003 mouse_emulation = FALSE;
2007 if ( XGrabKeyboard(qt_xdisplay(),
2009 GrabModeAsync, GrabModeAsync,
2010 GET_QT_X_TIME()) == GrabSuccess )
2012 mouse_emulation = TRUE;
2013 mouse_emulation_state = 0;
2014 mouse_emulation_window = 0;
2024 WId Workspace::getMouseEmulationWindow()
2027 Window child = qt_xrootwin();
2028 int root_x, root_y, lx, ly;
2036 c = findClient( FrameIdMatchPredicate( w ));
2037 XQueryPointer( qt_xdisplay(), w, &root, &child,
2038 &root_x, &root_y, &lx, &ly, &state );
2039 }
while ( child != None && child != w );
2041 if ( c && !c->isActive() )
2042 activateClient( c );
2049 unsigned int Workspace::sendFakedMouseEvent( TQPoint pos, WId w, MouseEmulation type,
int button,
unsigned int state )
2053 TQWidget* widget = TQWidget::find( w );
2054 if ( (!widget || widget->inherits(TQTOOLBUTTON_OBJECT_NAME_STRING) ) && !findClient( WindowMatchPredicate( w )) )
2058 XTranslateCoordinates( qt_xdisplay(), qt_xrootwin(), w, pos.x(), pos.y(), &x, &y, &xw );
2059 if ( type == EmuMove )
2062 e.type = MotionNotify;
2063 e.xmotion.window = w;
2064 e.xmotion.root = qt_xrootwin();
2065 e.xmotion.subwindow = w;
2066 e.xmotion.time = GET_QT_X_TIME();
2069 e.xmotion.x_root = pos.x();
2070 e.xmotion.y_root = pos.y();
2071 e.xmotion.state = state;
2072 e.xmotion.is_hint = NotifyNormal;
2073 XSendEvent( qt_xdisplay(), w, TRUE, ButtonMotionMask, &e );
2078 e.type = type == EmuRelease ? ButtonRelease : ButtonPress;
2079 e.xbutton.window = w;
2080 e.xbutton.root = qt_xrootwin();
2081 e.xbutton.subwindow = w;
2082 e.xbutton.time = GET_QT_X_TIME();
2085 e.xbutton.x_root = pos.x();
2086 e.xbutton.y_root = pos.y();
2087 e.xbutton.state = state;
2088 e.xbutton.button = button;
2089 XSendEvent( qt_xdisplay(), w, TRUE, ButtonPressMask, &e );
2091 if ( type == EmuPress )
2096 state |= Button2Mask;
2099 state |= Button3Mask;
2102 state |= Button1Mask;
2111 state &= ~Button2Mask;
2114 state &= ~Button3Mask;
2117 state &= ~Button1Mask;
2129 bool Workspace::keyPressMouseEmulation( XKeyEvent& ev )
2131 if ( root != qt_xrootwin() )
2133 int kc = XKeycodeToKeysym(qt_xdisplay(), ev.keycode, 0);
2134 int km = ev.state & (ControlMask | Mod1Mask | ShiftMask);
2136 bool is_control = km & ControlMask;
2137 bool is_alt = km & Mod1Mask;
2138 bool is_shift = km & ShiftMask;
2139 int delta = is_control?1:is_alt?32:8;
2140 TQPoint pos = TQCursor::pos();
2161 if ( !mouse_emulation_state )
2162 mouse_emulation_window = getMouseEmulationWindow();
2163 if ( (mouse_emulation_state & Button1Mask) == 0 )
2164 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button1, mouse_emulation_state );
2166 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
2169 if ( !mouse_emulation_state )
2170 mouse_emulation_window = getMouseEmulationWindow();
2171 if ( (mouse_emulation_state & Button2Mask) == 0 )
2172 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button2, mouse_emulation_state );
2174 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button2, mouse_emulation_state );
2177 if ( !mouse_emulation_state )
2178 mouse_emulation_window = getMouseEmulationWindow();
2179 if ( (mouse_emulation_state & Button3Mask) == 0 )
2180 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button3, mouse_emulation_state );
2182 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button3, mouse_emulation_state );
2189 if ( !mouse_emulation_state )
2192 mouse_emulation_window = getMouseEmulationWindow();
2193 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button1, mouse_emulation_state );
2194 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
2198 if ( mouse_emulation_state & Button1Mask )
2199 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
2200 if ( mouse_emulation_state & Button2Mask )
2201 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button2, mouse_emulation_state );
2202 if ( mouse_emulation_state & Button3Mask )
2203 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button3, mouse_emulation_state );
2208 XUngrabKeyboard(qt_xdisplay(), GET_QT_X_TIME());
2209 mouse_emulation = FALSE;
2215 TQCursor::setPos( pos );
2216 if ( mouse_emulation_state )
2217 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuMove, 0, mouse_emulation_state );
2227 TQWidget* Workspace::desktopWidget()
2229 return desktop_widget;
2233 void Workspace::delayFocus()
2235 requestFocus( delayfocus_client );
2239 void Workspace::requestDelayFocus( Client* c )
2241 delayfocus_client = c;
2242 delete delayFocusTimer;
2243 delayFocusTimer =
new TQTimer(
this );
2244 connect( delayFocusTimer, TQT_SIGNAL( timeout() ),
this, TQT_SLOT( delayFocus() ) );
2245 delayFocusTimer->start( options->delayFocusInterval, TRUE );
2248 void Workspace::cancelDelayFocus()
2250 delete delayFocusTimer;
2251 delayFocusTimer = 0;
2261 void Workspace::checkElectricBorders(
bool force )
2264 destroyBorderWindows();
2266 electric_current_border = 0;
2268 TQRect r = TQApplication::desktop()->geometry();
2269 electricTop = r.top();
2270 electricBottom = r.bottom();
2271 electricLeft = r.left();
2272 electricRight = r.right();
2274 if (options->electricBorders() == Options::ElectricAlways)
2275 createBorderWindows();
2277 destroyBorderWindows();
2280 void Workspace::createBorderWindows()
2282 if ( electric_have_borders )
2285 electric_have_borders =
true;
2287 TQRect r = TQApplication::desktop()->geometry();
2288 XSetWindowAttributes attributes;
2289 unsigned long valuemask;
2290 attributes.override_redirect = True;
2291 attributes.event_mask = ( EnterWindowMask | LeaveWindowMask );
2292 valuemask= (CWOverrideRedirect | CWEventMask | CWCursor );
2293 attributes.cursor = XCreateFontCursor(qt_xdisplay(),
2295 electric_top_border = XCreateWindow (qt_xdisplay(), qt_xrootwin(),
2299 CopyFromParent, InputOnly,
2301 valuemask, &attributes);
2302 XMapWindow(qt_xdisplay(), electric_top_border);
2304 attributes.cursor = XCreateFontCursor(qt_xdisplay(),
2306 electric_bottom_border = XCreateWindow (qt_xdisplay(), qt_xrootwin(),
2310 CopyFromParent, InputOnly,
2312 valuemask, &attributes);
2313 XMapWindow(qt_xdisplay(), electric_bottom_border);
2315 attributes.cursor = XCreateFontCursor(qt_xdisplay(),
2317 electric_left_border = XCreateWindow (qt_xdisplay(), qt_xrootwin(),
2321 CopyFromParent, InputOnly,
2323 valuemask, &attributes);
2324 XMapWindow(qt_xdisplay(), electric_left_border);
2326 attributes.cursor = XCreateFontCursor(qt_xdisplay(),
2328 electric_right_border = XCreateWindow (qt_xdisplay(), qt_xrootwin(),
2332 CopyFromParent, InputOnly,
2334 valuemask, &attributes);
2335 XMapWindow(qt_xdisplay(), electric_right_border);
2338 XChangeProperty( qt_xdisplay(), electric_top_border, atoms->xdnd_aware, XA_ATOM,
2339 32, PropModeReplace, (
unsigned char* )&version, 1 );
2340 XChangeProperty( qt_xdisplay(), electric_bottom_border, atoms->xdnd_aware, XA_ATOM,
2341 32, PropModeReplace, (
unsigned char* )&version, 1 );
2342 XChangeProperty( qt_xdisplay(), electric_left_border, atoms->xdnd_aware, XA_ATOM,
2343 32, PropModeReplace, (
unsigned char* )&version, 1 );
2344 XChangeProperty( qt_xdisplay(), electric_right_border, atoms->xdnd_aware, XA_ATOM,
2345 32, PropModeReplace, (
unsigned char* )&version, 1 );
2354 void Workspace::destroyBorderWindows()
2356 if( !electric_have_borders)
2359 electric_have_borders =
false;
2361 if(electric_top_border)
2362 XDestroyWindow(qt_xdisplay(),electric_top_border);
2363 if(electric_bottom_border)
2364 XDestroyWindow(qt_xdisplay(),electric_bottom_border);
2365 if(electric_left_border)
2366 XDestroyWindow(qt_xdisplay(),electric_left_border);
2367 if(electric_right_border)
2368 XDestroyWindow(qt_xdisplay(),electric_right_border);
2370 electric_top_border = None;
2371 electric_bottom_border = None;
2372 electric_left_border = None;
2373 electric_right_border = None;
2376 void Workspace::clientMoved(
const TQPoint &pos, Time now)
2378 if (options->electricBorders() == Options::ElectricDisabled)
2381 if ((pos.x() != electricLeft) &&
2382 (pos.x() != electricRight) &&
2383 (pos.y() != electricTop) &&
2384 (pos.y() != electricBottom))
2387 Time treshold_set = options->electricBorderDelay();
2388 Time treshold_reset = 250;
2389 int distance_reset = 30;
2392 if (pos.x() == electricLeft)
2394 else if (pos.x() == electricRight)
2396 else if (pos.y() == electricTop)
2398 else if (pos.y() == electricBottom)
2401 if ((electric_current_border == border) &&
2402 (timestampDiff(electric_time_last, now) < treshold_reset) &&
2403 ((pos-electric_push_point).manhattanLength() < distance_reset))
2405 electric_time_last = now;
2407 if (timestampDiff(electric_time_first, now) > treshold_set)
2409 electric_current_border = 0;
2411 TQRect r = TQApplication::desktop()->geometry();
2414 int desk_before = currentDesktop();
2418 slotSwitchDesktopLeft();
2419 if (currentDesktop() != desk_before)
2421 offset = r.width() / 5;
2422 TQCursor::setPos(r.width() - offset, pos.y());
2427 slotSwitchDesktopRight();
2428 if (currentDesktop() != desk_before)
2430 offset = r.width() / 5;
2431 TQCursor::setPos(offset, pos.y());
2436 slotSwitchDesktopUp();
2437 if (currentDesktop() != desk_before)
2439 offset = r.height() / 5;
2440 TQCursor::setPos(pos.x(), r.height() - offset);
2445 slotSwitchDesktopDown();
2446 if (currentDesktop() != desk_before)
2448 offset = r.height() / 5;
2449 TQCursor::setPos(pos.x(), offset);
2458 electric_current_border = border;
2459 electric_time_first = now;
2460 electric_time_last = now;
2461 electric_push_point = pos;
2469 case 1: TQCursor::setPos(pos.x()+mouse_warp, pos.y());
break;
2470 case 2: TQCursor::setPos(pos.x()-mouse_warp, pos.y());
break;
2471 case 3: TQCursor::setPos(pos.x(), pos.y()+mouse_warp);
break;
2472 case 4: TQCursor::setPos(pos.x(), pos.y()-mouse_warp);
break;
2478 bool Workspace::electricBorder(XEvent *e)
2480 if( !electric_have_borders )
2482 if( e->type == EnterNotify )
2484 if( e->xcrossing.window == electric_top_border ||
2485 e->xcrossing.window == electric_left_border ||
2486 e->xcrossing.window == electric_bottom_border ||
2487 e->xcrossing.window == electric_right_border)
2490 clientMoved( TQPoint( e->xcrossing.x_root, e->xcrossing.y_root ), e->xcrossing.time );
2494 if( e->type == ClientMessage )
2496 if( e->xclient.message_type == atoms->xdnd_position
2497 && ( e->xclient.window == electric_top_border
2498 || e->xclient.window == electric_bottom_border
2499 || e->xclient.window == electric_left_border
2500 || e->xclient.window == electric_right_border ))
2503 clientMoved( TQPoint( e->xclient.data.l[2]>>16, e->xclient.data.l[2]&0xffff), GET_QT_X_TIME() );
2513 void Workspace::raiseElectricBorders()
2516 if(electric_have_borders)
2518 XRaiseWindow(qt_xdisplay(), electric_top_border);
2519 XRaiseWindow(qt_xdisplay(), electric_left_border);
2520 XRaiseWindow(qt_xdisplay(), electric_bottom_border);
2521 XRaiseWindow(qt_xdisplay(), electric_right_border);
2525 void Workspace::addTopMenu( Client* c )
2527 assert( c->isTopMenu());
2528 assert( !topmenus.contains( c ));
2529 topmenus.append( c );
2530 if( managingTopMenus())
2532 int minsize = c->minSize().height();
2533 if( minsize > topMenuHeight())
2535 topmenu_height = minsize;
2536 updateTopMenuGeometry();
2538 updateTopMenuGeometry( c );
2539 updateCurrentTopMenu();
2544 void Workspace::removeTopMenu( Client* c )
2548 assert( c->isTopMenu());
2549 assert( topmenus.contains( c ));
2550 topmenus.remove( c );
2551 updateCurrentTopMenu();
2555 void Workspace::lostTopMenuSelection()
2559 disconnect( topmenu_watcher, TQT_SIGNAL( lostOwner()),
this, TQT_SLOT( lostTopMenuOwner()));
2560 connect( topmenu_watcher, TQT_SIGNAL( lostOwner()),
this, TQT_SLOT( lostTopMenuOwner()));
2561 if( !managing_topmenus )
2563 connect( topmenu_watcher, TQT_SIGNAL( lostOwner()),
this, TQT_SLOT( lostTopMenuOwner()));
2564 disconnect( topmenu_selection, TQT_SIGNAL( lostOwnership()),
this, TQT_SLOT( lostTopMenuSelection()));
2565 managing_topmenus =
false;
2566 delete topmenu_space;
2567 topmenu_space = NULL;
2569 for( ClientList::ConstIterator it = topmenus.begin();
2570 it != topmenus.end();
2572 (*it)->checkWorkspacePosition();
2575 void Workspace::lostTopMenuOwner()
2577 if( !options->topMenuEnabled())
2580 if( !topmenu_selection->claim(
false ))
2586 setupTopMenuHandling();
2589 void Workspace::setupTopMenuHandling()
2591 if( managing_topmenus )
2593 connect( topmenu_selection, TQT_SIGNAL( lostOwnership()),
this, TQT_SLOT( lostTopMenuSelection()));
2594 disconnect( topmenu_watcher, TQT_SIGNAL( lostOwner()),
this, TQT_SLOT( lostTopMenuOwner()));
2595 managing_topmenus =
true;
2596 topmenu_space =
new TQWidget;
2598 stack[ 0 ] = supportWindow->winId();
2599 stack[ 1 ] = topmenu_space->winId();
2600 XRestackWindows(qt_xdisplay(), stack, 2);
2601 updateTopMenuGeometry();
2602 topmenu_space->show();
2604 updateCurrentTopMenu();
2607 int Workspace::topMenuHeight()
const
2609 if( topmenu_height == 0 )
2612 tmpmenu.insertItem(
"dummy" );
2613 topmenu_height = tmpmenu.sizeHint().height();
2615 return topmenu_height;
2618 KDecoration* Workspace::createDecoration( KDecorationBridge* bridge )
2620 return mgr->createDecoration( bridge );
2623 TQString Workspace::desktopName(
int desk )
const
2625 return TQString::fromUtf8( rootInfo->desktopName( desk ) );
2628 bool Workspace::checkStartupNotification( Window w, KStartupInfoId&
id, KStartupInfoData& data )
2630 return startup->checkStartup( w,
id, data ) == KStartupInfo::Match;
2637 void Workspace::focusToNull()
2639 XSetInputFocus(qt_xdisplay(), null_focus_window, RevertToPointerRoot, GET_QT_X_TIME() );
2642 void Workspace::helperDialog(
const TQString& message,
const Client* c )
2646 if( message ==
"noborderaltf3" )
2648 TQString shortcut = TQString(
"%1 (%2)" ).arg( keys->label(
"Window Operations Menu" ))
2649 .arg( keys->shortcut(
"Window Operations Menu" ).seq( 0 ).toString());
2650 args <<
"--msgbox" <<
2651 i18n(
"You have selected to show a window without its border.\n"
2652 "Without the border, you will not be able to enable the border "
2653 "again using the mouse: use the window operations menu instead, "
2654 "activated using the %1 keyboard shortcut." )
2656 type =
"altf3warning";
2658 else if( message ==
"fullscreenaltf3" )
2660 TQString shortcut = TQString(
"%1 (%2)" ).arg( keys->label(
"Window Operations Menu" ))
2661 .arg( keys->shortcut(
"Window Operations Menu" ).seq( 0 ).toString());
2662 args <<
"--msgbox" <<
2663 i18n(
"You have selected to show a window in fullscreen mode.\n"
2664 "If the application itself does not have an option to turn the fullscreen "
2665 "mode off you will not be able to disable it "
2666 "again using the mouse: use the window operations menu instead, "
2667 "activated using the %1 keyboard shortcut." )
2669 type =
"altf3warning";
2674 proc <<
"kdialog" << args;
2675 if( !type.isEmpty())
2677 KConfig cfg(
"kwin_dialogsrc" );
2678 cfg.setGroup(
"Notification Messages" );
2679 if( !cfg.readBoolEntry( type,
true ))
2681 proc <<
"--dontagain" <<
"kwin_dialogsrc:" + type;
2684 proc <<
"--embed" << TQString::number( c->window());
2685 proc.start( KProcess::DontCare );
2691 void Workspace::startKompmgr()
2696 unsigned long length, after;
2697 unsigned char* data_root;
2699 prop_root = XInternAtom(qt_xdisplay(),
"_XROOTPMAP_ID", False);
2700 if( XGetWindowProperty( qt_xdisplay(), qt_xrootwin(), prop_root, 0L, 1L, False, AnyPropertyType, &type, &format, &length, &after, &data_root) == Success && data_root != NULL ) {
2705 TQTimer::singleShot( 200,
this, TQT_SLOT(startKompmgr()) );
2708 if (!kompmgr || kompmgr->isRunning())
2710 if (!kompmgr->start(KProcess::OwnGroup, KProcess::Stderr))
2712 options->useTranslucency = FALSE;
2714 proc <<
"kdialog" <<
"--error"
2715 << i18n(
"The Composite Manager could not be started.\\nMake sure you have \"kompmgr\" in a $PATH directory.")
2716 <<
"--title" <<
"Composite Manager Failure";
2717 proc.start(KProcess::DontCare);
2721 delete kompmgr_selection;
2722 char selection_name[ 100 ];
2723 sprintf( selection_name,
"_NET_WM_CM_S%d", DefaultScreen( qt_xdisplay()));
2724 kompmgr_selection =
new KSelectionOwner( selection_name );
2725 connect( kompmgr_selection, TQT_SIGNAL( lostOwnership()), TQT_SLOT( stopKompmgr()));
2726 kompmgr_selection->claim(
true );
2727 connect(kompmgr, TQT_SIGNAL(processExited(KProcess*)), TQT_SLOT(restartKompmgr(KProcess*)));
2728 options->useTranslucency = TRUE;
2732 TQDataStream arg(ba, IO_WriteOnly);
2734 kapp->dcopClient()->emitDCOPSignal(
"default",
"kompmgrStarted()", ba);
2736 if (popup){
delete popup; popup = 0L; }
2739 void Workspace::stopKompmgr()
2741 if (!kompmgr || !kompmgr->isRunning()) {
2744 delete kompmgr_selection;
2745 kompmgr_selection = NULL;
2746 kompmgr->disconnect(
this, TQT_SLOT(restartKompmgr(KProcess*)));
2747 options->useTranslucency = FALSE;
2748 if (popup){
delete popup; popup = 0L; }
2751 TQDataStream arg(ba, IO_WriteOnly);
2753 kapp->dcopClient()->emitDCOPSignal(
"default",
"kompmgrStopped()", ba);
2756 bool Workspace::kompmgrIsRunning()
2758 return kompmgr && kompmgr->isRunning();
2761 void Workspace::unblockKompmgrRestart()
2763 allowKompmgrRestart = TRUE;
2766 void Workspace::restartKompmgr( KProcess *proc )
2770 if (proc->signalled()) {
2771 int exit_signal_number = proc->exitSignal();
2772 if ( (exit_signal_number == SIGILL) || (exit_signal_number == SIGTRAP) || (exit_signal_number == SIGABRT) || (exit_signal_number == SIGSYS) || (exit_signal_number == SIGFPE) || (exit_signal_number == SIGBUS) || (exit_signal_number == SIGSEGV) ) {
2778 if (!allowKompmgrRestart)
2780 delete kompmgr_selection;
2781 kompmgr_selection = NULL;
2782 options->useTranslucency = FALSE;
2785 proc <<
"kdialog" <<
"--error"
2786 << i18n(
"The Composite Manager crashed twice within a minute and is therefore disabled for this session.")
2787 <<
"--title" << i18n(
"Composite Manager Failure");
2788 proc.start(KProcess::DontCare);
2802 if (!kompmgr->start(KProcess::NotifyOnExit, KProcess::Stderr))
2804 delete kompmgr_selection;
2805 kompmgr_selection = NULL;
2806 options->useTranslucency = FALSE;
2808 proc <<
"kdialog" <<
"--error"
2809 << i18n(
"The Composite Manager could not be started.\\nMake sure you have \"kompmgr\" in a $PATH directory.")
2810 <<
"--title" << i18n(
"Composite Manager Failure");
2811 proc.start(KProcess::DontCare);
2815 allowKompmgrRestart = FALSE;
2816 TQTimer::singleShot( 60000,
this, TQT_SLOT(unblockKompmgrRestart()) );
2821 void Workspace::handleKompmgrOutput( KProcess* ,
char *buffer,
int buflen)
2824 TQString output = TQString::fromLocal8Bit( buffer, buflen );
2825 if (output.contains(
"Started",
false))
2827 else if (output.contains(
"Can't open display",
false))
2828 message = i18n(
"<qt><b>kompmgr failed to open the display</b><br>There is probably an invalid display entry in your ~/.xcompmgrrc.</qt>");
2829 else if (output.contains(
"No render extension",
false))
2830 message = i18n(
"<qt><b>kompmgr cannot find the Xrender extension</b><br>You are using either an outdated or a crippled version of XOrg.<br>Get XOrg ≥ 6.8 from www.freedesktop.org.<br></qt>");
2831 else if (output.contains(
"No composite extension",
false))
2832 message = i18n(
"<qt><b>Composite extension not found</b><br>You <i>must</i> use XOrg ≥ 6.8 for translucency and shadows to work.<br>Additionally, you need to add a new section to your X config file:<br>"
2833 "<i>Section \"Extensions\"<br>"
2834 "Option \"Composite\" \"Enable\"<br>"
2835 "EndSection</i></qt>");
2836 else if (output.contains(
"No damage extension",
false))
2837 message = i18n(
"<qt><b>Damage extension not found</b><br>You <i>must</i> use XOrg ≥ 6.8 for translucency and shadows to work.</qt>");
2838 else if (output.contains(
"No XFixes extension",
false))
2839 message = i18n(
"<qt><b>XFixes extension not found</b><br>You <i>must</i> use XOrg ≥ 6.8 for translucency and shadows to work.</qt>");
2842 kompmgr->closeStderr();
2843 disconnect(kompmgr, TQT_SIGNAL(receivedStderr(KProcess*,
char*,
int)),
this, TQT_SLOT(handleKompmgrOutput(KProcess*,
char*,
int)));
2844 if( !message.isEmpty())
2847 proc <<
"kdialog" <<
"--error"
2849 <<
"--title" << i18n(
"Composite Manager Failure");
2850 proc.start(KProcess::DontCare);
2855 void Workspace::setOpacity(
unsigned long winId,
unsigned int opacityPercent)
2857 if (opacityPercent > 100) opacityPercent = 100;
2858 for( ClientList::ConstIterator it = stackingOrder().begin(); it != stackingOrder().end(); it++ )
2859 if (winId == (*it)->window())
2861 (*it)->setOpacity(opacityPercent < 100, (
unsigned int)((opacityPercent/100.0)*0xFFFFFFFF));
2866 void Workspace::setShadowSize(
unsigned long winId,
unsigned int shadowSizePercent)
2869 if (shadowSizePercent > 400) shadowSizePercent = 400;
2870 for( ClientList::ConstIterator it = stackingOrder().begin(); it != stackingOrder().end(); it++ )
2871 if (winId == (*it)->window())
2873 (*it)->setShadowSize(shadowSizePercent);
2878 void Workspace::setUnshadowed(
unsigned long winId)
2880 for( ClientList::ConstIterator it = stackingOrder().begin(); it != stackingOrder().end(); it++ )
2881 if (winId == (*it)->window())
2883 (*it)->setShadowSize(0);
2888 void Workspace::setShowingDesktop(
bool showing )
2890 rootInfo->setShowingDesktop( showing );
2891 showing_desktop = showing;
2892 ++block_showing_desktop;
2893 if( showing_desktop )
2895 showing_desktop_clients.clear();
2897 ClientList cls = stackingOrder();
2900 for( ClientList::ConstIterator it = cls.begin();
2904 if( (*it)->isOnCurrentDesktop() && (*it)->isShown(
true ) && !(*it)->isSpecialWindow())
2905 showing_desktop_clients.prepend( *it );
2907 for( ClientList::ConstIterator it = showing_desktop_clients.begin();
2908 it != showing_desktop_clients.end();
2910 (*it)->minimize(
true);
2912 if( Client* desk = findDesktop(
true, currentDesktop()))
2913 requestFocus( desk );
2917 for( ClientList::ConstIterator it = showing_desktop_clients.begin();
2918 it != showing_desktop_clients.end();
2920 (*it)->unminimize(
true);
2921 if( showing_desktop_clients.count() > 0 )
2922 requestFocus( showing_desktop_clients.first());
2923 showing_desktop_clients.clear();
2925 --block_showing_desktop;
2937 void Workspace::resetShowingDesktop(
bool keep_hidden )
2939 if( block_showing_desktop > 0 )
2941 rootInfo->setShowingDesktop(
false );
2942 showing_desktop =
false;
2943 ++block_showing_desktop;
2946 for( ClientList::ConstIterator it = showing_desktop_clients.begin();
2947 it != showing_desktop_clients.end();
2949 (*it)->unminimize(
true);
2951 showing_desktop_clients.clear();
2952 --block_showing_desktop;
2962 void Workspace::slotDisableGlobalShortcuts()
2964 if( global_shortcuts_disabled || global_shortcuts_disabled_for_client )
2965 disableGlobalShortcuts(
false );
2967 disableGlobalShortcuts(
true );
2970 static bool pending_dfc =
false;
2972 void Workspace::disableGlobalShortcutsForClient(
bool disable )
2974 if( global_shortcuts_disabled_for_client == disable )
2976 if( !global_shortcuts_disabled )
2980 KIPC::sendMessageAll( KIPC::BlockShortcuts, disable );
2985 void Workspace::disableGlobalShortcuts(
bool disable )
2987 KIPC::sendMessageAll( KIPC::BlockShortcuts, disable );
2991 void Workspace::kipcMessage(
int id,
int data )
2993 if(
id != KIPC::BlockShortcuts )
2995 if( pending_dfc && data )
2997 global_shortcuts_disabled_for_client =
true;
2998 pending_dfc =
false;
3002 global_shortcuts_disabled = data;
3003 global_shortcuts_disabled_for_client =
false;
3006 for( ClientList::ConstIterator it = clients.begin();
3007 it != clients.end();
3009 (*it)->updateMouseGrab();
3014 #include "workspace.moc"