4 * Copyright 1993 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define COM_NO_WINDOWS_H
25 #include <X11/Xatom.h>
26 #include <X11/keysym.h>
29 #include <X11/Xresource.h>
30 #include <X11/Xutil.h>
31 #ifdef HAVE_LIBXXF86DGA2
32 #include <X11/extensions/xf86dga.h>
38 #include "wine/winuser16.h"
43 #include "shlobj.h" /* DROPFILES */
45 #include "clipboard.h"
51 #include "wine/debug.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(event);
54 WINE_DECLARE_DEBUG_CHANNEL(clipboard);
56 /* X context to associate a hwnd to an X window */
57 extern XContext winContext;
59 extern Atom wmProtocols;
60 extern Atom wmDeleteWindow;
61 extern Atom dndProtocol;
62 extern Atom dndSelection;
63 extern Atom netwmPing;
65 #define DndNotDnd -1 /* OffiX drag&drop */
77 #define DndURL 128 /* KDE drag&drop */
79 static const char * const event_names[] =
81 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
82 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
83 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
84 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
85 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
86 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
87 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
88 "ClientMessage", "MappingNotify"
92 static void EVENT_ProcessEvent( XEvent *event );
95 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
96 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
97 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
98 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
99 static void EVENT_PropertyNotify( XPropertyEvent *event );
100 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
102 extern void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event );
103 extern void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event );
104 extern void X11DRV_MotionNotify( HWND hwnd, XMotionEvent *event );
105 extern void X11DRV_EnterNotify( HWND hwnd, XCrossingEvent *event );
106 extern void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event );
107 extern void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event );
108 extern void X11DRV_Expose( HWND hwnd, XExposeEvent *event );
109 extern void X11DRV_MapNotify( HWND hwnd, XMapEvent *event );
110 extern void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event );
111 extern void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
112 extern void X11DRV_MappingNotify( XMappingEvent *event );
114 #ifdef HAVE_LIBXXF86DGA2
115 static int DGAMotionEventType;
116 static int DGAButtonPressEventType;
117 static int DGAButtonReleaseEventType;
118 static int DGAKeyPressEventType;
119 static int DGAKeyReleaseEventType;
121 static BOOL DGAUsed = FALSE;
122 static HWND DGAhwnd = 0;
124 extern void X11DRV_DGAMotionEvent( HWND hwnd, XDGAMotionEvent *event );
125 extern void X11DRV_DGAButtonPressEvent( HWND hwnd, XDGAButtonEvent *event );
126 extern void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XDGAButtonEvent *event );
129 /* Static used for the current input method */
130 static INPUT_TYPE current_input_type = X11DRV_INPUT_ABSOLUTE;
131 static BOOL in_transition = FALSE; /* This is not used as for today */
134 /***********************************************************************
137 static int process_events( struct x11drv_thread_data *data )
143 while ( XPending( data->display ) )
147 XNextEvent( data->display, &event );
148 ignore = XFilterEvent( &event, None );
150 if (!ignore) EVENT_ProcessEvent( &event );
159 /***********************************************************************
160 * MsgWaitForMultipleObjectsEx (X11DRV.@)
162 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
163 DWORD timeout, DWORD mask, DWORD flags )
165 HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1]; /* FIXME! */
167 struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
169 if (!data || data->process_event_count)
170 return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
171 timeout, flags & MWMO_ALERTABLE );
173 /* check whether only server queue handle was passed in */
174 if (count < 2) flags &= ~MWMO_WAITALL;
176 for (i = 0; i < count; i++) new_handles[i] = handles[i];
177 new_handles[count] = data->display_fd;
180 XFlush( gdi_display );
181 XFlush( data->display );
184 data->process_event_count++;
185 if (process_events( data )) ret = count;
188 ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
189 timeout, flags & MWMO_ALERTABLE );
190 if (ret == count) process_events( data );
192 data->process_event_count--;
197 /***********************************************************************
200 * Process an X event.
202 static void EVENT_ProcessEvent( XEvent *event )
205 Display *display = event->xany.display;
207 TRACE( "called.\n" );
211 case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
212 FIXME("Got SelectionNotify - must not happen!\n");
215 /* We get all these because of StructureNotifyMask.
216 This check is placed here to avoid getting error messages below,
217 as X might send some of these even for windows that have already
219 case CirculateNotify:
227 #ifdef HAVE_LIBXXF86DGA2
229 if (event->type == DGAMotionEventType) {
230 TRACE("DGAMotionEvent received.\n");
231 X11DRV_DGAMotionEvent( DGAhwnd, (XDGAMotionEvent *)event );
234 if (event->type == DGAButtonPressEventType) {
235 TRACE("DGAButtonPressEvent received.\n");
236 X11DRV_DGAButtonPressEvent( DGAhwnd, (XDGAButtonEvent *)event );
239 if (event->type == DGAButtonReleaseEventType) {
240 TRACE("DGAButtonReleaseEvent received.\n");
241 X11DRV_DGAButtonReleaseEvent( DGAhwnd, (XDGAButtonEvent *)event );
244 if ((event->type == DGAKeyPressEventType) ||
245 (event->type == DGAKeyReleaseEventType)) {
246 /* Fill a XKeyEvent to send to EVENT_Key */
248 XDGAKeyEvent *evt = (XDGAKeyEvent *) event;
250 TRACE("DGAKeyPress/ReleaseEvent received.\n");
252 if (evt->type == DGAKeyReleaseEventType)
253 ke.type = KeyRelease;
256 ke.serial = evt->serial;
257 ke.send_event = FALSE;
258 ke.display = evt->display;
267 ke.state = evt->state;
268 ke.keycode = evt->keycode;
269 ke.same_screen = TRUE;
270 X11DRV_KeyEvent( 0, &ke );
277 if (XFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
278 hWnd = 0; /* Not for a registered window */
280 if (!hWnd && event->xany.window == root_window) hWnd = GetDesktopWindow();
282 if (!hWnd && event->type != PropertyNotify && event->type != MappingNotify)
283 WARN( "Got event %s for unknown Window %08lx\n",
284 event_names[event->type], event->xany.window );
286 TRACE("Got event %s for hwnd %p\n",
287 event_names[event->type], hWnd );
293 /* FIXME: should generate a motion event if event point is different from current pos */
294 X11DRV_KeyEvent( hWnd, (XKeyEvent*)event );
298 X11DRV_ButtonPress( hWnd, (XButtonEvent*)event );
302 X11DRV_ButtonRelease( hWnd, (XButtonEvent*)event );
306 X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
310 X11DRV_EnterNotify( hWnd, (XCrossingEvent*)event );
314 EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
318 EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
322 X11DRV_Expose( hWnd, &event->xexpose );
325 case ConfigureNotify:
327 X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
330 case SelectionRequest:
332 EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
337 EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
341 EVENT_PropertyNotify( (XPropertyEvent *)event );
346 EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
353 X11DRV_MapNotify( hWnd, (XMapEvent *)event );
357 X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
361 X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
365 X11DRV_MappingNotify( (XMappingEvent *) event );
369 WARN("Unprocessed event %s for hwnd %p\n", event_names[event->type], hWnd );
372 TRACE( "returns.\n" );
376 /*******************************************************************
377 * can_activate_window
379 * Check if we can activate the specified window.
381 inline static BOOL can_activate_window( HWND hwnd )
383 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
384 if (!(style & WS_VISIBLE)) return FALSE;
385 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
386 return !(style & WS_DISABLED);
390 /**********************************************************************
391 * set_focus_error_handler
393 * Handler for X errors happening during XSetInputFocus call.
395 static int set_focus_error_handler( Display *display, XErrorEvent *event, void *arg )
397 return (event->error_code == BadMatch);
401 /**********************************************************************
404 static void set_focus( HWND hwnd, Time time )
409 TRACE( "setting foreground window to %p\n", hwnd );
410 SetForegroundWindow( hwnd );
413 if (focus) focus = GetAncestor( focus, GA_ROOT );
414 win = X11DRV_get_whole_window(focus);
418 Display *display = thread_display();
419 TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time );
420 X11DRV_expect_error( display, set_focus_error_handler, NULL );
421 XSetInputFocus( display, win, RevertToParent, time );
422 if (X11DRV_check_error()) TRACE("got BadMatch, ignoring\n" );
427 /**********************************************************************
428 * handle_wm_protocols_message
430 static void handle_wm_protocols_message( HWND hwnd, XClientMessageEvent *event )
432 Atom protocol = (Atom)event->data.l[0];
434 if (!protocol) return;
436 if (protocol == wmDeleteWindow)
438 /* Ignore the delete window request if the window has been disabled
439 * and we are in managed mode. This is to disallow applications from
440 * being closed by the window manager while in a modal state.
442 if (IsWindowEnabled(hwnd)) PostMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
444 else if (protocol == wmTakeFocus)
446 Time event_time = (Time)event->data.l[1];
447 HWND last_focus = x11drv_thread_data()->last_focus;
449 TRACE( "got take focus msg for %p, enabled=%d, focus=%p, active=%p, fg=%p, last=%p\n",
450 hwnd, IsWindowEnabled(hwnd), GetFocus(), GetActiveWindow(),
451 GetForegroundWindow(), last_focus );
453 if (can_activate_window(hwnd))
455 /* simulate a mouse click on the caption to find out
456 * whether the window wants to be activated */
457 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
458 (WPARAM)GetAncestor( hwnd, GA_ROOT ),
459 MAKELONG(HTCAPTION,WM_LBUTTONDOWN) );
460 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) set_focus( hwnd, event_time );
461 else TRACE( "not setting focus to %p (%lx), ma=%ld\n", hwnd, event->window, ma );
466 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
467 if (!hwnd) hwnd = GetActiveWindow();
468 if (!hwnd) hwnd = last_focus;
469 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
471 } else if (protocol == netwmPing) {
472 XClientMessageEvent xev;
475 TRACE("NET_WM Ping\n");
476 xev.window = DefaultRootWindow(xev.display);
477 XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
478 /* this line is semi-stolen from gtk2 */
479 TRACE("NET_WM Pong\n");
484 static const char * const focus_details[] =
490 "NotifyNonlinearVirtual",
496 /**********************************************************************
499 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
505 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
507 if (event->detail == NotifyPointer) return;
509 if ((xic = X11DRV_get_ic( hwnd )))
515 if (wmTakeFocus) return; /* ignore FocusIn if we are using take focus */
517 if (!can_activate_window(hwnd))
519 HWND hwnd = GetFocus();
520 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
521 if (!hwnd) hwnd = GetActiveWindow();
522 if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
523 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
525 else SetForegroundWindow( hwnd );
529 /**********************************************************************
532 * Note: only top-level windows get FocusOut events.
534 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
541 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
543 if (event->detail == NotifyPointer) return;
544 x11drv_thread_data()->last_focus = hwnd;
545 if ((xic = X11DRV_get_ic( hwnd )))
548 XUnsetICFocus( xic );
551 if (hwnd != GetForegroundWindow()) return;
552 SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
554 /* don't reset the foreground window, if the window which is
555 getting the focus is a Wine window */
558 XGetInputFocus( thread_display(), &focus_win, &revert );
561 if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
568 /* Abey : 6-Oct-99. Check again if the focus out window is the
569 Foreground window, because in most cases the messages sent
570 above must have already changed the foreground window, in which
571 case we don't have to change the foreground window to 0 */
572 if (hwnd == GetForegroundWindow())
574 TRACE( "lost focus, setting fg to 0\n" );
575 SetForegroundWindow( 0 );
581 /***********************************************************************
582 * EVENT_SelectionRequest_AddTARGETS
583 * Utility function for EVENT_SelectionRequest_TARGETS.
585 static void EVENT_SelectionRequest_AddTARGETS(Atom* targets, unsigned long* cTargets, Atom prop)
590 /* Scan through what we have so far to avoid duplicates */
591 for (i = 0, bExists = FALSE; i < *cTargets; i++)
593 if (targets[i] == prop)
601 targets[(*cTargets)++] = prop;
605 /***********************************************************************
606 * EVENT_SelectionRequest_TARGETS
607 * Service a TARGETS selection request event
609 static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
610 Atom target, Atom rprop )
618 * Count the number of items we wish to expose as selection targets.
619 * We include the TARGETS item, and propery aliases
621 cTargets = X11DRV_CountClipboardFormats() + 1;
623 for (wFormat = 0; (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
625 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
626 if (lpFormat && X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData))
630 TRACE_(clipboard)(" found %ld formats\n", cTargets);
632 /* Allocate temp buffer */
633 targets = (Atom*)HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
637 /* Create TARGETS property list (First item in list is TARGETS itself) */
638 for (targets[0] = xaTargets, cTargets = 1, wFormat = 0;
639 (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
641 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
643 EVENT_SelectionRequest_AddTARGETS(targets, &cTargets, lpFormat->drvData);
645 /* Check if any alias should be listed */
646 alias = X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData);
648 EVENT_SelectionRequest_AddTARGETS(targets, &cTargets, alias);
651 if (TRACE_ON(clipboard))
654 for ( i = 0; i < cTargets; i++)
658 char *itemFmtName = TSXGetAtomName(display, targets[i]);
659 TRACE_(clipboard)("\tAtom# %d: Property %ld Type %s\n", i, targets[i], itemFmtName);
660 TSXFree(itemFmtName);
665 /* We may want to consider setting the type to xaTargets instead,
666 * in case some apps expect this instead of XA_ATOM */
667 TSXChangeProperty(display, requestor, rprop, XA_ATOM, 32,
668 PropModeReplace, (unsigned char *)targets, cTargets);
670 HeapFree(GetProcessHeap(), 0, targets);
676 /***********************************************************************
677 * EVENT_SelectionRequest_MULTIPLE
678 * Service a MULTIPLE selection request event
679 * rprop contains a list of (target,property) atom pairs.
680 * The first atom names a target and the second names a property.
681 * The effect is as if we have received a sequence of SelectionRequest events
682 * (one for each atom pair) except that:
683 * 1. We reply with a SelectionNotify only when all the requested conversions
684 * have been performed.
685 * 2. If we fail to convert the target named by an atom in the MULTIPLE property,
686 * we replace the atom in the property by None.
688 static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
690 Display *display = pevent->display;
692 Atom atype=AnyPropertyType;
694 unsigned long remain;
695 Atom* targetPropList=NULL;
696 unsigned long cTargetPropList = 0;
697 /* Atom xAtomPair = TSXInternAtom(display, "ATOM_PAIR", False); */
699 /* If the specified property is None the requestor is an obsolete client.
700 * We support these by using the specified target atom as the reply property.
702 rprop = pevent->property;
704 rprop = pevent->target;
708 /* Read the MULTIPLE property contents. This should contain a list of
709 * (target,property) atom pairs.
711 if(TSXGetWindowProperty(display, pevent->requestor, rprop,
712 0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
713 &cTargetPropList, &remain,
714 (unsigned char**)&targetPropList) != Success)
715 TRACE("\tCouldn't read MULTIPLE property\n");
718 TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
719 TSXGetAtomName(display, atype), aformat, cTargetPropList, remain);
722 * Make sure we got what we expect.
723 * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
724 * in a MULTIPLE selection request should be of type ATOM_PAIR.
725 * However some X apps(such as XPaint) are not compliant with this and return
726 * a user defined atom in atype when XGetWindowProperty is called.
727 * The data *is* an atom pair but is not denoted as such.
729 if(aformat == 32 /* atype == xAtomPair */ )
733 /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
734 * for each (target,property) pair */
736 for (i = 0; i < cTargetPropList; i+=2)
738 char *targetName = TSXGetAtomName(display, targetPropList[i]);
739 char *propName = TSXGetAtomName(display, targetPropList[i+1]);
740 XSelectionRequestEvent event;
742 TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
743 i/2, targetName, propName);
747 /* We must have a non "None" property to service a MULTIPLE target atom */
748 if ( !targetPropList[i+1] )
750 TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
754 /* Set up an XSelectionRequestEvent for this (target,property) pair */
755 memcpy( &event, pevent, sizeof(XSelectionRequestEvent) );
756 event.target = targetPropList[i];
757 event.property = targetPropList[i+1];
759 /* Fire a SelectionRequest, informing the handler that we are processing
760 * a MULTIPLE selection request event.
762 EVENT_SelectionRequest( hWnd, &event, TRUE );
766 /* Free the list of targets/properties */
767 TSXFree(targetPropList);
775 /***********************************************************************
776 * EVENT_SelectionRequest
777 * Process an event selection request event.
778 * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
779 * recursively while servicing a "MULTIPLE" selection target.
781 * Note: We only receive this event when WINE owns the X selection
783 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
785 Display *display = event->display;
786 XSelectionEvent result;
788 Window request = event->requestor;
790 TRACE_(clipboard)("\n");
793 * We can only handle the selection request if :
794 * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
795 * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
796 * since this has been already done.
800 if (((event->selection != XA_PRIMARY) && (event->selection != xaClipboard)))
804 /* If the specified property is None the requestor is an obsolete client.
805 * We support these by using the specified target atom as the reply property.
807 rprop = event->property;
809 rprop = event->target;
811 if(event->target == xaTargets) /* Return a list of all supported targets */
813 /* TARGETS selection request */
814 rprop = EVENT_SelectionRequest_TARGETS( display, request, event->target, rprop );
816 else if(event->target == xaMultiple) /* rprop contains a list of (target, property) atom pairs */
818 /* MULTIPLE selection request */
819 rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
823 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(event->target);
826 lpFormat = X11DRV_CLIPBOARD_LookupAliasProperty(event->target);
830 LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(lpFormat->wFormatID);
834 unsigned char* lpClipData;
836 HANDLE hClipData = lpFormat->lpDrvExportFunc(request, event->target,
837 rprop, lpData, &cBytes);
839 if (hClipData && (lpClipData = GlobalLock(hClipData)))
842 TRACE_(clipboard)("\tUpdating property %s, %ld bytes\n",
843 lpFormat->Name, cBytes);
845 TSXChangeProperty(display, request, rprop, event->target,
846 8, PropModeReplace, (unsigned char *)lpClipData, cBytes);
848 GlobalUnlock(hClipData);
849 GlobalFree(hClipData);
855 if (TRACE_ON(clipboard))
857 TRACE_(clipboard)("Request for property %s (%ld) failed\n",
858 TSXGetAtomName(display, event->target), event->target);
865 * SelectionNotify should be sent only at the end of a MULTIPLE request
869 result.type = SelectionNotify;
870 result.display = display;
871 result.requestor = request;
872 result.selection = event->selection;
873 result.property = rprop;
874 result.target = event->target;
875 result.time = event->time;
876 TRACE("Sending SelectionNotify event...\n");
877 TSXSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
881 /***********************************************************************
882 * EVENT_SelectionClear
884 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
886 if (event->selection == XA_PRIMARY || event->selection == xaClipboard)
887 X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
890 /***********************************************************************
891 * EVENT_PropertyNotify
892 * We use this to release resources like Pixmaps when a selection
893 * client no longer needs them.
895 static void EVENT_PropertyNotify( XPropertyEvent *event )
897 /* Check if we have any resources to free */
898 TRACE("Received PropertyNotify event: \n");
904 TRACE("\tPropertyDelete for atom %s on window %ld\n",
905 TSXGetAtomName(event->display, event->atom), (long)event->window);
909 case PropertyNewValue:
911 TRACE("\tPropertyNewValue for atom %s on window %ld\n\n",
912 TSXGetAtomName(event->display, event->atom), (long)event->window);
921 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
925 if (!IsWindowEnabled(hQueryWnd)) return 0;
927 GetWindowRect(hQueryWnd, &tempRect);
929 if(!PtInRect(&tempRect, *lpPt)) return 0;
931 if (!IsIconic( hQueryWnd ))
933 GetClientRect( hQueryWnd, &tempRect );
934 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
936 if (PtInRect( &tempRect, *lpPt))
938 HWND *list = WIN_ListChildren( hQueryWnd );
945 for (i = 0; list[i]; i++)
947 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
949 GetWindowRect( list[i], &tempRect );
950 if (PtInRect( &tempRect, *lpPt )) break;
955 if (IsWindowEnabled( list[i] ))
956 bResult = find_drop_window( list[i], lpPt );
958 HeapFree( GetProcessHeap(), 0, list );
960 if(bResult) return bResult;
964 if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
966 ScreenToClient(hQueryWnd, lpPt);
971 /**********************************************************************
972 * EVENT_DropFromOffix
974 * don't know if it still works (last Changlog is from 96/11/04)
976 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
978 unsigned long data_length;
979 unsigned long aux_long;
980 unsigned char* p_data = NULL;
991 Window w_aux_root, w_aux_child;
995 pWnd = WIN_FindWndPtr(hWnd);
997 TSXQueryPointer( event->display, get_whole_window(pWnd), &w_aux_root, &w_aux_child,
998 &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
999 (unsigned int*)&aux_long);
1001 /* find out drop point and drop window */
1002 if( x < 0 || y < 0 ||
1003 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1004 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1006 bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES;
1012 POINT pt = { x, y };
1013 HWND hwndDrop = find_drop_window( hWnd, &pt );
1026 WIN_ReleaseWndPtr(pWnd);
1028 if (!bAccept) return;
1030 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1031 dndSelection, 0, 65535, FALSE,
1032 AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1033 &data_length, &aux_long, &p_data);
1035 if( !aux_long && p_data) /* don't bother if > 64K */
1037 signed char *p = (signed char*) p_data;
1041 while( *p ) /* calculate buffer size */
1044 if((u.i = *p) != -1 )
1046 INT len = GetShortPathNameA( p, NULL, 0 );
1047 if (len) aux_long += len + 1;
1052 if( aux_long && aux_long < 65535 )
1057 aux_long += sizeof(DROPFILES) + 1;
1058 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
1059 lpDrop = (DROPFILES*)GlobalLock( hDrop );
1063 WND *pDropWnd = WIN_FindWndPtr( hScope );
1064 lpDrop->pFiles = sizeof(DROPFILES);
1068 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1069 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1070 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1071 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1072 lpDrop->fWide = FALSE;
1073 WIN_ReleaseWndPtr(pDropWnd);
1074 p_drop = (char *)(lpDrop + 1);
1078 if( *p != -1 ) /* use only "good" entries */
1080 GetShortPathNameA( p, p_drop, 65535 );
1081 p_drop += strlen( p_drop ) + 1;
1086 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1090 if( p_data ) TSXFree(p_data);
1093 /**********************************************************************
1096 * drop items are separated by \n
1097 * each item is prefixed by its mime type
1099 * event->data.l[3], event->data.l[4] contains drop x,y position
1101 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
1103 unsigned long data_length;
1104 unsigned long aux_long, drop_len = 0;
1105 unsigned char *p_data = NULL; /* property data */
1106 char *p_drop = NULL;
1117 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
1119 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1120 dndSelection, 0, 65535, FALSE,
1121 AnyPropertyType, &u.atom_aux, &u.i,
1122 &data_length, &aux_long, &p_data);
1124 WARN("property too large, truncated!\n");
1125 TRACE("urls=%s\n", p_data);
1127 if( !aux_long && p_data) { /* don't bother if > 64K */
1128 /* calculate length */
1130 next = strchr(p, '\n');
1133 if (strncmp(p,"file:",5) == 0 ) {
1134 INT len = GetShortPathNameA( p+5, NULL, 0 );
1135 if (len) drop_len += len + 1;
1140 next = strchr(p, '\n');
1146 if( drop_len && drop_len < 65535 ) {
1147 TSXQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
1148 &x, &y, &u.i, &u.i, &u.i);
1150 drop_len += sizeof(DROPFILES) + 1;
1151 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
1152 lpDrop = (DROPFILES *) GlobalLock( hDrop );
1155 WND *pDropWnd = WIN_FindWndPtr( hWnd );
1156 lpDrop->pFiles = sizeof(DROPFILES);
1157 lpDrop->pt.x = (INT)x;
1158 lpDrop->pt.y = (INT)y;
1160 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1161 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1162 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1163 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1164 lpDrop->fWide = FALSE;
1165 p_drop = (char*)(lpDrop + 1);
1166 WIN_ReleaseWndPtr(pDropWnd);
1169 /* create message content */
1172 next = strchr(p, '\n');
1175 if (strncmp(p,"file:",5) == 0 ) {
1176 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
1178 TRACE("drop file %s as %s\n", p+5, p_drop);
1181 WARN("can't convert file %s to dos name \n", p+5);
1184 WARN("unknown mime type %s\n", p);
1189 next = strchr(p, '\n');
1196 GlobalUnlock(hDrop);
1197 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1200 if( p_data ) TSXFree(p_data);
1204 /**********************************************************************
1205 * EVENT_ClientMessage
1207 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
1209 if (event->message_type != None && event->format == 32) {
1210 if (event->message_type == wmProtocols)
1211 handle_wm_protocols_message( hWnd, event );
1212 else if (event->message_type == dndProtocol)
1214 /* query window (drag&drop event contains only drag window) */
1216 int root_x, root_y, child_x, child_y;
1220 XQueryPointer( event->display, root_window, &root, &child,
1221 &root_x, &root_y, &child_x, &child_y, &u);
1222 if (XFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) hWnd = 0;
1223 wine_tsx11_unlock();
1225 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
1226 EVENT_DropFromOffiX(hWnd, event);
1227 else if (event->data.l[0] == DndURL)
1228 EVENT_DropURLs(hWnd, event);
1232 /* enable this if you want to see the message */
1233 unsigned char* p_data = NULL;
1239 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1240 dndSelection, 0, 65535, FALSE,
1241 AnyPropertyType, &u.atom, &u.i,
1242 &u.l, &u.l, &p_data);
1243 TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1244 event->message_type, event->data.l[0], event->data.l[1],
1245 event->data.l[2], event->data.l[3], event->data.l[4],
1248 TRACE("unrecognized ClientMessage\n" );
1254 /**********************************************************************
1255 * X11DRV_EVENT_SetInputMethod
1257 INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
1259 INPUT_TYPE prev = current_input_type;
1261 /* Flag not used yet */
1262 in_transition = FALSE;
1263 current_input_type = type;
1268 #ifdef HAVE_LIBXXF86DGA2
1269 /**********************************************************************
1270 * X11DRV_EVENT_SetDGAStatus
1272 void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
1274 if (event_base < 0) {
1280 DGAMotionEventType = event_base + MotionNotify;
1281 DGAButtonPressEventType = event_base + ButtonPress;
1282 DGAButtonReleaseEventType = event_base + ButtonRelease;
1283 DGAKeyPressEventType = event_base + KeyPress;
1284 DGAKeyReleaseEventType = event_base + KeyRelease;