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