00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "workspace.h"
00015
00016 #include <kapplication.h>
00017 #include <kstartupinfo.h>
00018 #include <fixx11h.h>
00019 #include <kconfig.h>
00020 #include <kglobal.h>
00021 #include <qpopupmenu.h>
00022 #include <klocale.h>
00023 #include <qregexp.h>
00024 #include <qpainter.h>
00025 #include <qbitmap.h>
00026 #include <qclipboard.h>
00027 #include <kmenubar.h>
00028 #include <kprocess.h>
00029 #include <kglobalaccel.h>
00030 #include <dcopclient.h>
00031
00032 #include "plugins.h"
00033 #include "client.h"
00034 #include "popupinfo.h"
00035 #include "tabbox.h"
00036 #include "atoms.h"
00037 #include "placement.h"
00038 #include "notifications.h"
00039 #include "group.h"
00040 #include "rules.h"
00041
00042 #include <X11/extensions/shape.h>
00043 #include <X11/keysym.h>
00044 #include <X11/keysymdef.h>
00045 #include <X11/cursorfont.h>
00046
00047 extern Time qt_x_time;
00048
00049 namespace KWinInternal
00050 {
00051
00052 extern int screen_number;
00053
00054 Workspace *Workspace::_self = 0;
00055
00056 KProcess* kompmgr = 0;
00057
00058 bool allowKompmgrRestart = TRUE;
00059
00060
00061
00062
00063
00064
00065
00066
00067 Workspace::Workspace( bool restore )
00068 : DCOPObject ("KWinInterface"),
00069 QObject (0, "workspace"),
00070 current_desktop (0),
00071 number_of_desktops(0),
00072 active_popup( NULL ),
00073 active_popup_client( NULL ),
00074 desktop_widget (0),
00075 temporaryRulesMessages( "_KDE_NET_WM_TEMPORARY_RULES", NULL, false ),
00076 active_client (0),
00077 last_active_client (0),
00078 most_recently_raised (0),
00079 movingClient(0),
00080 pending_take_activity ( NULL ),
00081 delayfocus_client (0),
00082 was_user_interaction (false),
00083 session_saving (false),
00084 control_grab (false),
00085 tab_grab (false),
00086 mouse_emulation (false),
00087 block_focus (0),
00088 tab_box (0),
00089 popupinfo (0),
00090 popup (0),
00091 advanced_popup (0),
00092 desk_popup (0),
00093 desk_popup_index (0),
00094 keys (0),
00095 client_keys ( NULL ),
00096 client_keys_dialog ( NULL ),
00097 client_keys_client ( NULL ),
00098 root (0),
00099 workspaceInit (true),
00100 startup(0), electric_have_borders(false),
00101 electric_current_border(0),
00102 electric_top_border(None),
00103 electric_bottom_border(None),
00104 electric_left_border(None),
00105 electric_right_border(None),
00106 layoutOrientation(Qt::Vertical),
00107 layoutX(-1),
00108 layoutY(2),
00109 workarea(NULL),
00110 screenarea(NULL),
00111 managing_topmenus( false ),
00112 topmenu_selection( NULL ),
00113 topmenu_watcher( NULL ),
00114 topmenu_height( 0 ),
00115 topmenu_space( NULL ),
00116 set_active_client_recursion( 0 ),
00117 block_stacking_updates( 0 ),
00118 forced_global_mouse_grab( false )
00119 {
00120 _self = this;
00121 mgr = new PluginMgr;
00122 root = qt_xrootwin();
00123 default_colormap = DefaultColormap(qt_xdisplay(), qt_xscreen() );
00124 installed_colormap = default_colormap;
00125 session.setAutoDelete( TRUE );
00126
00127 connect( &temporaryRulesMessages, SIGNAL( gotMessage( const QString& )),
00128 this, SLOT( gotTemporaryRulesMessage( const QString& )));
00129 connect( &rulesUpdatedTimer, SIGNAL( timeout()), this, SLOT( writeWindowRules()));
00130
00131 updateXTime();
00132
00133 delayFocusTimer = 0;
00134
00135 electric_time_first = qt_x_time;
00136 electric_time_last = qt_x_time;
00137
00138 if ( restore )
00139 loadSessionInfo();
00140
00141 loadWindowRules();
00142
00143 (void) QApplication::desktop();
00144
00145 desktop_widget =
00146 new QWidget(
00147 0,
00148 "desktop_widget",
00149 Qt::WType_Desktop | Qt::WPaintUnclipped
00150 );
00151
00152 kapp->setGlobalMouseTracking( true );
00153
00154 startup = new KStartupInfo(
00155 KStartupInfo::DisableKWinModule | KStartupInfo::AnnounceSilenceChanges, this );
00156
00157
00158 XSelectInput(qt_xdisplay(), root,
00159 KeyPressMask |
00160 PropertyChangeMask |
00161 ColormapChangeMask |
00162 SubstructureRedirectMask |
00163 SubstructureNotifyMask |
00164 FocusChangeMask
00165 );
00166
00167 Shape::init();
00168
00169
00170 long data = 1;
00171
00172 XChangeProperty(
00173 qt_xdisplay(),
00174 qt_xrootwin(),
00175 atoms->kwin_running,
00176 atoms->kwin_running,
00177 32,
00178 PropModeAppend,
00179 (unsigned char*) &data,
00180 1
00181 );
00182
00183 client_keys = new KGlobalAccel( this );
00184 initShortcuts();
00185 tab_box = new TabBox( this );
00186 popupinfo = new PopupInfo( );
00187
00188 init();
00189
00190 #if (QT_VERSION-0 >= 0x030200) // XRANDR support
00191 connect( kapp->desktop(), SIGNAL( resized( int )), SLOT( desktopResized()));
00192 #endif
00193
00194
00195 if (options->useTranslucency)
00196 {
00197 kompmgr = new KProcess;
00198 connect(kompmgr, SIGNAL(receivedStderr(KProcess*, char*, int)), SLOT(handleKompmgrOutput(KProcess*, char*, int)));
00199 *kompmgr << "kompmgr";
00200 startKompmgr();
00201 }
00202 }
00203
00204
00205 void Workspace::init()
00206 {
00207 checkElectricBorders();
00208
00209
00210
00211
00212
00213 supportWindow = new QWidget;
00214 XLowerWindow( qt_xdisplay(), supportWindow->winId());
00215
00216 XSetWindowAttributes attr;
00217 attr.override_redirect = 1;
00218 null_focus_window = XCreateWindow( qt_xdisplay(), qt_xrootwin(), -1,-1, 1, 1, 0, CopyFromParent,
00219 InputOnly, CopyFromParent, CWOverrideRedirect, &attr );
00220 XMapWindow(qt_xdisplay(), null_focus_window);
00221
00222 unsigned long protocols[ 5 ] =
00223 {
00224 NET::Supported |
00225 NET::SupportingWMCheck |
00226 NET::ClientList |
00227 NET::ClientListStacking |
00228 NET::DesktopGeometry |
00229 NET::NumberOfDesktops |
00230 NET::CurrentDesktop |
00231 NET::ActiveWindow |
00232 NET::WorkArea |
00233 NET::CloseWindow |
00234 NET::DesktopNames |
00235 NET::KDESystemTrayWindows |
00236 NET::WMName |
00237 NET::WMVisibleName |
00238 NET::WMDesktop |
00239 NET::WMWindowType |
00240 NET::WMState |
00241 NET::WMStrut |
00242 NET::WMIconGeometry |
00243 NET::WMIcon |
00244 NET::WMPid |
00245 NET::WMMoveResize |
00246 NET::WMKDESystemTrayWinFor |
00247 NET::WMKDEFrameStrut |
00248 NET::WMPing
00249 ,
00250 NET::NormalMask |
00251 NET::DesktopMask |
00252 NET::DockMask |
00253 NET::ToolbarMask |
00254 NET::MenuMask |
00255 NET::DialogMask |
00256 NET::OverrideMask |
00257 NET::TopMenuMask |
00258 NET::UtilityMask |
00259 NET::SplashMask |
00260 0
00261 ,
00262 NET::Modal |
00263
00264 NET::MaxVert |
00265 NET::MaxHoriz |
00266 NET::Shaded |
00267 NET::SkipTaskbar |
00268 NET::KeepAbove |
00269
00270 NET::SkipPager |
00271 NET::Hidden |
00272 NET::FullScreen |
00273 NET::KeepBelow |
00274 NET::DemandsAttention |
00275 0
00276 ,
00277 NET::WM2UserTime |
00278 NET::WM2StartupId |
00279 NET::WM2AllowedActions |
00280 NET::WM2RestackWindow |
00281 NET::WM2MoveResizeWindow |
00282 NET::WM2ExtendedStrut |
00283 NET::WM2KDETemporaryRules |
00284 0
00285 ,
00286 NET::ActionMove |
00287 NET::ActionResize |
00288 NET::ActionMinimize |
00289 NET::ActionShade |
00290
00291 NET::ActionMaxVert |
00292 NET::ActionMaxHoriz |
00293 NET::ActionFullScreen |
00294 NET::ActionChangeDesktop |
00295 NET::ActionClose |
00296 0
00297 ,
00298 };
00299
00300 rootInfo = new RootInfo( this, qt_xdisplay(), supportWindow->winId(), "KWin",
00301 protocols, 5, qt_xscreen() );
00302
00303 loadDesktopSettings();
00304
00305 NETRootInfo client_info( qt_xdisplay(), NET::ActiveWindow | NET::CurrentDesktop );
00306 int initial_desktop;
00307 if( !kapp->isSessionRestored())
00308 initial_desktop = client_info.currentDesktop();
00309 else
00310 {
00311 KConfigGroupSaver saver( kapp->sessionConfig(), "Session" );
00312 initial_desktop = kapp->sessionConfig()->readNumEntry( "desktop", 1 );
00313 }
00314 if( !setCurrentDesktop( initial_desktop ))
00315 setCurrentDesktop( 1 );
00316
00317
00318 initPositioning = new Placement(this);
00319
00320 connect(&reconfigureTimer, SIGNAL(timeout()), this,
00321 SLOT(slotReconfigure()));
00322 connect( &updateToolWindowsTimer, SIGNAL( timeout()), this, SLOT( slotUpdateToolWindows()));
00323
00324 connect(kapp, SIGNAL(appearanceChanged()), this,
00325 SLOT(slotReconfigure()));
00326 connect(kapp, SIGNAL(settingsChanged(int)), this,
00327 SLOT(slotSettingsChanged(int)));
00328
00329 active_client = NULL;
00330 rootInfo->setActiveWindow( None );
00331 focusToNull();
00332 if( !kapp->isSessionRestored())
00333 ++block_focus;
00334
00335 char nm[ 100 ];
00336 sprintf( nm, "_KDE_TOPMENU_OWNER_S%d", DefaultScreen( qt_xdisplay()));
00337 Atom topmenu_atom = XInternAtom( qt_xdisplay(), nm, False );
00338 topmenu_selection = new KSelectionOwner( topmenu_atom );
00339 topmenu_watcher = new KSelectionWatcher( topmenu_atom );
00340
00341
00342 {
00343 StackingUpdatesBlocker blocker( this );
00344
00345 if( options->topMenuEnabled() && topmenu_selection->claim( false ))
00346 setupTopMenuHandling();
00347 else
00348 lostTopMenuSelection();
00349
00350 unsigned int i, nwins;
00351 Window root_return, parent_return, *wins;
00352 XQueryTree(qt_xdisplay(), root, &root_return, &parent_return, &wins, &nwins);
00353 for (i = 0; i < nwins; i++)
00354 {
00355 XWindowAttributes attr;
00356 XGetWindowAttributes(qt_xdisplay(), wins[i], &attr);
00357 if (attr.override_redirect )
00358 continue;
00359 if( topmenu_space && topmenu_space->winId() == wins[ i ] )
00360 continue;
00361 if (attr.map_state != IsUnmapped)
00362 {
00363 if ( addSystemTrayWin( wins[i] ) )
00364 continue;
00365 Client* c = createClient( wins[i], true );
00366 if ( c != NULL && root != qt_xrootwin() )
00367 {
00368
00369 XReparentWindow( qt_xdisplay(), c->frameId(), root, 0, 0 );
00370 c->move(0,0);
00371 }
00372 }
00373 }
00374 if ( wins )
00375 XFree((void *) wins);
00376
00377 updateStackingOrder( true );
00378
00379 updateClientArea();
00380 raiseElectricBorders();
00381
00382
00383 NETPoint* viewports = new NETPoint[ number_of_desktops ];
00384 rootInfo->setDesktopViewport( number_of_desktops, *viewports );
00385 delete[] viewports;
00386 QRect geom = QApplication::desktop()->geometry();
00387 NETSize desktop_geometry;
00388 desktop_geometry.width = geom.width();
00389 desktop_geometry.height = geom.height();
00390
00391 rootInfo->setDesktopGeometry( -1, desktop_geometry );
00392
00393 }
00394
00395 Client* new_active_client = NULL;
00396 if( !kapp->isSessionRestored())
00397 {
00398 --block_focus;
00399 new_active_client = findClient( WindowMatchPredicate( client_info.activeWindow()));
00400 }
00401 if( new_active_client == NULL
00402 && activeClient() == NULL && should_get_focus.count() == 0 )
00403 {
00404 if( new_active_client == NULL )
00405 new_active_client = topClientOnDesktop( currentDesktop());
00406 if( new_active_client == NULL && !desktops.isEmpty() )
00407 new_active_client = findDesktop( true, currentDesktop());
00408 }
00409 if( new_active_client != NULL )
00410 activateClient( new_active_client );
00411
00412
00413
00414 workspaceInit = false;
00415
00416 }
00417
00418 Workspace::~Workspace()
00419 {
00420 if (kompmgr)
00421 delete kompmgr;
00422 blockStackingUpdates( true );
00423
00424
00425 for( ClientList::ConstIterator it = stacking_order.begin();
00426 it != stacking_order.end();
00427 ++it )
00428 {
00429
00430 (*it)->releaseWindow( true );
00431
00432 }
00433 delete desktop_widget;
00434 delete tab_box;
00435 delete popupinfo;
00436 delete popup;
00437 if ( root == qt_xrootwin() )
00438 XDeleteProperty(qt_xdisplay(), qt_xrootwin(), atoms->kwin_running);
00439
00440 writeWindowRules();
00441 KGlobal::config()->sync();
00442
00443 delete rootInfo;
00444 delete supportWindow;
00445 delete mgr;
00446 delete[] workarea;
00447 delete[] screenarea;
00448 delete startup;
00449 delete initPositioning;
00450 delete topmenu_watcher;
00451 delete topmenu_selection;
00452 delete topmenu_space;
00453 delete client_keys_dialog;
00454 while( !rules.isEmpty())
00455 {
00456 delete rules.front();
00457 rules.pop_front();
00458 }
00459 XDestroyWindow( qt_xdisplay(), null_focus_window );
00460
00461 _self = 0;
00462 }
00463
00464 Client* Workspace::createClient( Window w, bool is_mapped )
00465 {
00466 StackingUpdatesBlocker blocker( this );
00467 Client* c = new Client( this );
00468 if( !c->manage( w, is_mapped ))
00469 {
00470 Client::deleteClient( c, Allowed );
00471 return NULL;
00472 }
00473 addClient( c, Allowed );
00474 return c;
00475 }
00476
00477 void Workspace::addClient( Client* c, allowed_t )
00478 {
00479
00480
00481 c->setBMP(c->resourceName() == "beep-media-player" || c->decorationId() == None);
00482
00483 c->getWindowOpacity();
00484 if (c->isDock())
00485 {
00486
00487 if (!c->hasCustomOpacity())
00488 {
00489 c->setShadowSize(options->dockShadowSize);
00490 c->setOpacity(options->translucentDocks, options->dockOpacity);
00491 }
00492 }
00493
00494 Group* grp = findGroup( c->window());
00495 if( grp != NULL )
00496 grp->gotLeader( c );
00497
00498 if ( c->isDesktop() )
00499 {
00500 desktops.append( c );
00501 if( active_client == NULL && should_get_focus.isEmpty() && c->isOnCurrentDesktop())
00502 requestFocus( c );
00503 }
00504 else
00505 {
00506 if ( c->wantsTabFocus() && !focus_chain.contains( c ))
00507 focus_chain.append( c );
00508 clients.append( c );
00509 }
00510 if( !unconstrained_stacking_order.contains( c ))
00511 unconstrained_stacking_order.append( c );
00512 if( !stacking_order.contains( c ))
00513 stacking_order.append( c );
00514 if( c->isTopMenu())
00515 addTopMenu( c );
00516 updateClientArea();
00517 updateClientLayer( c );
00518 if( c->isDesktop())
00519 {
00520 raiseClient( c );
00521
00522 if( activeClient() == NULL && should_get_focus.count() == 0 )
00523 activateClient( findDesktop( true, currentDesktop()));
00524 }
00525 c->checkActiveModal();
00526 checkTransients( c->window());
00527 updateStackingOrder( true );
00528 if( c->isUtility() || c->isMenu() || c->isToolbar())
00529 updateToolWindows( true );
00530 }
00531
00532
00533
00534
00535 void Workspace::removeClient( Client* c, allowed_t )
00536 {
00537 if (c == active_popup_client)
00538 closeActivePopup();
00539
00540 if( client_keys_client == c )
00541 setupWindowShortcutDone( false );
00542 if( !c->shortcut().isNull())
00543 c->setShortcut( QString::null );
00544
00545 if( c->isDialog())
00546 Notify::raise( Notify::TransDelete );
00547 if( c->isNormalWindow())
00548 Notify::raise( Notify::Delete );
00549
00550 Q_ASSERT( clients.contains( c ) || desktops.contains( c ));
00551 clients.remove( c );
00552 desktops.remove( c );
00553 unconstrained_stacking_order.remove( c );
00554 stacking_order.remove( c );
00555 focus_chain.remove( c );
00556 attention_chain.remove( c );
00557 if( c->isTopMenu())
00558 removeTopMenu( c );
00559 Group* group = findGroup( c->window());
00560 if( group != NULL )
00561 group->lostLeader();
00562
00563 if ( c == most_recently_raised )
00564 most_recently_raised = 0;
00565 should_get_focus.remove( c );
00566 Q_ASSERT( c != active_client );
00567 if ( c == last_active_client )
00568 last_active_client = 0;
00569 if( c == pending_take_activity )
00570 pending_take_activity = NULL;
00571 if( c == delayfocus_client )
00572 cancelDelayFocus();
00573
00574 updateStackingOrder( true );
00575
00576 if (tab_grab)
00577 tab_box->repaint();
00578
00579 updateClientArea();
00580 }
00581
00582 void Workspace::updateCurrentTopMenu()
00583 {
00584 if( !managingTopMenus())
00585 return;
00586
00587 Client* menubar = 0;
00588 bool block_desktop_menubar = false;
00589 if( active_client )
00590 {
00591
00592 Client* menu_client = active_client;
00593 for(;;)
00594 {
00595 if( menu_client->isFullScreen())
00596 block_desktop_menubar = true;
00597 for( ClientList::ConstIterator it = menu_client->transients().begin();
00598 it != menu_client->transients().end();
00599 ++it )
00600 if( (*it)->isTopMenu())
00601 {
00602 menubar = *it;
00603 break;
00604 }
00605 if( menubar != NULL || !menu_client->isTransient())
00606 break;
00607 if( menu_client->isModal() || menu_client->transientFor() == NULL )
00608 break;
00609 menu_client = menu_client->transientFor();
00610 }
00611 if( !menubar )
00612 {
00613 for( ClientList::ConstIterator it = active_client->group()->members().begin();
00614 it != active_client->group()->members().end();
00615 ++it )
00616 if( (*it)->isTopMenu())
00617 {
00618 menubar = *it;
00619 break;
00620 }
00621 }
00622 }
00623 if( !menubar && !block_desktop_menubar && options->desktopTopMenu())
00624 {
00625
00626 Client* desktop = findDesktop( true, currentDesktop());
00627 if( desktop != NULL )
00628 {
00629 for( ClientList::ConstIterator it = desktop->transients().begin();
00630 it != desktop->transients().end();
00631 ++it )
00632 if( (*it)->isTopMenu())
00633 {
00634 menubar = *it;
00635 break;
00636 }
00637 }
00638
00639
00640
00641 if( menubar == NULL )
00642 {
00643 for( ClientList::ConstIterator it = topmenus.begin();
00644 it != topmenus.end();
00645 ++it )
00646 if( (*it)->wasOriginallyGroupTransient())
00647 {
00648 menubar = *it;
00649 break;
00650 }
00651 }
00652 }
00653
00654
00655 if ( menubar )
00656 {
00657 if( active_client && !menubar->isOnDesktop( active_client->desktop()))
00658 menubar->setDesktop( active_client->desktop());
00659 menubar->hideClient( false );
00660 topmenu_space->hide();
00661
00662
00663
00664 unconstrained_stacking_order.remove( menubar );
00665 unconstrained_stacking_order.append( menubar );
00666 }
00667 else if( !block_desktop_menubar )
00668 {
00669 topmenu_space->show();
00670 }
00671
00672
00673 for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
00674 {
00675 if( (*it)->isTopMenu() && (*it) != menubar )
00676 (*it)->hideClient( true );
00677 }
00678 }
00679
00680
00681 void Workspace::updateToolWindows( bool also_hide )
00682 {
00683
00684 const Group* group = NULL;
00685 const Client* client = active_client;
00686
00687
00688 while( client != NULL )
00689 {
00690 if( !client->isTransient())
00691 break;
00692 if( client->groupTransient())
00693 {
00694 group = client->group();
00695 break;
00696 }
00697 client = client->transientFor();
00698 }
00699
00700
00701
00702
00703 ClientList to_show, to_hide;
00704 for( ClientList::ConstIterator it = stacking_order.begin();
00705 it != stacking_order.end();
00706 ++it )
00707 {
00708 if( (*it)->isUtility() || (*it)->isMenu() || (*it)->isToolbar())
00709 {
00710 bool show = true;
00711 if( !(*it)->isTransient())
00712 {
00713 if( (*it)->group()->members().count() == 1 )
00714 show = true;
00715 else if( client != NULL && (*it)->group() == client->group())
00716 show = true;
00717 else
00718 show = false;
00719 }
00720 else
00721 {
00722 if( group != NULL && (*it)->group() == group )
00723 show = true;
00724 else if( client != NULL && client->hasTransient( (*it), true ))
00725 show = true;
00726 else
00727 show = false;
00728 }
00729 if( !show && also_hide )
00730 {
00731 const ClientList mainclients = (*it)->mainClients();
00732
00733
00734 if( mainclients.isEmpty())
00735 show = true;
00736 for( ClientList::ConstIterator it2 = mainclients.begin();
00737 it2 != mainclients.end();
00738 ++it2 )
00739 {
00740 if( (*it2)->isSpecialWindow())
00741 show = true;
00742 }
00743 if( !show )
00744 to_hide.append( *it );
00745 }
00746 if( show )
00747 to_show.append( *it );
00748 }
00749 }
00750 for( ClientList::ConstIterator it = to_show.fromLast();
00751 it != to_show.end();
00752 --it )
00753
00754 (*it)->hideClient( false );
00755 if( also_hide )
00756 {
00757 for( ClientList::ConstIterator it = to_hide.begin();
00758 it != to_hide.end();
00759 ++it )
00760 (*it)->hideClient( true );
00761 updateToolWindowsTimer.stop();
00762 }
00763 else
00764 {
00765 updateToolWindowsTimer.start( 50, true );
00766 }
00767 }
00768
00769 void Workspace::slotUpdateToolWindows()
00770 {
00771 updateToolWindows( true );
00772 }
00773
00777 void Workspace::updateColormap()
00778 {
00779 Colormap cmap = default_colormap;
00780 if ( activeClient() && activeClient()->colormap() != None )
00781 cmap = activeClient()->colormap();
00782 if ( cmap != installed_colormap )
00783 {
00784 XInstallColormap(qt_xdisplay(), cmap );
00785 installed_colormap = cmap;
00786 }
00787 }
00788
00789 void Workspace::reconfigure()
00790 {
00791 reconfigureTimer.start(200, true);
00792 }
00793
00794
00795 void Workspace::slotSettingsChanged(int category)
00796 {
00797 kdDebug(1212) << "Workspace::slotSettingsChanged()" << endl;
00798 if( category == (int) KApplication::SETTINGS_SHORTCUTS )
00799 readShortcuts();
00800 }
00801
00805 KWIN_PROCEDURE( CheckBorderSizesProcedure, cl->checkBorderSizes() );
00806 KWIN_PROCEDURE( ResetupRulesProcedure, cl->setupWindowRules( true ) );
00807
00808 void Workspace::slotReconfigure()
00809 {
00810 kdDebug(1212) << "Workspace::slotReconfigure()" << endl;
00811 reconfigureTimer.stop();
00812
00813 KGlobal::config()->reparseConfiguration();
00814 unsigned long changed = options->updateSettings();
00815 tab_box->reconfigure();
00816 popupinfo->reconfigure();
00817 readShortcuts();
00818 forEachClient( CheckIgnoreFocusStealingProcedure());
00819
00820 if( mgr->reset( changed ))
00821 {
00822 #if 0 // This actually seems to make things worse now
00823 QWidget curtain;
00824 curtain.setBackgroundMode( NoBackground );
00825 curtain.setGeometry( QApplication::desktop()->geometry() );
00826 curtain.show();
00827 #endif
00828 for( ClientList::ConstIterator it = clients.begin();
00829 it != clients.end();
00830 ++it )
00831 {
00832 (*it)->updateDecoration( true, true );
00833 }
00834 mgr->destroyPreviousPlugin();
00835 }
00836 else
00837 {
00838 forEachClient( CheckBorderSizesProcedure());
00839 }
00840
00841 checkElectricBorders();
00842
00843 if( options->topMenuEnabled() && !managingTopMenus())
00844 {
00845 if( topmenu_selection->claim( false ))
00846 setupTopMenuHandling();
00847 else
00848 lostTopMenuSelection();
00849 }
00850 else if( !options->topMenuEnabled() && managingTopMenus())
00851 {
00852 topmenu_selection->release();
00853 lostTopMenuSelection();
00854 }
00855 topmenu_height = 0;
00856 if( managingTopMenus())
00857 {
00858 updateTopMenuGeometry();
00859 updateCurrentTopMenu();
00860 }
00861
00862 loadWindowRules();
00863 forEachClient( ResetupRulesProcedure());
00864
00865 if (options->resetKompmgr)
00866 {
00867 bool tmp = options->useTranslucency;
00868 stopKompmgr();
00869 if (tmp)
00870 QTimer::singleShot( 200, this, SLOT(startKompmgr()) );
00871 }
00872 }
00873
00874 void Workspace::loadDesktopSettings()
00875 {
00876 KConfig* c = KGlobal::config();
00877 QCString groupname;
00878 if (screen_number == 0)
00879 groupname = "Desktops";
00880 else
00881 groupname.sprintf("Desktops-screen-%d", screen_number);
00882 KConfigGroupSaver saver(c,groupname);
00883
00884 int n = c->readNumEntry("Number", 4);
00885 number_of_desktops = n;
00886 delete workarea;
00887 workarea = new QRect[ n + 1 ];
00888 delete screenarea;
00889 screenarea = NULL;
00890 rootInfo->setNumberOfDesktops( number_of_desktops );
00891 desktop_focus_chain.resize( n );
00892 for(int i = 1; i <= n; i++)
00893 {
00894 QString s = c->readEntry(QString("Name_%1").arg(i),
00895 i18n("Desktop %1").arg(i));
00896 rootInfo->setDesktopName( i, s.utf8().data() );
00897 desktop_focus_chain[i-1] = i;
00898 }
00899 }
00900
00901 void Workspace::saveDesktopSettings()
00902 {
00903 KConfig* c = KGlobal::config();
00904 QCString groupname;
00905 if (screen_number == 0)
00906 groupname = "Desktops";
00907 else
00908 groupname.sprintf("Desktops-screen-%d", screen_number);
00909 KConfigGroupSaver saver(c,groupname);
00910
00911 c->writeEntry("Number", number_of_desktops );
00912 for(int i = 1; i <= number_of_desktops; i++)
00913 {
00914 QString s = desktopName( i );
00915 QString defaultvalue = i18n("Desktop %1").arg(i);
00916 if ( s.isEmpty() )
00917 {
00918 s = defaultvalue;
00919 rootInfo->setDesktopName( i, s.utf8().data() );
00920 }
00921
00922 if (s != defaultvalue)
00923 {
00924 c->writeEntry( QString("Name_%1").arg(i), s );
00925 }
00926 else
00927 {
00928 QString currentvalue = c->readEntry(QString("Name_%1").arg(i));
00929 if (currentvalue != defaultvalue)
00930 c->writeEntry( QString("Name_%1").arg(i), "" );
00931 }
00932 }
00933 }
00934
00935 QStringList Workspace::configModules(bool controlCenter)
00936 {
00937 QStringList args;
00938 args << "kde-kwindecoration.desktop";
00939 if (controlCenter)
00940 args << "kde-kwinoptions.desktop";
00941 else if (kapp->authorizeControlModule("kde-kwinoptions.desktop"))
00942 args << "kwinactions" << "kwinfocus" << "kwinmoving" << "kwinadvanced" << "kwinrules" << "kwintranslucency";
00943 return args;
00944 }
00945
00946 void Workspace::configureWM()
00947 {
00948 KApplication::kdeinitExec( "kcmshell", configModules(false) );
00949 }
00950
00954 void Workspace::doNotManage( QString title )
00955 {
00956 doNotManageList.append( title );
00957 }
00958
00962 bool Workspace::isNotManaged( const QString& title )
00963 {
00964 for ( QStringList::Iterator it = doNotManageList.begin(); it != doNotManageList.end(); ++it )
00965 {
00966 QRegExp r( (*it) );
00967 if (r.search(title) != -1)
00968 {
00969 doNotManageList.remove( it );
00970 return TRUE;
00971 }
00972 }
00973 return FALSE;
00974 }
00975
00979 void Workspace::refresh()
00980 {
00981 QWidget w;
00982 w.setGeometry( QApplication::desktop()->geometry() );
00983 w.show();
00984 w.hide();
00985 QApplication::flushX();
00986 }
00987
00995 class ObscuringWindows
00996 {
00997 public:
00998 ~ObscuringWindows();
00999 void create( Client* c );
01000 private:
01001 QValueList<Window> obscuring_windows;
01002 static QValueList<Window>* cached;
01003 static unsigned int max_cache_size;
01004 };
01005
01006 QValueList<Window>* ObscuringWindows::cached = 0;
01007 unsigned int ObscuringWindows::max_cache_size = 0;
01008
01009 void ObscuringWindows::create( Client* c )
01010 {
01011 if( cached == 0 )
01012 cached = new QValueList<Window>;
01013 Window obs_win;
01014 XWindowChanges chngs;
01015 int mask = CWSibling | CWStackMode;
01016 if( cached->count() > 0 )
01017 {
01018 cached->remove( obs_win = cached->first());
01019 chngs.x = c->x();
01020 chngs.y = c->y();
01021 chngs.width = c->width();
01022 chngs.height = c->height();
01023 mask |= CWX | CWY | CWWidth | CWHeight;
01024 }
01025 else
01026 {
01027 XSetWindowAttributes a;
01028 a.background_pixmap = None;
01029 a.override_redirect = True;
01030 obs_win = XCreateWindow( qt_xdisplay(), qt_xrootwin(), c->x(), c->y(),
01031 c->width(), c->height(), 0, CopyFromParent, InputOutput,
01032 CopyFromParent, CWBackPixmap | CWOverrideRedirect, &a );
01033 }
01034 chngs.sibling = c->frameId();
01035 chngs.stack_mode = Below;
01036 XConfigureWindow( qt_xdisplay(), obs_win, mask, &chngs );
01037 XMapWindow( qt_xdisplay(), obs_win );
01038 obscuring_windows.append( obs_win );
01039 }
01040
01041 ObscuringWindows::~ObscuringWindows()
01042 {
01043 max_cache_size = QMAX( max_cache_size, obscuring_windows.count() + 4 ) - 1;
01044 for( QValueList<Window>::ConstIterator it = obscuring_windows.begin();
01045 it != obscuring_windows.end();
01046 ++it )
01047 {
01048 XUnmapWindow( qt_xdisplay(), *it );
01049 if( cached->count() < max_cache_size )
01050 cached->prepend( *it );
01051 else
01052 XDestroyWindow( qt_xdisplay(), *it );
01053 }
01054 }
01055
01056
01063 bool Workspace::setCurrentDesktop( int new_desktop )
01064 {
01065 if (new_desktop < 1 || new_desktop > number_of_desktops )
01066 return false;
01067
01068 closeActivePopup();
01069 ++block_focus;
01070
01071 StackingUpdatesBlocker blocker( this );
01072
01073 if (new_desktop != current_desktop)
01074 {
01075
01076
01077
01078
01079 Notify::raise((Notify::Event) (Notify::DesktopChange+new_desktop));
01080
01081 ObscuringWindows obs_wins;
01082
01083 int old_desktop = current_desktop;
01084 current_desktop = new_desktop;
01085
01086 for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it)
01087 if ( !(*it)->isOnDesktop( new_desktop ) && (*it) != movingClient )
01088 {
01089 if( (*it)->isShown( true ) && (*it)->isOnDesktop( old_desktop ))
01090 obs_wins.create( *it );
01091 (*it)->virtualDesktopChange();
01092 }
01093
01094 rootInfo->setCurrentDesktop( current_desktop );
01095
01096 if( movingClient && !movingClient->isOnDesktop( new_desktop ))
01097 movingClient->setDesktop( new_desktop );
01098
01099 for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it)
01100 if ( (*it)->isOnDesktop( new_desktop ) )
01101 (*it)->virtualDesktopChange();
01102 }
01103
01104
01105 --block_focus;
01106 Client* c = 0;
01107
01108 if ( options->focusPolicyIsReasonable())
01109 {
01110
01111
01112 if ( focus_chain.contains( active_client ) && active_client->isShown( true )
01113 && active_client->isOnCurrentDesktop())
01114 {
01115 c = active_client;
01116 }
01117
01118 if ( !c )
01119 {
01120 for( ClientList::ConstIterator it = focus_chain.fromLast(); it != focus_chain.end(); --it)
01121 {
01122 if ( (*it)->isShown( false ) && !(*it)->isOnAllDesktops() && (*it)->isOnCurrentDesktop())
01123 {
01124 c = *it;
01125 break;
01126 }
01127 }
01128 }
01129
01130 if ( !c )
01131 {
01132 for( ClientList::ConstIterator it = focus_chain.fromLast(); it != focus_chain.end(); --it)
01133 {
01134 if ( (*it)->isShown( false ) && (*it)->isOnCurrentDesktop())
01135 {
01136 c = *it;
01137 break;
01138 }
01139 }
01140 }
01141 }
01142
01143
01144
01145
01146 else if( active_client && active_client->isShown( true ) && active_client->isOnCurrentDesktop())
01147 c= active_client;
01148
01149 if( c != active_client )
01150 setActiveClient( NULL, Allowed );
01151
01152 if ( c )
01153 requestFocus( c );
01154 else
01155 focusToNull();
01156
01157 if( !desktops.isEmpty() )
01158 {
01159 Window w_tmp;
01160 int i_tmp;
01161 XGetInputFocus( qt_xdisplay(), &w_tmp, &i_tmp );
01162 if( w_tmp == null_focus_window )
01163 requestFocus( findDesktop( true, currentDesktop()));
01164 }
01165
01166 updateCurrentTopMenu();
01167
01168
01169
01170
01171
01172
01173 for( int i = desktop_focus_chain.find( current_desktop ); i > 0; i-- )
01174 desktop_focus_chain[i] = desktop_focus_chain[i-1];
01175 desktop_focus_chain[0] = current_desktop;
01176
01177
01178
01179
01180
01181 return true;
01182 }
01183
01184
01185 void Workspace::nextDesktop()
01186 {
01187 int desktop = currentDesktop() + 1;
01188 setCurrentDesktop(desktop > numberOfDesktops() ? 1 : desktop);
01189 popupinfo->showInfo( desktopName(currentDesktop()) );
01190 }
01191
01192
01193 void Workspace::previousDesktop()
01194 {
01195 int desktop = currentDesktop() - 1;
01196 setCurrentDesktop(desktop > 0 ? desktop : numberOfDesktops());
01197 popupinfo->showInfo( desktopName(currentDesktop()) );
01198 }
01199
01200 int Workspace::desktopToRight( int desktop ) const
01201 {
01202 int x,y;
01203 calcDesktopLayout(x,y);
01204 int dt = desktop-1;
01205 if (layoutOrientation == Qt::Vertical)
01206 {
01207 dt += y;
01208 if ( dt >= numberOfDesktops() )
01209 {
01210 if ( options->rollOverDesktops )
01211 dt -= numberOfDesktops();
01212 else
01213 return desktop;
01214 }
01215 }
01216 else
01217 {
01218 int d = (dt % x) + 1;
01219 if ( d >= x )
01220 {
01221 if ( options->rollOverDesktops )
01222 d -= x;
01223 else
01224 return desktop;
01225 }
01226 dt = dt - (dt % x) + d;
01227 }
01228 return dt+1;
01229 }
01230
01231 int Workspace::desktopToLeft( int desktop ) const
01232 {
01233 int x,y;
01234 calcDesktopLayout(x,y);
01235 int dt = desktop-1;
01236 if (layoutOrientation == Qt::Vertical)
01237 {
01238 dt -= y;
01239 if ( dt < 0 )
01240 {
01241 if ( options->rollOverDesktops )
01242 dt += numberOfDesktops();
01243 else
01244 return desktop;
01245 }
01246 }
01247 else
01248 {
01249 int d = (dt % x) - 1;
01250 if ( d < 0 )
01251 {
01252 if ( options->rollOverDesktops )
01253 d += x;
01254 else
01255 return desktop;
01256 }
01257 dt = dt - (dt % x) + d;
01258 }
01259 return dt+1;
01260 }
01261
01262 int Workspace::desktopUp( int desktop ) const
01263 {
01264 int x,y;
01265 calcDesktopLayout(x,y);
01266 int dt = desktop-1;
01267 if (layoutOrientation == Qt::Horizontal)
01268 {
01269 dt -= x;
01270 if ( dt < 0 )
01271 {
01272 if ( options->rollOverDesktops )
01273 dt += numberOfDesktops();
01274 else
01275 return desktop;
01276 }
01277 }
01278 else
01279 {
01280 int d = (dt % y) - 1;
01281 if ( d < 0 )
01282 {
01283 if ( options->rollOverDesktops )
01284 d += y;
01285 else
01286 return desktop;
01287 }
01288 dt = dt - (dt % y) + d;
01289 }
01290 return dt+1;
01291 }
01292
01293 int Workspace::desktopDown( int desktop ) const
01294 {
01295 int x,y;
01296 calcDesktopLayout(x,y);
01297 int dt = desktop-1;
01298 if (layoutOrientation == Qt::Horizontal)
01299 {
01300 dt += x;
01301 if ( dt >= numberOfDesktops() )
01302 {
01303 if ( options->rollOverDesktops )
01304 dt -= numberOfDesktops();
01305 else
01306 return desktop;
01307 }
01308 }
01309 else
01310 {
01311 int d = (dt % y) + 1;
01312 if ( d >= y )
01313 {
01314 if ( options->rollOverDesktops )
01315 d -= y;
01316 else
01317 return desktop;
01318 }
01319 dt = dt - (dt % y) + d;
01320 }
01321 return dt+1;
01322 }
01323
01324
01328 void Workspace::setNumberOfDesktops( int n )
01329 {
01330 if ( n == number_of_desktops )
01331 return;
01332 int old_number_of_desktops = number_of_desktops;
01333 number_of_desktops = n;
01334
01335 if( currentDesktop() > numberOfDesktops())
01336 setCurrentDesktop( numberOfDesktops());
01337
01338
01339
01340 if( old_number_of_desktops < number_of_desktops )
01341 {
01342 rootInfo->setNumberOfDesktops( number_of_desktops );
01343 NETPoint* viewports = new NETPoint[ number_of_desktops ];
01344 rootInfo->setDesktopViewport( number_of_desktops, *viewports );
01345 delete[] viewports;
01346 updateClientArea( true );
01347 }
01348
01349
01350
01351 if( old_number_of_desktops > number_of_desktops )
01352 {
01353 for( ClientList::ConstIterator it = clients.begin();
01354 it != clients.end();
01355 ++it)
01356 {
01357 if( !(*it)->isOnAllDesktops() && (*it)->desktop() > numberOfDesktops())
01358 sendClientToDesktop( *it, numberOfDesktops(), true );
01359 }
01360 }
01361 if( old_number_of_desktops > number_of_desktops )
01362 {
01363 rootInfo->setNumberOfDesktops( number_of_desktops );
01364 NETPoint* viewports = new NETPoint[ number_of_desktops ];
01365 rootInfo->setDesktopViewport( number_of_desktops, *viewports );
01366 delete[] viewports;
01367 updateClientArea( true );
01368 }
01369
01370 saveDesktopSettings();
01371
01372
01373 desktop_focus_chain.resize( n );
01374 for( int i = 0; i < (int)desktop_focus_chain.size(); i++ )
01375 desktop_focus_chain[i] = i+1;
01376 }
01377
01383 void Workspace::sendClientToDesktop( Client* c, int desk, bool dont_activate )
01384 {
01385 bool was_on_desktop = c->isOnDesktop( desk ) || c->isOnAllDesktops();
01386 c->setDesktop( desk );
01387 if ( c->desktop() != desk )
01388 return;
01389 desk = c->desktop();
01390
01391 if ( c->isOnDesktop( currentDesktop() ) )
01392 {
01393 if ( c->wantsTabFocus() && options->focusPolicyIsReasonable()
01394 && !was_on_desktop
01395 && !dont_activate )
01396 requestFocus( c );
01397 else
01398 restackClientUnderActive( c );
01399 }
01400 else
01401 {
01402 raiseClient( c );
01403 focus_chain.remove( c );
01404 if ( c->wantsTabFocus() )
01405 focus_chain.append( c );
01406 }
01407
01408 ClientList transients_stacking_order = ensureStackingOrder( c->transients());
01409 for( ClientList::ConstIterator it = transients_stacking_order.begin();
01410 it != transients_stacking_order.end();
01411 ++it )
01412 sendClientToDesktop( *it, desk, dont_activate );
01413 updateClientArea();
01414 }
01415
01416 void Workspace::setDesktopLayout(int o, int x, int y)
01417 {
01418 layoutOrientation = (Qt::Orientation) o;
01419 layoutX = x;
01420 layoutY = y;
01421 }
01422
01423 void Workspace::calcDesktopLayout(int &x, int &y) const
01424 {
01425 x = layoutX;
01426 y = layoutY;
01427 if ((x == -1) && (y > 0))
01428 x = (numberOfDesktops()+y-1) / y;
01429 else if ((y == -1) && (x > 0))
01430 y = (numberOfDesktops()+x-1) / x;
01431
01432 if (x == -1)
01433 x = 1;
01434 if (y == -1)
01435 y = 1;
01436 }
01437
01442 bool Workspace::addSystemTrayWin( WId w )
01443 {
01444 if ( systemTrayWins.contains( w ) )
01445 return TRUE;
01446
01447 NETWinInfo ni( qt_xdisplay(), w, root, NET::WMKDESystemTrayWinFor );
01448 WId trayWinFor = ni.kdeSystemTrayWinFor();
01449 if ( !trayWinFor )
01450 return FALSE;
01451 systemTrayWins.append( SystemTrayWindow( w, trayWinFor ) );
01452 XSelectInput( qt_xdisplay(), w,
01453 StructureNotifyMask
01454 );
01455 XAddToSaveSet( qt_xdisplay(), w );
01456 propagateSystemTrayWins();
01457 return TRUE;
01458 }
01459
01464 bool Workspace::removeSystemTrayWin( WId w, bool check )
01465 {
01466 if ( !systemTrayWins.contains( w ) )
01467 return FALSE;
01468 if( check )
01469 {
01470
01471
01472
01473
01474
01475
01476
01477 int num_props;
01478 Atom* props = XListProperties( qt_xdisplay(), w, &num_props );
01479 if( props != NULL )
01480 {
01481 for( int i = 0;
01482 i < num_props;
01483 ++i )
01484 if( props[ i ] == atoms->kde_system_tray_embedding )
01485 {
01486 XFree( props );
01487 return false;
01488 }
01489 XFree( props );
01490 }
01491 }
01492 systemTrayWins.remove( w );
01493 propagateSystemTrayWins();
01494 return TRUE;
01495 }
01496
01497
01501 void Workspace::propagateSystemTrayWins()
01502 {
01503 Window *cl = new Window[ systemTrayWins.count()];
01504
01505 int i = 0;
01506 for ( SystemTrayWindowList::ConstIterator it = systemTrayWins.begin(); it != systemTrayWins.end(); ++it )
01507 {
01508 cl[i++] = (*it).win;
01509 }
01510
01511 rootInfo->setKDESystemTrayWindows( cl, i );
01512 delete [] cl;
01513 }
01514
01515
01516 void Workspace::killWindowId( Window window_to_kill )
01517 {
01518 if( window_to_kill == None )
01519 return;
01520 Window window = window_to_kill;
01521 Client* client = NULL;
01522 for(;;)
01523 {
01524 client = findClient( FrameIdMatchPredicate( window ));
01525 if( client != NULL )
01526 break;
01527 Window parent, root;
01528 Window* children;
01529 unsigned int children_count;
01530 XQueryTree( qt_xdisplay(), window, &root, &parent, &children, &children_count );
01531 if( children != NULL )
01532 XFree( children );
01533 if( window == root )
01534 break;
01535 window = parent;
01536 }
01537 if( client != NULL )
01538 client->killWindow();
01539 else
01540 XKillClient( qt_xdisplay(), window_to_kill );
01541 }
01542
01543
01544 void Workspace::sendPingToWindow( Window window, Time timestamp )
01545 {
01546 rootInfo->sendPing( window, timestamp );
01547 }
01548
01549 void Workspace::sendTakeActivity( Client* c, Time timestamp, long flags )
01550 {
01551 rootInfo->takeActivity( c->window(), timestamp, flags );
01552 pending_take_activity = c;
01553 }
01554
01555
01559 void Workspace::slotGrabWindow()
01560 {
01561 if ( active_client )
01562 {
01563 QPixmap snapshot = QPixmap::grabWindow( active_client->frameId() );
01564
01565
01566 if( Shape::available())
01567 {
01568
01569 int count, order;
01570 XRectangle* rects = XShapeGetRectangles( qt_xdisplay(), active_client->frameId(),
01571 ShapeBounding, &count, &order);
01572
01573
01574
01575
01576 if (rects)
01577 {
01578
01579 QRegion contents;
01580 for (int pos = 0; pos < count; pos++)
01581 contents += QRegion(rects[pos].x, rects[pos].y,
01582 rects[pos].width, rects[pos].height);
01583 XFree(rects);
01584
01585
01586 QRegion bbox(0, 0, snapshot.width(), snapshot.height());
01587
01588
01589 QRegion maskedAway = bbox - contents;
01590 QMemArray<QRect> maskedAwayRects = maskedAway.rects();
01591
01592
01593 QBitmap mask( snapshot.width(), snapshot.height());
01594 QPainter p(&mask);
01595 p.fillRect(0, 0, mask.width(), mask.height(), Qt::color1);
01596 for (uint pos = 0; pos < maskedAwayRects.count(); pos++)
01597 p.fillRect(maskedAwayRects[pos], Qt::color0);
01598 p.end();
01599 snapshot.setMask(mask);
01600 }
01601 }
01602
01603 QClipboard *cb = QApplication::clipboard();
01604 cb->setPixmap( snapshot );
01605 }
01606 else
01607 slotGrabDesktop();
01608 }
01609
01613 void Workspace::slotGrabDesktop()
01614 {
01615 QPixmap p = QPixmap::grabWindow( qt_xrootwin() );
01616 QClipboard *cb = QApplication::clipboard();
01617 cb->setPixmap( p );
01618 }
01619
01620
01624 void Workspace::slotMouseEmulation()
01625 {
01626
01627 if ( mouse_emulation )
01628 {
01629 XUngrabKeyboard(qt_xdisplay(), qt_x_time);
01630 mouse_emulation = FALSE;
01631 return;
01632 }
01633
01634 if ( XGrabKeyboard(qt_xdisplay(),
01635 root, FALSE,
01636 GrabModeAsync, GrabModeAsync,
01637 qt_x_time) == GrabSuccess )
01638 {
01639 mouse_emulation = TRUE;
01640 mouse_emulation_state = 0;
01641 mouse_emulation_window = 0;
01642 }
01643 }
01644
01651 WId Workspace::getMouseEmulationWindow()
01652 {
01653 Window root;
01654 Window child = qt_xrootwin();
01655 int root_x, root_y, lx, ly;
01656 uint state;
01657 Window w;
01658 Client * c = 0;
01659 do
01660 {
01661 w = child;
01662 if (!c)
01663 c = findClient( FrameIdMatchPredicate( w ));
01664 XQueryPointer( qt_xdisplay(), w, &root, &child,
01665 &root_x, &root_y, &lx, &ly, &state );
01666 } while ( child != None && child != w );
01667
01668 if ( c && !c->isActive() )
01669 activateClient( c );
01670 return (WId) w;
01671 }
01672
01676 unsigned int Workspace::sendFakedMouseEvent( QPoint pos, WId w, MouseEmulation type, int button, unsigned int state )
01677 {
01678 if ( !w )
01679 return state;
01680 QWidget* widget = QWidget::find( w );
01681 if ( (!widget || widget->inherits("QToolButton") ) && !findClient( WindowMatchPredicate( w )) )
01682 {
01683 int x, y;
01684 Window xw;
01685 XTranslateCoordinates( qt_xdisplay(), qt_xrootwin(), w, pos.x(), pos.y(), &x, &y, &xw );
01686 if ( type == EmuMove )
01687 {
01688 XMotionEvent e;
01689 e.type = MotionNotify;
01690 e.window = w;
01691 e.root = qt_xrootwin();
01692 e.subwindow = w;
01693 e.time = qt_x_time;
01694 e.x = x;
01695 e.y = y;
01696 e.x_root = pos.x();
01697 e.y_root = pos.y();
01698 e.state = state;
01699 e.is_hint = NotifyNormal;
01700 XSendEvent( qt_xdisplay(), w, TRUE, ButtonMotionMask, (XEvent*)&e );
01701 }
01702 else
01703 {
01704 XButtonEvent e;
01705 e.type = type == EmuRelease ? ButtonRelease : ButtonPress;
01706 e.window = w;
01707 e.root = qt_xrootwin();
01708 e.subwindow = w;
01709 e.time = qt_x_time;
01710 e.x = x;
01711 e.y = y;
01712 e.x_root = pos.x();
01713 e.y_root = pos.y();
01714 e.state = state;
01715 e.button = button;
01716 XSendEvent( qt_xdisplay(), w, TRUE, ButtonPressMask, (XEvent*)&e );
01717
01718 if ( type == EmuPress )
01719 {
01720 switch ( button )
01721 {
01722 case 2:
01723 state |= Button2Mask;
01724 break;
01725 case 3:
01726 state |= Button3Mask;
01727 break;
01728 default:
01729 state |= Button1Mask;
01730 break;
01731 }
01732 }
01733 else
01734 {
01735 switch ( button )
01736 {
01737 case 2:
01738 state &= ~Button2Mask;
01739 break;
01740 case 3:
01741 state &= ~Button3Mask;
01742 break;
01743 default:
01744 state &= ~Button1Mask;
01745 break;
01746 }
01747 }
01748 }
01749 }
01750 return state;
01751 }
01752
01756 bool Workspace::keyPressMouseEmulation( XKeyEvent& ev )
01757 {
01758 if ( root != qt_xrootwin() )
01759 return FALSE;
01760 int kc = XKeycodeToKeysym(qt_xdisplay(), ev.keycode, 0);
01761 int km = ev.state & (ControlMask | Mod1Mask | ShiftMask);
01762
01763 bool is_control = km & ControlMask;
01764 bool is_alt = km & Mod1Mask;
01765 bool is_shift = km & ShiftMask;
01766 int delta = is_control?1:is_alt?32:8;
01767 QPoint pos = QCursor::pos();
01768
01769 switch ( kc )
01770 {
01771 case XK_Left:
01772 case XK_KP_Left:
01773 pos.rx() -= delta;
01774 break;
01775 case XK_Right:
01776 case XK_KP_Right:
01777 pos.rx() += delta;
01778 break;
01779 case XK_Up:
01780 case XK_KP_Up:
01781 pos.ry() -= delta;
01782 break;
01783 case XK_Down:
01784 case XK_KP_Down:
01785 pos.ry() += delta;
01786 break;
01787 case XK_F1:
01788 if ( !mouse_emulation_state )
01789 mouse_emulation_window = getMouseEmulationWindow();
01790 if ( (mouse_emulation_state & Button1Mask) == 0 )
01791 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button1, mouse_emulation_state );
01792 if ( !is_shift )
01793 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
01794 break;
01795 case XK_F2:
01796 if ( !mouse_emulation_state )
01797 mouse_emulation_window = getMouseEmulationWindow();
01798 if ( (mouse_emulation_state & Button2Mask) == 0 )
01799 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button2, mouse_emulation_state );
01800 if ( !is_shift )
01801 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button2, mouse_emulation_state );
01802 break;
01803 case XK_F3:
01804 if ( !mouse_emulation_state )
01805 mouse_emulation_window = getMouseEmulationWindow();
01806 if ( (mouse_emulation_state & Button3Mask) == 0 )
01807 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button3, mouse_emulation_state );
01808 if ( !is_shift )
01809 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button3, mouse_emulation_state );
01810 break;
01811 case XK_Return:
01812 case XK_space:
01813 case XK_KP_Enter:
01814 case XK_KP_Space:
01815 {
01816 if ( !mouse_emulation_state )
01817 {
01818
01819 mouse_emulation_window = getMouseEmulationWindow();
01820 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button1, mouse_emulation_state );
01821 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
01822 }
01823 else
01824 {
01825 if ( mouse_emulation_state & Button1Mask )
01826 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
01827 if ( mouse_emulation_state & Button2Mask )
01828 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button2, mouse_emulation_state );
01829 if ( mouse_emulation_state & Button3Mask )
01830 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button3, mouse_emulation_state );
01831 }
01832 }
01833
01834 case XK_Escape:
01835 XUngrabKeyboard(qt_xdisplay(), qt_x_time);
01836 mouse_emulation = FALSE;
01837 return TRUE;
01838 default:
01839 return FALSE;
01840 }
01841
01842 QCursor::setPos( pos );
01843 if ( mouse_emulation_state )
01844 mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuMove, 0, mouse_emulation_state );
01845 return TRUE;
01846
01847 }
01848
01854 QWidget* Workspace::desktopWidget()
01855 {
01856 return desktop_widget;
01857 }
01858
01859
01860 void Workspace::delayFocus()
01861 {
01862 requestFocus( delayfocus_client );
01863 cancelDelayFocus();
01864 }
01865
01866 void Workspace::requestDelayFocus( Client* c )
01867 {
01868 delayfocus_client = c;
01869 delete delayFocusTimer;
01870 delayFocusTimer = new QTimer( this );
01871 connect( delayFocusTimer, SIGNAL( timeout() ), this, SLOT( delayFocus() ) );
01872 delayFocusTimer->start( options->delayFocusInterval, TRUE );
01873 }
01874
01875 void Workspace::cancelDelayFocus()
01876 {
01877 delete delayFocusTimer;
01878 delayFocusTimer = 0;
01879 }
01880
01881
01882
01883
01884
01885
01886
01887
01888 void Workspace::checkElectricBorders( bool force )
01889 {
01890 if( force )
01891 destroyBorderWindows();
01892
01893 electric_current_border = 0;
01894
01895 QRect r = QApplication::desktop()->geometry();
01896 electricTop = r.top();
01897 electricBottom = r.bottom();
01898 electricLeft = r.left();
01899 electricRight = r.right();
01900
01901 if (options->electricBorders() == Options::ElectricAlways)
01902 createBorderWindows();
01903 else
01904 destroyBorderWindows();
01905 }
01906
01907 void Workspace::createBorderWindows()
01908 {
01909 if ( electric_have_borders )
01910 return;
01911
01912 electric_have_borders = true;
01913
01914 QRect r = QApplication::desktop()->geometry();
01915 XSetWindowAttributes attributes;
01916 unsigned long valuemask;
01917 attributes.override_redirect = True;
01918 attributes.event_mask = (EnterWindowMask | LeaveWindowMask |
01919 VisibilityChangeMask);
01920 valuemask= (CWOverrideRedirect | CWEventMask | CWCursor );
01921 attributes.cursor = XCreateFontCursor(qt_xdisplay(),
01922 XC_sb_up_arrow);
01923 electric_top_border = XCreateWindow (qt_xdisplay(), qt_xrootwin(),
01924 0,0,
01925 r.width(),1,
01926 0,
01927 CopyFromParent, InputOnly,
01928 CopyFromParent,
01929 valuemask, &attributes);
01930 XMapWindow(qt_xdisplay(), electric_top_border);
01931
01932 attributes.cursor = XCreateFontCursor(qt_xdisplay(),
01933 XC_sb_down_arrow);
01934 electric_bottom_border = XCreateWindow (qt_xdisplay(), qt_xrootwin(),
01935 0,r.height()-1,
01936 r.width(),1,
01937 0,
01938 CopyFromParent, InputOnly,
01939 CopyFromParent,
01940 valuemask, &attributes);
01941 XMapWindow(qt_xdisplay(), electric_bottom_border);
01942
01943 attributes.cursor = XCreateFontCursor(qt_xdisplay(),
01944 XC_sb_left_arrow);
01945 electric_left_border = XCreateWindow (qt_xdisplay(), qt_xrootwin(),
01946 0,0,
01947 1,r.height(),
01948 0,
01949 CopyFromParent, InputOnly,
01950 CopyFromParent,
01951 valuemask, &attributes);
01952 XMapWindow(qt_xdisplay(), electric_left_border);
01953
01954 attributes.cursor = XCreateFontCursor(qt_xdisplay(),
01955 XC_sb_right_arrow);
01956 electric_right_border = XCreateWindow (qt_xdisplay(), qt_xrootwin(),
01957 r.width()-1,0,
01958 1,r.height(),
01959 0,
01960 CopyFromParent, InputOnly,
01961 CopyFromParent,
01962 valuemask, &attributes);
01963 XMapWindow(qt_xdisplay(), electric_right_border);
01964
01965 Atom version = 4;
01966 XChangeProperty( qt_xdisplay(), electric_top_border, atoms->xdnd_aware, XA_ATOM,
01967 32, PropModeReplace, ( unsigned char* )&version, 1 );
01968 XChangeProperty( qt_xdisplay(), electric_bottom_border, atoms->xdnd_aware, XA_ATOM,
01969 32, PropModeReplace, ( unsigned char* )&version, 1 );
01970 XChangeProperty( qt_xdisplay(), electric_left_border, atoms->xdnd_aware, XA_ATOM,
01971 32, PropModeReplace, ( unsigned char* )&version, 1 );
01972 XChangeProperty( qt_xdisplay(), electric_right_border, atoms->xdnd_aware, XA_ATOM,
01973 32, PropModeReplace, ( unsigned char* )&version, 1 );
01974 }
01975
01976
01977
01978
01979
01980
01981
01982 void Workspace::destroyBorderWindows()
01983 {
01984 if( !electric_have_borders)
01985 return;
01986
01987 electric_have_borders = false;
01988
01989 if(electric_top_border)
01990 XDestroyWindow(qt_xdisplay(),electric_top_border);
01991 if(electric_bottom_border)
01992 XDestroyWindow(qt_xdisplay(),electric_bottom_border);
01993 if(electric_left_border)
01994 XDestroyWindow(qt_xdisplay(),electric_left_border);
01995 if(electric_right_border)
01996 XDestroyWindow(qt_xdisplay(),electric_right_border);
01997
01998 electric_top_border = None;
01999 electric_bottom_border = None;
02000 electric_left_border = None;
02001 electric_right_border = None;
02002 }
02003
02004 void Workspace::clientMoved(const QPoint &pos, Time now)
02005 {
02006 if (options->electricBorders() == Options::ElectricDisabled)
02007 return;
02008
02009 if ((pos.x() != electricLeft) &&
02010 (pos.x() != electricRight) &&
02011 (pos.y() != electricTop) &&
02012 (pos.y() != electricBottom))
02013 return;
02014
02015 Time treshold_set = options->electricBorderDelay();
02016 Time treshold_reset = 250;
02017 int distance_reset = 30;
02018
02019 int border = 0;
02020 if (pos.x() == electricLeft)
02021 border = 1;
02022 else if (pos.x() == electricRight)
02023 border = 2;
02024 else if (pos.y() == electricTop)
02025 border = 3;
02026 else if (pos.y() == electricBottom)
02027 border = 4;
02028
02029 if ((electric_current_border == border) &&
02030 (timestampDiff(electric_time_last, now) < treshold_reset) &&
02031 ((pos-electric_push_point).manhattanLength() < distance_reset))
02032 {
02033 electric_time_last = now;
02034
02035 if (timestampDiff(electric_time_first, now) > treshold_set)
02036 {
02037 electric_current_border = 0;
02038
02039 QRect r = QApplication::desktop()->geometry();
02040 int offset;
02041
02042 int desk_before = currentDesktop();
02043 switch(border)
02044 {
02045 case 1:
02046 slotSwitchDesktopLeft();
02047 if (currentDesktop() != desk_before)
02048 {
02049 offset = r.width() / 5;
02050 QCursor::setPos(r.width() - offset, pos.y());
02051 }
02052 break;
02053
02054 case 2:
02055 slotSwitchDesktopRight();
02056 if (currentDesktop() != desk_before)
02057 {
02058 offset = r.width() / 5;
02059 QCursor::setPos(offset, pos.y());
02060 }
02061 break;
02062
02063 case 3:
02064 slotSwitchDesktopUp();
02065 if (currentDesktop() != desk_before)
02066 {
02067 offset = r.height() / 5;
02068 QCursor::setPos(pos.x(), r.height() - offset);
02069 }
02070 break;
02071
02072 case 4:
02073 slotSwitchDesktopDown();
02074 if (currentDesktop() != desk_before)
02075 {
02076 offset = r.height() / 5;
02077 QCursor::setPos(pos.x(), offset);
02078 }
02079 break;
02080 }
02081 return;
02082 }
02083 }
02084 else
02085 {
02086 electric_current_border = border;
02087 electric_time_first = now;
02088 electric_time_last = now;
02089 electric_push_point = pos;
02090 }
02091
02092 int mouse_warp = 1;
02093
02094
02095 switch( border)
02096 {
02097 case 1: QCursor::setPos(pos.x()+mouse_warp, pos.y()); break;
02098 case 2: QCursor::setPos(pos.x()-mouse_warp, pos.y()); break;
02099 case 3: QCursor::setPos(pos.x(), pos.y()+mouse_warp); break;
02100 case 4: QCursor::setPos(pos.x(), pos.y()-mouse_warp); break;
02101 }
02102 }
02103
02104
02105
02106 bool Workspace::electricBorder(XEvent *e)
02107 {
02108 if( !electric_have_borders )
02109 return false;
02110 if( e->type == EnterNotify )
02111 {
02112 if( e->xcrossing.window == electric_top_border ||
02113 e->xcrossing.window == electric_left_border ||
02114 e->xcrossing.window == electric_bottom_border ||
02115 e->xcrossing.window == electric_right_border)
02116
02117 {
02118 clientMoved( QPoint( e->xcrossing.x_root, e->xcrossing.y_root ), e->xcrossing.time );
02119 return true;
02120 }
02121 }
02122 if( e->type == ClientMessage )
02123 {
02124 if( e->xclient.message_type == atoms->xdnd_position
02125 && ( e->xclient.window == electric_top_border
02126 || e->xclient.window == electric_bottom_border
02127 || e->xclient.window == electric_left_border
02128 || e->xclient.window == electric_right_border ))
02129 {
02130 updateXTime();
02131 clientMoved( QPoint( e->xclient.data.l[2]>>16, e->xclient.data.l[2]&0xffff), qt_x_time );
02132 return true;
02133 }
02134 }
02135 return false;
02136 }
02137
02138
02139
02140
02141 void Workspace::raiseElectricBorders()
02142 {
02143
02144 if(electric_have_borders)
02145 {
02146 XRaiseWindow(qt_xdisplay(), electric_top_border);
02147 XRaiseWindow(qt_xdisplay(), electric_left_border);
02148 XRaiseWindow(qt_xdisplay(), electric_bottom_border);
02149 XRaiseWindow(qt_xdisplay(), electric_right_border);
02150 }
02151 }
02152
02153 void Workspace::addTopMenu( Client* c )
02154 {
02155 assert( c->isTopMenu());
02156 assert( !topmenus.contains( c ));
02157 topmenus.append( c );
02158 if( managingTopMenus())
02159 {
02160 int minsize = c->minSize().height();
02161 if( minsize > topMenuHeight())
02162 {
02163 topmenu_height = minsize;
02164 updateTopMenuGeometry();
02165 }
02166 updateTopMenuGeometry( c );
02167 updateCurrentTopMenu();
02168 }
02169
02170 }
02171
02172 void Workspace::removeTopMenu( Client* c )
02173 {
02174
02175
02176 assert( c->isTopMenu());
02177 assert( topmenus.contains( c ));
02178 topmenus.remove( c );
02179 updateCurrentTopMenu();
02180
02181 }
02182
02183 void Workspace::lostTopMenuSelection()
02184 {
02185
02186
02187 disconnect( topmenu_watcher, SIGNAL( lostOwner()), this, SLOT( lostTopMenuOwner()));
02188 connect( topmenu_watcher, SIGNAL( lostOwner()), this, SLOT( lostTopMenuOwner()));
02189 if( !managing_topmenus )
02190 return;
02191 connect( topmenu_watcher, SIGNAL( lostOwner()), this, SLOT( lostTopMenuOwner()));
02192 disconnect( topmenu_selection, SIGNAL( lostOwnership()), this, SLOT( lostTopMenuSelection()));
02193 managing_topmenus = false;
02194 delete topmenu_space;
02195 topmenu_space = NULL;
02196 updateClientArea();
02197 for( ClientList::ConstIterator it = topmenus.begin();
02198 it != topmenus.end();
02199 ++it )
02200 (*it)->checkWorkspacePosition();
02201 }
02202
02203 void Workspace::lostTopMenuOwner()
02204 {
02205 if( !options->topMenuEnabled())
02206 return;
02207
02208 if( !topmenu_selection->claim( false ))
02209 {
02210
02211 return;
02212 }
02213
02214 setupTopMenuHandling();
02215 }
02216
02217 void Workspace::setupTopMenuHandling()
02218 {
02219 if( managing_topmenus )
02220 return;
02221 connect( topmenu_selection, SIGNAL( lostOwnership()), this, SLOT( lostTopMenuSelection()));
02222 disconnect( topmenu_watcher, SIGNAL( lostOwner()), this, SLOT( lostTopMenuOwner()));
02223 managing_topmenus = true;
02224 topmenu_space = new QWidget;
02225 Window stack[ 2 ];
02226 stack[ 0 ] = supportWindow->winId();
02227 stack[ 1 ] = topmenu_space->winId();
02228 XRestackWindows(qt_xdisplay(), stack, 2);
02229 updateTopMenuGeometry();
02230 topmenu_space->show();
02231 updateClientArea();
02232 updateCurrentTopMenu();
02233 }
02234
02235 int Workspace::topMenuHeight() const
02236 {
02237 if( topmenu_height == 0 )
02238 {
02239 KMenuBar tmpmenu;
02240 tmpmenu.insertItem( "dummy" );
02241 topmenu_height = tmpmenu.sizeHint().height();
02242 }
02243 return topmenu_height;
02244 }
02245
02246 KDecoration* Workspace::createDecoration( KDecorationBridge* bridge )
02247 {
02248 return mgr->createDecoration( bridge );
02249 }
02250
02251 QString Workspace::desktopName( int desk ) const
02252 {
02253 return QString::fromUtf8( rootInfo->desktopName( desk ) );
02254 }
02255
02256 bool Workspace::checkStartupNotification( Window w, KStartupInfoId& id, KStartupInfoData& data )
02257 {
02258 return startup->checkStartup( w, id, data ) == KStartupInfo::Match;
02259 }
02260
02265 void Workspace::focusToNull()
02266 {
02267 XSetInputFocus(qt_xdisplay(), null_focus_window, RevertToPointerRoot, qt_x_time );
02268 }
02269
02270 void Workspace::helperDialog( const QString& message, const Client* c )
02271 {
02272 QStringList args;
02273 QString type;
02274 if( message == "noborderaltf3" )
02275 {
02276 QString shortcut = QString( "%1 (%2)" ).arg( keys->label( "Window Operations Menu" ))
02277 .arg( keys->shortcut( "Window Operations Menu" ).seq( 0 ).toString());
02278 args << "--msgbox" <<
02279 i18n( "You have selected to show a window without its border.\n"
02280 "Without the border, you will not be able to enable the border "
02281 "again using the mouse: use the window operations menu instead, "
02282 "activated using the %1 keyboard shortcut." )
02283 .arg( shortcut );
02284 type = "altf3warning";
02285 }
02286 else if( message == "fullscreenaltf3" )
02287 {
02288 QString shortcut = QString( "%1 (%2)" ).arg( keys->label( "Window Operations Menu" ))
02289 .arg( keys->shortcut( "Window Operations Menu" ).seq( 0 ).toString());
02290 args << "--msgbox" <<
02291 i18n( "You have selected to show a window in fullscreen mode.\n"
02292 "If the application itself does not have an option to turn the fullscreen "
02293 "mode off you will not be able to disable it "
02294 "again using the mouse: use the window operations menu instead, "
02295 "activated using the %1 keyboard shortcut." )
02296 .arg( shortcut );
02297 type = "altf3warning";
02298 }
02299 else
02300 assert( false );
02301 KProcess proc;
02302 proc << "kdialog" << args;
02303 if( !type.isEmpty())
02304 {
02305 KConfig cfg( "kwin_dialogsrc" );
02306 cfg.setGroup( "Notification Messages" );
02307 if( !cfg.readBoolEntry( type, true ))
02308 return;
02309 proc << "--dontagain" << "kwin_dialogsrc:" + type;
02310 }
02311 if( c != NULL )
02312 proc << "--embed" << QString::number( c->window());
02313 proc.start( KProcess::DontCare );
02314 }
02315
02316
02317
02318
02319 void Workspace::startKompmgr()
02320 {
02321 if (!kompmgr || kompmgr->isRunning())
02322 return;
02323 if (!kompmgr->start(KProcess::OwnGroup, KProcess::Stderr))
02324 {
02325 options->useTranslucency = FALSE;
02326 KProcess proc;
02327 proc << "kdialog" << "--error"
02328 << i18n("The Composite Manager could not be started.\\nMake sure you have \"kompmgr\" in a $PATH directory.")
02329 << "--title" << "Composite Manager Failure";
02330 proc.start(KProcess::DontCare);
02331 }
02332 else
02333 {
02334 connect(kompmgr, SIGNAL(processExited(KProcess*)), SLOT(restartKompmgr()));
02335 options->useTranslucency = TRUE;
02336 allowKompmgrRestart = FALSE;
02337 QTimer::singleShot( 60000, this, SLOT(unblockKompmgrRestart()) );
02338 QByteArray ba;
02339 QDataStream arg(ba, IO_WriteOnly);
02340 arg << "";
02341 kapp->dcopClient()->emitDCOPSignal("default", "kompmgrStarted()", ba);
02342 }
02343 if (popup){ delete popup; popup = 0L; }
02344 }
02345
02346 void Workspace::stopKompmgr()
02347 {
02348 if (!kompmgr || !kompmgr->isRunning())
02349 return;
02350 kompmgr->disconnect(this, SLOT(restartKompmgr()));
02351 options->useTranslucency = FALSE;
02352 if (popup){ delete popup; popup = 0L; }
02353 kompmgr->kill();
02354 QByteArray ba;
02355 QDataStream arg(ba, IO_WriteOnly);
02356 arg << "";
02357 kapp->dcopClient()->emitDCOPSignal("default", "kompmgrStopped()", ba);
02358 }
02359
02360 bool Workspace::kompmgrIsRunning()
02361 {
02362 return kompmgr && kompmgr->isRunning();
02363 }
02364
02365 void Workspace::unblockKompmgrRestart()
02366 {
02367 allowKompmgrRestart = TRUE;
02368 }
02369
02370 void Workspace::restartKompmgr()
02371
02372 {
02373 if (!allowKompmgrRestart)
02374 {
02375 options->useTranslucency = FALSE;
02376 KProcess proc;
02377 proc << "kdialog" << "--error"
02378 << i18n( "The Composite Manager crashed twice within a minute and is therefore disabled for this session.")
02379 << "--title" << i18n("Composite Manager Failure");
02380 proc.start(KProcess::DontCare);
02381 return;
02382 }
02383 if (!kompmgr)
02384 return;
02385
02386
02387
02388
02389
02390
02391
02392
02393 if (!kompmgr->start(KProcess::NotifyOnExit, KProcess::Stderr))
02394 {
02395 options->useTranslucency = FALSE;
02396 KProcess proc;
02397 proc << "kdialog" << "--error"
02398 << i18n("The Composite Manager could not be started.\\nMake sure you have \"kompmgr\" in a $PATH directory.")
02399 << "--title" << i18n("Composite Manager Failure");
02400 proc.start(KProcess::DontCare);
02401 }
02402 else
02403 {
02404 allowKompmgrRestart = FALSE;
02405 QTimer::singleShot( 60000, this, SLOT(unblockKompmgrRestart()) );
02406 }
02407 }
02408
02409 void Workspace::handleKompmgrOutput( KProcess* , char *buffer, int buflen)
02410 {
02411 QString message;
02412 QString output = QString::fromLocal8Bit( buffer, buflen );
02413 if (output.contains("Started",false))
02414 ;
02415 else if (output.contains("Can't open display",false))
02416 message = i18n("<qt><b>kompmgr failed to open the display</b><br>There is probably an invalid display entry in your ~/.xcompmgrrc.</qt>");
02417 else if (output.contains("No render extension",false))
02418 message = i18n("<qt><b>kompmgr cannot find the Xrender extension</b><br>You are using either an outdated or a crippled version of XOrg.<br>Get XOrg ≥ 6.8 from www.freedesktop.org.<br></qt>");
02419 else if (output.contains("No composite extension",false))
02420 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>"
02421 "<i>Section \"Extensions\"<br>"
02422 "Option \"Composite\" \"Enable\"<br>"
02423 "EndSection</i></qt>");
02424 else if (output.contains("No damage extension",false))
02425 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>");
02426 else if (output.contains("No XFixes extension",false))
02427 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>");
02428 else return;
02429
02430 kompmgr->closeStderr();
02431 disconnect(kompmgr, SIGNAL(receivedStderr(KProcess*, char*, int)), this, SLOT(handleKompmgrOutput(KProcess*, char*, int)));
02432 if( !message.isEmpty())
02433 {
02434 KProcess proc;
02435 proc << "kdialog" << "--error"
02436 << message
02437 << "--title" << i18n("Composite Manager Failure");
02438 proc.start(KProcess::DontCare);
02439 }
02440 }
02441
02442
02443 void Workspace::setOpacity(unsigned long winId, unsigned int opacityPercent)
02444 {
02445 if (opacityPercent > 100) opacityPercent = 100;
02446 for( ClientList::ConstIterator it = stackingOrder().begin(); it != stackingOrder().end(); it++ )
02447 if (winId == (*it)->window())
02448 {
02449 (*it)->setOpacity(opacityPercent < 100, (unsigned int)((opacityPercent/100.0)*0xFFFFFFFF));
02450 return;
02451 }
02452 }
02453
02454 void Workspace::setShadowSize(unsigned long winId, unsigned int shadowSizePercent)
02455 {
02456
02457 if (shadowSizePercent > 400) shadowSizePercent = 400;
02458 for( ClientList::ConstIterator it = stackingOrder().begin(); it != stackingOrder().end(); it++ )
02459 if (winId == (*it)->window())
02460 {
02461 (*it)->setShadowSize(shadowSizePercent);
02462 return;
02463 }
02464 }
02465
02466 void Workspace::setUnshadowed(unsigned long winId)
02467 {
02468 for( ClientList::ConstIterator it = stackingOrder().begin(); it != stackingOrder().end(); it++ )
02469 if (winId == (*it)->window())
02470 {
02471 (*it)->setShadowSize(0);
02472 return;
02473 }
02474 }
02475
02476 }
02477
02478 #include "workspace.moc"