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