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()
00418 && ( e->xfocus.detail == NotifyDetailNone || e->xfocus.detail == NotifyPointerRoot ))
00419 {
00420 updateXTime();
00421 Window focus;
00422
int revert;
00423 XGetInputFocus( qt_xdisplay(), &focus, &revert );
00424
if( focus == None || focus == PointerRoot )
00425 {
00426
00427
if( mostRecentlyActivatedClient() != NULL )
00428 requestFocus( mostRecentlyActivatedClient(),
true );
00429
else
00430 focusToNull();
00431 }
00432 }
00433
00434
case FocusOut:
00435
return true;
00436
default:
00437
break;
00438 }
00439
return FALSE;
00440 }
00441
00442
00443
00444
00445 Window Workspace::findSpecialEventWindow( XEvent* e )
00446 {
00447
switch( e->type )
00448 {
00449
case CreateNotify:
00450
return e->xcreatewindow.window;
00451
case DestroyNotify:
00452
return e->xdestroywindow.window;
00453
case UnmapNotify:
00454
return e->xunmap.window;
00455
case MapNotify:
00456
return e->xmap.window;
00457
case MapRequest:
00458
return e->xmaprequest.window;
00459
case ReparentNotify:
00460
return e->xreparent.window;
00461
case ConfigureNotify:
00462
return e->xconfigure.window;
00463
case GravityNotify:
00464
return e->xgravity.window;
00465
case ConfigureRequest:
00466
return e->xconfigurerequest.window;
00467
case CirculateNotify:
00468
return e->xcirculate.window;
00469
case CirculateRequest:
00470
return e->xcirculaterequest.window;
00471
default:
00472
return None;
00473 };
00474 }
00475
00479
bool Workspace::netCheck( XEvent* e )
00480 {
00481
unsigned int dirty = rootInfo->event( e );
00482
00483
if ( dirty & NET::DesktopNames )
00484 saveDesktopSettings();
00485
00486
return dirty != 0;
00487 }
00488
00489
00490
00491
00492
00493
00497 bool Client::windowEvent( XEvent* e )
00498 {
00499
if( e->xany.window == window())
00500 {
00501
unsigned long dirty[ 2 ];
00502 info->event( e, dirty, 2 );
00503
00504
if ( ( dirty[ WinInfo::PROTOCOLS ] & NET::WMName ) != 0 )
00505 fetchName();
00506
if ( ( dirty[ WinInfo::PROTOCOLS ] & NET::WMIconName ) != 0 )
00507 fetchIconicName();
00508
if ( ( dirty[ WinInfo::PROTOCOLS ] & NET::WMStrut ) != 0 )
00509 {
00510
if( isTopMenu())
00511 checkWorkspacePosition();
00512 workspace()->updateClientArea();
00513 }
00514
if ( ( dirty[ WinInfo::PROTOCOLS ] & NET::WMIcon) != 0 )
00515 getIcons();
00516
00517
00518
00519
if(( dirty[ WinInfo::PROTOCOLS2 ] & NET::WM2UserTime ) != 0 )
00520 {
00521 workspace()->setWasUserInteraction();
00522
updateUserTime( info->userTime());
00523 }
00524
if(( dirty[ WinInfo::PROTOCOLS2 ] & NET::WM2StartupId ) != 0 )
00525 startupIdChanged();
00526 }
00527
00528
00529
switch (e->type)
00530 {
00531
case UnmapNotify:
00532 unmapNotifyEvent( &e->xunmap );
00533
break;
00534
case DestroyNotify:
00535 destroyNotifyEvent( &e->xdestroywindow );
00536
break;
00537
case MapRequest:
00538
00539
return mapRequestEvent( &e->xmaprequest );
00540
case ConfigureRequest:
00541 configureRequestEvent( &e->xconfigurerequest );
00542
break;
00543
case PropertyNotify:
00544 propertyNotifyEvent( &e->xproperty );
00545
break;
00546
case KeyPress:
00547
updateUserTime();
00548 workspace()->setWasUserInteraction();
00549
break;
00550
case ButtonPress:
00551
updateUserTime();
00552 workspace()->setWasUserInteraction();
00553 buttonPressEvent( e->xbutton.window, e->xbutton.button, e->xbutton.state,
00554 e->xbutton.x, e->xbutton.y, e->xbutton.x_root, e->xbutton.y_root );
00555
break;;
00556
case KeyRelease:
00557
00558
00559
00560
break;
00561
case ButtonRelease:
00562
00563
00564
00565 buttonReleaseEvent( e->xbutton.window, e->xbutton.button, e->xbutton.state,
00566 e->xbutton.x, e->xbutton.y, e->xbutton.x_root, e->xbutton.y_root );
00567
break;
00568
case MotionNotify:
00569 motionNotifyEvent( e->xmotion.window, e->xmotion.state,
00570 e->xmotion.x, e->xmotion.y, e->xmotion.x_root, e->xmotion.y_root );
00571
break;
00572
case EnterNotify:
00573 enterNotifyEvent( &e->xcrossing );
00574
00575
00576
00577
00578
00579 motionNotifyEvent( e->xcrossing.window, e->xcrossing.state,
00580 e->xcrossing.x, e->xcrossing.y, e->xcrossing.x_root, e->xcrossing.y_root );
00581
break;
00582
case LeaveNotify:
00583 motionNotifyEvent( e->xcrossing.window, e->xcrossing.state,
00584 e->xcrossing.x, e->xcrossing.y, e->xcrossing.x_root, e->xcrossing.y_root );
00585 leaveNotifyEvent( &e->xcrossing );
00586
break;
00587
case FocusIn:
00588 focusInEvent( &e->xfocus );
00589
break;
00590
case FocusOut:
00591 focusOutEvent( &e->xfocus );
00592
break;
00593
case ReparentNotify:
00594
break;
00595
case ClientMessage:
00596 clientMessageEvent( &e->xclient );
00597
break;
00598
case ColormapChangeMask:
00599
if( e->xany.window == window())
00600 {
00601 cmap = e->xcolormap.colormap;
00602
if ( isActive() )
00603 workspace()->updateColormap();
00604 }
00605
break;
00606
case VisibilityNotify:
00607 visibilityNotifyEvent( &e->xvisibility );
00608
break;
00609
default:
00610
if( e->xany.window == window())
00611 {
00612
if( e->type == Shape::shapeEvent() )
00613 {
00614 is_shape = Shape::hasShape( window());
00615 updateShape();
00616 }
00617 }
00618
break;
00619 }
00620
return true;
00621 }
00622
00626
bool Client::mapRequestEvent( XMapRequestEvent* e )
00627 {
00628
if( e->window != window())
00629 {
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
if( e->parent == wrapperId())
00643
return false;
00644
return true;
00645 }
00646
if( isTopMenu() && workspace()->managingTopMenus())
00647
return true;
00648
switch ( mappingState() )
00649 {
00650
case WithdrawnState:
00651 assert(
false );
00652
00653
break;
00654
case IconicState:
00655
00656
if( isMinimized())
00657 unminimize();
00658
if( isShade())
00659 setShade( ShadeNone );
00660
if( !isOnCurrentDesktop())
00661 {
00662
if( workspace()->allowClientActivation(
this ))
00663 workspace()->activateClient(
this );
00664
else
00665 demandAttention();
00666 }
00667
break;
00668
case NormalState:
00669
00670
break;
00671 }
00672
return true;
00673 }
00674
00678
void Client::unmapNotifyEvent( XUnmapEvent* e )
00679 {
00680
if( e->window != window())
00681
return;
00682
if( e->event != wrapperId())
00683 {
00684
bool ignore =
true;
00685
if( e->event == workspace()->rootWin() && e->send_event )
00686 ignore =
false;
00687
if( ignore )
00688
return;
00689 }
00690
switch( mappingState())
00691 {
00692
case IconicState:
00693
releaseWindow();
00694
return;
00695
case NormalState:
00696
00697 XEvent ev;
00698
if( XCheckTypedWindowEvent (qt_xdisplay(), window(),
00699 DestroyNotify, &ev) )
00700 {
00701 destroyClient();
00702
return;
00703 }
00704
releaseWindow();
00705
break;
00706
default:
00707 assert(
false );
00708 }
00709 }
00710
00711
void Client::destroyNotifyEvent( XDestroyWindowEvent* e )
00712 {
00713
if( e->window != window())
00714
return;
00715 destroyClient();
00716 }
00717
00718
00719
bool blockAnimation = FALSE;
00720
00724
void Client::clientMessageEvent( XClientMessageEvent* e )
00725 {
00726
if( e->window != window())
00727
return;
00728
00729
if ( e->message_type == atoms->kde_wm_change_state )
00730 {
00731
if( isTopMenu() && workspace()->managingTopMenus())
00732
return;
00733
if( e->data.l[ 1 ] )
00734 blockAnimation =
true;
00735
if( e->data.l[ 0 ] == IconicState )
00736
minimize();
00737
else if( e->data.l[ 0 ] == NormalState )
00738 {
00739
if( isMinimized())
00740 unminimize();
00741
if( isShade())
00742 setShade( ShadeNone );
00743
if( !isOnCurrentDesktop())
00744 {
00745
if( workspace()->allowClientActivation(
this ))
00746 workspace()->activateClient(
this );
00747
else
00748 demandAttention();
00749 }
00750 }
00751 blockAnimation =
false;
00752 }
00753
else if ( e->message_type == atoms->wm_change_state)
00754 {
00755
if( isTopMenu() && workspace()->managingTopMenus())
00756
return;
00757
if ( e->data.l[0] == IconicState )
00758
minimize();
00759
return;
00760 }
00761 }
00762
00763
00767
void Client::configureRequestEvent( XConfigureRequestEvent* e )
00768 {
00769
if( e->window != window())
00770
return;
00771
if ( isResize() || isMove())
00772
return;
00773
00774
if( isFullScreen()
00775 || isSplash()
00776 || isTopMenu())
00777 {
00778 sendSyntheticConfigureNotify();
00779
return;
00780 }
00781
00782
if ( e->value_mask & CWBorderWidth )
00783 {
00784
00785 XWindowChanges wc;
00786
unsigned int value_mask = 0;
00787
00788 wc.border_width = 0;
00789 value_mask = CWBorderWidth;
00790 XConfigureWindow( qt_xdisplay(), window(), value_mask, & wc );
00791 }
00792
00793
if( e->value_mask & ( CWX | CWY | CWHeight | CWWidth ))
00794 configureRequest( e->value_mask, e->x, e->y, e->width, e->height );
00795
00796
if ( e->value_mask & CWStackMode )
00797 restackWindow( e->above, e->detail, NET::FromApplication );
00798
00799
00800
00801
00802
00803 sendSyntheticConfigureNotify();
00804
00805
00806
00807 }
00808
00809
00813
void Client::propertyNotifyEvent( XPropertyEvent* e )
00814 {
00815
if( e->window != window())
00816
return;
00817
switch ( e->atom )
00818 {
00819
case XA_WM_NORMAL_HINTS:
00820 getWmNormalHints();
00821
break;
00822
case XA_WM_NAME:
00823 fetchName();
00824
break;
00825
case XA_WM_ICON_NAME:
00826 fetchIconicName();
00827
break;
00828
case XA_WM_TRANSIENT_FOR:
00829 readTransient();
00830
break;
00831
case XA_WM_HINTS:
00832 getWMHints();
00833 getIcons();
00834
break;
00835
default:
00836
if ( e->atom == atoms->wm_protocols )
00837 getWindowProtocols();
00838
else if (e->atom == atoms->wm_client_leader )
00839 getWmClientLeader();
00840
else if( e->atom == qt_window_role )
00841 window_role = getStringProperty( window(), qt_window_role );
00842
break;
00843 }
00844 }
00845
00846
00847
void Client::enterNotifyEvent( XCrossingEvent* e )
00848 {
00849
if( e->window != frameId())
00850
return;
00851
if( e->mode == NotifyNormal ||
00852 ( !options->focusPolicyIsReasonable() &&
00853 e->mode == NotifyUngrab ) )
00854 {
00855
00856
if (options->shadeHover && isShade())
00857 {
00858
delete shadeHoverTimer;
00859 shadeHoverTimer =
new QTimer(
this );
00860 connect( shadeHoverTimer, SIGNAL( timeout() ),
this, SLOT( shadeHover() ));
00861 shadeHoverTimer->start( options->shadeHoverInterval, TRUE );
00862 }
00863
00864
if ( options->focusPolicy == Options::ClickToFocus )
00865
return;
00866
00867
if ( options->autoRaise && !isDesktop() &&
00868 !isDock() && !isTopMenu() && workspace()->focusChangeEnabled() &&
00869 workspace()->topClientOnDesktop( workspace()->currentDesktop()) !=
this )
00870 {
00871
delete autoRaiseTimer;
00872 autoRaiseTimer =
new QTimer(
this );
00873 connect( autoRaiseTimer, SIGNAL( timeout() ),
this, SLOT( autoRaise() ) );
00874 autoRaiseTimer->start( options->autoRaiseInterval, TRUE );
00875 }
00876
00877
if ( options->focusPolicy != Options::FocusStrictlyUnderMouse && ( isDesktop() || isDock() || isTopMenu() ) )
00878
return;
00879
00880 workspace()->requestFocus(
this );
00881
return;
00882 }
00883 }
00884
00885
void Client::leaveNotifyEvent( XCrossingEvent* e )
00886 {
00887
if( e->window != frameId())
00888
return;
00889
if ( e->mode == NotifyNormal )
00890 {
00891
if ( !buttonDown )
00892 {
00893 mode = PositionCenter;
00894 setCursor( arrowCursor );
00895 }
00896
bool lostMouse = !rect().contains( QPoint( e->x, e->y ) );
00897
00898
00899
00900
00901
00902
00903
00904
if ( !lostMouse && e->detail != NotifyInferior )
00905 {
00906
int d1, d2, d3, d4;
00907
unsigned int d5;
00908 Window w, child;
00909
if( XQueryPointer( qt_xdisplay(), frameId(), &w, &child, &d1, &d2, &d3, &d4, &d5 ) == False
00910 || child == None )
00911 lostMouse =
true;
00912 }
00913
if ( lostMouse )
00914 {
00915 cancelAutoRaise();
00916
delete shadeHoverTimer;
00917 shadeHoverTimer = 0;
00918
if ( shade_mode == ShadeHover && !moveResizeMode && !buttonDown )
00919 setShade( ShadeNormal );
00920 }
00921
if ( options->focusPolicy == Options::FocusStrictlyUnderMouse )
00922
if ( isActive() && lostMouse )
00923 workspace()->requestFocus( 0 ) ;
00924
return;
00925 }
00926 }
00927
00928
#define XCapL KKeyNative::modXLock()
00929
#define XNumL KKeyNative::modXNumLock()
00930
#define XScrL KKeyNative::modXScrollLock()
00931
void Client::grabButton(
int modifier )
00932 {
00933
unsigned int mods[ 8 ] =
00934 {
00935 0, XCapL, XNumL, XNumL | XCapL,
00936 XScrL, XScrL | XCapL,
00937 XScrL | XNumL, XScrL | XNumL | XCapL
00938 };
00939
for(
int i = 0;
00940 i < 8;
00941 ++i )
00942 XGrabButton( qt_xdisplay(), AnyButton,
00943 modifier | mods[ i ],
00944 wrapperId(), FALSE, ButtonPressMask,
00945 GrabModeSync, GrabModeAsync, None, None );
00946 }
00947
00948
void Client::ungrabButton(
int modifier )
00949 {
00950
unsigned int mods[ 8 ] =
00951 {
00952 0, XCapL, XNumL, XNumL | XCapL,
00953 XScrL, XScrL | XCapL,
00954 XScrL | XNumL, XScrL | XNumL | XCapL
00955 };
00956
for(
int i = 0;
00957 i < 8;
00958 ++i )
00959 XUngrabButton( qt_xdisplay(), AnyButton,
00960 modifier | mods[ i ], wrapperId());
00961 }
00962
#undef XCapL
00963
#undef XNumL
00964
#undef XScrL
00965
00966
00967
00968
00969
00970
00971
00972
void Client::updateMouseGrab()
00973 {
00974
if( isActive() )
00975 {
00976
00977
00978
if( !options->clickRaise || not_obscured )
00979 ungrabButton( None );
00980
else
00981 grabButton( None );
00982 ungrabButton( ShiftMask );
00983 ungrabButton( ControlMask );
00984 ungrabButton( ControlMask | ShiftMask );
00985 }
00986
else
00987 {
00988 XUngrabButton( qt_xdisplay(), AnyButton, AnyModifier, wrapperId());
00989
00990 XGrabButton(qt_xdisplay(), AnyButton, AnyModifier, wrapperId(), FALSE,
00991 ButtonPressMask,
00992 GrabModeSync, GrabModeAsync,
00993 None, None );
00994 }
00995 }
00996
00997
int qtToX11Button( Qt::ButtonState button )
00998 {
00999
if( button == Qt::LeftButton )
01000
return Button1;
01001
else if( button == Qt::MidButton )
01002
return Button2;
01003
else if( button == Qt::RightButton )
01004
return Button3;
01005
return AnyButton;
01006 }
01007
01008
int qtToX11State( Qt::ButtonState state )
01009 {
01010
int ret = 0;
01011
if( state & Qt::LeftButton )
01012 ret |= Button1Mask;
01013
if( state & Qt::MidButton )
01014 ret |= Button2Mask;
01015
if( state & Qt::RightButton )
01016 ret |= Button3Mask;
01017
if( state & Qt::ShiftButton )
01018 ret |= ShiftMask;
01019
if( state & Qt::ControlButton )
01020 ret |= ControlMask;
01021
if( state & Qt::AltButton )
01022 ret |= KKeyNative::modX(KKey::ALT);
01023
if( state & Qt::MetaButton )
01024 ret |= KKeyNative::modX(KKey::WIN);
01025
return ret;
01026 }
01027
01028
01029
01030
bool Client::eventFilter( QObject* o, QEvent* e )
01031 {
01032
if( decoration == NULL
01033 || o != decoration->
widget())
01034
return false;
01035
if( e->type() == QEvent::MouseButtonPress )
01036 {
01037 QMouseEvent* ev = static_cast< QMouseEvent* >( e );
01038
return buttonPressEvent( decorationId(), qtToX11Button( ev->button()), qtToX11State( ev->state()),
01039 ev->x(), ev->y(), ev->globalX(), ev->globalY() );
01040 }
01041
if( e->type() == QEvent::MouseButtonRelease )
01042 {
01043 QMouseEvent* ev = static_cast< QMouseEvent* >( e );
01044
return buttonReleaseEvent( decorationId(), qtToX11Button( ev->button()), qtToX11State( ev->state()),
01045 ev->x(), ev->y(), ev->globalX(), ev->globalY() );
01046 }
01047
if( e->type() == QEvent::MouseMove )
01048 {
01049 QMouseEvent* ev = static_cast< QMouseEvent* >( e );
01050
return motionNotifyEvent( decorationId(), qtToX11State( ev->state()),
01051 ev->x(), ev->y(), ev->globalX(), ev->globalY() );
01052 }
01053
if( e->type() == QEvent::Resize )
01054 {
01055 QResizeEvent* ev = static_cast< QResizeEvent* >( e );
01056
01057
01058
01059
01060
if( ev->size() != size())
01061
return true;
01062 }
01063
return false;
01064 }
01065
01066
01067
bool Client::buttonPressEvent( Window w,
int button,
int state,
int x,
int y,
int x_root,
int y_root )
01068 {
01069
if (buttonDown)
01070 {
01071
if( w == wrapperId())
01072 XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime );
01073
return true;
01074 }
01075
01076
if( w == wrapperId() || w == frameId() || w == decorationId())
01077 {
01078
updateUserTime();
01079 workspace()->setWasUserInteraction();
01080 uint keyModX = (options->keyCmdAllModKey() == Qt::Key_Meta) ?
01081 KKeyNative::modX(KKey::WIN) :
01082 KKeyNative::modX(KKey::ALT);
01083
bool bModKeyHeld = keyModX != 0 && ( state & KKeyNative::accelModMaskX()) == keyModX;
01084
01085
if( isSplash()
01086 && button == Button1 && !bModKeyHeld )
01087 {
01088 hideClient(
true );
01089
if( w == wrapperId())
01090 XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime );
01091
return true;
01092 }
01093
01094
if ( isActive() && w == wrapperId()
01095 && ( options->clickRaise && !bModKeyHeld ) )
01096 {
01097
if ( button < 4 )
01098 autoRaise();
01099 }
01100
01101 Options::MouseCommand com = Options::MouseNothing;
01102
bool was_action =
false;
01103
if ( bModKeyHeld )
01104 {
01105 was_action =
true;
01106
switch (button)
01107 {
01108
case Button1:
01109 com = options->commandAll1();
01110
break;
01111
case Button2:
01112 com = options->commandAll2();
01113
break;
01114
case Button3:
01115 com = options->commandAll3();
01116
break;
01117 }
01118 }
01119
else
01120 {
01121
if( !isActive() && w == wrapperId())
01122 {
01123 was_action =
true;
01124
switch (button)
01125 {
01126
case Button1:
01127 com = options->commandWindow1();
01128
break;
01129
case Button2:
01130 com = options->commandWindow2();
01131
break;
01132
case Button3:
01133 com = options->commandWindow3();
01134
break;
01135
default:
01136 com = Options::MouseActivateAndPassClick;
01137 }
01138 }
01139 }
01140
if( was_action )
01141 {
01142
bool replay =
performMouseCommand( com, QPoint( x_root, y_root) );
01143
01144
if ( isSpecialWindow() && !isOverride())
01145 replay = TRUE;
01146
01147
if( w == wrapperId())
01148 XAllowEvents(qt_xdisplay(), replay? ReplayPointer : SyncPointer, CurrentTime );
01149
return true;
01150 }
01151 }
01152
01153
if( w == wrapperId())
01154 {
01155 XAllowEvents(qt_xdisplay(), ReplayPointer, CurrentTime );
01156
return true;
01157 }
01158
if( w == decorationId())
01159
return false;
01160
if( w == frameId())
01161 processDecorationButtonPress( button, state, x, y, x_root, y_root );
01162
return true;
01163 }
01164
01165
01166
01167
01168
void Client::processDecorationButtonPress(
int button,
int ,
int x,
int y,
int x_root,
int y_root )
01169 {
01170 Options::MouseCommand com = Options::MouseNothing;
01171
bool active = isActive();
01172
if ( !wantsInput() )
01173 active = TRUE;
01174
01175
if ( button == Button1 )
01176 com = active ? options->commandActiveTitlebar1() : options->commandInactiveTitlebar1();
01177
else if ( button == Button2 )
01178 com = active ? options->commandActiveTitlebar2() : options->commandInactiveTitlebar2();
01179
else if ( button == Button3 )
01180 com = active ? options->commandActiveTitlebar3() : options->commandInactiveTitlebar3();
01181
if( com != Options::MouseOperationsMenu
01182 && com != Options::MouseMinimize )
01183 {
01184
01185 buttonDown = TRUE;
01186 moveOffset = QPoint( x, y );
01187 invertedMoveOffset = rect().bottomRight() - moveOffset;
01188 unrestrictedMoveResize =
false;
01189 setCursor( mode );
01190 }
01191
performMouseCommand( com, QPoint( x_root, y_root ));
01192 }
01193
01194
01195
void Client::processMousePressEvent( QMouseEvent* e )
01196 {
01197
if( e->type() != QEvent::MouseButtonPress )
01198 {
01199 kdWarning() <<
"processMousePressEvent()" << endl;
01200
return;
01201 }
01202
int button;
01203
switch( e->button())
01204 {
01205
case LeftButton:
01206 button = Button1;
01207
break;
01208
case MidButton:
01209 button = Button2;
01210
break;
01211
case RightButton:
01212 button = Button3;
01213
break;
01214
default:
01215
return;
01216 }
01217 processDecorationButtonPress( button, e->state(), e->x(), e->y(), e->globalX(), e->globalY());
01218 }
01219
01220
01221
bool Client::buttonReleaseEvent( Window w,
int ,
int state,
int x,
int y,
int x_root,
int y_root )
01222 {
01223
if( w == decorationId() && !buttonDown)
01224
return false;
01225
if( w == wrapperId())
01226 {
01227 XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime );
01228
return true;
01229 }
01230
if( w != frameId() && w != decorationId() && w != moveResizeGrabWindow())
01231
return true;
01232 x = this->x();
01233 y = this->y();
01234
if ( (state & ( Button1Mask & Button2Mask & Button3Mask )) == 0 )
01235 {
01236 buttonDown = FALSE;
01237
if ( moveResizeMode )
01238 {
01239 finishMoveResize(
false );
01240
01241 QPoint mousepos( x_root - x, y_root - y );
01242 mode = mousePosition( mousepos );
01243 }
01244 setCursor( mode );
01245 }
01246
return true;
01247 }
01248
01249
static bool was_motion =
false;
01250
static Time next_motion_time = CurrentTime;
01251
01252
01253
01254
01255
01256
01257
01258
static Bool motion_predicate( Display*, XEvent* ev, XPointer )
01259 {
01260
if( ev->type == MotionNotify )
01261 {
01262 was_motion =
true;
01263 next_motion_time = ev->xmotion.time;
01264 }
01265
return False;
01266 }
01267
01268
static bool waitingMotionEvent()
01269 {
01270
01271
01272
01273
if( next_motion_time != CurrentTime
01274 && timestampCompare( qt_x_time, next_motion_time ) < 0 )
01275
return true;
01276 was_motion =
false;
01277 XSync( qt_xdisplay(), False );
01278 XEvent dummy;
01279 XCheckIfEvent( qt_xdisplay(), &dummy, motion_predicate, NULL );
01280
return was_motion;
01281 }
01282
01283
01284
bool Client::motionNotifyEvent( Window w,
int ,
int x,
int y,
int x_root,
int y_root )
01285 {
01286
if( w != frameId() && w != decorationId() && w != moveResizeGrabWindow())
01287
return true;
01288
if ( !buttonDown )
01289 {
01290
Position newmode = mousePosition( QPoint( x, y ));
01291
if( newmode != mode )
01292 setCursor( newmode );
01293 mode = newmode;
01294
return false;
01295 }
01296
if( w == moveResizeGrabWindow())
01297 {
01298 x = this->x();
01299 y = this->y();
01300 }
01301
if( !waitingMotionEvent())
01302 handleMoveResize( x, y, x_root, y_root );
01303
return true;
01304 }
01305
01306
void Client::focusInEvent( XFocusInEvent* e )
01307 {
01308
if( e->window != window())
01309
return;
01310
if ( e->mode == NotifyUngrab )
01311
return;
01312
if ( e->detail == NotifyPointer )
01313
return;
01314
if( !isShown(
false ) || !isOnCurrentDesktop())
01315
return;
01316
01317
bool activate = workspace()->allowClientActivation(
this, -1U,
true );
01318 workspace()->gotFocusIn(
this );
01319
if( activate )
01320
setActive( TRUE );
01321
else
01322 {
01323 workspace()->restoreFocus();
01324 demandAttention();
01325 }
01326 }
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
static bool follows_focusin =
false;
01343
static bool follows_focusin_failed =
false;
01344
static Bool predicate_follows_focusin( Display*, XEvent* e, XPointer arg )
01345 {
01346
if( follows_focusin || follows_focusin_failed )
01347
return False;
01348 Client* c = ( Client* ) arg;
01349
if( e->type == FocusIn && c->workspace()->findClient( WindowMatchPredicate( e->xfocus.window )))
01350 {
01351 follows_focusin =
true;
01352
return False;
01353 }
01354
01355
01356
if( e->type == FocusIn || e->type == FocusOut || e->type == KeymapNotify )
01357
return False;
01358 follows_focusin_failed =
true;
01359
return False;
01360 }
01361
01362
static bool check_follows_focusin( Client* c )
01363 {
01364 follows_focusin = follows_focusin_failed =
false;
01365 XEvent dummy;
01366
01367
01368
01369 XCheckIfEvent( qt_xdisplay(), &dummy, predicate_follows_focusin, (XPointer)c );
01370
return follows_focusin;
01371 }
01372
01373
01374
void Client::focusOutEvent( XFocusOutEvent* e )
01375 {
01376
if( e->window != window())
01377
return;
01378
if ( e->mode == NotifyGrab )
01379
return;
01380
if ( isShade() )
01381
return;
01382
if ( e->detail != NotifyNonlinear
01383 && e->detail != NotifyNonlinearVirtual )
01384
01385
return;
01386
if ( QApplication::activePopupWidget() )
01387
return;
01388
if( !check_follows_focusin(
this ))
01389
setActive( FALSE );
01390 }
01391
01392
void Client::visibilityNotifyEvent( XVisibilityEvent * e)
01393 {
01394
if( e->window != frameId())
01395
return;
01396
bool new_not_obscured = e->state == VisibilityUnobscured;
01397
if( not_obscured == new_not_obscured )
01398
return;
01399 not_obscured = new_not_obscured;
01400 updateMouseGrab();
01401 }
01402
01403
01404
void Client::NETMoveResize(
int x_root,
int y_root, NET::Direction direction )
01405 {
01406
if( direction == NET::Move )
01407
performMouseCommand( Options::MouseMove, QPoint( x_root, y_root ));
01408
else if( direction >= NET::TopLeft && direction <= NET::Left )
01409 {
01410
static const Position convert[] =
01411 {
01412 PositionTopLeft,
01413 PositionTop,
01414 PositionTopRight,
01415 PositionRight,
01416 PositionBottomRight,
01417 PositionBottom,
01418 PositionBottomLeft,
01419 PositionLeft
01420 };
01421
if(!
isResizable() || isShade())
01422
return;
01423
if( moveResizeMode )
01424 finishMoveResize(
false );
01425 buttonDown = TRUE;
01426 moveOffset = QPoint( x_root - x(), y_root - y());
01427 invertedMoveOffset = rect().bottomRight() - moveOffset;
01428 unrestrictedMoveResize =
false;
01429 mode = convert[ direction ];
01430 setCursor( mode );
01431
if( !startMoveResize())
01432 {
01433 buttonDown =
false;
01434 setCursor( mode );
01435 }
01436 }
01437
else if( direction == NET::KeyboardMove )
01438 {
01439 QCursor::setPos( geometry().center() );
01440
performMouseCommand( Options::MouseUnrestrictedMove, geometry().center());
01441 }
01442
else if( direction == NET::KeyboardSize )
01443 {
01444 QCursor::setPos( geometry().bottomRight());
01445
performMouseCommand( Options::MouseUnrestrictedResize, geometry().bottomRight());
01446 }
01447 }
01448
01449
void Client::keyPressEvent( uint key_code )
01450 {
01451
updateUserTime();
01452
if ( !isMove() && !isResize() )
01453
return;
01454
bool is_control = key_code & Qt::CTRL;
01455
bool is_alt = key_code & Qt::ALT;
01456 key_code = key_code & 0xffff;
01457
int delta = is_control?1:is_alt?32:8;
01458 QPoint pos = QCursor::pos();
01459
switch ( key_code )
01460 {
01461
case Key_Left:
01462 pos.rx() -= delta;
01463
break;
01464
case Key_Right:
01465 pos.rx() += delta;
01466
break;
01467
case Key_Up:
01468 pos.ry() -= delta;
01469
break;
01470
case Key_Down:
01471 pos.ry() += delta;
01472
break;
01473
case Key_Space:
01474
case Key_Return:
01475
case Key_Enter:
01476 finishMoveResize(
false );
01477 buttonDown = FALSE;
01478 setCursor( mode );
01479
break;
01480
case Key_Escape:
01481 finishMoveResize(
true );
01482 buttonDown = FALSE;
01483 setCursor( mode );
01484
break;
01485
default:
01486
return;
01487 }
01488 QCursor::setPos( pos );
01489 }
01490
01491
01492
01493
01494
01495
bool Group::groupEvent( XEvent* e )
01496 {
01497
unsigned long dirty[ 2 ];
01498 leader_info->event( e, dirty, 2 );
01499
if ( ( dirty[ WinInfo::PROTOCOLS ] & NET::WMIcon) != 0 )
01500 getIcons();
01501
if(( dirty[ WinInfo::PROTOCOLS2 ] & NET::WM2StartupId ) != 0 )
01502 startupIdChanged();
01503
return false;
01504 }
01505
01506
01507 }