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--;
190 /***********************************************************************
191 * EVENT_x11_time_to_win32_time
193 * Make our timer and the X timer line up as best we can
194 * Pass 0 to retrieve the current adjustment value (times -1)
196 DWORD EVENT_x11_time_to_win32_time(Time time)
198 static DWORD adjust = 0;
199 DWORD now = GetTickCount();
202 if (! adjust && time != 0)
209 /* If we got an event in the 'future', then our clock is clearly wrong.
210 If we got it more than 10000 ms in the future, then it's most likely
211 that the clock has wrapped. */
214 if (ret > now && ((ret - now) < 10000) && time != 0)
225 /***********************************************************************
228 * Process an X event.
230 static void EVENT_ProcessEvent( XEvent *event )
233 Display *display = event->xany.display;
235 TRACE( "called.\n" );
239 case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
240 FIXME("Got SelectionNotify - must not happen!\n");
243 /* We get all these because of StructureNotifyMask.
244 This check is placed here to avoid getting error messages below,
245 as X might send some of these even for windows that have already
247 case CirculateNotify:
255 #ifdef HAVE_LIBXXF86DGA2
257 if (event->type == DGAMotionEventType) {
258 TRACE("DGAMotionEvent received.\n");
259 X11DRV_DGAMotionEvent( DGAhwnd, (XDGAMotionEvent *)event );
262 if (event->type == DGAButtonPressEventType) {
263 TRACE("DGAButtonPressEvent received.\n");
264 X11DRV_DGAButtonPressEvent( DGAhwnd, (XDGAButtonEvent *)event );
267 if (event->type == DGAButtonReleaseEventType) {
268 TRACE("DGAButtonReleaseEvent received.\n");
269 X11DRV_DGAButtonReleaseEvent( DGAhwnd, (XDGAButtonEvent *)event );
272 if ((event->type == DGAKeyPressEventType) ||
273 (event->type == DGAKeyReleaseEventType)) {
274 /* Fill a XKeyEvent to send to EVENT_Key */
276 XDGAKeyEvent *evt = (XDGAKeyEvent *) event;
278 TRACE("DGAKeyPress/ReleaseEvent received.\n");
280 if (evt->type == DGAKeyReleaseEventType)
281 ke.type = KeyRelease;
284 ke.serial = evt->serial;
285 ke.send_event = FALSE;
286 ke.display = evt->display;
295 ke.state = evt->state;
296 ke.keycode = evt->keycode;
297 ke.same_screen = TRUE;
298 X11DRV_KeyEvent( 0, &ke );
305 if (XFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
306 hWnd = 0; /* Not for a registered window */
308 if (!hWnd && event->xany.window == root_window) hWnd = GetDesktopWindow();
310 if (!hWnd && event->type != PropertyNotify &&
311 event->type != MappingNotify && event->type != KeymapNotify)
312 WARN( "Got event %s for unknown Window %08lx\n",
313 event_names[event->type], event->xany.window );
314 else if (event->type <= MappingNotify)
315 TRACE("Got event %s for hwnd/window %p/%lx, GetFocus()=%p\n",
316 event_names[event->type], hWnd, event->xany.window, GetFocus() );
318 TRACE("Got extension event for hwnd/window %p/%lx, GetFocus()=%p\n",
319 hWnd, event->xany.window, GetFocus() );
321 if (X11DRV_ProcessTabletEvent(hWnd, event))
323 TRACE("Return: filtered by tablet\n");
331 /* FIXME: should generate a motion event if event point is different from current pos */
332 X11DRV_KeyEvent( hWnd, (XKeyEvent*)event );
336 X11DRV_ButtonPress( hWnd, (XButtonEvent*)event );
340 X11DRV_ButtonRelease( hWnd, (XButtonEvent*)event );
344 X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
348 X11DRV_EnterNotify( hWnd, (XCrossingEvent*)event );
352 EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
356 EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
360 X11DRV_Expose( hWnd, &event->xexpose );
363 case ConfigureNotify:
365 X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
368 case SelectionRequest:
370 EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
375 EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
379 EVENT_PropertyNotify( (XPropertyEvent *)event );
384 EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
391 X11DRV_MapNotify( hWnd, (XMapEvent *)event );
395 X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
399 X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
403 X11DRV_MappingNotify( (XMappingEvent *) event );
407 WARN("Unprocessed event %s for hwnd %p\n", event_names[event->type], hWnd );
410 TRACE( "returns.\n" );
414 /*******************************************************************
415 * can_activate_window
417 * Check if we can activate the specified window.
419 inline static BOOL can_activate_window( HWND hwnd )
421 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
422 if (!(style & WS_VISIBLE)) return FALSE;
423 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
424 return !(style & WS_DISABLED);
428 /**********************************************************************
431 static void set_focus( HWND hwnd, Time time )
436 TRACE( "setting foreground window to %p\n", hwnd );
437 SetForegroundWindow( hwnd );
440 if (focus) focus = GetAncestor( focus, GA_ROOT );
441 win = X11DRV_get_whole_window(focus);
445 TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time );
447 XSetInputFocus( thread_display(), win, RevertToParent, time );
453 /**********************************************************************
454 * handle_wm_protocols_message
456 static void handle_wm_protocols_message( HWND hwnd, XClientMessageEvent *event )
458 Atom protocol = (Atom)event->data.l[0];
460 if (!protocol) return;
462 if (protocol == x11drv_atom(WM_DELETE_WINDOW))
464 /* Ignore the delete window request if the window has been disabled
465 * and we are in managed mode. This is to disallow applications from
466 * being closed by the window manager while in a modal state.
468 if (IsWindowEnabled(hwnd)) PostMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
470 else if (protocol == x11drv_atom(WM_TAKE_FOCUS))
472 Time event_time = (Time)event->data.l[1];
473 HWND last_focus = x11drv_thread_data()->last_focus;
475 TRACE( "got take focus msg for %p, enabled=%d, focus=%p, active=%p, fg=%p, last=%p\n",
476 hwnd, IsWindowEnabled(hwnd), GetFocus(), GetActiveWindow(),
477 GetForegroundWindow(), last_focus );
479 if (can_activate_window(hwnd))
481 /* simulate a mouse click on the caption to find out
482 * whether the window wants to be activated */
483 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
484 (WPARAM)GetAncestor( hwnd, GA_ROOT ),
485 MAKELONG(HTCAPTION,WM_LBUTTONDOWN) );
486 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) set_focus( hwnd, event_time );
487 else TRACE( "not setting focus to %p (%lx), ma=%ld\n", hwnd, event->window, ma );
492 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
493 if (!hwnd) hwnd = GetActiveWindow();
494 if (!hwnd) hwnd = last_focus;
495 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
498 else if (protocol == x11drv_atom(_NET_WM_PING))
500 XClientMessageEvent xev;
503 TRACE("NET_WM Ping\n");
504 xev.window = DefaultRootWindow(xev.display);
505 XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
506 /* this line is semi-stolen from gtk2 */
507 TRACE("NET_WM Pong\n");
512 static const char * const focus_details[] =
518 "NotifyNonlinearVirtual",
524 /**********************************************************************
527 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
533 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
535 if (event->detail == NotifyPointer) return;
537 if ((xic = X11DRV_get_ic( hwnd )))
543 if (use_take_focus) return; /* ignore FocusIn if we are using take focus */
545 if (!can_activate_window(hwnd))
547 HWND hwnd = GetFocus();
548 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
549 if (!hwnd) hwnd = GetActiveWindow();
550 if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
551 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
553 else SetForegroundWindow( hwnd );
557 /**********************************************************************
560 * Note: only top-level windows get FocusOut events.
562 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
571 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
573 if (event->detail == NotifyPointer) return;
574 if (ximInComposeMode) return;
576 x11drv_thread_data()->last_focus = hwnd;
577 if ((xic = X11DRV_get_ic( hwnd )))
580 XUnsetICFocus( xic );
583 if (hwnd != GetForegroundWindow()) return;
584 SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
586 /* don't reset the foreground window, if the window which is
587 getting the focus is a Wine window */
590 XGetInputFocus( thread_display(), &focus_win, &revert );
593 if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
600 /* Abey : 6-Oct-99. Check again if the focus out window is the
601 Foreground window, because in most cases the messages sent
602 above must have already changed the foreground window, in which
603 case we don't have to change the foreground window to 0 */
604 if (hwnd == GetForegroundWindow())
606 TRACE( "lost focus, setting fg to 0\n" );
607 SetForegroundWindow( 0 );
613 /***********************************************************************
614 * EVENT_SelectionRequest_AddTARGETS
615 * Utility function for EVENT_SelectionRequest_TARGETS.
617 static BOOL EVENT_SelectionRequest_AddTARGETS(Atom* targets, unsigned long cTargets, Atom prop)
622 /* Scan through what we have so far to avoid duplicates */
623 for (i = 0, bExists = FALSE; i < cTargets; i++)
625 if (targets[i] == prop)
633 targets[cTargets] = prop;
639 /***********************************************************************
640 * EVENT_SelectionRequest_TARGETS
641 * Service a TARGETS selection request event
643 static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
644 Atom target, Atom rprop )
650 LPWINE_CLIPFORMAT lpFormat;
653 * Count the number of items we wish to expose as selection targets.
654 * We include the TARGETS item, and property aliases
656 cTargets = X11DRV_CountClipboardFormats() + 1;
658 for (wFormat = 0; (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
660 lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
664 if (!lpFormat->lpDrvExportFunc)
667 if (X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData))
670 /* else most likely unregistered format such as CF_PRIVATE or CF_GDIOBJ */
673 TRACE_(clipboard)(" found %ld formats\n", cTargets);
675 /* Allocate temp buffer */
676 targets = (Atom*)HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
680 /* Create TARGETS property list (First item in list is TARGETS itself) */
681 for (targets[0] = x11drv_atom(TARGETS), cTargets = 1, wFormat = 0;
682 (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
684 lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
688 if (lpFormat->lpDrvExportFunc)
690 if (EVENT_SelectionRequest_AddTARGETS(targets, cTargets, lpFormat->drvData))
694 /* Check if any alias should be listed */
695 alias = X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData);
698 if (EVENT_SelectionRequest_AddTARGETS(targets, cTargets, alias))
706 if (TRACE_ON(clipboard))
709 for ( i = 0; i < cTargets; i++)
713 char *itemFmtName = XGetAtomName(display, targets[i]);
714 TRACE_(clipboard)("\tAtom# %d: Property %ld Type %s\n", i, targets[i], itemFmtName);
720 /* We may want to consider setting the type to xaTargets instead,
721 * in case some apps expect this instead of XA_ATOM */
722 XChangeProperty(display, requestor, rprop, XA_ATOM, 32,
723 PropModeReplace, (unsigned char *)targets, cTargets);
726 HeapFree(GetProcessHeap(), 0, targets);
732 /***********************************************************************
733 * EVENT_SelectionRequest_MULTIPLE
734 * Service a MULTIPLE selection request event
735 * rprop contains a list of (target,property) atom pairs.
736 * The first atom names a target and the second names a property.
737 * The effect is as if we have received a sequence of SelectionRequest events
738 * (one for each atom pair) except that:
739 * 1. We reply with a SelectionNotify only when all the requested conversions
740 * have been performed.
741 * 2. If we fail to convert the target named by an atom in the MULTIPLE property,
742 * we replace the atom in the property by None.
744 static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
746 Display *display = pevent->display;
748 Atom atype=AnyPropertyType;
750 unsigned long remain;
751 Atom* targetPropList=NULL;
752 unsigned long cTargetPropList = 0;
754 /* If the specified property is None the requestor is an obsolete client.
755 * We support these by using the specified target atom as the reply property.
757 rprop = pevent->property;
759 rprop = pevent->target;
763 /* Read the MULTIPLE property contents. This should contain a list of
764 * (target,property) atom pairs.
767 if(XGetWindowProperty(display, pevent->requestor, rprop,
768 0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
769 &cTargetPropList, &remain,
770 (unsigned char**)&targetPropList) != Success)
773 TRACE("\tCouldn't read MULTIPLE property\n");
777 TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
778 XGetAtomName(display, atype), aformat, cTargetPropList, remain);
782 * Make sure we got what we expect.
783 * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
784 * in a MULTIPLE selection request should be of type ATOM_PAIR.
785 * However some X apps(such as XPaint) are not compliant with this and return
786 * a user defined atom in atype when XGetWindowProperty is called.
787 * The data *is* an atom pair but is not denoted as such.
789 if(aformat == 32 /* atype == xAtomPair */ )
793 /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
794 * for each (target,property) pair */
796 for (i = 0; i < cTargetPropList; i+=2)
798 XSelectionRequestEvent event;
802 char *targetName, *propName;
804 targetName = XGetAtomName(display, targetPropList[i]);
805 propName = XGetAtomName(display, targetPropList[i+1]);
806 TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
807 i/2, targetName, propName);
813 /* We must have a non "None" property to service a MULTIPLE target atom */
814 if ( !targetPropList[i+1] )
816 TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
820 /* Set up an XSelectionRequestEvent for this (target,property) pair */
821 memcpy( &event, pevent, sizeof(XSelectionRequestEvent) );
822 event.target = targetPropList[i];
823 event.property = targetPropList[i+1];
825 /* Fire a SelectionRequest, informing the handler that we are processing
826 * a MULTIPLE selection request event.
828 EVENT_SelectionRequest( hWnd, &event, TRUE );
832 /* Free the list of targets/properties */
834 XFree(targetPropList);
843 /***********************************************************************
844 * EVENT_SelectionRequest
845 * Process an event selection request event.
846 * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
847 * recursively while servicing a "MULTIPLE" selection target.
849 * Note: We only receive this event when WINE owns the X selection
851 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
853 Display *display = event->display;
854 XSelectionEvent result;
856 Window request = event->requestor;
858 TRACE_(clipboard)("\n");
861 * We can only handle the selection request if :
862 * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
863 * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
864 * since this has been already done.
868 if (((event->selection != XA_PRIMARY) && (event->selection != x11drv_atom(CLIPBOARD))))
872 /* If the specified property is None the requestor is an obsolete client.
873 * We support these by using the specified target atom as the reply property.
875 rprop = event->property;
877 rprop = event->target;
879 if(event->target == x11drv_atom(TARGETS)) /* Return a list of all supported targets */
881 /* TARGETS selection request */
882 rprop = EVENT_SelectionRequest_TARGETS( display, request, event->target, rprop );
884 else if(event->target == x11drv_atom(MULTIPLE)) /* rprop contains a list of (target, property) atom pairs */
886 /* MULTIPLE selection request */
887 rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
891 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(event->target);
894 lpFormat = X11DRV_CLIPBOARD_LookupAliasProperty(event->target);
896 if (lpFormat && lpFormat->lpDrvExportFunc)
898 LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(lpFormat->wFormatID);
902 unsigned char* lpClipData;
904 HANDLE hClipData = lpFormat->lpDrvExportFunc(request, event->target,
905 rprop, lpData, &cBytes);
907 if (hClipData && (lpClipData = GlobalLock(hClipData)))
909 TRACE_(clipboard)("\tUpdating property %s, %ld bytes\n",
910 debugstr_w(lpFormat->Name), cBytes);
913 XChangeProperty(display, request, rprop, event->target,
914 8, PropModeReplace, (unsigned char *)lpClipData, cBytes);
917 GlobalUnlock(hClipData);
918 GlobalFree(hClipData);
926 * SelectionNotify should be sent only at the end of a MULTIPLE request
930 result.type = SelectionNotify;
931 result.display = display;
932 result.requestor = request;
933 result.selection = event->selection;
934 result.property = rprop;
935 result.target = event->target;
936 result.time = event->time;
937 TRACE("Sending SelectionNotify event...\n");
939 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
944 /***********************************************************************
945 * EVENT_SelectionClear
947 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
949 if (event->selection == XA_PRIMARY || event->selection == x11drv_atom(CLIPBOARD))
950 X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd, event->time );
953 /***********************************************************************
954 * EVENT_PropertyNotify
955 * We use this to release resources like Pixmaps when a selection
956 * client no longer needs them.
958 static void EVENT_PropertyNotify( XPropertyEvent *event )
960 /* Check if we have any resources to free */
961 TRACE("Received PropertyNotify event: \n");
967 TRACE("\tPropertyDelete for atom %ld on window %ld\n",
968 event->atom, (long)event->window);
972 case PropertyNewValue:
974 TRACE("\tPropertyNewValue for atom %ld on window %ld\n\n",
975 event->atom, (long)event->window);
984 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
988 if (!IsWindowEnabled(hQueryWnd)) return 0;
990 GetWindowRect(hQueryWnd, &tempRect);
992 if(!PtInRect(&tempRect, *lpPt)) return 0;
994 if (!IsIconic( hQueryWnd ))
996 GetClientRect( hQueryWnd, &tempRect );
997 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
999 if (PtInRect( &tempRect, *lpPt))
1001 HWND *list = WIN_ListChildren( hQueryWnd );
1008 for (i = 0; list[i]; i++)
1010 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
1012 GetWindowRect( list[i], &tempRect );
1013 if (PtInRect( &tempRect, *lpPt )) break;
1018 if (IsWindowEnabled( list[i] ))
1019 bResult = find_drop_window( list[i], lpPt );
1021 HeapFree( GetProcessHeap(), 0, list );
1023 if(bResult) return bResult;
1027 if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
1029 ScreenToClient(hQueryWnd, lpPt);
1034 /**********************************************************************
1035 * EVENT_DropFromOffix
1037 * don't know if it still works (last Changlog is from 96/11/04)
1039 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
1041 unsigned long data_length;
1042 unsigned long aux_long;
1043 unsigned char* p_data = NULL;
1054 Window w_aux_root, w_aux_child;
1058 pWnd = WIN_FindWndPtr(hWnd);
1061 XQueryPointer( event->display, get_whole_window(pWnd), &w_aux_root, &w_aux_child,
1062 &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
1063 (unsigned int*)&aux_long);
1064 wine_tsx11_unlock();
1066 /* find out drop point and drop window */
1067 if( x < 0 || y < 0 ||
1068 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1069 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1071 bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES;
1077 POINT pt = { x, y };
1078 HWND hwndDrop = find_drop_window( hWnd, &pt );
1091 WIN_ReleaseWndPtr(pWnd);
1093 if (!bAccept) return;
1096 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1097 x11drv_atom(DndSelection), 0, 65535, FALSE,
1098 AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1099 &data_length, &aux_long, &p_data);
1100 wine_tsx11_unlock();
1102 if( !aux_long && p_data) /* don't bother if > 64K */
1104 signed char *p = (signed char*) p_data;
1108 while( *p ) /* calculate buffer size */
1111 if((u.i = *p) != -1 )
1113 INT len = GetShortPathNameA( p, NULL, 0 );
1114 if (len) aux_long += len + 1;
1119 if( aux_long && aux_long < 65535 )
1124 aux_long += sizeof(DROPFILES) + 1;
1125 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
1126 lpDrop = (DROPFILES*)GlobalLock( hDrop );
1130 WND *pDropWnd = WIN_FindWndPtr( hScope );
1131 lpDrop->pFiles = sizeof(DROPFILES);
1135 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1136 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1137 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1138 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1139 lpDrop->fWide = FALSE;
1140 WIN_ReleaseWndPtr(pDropWnd);
1141 p_drop = (char *)(lpDrop + 1);
1145 if( *p != -1 ) /* use only "good" entries */
1147 GetShortPathNameA( p, p_drop, 65535 );
1148 p_drop += strlen( p_drop ) + 1;
1153 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1158 if( p_data ) XFree(p_data);
1159 wine_tsx11_unlock();
1162 /**********************************************************************
1165 * drop items are separated by \n
1166 * each item is prefixed by its mime type
1168 * event->data.l[3], event->data.l[4] contains drop x,y position
1170 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
1172 unsigned long data_length;
1173 unsigned long aux_long, drop_len = 0;
1174 unsigned char *p_data = NULL; /* property data */
1175 char *p_drop = NULL;
1186 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
1189 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1190 x11drv_atom(DndSelection), 0, 65535, FALSE,
1191 AnyPropertyType, &u.atom_aux, &u.i,
1192 &data_length, &aux_long, &p_data);
1193 wine_tsx11_unlock();
1195 WARN("property too large, truncated!\n");
1196 TRACE("urls=%s\n", p_data);
1198 if( !aux_long && p_data) { /* don't bother if > 64K */
1199 /* calculate length */
1201 next = strchr(p, '\n');
1204 if (strncmp(p,"file:",5) == 0 ) {
1205 INT len = GetShortPathNameA( p+5, NULL, 0 );
1206 if (len) drop_len += len + 1;
1211 next = strchr(p, '\n');
1217 if( drop_len && drop_len < 65535 ) {
1219 XQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
1220 &x, &y, &u.i, &u.i, &u.i);
1221 wine_tsx11_unlock();
1223 drop_len += sizeof(DROPFILES) + 1;
1224 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
1225 lpDrop = (DROPFILES *) GlobalLock( hDrop );
1228 WND *pDropWnd = WIN_FindWndPtr( hWnd );
1229 lpDrop->pFiles = sizeof(DROPFILES);
1230 lpDrop->pt.x = (INT)x;
1231 lpDrop->pt.y = (INT)y;
1233 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1234 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1235 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1236 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1237 lpDrop->fWide = FALSE;
1238 p_drop = (char*)(lpDrop + 1);
1239 WIN_ReleaseWndPtr(pDropWnd);
1242 /* create message content */
1245 next = strchr(p, '\n');
1248 if (strncmp(p,"file:",5) == 0 ) {
1249 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
1251 TRACE("drop file %s as %s\n", p+5, p_drop);
1254 WARN("can't convert file %s to dos name \n", p+5);
1257 WARN("unknown mime type %s\n", p);
1262 next = strchr(p, '\n');
1269 GlobalUnlock(hDrop);
1270 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1274 if( p_data ) XFree(p_data);
1275 wine_tsx11_unlock();
1279 /**********************************************************************
1280 * EVENT_ClientMessage
1282 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
1284 if (event->message_type != None && event->format == 32) {
1285 if (event->message_type == x11drv_atom(WM_PROTOCOLS))
1286 handle_wm_protocols_message( hWnd, event );
1287 else if (event->message_type == x11drv_atom(DndProtocol))
1289 /* query window (drag&drop event contains only drag window) */
1291 int root_x, root_y, child_x, child_y;
1295 XQueryPointer( event->display, root_window, &root, &child,
1296 &root_x, &root_y, &child_x, &child_y, &u);
1297 if (XFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) hWnd = 0;
1298 wine_tsx11_unlock();
1300 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
1301 EVENT_DropFromOffiX(hWnd, event);
1302 else if (event->data.l[0] == DndURL)
1303 EVENT_DropURLs(hWnd, event);
1305 else if (!X11DRV_XDND_Event(hWnd, event))
1308 /* enable this if you want to see the message */
1309 unsigned char* p_data = NULL;
1316 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1317 dndSelection, 0, 65535, FALSE,
1318 AnyPropertyType, &u.atom, &u.i,
1319 &u.l, &u.l, &p_data);
1320 wine_tsx11_unlock();
1321 TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1322 event->message_type, event->data.l[0], event->data.l[1],
1323 event->data.l[2], event->data.l[3], event->data.l[4],
1326 TRACE("unrecognized ClientMessage\n" );
1332 /**********************************************************************
1333 * X11DRV_EVENT_SetInputMethod
1335 INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
1337 INPUT_TYPE prev = current_input_type;
1339 /* Flag not used yet */
1340 in_transition = FALSE;
1341 current_input_type = type;
1346 #ifdef HAVE_LIBXXF86DGA2
1347 /**********************************************************************
1348 * X11DRV_EVENT_SetDGAStatus
1350 void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
1352 if (event_base < 0) {
1358 DGAMotionEventType = event_base + MotionNotify;
1359 DGAButtonPressEventType = event_base + ButtonPress;
1360 DGAButtonReleaseEventType = event_base + ButtonRelease;
1361 DGAKeyPressEventType = event_base + KeyPress;
1362 DGAKeyReleaseEventType = event_base + KeyRelease;