1
/*****************************************************************
2
KWin - the KDE window manager
3
This file is part of the KDE project.
5
Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
6
Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
8
You can Freely distribute this program under the GNU General Public
9
License. See the file "COPYING" for the exact licensing terms.
10
******************************************************************/
14
This file is for (very) small utility functions/classes.
24
#include <kxerrorhandler.h>
27
#include <kshortcut.h>
28
#include <kkeyserver.h>
31
#include <X11/extensions/shape.h>
32
#include <X11/Xatom.h>
36
#include <X11/extensions/Xrender.h>
39
#include <X11/extensions/Xfixes.h>
42
#include <X11/extensions/Xdamage.h>
45
#include <X11/extensions/Xrandr.h>
47
#ifdef HAVE_XCOMPOSITE
48
#include <X11/extensions/Xcomposite.h>
54
#include <X11/extensions/sync.h>
60
#include "notifications.h"
61
#include "workspace.h"
70
int Extensions::shape_version = 0;
71
int Extensions::shape_event_base = 0;
72
bool Extensions::has_randr = false;
73
int Extensions::randr_event_base = 0;
74
bool Extensions::has_damage = false;
75
int Extensions::damage_event_base = 0;
76
int Extensions::composite_version = 0;
77
int Extensions::fixes_version = 0;
78
int Extensions::render_version = 0;
79
bool Extensions::has_glx = false;
80
bool Extensions::has_sync = false;
81
int Extensions::sync_event_base = 0;
83
void Extensions::init()
87
if( XShapeQueryExtension( display(), &shape_event_base, &dummy ))
90
if( XShapeQueryVersion( display(), &major, &minor ))
91
shape_version = major * 0x10 + minor;
94
has_randr = XRRQueryExtension( display(), &randr_event_base, &dummy );
98
XRRQueryVersion( display(), &major, &minor );
99
has_randr = ( major > 1 || ( major == 1 && minor >= 1 ) );
105
has_damage = XDamageQueryExtension( display(), &damage_event_base, &dummy );
109
composite_version = 0;
110
#ifdef HAVE_XCOMPOSITE
111
if( XCompositeQueryExtension( display(), &dummy, &dummy ))
113
int major = 0, minor = 0;
114
XCompositeQueryVersion( display(), &major, &minor );
115
composite_version = major * 0x10 + minor;
120
if( XFixesQueryExtension( display(), &dummy, &dummy ))
122
int major = 0, minor = 0;
123
XFixesQueryVersion( display(), &major, &minor );
124
fixes_version = major * 0x10 + minor;
129
if( XRenderQueryExtension( display(), &dummy, &dummy ))
131
int major = 0, minor = 0;
132
XRenderQueryVersion( display(), &major, &minor );
133
render_version = major * 0x10 + minor;
138
has_glx = glXQueryExtension( display(), &dummy, &dummy );
141
if( XSyncQueryExtension( display(), &sync_event_base, &dummy ))
143
int major = 0, minor = 0;
144
if( XSyncInitialize( display(), &major, &minor ))
148
kDebug( 1212 ) << "Extensions: shape: 0x" << QString::number( shape_version, 16 )
149
<< " composite: 0x" << QString::number( composite_version, 16 )
150
<< " render: 0x" << QString::number( render_version, 16 )
151
<< " fixes: 0x" << QString::number( fixes_version, 16 ) << endl;
154
int Extensions::shapeNotifyEvent()
156
return shape_event_base + ShapeNotify;
159
// does the window w need a shape combine mask around it?
160
bool Extensions::hasShape( Window w )
162
int xws, yws, xbs, ybs;
163
unsigned int wws, hws, wbs, hbs;
164
int boundingShaped = 0, clipShaped = 0;
165
if( !shapeAvailable())
167
XShapeQueryExtents(display(), w,
168
&boundingShaped, &xws, &yws, &wws, &hws,
169
&clipShaped, &xbs, &ybs, &wbs, &hbs);
170
return boundingShaped != 0;
173
bool Extensions::shapeInputAvailable()
175
return shape_version >= 0x11; // 1.1
178
int Extensions::randrNotifyEvent()
181
return randr_event_base + RRScreenChangeNotify;
187
int Extensions::damageNotifyEvent()
190
return damage_event_base + XDamageNotify;
196
bool Extensions::compositeOverlayAvailable()
198
return composite_version >= 0x03; // 0.3
201
bool Extensions::fixesRegionAvailable()
203
return fixes_version >= 0x30; // 3
206
int Extensions::syncAlarmNotifyEvent()
209
return sync_event_base + XSyncAlarmNotify;
215
void Motif::readFlags( WId w, bool& noborder, bool& resize, bool& move,
216
bool& minimize, bool& maximize, bool& close )
220
unsigned long length, after;
223
if ( XGetWindowProperty( display(), w, atoms->motif_wm_hints, 0, 5,
224
false, atoms->motif_wm_hints, &type, &format,
225
&length, &after, &data ) == Success )
228
hints = (MwmHints*) data;
238
// To quote from Metacity 'We support those MWM hints deemed non-stupid'
239
if ( hints->flags & MWM_HINTS_FUNCTIONS )
241
// if MWM_FUNC_ALL is set, other flags say what to turn _off_
242
bool set_value = (( hints->functions & MWM_FUNC_ALL ) == 0 );
243
resize = move = minimize = maximize = close = !set_value;
244
if( hints->functions & MWM_FUNC_RESIZE )
246
if( hints->functions & MWM_FUNC_MOVE )
248
if( hints->functions & MWM_FUNC_MINIMIZE )
249
minimize = set_value;
250
if( hints->functions & MWM_FUNC_MAXIMIZE )
251
maximize = set_value;
252
if( hints->functions & MWM_FUNC_CLOSE )
255
if ( hints->flags & MWM_HINTS_DECORATIONS )
257
if ( hints->decorations == 0 )
264
//************************************
265
// KWinSelectionOwner
266
//************************************
268
KWinSelectionOwner::KWinSelectionOwner( int screen_P )
269
: KSelectionOwner( make_selection_atom( screen_P ), screen_P )
273
Atom KWinSelectionOwner::make_selection_atom( int screen_P )
276
screen_P = DefaultScreen( display());
278
sprintf( tmp, "WM_S%d", screen_P );
279
return XInternAtom( display(), tmp, False );
282
void KWinSelectionOwner::getAtoms()
284
KSelectionOwner::getAtoms();
285
if( xa_version == None )
288
const char* const names[] =
290
XInternAtoms( display(), const_cast< char** >( names ), 1, False, atoms );
291
xa_version = atoms[ 0 ];
295
void KWinSelectionOwner::replyTargets( Atom property_P, Window requestor_P )
297
KSelectionOwner::replyTargets( property_P, requestor_P );
298
Atom atoms[ 1 ] = { xa_version };
300
XChangeProperty( display(), requestor_P, property_P, XA_ATOM, 32, PropModeAppend,
301
reinterpret_cast< unsigned char* >( atoms ), 1 );
304
bool KWinSelectionOwner::genericReply( Atom target_P, Atom property_P, Window requestor_P )
306
if( target_P == xa_version )
308
long version[] = { 2, 0 };
309
XChangeProperty( display(), requestor_P, property_P, XA_INTEGER, 32,
310
PropModeReplace, reinterpret_cast< unsigned char* >( &version ), 2 );
313
return KSelectionOwner::genericReply( target_P, property_P, requestor_P );
317
Atom KWinSelectionOwner::xa_version = None;
320
QByteArray getStringProperty(WId w, Atom prop, char separator)
324
unsigned long nitems = 0;
325
unsigned long extra = 0;
326
unsigned char *data = 0;
327
QByteArray result = "";
328
KXErrorHandler handler; // ignore errors
329
status = XGetWindowProperty( display(), w, prop, 0, 10000,
330
false, XA_STRING, &type, &format,
331
&nitems, &extra, &data );
332
if ( status == Success)
334
if (data && separator)
336
for (int i=0; i<(int)nitems; i++)
337
if (!data[i] && i+1<(int)nitems)
341
result = (const char*) data;
347
static Time next_x_time;
348
static Bool update_x_time_predicate( Display*, XEvent* event, XPointer )
350
if( next_x_time != CurrentTime )
352
// from qapplication_x11.cpp
353
switch ( event->type ) {
355
// fallthrough intended
357
next_x_time = event->xbutton.time;
360
next_x_time = event->xmotion.time;
363
// fallthrough intended
365
next_x_time = event->xkey.time;
368
next_x_time = event->xproperty.time;
372
next_x_time = event->xcrossing.time;
375
next_x_time = event->xselectionclear.time;
384
Updates xTime(). This used to simply fetch current timestamp from the server,
385
but that can cause xTime() to be newer than timestamp of events that are
386
still in our events queue, thus e.g. making XSetInputFocus() caused by such
387
event to be ignored. Therefore events queue is searched for first
388
event with timestamp, and extra PropertyNotify is generated in order to make
389
sure such event is found.
393
static QWidget* w = 0;
397
XChangeProperty(display(), w->winId(), atoms->kwin_running, atoms->kwin_running, 32,
398
PropModeAppend, (unsigned char*) &data, 1);
399
next_x_time = CurrentTime;
401
XCheckIfEvent( display(), &dummy, update_x_time_predicate, NULL );
402
if( next_x_time == CurrentTime )
404
XSync( display(), False );
405
XCheckIfEvent( display(), &dummy, update_x_time_predicate, NULL );
407
assert( next_x_time != CurrentTime );
408
QX11Info::setAppTime( next_x_time );
409
XEvent ev; // remove the PropertyNotify event from the events queue
410
XWindowEvent( display(), w->winId(), PropertyChangeMask, &ev );
413
static int server_grab_count = 0;
417
if( ++server_grab_count == 1 )
418
XGrabServer( display());
423
assert( server_grab_count > 0 );
424
if( --server_grab_count == 0 )
426
XUngrabServer( display());
428
Notify::sendPendingEvents();
432
bool grabbedXServer()
434
return server_grab_count > 0;
437
static bool keyboard_grabbed = false;
439
bool grabXKeyboard( Window w )
441
if( QWidget::keyboardGrabber() != NULL )
443
if( keyboard_grabbed )
445
if( qApp->activePopupWidget() != NULL )
449
if( XGrabKeyboard( display(), w, False,
450
GrabModeAsync, GrabModeAsync, xTime()) != GrabSuccess )
452
keyboard_grabbed = true;
456
void ungrabXKeyboard()
458
assert( keyboard_grabbed );
459
keyboard_grabbed = false;
460
XUngrabKeyboard( display(), xTime());
465
return Workspace::self()->cursorPos();
468
// converting between X11 mouse/keyboard state mask and Qt button/keyboard states
470
int qtToX11Button( Qt::MouseButton button )
472
if( button == Qt::LeftButton )
474
else if( button == Qt::MidButton )
476
else if( button == Qt::RightButton )
478
return AnyButton; // 0
481
Qt::MouseButton x11ToQtMouseButton( int button )
483
if( button == Button1 )
484
return Qt::LeftButton;
485
if( button == Button2 )
486
return Qt::MidButton;
487
if( button == Button3 )
488
return Qt::RightButton;
492
int qtToX11State( Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers )
495
if( buttons & Qt::LeftButton )
497
if( buttons & Qt::MidButton )
499
if( buttons & Qt::RightButton )
501
if( modifiers & Qt::ShiftModifier )
503
if( modifiers & Qt::ControlModifier )
505
if( modifiers & Qt::AltModifier )
506
ret |= KKeyServer::modXAlt();
507
if( modifiers & Qt::MetaModifier )
508
ret |= KKeyServer::modXMeta();
512
Qt::MouseButtons x11ToQtMouseButtons( int state )
514
Qt::MouseButtons ret = 0;
515
if( state & Button1Mask )
516
ret |= Qt::LeftButton;
517
if( state & Button2Mask )
518
ret |= Qt::MidButton;
519
if( state & Button3Mask )
520
ret |= Qt::RightButton;
524
Qt::KeyboardModifiers x11ToQtKeyboardModifiers( int state )
526
Qt::KeyboardModifiers ret = 0;
527
if( state & ShiftMask )
528
ret |= Qt::ShiftModifier;
529
if( state & ControlMask )
530
ret |= Qt::ControlModifier;
531
if( state & KKeyServer::modXAlt())
532
ret |= Qt::AltModifier;
533
if( state & KKeyServer::modXMeta())
534
ret |= Qt::MetaModifier;
540
bool isLocalMachine( const QByteArray& host )
543
char hostnamebuf[HOST_NAME_MAX];
545
char hostnamebuf[256];
547
if (gethostname (hostnamebuf, sizeof hostnamebuf) >= 0)
549
hostnamebuf[sizeof(hostnamebuf)-1] = 0;
550
if (host == hostnamebuf)
552
if( char *dot = strchr(hostnamebuf, '.'))
555
if( host == hostnamebuf )
564
#warning KShortcutDialog is gone
567
ShortcutDialog::ShortcutDialog( const KShortcut& cut )
568
: KShortcutDialog( cut, false /*TODO: ???*/ )
570
// make it a popup, so that it has the grab
571
XSetWindowAttributes attrs;
572
attrs.override_redirect = True;
573
XChangeWindowAttributes( display(), winId(), CWOverrideRedirect, &attrs );
574
setWindowFlags( Qt::Popup );
577
void ShortcutDialog::accept()
579
foreach( const QKeySequence &seq, shortcut() )
583
if( seq[0] == Qt::Key_Escape )
588
if( seq[0] == Qt::Key_Space )
590
setShortcut( KShortcut());
591
KShortcutDialog::accept();
594
if( (seq[0] & Qt::KeyboardModifierMask) == 0 )
595
{ // no shortcuts without modifiers
596
KShortcut cut = shortcut();
602
KShortcutDialog::accept();