31 #ifdef HAVE_SYS_TYPES_H
32 #include <sys/types.h>
35 #ifdef HAVE_SYS_TIME_H
44 #ifdef Q_WS_X11 // FIXME(E)
46 #include "kmanagerselection.h"
50 #include <kapplication.h>
51 #include <kxerrorhandler.h>
52 #include <X11/Xatom.h>
54 class KSelectionOwnerPrivate
58 KSelectionOwnerPrivate( KSelectionOwner* owner );
60 virtual bool x11Event( XEvent* ev );
62 KSelectionOwner* owner;
65 KSelectionOwnerPrivate::KSelectionOwnerPrivate( KSelectionOwner* owner_P )
68 kapp->installX11EventFilter( TQT_TQWIDGET(
this) );
71 bool KSelectionOwnerPrivate::x11Event( XEvent* ev_P )
73 return owner->filterEvent( ev_P );
76 KSelectionOwner::KSelectionOwner( Atom selection_P,
int screen_P, TQObject* parent_P )
77 : TQObject( parent_P ),
78 selection( selection_P ),
79 screen( screen_P >= 0 ? screen_P : DefaultScreen( qt_xdisplay())),
81 timestamp( CurrentTime ),
82 extra1( 0 ), extra2( 0 ),
83 d( new KSelectionOwnerPrivate( this ))
87 KSelectionOwner::KSelectionOwner(
const char* selection_P,
int screen_P, TQObject* parent_P )
88 : TQObject( parent_P ),
89 selection( XInternAtom( qt_xdisplay(), selection_P, False )),
90 screen( screen_P >= 0 ? screen_P : DefaultScreen( qt_xdisplay())),
92 timestamp( CurrentTime ),
93 extra1( 0 ), extra2( 0 ),
94 d( new KSelectionOwnerPrivate( this ))
98 KSelectionOwner::~KSelectionOwner()
104 bool KSelectionOwner::claim(
bool force_P,
bool force_kill_P )
106 if( manager_atom == None )
108 if( timestamp != CurrentTime )
110 Display*
const dpy = qt_xdisplay();
111 Window prev_owner = XGetSelectionOwner( dpy, selection );
112 if( prev_owner != None )
119 XSelectInput( dpy, prev_owner, StructureNotifyMask );
121 XSetWindowAttributes attrs;
122 attrs.override_redirect = True;
123 window = XCreateWindow( dpy, RootWindow( dpy, screen ), 0, 0, 1, 1,
124 0, CopyFromParent, InputOnly, CopyFromParent, CWOverrideRedirect, &attrs );
127 XSelectInput( dpy, window, PropertyChangeMask );
128 XChangeProperty( dpy, window, XA_ATOM, XA_ATOM, 32, PropModeReplace,
129 reinterpret_cast< unsigned char* >( &tmp ), 1 );
132 XCheckTypedWindowEvent( dpy, window, PropertyNotify, &ev );
133 timestamp = ev.xproperty.time;
134 XSelectInput( dpy, window, StructureNotifyMask );
135 XSetSelectionOwner( dpy, selection, window, timestamp );
136 Window new_owner = XGetSelectionOwner( dpy, selection );
137 if( new_owner != window )
140 XDestroyWindow( dpy, window );
141 timestamp = CurrentTime;
144 if( prev_owner != None )
151 if( XCheckTypedWindowEvent( dpy, prev_owner, DestroyNotify, &ev ) == True )
153 struct timeval tm = { 0, 50000 };
154 select( 0, NULL, NULL, NULL, &tm );
160 XKillClient( dpy, prev_owner );
166 ev.type = ClientMessage;
167 ev.xclient.window = RootWindow( dpy, screen );
168 ev.xclient.display = dpy;
169 ev.xclient.message_type = manager_atom;
170 ev.xclient.format = 32;
171 ev.xclient.data.l[ 0 ] = timestamp;
172 ev.xclient.data.l[ 1 ] = selection;
173 ev.xclient.data.l[ 2 ] = window;
174 ev.xclient.data.l[ 3 ] = extra1;
175 ev.xclient.data.l[ 4 ] = extra2;
176 XSendEvent( dpy, RootWindow( dpy, screen ), False, StructureNotifyMask, &ev );
182 void KSelectionOwner::release()
184 if( timestamp == CurrentTime )
186 XDestroyWindow( qt_xdisplay(), window );
188 timestamp = CurrentTime;
191 Window KSelectionOwner::ownerWindow()
const
193 if( timestamp == CurrentTime )
198 void KSelectionOwner::setData(
long extra1_P,
long extra2_P )
204 bool KSelectionOwner::filterEvent( XEvent* ev_P )
206 if( timestamp != CurrentTime && ev_P->xany.window == window )
208 if( handleMessage( ev_P ))
215 if( timestamp == CurrentTime || ev_P->xselectionclear.selection != selection )
217 timestamp = CurrentTime;
219 emit lostOwnership();
220 XSelectInput( qt_xdisplay(), window, 0 );
221 XDestroyWindow( qt_xdisplay(), window );
226 if( timestamp == CurrentTime || ev_P->xdestroywindow.window != window )
228 timestamp = CurrentTime;
230 emit lostOwnership();
233 case SelectionNotify:
235 if( timestamp == CurrentTime || ev_P->xselection.selection != selection )
240 case SelectionRequest:
241 filter_selection_request( ev_P->xselectionrequest );
247 bool KSelectionOwner::handleMessage( XEvent* )
252 void KSelectionOwner::filter_selection_request( XSelectionRequestEvent& ev_P )
254 if( timestamp == CurrentTime || ev_P.selection != selection )
256 if( ev_P.time != CurrentTime
257 && ev_P.time - timestamp > 1U << 31 )
260 bool handled =
false;
261 if( ev_P.target == xa_multiple )
263 if( ev_P.property != None )
265 const int MAX_ATOMS = 100;
271 if( XGetWindowProperty( qt_xdisplay(), ev_P.requestor, ev_P.property, 0,
272 MAX_ATOMS, False, AnyPropertyType, &type, &format, &items, &after,
273 &data ) == Success && format == 32 && items % 2 == 0 )
275 bool handled_array[ MAX_ATOMS ];
276 Atom* atoms =
reinterpret_cast< Atom*
>( data );
277 for(
unsigned int i = 0;
280 handled_array[ i ] = handle_selection(
281 atoms[ i * 2 ], atoms[ i * 2 + 1 ], ev_P.requestor );
282 bool all_handled =
true;
283 for(
unsigned int i = 0;
286 if( !handled_array[ i ] )
289 atoms[ i * 2 + 1 ] = None;
292 XChangeProperty( qt_xdisplay(), ev_P.requestor, ev_P.property, XA_ATOM,
293 32, PropModeReplace, reinterpret_cast< unsigned char* >( atoms ), items );
301 if( ev_P.property == None )
302 ev_P.property = ev_P.target;
303 handled = handle_selection( ev_P.target, ev_P.property, ev_P.requestor );
306 ev.xselection.type = SelectionNotify;
307 ev.xselection.display = qt_xdisplay();
308 ev.xselection.requestor = ev_P.requestor;
309 ev.xselection.target = ev_P.target;
310 ev.xselection.property = handled ? ev_P.property : None;
311 XSendEvent( qt_xdisplay(), ev_P.requestor, False, 0, &ev );
314 bool KSelectionOwner::handle_selection( Atom target_P, Atom property_P, Window requestor_P )
316 if( target_P == xa_timestamp )
319 XChangeProperty( qt_xdisplay(), requestor_P, property_P, XA_INTEGER, 32,
320 PropModeReplace, reinterpret_cast< unsigned char* >( ×tamp ), 1 );
322 else if( target_P == xa_targets )
323 replyTargets( property_P, requestor_P );
324 else if( genericReply( target_P, property_P, requestor_P ))
331 void KSelectionOwner::replyTargets( Atom property_P, Window requestor_P )
333 Atom atoms[ 3 ] = { xa_multiple, xa_timestamp, xa_targets };
335 XChangeProperty( qt_xdisplay(), requestor_P, property_P, XA_ATOM, 32, PropModeReplace,
336 reinterpret_cast< unsigned char* >( atoms ), 3 );
339 bool KSelectionOwner::genericReply( Atom, Atom, Window )
344 void KSelectionOwner::getAtoms()
346 if( manager_atom == None )
349 const char*
const names[] =
350 {
"MANAGER",
"MULTIPLE",
"TARGETS",
"TIMESTAMP" };
351 XInternAtoms( qt_xdisplay(), const_cast< char** >( names ), 4, False, atoms );
352 manager_atom = atoms[ 0 ];
353 xa_multiple = atoms[ 1];
354 xa_targets = atoms[ 2 ];
355 xa_timestamp = atoms[ 3 ];
359 Atom KSelectionOwner::manager_atom = None;
360 Atom KSelectionOwner::xa_multiple = None;
361 Atom KSelectionOwner::xa_targets = None;
362 Atom KSelectionOwner::xa_timestamp = None;
369 class KSelectionWatcherPrivate
373 KSelectionWatcherPrivate( KSelectionWatcher* watcher );
375 virtual bool x11Event( XEvent* ev );
377 KSelectionWatcher* watcher;
380 KSelectionWatcherPrivate::KSelectionWatcherPrivate( KSelectionWatcher* watcher_P )
381 : watcher( watcher_P )
383 kapp->installX11EventFilter( TQT_TQWIDGET(
this) );
386 bool KSelectionWatcherPrivate::x11Event( XEvent* ev_P )
388 watcher->filterEvent( ev_P );
393 KSelectionWatcher::KSelectionWatcher( Atom selection_P,
int screen_P, TQObject* parent_P )
394 : TQObject( parent_P ),
395 selection( selection_P ),
396 screen( screen_P >= 0 ? screen_P : DefaultScreen( qt_xdisplay())),
397 selection_owner( None ),
398 d( new KSelectionWatcherPrivate( this ))
403 KSelectionWatcher::KSelectionWatcher(
const char* selection_P,
int screen_P, TQObject* parent_P )
404 : TQObject( parent_P ),
405 selection( XInternAtom( qt_xdisplay(), selection_P, False )),
406 screen( screen_P >= 0 ? screen_P : DefaultScreen( qt_xdisplay())),
407 selection_owner( None ),
408 d( new KSelectionWatcherPrivate( this ))
413 KSelectionWatcher::~KSelectionWatcher()
418 void KSelectionWatcher::init()
420 if( manager_atom == None )
422 Display*
const dpy = qt_xdisplay();
423 manager_atom = XInternAtom( dpy,
"MANAGER", False );
424 XWindowAttributes attrs;
425 XGetWindowAttributes( dpy, RootWindow( dpy, screen ), &attrs );
426 long event_mask = attrs.your_event_mask;
428 XSelectInput( dpy, RootWindow( dpy, screen ), event_mask | StructureNotifyMask );
432 Window KSelectionWatcher::owner()
434 Display*
const dpy = qt_xdisplay();
436 Window current_owner = XGetSelectionOwner( dpy, selection );
437 if( current_owner == None )
439 if( current_owner == selection_owner )
440 return selection_owner;
441 XSelectInput( dpy, current_owner, StructureNotifyMask );
442 if( !handler.
error(
true ) && current_owner == XGetSelectionOwner( dpy, selection ))
445 selection_owner = current_owner;
446 emit newOwner( selection_owner );
449 selection_owner = None;
450 return selection_owner;
454 void KSelectionWatcher::filterEvent( XEvent* ev_P )
456 if( ev_P->type == ClientMessage )
459 if( ev_P->xclient.message_type != manager_atom
460 || ev_P->xclient.data.l[ 1 ] != static_cast< long >( selection ))
463 if( static_cast< long >( owner()) == ev_P->xclient.data.l[ 2 ] )
469 if( ev_P->type == DestroyNotify )
471 if( selection_owner == None || ev_P->xdestroywindow.window != selection_owner )
473 selection_owner = None;
474 if( owner() == None )
481 Atom KSelectionWatcher::manager_atom = None;
483 void KSelectionOwner::virtual_hook(
int,
void* )
486 void KSelectionWatcher::virtual_hook(
int,
void* )
489 #include "kmanagerselection.moc"
bool error(bool sync) const
This function returns true if the error flag is set (i.e.
This class simplifies handling of X errors.