31#ifdef HAVE_SYS_TYPES_H
46#include "kmanagerselection.h"
50#include <tdeapplication.h>
51#include <kxerrorhandler.h>
54class TDESelectionOwnerPrivate
58 TDESelectionOwnerPrivate( TDESelectionOwner* owner );
60 virtual bool x11Event( XEvent* ev );
62 TDESelectionOwner* owner;
65TDESelectionOwnerPrivate::TDESelectionOwnerPrivate( TDESelectionOwner* owner_P )
68 tdeApp->installX11EventFilter(
this );
71bool TDESelectionOwnerPrivate::x11Event( XEvent* ev_P )
73 return owner->filterEvent( ev_P );
76TDESelectionOwner::TDESelectionOwner( 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( tqt_xdisplay())),
81 timestamp( CurrentTime ),
82 extra1( 0 ), extra2( 0 ),
83 d( new TDESelectionOwnerPrivate( this ))
87TDESelectionOwner::TDESelectionOwner(
const char* selection_P,
int screen_P, TQObject* parent_P )
88 : TQObject( parent_P ),
89 selection( XInternAtom( tqt_xdisplay(), selection_P, False )),
90 screen( screen_P >= 0 ? screen_P : DefaultScreen( tqt_xdisplay())),
92 timestamp( CurrentTime ),
93 extra1( 0 ), extra2( 0 ),
94 d( new TDESelectionOwnerPrivate( this ))
98TDESelectionOwner::~TDESelectionOwner()
104bool TDESelectionOwner::claim(
bool force_P,
bool force_kill_P )
106 if( manager_atom == None )
108 if( timestamp != CurrentTime )
110 Display*
const dpy = tqt_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 );
182void TDESelectionOwner::release()
184 if( timestamp == CurrentTime )
186 XDestroyWindow( tqt_xdisplay(), window );
188 timestamp = CurrentTime;
191Window TDESelectionOwner::ownerWindow()
const
193 if( timestamp == CurrentTime )
198void TDESelectionOwner::setData(
long extra1_P,
long extra2_P )
204bool TDESelectionOwner::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( tqt_xdisplay(), window, 0 );
221 XDestroyWindow( tqt_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 );
247bool TDESelectionOwner::handleMessage( XEvent* )
252void TDESelectionOwner::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( tqt_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( tqt_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 = tqt_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( tqt_xdisplay(), ev_P.requestor, False, 0, &ev );
314bool TDESelectionOwner::handle_selection( Atom target_P, Atom property_P, Window requestor_P )
316 if( target_P == xa_timestamp )
319 XChangeProperty( tqt_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 ))
331void TDESelectionOwner::replyTargets( Atom property_P, Window requestor_P )
333 Atom atoms[ 3 ] = { xa_multiple, xa_timestamp, xa_targets };
335 XChangeProperty( tqt_xdisplay(), requestor_P, property_P, XA_ATOM, 32, PropModeReplace,
336 reinterpret_cast< unsigned char*
>( atoms ), 3 );
339bool TDESelectionOwner::genericReply( Atom, Atom, Window )
344void TDESelectionOwner::getAtoms()
346 if( manager_atom == None )
349 const char*
const names[] =
350 {
"MANAGER",
"MULTIPLE",
"TARGETS",
"TIMESTAMP" };
351 XInternAtoms( tqt_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 ];
359Atom TDESelectionOwner::manager_atom = None;
360Atom TDESelectionOwner::xa_multiple = None;
361Atom TDESelectionOwner::xa_targets = None;
362Atom TDESelectionOwner::xa_timestamp = None;
369class TDESelectionWatcherPrivate
373 TDESelectionWatcherPrivate( TDESelectionWatcher* watcher );
375 virtual bool x11Event( XEvent* ev );
377 TDESelectionWatcher* watcher;
380TDESelectionWatcherPrivate::TDESelectionWatcherPrivate( TDESelectionWatcher* watcher_P )
381 : watcher( watcher_P )
383 tdeApp->installX11EventFilter(
this );
386bool TDESelectionWatcherPrivate::x11Event( XEvent* ev_P )
388 watcher->filterEvent( ev_P );
393TDESelectionWatcher::TDESelectionWatcher( 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( tqt_xdisplay())),
397 selection_owner( None ),
398 d( new TDESelectionWatcherPrivate( this ))
403TDESelectionWatcher::TDESelectionWatcher(
const char* selection_P,
int screen_P, TQObject* parent_P )
404 : TQObject( parent_P ),
405 selection( XInternAtom( tqt_xdisplay(), selection_P, False )),
406 screen( screen_P >= 0 ? screen_P : DefaultScreen( tqt_xdisplay())),
407 selection_owner( None ),
408 d( new TDESelectionWatcherPrivate( this ))
413TDESelectionWatcher::~TDESelectionWatcher()
418void TDESelectionWatcher::init()
420 if( manager_atom == None )
422 Display*
const dpy = tqt_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 );
432Window TDESelectionWatcher::owner()
434 Display*
const dpy = tqt_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;
454void TDESelectionWatcher::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 )
481Atom TDESelectionWatcher::manager_atom = None;
483void TDESelectionOwner::virtual_hook(
int,
void* )
486void TDESelectionWatcher::virtual_hook(
int,
void* )
489#include "kmanagerselection.moc"
This class simplifies handling of X errors.
bool error(bool sync) const
This function returns true if the error flag is set (i.e.