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>
28 #include <X11/Xresource.h>
29 #include <X11/Xutil.h>
30 #ifdef HAVE_LIBXXF86DGA2
31 #include <X11/extensions/xf86dga.h>
37 #include "wine/winuser16.h"
42 #include "shlobj.h" /* DROPFILES */
49 #include "wine/debug.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(event);
52 WINE_DECLARE_DEBUG_CHANNEL(clipboard);
54 /* X context to associate a hwnd to an X window */
55 extern XContext winContext;
57 extern BOOL ximInComposeMode;
59 #define DndNotDnd -1 /* OffiX drag&drop */
71 #define DndURL 128 /* KDE drag&drop */
73 static const char * const event_names[] =
75 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
76 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
77 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
78 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
79 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
80 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
81 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
82 "ClientMessage", "MappingNotify"
86 static void EVENT_ProcessEvent( XEvent *event );
89 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
90 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
91 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
92 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
93 static void EVENT_PropertyNotify( XPropertyEvent *event );
94 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
96 extern void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event );
97 extern void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event );
98 extern void X11DRV_MotionNotify( HWND hwnd, XMotionEvent *event );
99 extern void X11DRV_EnterNotify( HWND hwnd, XCrossingEvent *event );
100 extern void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event );
101 extern void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event );
102 extern void X11DRV_Expose( HWND hwnd, XExposeEvent *event );
103 extern void X11DRV_MapNotify( HWND hwnd, XMapEvent *event );
104 extern void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event );
105 extern void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
106 extern void X11DRV_MappingNotify( XMappingEvent *event );
108 #ifdef HAVE_LIBXXF86DGA2
109 static int DGAMotionEventType;
110 static int DGAButtonPressEventType;
111 static int DGAButtonReleaseEventType;
112 static int DGAKeyPressEventType;
113 static int DGAKeyReleaseEventType;
115 static BOOL DGAUsed = FALSE;
116 static HWND DGAhwnd = 0;
118 extern void X11DRV_DGAMotionEvent( HWND hwnd, XDGAMotionEvent *event );
119 extern void X11DRV_DGAButtonPressEvent( HWND hwnd, XDGAButtonEvent *event );
120 extern void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XDGAButtonEvent *event );
123 /* Static used for the current input method */
124 static INPUT_TYPE current_input_type = X11DRV_INPUT_ABSOLUTE;
125 static BOOL in_transition = FALSE; /* This is not used as for today */
128 /***********************************************************************
131 static int process_events( struct x11drv_thread_data *data )
137 while ( XPending( data->display ) )
141 XNextEvent( data->display, &event );
142 ignore = XFilterEvent( &event, None );
144 if (!ignore) EVENT_ProcessEvent( &event );
153 /***********************************************************************
154 * MsgWaitForMultipleObjectsEx (X11DRV.@)
156 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
157 DWORD timeout, DWORD mask, DWORD flags )
159 HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1]; /* FIXME! */
161 struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
163 if (!data || data->process_event_count)
164 return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
165 timeout, flags & MWMO_ALERTABLE );
167 /* check whether only server queue handle was passed in */
168 if (count < 2) flags &= ~MWMO_WAITALL;
170 for (i = 0; i < count; i++) new_handles[i] = handles[i];
171 new_handles[count] = data->display_fd;
174 XFlush( gdi_display );
175 XFlush( data->display );
178 data->process_event_count++;
179 if (process_events( data )) ret = count;
182 ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
183 timeout, flags & MWMO_ALERTABLE );
184 if (ret == count) process_events( data );
186 data->process_event_count--;
191 /***********************************************************************
194 * Process an X event.
196 static void EVENT_ProcessEvent( XEvent *event )
199 Display *display = event->xany.display;
201 TRACE( "called.\n" );
205 case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
206 FIXME("Got SelectionNotify - must not happen!\n");
209 /* We get all these because of StructureNotifyMask.
210 This check is placed here to avoid getting error messages below,
211 as X might send some of these even for windows that have already
213 case CirculateNotify:
221 #ifdef HAVE_LIBXXF86DGA2
223 if (event->type == DGAMotionEventType) {
224 TRACE("DGAMotionEvent received.\n");
225 X11DRV_DGAMotionEvent( DGAhwnd, (XDGAMotionEvent *)event );
228 if (event->type == DGAButtonPressEventType) {
229 TRACE("DGAButtonPressEvent received.\n");
230 X11DRV_DGAButtonPressEvent( DGAhwnd, (XDGAButtonEvent *)event );
233 if (event->type == DGAButtonReleaseEventType) {
234 TRACE("DGAButtonReleaseEvent received.\n");
235 X11DRV_DGAButtonReleaseEvent( DGAhwnd, (XDGAButtonEvent *)event );
238 if ((event->type == DGAKeyPressEventType) ||
239 (event->type == DGAKeyReleaseEventType)) {
240 /* Fill a XKeyEvent to send to EVENT_Key */
242 XDGAKeyEvent *evt = (XDGAKeyEvent *) event;
244 TRACE("DGAKeyPress/ReleaseEvent received.\n");
246 if (evt->type == DGAKeyReleaseEventType)
247 ke.type = KeyRelease;
250 ke.serial = evt->serial;
251 ke.send_event = FALSE;
252 ke.display = evt->display;
261 ke.state = evt->state;
262 ke.keycode = evt->keycode;
263 ke.same_screen = TRUE;
264 X11DRV_KeyEvent( 0, &ke );
271 if (XFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
272 hWnd = 0; /* Not for a registered window */
274 if (!hWnd && event->xany.window == root_window) hWnd = GetDesktopWindow();
276 if (!hWnd && event->type != PropertyNotify && event->type != MappingNotify)
277 WARN( "Got event %s for unknown Window %08lx\n",
278 event_names[event->type], event->xany.window );
279 else if (event->type <= MappingNotify)
280 TRACE("Got event %s for hwnd/window %p/%lx, GetFocus()=%p\n",
281 event_names[event->type], hWnd, event->xany.window, GetFocus() );
283 TRACE("Got extension event for hwnd/window %p/%lx, GetFocus()=%p\n",
284 hWnd, event->xany.window, GetFocus() );
286 if (X11DRV_ProcessTabletEvent(hWnd, event))
288 TRACE("Return: filtered by tablet\n");
296 /* FIXME: should generate a motion event if event point is different from current pos */
297 X11DRV_KeyEvent( hWnd, (XKeyEvent*)event );
301 X11DRV_ButtonPress( hWnd, (XButtonEvent*)event );
305 X11DRV_ButtonRelease( hWnd, (XButtonEvent*)event );
309 X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
313 X11DRV_EnterNotify( hWnd, (XCrossingEvent*)event );
317 EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
321 EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
325 X11DRV_Expose( hWnd, &event->xexpose );
328 case ConfigureNotify:
330 X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
333 case SelectionRequest:
335 EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
340 EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
344 EVENT_PropertyNotify( (XPropertyEvent *)event );
349 EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
356 X11DRV_MapNotify( hWnd, (XMapEvent *)event );
360 X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
364 X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
368 X11DRV_MappingNotify( (XMappingEvent *) event );
372 WARN("Unprocessed event %s for hwnd %p\n", event_names[event->type], hWnd );
375 TRACE( "returns.\n" );
379 /*******************************************************************
380 * can_activate_window
382 * Check if we can activate the specified window.
384 inline static BOOL can_activate_window( HWND hwnd )
386 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
387 if (!(style & WS_VISIBLE)) return FALSE;
388 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
389 return !(style & WS_DISABLED);
393 /**********************************************************************
396 static void set_focus( HWND hwnd, Time time )
401 TRACE( "setting foreground window to %p\n", hwnd );
402 SetForegroundWindow( hwnd );
405 if (focus) focus = GetAncestor( focus, GA_ROOT );
406 win = X11DRV_get_whole_window(focus);
410 TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time );
412 XSetInputFocus( thread_display(), win, RevertToParent, time );
418 /**********************************************************************
419 * handle_wm_protocols_message
421 static void handle_wm_protocols_message( HWND hwnd, XClientMessageEvent *event )
423 Atom protocol = (Atom)event->data.l[0];
425 if (!protocol) return;
427 if (protocol == x11drv_atom(WM_DELETE_WINDOW))
429 /* Ignore the delete window request if the window has been disabled
430 * and we are in managed mode. This is to disallow applications from
431 * being closed by the window manager while in a modal state.
433 if (IsWindowEnabled(hwnd)) PostMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
435 else if (protocol == x11drv_atom(WM_TAKE_FOCUS))
437 Time event_time = (Time)event->data.l[1];
438 HWND last_focus = x11drv_thread_data()->last_focus;
440 TRACE( "got take focus msg for %p, enabled=%d, focus=%p, active=%p, fg=%p, last=%p\n",
441 hwnd, IsWindowEnabled(hwnd), GetFocus(), GetActiveWindow(),
442 GetForegroundWindow(), last_focus );
444 if (can_activate_window(hwnd))
446 /* simulate a mouse click on the caption to find out
447 * whether the window wants to be activated */
448 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
449 (WPARAM)GetAncestor( hwnd, GA_ROOT ),
450 MAKELONG(HTCAPTION,WM_LBUTTONDOWN) );
451 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) set_focus( hwnd, event_time );
452 else TRACE( "not setting focus to %p (%lx), ma=%ld\n", hwnd, event->window, ma );
457 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
458 if (!hwnd) hwnd = GetActiveWindow();
459 if (!hwnd) hwnd = last_focus;
460 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
463 else if (protocol == x11drv_atom(_NET_WM_PING))
465 XClientMessageEvent xev;
468 TRACE("NET_WM Ping\n");
469 xev.window = DefaultRootWindow(xev.display);
470 XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
471 /* this line is semi-stolen from gtk2 */
472 TRACE("NET_WM Pong\n");
477 static const char * const focus_details[] =
483 "NotifyNonlinearVirtual",
489 /**********************************************************************
492 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
498 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
500 if (event->detail == NotifyPointer) return;
502 if ((xic = X11DRV_get_ic( hwnd )))
508 if (use_take_focus) return; /* ignore FocusIn if we are using take focus */
510 if (!can_activate_window(hwnd))
512 HWND hwnd = GetFocus();
513 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
514 if (!hwnd) hwnd = GetActiveWindow();
515 if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
516 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
518 else SetForegroundWindow( hwnd );
522 /**********************************************************************
525 * Note: only top-level windows get FocusOut events.
527 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
534 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
536 if (event->detail == NotifyPointer) return;
537 if (ximInComposeMode) return;
539 x11drv_thread_data()->last_focus = hwnd;
540 if ((xic = X11DRV_get_ic( hwnd )))
543 XUnsetICFocus( xic );
546 if (hwnd != GetForegroundWindow()) return;
547 SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
549 /* don't reset the foreground window, if the window which is
550 getting the focus is a Wine window */
553 XGetInputFocus( thread_display(), &focus_win, &revert );
556 if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
563 /* Abey : 6-Oct-99. Check again if the focus out window is the
564 Foreground window, because in most cases the messages sent
565 above must have already changed the foreground window, in which
566 case we don't have to change the foreground window to 0 */
567 if (hwnd == GetForegroundWindow())
569 TRACE( "lost focus, setting fg to 0\n" );
570 SetForegroundWindow( 0 );
576 /***********************************************************************
577 * EVENT_SelectionRequest_AddTARGETS
578 * Utility function for EVENT_SelectionRequest_TARGETS.
580 static void EVENT_SelectionRequest_AddTARGETS(Atom* targets, unsigned long* cTargets, Atom prop)
585 /* Scan through what we have so far to avoid duplicates */
586 for (i = 0, bExists = FALSE; i < *cTargets; i++)
588 if (targets[i] == prop)
596 targets[(*cTargets)++] = prop;
600 /***********************************************************************
601 * EVENT_SelectionRequest_TARGETS
602 * Service a TARGETS selection request event
604 static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
605 Atom target, Atom rprop )
613 * Count the number of items we wish to expose as selection targets.
614 * We include the TARGETS item, and propery aliases
616 cTargets = X11DRV_CountClipboardFormats() + 1;
618 for (wFormat = 0; (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
620 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
621 if (lpFormat && X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData))
625 TRACE_(clipboard)(" found %ld formats\n", cTargets);
627 /* Allocate temp buffer */
628 targets = (Atom*)HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
632 /* Create TARGETS property list (First item in list is TARGETS itself) */
633 for (targets[0] = x11drv_atom(TARGETS), cTargets = 1, wFormat = 0;
634 (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
636 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
638 EVENT_SelectionRequest_AddTARGETS(targets, &cTargets, lpFormat->drvData);
640 /* Check if any alias should be listed */
641 alias = X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData);
643 EVENT_SelectionRequest_AddTARGETS(targets, &cTargets, alias);
648 if (TRACE_ON(clipboard))
651 for ( i = 0; i < cTargets; i++)
655 char *itemFmtName = XGetAtomName(display, targets[i]);
656 TRACE_(clipboard)("\tAtom# %d: Property %ld Type %s\n", i, targets[i], itemFmtName);
662 /* We may want to consider setting the type to xaTargets instead,
663 * in case some apps expect this instead of XA_ATOM */
664 XChangeProperty(display, requestor, rprop, XA_ATOM, 32,
665 PropModeReplace, (unsigned char *)targets, cTargets);
668 HeapFree(GetProcessHeap(), 0, targets);
674 /***********************************************************************
675 * EVENT_SelectionRequest_MULTIPLE
676 * Service a MULTIPLE selection request event
677 * rprop contains a list of (target,property) atom pairs.
678 * The first atom names a target and the second names a property.
679 * The effect is as if we have received a sequence of SelectionRequest events
680 * (one for each atom pair) except that:
681 * 1. We reply with a SelectionNotify only when all the requested conversions
682 * have been performed.
683 * 2. If we fail to convert the target named by an atom in the MULTIPLE property,
684 * we replace the atom in the property by None.
686 static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
688 Display *display = pevent->display;
690 Atom atype=AnyPropertyType;
692 unsigned long remain;
693 Atom* targetPropList=NULL;
694 unsigned long cTargetPropList = 0;
696 /* If the specified property is None the requestor is an obsolete client.
697 * We support these by using the specified target atom as the reply property.
699 rprop = pevent->property;
701 rprop = pevent->target;
705 /* Read the MULTIPLE property contents. This should contain a list of
706 * (target,property) atom pairs.
709 if(XGetWindowProperty(display, pevent->requestor, rprop,
710 0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
711 &cTargetPropList, &remain,
712 (unsigned char**)&targetPropList) != Success)
715 TRACE("\tCouldn't read MULTIPLE property\n");
719 TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
720 XGetAtomName(display, atype), aformat, cTargetPropList, remain);
724 * Make sure we got what we expect.
725 * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
726 * in a MULTIPLE selection request should be of type ATOM_PAIR.
727 * However some X apps(such as XPaint) are not compliant with this and return
728 * a user defined atom in atype when XGetWindowProperty is called.
729 * The data *is* an atom pair but is not denoted as such.
731 if(aformat == 32 /* atype == xAtomPair */ )
735 /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
736 * for each (target,property) pair */
738 for (i = 0; i < cTargetPropList; i+=2)
740 XSelectionRequestEvent event;
744 char *targetName, *propName;
746 targetName = XGetAtomName(display, targetPropList[i]);
747 propName = XGetAtomName(display, targetPropList[i+1]);
748 TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
749 i/2, targetName, propName);
755 /* We must have a non "None" property to service a MULTIPLE target atom */
756 if ( !targetPropList[i+1] )
758 TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
762 /* Set up an XSelectionRequestEvent for this (target,property) pair */
763 memcpy( &event, pevent, sizeof(XSelectionRequestEvent) );
764 event.target = targetPropList[i];
765 event.property = targetPropList[i+1];
767 /* Fire a SelectionRequest, informing the handler that we are processing
768 * a MULTIPLE selection request event.
770 EVENT_SelectionRequest( hWnd, &event, TRUE );
774 /* Free the list of targets/properties */
776 XFree(targetPropList);
785 /***********************************************************************
786 * EVENT_SelectionRequest
787 * Process an event selection request event.
788 * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
789 * recursively while servicing a "MULTIPLE" selection target.
791 * Note: We only receive this event when WINE owns the X selection
793 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
795 Display *display = event->display;
796 XSelectionEvent result;
798 Window request = event->requestor;
800 TRACE_(clipboard)("\n");
803 * We can only handle the selection request if :
804 * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
805 * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
806 * since this has been already done.
810 if (((event->selection != XA_PRIMARY) && (event->selection != x11drv_atom(CLIPBOARD))))
814 /* If the specified property is None the requestor is an obsolete client.
815 * We support these by using the specified target atom as the reply property.
817 rprop = event->property;
819 rprop = event->target;
821 if(event->target == x11drv_atom(TARGETS)) /* Return a list of all supported targets */
823 /* TARGETS selection request */
824 rprop = EVENT_SelectionRequest_TARGETS( display, request, event->target, rprop );
826 else if(event->target == x11drv_atom(MULTIPLE)) /* rprop contains a list of (target, property) atom pairs */
828 /* MULTIPLE selection request */
829 rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
833 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(event->target);
836 lpFormat = X11DRV_CLIPBOARD_LookupAliasProperty(event->target);
840 LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(lpFormat->wFormatID);
844 unsigned char* lpClipData;
846 HANDLE hClipData = lpFormat->lpDrvExportFunc(request, event->target,
847 rprop, lpData, &cBytes);
849 if (hClipData && (lpClipData = GlobalLock(hClipData)))
852 TRACE_(clipboard)("\tUpdating property %s, %ld bytes\n",
853 lpFormat->Name, cBytes);
856 XChangeProperty(display, request, rprop, event->target,
857 8, PropModeReplace, (unsigned char *)lpClipData, cBytes);
860 GlobalUnlock(hClipData);
861 GlobalFree(hClipData);
869 * SelectionNotify should be sent only at the end of a MULTIPLE request
873 result.type = SelectionNotify;
874 result.display = display;
875 result.requestor = request;
876 result.selection = event->selection;
877 result.property = rprop;
878 result.target = event->target;
879 result.time = event->time;
880 TRACE("Sending SelectionNotify event...\n");
882 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
887 /***********************************************************************
888 * EVENT_SelectionClear
890 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
892 if (event->selection == XA_PRIMARY || event->selection == x11drv_atom(CLIPBOARD))
893 X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
896 /***********************************************************************
897 * EVENT_PropertyNotify
898 * We use this to release resources like Pixmaps when a selection
899 * client no longer needs them.
901 static void EVENT_PropertyNotify( XPropertyEvent *event )
903 /* Check if we have any resources to free */
904 TRACE("Received PropertyNotify event: \n");
910 TRACE("\tPropertyDelete for atom %ld on window %ld\n",
911 event->atom, (long)event->window);
915 case PropertyNewValue:
917 TRACE("\tPropertyNewValue for atom %ld on window %ld\n\n",
918 event->atom, (long)event->window);
927 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
931 if (!IsWindowEnabled(hQueryWnd)) return 0;
933 GetWindowRect(hQueryWnd, &tempRect);
935 if(!PtInRect(&tempRect, *lpPt)) return 0;
937 if (!IsIconic( hQueryWnd ))
939 GetClientRect( hQueryWnd, &tempRect );
940 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
942 if (PtInRect( &tempRect, *lpPt))
944 HWND *list = WIN_ListChildren( hQueryWnd );
951 for (i = 0; list[i]; i++)
953 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
955 GetWindowRect( list[i], &tempRect );
956 if (PtInRect( &tempRect, *lpPt )) break;
961 if (IsWindowEnabled( list[i] ))
962 bResult = find_drop_window( list[i], lpPt );
964 HeapFree( GetProcessHeap(), 0, list );
966 if(bResult) return bResult;
970 if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
972 ScreenToClient(hQueryWnd, lpPt);
977 /**********************************************************************
978 * EVENT_DropFromOffix
980 * don't know if it still works (last Changlog is from 96/11/04)
982 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
984 unsigned long data_length;
985 unsigned long aux_long;
986 unsigned char* p_data = NULL;
997 Window w_aux_root, w_aux_child;
1001 pWnd = WIN_FindWndPtr(hWnd);
1004 XQueryPointer( event->display, get_whole_window(pWnd), &w_aux_root, &w_aux_child,
1005 &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
1006 (unsigned int*)&aux_long);
1007 wine_tsx11_unlock();
1009 /* find out drop point and drop window */
1010 if( x < 0 || y < 0 ||
1011 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1012 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1014 bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES;
1020 POINT pt = { x, y };
1021 HWND hwndDrop = find_drop_window( hWnd, &pt );
1034 WIN_ReleaseWndPtr(pWnd);
1036 if (!bAccept) return;
1039 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1040 x11drv_atom(DndSelection), 0, 65535, FALSE,
1041 AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1042 &data_length, &aux_long, &p_data);
1043 wine_tsx11_unlock();
1045 if( !aux_long && p_data) /* don't bother if > 64K */
1047 signed char *p = (signed char*) p_data;
1051 while( *p ) /* calculate buffer size */
1054 if((u.i = *p) != -1 )
1056 INT len = GetShortPathNameA( p, NULL, 0 );
1057 if (len) aux_long += len + 1;
1062 if( aux_long && aux_long < 65535 )
1067 aux_long += sizeof(DROPFILES) + 1;
1068 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
1069 lpDrop = (DROPFILES*)GlobalLock( hDrop );
1073 WND *pDropWnd = WIN_FindWndPtr( hScope );
1074 lpDrop->pFiles = sizeof(DROPFILES);
1078 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1079 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1080 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1081 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1082 lpDrop->fWide = FALSE;
1083 WIN_ReleaseWndPtr(pDropWnd);
1084 p_drop = (char *)(lpDrop + 1);
1088 if( *p != -1 ) /* use only "good" entries */
1090 GetShortPathNameA( p, p_drop, 65535 );
1091 p_drop += strlen( p_drop ) + 1;
1096 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1101 if( p_data ) XFree(p_data);
1102 wine_tsx11_unlock();
1105 /**********************************************************************
1108 * drop items are separated by \n
1109 * each item is prefixed by its mime type
1111 * event->data.l[3], event->data.l[4] contains drop x,y position
1113 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
1115 unsigned long data_length;
1116 unsigned long aux_long, drop_len = 0;
1117 unsigned char *p_data = NULL; /* property data */
1118 char *p_drop = NULL;
1129 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
1132 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1133 x11drv_atom(DndSelection), 0, 65535, FALSE,
1134 AnyPropertyType, &u.atom_aux, &u.i,
1135 &data_length, &aux_long, &p_data);
1136 wine_tsx11_unlock();
1138 WARN("property too large, truncated!\n");
1139 TRACE("urls=%s\n", p_data);
1141 if( !aux_long && p_data) { /* don't bother if > 64K */
1142 /* calculate length */
1144 next = strchr(p, '\n');
1147 if (strncmp(p,"file:",5) == 0 ) {
1148 INT len = GetShortPathNameA( p+5, NULL, 0 );
1149 if (len) drop_len += len + 1;
1154 next = strchr(p, '\n');
1160 if( drop_len && drop_len < 65535 ) {
1162 XQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
1163 &x, &y, &u.i, &u.i, &u.i);
1164 wine_tsx11_unlock();
1166 drop_len += sizeof(DROPFILES) + 1;
1167 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
1168 lpDrop = (DROPFILES *) GlobalLock( hDrop );
1171 WND *pDropWnd = WIN_FindWndPtr( hWnd );
1172 lpDrop->pFiles = sizeof(DROPFILES);
1173 lpDrop->pt.x = (INT)x;
1174 lpDrop->pt.y = (INT)y;
1176 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1177 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1178 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1179 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1180 lpDrop->fWide = FALSE;
1181 p_drop = (char*)(lpDrop + 1);
1182 WIN_ReleaseWndPtr(pDropWnd);
1185 /* create message content */
1188 next = strchr(p, '\n');
1191 if (strncmp(p,"file:",5) == 0 ) {
1192 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
1194 TRACE("drop file %s as %s\n", p+5, p_drop);
1197 WARN("can't convert file %s to dos name \n", p+5);
1200 WARN("unknown mime type %s\n", p);
1205 next = strchr(p, '\n');
1212 GlobalUnlock(hDrop);
1213 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1217 if( p_data ) XFree(p_data);
1218 wine_tsx11_unlock();
1222 /**********************************************************************
1223 * EVENT_ClientMessage
1225 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
1227 if (event->message_type != None && event->format == 32) {
1228 if (event->message_type == x11drv_atom(WM_PROTOCOLS))
1229 handle_wm_protocols_message( hWnd, event );
1230 else if (event->message_type == x11drv_atom(DndProtocol))
1232 /* query window (drag&drop event contains only drag window) */
1234 int root_x, root_y, child_x, child_y;
1238 XQueryPointer( event->display, root_window, &root, &child,
1239 &root_x, &root_y, &child_x, &child_y, &u);
1240 if (XFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) hWnd = 0;
1241 wine_tsx11_unlock();
1243 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
1244 EVENT_DropFromOffiX(hWnd, event);
1245 else if (event->data.l[0] == DndURL)
1246 EVENT_DropURLs(hWnd, event);
1248 else if (!X11DRV_XDND_Event(hWnd, event))
1251 /* enable this if you want to see the message */
1252 unsigned char* p_data = NULL;
1259 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1260 dndSelection, 0, 65535, FALSE,
1261 AnyPropertyType, &u.atom, &u.i,
1262 &u.l, &u.l, &p_data);
1263 wine_tsx11_unlock();
1264 TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1265 event->message_type, event->data.l[0], event->data.l[1],
1266 event->data.l[2], event->data.l[3], event->data.l[4],
1269 TRACE("unrecognized ClientMessage\n" );
1275 /**********************************************************************
1276 * X11DRV_EVENT_SetInputMethod
1278 INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
1280 INPUT_TYPE prev = current_input_type;
1282 /* Flag not used yet */
1283 in_transition = FALSE;
1284 current_input_type = type;
1289 #ifdef HAVE_LIBXXF86DGA2
1290 /**********************************************************************
1291 * X11DRV_EVENT_SetDGAStatus
1293 void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
1295 if (event_base < 0) {
1301 DGAMotionEventType = event_base + MotionNotify;
1302 DGAButtonPressEventType = event_base + ButtonPress;
1303 DGAButtonReleaseEventType = event_base + ButtonRelease;
1304 DGAKeyPressEventType = event_base + KeyPress;
1305 DGAKeyReleaseEventType = event_base + KeyRelease;