00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "workspace.h"
00013
00014 #include <tdeapplication.h>
00015 #include <tdestartupinfo.h>
00016 #include <fixx11h.h>
00017 #include <tdeconfig.h>
00018 #include <tdeglobal.h>
00019 #include <tqpopupmenu.h>
00020 #include <tdelocale.h>
00021 #include <tqregexp.h>
00022 #include <tqpainter.h>
00023 #include <tqbitmap.h>
00024 #include <tqclipboard.h>
00025 #include <tdemenubar.h>
00026 #include <kprocess.h>
00027 #include <kglobalaccel.h>
00028 #include <dcopclient.h>
00029 #include <kipc.h>
00030
00031 #include "plugins.h"
00032 #include "client.h"
00033 #include "popupinfo.h"
00034 #include "tabbox.h"
00035 #include "atoms.h"
00036 #include "placement.h"
00037 #include "notifications.h"
00038 #include "group.h"
00039 #include "rules.h"
00040
00041 #include <X11/XKBlib.h>
00042 #include <X11/extensions/shape.h>
00043 #include <X11/keysym.h>
00044 #include <X11/keysymdef.h>
00045 #include <X11/cursorfont.h>
00046
00047 #include <pwd.h>
00048
00049 #include "config.h"
00050
00051 namespace KWinInternal
00052 {
00053
00054 extern int screen_number;
00055
00056 Workspace *Workspace::_self = 0;
00057
00058 TDEProcess* kompmgr = 0;
00059 TDESelectionOwner* kompmgr_selection;
00060
00061 bool allowKompmgrRestart = TRUE;
00062 extern bool disable_twin_composition_manager;
00063
00064 bool supportsCompMgr()
00065 {
00066 if (disable_twin_composition_manager) {
00067 return false;
00068 }
00069
00070 int i;
00071
00072 bool damageExt = XQueryExtension(tqt_xdisplay(), "DAMAGE", &i, &i, &i);
00073 bool compositeExt = XQueryExtension(tqt_xdisplay(), "Composite", &i, &i, &i);
00074 bool xfixesExt = XQueryExtension(tqt_xdisplay(), "XFIXES", &i, &i, &i);
00075
00076 return damageExt && compositeExt && xfixesExt;
00077 }
00078
00079 pid_t getCompositorPID() {
00080
00081 char *filename;
00082 const char *pidfile = "compton-tde.pid";
00083 char uidstr[sizeof(uid_t)*8+1];
00084 sprintf(uidstr, "%d", getuid());
00085 int n = strlen(P_tmpdir)+strlen(uidstr)+strlen(pidfile)+3;
00086 filename = (char*)malloc(n*sizeof(char)+1);
00087 memset(filename,0,n);
00088 strcat(filename, P_tmpdir);
00089 strcat(filename, "/.");
00090 strcat(filename, uidstr);
00091 strcat(filename, "-");
00092 strcat(filename, pidfile);
00093
00094
00095 FILE *pFile;
00096 char buffer[255];
00097 pFile = fopen(filename, "r");
00098 pid_t kompmgrpid = 0;
00099 if (pFile)
00100 {
00101 printf("[twin-workspace] Using '%s' as compton-tde pidfile\n\n", filename);
00102
00103 fseek (pFile , 0 , SEEK_END);
00104 unsigned long lSize = ftell (pFile);
00105 if (lSize > 254)
00106 lSize = 254;
00107 rewind (pFile);
00108 size_t result = fread (buffer, 1, lSize, pFile);
00109 fclose(pFile);
00110 if (result > 0)
00111 {
00112 kompmgrpid = atoi(buffer);
00113 }
00114 }
00115
00116 free(filename);
00117 filename = NULL;
00118
00119 return kompmgrpid;
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129 Workspace::Workspace( bool restore )
00130 : DCOPObject ("KWinInterface"),
00131 TQObject (0, "workspace"),
00132 current_desktop (0),
00133 number_of_desktops(0),
00134 active_screen (0),
00135 active_popup( NULL ),
00136 active_popup_client( NULL ),
00137 desktop_widget (0),
00138 temporaryRulesMessages( "_KDE_NET_WM_TEMPORARY_RULES", NULL, false ),
00139 rules_updates_disabled( false ),
00140 active_client (0),
00141 last_active_client (0),
00142 next_active_client (0),
00143 most_recently_raised (0),
00144 movingClient(0),
00145 pending_take_activity ( NULL ),
00146 delayfocus_client (0),
00147 showing_desktop( false ),
00148 block_showing_desktop( 0 ),
00149 was_user_interaction (false),
00150 session_saving (false),
00151 control_grab (false),
00152 tab_grab (false),
00153 mouse_emulation (false),
00154 block_focus (0),
00155 tab_box (0),
00156 popupinfo (0),
00157 popup (0),
00158 advanced_popup (0),
00159 desk_popup (0),
00160 desk_popup_index (0),
00161 keys (0),
00162 client_keys ( NULL ),
00163 client_keys_dialog ( NULL ),
00164 client_keys_client ( NULL ),
00165 disable_shortcuts_keys ( NULL ),
00166 global_shortcuts_disabled( false ),
00167 global_shortcuts_disabled_for_client( false ),
00168 root (0),
00169 workspaceInit (true),
00170 startup(0), electric_have_borders(false),
00171 electric_current_border(0),
00172 electric_top_border(None),
00173 electric_bottom_border(None),
00174 electric_left_border(None),
00175 electric_right_border(None),
00176 layoutOrientation(Qt::Vertical),
00177 layoutX(-1),
00178 layoutY(2),
00179 workarea(NULL),
00180 screenarea(NULL),
00181 managing_topmenus( false ),
00182 topmenu_selection( NULL ),
00183 topmenu_watcher( NULL ),
00184 topmenu_height( 0 ),
00185 topmenu_space( NULL ),
00186 set_active_client_recursion( 0 ),
00187 block_stacking_updates( 0 ),
00188 forced_global_mouse_grab( false )
00189 {
00190 _self = this;
00191 mgr = new PluginMgr;
00192 root = tqt_xrootwin();
00193 default_colormap = DefaultColormap(tqt_xdisplay(), tqt_xscreen() );
00194 installed_colormap = default_colormap;
00195 session.setAutoDelete( TRUE );
00196
00197 connect( &temporaryRulesMessages, TQT_SIGNAL( gotMessage( const TQString& )),
00198 this, TQT_SLOT( gotTemporaryRulesMessage( const TQString& )));
00199 connect( &rulesUpdatedTimer, TQT_SIGNAL( timeout()), this, TQT_SLOT( writeWindowRules()));
00200
00201 updateXTime();
00202
00203 delayFocusTimer = 0;
00204
00205 electric_time_first = GET_QT_X_TIME();
00206 electric_time_last = GET_QT_X_TIME();
00207
00208 if ( restore )
00209 loadSessionInfo();
00210
00211 loadWindowRules();
00212
00213 (void) TQApplication::desktop();
00214
00215 desktop_widget =
00216 new TQWidget(
00217 0,
00218 "desktop_widget",
00219 (WFlags)(TQt::WType_Desktop | TQt::WPaintUnclipped)
00220 );
00221
00222 kapp->setGlobalMouseTracking( true );
00223
00224 startup = new TDEStartupInfo(
00225 TDEStartupInfo::DisableKWinModule | TDEStartupInfo::AnnounceSilenceChanges, this );
00226
00227
00228 XSelectInput(tqt_xdisplay(), root,
00229 KeyPressMask |
00230 PropertyChangeMask |
00231 ColormapChangeMask |
00232 SubstructureRedirectMask |
00233 SubstructureNotifyMask |
00234 FocusChangeMask
00235 );
00236
00237 Shape::init();
00238
00239
00240 long data = 1;
00241
00242 XChangeProperty(
00243 tqt_xdisplay(),
00244 tqt_xrootwin(),
00245 atoms->twin_running,
00246 atoms->twin_running,
00247 32,
00248 PropModeAppend,
00249 (unsigned char*) &data,
00250 1
00251 );
00252
00253 client_keys = new TDEGlobalAccel( this );
00254 initShortcuts();
00255 tab_box = new TabBox( this );
00256 popupinfo = new PopupInfo( this );
00257
00258 init();
00259
00260 #if (TQT_VERSION-0 >= 0x030200) // XRANDR support
00261 connect( kapp->desktop(), TQT_SIGNAL( resized( int )), TQT_SLOT( desktopResized()));
00262 #endif
00263
00264 if (!supportsCompMgr()) {
00265 options->useTranslucency = false;
00266 }
00267
00268
00269
00270
00271 pid_t kompmgrpid = getCompositorPID();
00272
00273 if (options->useTranslucency)
00274 {
00275 kompmgr = new TDEProcess;
00276 connect(kompmgr, TQT_SIGNAL(receivedStderr(TDEProcess*, char*, int)), TQT_SLOT(handleKompmgrOutput(TDEProcess*, char*, int)));
00277 *kompmgr << TDE_COMPOSITOR_BINARY;
00278 if (kompmgrpid)
00279 {
00280 if (kill(kompmgrpid, 0) < 0)
00281 {
00282
00283 startKompmgr();
00284 }
00285 }
00286 else
00287 {
00288 startKompmgr();
00289 }
00290 }
00291 else if (!disable_twin_composition_manager)
00292 {
00293
00294 if (kompmgrpid)
00295 {
00296 kill(kompmgrpid, SIGTERM);
00297 }
00298 else
00299 {
00300 stopKompmgr();
00301 }
00302 }
00303 }
00304
00305
00306 void Workspace::init()
00307 {
00308 checkElectricBorders();
00309
00310
00311
00312
00313
00314 supportWindow = new TQWidget;
00315 XLowerWindow( tqt_xdisplay(), supportWindow->winId());
00316
00317 XSetWindowAttributes attr;
00318 attr.override_redirect = 1;
00319 null_focus_window = XCreateWindow( tqt_xdisplay(), tqt_xrootwin(), -1,-1, 1, 1, 0, CopyFromParent,
00320 InputOnly, CopyFromParent, CWOverrideRedirect, &attr );
00321 XMapWindow(tqt_xdisplay(), null_focus_window);
00322
00323 unsigned long protocols[ 5 ] =
00324 {
00325 NET::Supported |
00326 NET::SupportingWMCheck |
00327 NET::ClientList |
00328 NET::ClientListStacking |
00329 NET::DesktopGeometry |
00330 NET::NumberOfDesktops |
00331 NET::CurrentDesktop |
00332 NET::ActiveWindow |
00333 NET::WorkArea |
00334 NET::CloseWindow |
00335 NET::DesktopNames |
00336 NET::KDESystemTrayWindows |
00337 NET::WMName |
00338 NET::WMVisibleName |
00339 NET::WMDesktop |
00340 NET::WMWindowType |
00341 NET::WMState |
00342 NET::WMStrut |
00343 NET::WMIconGeometry |
00344 NET::WMIcon |
00345 NET::WMPid |
00346 NET::WMMoveResize |
00347 NET::WMKDESystemTrayWinFor |
00348 NET::WMFrameExtents |
00349 NET::WMPing
00350 ,
00351 NET::NormalMask |
00352 NET::DesktopMask |
00353 NET::DockMask |
00354 NET::ToolbarMask |
00355 NET::MenuMask |
00356 NET::DialogMask |
00357 NET::OverrideMask |
00358 NET::TopMenuMask |
00359 NET::UtilityMask |
00360 NET::SplashMask |
00361 0
00362 ,
00363 NET::Modal |
00364
00365 NET::MaxVert |
00366 NET::MaxHoriz |
00367 NET::Shaded |
00368 NET::SkipTaskbar |
00369 NET::KeepAbove |
00370
00371 NET::SkipPager |
00372 NET::Hidden |
00373 NET::FullScreen |
00374 NET::KeepBelow |
00375 NET::DemandsAttention |
00376 0
00377 ,
00378 NET::WM2UserTime |
00379 NET::WM2StartupId |
00380 NET::WM2AllowedActions |
00381 NET::WM2RestackWindow |
00382 NET::WM2MoveResizeWindow |
00383 NET::WM2ExtendedStrut |
00384 NET::WM2KDETemporaryRules |
00385 NET::WM2ShowingDesktop |
00386 NET::WM2FullPlacement |
00387 NET::WM2DesktopLayout |
00388 0
00389 ,
00390 NET::ActionMove |
00391 NET::ActionResize |
00392 NET::ActionMinimize |
00393 NET::ActionShade |
00394
00395 NET::ActionMaxVert |
00396 NET::ActionMaxHoriz |
00397 NET::ActionFullScreen |
00398 NET::ActionChangeDesktop |
00399 NET::ActionClose |
00400 0
00401 ,
00402 };
00403
00404 rootInfo = new RootInfo( this, tqt_xdisplay(), supportWindow->winId(), "KWin",
00405 protocols, 5, tqt_xscreen() );
00406
00407 loadDesktopSettings();
00408 updateDesktopLayout();
00409
00410 NETRootInfo client_info( tqt_xdisplay(), NET::ActiveWindow | NET::CurrentDesktop );
00411 int initial_desktop;
00412 if( !kapp->isSessionRestored())
00413 initial_desktop = client_info.currentDesktop();
00414 else
00415 {
00416 TDEConfigGroupSaver saver( kapp->sessionConfig(), "Session" );
00417 initial_desktop = kapp->sessionConfig()->readNumEntry( "desktop", 1 );
00418 }
00419 if( !setCurrentDesktop( initial_desktop ))
00420 setCurrentDesktop( 1 );
00421
00422
00423 initPositioning = new Placement(this);
00424
00425 connect(&reconfigureTimer, TQT_SIGNAL(timeout()), this,
00426 TQT_SLOT(slotReconfigure()));
00427 connect( &updateToolWindowsTimer, TQT_SIGNAL( timeout()), this, TQT_SLOT( slotUpdateToolWindows()));
00428
00429 connect(kapp, TQT_SIGNAL(appearanceChanged()), this,
00430 TQT_SLOT(slotReconfigure()));
00431 connect(kapp, TQT_SIGNAL(settingsChanged(int)), this,
00432 TQT_SLOT(slotSettingsChanged(int)));
00433 connect(kapp, TQT_SIGNAL( kipcMessage( int, int )), this, TQT_SLOT( kipcMessage( int, int )));
00434
00435 active_client = NULL;
00436 rootInfo->setActiveWindow( None );
00437 focusToNull();
00438 if( !kapp->isSessionRestored())
00439 ++block_focus;
00440
00441 char nm[ 100 ];
00442 sprintf( nm, "_KDE_TOPMENU_OWNER_S%d", DefaultScreen( tqt_xdisplay()));
00443 Atom topmenu_atom = XInternAtom( tqt_xdisplay(), nm, False );
00444 topmenu_selection = new TDESelectionOwner( topmenu_atom );
00445 topmenu_watcher = new TDESelectionWatcher( topmenu_atom );
00446
00447
00448 {
00449 StackingUpdatesBlocker blocker( this );
00450
00451 if( options->topMenuEnabled() && topmenu_selection->claim( false ))
00452 setupTopMenuHandling();
00453 else
00454 lostTopMenuSelection();
00455
00456 unsigned int i, nwins;
00457 Window root_return, parent_return, *wins;
00458 XQueryTree(tqt_xdisplay(), root, &root_return, &parent_return, &wins, &nwins);
00459 for (i = 0; i < nwins; i++)
00460 {
00461 XWindowAttributes attr;
00462 XGetWindowAttributes(tqt_xdisplay(), wins[i], &attr);
00463 if (attr.override_redirect )
00464 continue;
00465 if( topmenu_space && topmenu_space->winId() == wins[ i ] )
00466 continue;
00467 if (attr.map_state != IsUnmapped)
00468 {
00469 if ( addSystemTrayWin( wins[i] ) )
00470 continue;
00471 Client* c = createClient( wins[i], true );
00472 if ( c != NULL && root != tqt_xrootwin() )
00473 {
00474
00475 XReparentWindow( tqt_xdisplay(), c->frameId(), root, 0, 0 );
00476 c->move(0,0);
00477 }
00478 }
00479 }
00480 if ( wins )
00481 XFree((void *) wins);
00482
00483 updateStackingOrder( true );
00484
00485 updateClientArea();
00486 raiseElectricBorders();
00487
00488
00489 NETPoint* viewports = new NETPoint[ number_of_desktops ];
00490 rootInfo->setDesktopViewport( number_of_desktops, *viewports );
00491 delete[] viewports;
00492 TQRect geom = TQApplication::desktop()->geometry();
00493 NETSize desktop_geometry;
00494 desktop_geometry.width = geom.width();
00495 desktop_geometry.height = geom.height();
00496 rootInfo->setDesktopGeometry( -1, desktop_geometry );
00497 setShowingDesktop( false );
00498
00499 }
00500
00501 Client* new_active_client = NULL;
00502 if( !kapp->isSessionRestored())
00503 {
00504 --block_focus;
00505 new_active_client = findClient( WindowMatchPredicate( client_info.activeWindow()));
00506 }
00507 if( new_active_client == NULL
00508 && activeClient() == NULL && should_get_focus.count() == 0 )
00509 {
00510 if( new_active_client == NULL )
00511 new_active_client = topClientOnDesktop( currentDesktop());
00512 if( new_active_client == NULL && !desktops.isEmpty() )
00513 new_active_client = findDesktop( true, currentDesktop());
00514 }
00515 if( new_active_client != NULL )
00516 activateClient( new_active_client );
00517
00518
00519
00520 workspaceInit = false;
00521
00522 }
00523
00524 Workspace::~Workspace()
00525 {
00526 if (kompmgr)
00527 delete kompmgr;
00528 blockStackingUpdates( true );
00529
00530
00531 for( ClientList::ConstIterator it = stacking_order.begin();
00532 it != stacking_order.end();
00533 ++it )
00534 {
00535
00536 (*it)->releaseWindow( true );
00537
00538
00539
00540 clients.remove( *it );
00541 desktops.remove( *it );
00542 }
00543 delete desktop_widget;
00544 delete tab_box;
00545 delete popupinfo;
00546 delete popup;
00547 if ( root == tqt_xrootwin() )
00548 XDeleteProperty(tqt_xdisplay(), tqt_xrootwin(), atoms->twin_running);
00549
00550 writeWindowRules();
00551 TDEGlobal::config()->sync();
00552
00553 delete rootInfo;
00554 delete supportWindow;
00555 delete mgr;
00556 delete[] workarea;
00557 delete[] screenarea;
00558 delete startup;
00559 delete initPositioning;
00560 delete topmenu_watcher;
00561 delete topmenu_selection;
00562 delete topmenu_space;
00563 delete client_keys_dialog;
00564 while( !rules.isEmpty())
00565 {
00566 delete rules.front();
00567 rules.pop_front();
00568 }
00569 XDestroyWindow( tqt_xdisplay(), null_focus_window );
00570
00571 _self = 0;
00572 }
00573
00574 Client* Workspace::createClient( Window w, bool is_mapped )
00575 {
00576 StackingUpdatesBlocker blocker( this );
00577 Client* c = new Client( this );
00578 if( !c->manage( w, is_mapped ))
00579 {
00580 Client::deleteClient( c, Allowed );
00581 return NULL;
00582 }
00583 addClient( c, Allowed );
00584 return c;
00585 }
00586
00587 void Workspace::addClient( Client* c, allowed_t )
00588 {
00589
00590
00591 c->setBMP(c->resourceName() == "beep-media-player" || c->decorationId() == None);
00592
00593 c->getWindowOpacity();
00594 if (c->isDock())
00595 {
00596
00597 if (!c->hasCustomOpacity())
00598 {
00599 c->setShadowSize(options->dockShadowSize);
00600 c->setOpacity(options->translucentDocks, options->dockOpacity);
00601 }
00602 }
00603
00604 if (c->isMenu() || c->isTopMenu())
00605 {
00606 c->setShadowSize(options->menuShadowSize);
00607 }
00608
00609 Group* grp = findGroup( c->window());
00610 if( grp != NULL )
00611 grp->gotLeader( c );
00612
00613 if ( c->isDesktop() )
00614 {
00615 desktops.append( c );
00616 if( active_client == NULL && should_get_focus.isEmpty() && c->isOnCurrentDesktop())
00617 requestFocus( c );
00618 }
00619 else
00620 {
00621 updateFocusChains( c, FocusChainUpdate );
00622 clients.append( c );
00623 }
00624 if( !unconstrained_stacking_order.contains( c ))
00625 unconstrained_stacking_order.append( c );
00626 if( !stacking_order.contains( c ))
00627 stacking_order.append( c );
00628 if( c->isTopMenu())
00629 addTopMenu( c );
00630 updateClientArea();
00631 updateClientLayer( c );
00632 if( c->isDesktop())
00633 {
00634 raiseClient( c );
00635
00636 if( activeClient() == NULL && should_get_focus.count() == 0 )
00637 activateClient( findDesktop( true, currentDesktop()));
00638 }
00639 c->checkActiveModal();
00640 checkTransients( c->window());
00641 updateStackingOrder( true );
00642 if( c->isUtility() || c->isMenu() || c->isToolbar())
00643 updateToolWindows( true );
00644 checkNonExistentClients();
00645 }
00646
00647
00648
00649
00650 void Workspace::removeClient( Client* c, allowed_t )
00651 {
00652 if (c == active_popup_client)
00653 closeActivePopup();
00654
00655 if( client_keys_client == c )
00656 setupWindowShortcutDone( false );
00657 if( !c->shortcut().isNull())
00658 c->setShortcut( TQString::null );
00659
00660 if( c->isDialog())
00661 Notify::raise( Notify::TransDelete );
00662 if( c->isNormalWindow())
00663 Notify::raise( Notify::Delete );
00664
00665 Q_ASSERT( clients.contains( c ) || desktops.contains( c ));
00666 clients.remove( c );
00667 desktops.remove( c );
00668 unconstrained_stacking_order.remove( c );
00669 stacking_order.remove( c );
00670 for( int i = 1;
00671 i <= numberOfDesktops();
00672 ++i )
00673 focus_chain[ i ].remove( c );
00674 global_focus_chain.remove( c );
00675 attention_chain.remove( c );
00676 showing_desktop_clients.remove( c );
00677 if( c->isTopMenu())
00678 removeTopMenu( c );
00679 Group* group = findGroup( c->window());
00680 if( group != NULL )
00681 group->lostLeader();
00682
00683 if ( c == most_recently_raised )
00684 most_recently_raised = 0;
00685 should_get_focus.remove( c );
00686 Q_ASSERT( c != active_client );
00687 if ( c == last_active_client )
00688 last_active_client = 0;
00689 if( c == pending_take_activity )
00690 pending_take_activity = NULL;
00691 if( c == delayfocus_client )
00692 cancelDelayFocus();
00693
00694 updateStackingOrder( true );
00695
00696 if (tab_grab)
00697 tab_box->repaint();
00698
00699 updateClientArea();
00700 }
00701
00702 void Workspace::updateFocusChains( Client* c, FocusChainChange change )
00703 {
00704 if( !c->wantsTabFocus())
00705 {
00706 for( int i=1;
00707 i<= numberOfDesktops();
00708 ++i )
00709 focus_chain[i].remove(c);
00710 global_focus_chain.remove( c );
00711 return;
00712 }
00713 if(c->desktop() == NET::OnAllDesktops)
00714 {
00715 for( int i=1; i<= numberOfDesktops(); i++)
00716 {
00717 if( i == currentDesktop()
00718 && ( change == FocusChainMakeFirst || change == FocusChainMakeLast ))
00719 {
00720 focus_chain[ i ].remove( c );
00721 if( change == FocusChainMakeFirst )
00722 focus_chain[ i ].append( c );
00723 else
00724 focus_chain[ i ].prepend( c );
00725 }
00726 else if( !focus_chain[ i ].contains( c ))
00727 {
00728 if( active_client != NULL && active_client != c
00729 && !focus_chain[ i ].isEmpty() && focus_chain[ i ].last() == active_client )
00730 focus_chain[ i ].insert( focus_chain[ i ].fromLast(), c );
00731 else
00732 focus_chain[ i ].append( c );
00733 }
00734 }
00735 }
00736 else
00737 {
00738 for( int i=1; i<= numberOfDesktops(); i++)
00739 {
00740 if( i == c->desktop())
00741 {
00742 if( change == FocusChainMakeFirst )
00743 {
00744 focus_chain[ i ].remove( c );
00745 focus_chain[ i ].append( c );
00746 }
00747 else if( change == FocusChainMakeLast )
00748 {
00749 focus_chain[ i ].remove( c );
00750 focus_chain[ i ].prepend( c );
00751 }
00752 else if( !focus_chain[ i ].contains( c ))
00753 {
00754 if( active_client != NULL && active_client != c
00755 && !focus_chain[ i ].isEmpty() && focus_chain[ i ].last() == active_client )
00756 focus_chain[ i ].insert( focus_chain[ i ].fromLast(), c );
00757 else
00758 focus_chain[ i ].append( c );
00759 }
00760 }
00761 else
00762 focus_chain[ i ].remove( c );
00763 }
00764 }
00765 if( change == FocusChainMakeFirst )
00766 {
00767 global_focus_chain.remove( c );
00768 global_focus_chain.append( c );
00769 }
00770 else if( change == FocusChainMakeLast )
00771 {
00772 global_focus_chain.remove( c );
00773 global_focus_chain.prepend( c );
00774 }
00775 else if( !global_focus_chain.contains( c ))
00776 {
00777 if( active_client != NULL && active_client != c
00778 && !global_focus_chain.isEmpty() && global_focus_chain.last() == active_client )
00779 global_focus_chain.insert( global_focus_chain.fromLast(), c );
00780 else
00781 global_focus_chain.append( c );
00782 }
00783 }
00784
00785 void Workspace::updateOverlappingShadows(unsigned long window)
00786 {
00787 Client *client;
00788
00789 if ((client = findClient(WindowMatchPredicate((WId)window))))
00790
00791
00792 client->drawOverlappingShadows(false);
00793 }
00794
00795 void Workspace::setShadowed(unsigned long window, bool shadowed)
00796 {
00797 Client *client;
00798
00799 if ((client = findClient(WindowMatchPredicate((WId)window))))
00800 client->setShadowed(shadowed);
00801 }
00802
00803 void Workspace::updateCurrentTopMenu()
00804 {
00805 if( !managingTopMenus())
00806 return;
00807
00808 Client* menubar = 0;
00809 bool block_desktop_menubar = false;
00810 if( active_client )
00811 {
00812
00813 Client* menu_client = active_client;
00814 for(;;)
00815 {
00816 if( menu_client->isFullScreen())
00817 block_desktop_menubar = true;
00818 for( ClientList::ConstIterator it = menu_client->transients().begin();
00819 it != menu_client->transients().end();
00820 ++it )
00821 if( (*it)->isTopMenu())
00822 {
00823 menubar = *it;
00824 break;
00825 }
00826 if( menubar != NULL || !menu_client->isTransient())
00827 break;
00828 if( menu_client->isModal() || menu_client->transientFor() == NULL )
00829 break;
00830 menu_client = menu_client->transientFor();
00831 }
00832 if( !menubar )
00833 {
00834 for( ClientList::ConstIterator it = active_client->group()->members().begin();
00835 it != active_client->group()->members().end();
00836 ++it )
00837 if( (*it)->isTopMenu())
00838 {
00839 menubar = *it;
00840 break;
00841 }
00842 }
00843 }
00844 if( !menubar && !block_desktop_menubar && options->desktopTopMenu())
00845 {
00846
00847 Client* desktop = findDesktop( true, currentDesktop());
00848 if( desktop != NULL )
00849 {
00850 for( ClientList::ConstIterator it = desktop->transients().begin();
00851 it != desktop->transients().end();
00852 ++it )
00853 if( (*it)->isTopMenu())
00854 {
00855 menubar = *it;
00856 break;
00857 }
00858 }
00859
00860
00861
00862 if( menubar == NULL )
00863 {
00864 for( ClientList::ConstIterator it = topmenus.begin();
00865 it != topmenus.end();
00866 ++it )
00867 if( (*it)->wasOriginallyGroupTransient())
00868 {
00869 menubar = *it;
00870 break;
00871 }
00872 }
00873 }
00874
00875
00876 if ( menubar )
00877 {
00878 if( active_client && !menubar->isOnDesktop( active_client->desktop()))
00879 menubar->setDesktop( active_client->desktop());
00880 menubar->hideClient( false );
00881 topmenu_space->hide();
00882
00883
00884
00885 unconstrained_stacking_order.remove( menubar );
00886 unconstrained_stacking_order.append( menubar );
00887 }
00888 else if( !block_desktop_menubar )
00889 {
00890 topmenu_space->show();
00891 }
00892
00893
00894 for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
00895 {
00896 if( (*it)->isTopMenu() && (*it) != menubar )
00897 (*it)->hideClient( true );
00898 }
00899 }
00900
00901
00902 void Workspace::updateToolWindows( bool also_hide )
00903 {
00904
00905 if( !options->hideUtilityWindowsForInactive )
00906 {
00907 for( ClientList::ConstIterator it = clients.begin();
00908 it != clients.end();
00909 ++it )
00910 (*it)->hideClient( false );
00911 return;
00912 }
00913 const Group* group = NULL;
00914 const Client* client = active_client;
00915
00916
00917 while( client != NULL )
00918 {
00919 if( !client->isTransient())
00920 break;
00921 if( client->groupTransient())
00922 {
00923 group = client->group();
00924 break;
00925 }
00926 client = client->transientFor();
00927 }
00928
00929
00930
00931
00932 ClientList to_show, to_hide;
00933 for( ClientList::ConstIterator it = stacking_order.begin();
00934 it != stacking_order.end();
00935 ++it )
00936 {
00937 if( (*it)->isUtility() || (*it)->isMenu() || (*it)->isToolbar())
00938 {
00939 bool show = true;
00940 if( !(*it)->isTransient())
00941 {
00942 if( (*it)->group()->members().count() == 1 )
00943 show = true;
00944 else if( client != NULL && (*it)->group() == client->group())
00945 show = true;
00946 else
00947 show = false;
00948 }
00949 else
00950 {
00951 if( group != NULL && (*it)->group() == group )
00952 show = true;
00953 else if( client != NULL && client->hasTransient( (*it), true ))
00954 show = true;
00955 else
00956 show = false;
00957 }
00958 if( !show && also_hide )
00959 {
00960 const ClientList mainclients = (*it)->mainClients();
00961
00962
00963 if( mainclients.isEmpty())
00964 show = true;
00965 for( ClientList::ConstIterator it2 = mainclients.begin();
00966 it2 != mainclients.end();
00967 ++it2 )
00968 {
00969 if( (*it2)->isSpecialWindow())
00970 show = true;
00971 }
00972 if( !show )
00973 to_hide.append( *it );
00974 }
00975 if( show )
00976 to_show.append( *it );
00977 }
00978 }
00979 for( ClientList::ConstIterator it = to_show.fromLast();
00980 it != to_show.end();
00981 --it )
00982
00983 (*it)->hideClient( false );
00984 if( also_hide )
00985 {
00986 for( ClientList::ConstIterator it = to_hide.begin();
00987 it != to_hide.end();
00988 ++it )
00989 (*it)->hideClient( true );
00990 updateToolWindowsTimer.stop();
00991 }
00992 else
00993 {
00994 updateToolWindowsTimer.start( 50, true );
00995 }
00996 }
00997
00998 void Workspace::slotUpdateToolWindows()
00999 {
01000 updateToolWindows( true );
01001 }
01002
01006 void Workspace::updateColormap()
01007 {
01008 Colormap cmap = default_colormap;
01009 if ( activeClient() && activeClient()->colormap() != None )
01010 cmap = activeClient()->colormap();
01011 if ( cmap != installed_colormap )
01012 {
01013 XInstallColormap(tqt_xdisplay(), cmap );
01014 installed_colormap = cmap;
01015 }
01016 }
01017
01018 void Workspace::reconfigure()
01019 {
01020 reconfigureTimer.start(200, true);
01021 }
01022
01023
01024 void Workspace::slotSettingsChanged(int category)
01025 {
01026 kdDebug(1212) << "Workspace::slotSettingsChanged()" << endl;
01027 if( category == (int) TDEApplication::SETTINGS_SHORTCUTS )
01028 readShortcuts();
01029 }
01030
01034 KWIN_PROCEDURE( CheckBorderSizesProcedure, cl->checkBorderSizes() );
01035
01036 void Workspace::slotReconfigure()
01037 {
01038 kdDebug(1212) << "Workspace::slotReconfigure()" << endl;
01039 reconfigureTimer.stop();
01040
01041 TDEGlobal::config()->reparseConfiguration();
01042 unsigned long changed = options->updateSettings();
01043 tab_box->reconfigure();
01044 popupinfo->reconfigure();
01045 initPositioning->reinitCascading( 0 );
01046 readShortcuts();
01047 forEachClient( CheckIgnoreFocusStealingProcedure());
01048 updateToolWindows( true );
01049
01050 if( mgr->reset( changed ))
01051 {
01052 #if 0 // This actually seems to make things worse now
01053 TQWidget curtain;
01054 curtain.setBackgroundMode( NoBackground );
01055 curtain.setGeometry( TQApplication::desktop()->geometry() );
01056 curtain.show();
01057 #endif
01058 for( ClientList::ConstIterator it = clients.begin();
01059 it != clients.end();
01060 ++it )
01061 {
01062 (*it)->updateDecoration( true, true );
01063 }
01064 mgr->destroyPreviousPlugin();
01065 }
01066 else
01067 {
01068 forEachClient( CheckBorderSizesProcedure());
01069 }
01070
01071 checkElectricBorders();
01072
01073 if( options->topMenuEnabled() && !managingTopMenus())
01074 {
01075 if( topmenu_selection->claim( false ))
01076 setupTopMenuHandling();
01077 else
01078 lostTopMenuSelection();
01079 }
01080 else if( !options->topMenuEnabled() && managingTopMenus())
01081 {
01082 topmenu_selection->release();
01083 lostTopMenuSelection();
01084 }
01085 topmenu_height = 0;
01086 if( managingTopMenus())
01087 {
01088 updateTopMenuGeometry();
01089 updateCurrentTopMenu();
01090 }
01091
01092 loadWindowRules();
01093 for( ClientList::Iterator it = clients.begin();
01094 it != clients.end();
01095 ++it )
01096 {
01097 (*it)->setupWindowRules( true );
01098 (*it)->applyWindowRules();
01099 discardUsedWindowRules( *it, false );
01100 }
01101
01102 if (options->resetKompmgr)
01103 {
01104 bool tmp = options->useTranslucency;
01105
01106
01107
01108 char *filename;
01109 const char *pidfile = "compton-tde.pid";
01110 char uidstr[sizeof(uid_t)*8+1];
01111 sprintf(uidstr, "%d", getuid());
01112 int n = strlen(P_tmpdir)+strlen(uidstr)+strlen(pidfile)+3;
01113 filename = (char*)malloc(n*sizeof(char)+1);
01114 memset(filename,0,n);
01115 strcat(filename, P_tmpdir);
01116 strcat(filename, "/.");
01117 strcat(filename, uidstr);
01118 strcat(filename, "-");
01119 strcat(filename, pidfile);
01120
01121
01122 FILE *pFile;
01123 char buffer[255];
01124 pFile = fopen(filename, "r");
01125 int kompmgrpid = 0;
01126 if (pFile)
01127 {
01128 printf("[twin-workspace] Using '%s' as compton-tde pidfile\n\n", filename);
01129
01130 fseek (pFile , 0 , SEEK_END);
01131 unsigned long lSize = ftell (pFile);
01132 if (lSize > 254)
01133 lSize = 254;
01134 rewind (pFile);
01135 size_t result = fread (buffer, 1, lSize, pFile);
01136 fclose(pFile);
01137 if (result > 0)
01138 {
01139 kompmgrpid = atoi(buffer);
01140 }
01141 }
01142
01143 free(filename);
01144 filename = NULL;
01145
01146 if (tmp)
01147 {
01148 if (kompmgrpid)
01149 {
01150 kill(kompmgrpid, SIGUSR2);
01151 }
01152 else
01153 {
01154 stopKompmgr();
01155 if (!kompmgr)
01156 {
01157 kompmgr = new TDEProcess;
01158 connect(kompmgr, TQT_SIGNAL(receivedStderr(TDEProcess*, char*, int)), TQT_SLOT(handleKompmgrOutput(TDEProcess*, char*, int)));
01159 *kompmgr << TDE_COMPOSITOR_BINARY;
01160 }
01161 TQTimer::singleShot( 200, this, TQT_SLOT(startKompmgr()) );
01162 }
01163 }
01164 else
01165 {
01166 if (kompmgrpid)
01167 {
01168 kill(kompmgrpid, SIGTERM);
01169 }
01170 else
01171 {
01172 stopKompmgr();
01173 }
01174 }
01175 }
01176 }
01177
01178 void Workspace::loadDesktopSettings()
01179 {
01180 TDEConfig* c = TDEGlobal::config();
01181 TQCString groupname;
01182 if (screen_number == 0)
01183 groupname = "Desktops";
01184 else
01185 groupname.sprintf("Desktops-screen-%d", screen_number);
01186 TDEConfigGroupSaver saver(c,groupname);
01187
01188 int n = c->readNumEntry("Number", 4);
01189 number_of_desktops = n;
01190 delete workarea;
01191 workarea = new TQRect[ n + 1 ];
01192 delete screenarea;
01193 screenarea = NULL;
01194 rootInfo->setNumberOfDesktops( number_of_desktops );
01195 desktop_focus_chain.resize( n );
01196
01197 focus_chain.resize( n + 1 );
01198 for(int i = 1; i <= n; i++)
01199 {
01200 TQString s = c->readEntry(TQString("Name_%1").arg(i),
01201 i18n("Desktop %1").arg(i));
01202 rootInfo->setDesktopName( i, s.utf8().data() );
01203 desktop_focus_chain[i-1] = i;
01204 }
01205 }
01206
01207 void Workspace::saveDesktopSettings()
01208 {
01209 TDEConfig* c = TDEGlobal::config();
01210 TQCString groupname;
01211 if (screen_number == 0)
01212 groupname = "Desktops";
01213 else
01214 groupname.sprintf("Desktops-screen-%d", screen_number);
01215 TDEConfigGroupSaver saver(c,groupname);
01216
01217 c->writeEntry("Number", number_of_desktops );
01218 for(int i = 1; i <= number_of_desktops; i++)
01219 {
01220 TQString s = desktopName( i );
01221 TQString defaultvalue = i18n("Desktop %1").arg(i);
01222 if ( s.isEmpty() )
01223 {
01224 s = defaultvalue;
01225 rootInfo->setDesktopName( i, s.utf8().data() );
01226 }
01227
01228 if (s != defaultvalue)
01229 {
01230 c->writeEntry( TQString("Name_%1").arg(i), s );
01231 }
01232 else
01233 {
01234 TQString currentvalue = c->readEntry(TQString("Name_%1").arg(i));
01235 if (currentvalue != defaultvalue)
01236 c->writeEntry( TQString("Name_%1").arg(i), "" );
01237 }
01238 }
01239 }
01240
01241 TQStringList Workspace::configModules(bool controlCenter)
01242 {
01243 TQStringList args;
01244 args << "tde-twindecoration.desktop";
01245 if (controlCenter)
01246 args << "tde-twinoptions.desktop";
01247 else if (kapp->authorizeControlModule("tde-twinoptions.desktop"))
01248 args << "twinactions" << "twinfocus" << "twinmoving" << "twinadvanced" << "twinrules" << "twintranslucency";
01249 return args;
01250 }
01251
01252 void Workspace::configureWM()
01253 {
01254 TDEApplication::tdeinitExec( "tdecmshell", configModules(false) );
01255 }
01256
01260 void Workspace::doNotManage( TQString title )
01261 {
01262 doNotManageList.append( title );
01263 }
01264
01268 bool Workspace::isNotManaged( const TQString& title )
01269 {
01270 for ( TQStringList::Iterator it = doNotManageList.begin(); it != doNotManageList.end(); ++it )
01271 {
01272 TQRegExp r( (*it) );
01273 if (r.search(title) != -1)
01274 {
01275 doNotManageList.remove( it );
01276 return TRUE;
01277 }
01278 }
01279 return FALSE;
01280 }
01281
01285 void Workspace::refresh()
01286 {
01287 TQWidget w;
01288 w.setGeometry( TQApplication::desktop()->geometry() );
01289 w.show();
01290 w.hide();
01291 TQApplication::flushX();
01292 }
01293
01301 class ObscuringWindows
01302 {
01303 public:
01304 ~ObscuringWindows();
01305 void create( Client* c );
01306 private:
01307 TQValueList<Window> obscuring_windows;
01308 static TQValueList<Window>* cached;
01309 static unsigned int max_cache_size;
01310 };
01311
01312 TQValueList<Window>* ObscuringWindows::cached = 0;
01313 unsigned int ObscuringWindows::max_cache_size = 0;
01314
01315 void ObscuringWindows::create( Client* c )
01316 {
01317 if( cached == 0 )
01318 cached = new TQValueList<Window>;
01319 Window obs_win;
01320 XWindowChanges chngs;
01321 int mask = CWSibling | CWStackMode;
01322 if( cached->count() > 0 )
01323 {
01324 cached->remove( obs_win = cached->first());
01325 chngs.x = c->x();
01326 chngs.y = c->y();
01327 chngs.width = c->width();
01328 chngs.height = c->height();
01329 mask |= CWX | CWY | CWWidth | CWHeight;
01330 }
01331 else
01332 {
01333 XSetWindowAttributes a;
01334 a.background_pixmap = None;
01335 a.override_redirect = True;
01336 obs_win = XCreateWindow( tqt_xdisplay(), tqt_xrootwin(), c->x(), c->y(),
01337 c->width(), c->height(), 0, CopyFromParent, InputOutput,
01338 CopyFromParent, CWBackPixmap | CWOverrideRedirect, &a );
01339 }
01340 chngs.sibling = c->frameId();
01341 chngs.stack_mode = Below;
01342 XConfigureWindow( tqt_xdisplay(), obs_win, mask, &chngs );
01343 XMapWindow( tqt_xdisplay(), obs_win );
01344 obscuring_windows.append( obs_win );
01345 }
01346
01347 ObscuringWindows::~ObscuringWindows()
01348 {
01349 max_cache_size = TQMAX( max_cache_size, obscuring_windows.count() + 4 ) - 1;
01350 for( TQValueList<Window>::ConstIterator it = obscuring_windows.begin();
01351 it != obscuring_windows.end();
01352 ++it )
01353 {
01354 XUnmapWindow( tqt_xdisplay(), *it );
01355 if( cached->count() < max_cache_size )
01356 cached->prepend( *it );
01357 else
01358 XDestroyWindow( tqt_xdisplay(), *it );
01359 }
01360 }
01361
01362
01369 bool Workspace::setCurrentDesktop( int new_desktop )
01370 {
01371 if (new_desktop < 1 || new_desktop > number_of_desktops )
01372 return false;
01373
01374 closeActivePopup();
01375 ++block_focus;
01376
01377 StackingUpdatesBlocker blocker( this );
01378
01379 int old_desktop = current_desktop;
01380 if (new_desktop != current_desktop)
01381 {
01382 ++block_showing_desktop;
01383
01384
01385
01386
01387 Notify::raise((Notify::Event) (Notify::DesktopChange+new_desktop));
01388
01389 ObscuringWindows obs_wins;
01390
01391 current_desktop = new_desktop;
01392
01393 bool desktopHasCompositing = kapp->isCompositionManagerAvailable();
01394 if (!desktopHasCompositing) {
01395
01396 for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it) {
01397 if ( !(*it)->isOnDesktop( new_desktop ) && (*it) != movingClient )
01398 {
01399 if( (*it)->isShown( true ) && (*it)->isOnDesktop( old_desktop )) {
01400 obs_wins.create( *it );
01401 }
01402 (*it)->updateVisibility();
01403 }
01404 }
01405 }
01406
01407 rootInfo->setCurrentDesktop( current_desktop );
01408
01409 if( movingClient && !movingClient->isOnDesktop( new_desktop ))
01410 movingClient->setDesktop( new_desktop );
01411
01412 for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
01413 if ( (*it)->isOnDesktop( new_desktop ) ) {
01414 (*it)->updateVisibility();
01415 }
01416 }
01417
01418 if (desktopHasCompositing) {
01419
01420
01421 XSync( tqt_xdisplay(), false);
01422 for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it) {
01423 if ( !(*it)->isOnDesktop( new_desktop ) && (*it) != movingClient )
01424 {
01425 if( (*it)->isShown( true ) && (*it)->isOnDesktop( old_desktop )) {
01426 obs_wins.create( *it );
01427 }
01428 (*it)->updateVisibility();
01429 }
01430 }
01431 }
01432
01433 --block_showing_desktop;
01434 if( showingDesktop())
01435 resetShowingDesktop( false );
01436 }
01437
01438
01439 --block_focus;
01440 Client* c = 0;
01441
01442 if ( options->focusPolicyIsReasonable())
01443 {
01444
01445 if ( movingClient != NULL && active_client == movingClient
01446 && focus_chain[currentDesktop()].contains( active_client )
01447 && active_client->isShown( true ) && active_client->isOnCurrentDesktop())
01448 {
01449 c = active_client;
01450 }
01451 if ( !c )
01452 {
01453 for( ClientList::ConstIterator it = focus_chain[currentDesktop()].fromLast();
01454 it != focus_chain[currentDesktop()].end();
01455 --it )
01456 {
01457 if ( (*it)->isShown( false ) && (*it)->isOnCurrentDesktop())
01458 {
01459 c = *it;
01460 break;
01461 }
01462 }
01463 }
01464 }
01465
01466
01467
01468
01469 else if( active_client && active_client->isShown( true ) && active_client->isOnCurrentDesktop())
01470 c = active_client;
01471
01472 if( c == NULL && !desktops.isEmpty())
01473 c = findDesktop( true, currentDesktop());
01474
01475 if( c != active_client )
01476 setActiveClient( NULL, Allowed );
01477
01478 if ( c )
01479 requestFocus( c );
01480 else
01481 focusToNull();
01482
01483 updateCurrentTopMenu();
01484
01485
01486
01487
01488
01489
01490 for( int i = desktop_focus_chain.find( currentDesktop() ); i > 0; i-- )
01491 desktop_focus_chain[i] = desktop_focus_chain[i-1];
01492 desktop_focus_chain[0] = currentDesktop();
01493
01494
01495
01496
01497
01498
01499 if( old_desktop != 0 )
01500 popupinfo->showInfo( desktopName(currentDesktop()) );
01501 return true;
01502 }
01503
01504
01505 void Workspace::nextDesktop()
01506 {
01507 int desktop = currentDesktop() + 1;
01508 setCurrentDesktop(desktop > numberOfDesktops() ? 1 : desktop);
01509 }
01510
01511
01512 void Workspace::previousDesktop()
01513 {
01514 int desktop = currentDesktop() - 1;
01515 setCurrentDesktop(desktop > 0 ? desktop : numberOfDesktops());
01516 }
01517
01518 int Workspace::desktopToRight( int desktop ) const
01519 {
01520 int x,y;
01521 calcDesktopLayout(x,y);
01522 int dt = desktop-1;
01523 if (layoutOrientation == Qt::Vertical)
01524 {
01525 dt += y;
01526 if ( dt >= numberOfDesktops() )
01527 {
01528 if ( options->rollOverDesktops )
01529 dt -= numberOfDesktops();
01530 else
01531 return desktop;
01532 }
01533 }
01534 else
01535 {
01536 int d = (dt % x) + 1;
01537 if ( d >= x )
01538 {
01539 if ( options->rollOverDesktops )
01540 d -= x;
01541 else
01542 return desktop;
01543 }
01544 dt = dt - (dt % x) + d;
01545 }
01546 return dt+1;
01547 }
01548
01549 int Workspace::desktopToLeft( int desktop ) const
01550 {
01551 int x,y;
01552 calcDesktopLayout(x,y);
01553 int dt = desktop-1;
01554 if (layoutOrientation == Qt::Vertical)
01555 {
01556 dt -= y;
01557 if ( dt < 0 )
01558 {
01559 if ( options->rollOverDesktops )
01560 dt += numberOfDesktops();
01561 else
01562 return desktop;
01563 }
01564 }
01565 else
01566 {
01567 int d = (dt % x) - 1;
01568 if ( d < 0 )
01569 {
01570 if ( options->rollOverDesktops )
01571 d += x;
01572 else
01573 return desktop;
01574 }
01575 dt = dt - (dt % x) + d;
01576 }
01577 return dt+1;
01578 }
01579
01580 int Workspace::desktopUp( int desktop ) const
01581 {
01582 int x,y;
01583 calcDesktopLayout(x,y);
01584 int dt = desktop-1;
01585 if (layoutOrientation == Qt::Horizontal)
01586 {
01587 dt -= x;
01588 if ( dt < 0 )
01589 {
01590 if ( options->rollOverDesktops )
01591 dt += numberOfDesktops();
01592 else
01593 return desktop;
01594 }
01595 }
01596 else
01597 {
01598 int d = (dt % y) - 1;
01599 if ( d < 0 )
01600 {
01601 if ( options->rollOverDesktops )
01602 d += y;
01603 else
01604 return desktop;
01605 }
01606 dt = dt - (dt % y) + d;
01607 }
01608 return dt+1;
01609 }
01610
01611 int Workspace::desktopDown( int desktop ) const
01612 {
01613 int x,y;
01614 calcDesktopLayout(x,y);
01615 int dt = desktop-1;
01616 if (layoutOrientation == Qt::Horizontal)
01617 {
01618 dt += x;
01619 if ( dt >= numberOfDesktops() )
01620 {
01621 if ( options->rollOverDesktops )
01622 dt -= numberOfDesktops();
01623 else
01624 return desktop;
01625 }
01626 }
01627 else
01628 {
01629 int d = (dt % y) + 1;
01630 if ( d >= y )
01631 {
01632 if ( options->rollOverDesktops )
01633 d -= y;
01634 else
01635 return desktop;
01636 }
01637 dt = dt - (dt % y) + d;
01638 }
01639 return dt+1;
01640 }
01641
01642
01646 void Workspace::setNumberOfDesktops( int n )
01647 {
01648 if ( n == number_of_desktops )
01649 return;
01650 int old_number_of_desktops = number_of_desktops;
01651 number_of_desktops = n;
01652
01653 if( currentDesktop() > numberOfDesktops())
01654 setCurrentDesktop( numberOfDesktops());
01655
01656
01657
01658 if( old_number_of_desktops < number_of_desktops )
01659 {
01660 rootInfo->setNumberOfDesktops( number_of_desktops );
01661 NETPoint* viewports = new NETPoint[ number_of_desktops ];
01662 rootInfo->setDesktopViewport( number_of_desktops, *viewports );
01663 delete[] viewports;
01664 updateClientArea( true );
01665 focus_chain.resize( number_of_desktops + 1 );
01666 }
01667
01668
01669
01670 if( old_number_of_desktops > number_of_desktops )
01671 {
01672 for( ClientList::ConstIterator it = clients.begin();
01673 it != clients.end();
01674 ++it)
01675 {
01676 if( !(*it)->isOnAllDesktops() && (*it)->desktop() > numberOfDesktops())
01677 sendClientToDesktop( *it, numberOfDesktops(), true );
01678 }
01679 }
01680 if( old_number_of_desktops > number_of_desktops )
01681 {
01682 rootInfo->setNumberOfDesktops( number_of_desktops );
01683 NETPoint* viewports = new NETPoint[ number_of_desktops ];
01684 rootInfo->setDesktopViewport( number_of_desktops, *viewports );
01685 delete[] viewports;
01686 updateClientArea( true );
01687 focus_chain.resize( number_of_desktops + 1 );
01688 }
01689
01690 saveDesktopSettings();
01691
01692
01693 desktop_focus_chain.resize( n );
01694 for( int i = 0; i < (int)desktop_focus_chain.size(); i++ )
01695 desktop_focus_chain[i] = i+1;
01696 }
01697
01703 void Workspace::sendClientToDesktop( Client* c, int desk, bool dont_activate )
01704 {
01705 bool was_on_desktop = c->isOnDesktop( desk ) || c->isOnAllDesktops();
01706 c->setDesktop( desk );
01707 if ( c->desktop() != desk )
01708 return;
01709 desk = c->desktop();
01710
01711 if ( c->isOnDesktop( currentDesktop() ) )
01712 {
01713 if ( c->wantsTabFocus() && options->focusPolicyIsReasonable()
01714 && !was_on_desktop
01715 && !dont_activate )
01716 requestFocus( c );
01717 else
01718 restackClientUnderActive( c );
01719 }
01720 else
01721 {
01722 raiseClient( c );
01723 }
01724
01725 ClientList transients_stacking_order = ensureStackingOrder( c->transients());
01726 for( ClientList::ConstIterator it = transients_stacking_order.begin();
01727 it != transients_stacking_order.end();
01728 ++it )
01729 sendClientToDesktop( *it, desk, dont_activate );
01730 updateClientArea();
01731 }
01732
01733 int Workspace::numScreens() const
01734 {
01735 if( !options->xineramaEnabled )
01736 return 0;
01737 return tqApp->desktop()->numScreens();
01738 }
01739
01740 int Workspace::activeScreen() const
01741 {
01742 if( !options->xineramaEnabled )
01743 return 0;
01744 if( !options->activeMouseScreen )
01745 {
01746 if( activeClient() != NULL && !activeClient()->isOnScreen( active_screen ))
01747 return tqApp->desktop()->screenNumber( activeClient()->geometry().center());
01748 return active_screen;
01749 }
01750 return tqApp->desktop()->screenNumber( TQCursor::pos());
01751 }
01752
01753
01754
01755 void Workspace::checkActiveScreen( const Client* c )
01756 {
01757 if( !options->xineramaEnabled )
01758 return;
01759 if( !c->isActive())
01760 return;
01761 if( !c->isOnScreen( active_screen ))
01762 active_screen = c->screen();
01763 }
01764
01765
01766
01767 void Workspace::setActiveScreenMouse( TQPoint mousepos )
01768 {
01769 if( !options->xineramaEnabled )
01770 return;
01771 active_screen = tqApp->desktop()->screenNumber( mousepos );
01772 }
01773
01774 TQRect Workspace::screenGeometry( int screen ) const
01775 {
01776 if (( !options->xineramaEnabled ) || (kapp->desktop()->numScreens() < 2))
01777 return tqApp->desktop()->geometry();
01778 return tqApp->desktop()->screenGeometry( screen );
01779 }
01780
01781 int Workspace::screenNumber( TQPoint pos ) const
01782 {
01783 if( !options->xineramaEnabled )
01784 return 0;
01785 return tqApp->desktop()->screenNumber( pos );
01786 }
01787
01788 void Workspace::sendClientToScreen( Client* c, int screen )
01789 {
01790 if( c->screen() == screen )
01791 return;
01792 GeometryUpdatesPostponer blocker( c );
01793 TQRect old_sarea = clientArea( MaximizeArea, c );
01794 TQRect sarea = clientArea( MaximizeArea, screen, c->desktop());
01795 c->setGeometry( sarea.x() - old_sarea.x() + c->x(), sarea.y() - old_sarea.y() + c->y(),
01796 c->size().width(), c->size().height());
01797 c->checkWorkspacePosition();
01798 ClientList transients_stacking_order = ensureStackingOrder( c->transients());
01799 for( ClientList::ConstIterator it = transients_stacking_order.begin();
01800 it != transients_stacking_order.end();
01801 ++it )
01802 sendClientToScreen( *it, screen );
01803 if( c->isActive())
01804 active_screen = screen;
01805 }
01806
01807
01808 void Workspace::setDesktopLayout( int, int, int )
01809 {
01810 }
01811
01812 void Workspace::updateDesktopLayout()
01813 {
01814
01815 layoutOrientation = ( rootInfo->desktopLayoutOrientation() == NET::OrientationHorizontal
01816 ? Qt::Horizontal : Qt::Vertical );
01817 layoutX = rootInfo->desktopLayoutColumnsRows().width();
01818 layoutY = rootInfo->desktopLayoutColumnsRows().height();
01819 if( layoutX == 0 && layoutY == 0 )
01820 layoutY = 2;
01821 }
01822
01823 void Workspace::calcDesktopLayout(int &x, int &y) const
01824 {
01825 x = layoutX;
01826 y = layoutY;
01827 if((x <= 0) && (y > 0))
01828 x = (numberOfDesktops()+y-1) / y;
01829 else if((y <=0) && (x > 0))
01830 y = (numberOfDesktops()+x-1) / x;
01831
01832 if(x <=0)
01833 x = 1;
01834 if (y <= 0)
01835 y = 1;
01836 }
01837
01842 bool Workspace::addSystemTrayWin( WId w )
01843 {
01844 if ( systemTrayWins.contains( w ) )
01845 return TRUE;
01846
01847 NETWinInfo ni( tqt_xdisplay(), w, root, NET::WMKDESystemTrayWinFor );
01848 WId trayWinFor = ni.kdeSystemTrayWinFor();
01849 if ( !trayWinFor )
01850 return FALSE;
01851 systemTrayWins.append( SystemTrayWindow( w, trayWinFor ) );
01852 XSelectInput( tqt_xdisplay(), w,
01853 StructureNotifyMask
01854 );
01855 XAddToSaveSet( tqt_xdisplay(), w );
01856 propagateSystemTrayWins();
01857 return TRUE;
01858 }
01859
01864 bool Workspace::removeSystemTrayWin( WId w, bool check )
01865 {
01866 if ( !systemTrayWins.contains( w ) )
01867 return FALSE;
01868 if( check )
01869 {
01870
01871
01872
01873
01874
01875
01876
01877 int num_props;
01878 Atom* props = XListProperties( tqt_xdisplay(), w, &num_props );
01879 if( props != NULL )
01880 {
01881 for( int i = 0;
01882 i < num_props;
01883 ++i )
01884 if( props[ i ] == atoms->kde_system_tray_embedding )
01885 {
01886 XFree( props );
01887 return false;
01888 }
01889 XFree( props );
01890 }
01891 }
01892 systemTrayWins.remove( w );
01893 XRemoveFromSaveSet (tqt_xdisplay (), w);
01894 propagateSystemTrayWins();
01895 return TRUE;
01896 }
01897
01898
01902 void Workspace::propagateSystemTrayWins()
01903 {
01904 Window *cl = new Window[ systemTrayWins.count()];
01905
01906 int i = 0;
01907 for ( SystemTrayWindowList::ConstIterator it = systemTrayWins.begin(); it != systemTrayWins.end(); ++it )
01908 {
01909 cl[i++] = (*it).win;
01910 }
01911
01912 rootInfo->setKDESystemTrayWindows( cl, i );
01913 delete [] cl;
01914 }
01915
01916
01917 void Workspace::killWindowId( Window window_to_kill )
01918 {
01919 if( window_to_kill == None )
01920 return;
01921 Window window = window_to_kill;
01922 Client* client = NULL;
01923 for(;;)
01924 {
01925 client = findClient( FrameIdMatchPredicate( window ));
01926 if( client != NULL )
01927 break;
01928 Window parent = 0L;
01929 Window root = 0L;
01930 Window* children = 0L;
01931 unsigned int children_count;
01932 XQueryTree( tqt_xdisplay(), window, &root, &parent, &children, &children_count );
01933 if( children != NULL )
01934 XFree( children );
01935 if( window == root )
01936 break;
01937 window = parent;
01938 if( window == 0L )
01939 break;
01940 }
01941 if( client != NULL )
01942 client->killWindow();
01943 else
01944 XKillClient( tqt_xdisplay(), window_to_kill );
01945 }
01946
01947 void Workspace::suspendWindowId( Window window_to_suspend )
01948 {
01949 if( window_to_suspend == None )
01950 return;
01951 Window window = window_to_suspend;
01952 Client* client = NULL;
01953 for(;;)
01954 {
01955 client = findClient( FrameIdMatchPredicate( window ));
01956 if( client != NULL )
01957 break;
01958 Window parent = 0L;
01959 Window root = 0L;
01960 Window* children = 0L;
01961 unsigned int children_count;
01962 XQueryTree( tqt_xdisplay(), window, &root, &parent, &children, &children_count );
01963 if( children != NULL )
01964 XFree( children );
01965 if( window == root )
01966 break;
01967 window = parent;
01968 if( window == 0L )
01969 break;
01970 }
01971 if( client != NULL )
01972 client->suspendWindow();
01973 else
01974 return;
01975 }
01976
01977 void Workspace::resumeWindowId( Window window_to_resume )
01978 {
01979 if( window_to_resume == None )
01980 return;
01981 Window window = window_to_resume;
01982 Client* client = NULL;
01983 for(;;)
01984 {
01985 client = findClient( FrameIdMatchPredicate( window ));
01986 if( client != NULL )
01987 break;
01988 Window parent = 0L;
01989 Window root = 0L;
01990 Window* children = 0L;
01991 unsigned int children_count;
01992 XQueryTree( tqt_xdisplay(), window, &root, &parent, &children, &children_count );
01993 if( children != NULL )
01994 XFree( children );
01995 if( window == root )
01996 break;
01997 window = parent;
01998 if( window == 0L )
01999 break;
02000 }
02001 if( client != NULL )
02002 client->resumeWindow();
02003 else
02004 return;
02005 }
02006
02007
02008 bool Workspace::isResumeableWindowID( Window window_to_check )
02009 {
02010 if( window_to_check == None )
02011 return false;
02012 Window window = window_to_check;
02013 Client* client = NULL;
02014 for(;;)
02015 {
02016 client = findClient( FrameIdMatchPredicate( window ));
02017 if( client != NULL )
02018 break;
02019 Window parent = 0L;
02020 Window root = 0L;
02021 Window* children = 0L;
02022 unsigned int children_count;
02023 XQueryTree( tqt_xdisplay(), window, &root, &parent, &children, &children_count );
02024 if( children != NULL )
02025 XFree( children );
02026 if( window == root )
02027 break;
02028 window = parent;
02029 if( window == 0L )
02030 break;
02031 }
02032 if( client != NULL )
02033 return client->isResumeable();
02034 else
02035 return false;
02036 }
02037
02038
02039 void Workspace::sendPingToWindow( Window window, Time timestamp )
02040 {
02041 rootInfo->sendPing( window, timestamp );
02042 }
02043
02044 void Workspace::sendTakeActivity( Client* c, Time timestamp, long flags )
02045 {
02046 rootInfo->takeActivity( c->window(), timestamp, flags );
02047 pending_take_activity = c;
02048 }
02049
02050
02054 void Workspace::slotGrabWindow()
02055 {
02056 if ( active_client )
02057 {
02058 TQPixmap snapshot = TQPixmap::grabWindow( active_client->frameId() );
02059
02060
02061 if( Shape::available())
02062 {
02063
02064 int count, order;
02065 XRectangle* rects = XShapeGetRectangles( tqt_xdisplay(), active_client->frameId(),
02066 ShapeBounding, &count, &order);
02067
02068
02069
02070
02071 if (rects)
02072 {
02073
02074 TQRegion contents;
02075 for (int pos = 0; pos < count; pos++)
02076 contents += TQRegion(rects[pos].x, rects[pos].y,
02077 rects[pos].width, rects[pos].height);
02078 XFree(rects);
02079
02080
02081 TQRegion bbox(0, 0, snapshot.width(), snapshot.height());
02082
02083
02084 TQRegion maskedAway = bbox - contents;
02085 TQMemArray<TQRect> maskedAwayRects = maskedAway.rects();
02086
02087
02088 TQBitmap mask( snapshot.width(), snapshot.height());
02089 TQPainter p(&mask);
02090 p.fillRect(0, 0, mask.width(), mask.height(), Qt::color1);
02091 for (uint pos = 0; pos < maskedAwayRects.count(); pos++)
02092 p.fillRect(maskedAwayRects[pos], Qt::color0);
02093 p.end();
02094 snapshot.setMask(mask);
02095 }
02096 }
02097
02098 TQClipboard *cb = TQApplication::clipboard();
02099 cb->setPixmap( snapshot );
02100 }
02101 else
02102 slotGrabDesktop();
02103 }
02104
02108 void Workspace::slotGrabDesktop()
02109 {
02110 TQPixmap p = TQPixmap::grabWindow( tqt_xrootwin() );
02111 TQClipboard *cb = TQApplication::clipboard();
02112 cb->setPixmap( p );
02113 }
02114
02115
02119 void Workspace::slotMouseEmulation()
02120 {
02121
02122 if ( mouse_emulation )
02123 {
02124 XUngrabKeyboard(tqt_xdisplay(), GET_QT_X_TIME());
02125 mouse_emulation = FALSE;
02126 return;
02127 }
02128
02129 if ( XGrabKeyboard(tqt_xdisplay(),
02130 root, FALSE,
02131 GrabModeAsync, GrabModeAsync,
02132 GET_QT_X_TIME()) == GrabSuccess )
02133 {
02134 mouse_emulation = TRUE;
02135 mouse_emulation_state = 0;
02136 mouse_emulation_window = 0;
02137 }
02138 }
02139
02146 WId Workspace::getMouseEmulationWindow()
02147 {
02148 Window root;
02149 Window child = tqt_xrootwin();
02150 int root_x, root_y, lx, ly;
02151 uint state;
02152 Window w;
02153 Client * c = 0;
02154 do
02155 {
02156 w = child;
02157 if (!c)
02158 c = findClient( FrameIdMatchPredicate( w ));
02159 XQueryPointer( tqt_xdisplay(), w, &root, &child,
02160 &root_x, &root_y, &lx, &ly, &state );
02161 } while ( child != None && child != w );
02162
02163 if ( c && !c->isActive() )
02164 activateClient( c );
02165 return (WId) w;
02166 }
02167
02171 unsigned int Workspace::sendFakedMouseEvent( TQPoint pos, WId w, MouseEmulation type, int button, unsigned int state )
02172 {
02173 if ( !w )
02174 return state;
02175 TQWidget* widget = TQWidget::find( w );
02176 if ( (!widget || widget->inherits(TQTOOLBUTTON_OBJECT_NAME_STRING) ) && !findClient( WindowMatchPredicate( w )) )
02177 {
02178 int x, y;
02179 Window xw;
02180 XTranslateCoordinates( tqt_xdisplay(), tqt_xrootwin(), w, pos.x(), pos.y(), &x, &y, &xw );
02181 if ( type == EmuMove )
02182 {
02183 XEvent e;
02184 e.type = MotionNotify;
02185 e.xmotion.window = w;
02186 e.xmotion.root = tqt_xrootwin();
02187 e.xmotion.subwindow = w;
02188 e.xmotion.time = GET_QT_X_TIME();
02189 e.xmotion.x = x;
02190 e.xmotion.y = y;
02191 e.xmotion.x_root = pos.x();
02192 e.xmotion.y_root = pos.y();
02193 e.xmotion.state = state;
02194 e.xmotion.is_hint = NotifyNormal;
02195 XSendEvent( tqt_xdisplay(), w, TRUE, ButtonMotionMask, &e );
02196 }
02197 else
02198 {
02199 XEvent e;
02200 e.type = type == EmuRelease ? ButtonRelease : ButtonPress;
02201 e.xbutton.window = w;
02202 e.xbutton.root = tqt_xrootwin();
02203 e.xbutton.subwindow = w;
02204 e.xbutton.time = GET_QT_X_TIME();
02205 e.xbutton.x = x;
02206 e.xbutton.y = y;
02207 e.xbutton.x_root = pos.x();
02208 e.xbutton.y_root = pos.y();
02209 e.xbutton.state = state;
02210 e.xbutton.button = button;
02211 XSendEvent( tqt_xdisplay(), w, TRUE, ButtonPressMask, &e );
02212
02213 if ( type == EmuPress )
02214 {
02215 switch ( button )
02216 {
02217 case 2:
02218 state |= Button2Mask;
02219 break;
02220 case 3:
02221 state |= Button3Mask;
02222 break;
02223 default:
02224 state |= Button1Mask;
02225 break;
02226 }
02227 }
02228 else
02229 {
02230 switch ( button )
02231 {
02232 case 2:
02233 state &= ~Button2Mask;
02234 break;
02235 case 3:
02236 state &= ~Button3Mask;
02237 break;
02238 default:
02239 state &= ~Button1Mask;
02240 break;
02241 }
02242 }
02243 }
02244 }
02245 return state;
02246 }
02247
02251 bool Workspace::keyPressMouseEmulation( XKeyEvent& ev )
02252 {
02253 if ( root != tqt_xrootwin() )
02254 return FALSE;
02255 int kc = XkbKeycodeToKeysym(tqt_xdisplay(), ev.keycode, 0, 0);
02256 int km = ev.state & (ControlMask | Mod1Mask | ShiftMask);
02257
02258 bool is_control = km & ControlMask;
02259 bool is_alt = km & Mod1Mask;
02260 bool is_shift = km & ShiftMask;
02261 int delta = is_control?1:is_alt?32:8;
02262 TQPoint pos = TQCursor::pos();
02263
02264 switch ( kc )
02265 {
02266 case XK_Left:
02267 case XK_KP_Left:
02268 pos.rx() -= delta;
02269 break;
02270 case XK_Right:
02271 case XK_KP_Right:
02272 pos.rx() += delta;
02273 break;
02274 case XK_Up:
02275 case XK_KP_Up:
02276 pos.ry() -= delta;
02277 break;
02278 case XK_Down:
02279 case XK_KP_Down:
02280 pos.ry() += delta;
02281 break;
02282 case XK_F1:
02283 if ( !mouse_emulation_state )
02284 mouse_emulation_window = getMouseEmulationWindow();
02285 if ( (mouse_emulation_state & Button1Mask) == 0 )
02286 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button1, mouse_emulation_state );
02287 if ( !is_shift )
02288 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
02289 break;
02290 case XK_F2:
02291 if ( !mouse_emulation_state )
02292 mouse_emulation_window = getMouseEmulationWindow();
02293 if ( (mouse_emulation_state & Button2Mask) == 0 )
02294 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button2, mouse_emulation_state );
02295 if ( !is_shift )
02296 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button2, mouse_emulation_state );
02297 break;
02298 case XK_F3:
02299 if ( !mouse_emulation_state )
02300 mouse_emulation_window = getMouseEmulationWindow();
02301 if ( (mouse_emulation_state & Button3Mask) == 0 )
02302 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button3, mouse_emulation_state );
02303 if ( !is_shift )
02304 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button3, mouse_emulation_state );
02305 break;
02306 case XK_Return:
02307 case XK_space:
02308 case XK_KP_Enter:
02309 case XK_KP_Space:
02310 {
02311 if ( !mouse_emulation_state )
02312 {
02313
02314 mouse_emulation_window = getMouseEmulationWindow();
02315 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button1, mouse_emulation_state );
02316 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
02317 }
02318 else
02319 {
02320 if ( mouse_emulation_state & Button1Mask )
02321 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
02322 if ( mouse_emulation_state & Button2Mask )
02323 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button2, mouse_emulation_state );
02324 if ( mouse_emulation_state & Button3Mask )
02325 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button3, mouse_emulation_state );
02326 }
02327 }
02328
02329 case XK_Escape:
02330 XUngrabKeyboard(tqt_xdisplay(), GET_QT_X_TIME());
02331 mouse_emulation = FALSE;
02332 return TRUE;
02333 default:
02334 return FALSE;
02335 }
02336
02337 TQCursor::setPos( pos );
02338 if ( mouse_emulation_state )
02339 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuMove, 0, mouse_emulation_state );
02340 return TRUE;
02341
02342 }
02343
02349 TQWidget* Workspace::desktopWidget()
02350 {
02351 return desktop_widget;
02352 }
02353
02354
02355 void Workspace::delayFocus()
02356 {
02357 requestFocus( delayfocus_client );
02358 cancelDelayFocus();
02359 }
02360
02361 void Workspace::requestDelayFocus( Client* c )
02362 {
02363 delayfocus_client = c;
02364 delete delayFocusTimer;
02365 delayFocusTimer = new TQTimer( this );
02366 connect( delayFocusTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( delayFocus() ) );
02367 delayFocusTimer->start( options->delayFocusInterval, TRUE );
02368 }
02369
02370 void Workspace::cancelDelayFocus()
02371 {
02372 delete delayFocusTimer;
02373 delayFocusTimer = 0;
02374 }
02375
02376
02377
02378
02379
02380
02381
02382
02383 void Workspace::checkElectricBorders( bool force )
02384 {
02385 if( force )
02386 destroyBorderWindows();
02387
02388 electric_current_border = 0;
02389
02390 TQRect r = TQApplication::desktop()->geometry();
02391 electricTop = r.top();
02392 electricBottom = r.bottom();
02393 electricLeft = r.left();
02394 electricRight = r.right();
02395
02396 if (options->electricBorders() == Options::ElectricAlways)
02397 createBorderWindows();
02398 else
02399 destroyBorderWindows();
02400 }
02401
02402 void Workspace::createBorderWindows()
02403 {
02404 if ( electric_have_borders )
02405 return;
02406
02407 electric_have_borders = true;
02408
02409 TQRect r = TQApplication::desktop()->geometry();
02410 XSetWindowAttributes attributes;
02411 unsigned long valuemask;
02412 attributes.override_redirect = True;
02413 attributes.event_mask = ( EnterWindowMask | LeaveWindowMask );
02414 valuemask= (CWOverrideRedirect | CWEventMask | CWCursor );
02415 attributes.cursor = XCreateFontCursor(tqt_xdisplay(),
02416 XC_sb_up_arrow);
02417 electric_top_border = XCreateWindow (tqt_xdisplay(), tqt_xrootwin(),
02418 0,0,
02419 r.width(),1,
02420 0,
02421 CopyFromParent, InputOnly,
02422 CopyFromParent,
02423 valuemask, &attributes);
02424 XMapWindow(tqt_xdisplay(), electric_top_border);
02425
02426 attributes.cursor = XCreateFontCursor(tqt_xdisplay(),
02427 XC_sb_down_arrow);
02428 electric_bottom_border = XCreateWindow (tqt_xdisplay(), tqt_xrootwin(),
02429 0,r.height()-1,
02430 r.width(),1,
02431 0,
02432 CopyFromParent, InputOnly,
02433 CopyFromParent,
02434 valuemask, &attributes);
02435 XMapWindow(tqt_xdisplay(), electric_bottom_border);
02436
02437 attributes.cursor = XCreateFontCursor(tqt_xdisplay(),
02438 XC_sb_left_arrow);
02439 electric_left_border = XCreateWindow (tqt_xdisplay(), tqt_xrootwin(),
02440 0,0,
02441 1,r.height(),
02442 0,
02443 CopyFromParent, InputOnly,
02444 CopyFromParent,
02445 valuemask, &attributes);
02446 XMapWindow(tqt_xdisplay(), electric_left_border);
02447
02448 attributes.cursor = XCreateFontCursor(tqt_xdisplay(),
02449 XC_sb_right_arrow);
02450 electric_right_border = XCreateWindow (tqt_xdisplay(), tqt_xrootwin(),
02451 r.width()-1,0,
02452 1,r.height(),
02453 0,
02454 CopyFromParent, InputOnly,
02455 CopyFromParent,
02456 valuemask, &attributes);
02457 XMapWindow(tqt_xdisplay(), electric_right_border);
02458
02459 Atom version = 4;
02460 XChangeProperty( tqt_xdisplay(), electric_top_border, atoms->xdnd_aware, XA_ATOM,
02461 32, PropModeReplace, ( unsigned char* )&version, 1 );
02462 XChangeProperty( tqt_xdisplay(), electric_bottom_border, atoms->xdnd_aware, XA_ATOM,
02463 32, PropModeReplace, ( unsigned char* )&version, 1 );
02464 XChangeProperty( tqt_xdisplay(), electric_left_border, atoms->xdnd_aware, XA_ATOM,
02465 32, PropModeReplace, ( unsigned char* )&version, 1 );
02466 XChangeProperty( tqt_xdisplay(), electric_right_border, atoms->xdnd_aware, XA_ATOM,
02467 32, PropModeReplace, ( unsigned char* )&version, 1 );
02468 }
02469
02470
02471
02472
02473
02474
02475
02476 void Workspace::destroyBorderWindows()
02477 {
02478 if( !electric_have_borders)
02479 return;
02480
02481 electric_have_borders = false;
02482
02483 if(electric_top_border)
02484 XDestroyWindow(tqt_xdisplay(),electric_top_border);
02485 if(electric_bottom_border)
02486 XDestroyWindow(tqt_xdisplay(),electric_bottom_border);
02487 if(electric_left_border)
02488 XDestroyWindow(tqt_xdisplay(),electric_left_border);
02489 if(electric_right_border)
02490 XDestroyWindow(tqt_xdisplay(),electric_right_border);
02491
02492 electric_top_border = None;
02493 electric_bottom_border = None;
02494 electric_left_border = None;
02495 electric_right_border = None;
02496 }
02497
02498 void Workspace::clientMoved(const TQPoint &pos, Time now)
02499 {
02500 if (options->electricBorders() == Options::ElectricDisabled)
02501 return;
02502
02503 if ((pos.x() != electricLeft) &&
02504 (pos.x() != electricRight) &&
02505 (pos.y() != electricTop) &&
02506 (pos.y() != electricBottom))
02507 return;
02508
02509 Time treshold_set = options->electricBorderDelay();
02510 Time treshold_reset = 250;
02511 int distance_reset = 30;
02512
02513 int border = 0;
02514 if (pos.x() == electricLeft)
02515 border = 1;
02516 else if (pos.x() == electricRight)
02517 border = 2;
02518 else if (pos.y() == electricTop)
02519 border = 3;
02520 else if (pos.y() == electricBottom)
02521 border = 4;
02522
02523 if ((electric_current_border == border) &&
02524 (timestampDiff(electric_time_last, now) < treshold_reset) &&
02525 ((pos-electric_push_point).manhattanLength() < distance_reset))
02526 {
02527 electric_time_last = now;
02528
02529 if (timestampDiff(electric_time_first, now) > treshold_set)
02530 {
02531 electric_current_border = 0;
02532
02533 TQRect r = TQApplication::desktop()->geometry();
02534 int offset;
02535
02536 int desk_before = currentDesktop();
02537 switch(border)
02538 {
02539 case 1:
02540 slotSwitchDesktopLeft();
02541 if (currentDesktop() != desk_before)
02542 {
02543 offset = r.width() / 5;
02544 TQCursor::setPos(r.width() - offset, pos.y());
02545 }
02546 break;
02547
02548 case 2:
02549 slotSwitchDesktopRight();
02550 if (currentDesktop() != desk_before)
02551 {
02552 offset = r.width() / 5;
02553 TQCursor::setPos(offset, pos.y());
02554 }
02555 break;
02556
02557 case 3:
02558 slotSwitchDesktopUp();
02559 if (currentDesktop() != desk_before)
02560 {
02561 offset = r.height() / 5;
02562 TQCursor::setPos(pos.x(), r.height() - offset);
02563 }
02564 break;
02565
02566 case 4:
02567 slotSwitchDesktopDown();
02568 if (currentDesktop() != desk_before)
02569 {
02570 offset = r.height() / 5;
02571 TQCursor::setPos(pos.x(), offset);
02572 }
02573 break;
02574 }
02575 return;
02576 }
02577 }
02578 else
02579 {
02580 electric_current_border = border;
02581 electric_time_first = now;
02582 electric_time_last = now;
02583 electric_push_point = pos;
02584 }
02585
02586 int mouse_warp = 1;
02587
02588
02589 switch( border)
02590 {
02591 case 1: TQCursor::setPos(pos.x()+mouse_warp, pos.y()); break;
02592 case 2: TQCursor::setPos(pos.x()-mouse_warp, pos.y()); break;
02593 case 3: TQCursor::setPos(pos.x(), pos.y()+mouse_warp); break;
02594 case 4: TQCursor::setPos(pos.x(), pos.y()-mouse_warp); break;
02595 }
02596 }
02597
02598
02599
02600 bool Workspace::electricBorder(XEvent *e)
02601 {
02602 if( !electric_have_borders )
02603 return false;
02604 if( e->type == EnterNotify )
02605 {
02606 if( e->xcrossing.window == electric_top_border ||
02607 e->xcrossing.window == electric_left_border ||
02608 e->xcrossing.window == electric_bottom_border ||
02609 e->xcrossing.window == electric_right_border)
02610
02611 {
02612 clientMoved( TQPoint( e->xcrossing.x_root, e->xcrossing.y_root ), e->xcrossing.time );
02613 return true;
02614 }
02615 }
02616 if( e->type == ClientMessage )
02617 {
02618 if( e->xclient.message_type == atoms->xdnd_position
02619 && ( e->xclient.window == electric_top_border
02620 || e->xclient.window == electric_bottom_border
02621 || e->xclient.window == electric_left_border
02622 || e->xclient.window == electric_right_border ))
02623 {
02624 updateXTime();
02625 clientMoved( TQPoint( e->xclient.data.l[2]>>16, e->xclient.data.l[2]&0xffff), GET_QT_X_TIME() );
02626 return true;
02627 }
02628 }
02629 return false;
02630 }
02631
02632
02633
02634
02635 void Workspace::raiseElectricBorders()
02636 {
02637
02638 if(electric_have_borders)
02639 {
02640 XRaiseWindow(tqt_xdisplay(), electric_top_border);
02641 XRaiseWindow(tqt_xdisplay(), electric_left_border);
02642 XRaiseWindow(tqt_xdisplay(), electric_bottom_border);
02643 XRaiseWindow(tqt_xdisplay(), electric_right_border);
02644 }
02645 }
02646
02647 void Workspace::addTopMenu( Client* c )
02648 {
02649 assert( c->isTopMenu());
02650 assert( !topmenus.contains( c ));
02651 topmenus.append( c );
02652 if( managingTopMenus())
02653 {
02654 int minsize = c->minSize().height();
02655 if( minsize > topMenuHeight())
02656 {
02657 topmenu_height = minsize;
02658 updateTopMenuGeometry();
02659 }
02660 updateTopMenuGeometry( c );
02661 updateCurrentTopMenu();
02662 }
02663
02664 }
02665
02666 void Workspace::removeTopMenu( Client* c )
02667 {
02668
02669
02670 assert( c->isTopMenu());
02671 assert( topmenus.contains( c ));
02672 topmenus.remove( c );
02673 updateCurrentTopMenu();
02674
02675 }
02676
02677 void Workspace::lostTopMenuSelection()
02678 {
02679
02680
02681 disconnect( topmenu_watcher, TQT_SIGNAL( lostOwner()), this, TQT_SLOT( lostTopMenuOwner()));
02682 connect( topmenu_watcher, TQT_SIGNAL( lostOwner()), this, TQT_SLOT( lostTopMenuOwner()));
02683 if( !managing_topmenus )
02684 return;
02685 connect( topmenu_watcher, TQT_SIGNAL( lostOwner()), this, TQT_SLOT( lostTopMenuOwner()));
02686 disconnect( topmenu_selection, TQT_SIGNAL( lostOwnership()), this, TQT_SLOT( lostTopMenuSelection()));
02687 managing_topmenus = false;
02688 delete topmenu_space;
02689 topmenu_space = NULL;
02690 updateClientArea();
02691 for( ClientList::ConstIterator it = topmenus.begin();
02692 it != topmenus.end();
02693 ++it )
02694 (*it)->checkWorkspacePosition();
02695 }
02696
02697 void Workspace::lostTopMenuOwner()
02698 {
02699 if( !options->topMenuEnabled())
02700 return;
02701
02702 if( !topmenu_selection->claim( false ))
02703 {
02704
02705 return;
02706 }
02707
02708 setupTopMenuHandling();
02709 }
02710
02711 void Workspace::setupTopMenuHandling()
02712 {
02713 if( managing_topmenus )
02714 return;
02715 connect( topmenu_selection, TQT_SIGNAL( lostOwnership()), this, TQT_SLOT( lostTopMenuSelection()));
02716 disconnect( topmenu_watcher, TQT_SIGNAL( lostOwner()), this, TQT_SLOT( lostTopMenuOwner()));
02717 managing_topmenus = true;
02718 topmenu_space = new TQWidget;
02719 Window stack[ 2 ];
02720 stack[ 0 ] = supportWindow->winId();
02721 stack[ 1 ] = topmenu_space->winId();
02722 XRestackWindows(tqt_xdisplay(), stack, 2);
02723 updateTopMenuGeometry();
02724 topmenu_space->show();
02725 updateClientArea();
02726 updateCurrentTopMenu();
02727 }
02728
02729 int Workspace::topMenuHeight() const
02730 {
02731 if( topmenu_height == 0 )
02732 {
02733 KMenuBar tmpmenu;
02734 tmpmenu.insertItem( "dummy" );
02735 topmenu_height = tmpmenu.sizeHint().height();
02736 }
02737 return topmenu_height;
02738 }
02739
02740 KDecoration* Workspace::createDecoration( KDecorationBridge* bridge )
02741 {
02742 return mgr->createDecoration( bridge );
02743 }
02744
02745 TQString Workspace::desktopName( int desk ) const
02746 {
02747 return TQString::fromUtf8( rootInfo->desktopName( desk ) );
02748 }
02749
02750 bool Workspace::checkStartupNotification( Window w, TDEStartupInfoId& id, TDEStartupInfoData& data )
02751 {
02752 return startup->checkStartup( w, id, data ) == TDEStartupInfo::Match;
02753 }
02754
02759 void Workspace::focusToNull()
02760 {
02761 XSetInputFocus(tqt_xdisplay(), null_focus_window, RevertToPointerRoot, GET_QT_X_TIME() );
02762 }
02763
02764 void Workspace::helperDialog( const TQString& message, const Client* c )
02765 {
02766 TQStringList args;
02767 TQString type;
02768 if( message == "noborderaltf3" )
02769 {
02770 TQString shortcut = TQString( "%1 (%2)" ).arg( keys->label( "Window Operations Menu" ))
02771 .arg( keys->shortcut( "Window Operations Menu" ).seq( 0 ).toString());
02772 args << "--msgbox" <<
02773 i18n( "You have selected to show a window without its border.\n"
02774 "Without the border, you will not be able to enable the border "
02775 "again using the mouse: use the window operations menu instead, "
02776 "activated using the %1 keyboard shortcut." )
02777 .arg( shortcut );
02778 type = "altf3warning";
02779 }
02780 else if( message == "fullscreenaltf3" )
02781 {
02782 TQString shortcut = TQString( "%1 (%2)" ).arg( keys->label( "Window Operations Menu" ))
02783 .arg( keys->shortcut( "Window Operations Menu" ).seq( 0 ).toString());
02784 args << "--msgbox" <<
02785 i18n( "You have selected to show a window in fullscreen mode.\n"
02786 "If the application itself does not have an option to turn the fullscreen "
02787 "mode off you will not be able to disable it "
02788 "again using the mouse: use the window operations menu instead, "
02789 "activated using the %1 keyboard shortcut." )
02790 .arg( shortcut );
02791 type = "altf3warning";
02792 }
02793 else
02794 assert( false );
02795 TDEProcess proc;
02796 proc << "kdialog" << args;
02797 if( !type.isEmpty())
02798 {
02799 TDEConfig cfg( "twin_dialogsrc" );
02800 cfg.setGroup( "Notification Messages" );
02801 if( !cfg.readBoolEntry( type, true ))
02802 return;
02803 proc << "--dontagain" << "twin_dialogsrc:" + type;
02804 }
02805 if( c != NULL )
02806 proc << "--embed" << TQString::number( c->window());
02807 proc.start( TDEProcess::DontCare );
02808 }
02809
02810
02811
02812
02813 void Workspace::startKompmgr()
02814 {
02815
02816 Atom type;
02817 int format;
02818 unsigned long length, after;
02819 unsigned char* data_root;
02820 Atom prop_root;
02821 prop_root = XInternAtom(tqt_xdisplay(), "_XROOTPMAP_ID", False);
02822 if( XGetWindowProperty( tqt_xdisplay(), tqt_xrootwin(), prop_root, 0L, 1L, False, AnyPropertyType, &type, &format, &length, &after, &data_root) == Success && data_root != NULL ) {
02823
02824 }
02825 else {
02826
02827 TQTimer::singleShot( 200, this, TQT_SLOT(startKompmgr()) );
02828 return;
02829 }
02830 pid_t kompmgrpid = getCompositorPID();
02831 if (kompmgrpid && kill(kompmgrpid, 0) >= 0)
02832 {
02833
02834 return;
02835 }
02836 if (!kompmgr || kompmgr->isRunning()) {
02837 kompmgrReloadSettings();
02838 return;
02839 }
02840 if (!kompmgr->start(TDEProcess::OwnGroup, TDEProcess::Stderr))
02841 {
02842 options->useTranslucency = FALSE;
02843 TDEProcess proc;
02844 proc << "kdialog" << "--error"
02845 << i18n("The Composite Manager could not be started.\\nMake sure you have \"" TDE_COMPOSITOR_BINARY "\" in a $PATH directory.")
02846 << "--title" << "Composite Manager Failure";
02847 proc.start(TDEProcess::DontCare);
02848 }
02849 else
02850 {
02851 delete kompmgr_selection;
02852 char selection_name[ 100 ];
02853 sprintf( selection_name, "_NET_WM_CM_S%d", DefaultScreen( tqt_xdisplay()));
02854 kompmgr_selection = new TDESelectionOwner( selection_name );
02855 connect( kompmgr_selection, TQT_SIGNAL( lostOwnership()), TQT_SLOT( stopKompmgr()));
02856 kompmgr_selection->claim( true );
02857 connect(kompmgr, TQT_SIGNAL(processExited(TDEProcess*)), TQT_SLOT(restartKompmgr(TDEProcess*)));
02858 options->useTranslucency = TRUE;
02859
02860
02861 TQByteArray ba;
02862 TQDataStream arg(ba, IO_WriteOnly);
02863 arg << "";
02864 kapp->dcopClient()->emitDCOPSignal("default", "kompmgrStarted()", ba);
02865 }
02866 if (popup){ delete popup; popup = 0L; }
02867 }
02868
02869 void Workspace::stopKompmgr()
02870 {
02871 if (!kompmgr || !kompmgr->isRunning()) {
02872 return;
02873 }
02874 delete kompmgr_selection;
02875 kompmgr_selection = NULL;
02876 kompmgr->disconnect(this, TQT_SLOT(restartKompmgr(TDEProcess*)));
02877 options->useTranslucency = FALSE;
02878 if (popup){ delete popup; popup = 0L; }
02879 kompmgr->kill(SIGKILL);
02880 TQByteArray ba;
02881 TQDataStream arg(ba, IO_WriteOnly);
02882 arg << "";
02883 kapp->dcopClient()->emitDCOPSignal("default", "kompmgrStopped()", ba);
02884 }
02885
02886 void Workspace::kompmgrReloadSettings()
02887 {
02888 if (!kompmgr || !kompmgr->isRunning()) {
02889 return;
02890 }
02891 kompmgr->kill(SIGUSR2);
02892 }
02893
02894 bool Workspace::kompmgrIsRunning()
02895 {
02896 return kompmgr && kompmgr->isRunning();
02897 }
02898
02899 void Workspace::unblockKompmgrRestart()
02900 {
02901 allowKompmgrRestart = TRUE;
02902 }
02903
02904 void Workspace::restartKompmgr( TDEProcess *proc )
02905
02906 {
02907 bool crashed;
02908 if (proc->signalled()) {
02909 int exit_signal_number = proc->exitSignal();
02910 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) ) {
02911 crashed = true;
02912 }
02913 else {
02914 crashed = false;
02915 }
02916 if (!allowKompmgrRestart)
02917 {
02918 delete kompmgr_selection;
02919 kompmgr_selection = NULL;
02920 options->useTranslucency = FALSE;
02921 if (crashed) {
02922 TDEProcess proc;
02923 proc << "kdialog" << "--error"
02924 << i18n( "The Composite Manager crashed twice within a minute and is therefore disabled for this session.")
02925 << "--title" << i18n("Composite Manager Failure");
02926 proc.start(TDEProcess::DontCare);
02927 }
02928 return;
02929 }
02930 if (!kompmgr)
02931 return;
02932
02933
02934
02935
02936
02937
02938
02939
02940 if (!kompmgr->start(TDEProcess::NotifyOnExit, TDEProcess::Stderr))
02941 {
02942 delete kompmgr_selection;
02943 kompmgr_selection = NULL;
02944 options->useTranslucency = FALSE;
02945 TDEProcess proc;
02946 proc << "kdialog" << "--error"
02947 << i18n("The Composite Manager could not be started.\\nMake sure you have \"" TDE_COMPOSITOR_BINARY "\" in a $PATH directory.")
02948 << "--title" << i18n("Composite Manager Failure");
02949 proc.start(TDEProcess::DontCare);
02950 }
02951 else
02952 {
02953 allowKompmgrRestart = FALSE;
02954 TQTimer::singleShot( 60000, this, TQT_SLOT(unblockKompmgrRestart()) );
02955 }
02956 }
02957 }
02958
02959 void Workspace::handleKompmgrOutput( TDEProcess* , char *buffer, int buflen)
02960 {
02961 TQString message;
02962 TQString output = TQString::fromLocal8Bit( buffer, buflen );
02963 if (output.contains("Started",false))
02964 ;
02965 else if (output.contains("Can't open display",false))
02966 message = i18n("<qt><b>The TDE composition manager failed to open the display</b><br>There is probably an invalid display entry in your ~/.compton-tde.conf file.</qt>");
02967 else if (output.contains("No render extension",false))
02968 message = i18n("<qt><b>The TDE composition manager 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>");
02969 else if (output.contains("No composite extension",false))
02970 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>"
02971 "<i>Section \"Extensions\"<br>"
02972 "Option \"Composite\" \"Enable\"<br>"
02973 "EndSection</i></qt>");
02974 else if (output.contains("No damage extension",false))
02975 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>");
02976 else if (output.contains("No XFixes extension",false))
02977 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>");
02978 else return;
02979
02980 kompmgr->closeStderr();
02981 disconnect(kompmgr, TQT_SIGNAL(receivedStderr(TDEProcess*, char*, int)), this, TQT_SLOT(handleKompmgrOutput(TDEProcess*, char*, int)));
02982 if( !message.isEmpty())
02983 {
02984 TDEProcess proc;
02985 proc << "kdialog" << "--error"
02986 << message
02987 << "--title" << i18n("Composite Manager Failure");
02988 proc.start(TDEProcess::DontCare);
02989 }
02990 }
02991
02992
02993 void Workspace::setOpacity(unsigned long winId, unsigned int opacityPercent)
02994 {
02995 if (opacityPercent > 100) opacityPercent = 100;
02996 for( ClientList::ConstIterator it = stackingOrder().begin(); it != stackingOrder().end(); it++ )
02997 if (winId == (*it)->window())
02998 {
02999 (*it)->setOpacity(opacityPercent < 100, (unsigned int)((opacityPercent/100.0)*0xFFFFFFFF));
03000 return;
03001 }
03002 }
03003
03004 void Workspace::setShadowSize(unsigned long winId, unsigned int shadowSizePercent)
03005 {
03006
03007 if (shadowSizePercent > 400) shadowSizePercent = 400;
03008 for( ClientList::ConstIterator it = stackingOrder().begin(); it != stackingOrder().end(); it++ )
03009 if (winId == (*it)->window())
03010 {
03011 (*it)->setShadowSize(shadowSizePercent);
03012 return;
03013 }
03014 }
03015
03016 void Workspace::setUnshadowed(unsigned long winId)
03017 {
03018 for( ClientList::ConstIterator it = stackingOrder().begin(); it != stackingOrder().end(); it++ )
03019 if (winId == (*it)->window())
03020 {
03021 (*it)->setShadowSize(0);
03022 return;
03023 }
03024 }
03025
03026 void Workspace::setShowingDesktop( bool showing )
03027 {
03028 rootInfo->setShowingDesktop( showing );
03029 showing_desktop = showing;
03030 ++block_showing_desktop;
03031 if( showing_desktop )
03032 {
03033 showing_desktop_clients.clear();
03034 ++block_focus;
03035 ClientList cls = stackingOrder();
03036
03037
03038 for( ClientList::ConstIterator it = cls.begin();
03039 it != cls.end();
03040 ++it )
03041 {
03042 if( (*it)->isOnCurrentDesktop() && (*it)->isShown( true ) && !(*it)->isSpecialWindow())
03043 showing_desktop_clients.prepend( *it );
03044 }
03045 for( ClientList::ConstIterator it = showing_desktop_clients.begin();
03046 it != showing_desktop_clients.end();
03047 ++it )
03048 (*it)->minimize(true);
03049 --block_focus;
03050 if( Client* desk = findDesktop( true, currentDesktop()))
03051 requestFocus( desk );
03052 }
03053 else
03054 {
03055 for( ClientList::ConstIterator it = showing_desktop_clients.begin();
03056 it != showing_desktop_clients.end();
03057 ++it )
03058 (*it)->unminimize(true);
03059 if( showing_desktop_clients.count() > 0 )
03060 requestFocus( showing_desktop_clients.first());
03061 showing_desktop_clients.clear();
03062 }
03063 --block_showing_desktop;
03064 }
03065
03066
03067
03068
03069
03070
03071
03072
03073
03074
03075 void Workspace::resetShowingDesktop( bool keep_hidden )
03076 {
03077 if( block_showing_desktop > 0 )
03078 return;
03079 rootInfo->setShowingDesktop( false );
03080 showing_desktop = false;
03081 ++block_showing_desktop;
03082 if( !keep_hidden )
03083 {
03084 for( ClientList::ConstIterator it = showing_desktop_clients.begin();
03085 it != showing_desktop_clients.end();
03086 ++it )
03087 (*it)->unminimize(true);
03088 }
03089 showing_desktop_clients.clear();
03090 --block_showing_desktop;
03091 }
03092
03093
03094
03095
03096
03097
03098
03099
03100 void Workspace::slotDisableGlobalShortcuts()
03101 {
03102 if( global_shortcuts_disabled || global_shortcuts_disabled_for_client )
03103 disableGlobalShortcuts( false );
03104 else
03105 disableGlobalShortcuts( true );
03106 }
03107
03108 static bool pending_dfc = false;
03109
03110 void Workspace::disableGlobalShortcutsForClient( bool disable )
03111 {
03112 if( global_shortcuts_disabled_for_client == disable )
03113 return;
03114 if( !global_shortcuts_disabled )
03115 {
03116 if( disable )
03117 pending_dfc = true;
03118 KIPC::sendMessageAll( KIPC::BlockShortcuts, disable );
03119
03120 }
03121 }
03122
03123 void Workspace::disableGlobalShortcuts( bool disable )
03124 {
03125 KIPC::sendMessageAll( KIPC::BlockShortcuts, disable );
03126
03127 }
03128
03129 void Workspace::kipcMessage( int id, int data )
03130 {
03131 if( id != KIPC::BlockShortcuts )
03132 return;
03133 if( pending_dfc && data )
03134 {
03135 global_shortcuts_disabled_for_client = true;
03136 pending_dfc = false;
03137 }
03138 else
03139 {
03140 global_shortcuts_disabled = data;
03141 global_shortcuts_disabled_for_client = false;
03142 }
03143
03144 for( ClientList::ConstIterator it = clients.begin();
03145 it != clients.end();
03146 ++it )
03147 (*it)->updateMouseGrab();
03148 }
03149
03150 }
03151
03152 #include "workspace.moc"