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 &&
277 event->type != MappingNotify && event->type != KeymapNotify)
278 WARN( "Got event %s for unknown Window %08lx\n",
279 event_names[event->type], event->xany.window );
280 else if (event->type <= MappingNotify)
281 TRACE("Got event %s for hwnd/window %p/%lx, GetFocus()=%p\n",
282 event_names[event->type], hWnd, event->xany.window, GetFocus() );
284 TRACE("Got extension event for hwnd/window %p/%lx, GetFocus()=%p\n",
285 hWnd, event->xany.window, GetFocus() );
287 if (X11DRV_ProcessTabletEvent(hWnd, event))
289 TRACE("Return: filtered by tablet\n");
297 /* FIXME: should generate a motion event if event point is different from current pos */
298 X11DRV_KeyEvent( hWnd, (XKeyEvent*)event );
302 X11DRV_ButtonPress( hWnd, (XButtonEvent*)event );
306 X11DRV_ButtonRelease( hWnd, (XButtonEvent*)event );
310 X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
314 X11DRV_EnterNotify( hWnd, (XCrossingEvent*)event );
318 EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
322 EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
326 X11DRV_Expose( hWnd, &event->xexpose );
329 case ConfigureNotify:
331 X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
334 case SelectionRequest:
336 EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
341 EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
345 EVENT_PropertyNotify( (XPropertyEvent *)event );
350 EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
357 X11DRV_MapNotify( hWnd, (XMapEvent *)event );
361 X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
365 X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
369 X11DRV_MappingNotify( (XMappingEvent *) event );
373 WARN("Unprocessed event %s for hwnd %p\n", event_names[event->type], hWnd );
376 TRACE( "returns.\n" );
380 /*******************************************************************
381 * can_activate_window
383 * Check if we can activate the specified window.
385 inline static BOOL can_activate_window( HWND hwnd )
387 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
388 if (!(style & WS_VISIBLE)) return FALSE;
389 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
390 return !(style & WS_DISABLED);
394 /**********************************************************************
397 static void set_focus( HWND hwnd, Time time )
402 TRACE( "setting foreground window to %p\n", hwnd );
403 SetForegroundWindow( hwnd );
406 if (focus) focus = GetAncestor( focus, GA_ROOT );
407 win = X11DRV_get_whole_window(focus);
411 TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time );
413 XSetInputFocus( thread_display(), win, RevertToParent, time );
419 /**********************************************************************
420 * handle_wm_protocols_message
422 static void handle_wm_protocols_message( HWND hwnd, XClientMessageEvent *event )
424 Atom protocol = (Atom)event->data.l[0];
426 if (!protocol) return;
428 if (protocol == x11drv_atom(WM_DELETE_WINDOW))
430 /* Ignore the delete window request if the window has been disabled
431 * and we are in managed mode. This is to disallow applications from
432 * being closed by the window manager while in a modal state.
434 if (IsWindowEnabled(hwnd)) PostMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
436 else if (protocol == x11drv_atom(WM_TAKE_FOCUS))
438 Time event_time = (Time)event->data.l[1];
439 HWND last_focus = x11drv_thread_data()->last_focus;
441 TRACE( "got take focus msg for %p, enabled=%d, focus=%p, active=%p, fg=%p, last=%p\n",
442 hwnd, IsWindowEnabled(hwnd), GetFocus(), GetActiveWindow(),
443 GetForegroundWindow(), last_focus );
445 if (can_activate_window(hwnd))
447 /* simulate a mouse click on the caption to find out
448 * whether the window wants to be activated */
449 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
450 (WPARAM)GetAncestor( hwnd, GA_ROOT ),
451 MAKELONG(HTCAPTION,WM_LBUTTONDOWN) );
452 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) set_focus( hwnd, event_time );
453 else TRACE( "not setting focus to %p (%lx), ma=%ld\n", hwnd, event->window, ma );
458 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
459 if (!hwnd) hwnd = GetActiveWindow();
460 if (!hwnd) hwnd = last_focus;
461 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
464 else if (protocol == x11drv_atom(_NET_WM_PING))
466 XClientMessageEvent xev;
469 TRACE("NET_WM Ping\n");
470 xev.window = DefaultRootWindow(xev.display);
471 XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
472 /* this line is semi-stolen from gtk2 */
473 TRACE("NET_WM Pong\n");
478 static const char * const focus_details[] =
484 "NotifyNonlinearVirtual",
490 /**********************************************************************
493 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
499 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
501 if (event->detail == NotifyPointer) return;
503 if ((xic = X11DRV_get_ic( hwnd )))
509 if (use_take_focus) return; /* ignore FocusIn if we are using take focus */
511 if (!can_activate_window(hwnd))
513 HWND hwnd = GetFocus();
514 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
515 if (!hwnd) hwnd = GetActiveWindow();
516 if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
517 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
519 else SetForegroundWindow( hwnd );
523 /**********************************************************************
526 * Note: only top-level windows get FocusOut events.
528 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
535 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
537 if (event->detail == NotifyPointer) return;
538 if (ximInComposeMode) return;
540 x11drv_thread_data()->last_focus = hwnd;
541 if ((xic = X11DRV_get_ic( hwnd )))
544 XUnsetICFocus( xic );
547 if (hwnd != GetForegroundWindow()) return;
548 SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
550 /* don't reset the foreground window, if the window which is
551 getting the focus is a Wine window */
554 XGetInputFocus( thread_display(), &focus_win, &revert );
557 if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
564 /* Abey : 6-Oct-99. Check again if the focus out window is the
565 Foreground window, because in most cases the messages sent
566 above must have already changed the foreground window, in which
567 case we don't have to change the foreground window to 0 */
568 if (hwnd == GetForegroundWindow())
570 TRACE( "lost focus, setting fg to 0\n" );
571 SetForegroundWindow( 0 );
577 /***********************************************************************
578 * EVENT_SelectionRequest_AddTARGETS
579 * Utility function for EVENT_SelectionRequest_TARGETS.
581 static void EVENT_SelectionRequest_AddTARGETS(Atom* targets, unsigned long* cTargets, Atom prop)
586 /* Scan through what we have so far to avoid duplicates */
587 for (i = 0, bExists = FALSE; i < *cTargets; i++)
589 if (targets[i] == prop)
597 targets[(*cTargets)++] = prop;
601 /***********************************************************************
602 * EVENT_SelectionRequest_TARGETS
603 * Service a TARGETS selection request event
605 static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
606 Atom target, Atom rprop )
612 LPWINE_CLIPFORMAT lpFormat;
615 * Count the number of items we wish to expose as selection targets.
616 * We include the TARGETS item, and propery aliases
618 cTargets = X11DRV_CountClipboardFormats() + 1;
620 for (wFormat = 0; (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
622 lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
626 if (!lpFormat->lpDrvExportFunc)
629 if (X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData))
634 TRACE_(clipboard)(" found %ld formats\n", cTargets);
636 /* Allocate temp buffer */
637 targets = (Atom*)HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
641 /* Create TARGETS property list (First item in list is TARGETS itself) */
642 for (targets[0] = x11drv_atom(TARGETS), cTargets = 1, wFormat = 0;
643 (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
645 lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
647 if (lpFormat->lpDrvExportFunc)
648 EVENT_SelectionRequest_AddTARGETS(targets, &cTargets, lpFormat->drvData);
650 /* Check if any alias should be listed */
651 alias = X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData);
653 EVENT_SelectionRequest_AddTARGETS(targets, &cTargets, alias);
658 if (TRACE_ON(clipboard))
661 for ( i = 0; i < cTargets; i++)
665 char *itemFmtName = XGetAtomName(display, targets[i]);
666 TRACE_(clipboard)("\tAtom# %d: Property %ld Type %s\n", i, targets[i], itemFmtName);
672 /* We may want to consider setting the type to xaTargets instead,
673 * in case some apps expect this instead of XA_ATOM */
674 XChangeProperty(display, requestor, rprop, XA_ATOM, 32,
675 PropModeReplace, (unsigned char *)targets, cTargets);
678 HeapFree(GetProcessHeap(), 0, targets);
684 /***********************************************************************
685 * EVENT_SelectionRequest_MULTIPLE
686 * Service a MULTIPLE selection request event
687 * rprop contains a list of (target,property) atom pairs.
688 * The first atom names a target and the second names a property.
689 * The effect is as if we have received a sequence of SelectionRequest events
690 * (one for each atom pair) except that:
691 * 1. We reply with a SelectionNotify only when all the requested conversions
692 * have been performed.
693 * 2. If we fail to convert the target named by an atom in the MULTIPLE property,
694 * we replace the atom in the property by None.
696 static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
698 Display *display = pevent->display;
700 Atom atype=AnyPropertyType;
702 unsigned long remain;
703 Atom* targetPropList=NULL;
704 unsigned long cTargetPropList = 0;
706 /* If the specified property is None the requestor is an obsolete client.
707 * We support these by using the specified target atom as the reply property.
709 rprop = pevent->property;
711 rprop = pevent->target;
715 /* Read the MULTIPLE property contents. This should contain a list of
716 * (target,property) atom pairs.
719 if(XGetWindowProperty(display, pevent->requestor, rprop,
720 0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
721 &cTargetPropList, &remain,
722 (unsigned char**)&targetPropList) != Success)
725 TRACE("\tCouldn't read MULTIPLE property\n");
729 TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
730 XGetAtomName(display, atype), aformat, cTargetPropList, remain);
734 * Make sure we got what we expect.
735 * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
736 * in a MULTIPLE selection request should be of type ATOM_PAIR.
737 * However some X apps(such as XPaint) are not compliant with this and return
738 * a user defined atom in atype when XGetWindowProperty is called.
739 * The data *is* an atom pair but is not denoted as such.
741 if(aformat == 32 /* atype == xAtomPair */ )
745 /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
746 * for each (target,property) pair */
748 for (i = 0; i < cTargetPropList; i+=2)
750 XSelectionRequestEvent event;
754 char *targetName, *propName;
756 targetName = XGetAtomName(display, targetPropList[i]);
757 propName = XGetAtomName(display, targetPropList[i+1]);
758 TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
759 i/2, targetName, propName);
765 /* We must have a non "None" property to service a MULTIPLE target atom */
766 if ( !targetPropList[i+1] )
768 TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
772 /* Set up an XSelectionRequestEvent for this (target,property) pair */
773 memcpy( &event, pevent, sizeof(XSelectionRequestEvent) );
774 event.target = targetPropList[i];
775 event.property = targetPropList[i+1];
777 /* Fire a SelectionRequest, informing the handler that we are processing
778 * a MULTIPLE selection request event.
780 EVENT_SelectionRequest( hWnd, &event, TRUE );
784 /* Free the list of targets/properties */
786 XFree(targetPropList);
795 /***********************************************************************
796 * EVENT_SelectionRequest
797 * Process an event selection request event.
798 * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
799 * recursively while servicing a "MULTIPLE" selection target.
801 * Note: We only receive this event when WINE owns the X selection
803 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
805 Display *display = event->display;
806 XSelectionEvent result;
808 Window request = event->requestor;
810 TRACE_(clipboard)("\n");
813 * We can only handle the selection request if :
814 * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
815 * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
816 * since this has been already done.
820 if (((event->selection != XA_PRIMARY) && (event->selection != x11drv_atom(CLIPBOARD))))
824 /* If the specified property is None the requestor is an obsolete client.
825 * We support these by using the specified target atom as the reply property.
827 rprop = event->property;
829 rprop = event->target;
831 if(event->target == x11drv_atom(TARGETS)) /* Return a list of all supported targets */
833 /* TARGETS selection request */
834 rprop = EVENT_SelectionRequest_TARGETS( display, request, event->target, rprop );
836 else if(event->target == x11drv_atom(MULTIPLE)) /* rprop contains a list of (target, property) atom pairs */
838 /* MULTIPLE selection request */
839 rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
843 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(event->target);
846 lpFormat = X11DRV_CLIPBOARD_LookupAliasProperty(event->target);
848 if (lpFormat && lpFormat->lpDrvExportFunc)
850 LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(lpFormat->wFormatID);
854 unsigned char* lpClipData;
856 HANDLE hClipData = lpFormat->lpDrvExportFunc(request, event->target,
857 rprop, lpData, &cBytes);
859 if (hClipData && (lpClipData = GlobalLock(hClipData)))
861 TRACE_(clipboard)("\tUpdating property %s, %ld bytes\n",
862 lpFormat->Name, cBytes);
865 XChangeProperty(display, request, rprop, event->target,
866 8, PropModeReplace, (unsigned char *)lpClipData, cBytes);
869 GlobalUnlock(hClipData);
870 GlobalFree(hClipData);
878 * SelectionNotify should be sent only at the end of a MULTIPLE request
882 result.type = SelectionNotify;
883 result.display = display;
884 result.requestor = request;
885 result.selection = event->selection;
886 result.property = rprop;
887 result.target = event->target;
888 result.time = event->time;
889 TRACE("Sending SelectionNotify event...\n");
891 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
896 /***********************************************************************
897 * EVENT_SelectionClear
899 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
901 if (event->selection == XA_PRIMARY || event->selection == x11drv_atom(CLIPBOARD))
902 X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
905 /***********************************************************************
906 * EVENT_PropertyNotify
907 * We use this to release resources like Pixmaps when a selection
908 * client no longer needs them.
910 static void EVENT_PropertyNotify( XPropertyEvent *event )
912 /* Check if we have any resources to free */
913 TRACE("Received PropertyNotify event: \n");
919 TRACE("\tPropertyDelete for atom %ld on window %ld\n",
920 event->atom, (long)event->window);
924 case PropertyNewValue:
926 TRACE("\tPropertyNewValue for atom %ld on window %ld\n\n",
927 event->atom, (long)event->window);
936 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
940 if (!IsWindowEnabled(hQueryWnd)) return 0;
942 GetWindowRect(hQueryWnd, &tempRect);
944 if(!PtInRect(&tempRect, *lpPt)) return 0;
946 if (!IsIconic( hQueryWnd ))
948 GetClientRect( hQueryWnd, &tempRect );
949 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
951 if (PtInRect( &tempRect, *lpPt))
953 HWND *list = WIN_ListChildren( hQueryWnd );
960 for (i = 0; list[i]; i++)
962 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
964 GetWindowRect( list[i], &tempRect );
965 if (PtInRect( &tempRect, *lpPt )) break;
970 if (IsWindowEnabled( list[i] ))
971 bResult = find_drop_window( list[i], lpPt );
973 HeapFree( GetProcessHeap(), 0, list );
975 if(bResult) return bResult;
979 if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
981 ScreenToClient(hQueryWnd, lpPt);
986 /**********************************************************************
987 * EVENT_DropFromOffix
989 * don't know if it still works (last Changlog is from 96/11/04)
991 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
993 unsigned long data_length;
994 unsigned long aux_long;
995 unsigned char* p_data = NULL;
1006 Window w_aux_root, w_aux_child;
1010 pWnd = WIN_FindWndPtr(hWnd);
1013 XQueryPointer( event->display, get_whole_window(pWnd), &w_aux_root, &w_aux_child,
1014 &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
1015 (unsigned int*)&aux_long);
1016 wine_tsx11_unlock();
1018 /* find out drop point and drop window */
1019 if( x < 0 || y < 0 ||
1020 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1021 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1023 bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES;
1029 POINT pt = { x, y };
1030 HWND hwndDrop = find_drop_window( hWnd, &pt );
1043 WIN_ReleaseWndPtr(pWnd);
1045 if (!bAccept) return;
1048 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1049 x11drv_atom(DndSelection), 0, 65535, FALSE,
1050 AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1051 &data_length, &aux_long, &p_data);
1052 wine_tsx11_unlock();
1054 if( !aux_long && p_data) /* don't bother if > 64K */
1056 signed char *p = (signed char*) p_data;
1060 while( *p ) /* calculate buffer size */
1063 if((u.i = *p) != -1 )
1065 INT len = GetShortPathNameA( p, NULL, 0 );
1066 if (len) aux_long += len + 1;
1071 if( aux_long && aux_long < 65535 )
1076 aux_long += sizeof(DROPFILES) + 1;
1077 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
1078 lpDrop = (DROPFILES*)GlobalLock( hDrop );
1082 WND *pDropWnd = WIN_FindWndPtr( hScope );
1083 lpDrop->pFiles = sizeof(DROPFILES);
1087 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1088 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1089 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1090 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1091 lpDrop->fWide = FALSE;
1092 WIN_ReleaseWndPtr(pDropWnd);
1093 p_drop = (char *)(lpDrop + 1);
1097 if( *p != -1 ) /* use only "good" entries */
1099 GetShortPathNameA( p, p_drop, 65535 );
1100 p_drop += strlen( p_drop ) + 1;
1105 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1110 if( p_data ) XFree(p_data);
1111 wine_tsx11_unlock();
1114 /**********************************************************************
1117 * drop items are separated by \n
1118 * each item is prefixed by its mime type
1120 * event->data.l[3], event->data.l[4] contains drop x,y position
1122 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
1124 unsigned long data_length;
1125 unsigned long aux_long, drop_len = 0;
1126 unsigned char *p_data = NULL; /* property data */
1127 char *p_drop = NULL;
1138 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
1141 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1142 x11drv_atom(DndSelection), 0, 65535, FALSE,
1143 AnyPropertyType, &u.atom_aux, &u.i,
1144 &data_length, &aux_long, &p_data);
1145 wine_tsx11_unlock();
1147 WARN("property too large, truncated!\n");
1148 TRACE("urls=%s\n", p_data);
1150 if( !aux_long && p_data) { /* don't bother if > 64K */
1151 /* calculate length */
1153 next = strchr(p, '\n');
1156 if (strncmp(p,"file:",5) == 0 ) {
1157 INT len = GetShortPathNameA( p+5, NULL, 0 );
1158 if (len) drop_len += len + 1;
1163 next = strchr(p, '\n');
1169 if( drop_len && drop_len < 65535 ) {
1171 XQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
1172 &x, &y, &u.i, &u.i, &u.i);
1173 wine_tsx11_unlock();
1175 drop_len += sizeof(DROPFILES) + 1;
1176 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
1177 lpDrop = (DROPFILES *) GlobalLock( hDrop );
1180 WND *pDropWnd = WIN_FindWndPtr( hWnd );
1181 lpDrop->pFiles = sizeof(DROPFILES);
1182 lpDrop->pt.x = (INT)x;
1183 lpDrop->pt.y = (INT)y;
1185 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1186 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1187 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1188 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1189 lpDrop->fWide = FALSE;
1190 p_drop = (char*)(lpDrop + 1);
1191 WIN_ReleaseWndPtr(pDropWnd);
1194 /* create message content */
1197 next = strchr(p, '\n');
1200 if (strncmp(p,"file:",5) == 0 ) {
1201 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
1203 TRACE("drop file %s as %s\n", p+5, p_drop);
1206 WARN("can't convert file %s to dos name \n", p+5);
1209 WARN("unknown mime type %s\n", p);
1214 next = strchr(p, '\n');
1221 GlobalUnlock(hDrop);
1222 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1226 if( p_data ) XFree(p_data);
1227 wine_tsx11_unlock();
1231 /**********************************************************************
1232 * EVENT_ClientMessage
1234 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
1236 if (event->message_type != None && event->format == 32) {
1237 if (event->message_type == x11drv_atom(WM_PROTOCOLS))
1238 handle_wm_protocols_message( hWnd, event );
1239 else if (event->message_type == x11drv_atom(DndProtocol))
1241 /* query window (drag&drop event contains only drag window) */
1243 int root_x, root_y, child_x, child_y;
1247 XQueryPointer( event->display, root_window, &root, &child,
1248 &root_x, &root_y, &child_x, &child_y, &u);
1249 if (XFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) hWnd = 0;
1250 wine_tsx11_unlock();
1252 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
1253 EVENT_DropFromOffiX(hWnd, event);
1254 else if (event->data.l[0] == DndURL)
1255 EVENT_DropURLs(hWnd, event);
1257 else if (!X11DRV_XDND_Event(hWnd, event))
1260 /* enable this if you want to see the message */
1261 unsigned char* p_data = NULL;
1268 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1269 dndSelection, 0, 65535, FALSE,
1270 AnyPropertyType, &u.atom, &u.i,
1271 &u.l, &u.l, &p_data);
1272 wine_tsx11_unlock();
1273 TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1274 event->message_type, event->data.l[0], event->data.l[1],
1275 event->data.l[2], event->data.l[3], event->data.l[4],
1278 TRACE("unrecognized ClientMessage\n" );
1284 /**********************************************************************
1285 * X11DRV_EVENT_SetInputMethod
1287 INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
1289 INPUT_TYPE prev = current_input_type;
1291 /* Flag not used yet */
1292 in_transition = FALSE;
1293 current_input_type = type;
1298 #ifdef HAVE_LIBXXF86DGA2
1299 /**********************************************************************
1300 * X11DRV_EVENT_SetDGAStatus
1302 void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
1304 if (event_base < 0) {
1310 DGAMotionEventType = event_base + MotionNotify;
1311 DGAButtonPressEventType = event_base + ButtonPress;
1312 DGAButtonReleaseEventType = event_base + ButtonRelease;
1313 DGAKeyPressEventType = event_base + KeyPress;
1314 DGAKeyReleaseEventType = event_base + KeyRelease;