00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "client.h"
00019 #include "workspace.h"
00020 #include "atoms.h"
00021 #include "tabbox.h"
00022 #include "group.h"
00023 #include "rules.h"
00024
00025 #include <qwhatsthis.h>
00026 #include <kkeynative.h>
00027 #include <qapplication.h>
00028
00029 #include <X11/extensions/shape.h>
00030 #include <X11/Xatom.h>
00031
00032 extern Time qt_x_time;
00033 extern Atom qt_window_role;
00034
00035 namespace KWinInternal
00036 {
00037
00038
00039
00040
00041
00042 WinInfo::WinInfo( Client * c, Display * display, Window window,
00043 Window rwin, const unsigned long pr[], int pr_size )
00044 : NETWinInfo( display, window, rwin, pr, pr_size, NET::WindowManager ), m_client( c )
00045 {
00046 }
00047
00048 void WinInfo::changeDesktop(int desktop)
00049 {
00050 m_client->workspace()->sendClientToDesktop( m_client, desktop, true );
00051 }
00052
00053 void WinInfo::changeState( unsigned long state, unsigned long mask )
00054 {
00055 mask &= ~NET::Sticky;
00056 mask &= ~NET::Hidden;
00057 state &= mask;
00058
00059 if(( mask & NET::FullScreen ) != 0 && ( state & NET::FullScreen ) == 0 )
00060 m_client->setFullScreen( false, false );
00061 if ( (mask & NET::Max) == NET::Max )
00062 m_client->setMaximize( state & NET::MaxVert, state & NET::MaxHoriz );
00063 else if ( mask & NET::MaxVert )
00064 m_client->setMaximize( state & NET::MaxVert, m_client->maximizeMode() & Client::MaximizeHorizontal );
00065 else if ( mask & NET::MaxHoriz )
00066 m_client->setMaximize( m_client->maximizeMode() & Client::MaximizeVertical, state & NET::MaxHoriz );
00067
00068 if ( mask & NET::Shaded )
00069 m_client->setShade( state & NET::Shaded ? ShadeNormal : ShadeNone );
00070 if ( mask & NET::KeepAbove)
00071 m_client->setKeepAbove( (state & NET::KeepAbove) != 0 );
00072 if ( mask & NET::KeepBelow)
00073 m_client->setKeepBelow( (state & NET::KeepBelow) != 0 );
00074 if( mask & NET::SkipTaskbar )
00075 m_client->setSkipTaskbar( ( state & NET::SkipTaskbar ) != 0, true );
00076 if( mask & NET::SkipPager )
00077 m_client->setSkipPager( ( state & NET::SkipPager ) != 0 );
00078 if( mask & NET::DemandsAttention )
00079 m_client->demandAttention(( state & NET::DemandsAttention ) != 0 );
00080 if( mask & NET::Modal )
00081 m_client->setModal( ( state & NET::Modal ) != 0 );
00082
00083 if(( mask & NET::FullScreen ) != 0 && ( state & NET::FullScreen ) != 0 )
00084 m_client->setFullScreen( true, false );
00085 }
00086
00087
00088
00089
00090
00091
00092 RootInfo::RootInfo( Workspace* ws, Display *dpy, Window w, const char *name, unsigned long pr[], int pr_num, int scr )
00093 : NETRootInfo3( dpy, w, name, pr, pr_num, scr )
00094 {
00095 workspace = ws;
00096 }
00097
00098 void RootInfo::changeNumberOfDesktops(int n)
00099 {
00100 workspace->setNumberOfDesktops( n );
00101 }
00102
00103 void RootInfo::changeCurrentDesktop(int d)
00104 {
00105 workspace->setCurrentDesktop( d );
00106 }
00107
00108 void RootInfo::changeActiveWindow( Window w, NET::RequestSource src, Time timestamp, Window active_window )
00109 {
00110 if( Client* c = workspace->findClient( WindowMatchPredicate( w )))
00111 {
00112 if( timestamp == CurrentTime )
00113 timestamp = c->userTime();
00114 if( src != NET::FromApplication && src != FromTool )
00115 src = NET::FromTool;
00116 if( src == NET::FromTool )
00117 workspace->activateClient( c, true );
00118 else
00119 {
00120 Client* c2;
00121 if( workspace->allowClientActivation( c, timestamp ))
00122 workspace->activateClient( c );
00123
00124 else if( active_window != None
00125 && ( c2 = workspace->findClient( WindowMatchPredicate( active_window ))) != NULL
00126 && workspace->allowClientActivation( c2,
00127 timestampCompare( timestamp, c2->userTime() > 0 ? timestamp : c2->userTime())))
00128 workspace->activateClient( c );
00129 else
00130 c->demandAttention();
00131 }
00132 }
00133 }
00134
00135 void RootInfo::restackWindow( Window w, RequestSource src, Window above, int detail, Time timestamp )
00136 {
00137 if( Client* c = workspace->findClient( WindowMatchPredicate( w )))
00138 {
00139 if( timestamp == CurrentTime )
00140 timestamp = c->userTime();
00141 if( src != NET::FromApplication && src != FromTool )
00142 src = NET::FromTool;
00143 c->restackWindow( above, detail, src, timestamp, true );
00144 }
00145 }
00146
00147 void RootInfo::gotTakeActivity( Window w, Time timestamp, long flags )
00148 {
00149 if( Client* c = workspace->findClient( WindowMatchPredicate( w )))
00150 workspace->handleTakeActivity( c, timestamp, flags );
00151 }
00152
00153 void RootInfo::closeWindow(Window w)
00154 {
00155 Client* c = workspace->findClient( WindowMatchPredicate( w ));
00156 if ( c )
00157 c->closeWindow();
00158 }
00159
00160 void RootInfo::moveResize(Window w, int x_root, int y_root, unsigned long direction)
00161 {
00162 Client* c = workspace->findClient( WindowMatchPredicate( w ));
00163 if ( c )
00164 {
00165 updateXTime();
00166 c->NETMoveResize( x_root, y_root, (Direction)direction);
00167 }
00168 }
00169
00170 void RootInfo::moveResizeWindow(Window w, int flags, int x, int y, int width, int height )
00171 {
00172 Client* c = workspace->findClient( WindowMatchPredicate( w ));
00173 if ( c )
00174 c->NETMoveResizeWindow( flags, x, y, width, height );
00175 }
00176
00177 void RootInfo::gotPing( Window w, Time timestamp )
00178 {
00179 if( Client* c = workspace->findClient( WindowMatchPredicate( w )))
00180 c->gotPing( timestamp );
00181 }
00182
00183
00184
00185
00186
00190 bool Workspace::workspaceEvent( XEvent * e )
00191 {
00192 if ( mouse_emulation && (e->type == ButtonPress || e->type == ButtonRelease ) )
00193 {
00194 mouse_emulation = FALSE;
00195 XUngrabKeyboard( qt_xdisplay(), qt_x_time );
00196 }
00197
00198 if ( e->type == PropertyNotify || e->type == ClientMessage )
00199 {
00200 if ( netCheck( e ) )
00201 return TRUE;
00202 }
00203
00204
00205 switch (e->type)
00206 {
00207 case ButtonPress:
00208 case ButtonRelease:
00209 was_user_interaction = true;
00210
00211 case MotionNotify:
00212 if ( tab_grab || control_grab )
00213 {
00214 tab_box->handleMouseEvent( e );
00215 return TRUE;
00216 }
00217 break;
00218 case KeyPress:
00219 {
00220 was_user_interaction = true;
00221 KKeyNative keyX( (XEvent*)e );
00222 uint keyQt = keyX.keyCodeQt();
00223 kdDebug(125) << "Workspace::keyPress( " << keyX.key().toString() << " )" << endl;
00224 if (movingClient)
00225 {
00226 movingClient->keyPressEvent(keyQt);
00227 return true;
00228 }
00229 if( tab_grab || control_grab )
00230 {
00231 tabBoxKeyPress( keyX );
00232 return true;
00233 }
00234 break;
00235 }
00236 case KeyRelease:
00237 was_user_interaction = true;
00238 if( tab_grab || control_grab )
00239 {
00240 tabBoxKeyRelease( e->xkey );
00241 return true;
00242 }
00243 break;
00244 };
00245
00246 if( Client* c = findClient( WindowMatchPredicate( e->xany.window )))
00247 {
00248 if( c->windowEvent( e ))
00249 return true;
00250 }
00251 else if( Client* c = findClient( WrapperIdMatchPredicate( e->xany.window )))
00252 {
00253 if( c->windowEvent( e ))
00254 return true;
00255 }
00256 else if( Client* c = findClient( FrameIdMatchPredicate( e->xany.window )))
00257 {
00258 if( c->windowEvent( e ))
00259 return true;
00260 }
00261 else
00262 {
00263 Window special = findSpecialEventWindow( e );
00264 if( special != None )
00265 if( Client* c = findClient( WindowMatchPredicate( special )))
00266 {
00267 if( c->windowEvent( e ))
00268 return true;
00269 }
00270 }
00271 if( movingClient != NULL && movingClient->moveResizeGrabWindow() == e->xany.window
00272 && ( e->type == MotionNotify || e->type == ButtonPress || e->type == ButtonRelease ))
00273 {
00274 if( movingClient->windowEvent( e ))
00275 return true;
00276 }
00277
00278 switch (e->type)
00279 {
00280 case CreateNotify:
00281 if ( e->xcreatewindow.parent == root &&
00282 !QWidget::find( e->xcreatewindow.window) &&
00283 !e->xcreatewindow.override_redirect )
00284 {
00285
00286 XChangeProperty(qt_xdisplay(), e->xcreatewindow.window,
00287 atoms->kde_net_wm_user_creation_time, XA_CARDINAL,
00288 32, PropModeReplace, (unsigned char *)&qt_x_time, 1);
00289 }
00290 break;
00291
00292 case UnmapNotify:
00293 {
00294
00295 if ( removeSystemTrayWin( e->xunmap.window, true ) )
00296 {
00297
00298
00299
00300
00301
00302
00303
00304 XEvent ev;
00305 WId w = e->xunmap.window;
00306 if ( XCheckTypedWindowEvent (qt_xdisplay(), w,
00307 ReparentNotify, &ev) )
00308 {
00309 if ( ev.xreparent.parent != root )
00310 {
00311 XReparentWindow( qt_xdisplay(), w, root, 0, 0 );
00312 addSystemTrayWin( w );
00313 }
00314 }
00315 return TRUE;
00316 }
00317
00318 return ( e->xunmap.event != e->xunmap.window );
00319 }
00320 case MapNotify:
00321
00322 return ( e->xmap.event != e->xmap.window );
00323
00324 case ReparentNotify:
00325 {
00326
00327
00328 return TRUE;
00329 }
00330 case DestroyNotify:
00331 {
00332 if ( removeSystemTrayWin( e->xdestroywindow.window, false ) )
00333 return TRUE;
00334 return false;
00335 }
00336 case MapRequest:
00337 {
00338 updateXTime();
00339
00340
00341
00342 Client* c = findClient( WindowMatchPredicate( e->xmaprequest.window ));
00343 if ( !c )
00344 {
00345
00346
00347
00348
00349
00350
00351
00352
00353 if ( addSystemTrayWin( e->xmaprequest.window ) )
00354 return TRUE;
00355 c = createClient( e->xmaprequest.window, false );
00356 if ( c != NULL && root != qt_xrootwin() )
00357 {
00358
00359 XReparentWindow( qt_xdisplay(), c->frameId(), root, 0, 0 );
00360 }
00361 if( c == NULL )
00362 XMapRaised( qt_xdisplay(), e->xmaprequest.window );
00363 return true;
00364 }
00365 if ( c )
00366 {
00367 c->windowEvent( e );
00368 if ( !c->wantsTabFocus())
00369 focus_chain.remove( c );
00370 return true;
00371 }
00372 break;
00373 }
00374 case EnterNotify:
00375 {
00376 if ( QWhatsThis::inWhatsThisMode() )
00377 {
00378 QWidget* w = QWidget::find( e->xcrossing.window );
00379 if ( w )
00380 QWhatsThis::leaveWhatsThisMode();
00381 }
00382 if( electricBorder(e))
00383 return true;
00384 break;
00385 }
00386 case LeaveNotify:
00387 {
00388 if ( !QWhatsThis::inWhatsThisMode() )
00389 break;
00390
00391 Client* c = findClient( FrameIdMatchPredicate( e->xcrossing.window ));
00392 if ( c && e->xcrossing.detail != NotifyInferior )
00393 QWhatsThis::leaveWhatsThisMode();
00394 break;
00395 }
00396 case ConfigureRequest:
00397 {
00398 if ( e->xconfigurerequest.parent == root )
00399 {
00400 XWindowChanges wc;
00401 unsigned int value_mask = 0;
00402 wc.border_width = 0;
00403 wc.x = e->xconfigurerequest.x;
00404 wc.y = e->xconfigurerequest.y;
00405 wc.width = e->xconfigurerequest.width;
00406 wc.height = e->xconfigurerequest.height;
00407 wc.sibling = None;
00408 wc.stack_mode = Above;
00409 value_mask = e->xconfigurerequest.value_mask | CWBorderWidth;
00410 XConfigureWindow( qt_xdisplay(), e->xconfigurerequest.window, value_mask, &wc );
00411 return true;
00412 }
00413 break;
00414 }
00415 case KeyPress:
00416 if ( mouse_emulation )
00417 return keyPressMouseEmulation( e->xkey );
00418 break;
00419 case KeyRelease:
00420 if ( mouse_emulation )
00421 return FALSE;
00422 break;
00423 case FocusIn:
00424 if( e->xfocus.window == rootWin()
00425 && ( e->xfocus.detail == NotifyDetailNone || e->xfocus.detail == NotifyPointerRoot ))
00426 {
00427 updateXTime();
00428 Window focus;
00429 int revert;
00430 XGetInputFocus( qt_xdisplay(), &focus, &revert );
00431 if( focus == None || focus == PointerRoot )
00432 {
00433
00434 Client *c = mostRecentlyActivatedClient();
00435 if( c != NULL )
00436 requestFocus( c, true );
00437 else if( activateNextClient( NULL ))
00438 ;
00439 else
00440 focusToNull();
00441 }
00442 }
00443
00444 case FocusOut:
00445 return true;
00446 case ClientMessage:
00447 if( electricBorder( e ))
00448 return true;
00449 break;
00450 default:
00451 break;
00452 }
00453 return FALSE;
00454 }
00455
00456
00457
00458
00459 Window Workspace::findSpecialEventWindow( XEvent* e )
00460 {
00461 switch( e->type )
00462 {
00463 case CreateNotify:
00464 return e->xcreatewindow.window;
00465 case DestroyNotify:
00466 return e->xdestroywindow.window;
00467 case UnmapNotify:
00468 return e->xunmap.window;
00469 case MapNotify:
00470 return e->xmap.window;
00471 case MapRequest:
00472 return e->xmaprequest.window;
00473 case ReparentNotify:
00474 return e->xreparent.window;
00475 case ConfigureNotify:
00476 return e->xconfigure.window;
00477 case GravityNotify:
00478 return e->xgravity.window;
00479 case ConfigureRequest:
00480 return e->xconfigurerequest.window;
00481 case CirculateNotify:
00482 return e->xcirculate.window;
00483 case CirculateRequest:
00484 return e->xcirculaterequest.window;
00485 default:
00486 return None;
00487 };
00488 }
00489
00493 bool Workspace::netCheck( XEvent* e )
00494 {
00495 unsigned int dirty = rootInfo->event( e );
00496
00497 if ( dirty & NET::DesktopNames )
00498 saveDesktopSettings();
00499
00500 return dirty != 0;
00501 }
00502
00503
00504
00505
00506
00507
00511 bool Client::windowEvent( XEvent* e )
00512 {
00513 if( e->xany.window == window())
00514 {
00515 unsigned long dirty[ 2 ];
00516 info->event( e, dirty, 2 );
00517
00518 if ( ( dirty[ WinInfo::PROTOCOLS ] & NET::WMName ) != 0 )
00519 fetchName();
00520 if ( ( dirty[ WinInfo::PROTOCOLS ] & NET::WMIconName ) != 0 )
00521 fetchIconicName();
00522 if ( ( dirty[ WinInfo::PROTOCOLS ] & NET::WMStrut ) != 0
00523 || ( dirty[ WinInfo::PROTOCOLS2 ] & NET::WM2ExtendedStrut ) != 0 )
00524 {
00525 if( isTopMenu())
00526 checkWorkspacePosition();
00527 workspace()->updateClientArea();
00528 }
00529 if ( ( dirty[ WinInfo::PROTOCOLS ] & NET::WMIcon) != 0 )
00530 getIcons();
00531
00532
00533
00534 if(( dirty[ WinInfo::PROTOCOLS2 ] & NET::WM2UserTime ) != 0 )
00535 {
00536 workspace()->setWasUserInteraction();
00537 updateUserTime( info->userTime());
00538 }
00539 if(( dirty[ WinInfo::PROTOCOLS2 ] & NET::WM2StartupId ) != 0 )
00540 startupIdChanged();
00541 }
00542
00543
00544 switch (e->type)
00545 {
00546 case UnmapNotify:
00547 unmapNotifyEvent( &e->xunmap );
00548 break;
00549 case DestroyNotify:
00550 destroyNotifyEvent( &e->xdestroywindow );
00551 break;
00552 case MapRequest:
00553
00554 return mapRequestEvent( &e->xmaprequest );
00555 case ConfigureRequest:
00556 configureRequestEvent( &e->xconfigurerequest );
00557 break;
00558 case PropertyNotify:
00559 propertyNotifyEvent( &e->xproperty );
00560 break;
00561 case KeyPress:
00562 updateUserTime();
00563 workspace()->setWasUserInteraction();
00564 break;
00565 case ButtonPress:
00566 updateUserTime();
00567 workspace()->setWasUserInteraction();
00568 buttonPressEvent( e->xbutton.window, e->xbutton.button, e->xbutton.state,
00569 e->xbutton.x, e->xbutton.y, e->xbutton.x_root, e->xbutton.y_root );
00570 break;
00571 case KeyRelease:
00572
00573
00574
00575 break;
00576 case ButtonRelease:
00577
00578
00579
00580 buttonReleaseEvent( e->xbutton.window, e->xbutton.button, e->xbutton.state,
00581 e->xbutton.x, e->xbutton.y, e->xbutton.x_root, e->xbutton.y_root );
00582 break;
00583 case MotionNotify:
00584 motionNotifyEvent( e->xmotion.window, e->xmotion.state,
00585 e->xmotion.x, e->xmotion.y, e->xmotion.x_root, e->xmotion.y_root );
00586 break;
00587 case EnterNotify:
00588 enterNotifyEvent( &e->xcrossing );
00589
00590
00591
00592
00593
00594 motionNotifyEvent( e->xcrossing.window, e->xcrossing.state,
00595 e->xcrossing.x, e->xcrossing.y, e->xcrossing.x_root, e->xcrossing.y_root );
00596 break;
00597 case LeaveNotify:
00598 motionNotifyEvent( e->xcrossing.window, e->xcrossing.state,
00599 e->xcrossing.x, e->xcrossing.y, e->xcrossing.x_root, e->xcrossing.y_root );
00600 leaveNotifyEvent( &e->xcrossing );
00601 break;
00602 case FocusIn:
00603 focusInEvent( &e->xfocus );
00604 break;
00605 case FocusOut:
00606 focusOutEvent( &e->xfocus );
00607 break;
00608 case ReparentNotify:
00609 break;
00610 case ClientMessage:
00611 clientMessageEvent( &e->xclient );
00612 break;
00613 case ColormapChangeMask:
00614 if( e->xany.window == window())
00615 {
00616 cmap = e->xcolormap.colormap;
00617 if ( isActive() )
00618 workspace()->updateColormap();
00619 }
00620 break;
00621 case VisibilityNotify:
00622 visibilityNotifyEvent( &e->xvisibility );
00623 break;
00624 default:
00625 if( e->xany.window == window())
00626 {
00627 if( e->type == Shape::shapeEvent() )
00628 {
00629 is_shape = Shape::hasShape( window());
00630 updateShape();
00631 }
00632 }
00633 break;
00634 }
00635 return true;
00636 }
00637
00641 bool Client::mapRequestEvent( XMapRequestEvent* e )
00642 {
00643 if( e->window != window())
00644 {
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657 if( e->parent == wrapperId())
00658 return false;
00659 return true;
00660 }
00661 if( isTopMenu() && workspace()->managingTopMenus())
00662 return true;
00663 switch ( mappingState() )
00664 {
00665 case WithdrawnState:
00666 assert( false );
00667
00668 break;
00669 case IconicState:
00670
00671 if( isMinimized())
00672 unminimize();
00673 if( isShade())
00674 setShade( ShadeNone );
00675 if( !isOnCurrentDesktop())
00676 {
00677 if( workspace()->allowClientActivation( this ))
00678 workspace()->activateClient( this );
00679 else
00680 demandAttention();
00681 }
00682 break;
00683 case NormalState:
00684
00685 break;
00686 }
00687 return true;
00688 }
00689
00693 void Client::unmapNotifyEvent( XUnmapEvent* e )
00694 {
00695 if( e->window != window())
00696 return;
00697 if( e->event != wrapperId())
00698 {
00699 bool ignore = true;
00700 if( e->event == workspace()->rootWin() && e->send_event )
00701 ignore = false;
00702 if( ignore )
00703 return;
00704 }
00705 switch( mappingState())
00706 {
00707 case IconicState:
00708 releaseWindow();
00709 return;
00710 case NormalState:
00711
00712 XEvent ev;
00713 if( XCheckTypedWindowEvent (qt_xdisplay(), window(),
00714 DestroyNotify, &ev) )
00715 {
00716 destroyClient();
00717 return;
00718 }
00719 releaseWindow();
00720 break;
00721 default:
00722 assert( false );
00723 }
00724 }
00725
00726 void Client::destroyNotifyEvent( XDestroyWindowEvent* e )
00727 {
00728 if( e->window != window())
00729 return;
00730 destroyClient();
00731 }
00732
00733
00734 bool blockAnimation = FALSE;
00735
00739 void Client::clientMessageEvent( XClientMessageEvent* e )
00740 {
00741 if( e->window != window())
00742 return;
00743
00744 if ( e->message_type == atoms->kde_wm_change_state )
00745 {
00746 if( isTopMenu() && workspace()->managingTopMenus())
00747 return;
00748 if( e->data.l[ 1 ] )
00749 blockAnimation = true;
00750 if( e->data.l[ 0 ] == IconicState )
00751 minimize();
00752 else if( e->data.l[ 0 ] == NormalState )
00753 {
00754 if( isMinimized())
00755 unminimize();
00756 if( isShade())
00757 setShade( ShadeNone );
00758 if( !isOnCurrentDesktop())
00759 {
00760 if( workspace()->allowClientActivation( this ))
00761 workspace()->activateClient( this );
00762 else
00763 demandAttention();
00764 }
00765 }
00766 blockAnimation = false;
00767 }
00768 else if ( e->message_type == atoms->wm_change_state)
00769 {
00770 if( isTopMenu() && workspace()->managingTopMenus())
00771 return;
00772 if ( e->data.l[0] == IconicState )
00773 minimize();
00774 return;
00775 }
00776 }
00777
00778
00782 void Client::configureRequestEvent( XConfigureRequestEvent* e )
00783 {
00784 if( e->window != window())
00785 return;
00786 if ( isResize() || isMove())
00787 return;
00788
00789 if( fullscreen_mode == FullScreenNormal )
00790 {
00791 sendSyntheticConfigureNotify();
00792 return;
00793 }
00794 if( isSplash()
00795 || isTopMenu())
00796 {
00797 sendSyntheticConfigureNotify();
00798 return;
00799 }
00800
00801 if ( e->value_mask & CWBorderWidth )
00802 {
00803
00804 XWindowChanges wc;
00805 unsigned int value_mask = 0;
00806
00807 wc.border_width = 0;
00808 value_mask = CWBorderWidth;
00809 XConfigureWindow( qt_xdisplay(), window(), value_mask, & wc );
00810 }
00811
00812 if( e->value_mask & ( CWX | CWY | CWHeight | CWWidth ))
00813 configureRequest( e->value_mask, e->x, e->y, e->width, e->height, 0, false );
00814
00815 if ( e->value_mask & CWStackMode )
00816 restackWindow( e->above, e->detail, NET::FromApplication, userTime(), false );
00817
00818
00819
00820
00821
00822
00823 sendSyntheticConfigureNotify();
00824
00825
00826
00827 }
00828
00829
00833 void Client::propertyNotifyEvent( XPropertyEvent* e )
00834 {
00835 if( e->window != window())
00836 return;
00837 switch ( e->atom )
00838 {
00839 case XA_WM_NORMAL_HINTS:
00840 getWmNormalHints();
00841 break;
00842 case XA_WM_NAME:
00843 fetchName();
00844 break;
00845 case XA_WM_ICON_NAME:
00846 fetchIconicName();
00847 break;
00848 case XA_WM_TRANSIENT_FOR:
00849 readTransient();
00850 break;
00851 case XA_WM_HINTS:
00852 getWMHints();
00853 getIcons();
00854 break;
00855 default:
00856 if ( e->atom == atoms->wm_protocols )
00857 getWindowProtocols();
00858 else if (e->atom == atoms->wm_client_leader )
00859 getWmClientLeader();
00860 else if( e->atom == qt_window_role )
00861 window_role = staticWindowRole( window());
00862 else if( e->atom == atoms->motif_wm_hints )
00863 getMotifHints();
00864 break;
00865 }
00866 }
00867
00868
00869 void Client::enterNotifyEvent( XCrossingEvent* e )
00870 {
00871 if( e->window != frameId())
00872 return;
00873 if( e->mode == NotifyNormal ||
00874 ( !options->focusPolicyIsReasonable() &&
00875 e->mode == NotifyUngrab ) )
00876 {
00877
00878 if (options->shadeHover && isShade())
00879 {
00880 delete shadeHoverTimer;
00881 shadeHoverTimer = new QTimer( this );
00882 connect( shadeHoverTimer, SIGNAL( timeout() ), this, SLOT( shadeHover() ));
00883 shadeHoverTimer->start( options->shadeHoverInterval, TRUE );
00884 }
00885
00886 if ( options->focusPolicy == Options::ClickToFocus )
00887 return;
00888
00889 if ( options->autoRaise && !isDesktop() &&
00890 !isDock() && !isTopMenu() && workspace()->focusChangeEnabled() &&
00891 workspace()->topClientOnDesktop( workspace()->currentDesktop()) != this )
00892 {
00893 delete autoRaiseTimer;
00894 autoRaiseTimer = new QTimer( this );
00895 connect( autoRaiseTimer, SIGNAL( timeout() ), this, SLOT( autoRaise() ) );
00896 autoRaiseTimer->start( options->autoRaiseInterval, TRUE );
00897 }
00898
00899 if ( options->focusPolicy != Options::FocusStrictlyUnderMouse && ( isDesktop() || isDock() || isTopMenu() ) )
00900 return;
00901 if ( options->delayFocus )
00902 workspace()->requestDelayFocus( this );
00903 else
00904 workspace()->requestFocus( this );
00905
00906 return;
00907 }
00908 }
00909
00910 void Client::leaveNotifyEvent( XCrossingEvent* e )
00911 {
00912 if( e->window != frameId())
00913 return;
00914 if ( e->mode == NotifyNormal )
00915 {
00916 if ( !buttonDown )
00917 {
00918 mode = PositionCenter;
00919 setCursor( arrowCursor );
00920 }
00921 bool lostMouse = !rect().contains( QPoint( e->x, e->y ) );
00922
00923
00924
00925
00926
00927
00928
00929 if ( !lostMouse && e->detail != NotifyInferior )
00930 {
00931 int d1, d2, d3, d4;
00932 unsigned int d5;
00933 Window w, child;
00934 if( XQueryPointer( qt_xdisplay(), frameId(), &w, &child, &d1, &d2, &d3, &d4, &d5 ) == False
00935 || child == None )
00936 lostMouse = true;
00937 }
00938 if ( lostMouse )
00939 {
00940 cancelAutoRaise();
00941 workspace()->cancelDelayFocus();
00942 delete shadeHoverTimer;
00943 shadeHoverTimer = 0;
00944 if ( shade_mode == ShadeHover && !moveResizeMode && !buttonDown )
00945 setShade( ShadeNormal );
00946 }
00947 if ( options->focusPolicy == Options::FocusStrictlyUnderMouse )
00948 if ( isActive() && lostMouse )
00949 workspace()->requestFocus( 0 ) ;
00950 return;
00951 }
00952 }
00953
00954 #define XCapL KKeyNative::modXLock()
00955 #define XNumL KKeyNative::modXNumLock()
00956 #define XScrL KKeyNative::modXScrollLock()
00957 void Client::grabButton( int modifier )
00958 {
00959 unsigned int mods[ 8 ] =
00960 {
00961 0, XCapL, XNumL, XNumL | XCapL,
00962 XScrL, XScrL | XCapL,
00963 XScrL | XNumL, XScrL | XNumL | XCapL
00964 };
00965 for( int i = 0;
00966 i < 8;
00967 ++i )
00968 XGrabButton( qt_xdisplay(), AnyButton,
00969 modifier | mods[ i ],
00970 wrapperId(), FALSE, ButtonPressMask,
00971 GrabModeSync, GrabModeAsync, None, None );
00972 }
00973
00974 void Client::ungrabButton( int modifier )
00975 {
00976 unsigned int mods[ 8 ] =
00977 {
00978 0, XCapL, XNumL, XNumL | XCapL,
00979 XScrL, XScrL | XCapL,
00980 XScrL | XNumL, XScrL | XNumL | XCapL
00981 };
00982 for( int i = 0;
00983 i < 8;
00984 ++i )
00985 XUngrabButton( qt_xdisplay(), AnyButton,
00986 modifier | mods[ i ], wrapperId());
00987 }
00988 #undef XCapL
00989 #undef XNumL
00990 #undef XScrL
00991
00992
00993
00994
00995
00996
00997
00998 void Client::updateMouseGrab()
00999 {
01000 if( isActive() && !workspace()->forcedGlobalMouseGrab())
01001 {
01002
01003
01004 if( !options->clickRaise || not_obscured )
01005 ungrabButton( None );
01006 else
01007 grabButton( None );
01008 ungrabButton( ShiftMask );
01009 ungrabButton( ControlMask );
01010 ungrabButton( ControlMask | ShiftMask );
01011 }
01012 else
01013 {
01014 XUngrabButton( qt_xdisplay(), AnyButton, AnyModifier, wrapperId());
01015
01016 XGrabButton(qt_xdisplay(), AnyButton, AnyModifier, wrapperId(), FALSE,
01017 ButtonPressMask,
01018 GrabModeSync, GrabModeAsync,
01019 None, None );
01020 }
01021 }
01022
01023 int qtToX11Button( Qt::ButtonState button )
01024 {
01025 if( button == Qt::LeftButton )
01026 return Button1;
01027 else if( button == Qt::MidButton )
01028 return Button2;
01029 else if( button == Qt::RightButton )
01030 return Button3;
01031 return AnyButton;
01032 }
01033
01034 int qtToX11State( Qt::ButtonState state )
01035 {
01036 int ret = 0;
01037 if( state & Qt::LeftButton )
01038 ret |= Button1Mask;
01039 if( state & Qt::MidButton )
01040 ret |= Button2Mask;
01041 if( state & Qt::RightButton )
01042 ret |= Button3Mask;
01043 if( state & Qt::ShiftButton )
01044 ret |= ShiftMask;
01045 if( state & Qt::ControlButton )
01046 ret |= ControlMask;
01047 if( state & Qt::AltButton )
01048 ret |= KKeyNative::modX(KKey::ALT);
01049 if( state & Qt::MetaButton )
01050 ret |= KKeyNative::modX(KKey::WIN);
01051 return ret;
01052 }
01053
01054
01055
01056 bool Client::eventFilter( QObject* o, QEvent* e )
01057 {
01058 if( decoration == NULL
01059 || o != decoration->widget())
01060 return false;
01061 if( e->type() == QEvent::MouseButtonPress )
01062 {
01063 QMouseEvent* ev = static_cast< QMouseEvent* >( e );
01064 return buttonPressEvent( decorationId(), qtToX11Button( ev->button()), qtToX11State( ev->state()),
01065 ev->x(), ev->y(), ev->globalX(), ev->globalY() );
01066 }
01067 if( e->type() == QEvent::MouseButtonRelease )
01068 {
01069 QMouseEvent* ev = static_cast< QMouseEvent* >( e );
01070 return buttonReleaseEvent( decorationId(), qtToX11Button( ev->button()), qtToX11State( ev->state()),
01071 ev->x(), ev->y(), ev->globalX(), ev->globalY() );
01072 }
01073 if( e->type() == QEvent::MouseMove )
01074 {
01075 QMouseEvent* ev = static_cast< QMouseEvent* >( e );
01076 return motionNotifyEvent( decorationId(), qtToX11State( ev->state()),
01077 ev->x(), ev->y(), ev->globalX(), ev->globalY() );
01078 }
01079 if( e->type() == QEvent::Resize )
01080 {
01081 QResizeEvent* ev = static_cast< QResizeEvent* >( e );
01082
01083
01084
01085
01086 if( ev->size() != size())
01087 return true;
01088 }
01089 return false;
01090 }
01091
01092
01093 bool Client::buttonPressEvent( Window w, int button, int state, int x, int y, int x_root, int y_root )
01094 {
01095 if (buttonDown)
01096 {
01097 if( w == wrapperId())
01098 XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime );
01099 return true;
01100 }
01101
01102 if( w == wrapperId() || w == frameId() || w == decorationId())
01103 {
01104 updateUserTime();
01105 workspace()->setWasUserInteraction();
01106 uint keyModX = (options->keyCmdAllModKey() == Qt::Key_Meta) ?
01107 KKeyNative::modX(KKey::WIN) :
01108 KKeyNative::modX(KKey::ALT);
01109 bool bModKeyHeld = keyModX != 0 && ( state & KKeyNative::accelModMaskX()) == keyModX;
01110
01111 if( isSplash()
01112 && button == Button1 && !bModKeyHeld )
01113 {
01114 hideClient( true );
01115 if( w == wrapperId())
01116 XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime );
01117 return true;
01118 }
01119
01120 Options::MouseCommand com = Options::MouseNothing;
01121 bool was_action = false;
01122 bool perform_handled = false;
01123 if (keyModX != 0 && (state & keyModX) && (state & ControlMask))
01124 {
01125 switch (button)
01126 {
01127 case Button5:
01128 if (opacity_ > 0)
01129 {
01130 setOpacity(TRUE, (opacity_ > 0xCCCCCCC) ? opacity_ - 0xCCCCCCC : 0);
01131 custom_opacity = true;
01132 }
01133 XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime );
01134 return true;
01135 case Button4:
01136 if (opacity_ < 0xFFFFFFFF)
01137 {
01138 if (opacity_ < 0xF3333333){
01139 setOpacity(TRUE, opacity_ + 0xCCCCCCC);
01140 custom_opacity = true;
01141 }
01142 else{
01143 setOpacity(FALSE, 0xFFFFFFFF);
01144 custom_opacity = false;
01145 }
01146 }
01147 XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime );
01148 return true;
01149 }
01150 }
01151 else if ( bModKeyHeld )
01152 {
01153 was_action = true;
01154 switch (button)
01155 {
01156 case Button1:
01157 com = options->commandAll1();
01158 break;
01159 case Button2:
01160 com = options->commandAll2();
01161 break;
01162 case Button3:
01163 com = options->commandAll3();
01164 break;
01165 }
01166 }
01167 else
01168 {
01169 if( !isActive() && w == wrapperId())
01170 {
01171 was_action = true;
01172 perform_handled = true;
01173 switch (button)
01174 {
01175 case Button1:
01176 com = options->commandWindow1();
01177 break;
01178 case Button2:
01179 com = options->commandWindow2();
01180 break;
01181 case Button3:
01182 com = options->commandWindow3();
01183 break;
01184 default:
01185 com = Options::MouseActivateAndPassClick;
01186 }
01187 }
01188
01189 if( isActive() && w == wrapperId()
01190 && options->clickRaise && button < 4 )
01191 {
01192 com = Options::MouseActivateRaiseAndPassClick;
01193 was_action = true;
01194 perform_handled = true;
01195 }
01196 }
01197 if( was_action )
01198 {
01199 bool replay = performMouseCommand( com, QPoint( x_root, y_root), perform_handled );
01200
01201 if ( isSpecialWindow() && !isOverride())
01202 replay = TRUE;
01203
01204 if( w == wrapperId())
01205 XAllowEvents(qt_xdisplay(), replay? ReplayPointer : SyncPointer, CurrentTime );
01206 return true;
01207 }
01208 }
01209
01210 if( w == wrapperId())
01211 {
01212 XAllowEvents(qt_xdisplay(), ReplayPointer, CurrentTime );
01213 return true;
01214 }
01215 if( w == decorationId())
01216 return false;
01217 if( w == frameId())
01218 processDecorationButtonPress( button, state, x, y, x_root, y_root );
01219 return true;
01220 }
01221
01222
01223
01224
01225 void Client::processDecorationButtonPress( int button, int , int x, int y, int x_root, int y_root )
01226 {
01227 Options::MouseCommand com = Options::MouseNothing;
01228 bool active = isActive();
01229 if ( !wantsInput() )
01230 active = TRUE;
01231
01232 if ( button == Button1 )
01233 com = active ? options->commandActiveTitlebar1() : options->commandInactiveTitlebar1();
01234 else if ( button == Button2 )
01235 com = active ? options->commandActiveTitlebar2() : options->commandInactiveTitlebar2();
01236 else if ( button == Button3 )
01237 com = active ? options->commandActiveTitlebar3() : options->commandInactiveTitlebar3();
01238 if( com != Options::MouseOperationsMenu
01239 && com != Options::MouseMinimize )
01240 {
01241
01242 buttonDown = TRUE;
01243 moveOffset = QPoint( x, y );
01244 invertedMoveOffset = rect().bottomRight() - moveOffset;
01245 unrestrictedMoveResize = false;
01246 setCursor( mode );
01247 }
01248 performMouseCommand( com, QPoint( x_root, y_root ));
01249 }
01250
01251
01252 void Client::processMousePressEvent( QMouseEvent* e )
01253 {
01254 if( e->type() != QEvent::MouseButtonPress )
01255 {
01256 kdWarning() << "processMousePressEvent()" << endl;
01257 return;
01258 }
01259 int button;
01260 switch( e->button())
01261 {
01262 case LeftButton:
01263 button = Button1;
01264 break;
01265 case MidButton:
01266 button = Button2;
01267 break;
01268 case RightButton:
01269 button = Button3;
01270 break;
01271 default:
01272 return;
01273 }
01274 processDecorationButtonPress( button, e->state(), e->x(), e->y(), e->globalX(), e->globalY());
01275 }
01276
01277
01278 bool Client::buttonReleaseEvent( Window w, int , int state, int x, int y, int x_root, int y_root )
01279 {
01280 if( w == decorationId() && !buttonDown)
01281 return false;
01282 if( w == wrapperId())
01283 {
01284 XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime );
01285 return true;
01286 }
01287 if( w != frameId() && w != decorationId() && w != moveResizeGrabWindow())
01288 return true;
01289 x = this->x();
01290 y = this->y();
01291 if ( (state & ( Button1Mask & Button2Mask & Button3Mask )) == 0 )
01292 {
01293 buttonDown = FALSE;
01294 if ( moveResizeMode )
01295 {
01296 finishMoveResize( false );
01297
01298 QPoint mousepos( x_root - x, y_root - y );
01299 mode = mousePosition( mousepos );
01300 }
01301 setCursor( mode );
01302 }
01303 return true;
01304 }
01305
01306 static bool was_motion = false;
01307 static Time next_motion_time = CurrentTime;
01308
01309
01310
01311
01312
01313
01314
01315 static Bool motion_predicate( Display*, XEvent* ev, XPointer )
01316 {
01317 if( ev->type == MotionNotify )
01318 {
01319 was_motion = true;
01320 next_motion_time = ev->xmotion.time;
01321 }
01322 return False;
01323 }
01324
01325 static bool waitingMotionEvent()
01326 {
01327
01328
01329
01330 if( next_motion_time != CurrentTime
01331 && timestampCompare( qt_x_time, next_motion_time ) < 0 )
01332 return true;
01333 was_motion = false;
01334 XSync( qt_xdisplay(), False );
01335 XEvent dummy;
01336 XCheckIfEvent( qt_xdisplay(), &dummy, motion_predicate, NULL );
01337 return was_motion;
01338 }
01339
01340
01341 bool Client::motionNotifyEvent( Window w, int , int x, int y, int x_root, int y_root )
01342 {
01343 if( w != frameId() && w != decorationId() && w != moveResizeGrabWindow())
01344 return true;
01345 if ( !buttonDown )
01346 {
01347 Position newmode = mousePosition( QPoint( x, y ));
01348 if( newmode != mode )
01349 setCursor( newmode );
01350 mode = newmode;
01351
01352
01353 next_motion_time = CurrentTime;
01354 return false;
01355 }
01356 if( w == moveResizeGrabWindow())
01357 {
01358 x = this->x();
01359 y = this->y();
01360 }
01361 if( !waitingMotionEvent())
01362 handleMoveResize( x, y, x_root, y_root );
01363 return true;
01364 }
01365
01366 void Client::focusInEvent( XFocusInEvent* e )
01367 {
01368 if( e->window != window())
01369 return;
01370 if ( e->mode == NotifyUngrab )
01371 return;
01372 if ( e->detail == NotifyPointer )
01373 return;
01374 if( !isShown( false ) || !isOnCurrentDesktop())
01375 return;
01376
01377 bool activate = workspace()->allowClientActivation( this, -1U, true );
01378 workspace()->gotFocusIn( this );
01379 if( activate )
01380 setActive( TRUE );
01381 else
01382 {
01383 workspace()->restoreFocus();
01384 demandAttention();
01385 }
01386 }
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402 static bool follows_focusin = false;
01403 static bool follows_focusin_failed = false;
01404 static Bool predicate_follows_focusin( Display*, XEvent* e, XPointer arg )
01405 {
01406 if( follows_focusin || follows_focusin_failed )
01407 return False;
01408 Client* c = ( Client* ) arg;
01409 if( e->type == FocusIn && c->workspace()->findClient( WindowMatchPredicate( e->xfocus.window )))
01410 {
01411 follows_focusin = true;
01412 return False;
01413 }
01414
01415
01416 if( e->type == FocusIn || e->type == FocusOut || e->type == KeymapNotify )
01417 return False;
01418 follows_focusin_failed = true;
01419 return False;
01420 }
01421
01422 static bool check_follows_focusin( Client* c )
01423 {
01424 follows_focusin = follows_focusin_failed = false;
01425 XEvent dummy;
01426
01427
01428
01429 XCheckIfEvent( qt_xdisplay(), &dummy, predicate_follows_focusin, (XPointer)c );
01430 return follows_focusin;
01431 }
01432
01433
01434 void Client::focusOutEvent( XFocusOutEvent* e )
01435 {
01436 if( e->window != window())
01437 return;
01438 if ( e->mode == NotifyGrab )
01439 return;
01440 if ( isShade() )
01441 return;
01442 if ( e->detail != NotifyNonlinear
01443 && e->detail != NotifyNonlinearVirtual )
01444
01445 return;
01446 if ( QApplication::activePopupWidget() )
01447 return;
01448 if( !check_follows_focusin( this ))
01449 setActive( FALSE );
01450 }
01451
01452 void Client::visibilityNotifyEvent( XVisibilityEvent * e)
01453 {
01454 if( e->window != frameId())
01455 return;
01456 bool new_not_obscured = e->state == VisibilityUnobscured;
01457 if( not_obscured == new_not_obscured )
01458 return;
01459 not_obscured = new_not_obscured;
01460 updateMouseGrab();
01461 }
01462
01463
01464 void Client::NETMoveResize( int x_root, int y_root, NET::Direction direction )
01465 {
01466 if( direction == NET::Move )
01467 performMouseCommand( Options::MouseMove, QPoint( x_root, y_root ));
01468 else if( direction >= NET::TopLeft && direction <= NET::Left )
01469 {
01470 static const Position convert[] =
01471 {
01472 PositionTopLeft,
01473 PositionTop,
01474 PositionTopRight,
01475 PositionRight,
01476 PositionBottomRight,
01477 PositionBottom,
01478 PositionBottomLeft,
01479 PositionLeft
01480 };
01481 if(!isResizable() || isShade())
01482 return;
01483 if( moveResizeMode )
01484 finishMoveResize( false );
01485 buttonDown = TRUE;
01486 moveOffset = QPoint( x_root - x(), y_root - y());
01487 invertedMoveOffset = rect().bottomRight() - moveOffset;
01488 unrestrictedMoveResize = false;
01489 mode = convert[ direction ];
01490 setCursor( mode );
01491 if( !startMoveResize())
01492 {
01493 buttonDown = false;
01494 setCursor( mode );
01495 }
01496 }
01497 else if( direction == NET::KeyboardMove )
01498 {
01499 QCursor::setPos( geometry().center() );
01500 performMouseCommand( Options::MouseUnrestrictedMove, geometry().center());
01501 }
01502 else if( direction == NET::KeyboardSize )
01503 {
01504 QCursor::setPos( geometry().bottomRight());
01505 performMouseCommand( Options::MouseUnrestrictedResize, geometry().bottomRight());
01506 }
01507 }
01508
01509 void Client::keyPressEvent( uint key_code )
01510 {
01511 updateUserTime();
01512 if ( !isMove() && !isResize() )
01513 return;
01514 bool is_control = key_code & Qt::CTRL;
01515 bool is_alt = key_code & Qt::ALT;
01516 key_code = key_code & 0xffff;
01517 int delta = is_control?1:is_alt?32:8;
01518 QPoint pos = QCursor::pos();
01519 switch ( key_code )
01520 {
01521 case Key_Left:
01522 pos.rx() -= delta;
01523 break;
01524 case Key_Right:
01525 pos.rx() += delta;
01526 break;
01527 case Key_Up:
01528 pos.ry() -= delta;
01529 break;
01530 case Key_Down:
01531 pos.ry() += delta;
01532 break;
01533 case Key_Space:
01534 case Key_Return:
01535 case Key_Enter:
01536 finishMoveResize( false );
01537 buttonDown = FALSE;
01538 setCursor( mode );
01539 break;
01540 case Key_Escape:
01541 finishMoveResize( true );
01542 buttonDown = FALSE;
01543 setCursor( mode );
01544 break;
01545 default:
01546 return;
01547 }
01548 QCursor::setPos( pos );
01549 }
01550
01551
01552
01553
01554
01555 bool Group::groupEvent( XEvent* e )
01556 {
01557 unsigned long dirty[ 2 ];
01558 leader_info->event( e, dirty, 2 );
01559 if ( ( dirty[ WinInfo::PROTOCOLS ] & NET::WMIcon) != 0 )
01560 getIcons();
01561 if(( dirty[ WinInfo::PROTOCOLS2 ] & NET::WM2StartupId ) != 0 )
01562 startupIdChanged();
01563 return false;
01564 }
01565
01566
01567 }