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