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