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 */
44 #include "clipboard.h"
50 #include "wine/debug.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(event);
53 WINE_DECLARE_DEBUG_CHANNEL(clipboard);
55 /* X context to associate a hwnd to an X window */
56 extern XContext winContext;
58 #define DndNotDnd -1 /* OffiX drag&drop */
70 #define DndURL 128 /* KDE drag&drop */
72 static const char * const event_names[] =
74 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
75 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
76 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
77 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
78 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
79 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
80 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
81 "ClientMessage", "MappingNotify"
85 static void EVENT_ProcessEvent( XEvent *event );
88 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
89 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
90 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
91 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
92 static void EVENT_PropertyNotify( XPropertyEvent *event );
93 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
95 extern void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event );
96 extern void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event );
97 extern void X11DRV_MotionNotify( HWND hwnd, XMotionEvent *event );
98 extern void X11DRV_EnterNotify( HWND hwnd, XCrossingEvent *event );
99 extern void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event );
100 extern void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event );
101 extern void X11DRV_Expose( HWND hwnd, XExposeEvent *event );
102 extern void X11DRV_MapNotify( HWND hwnd, XMapEvent *event );
103 extern void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event );
104 extern void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
105 extern void X11DRV_MappingNotify( XMappingEvent *event );
107 #ifdef HAVE_LIBXXF86DGA2
108 static int DGAMotionEventType;
109 static int DGAButtonPressEventType;
110 static int DGAButtonReleaseEventType;
111 static int DGAKeyPressEventType;
112 static int DGAKeyReleaseEventType;
114 static BOOL DGAUsed = FALSE;
115 static HWND DGAhwnd = 0;
117 extern void X11DRV_DGAMotionEvent( HWND hwnd, XDGAMotionEvent *event );
118 extern void X11DRV_DGAButtonPressEvent( HWND hwnd, XDGAButtonEvent *event );
119 extern void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XDGAButtonEvent *event );
122 /* Static used for the current input method */
123 static INPUT_TYPE current_input_type = X11DRV_INPUT_ABSOLUTE;
124 static BOOL in_transition = FALSE; /* This is not used as for today */
127 /***********************************************************************
130 static int process_events( struct x11drv_thread_data *data )
136 while ( XPending( data->display ) )
140 XNextEvent( data->display, &event );
141 ignore = XFilterEvent( &event, None );
143 if (!ignore) EVENT_ProcessEvent( &event );
152 /***********************************************************************
153 * MsgWaitForMultipleObjectsEx (X11DRV.@)
155 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
156 DWORD timeout, DWORD mask, DWORD flags )
158 HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1]; /* FIXME! */
160 struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
162 if (!data || data->process_event_count)
163 return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
164 timeout, flags & MWMO_ALERTABLE );
166 /* check whether only server queue handle was passed in */
167 if (count < 2) flags &= ~MWMO_WAITALL;
169 for (i = 0; i < count; i++) new_handles[i] = handles[i];
170 new_handles[count] = data->display_fd;
173 XFlush( gdi_display );
174 XFlush( data->display );
177 data->process_event_count++;
178 if (process_events( data )) ret = count;
181 ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
182 timeout, flags & MWMO_ALERTABLE );
183 if (ret == count) process_events( data );
185 data->process_event_count--;
190 /***********************************************************************
193 * Process an X event.
195 static void EVENT_ProcessEvent( XEvent *event )
198 Display *display = event->xany.display;
200 TRACE( "called.\n" );
204 case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
205 FIXME("Got SelectionNotify - must not happen!\n");
208 /* We get all these because of StructureNotifyMask.
209 This check is placed here to avoid getting error messages below,
210 as X might send some of these even for windows that have already
212 case CirculateNotify:
220 #ifdef HAVE_LIBXXF86DGA2
222 if (event->type == DGAMotionEventType) {
223 TRACE("DGAMotionEvent received.\n");
224 X11DRV_DGAMotionEvent( DGAhwnd, (XDGAMotionEvent *)event );
227 if (event->type == DGAButtonPressEventType) {
228 TRACE("DGAButtonPressEvent received.\n");
229 X11DRV_DGAButtonPressEvent( DGAhwnd, (XDGAButtonEvent *)event );
232 if (event->type == DGAButtonReleaseEventType) {
233 TRACE("DGAButtonReleaseEvent received.\n");
234 X11DRV_DGAButtonReleaseEvent( DGAhwnd, (XDGAButtonEvent *)event );
237 if ((event->type == DGAKeyPressEventType) ||
238 (event->type == DGAKeyReleaseEventType)) {
239 /* Fill a XKeyEvent to send to EVENT_Key */
241 XDGAKeyEvent *evt = (XDGAKeyEvent *) event;
243 TRACE("DGAKeyPress/ReleaseEvent received.\n");
245 if (evt->type == DGAKeyReleaseEventType)
246 ke.type = KeyRelease;
249 ke.serial = evt->serial;
250 ke.send_event = FALSE;
251 ke.display = evt->display;
260 ke.state = evt->state;
261 ke.keycode = evt->keycode;
262 ke.same_screen = TRUE;
263 X11DRV_KeyEvent( 0, &ke );
270 if (XFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
271 hWnd = 0; /* Not for a registered window */
273 if (!hWnd && event->xany.window == root_window) hWnd = GetDesktopWindow();
275 if (!hWnd && event->type != PropertyNotify && event->type != MappingNotify)
276 WARN( "Got event %s for unknown Window %08lx\n",
277 event_names[event->type], event->xany.window );
279 TRACE("Got event %s for hwnd %p\n",
280 event_names[event->type], hWnd );
286 /* FIXME: should generate a motion event if event point is different from current pos */
287 X11DRV_KeyEvent( hWnd, (XKeyEvent*)event );
291 X11DRV_ButtonPress( hWnd, (XButtonEvent*)event );
295 X11DRV_ButtonRelease( hWnd, (XButtonEvent*)event );
299 X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
303 X11DRV_EnterNotify( hWnd, (XCrossingEvent*)event );
307 EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
311 EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
315 X11DRV_Expose( hWnd, &event->xexpose );
318 case ConfigureNotify:
320 X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
323 case SelectionRequest:
325 EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
330 EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
334 EVENT_PropertyNotify( (XPropertyEvent *)event );
339 EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
346 X11DRV_MapNotify( hWnd, (XMapEvent *)event );
350 X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
354 X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
358 X11DRV_MappingNotify( (XMappingEvent *) event );
362 WARN("Unprocessed event %s for hwnd %p\n", event_names[event->type], hWnd );
365 TRACE( "returns.\n" );
369 /*******************************************************************
370 * can_activate_window
372 * Check if we can activate the specified window.
374 inline static BOOL can_activate_window( HWND hwnd )
376 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
377 if (!(style & WS_VISIBLE)) return FALSE;
378 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
379 return !(style & WS_DISABLED);
383 /**********************************************************************
386 static void set_focus( HWND hwnd, Time time )
391 TRACE( "setting foreground window to %p\n", hwnd );
392 SetForegroundWindow( hwnd );
395 if (focus) focus = GetAncestor( focus, GA_ROOT );
396 win = X11DRV_get_whole_window(focus);
400 TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time );
402 XSetInputFocus( thread_display(), win, RevertToParent, time );
408 /**********************************************************************
409 * handle_wm_protocols_message
411 static void handle_wm_protocols_message( HWND hwnd, XClientMessageEvent *event )
413 Atom protocol = (Atom)event->data.l[0];
415 if (!protocol) return;
417 if (protocol == x11drv_atom(WM_DELETE_WINDOW))
419 /* Ignore the delete window request if the window has been disabled
420 * and we are in managed mode. This is to disallow applications from
421 * being closed by the window manager while in a modal state.
423 if (IsWindowEnabled(hwnd)) PostMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
425 else if (protocol == x11drv_atom(WM_TAKE_FOCUS))
427 Time event_time = (Time)event->data.l[1];
428 HWND last_focus = x11drv_thread_data()->last_focus;
430 TRACE( "got take focus msg for %p, enabled=%d, focus=%p, active=%p, fg=%p, last=%p\n",
431 hwnd, IsWindowEnabled(hwnd), GetFocus(), GetActiveWindow(),
432 GetForegroundWindow(), last_focus );
434 if (can_activate_window(hwnd))
436 /* simulate a mouse click on the caption to find out
437 * whether the window wants to be activated */
438 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
439 (WPARAM)GetAncestor( hwnd, GA_ROOT ),
440 MAKELONG(HTCAPTION,WM_LBUTTONDOWN) );
441 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) set_focus( hwnd, event_time );
442 else TRACE( "not setting focus to %p (%lx), ma=%ld\n", hwnd, event->window, ma );
447 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
448 if (!hwnd) hwnd = GetActiveWindow();
449 if (!hwnd) hwnd = last_focus;
450 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
453 else if (protocol == x11drv_atom(_NET_WM_PING))
455 XClientMessageEvent xev;
458 TRACE("NET_WM Ping\n");
459 xev.window = DefaultRootWindow(xev.display);
460 XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
461 /* this line is semi-stolen from gtk2 */
462 TRACE("NET_WM Pong\n");
467 static const char * const focus_details[] =
473 "NotifyNonlinearVirtual",
479 /**********************************************************************
482 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
488 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
490 if (event->detail == NotifyPointer) return;
492 if ((xic = X11DRV_get_ic( hwnd )))
498 if (use_take_focus) return; /* ignore FocusIn if we are using take focus */
500 if (!can_activate_window(hwnd))
502 HWND hwnd = GetFocus();
503 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
504 if (!hwnd) hwnd = GetActiveWindow();
505 if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
506 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
508 else SetForegroundWindow( hwnd );
512 /**********************************************************************
515 * Note: only top-level windows get FocusOut events.
517 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
524 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
526 if (event->detail == NotifyPointer) return;
527 x11drv_thread_data()->last_focus = hwnd;
528 if ((xic = X11DRV_get_ic( hwnd )))
531 XUnsetICFocus( xic );
534 if (hwnd != GetForegroundWindow()) return;
535 SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
537 /* don't reset the foreground window, if the window which is
538 getting the focus is a Wine window */
541 XGetInputFocus( thread_display(), &focus_win, &revert );
544 if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
551 /* Abey : 6-Oct-99. Check again if the focus out window is the
552 Foreground window, because in most cases the messages sent
553 above must have already changed the foreground window, in which
554 case we don't have to change the foreground window to 0 */
555 if (hwnd == GetForegroundWindow())
557 TRACE( "lost focus, setting fg to 0\n" );
558 SetForegroundWindow( 0 );
564 /***********************************************************************
565 * EVENT_SelectionRequest_AddTARGETS
566 * Utility function for EVENT_SelectionRequest_TARGETS.
568 static void EVENT_SelectionRequest_AddTARGETS(Atom* targets, unsigned long* cTargets, Atom prop)
573 /* Scan through what we have so far to avoid duplicates */
574 for (i = 0, bExists = FALSE; i < *cTargets; i++)
576 if (targets[i] == prop)
584 targets[(*cTargets)++] = prop;
588 /***********************************************************************
589 * EVENT_SelectionRequest_TARGETS
590 * Service a TARGETS selection request event
592 static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
593 Atom target, Atom rprop )
601 * Count the number of items we wish to expose as selection targets.
602 * We include the TARGETS item, and propery aliases
604 cTargets = X11DRV_CountClipboardFormats() + 1;
606 for (wFormat = 0; (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
608 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
609 if (lpFormat && X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData))
613 TRACE_(clipboard)(" found %ld formats\n", cTargets);
615 /* Allocate temp buffer */
616 targets = (Atom*)HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
620 /* Create TARGETS property list (First item in list is TARGETS itself) */
621 for (targets[0] = x11drv_atom(TARGETS), cTargets = 1, wFormat = 0;
622 (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
624 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
626 EVENT_SelectionRequest_AddTARGETS(targets, &cTargets, lpFormat->drvData);
628 /* Check if any alias should be listed */
629 alias = X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData);
631 EVENT_SelectionRequest_AddTARGETS(targets, &cTargets, alias);
636 if (TRACE_ON(clipboard))
639 for ( i = 0; i < cTargets; i++)
643 char *itemFmtName = XGetAtomName(display, targets[i]);
644 TRACE_(clipboard)("\tAtom# %d: Property %ld Type %s\n", i, targets[i], itemFmtName);
650 /* We may want to consider setting the type to xaTargets instead,
651 * in case some apps expect this instead of XA_ATOM */
652 XChangeProperty(display, requestor, rprop, XA_ATOM, 32,
653 PropModeReplace, (unsigned char *)targets, cTargets);
656 HeapFree(GetProcessHeap(), 0, targets);
662 /***********************************************************************
663 * EVENT_SelectionRequest_MULTIPLE
664 * Service a MULTIPLE selection request event
665 * rprop contains a list of (target,property) atom pairs.
666 * The first atom names a target and the second names a property.
667 * The effect is as if we have received a sequence of SelectionRequest events
668 * (one for each atom pair) except that:
669 * 1. We reply with a SelectionNotify only when all the requested conversions
670 * have been performed.
671 * 2. If we fail to convert the target named by an atom in the MULTIPLE property,
672 * we replace the atom in the property by None.
674 static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
676 Display *display = pevent->display;
678 Atom atype=AnyPropertyType;
680 unsigned long remain;
681 Atom* targetPropList=NULL;
682 unsigned long cTargetPropList = 0;
684 /* If the specified property is None the requestor is an obsolete client.
685 * We support these by using the specified target atom as the reply property.
687 rprop = pevent->property;
689 rprop = pevent->target;
693 /* Read the MULTIPLE property contents. This should contain a list of
694 * (target,property) atom pairs.
697 if(XGetWindowProperty(display, pevent->requestor, rprop,
698 0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
699 &cTargetPropList, &remain,
700 (unsigned char**)&targetPropList) != Success)
703 TRACE("\tCouldn't read MULTIPLE property\n");
707 TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
708 XGetAtomName(display, atype), aformat, cTargetPropList, remain);
712 * Make sure we got what we expect.
713 * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
714 * in a MULTIPLE selection request should be of type ATOM_PAIR.
715 * However some X apps(such as XPaint) are not compliant with this and return
716 * a user defined atom in atype when XGetWindowProperty is called.
717 * The data *is* an atom pair but is not denoted as such.
719 if(aformat == 32 /* atype == xAtomPair */ )
723 /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
724 * for each (target,property) pair */
726 for (i = 0; i < cTargetPropList; i+=2)
728 XSelectionRequestEvent event;
732 char *targetName, *propName;
734 targetName = XGetAtomName(display, targetPropList[i]);
735 propName = XGetAtomName(display, targetPropList[i+1]);
736 TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
737 i/2, targetName, propName);
743 /* We must have a non "None" property to service a MULTIPLE target atom */
744 if ( !targetPropList[i+1] )
746 TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
750 /* Set up an XSelectionRequestEvent for this (target,property) pair */
751 memcpy( &event, pevent, sizeof(XSelectionRequestEvent) );
752 event.target = targetPropList[i];
753 event.property = targetPropList[i+1];
755 /* Fire a SelectionRequest, informing the handler that we are processing
756 * a MULTIPLE selection request event.
758 EVENT_SelectionRequest( hWnd, &event, TRUE );
762 /* Free the list of targets/properties */
764 XFree(targetPropList);
773 /***********************************************************************
774 * EVENT_SelectionRequest
775 * Process an event selection request event.
776 * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
777 * recursively while servicing a "MULTIPLE" selection target.
779 * Note: We only receive this event when WINE owns the X selection
781 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
783 Display *display = event->display;
784 XSelectionEvent result;
786 Window request = event->requestor;
788 TRACE_(clipboard)("\n");
791 * We can only handle the selection request if :
792 * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
793 * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
794 * since this has been already done.
798 if (((event->selection != XA_PRIMARY) && (event->selection != x11drv_atom(CLIPBOARD))))
802 /* If the specified property is None the requestor is an obsolete client.
803 * We support these by using the specified target atom as the reply property.
805 rprop = event->property;
807 rprop = event->target;
809 if(event->target == x11drv_atom(TARGETS)) /* Return a list of all supported targets */
811 /* TARGETS selection request */
812 rprop = EVENT_SelectionRequest_TARGETS( display, request, event->target, rprop );
814 else if(event->target == x11drv_atom(MULTIPLE)) /* rprop contains a list of (target, property) atom pairs */
816 /* MULTIPLE selection request */
817 rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
821 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(event->target);
824 lpFormat = X11DRV_CLIPBOARD_LookupAliasProperty(event->target);
828 LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(lpFormat->wFormatID);
832 unsigned char* lpClipData;
834 HANDLE hClipData = lpFormat->lpDrvExportFunc(request, event->target,
835 rprop, lpData, &cBytes);
837 if (hClipData && (lpClipData = GlobalLock(hClipData)))
840 TRACE_(clipboard)("\tUpdating property %s, %ld bytes\n",
841 lpFormat->Name, cBytes);
844 XChangeProperty(display, request, rprop, event->target,
845 8, PropModeReplace, (unsigned char *)lpClipData, cBytes);
848 GlobalUnlock(hClipData);
849 GlobalFree(hClipData);
857 * SelectionNotify should be sent only at the end of a MULTIPLE request
861 result.type = SelectionNotify;
862 result.display = display;
863 result.requestor = request;
864 result.selection = event->selection;
865 result.property = rprop;
866 result.target = event->target;
867 result.time = event->time;
868 TRACE("Sending SelectionNotify event...\n");
870 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
875 /***********************************************************************
876 * EVENT_SelectionClear
878 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
880 if (event->selection == XA_PRIMARY || event->selection == x11drv_atom(CLIPBOARD))
881 X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
884 /***********************************************************************
885 * EVENT_PropertyNotify
886 * We use this to release resources like Pixmaps when a selection
887 * client no longer needs them.
889 static void EVENT_PropertyNotify( XPropertyEvent *event )
891 /* Check if we have any resources to free */
892 TRACE("Received PropertyNotify event: \n");
898 TRACE("\tPropertyDelete for atom %ld on window %ld\n",
899 event->atom, (long)event->window);
903 case PropertyNewValue:
905 TRACE("\tPropertyNewValue for atom %ld on window %ld\n\n",
906 event->atom, (long)event->window);
915 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
919 if (!IsWindowEnabled(hQueryWnd)) return 0;
921 GetWindowRect(hQueryWnd, &tempRect);
923 if(!PtInRect(&tempRect, *lpPt)) return 0;
925 if (!IsIconic( hQueryWnd ))
927 GetClientRect( hQueryWnd, &tempRect );
928 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
930 if (PtInRect( &tempRect, *lpPt))
932 HWND *list = WIN_ListChildren( hQueryWnd );
939 for (i = 0; list[i]; i++)
941 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
943 GetWindowRect( list[i], &tempRect );
944 if (PtInRect( &tempRect, *lpPt )) break;
949 if (IsWindowEnabled( list[i] ))
950 bResult = find_drop_window( list[i], lpPt );
952 HeapFree( GetProcessHeap(), 0, list );
954 if(bResult) return bResult;
958 if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
960 ScreenToClient(hQueryWnd, lpPt);
965 /**********************************************************************
966 * EVENT_DropFromOffix
968 * don't know if it still works (last Changlog is from 96/11/04)
970 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
972 unsigned long data_length;
973 unsigned long aux_long;
974 unsigned char* p_data = NULL;
985 Window w_aux_root, w_aux_child;
989 pWnd = WIN_FindWndPtr(hWnd);
992 XQueryPointer( event->display, get_whole_window(pWnd), &w_aux_root, &w_aux_child,
993 &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
994 (unsigned int*)&aux_long);
997 /* find out drop point and drop window */
998 if( x < 0 || y < 0 ||
999 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1000 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1002 bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES;
1008 POINT pt = { x, y };
1009 HWND hwndDrop = find_drop_window( hWnd, &pt );
1022 WIN_ReleaseWndPtr(pWnd);
1024 if (!bAccept) return;
1027 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1028 x11drv_atom(DndSelection), 0, 65535, FALSE,
1029 AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1030 &data_length, &aux_long, &p_data);
1031 wine_tsx11_unlock();
1033 if( !aux_long && p_data) /* don't bother if > 64K */
1035 signed char *p = (signed char*) p_data;
1039 while( *p ) /* calculate buffer size */
1042 if((u.i = *p) != -1 )
1044 INT len = GetShortPathNameA( p, NULL, 0 );
1045 if (len) aux_long += len + 1;
1050 if( aux_long && aux_long < 65535 )
1055 aux_long += sizeof(DROPFILES) + 1;
1056 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
1057 lpDrop = (DROPFILES*)GlobalLock( hDrop );
1061 WND *pDropWnd = WIN_FindWndPtr( hScope );
1062 lpDrop->pFiles = sizeof(DROPFILES);
1066 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1067 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1068 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1069 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1070 lpDrop->fWide = FALSE;
1071 WIN_ReleaseWndPtr(pDropWnd);
1072 p_drop = (char *)(lpDrop + 1);
1076 if( *p != -1 ) /* use only "good" entries */
1078 GetShortPathNameA( p, p_drop, 65535 );
1079 p_drop += strlen( p_drop ) + 1;
1084 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1089 if( p_data ) XFree(p_data);
1090 wine_tsx11_unlock();
1093 /**********************************************************************
1096 * drop items are separated by \n
1097 * each item is prefixed by its mime type
1099 * event->data.l[3], event->data.l[4] contains drop x,y position
1101 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
1103 unsigned long data_length;
1104 unsigned long aux_long, drop_len = 0;
1105 unsigned char *p_data = NULL; /* property data */
1106 char *p_drop = NULL;
1117 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
1120 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1121 x11drv_atom(DndSelection), 0, 65535, FALSE,
1122 AnyPropertyType, &u.atom_aux, &u.i,
1123 &data_length, &aux_long, &p_data);
1124 wine_tsx11_unlock();
1126 WARN("property too large, truncated!\n");
1127 TRACE("urls=%s\n", p_data);
1129 if( !aux_long && p_data) { /* don't bother if > 64K */
1130 /* calculate length */
1132 next = strchr(p, '\n');
1135 if (strncmp(p,"file:",5) == 0 ) {
1136 INT len = GetShortPathNameA( p+5, NULL, 0 );
1137 if (len) drop_len += len + 1;
1142 next = strchr(p, '\n');
1148 if( drop_len && drop_len < 65535 ) {
1150 XQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
1151 &x, &y, &u.i, &u.i, &u.i);
1152 wine_tsx11_unlock();
1154 drop_len += sizeof(DROPFILES) + 1;
1155 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
1156 lpDrop = (DROPFILES *) GlobalLock( hDrop );
1159 WND *pDropWnd = WIN_FindWndPtr( hWnd );
1160 lpDrop->pFiles = sizeof(DROPFILES);
1161 lpDrop->pt.x = (INT)x;
1162 lpDrop->pt.y = (INT)y;
1164 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1165 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1166 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1167 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1168 lpDrop->fWide = FALSE;
1169 p_drop = (char*)(lpDrop + 1);
1170 WIN_ReleaseWndPtr(pDropWnd);
1173 /* create message content */
1176 next = strchr(p, '\n');
1179 if (strncmp(p,"file:",5) == 0 ) {
1180 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
1182 TRACE("drop file %s as %s\n", p+5, p_drop);
1185 WARN("can't convert file %s to dos name \n", p+5);
1188 WARN("unknown mime type %s\n", p);
1193 next = strchr(p, '\n');
1200 GlobalUnlock(hDrop);
1201 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1205 if( p_data ) XFree(p_data);
1206 wine_tsx11_unlock();
1210 /**********************************************************************
1211 * EVENT_ClientMessage
1213 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
1215 if (event->message_type != None && event->format == 32) {
1216 if (event->message_type == x11drv_atom(WM_PROTOCOLS))
1217 handle_wm_protocols_message( hWnd, event );
1218 else if (event->message_type == x11drv_atom(DndProtocol))
1220 /* query window (drag&drop event contains only drag window) */
1222 int root_x, root_y, child_x, child_y;
1226 XQueryPointer( event->display, root_window, &root, &child,
1227 &root_x, &root_y, &child_x, &child_y, &u);
1228 if (XFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) hWnd = 0;
1229 wine_tsx11_unlock();
1231 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
1232 EVENT_DropFromOffiX(hWnd, event);
1233 else if (event->data.l[0] == DndURL)
1234 EVENT_DropURLs(hWnd, event);
1236 else if (!X11DRV_XDND_Event(hWnd, event))
1239 /* enable this if you want to see the message */
1240 unsigned char* p_data = NULL;
1247 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1248 dndSelection, 0, 65535, FALSE,
1249 AnyPropertyType, &u.atom, &u.i,
1250 &u.l, &u.l, &p_data);
1251 wine_tsx11_unlock();
1252 TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1253 event->message_type, event->data.l[0], event->data.l[1],
1254 event->data.l[2], event->data.l[3], event->data.l[4],
1257 TRACE("unrecognized ClientMessage\n" );
1263 /**********************************************************************
1264 * X11DRV_EVENT_SetInputMethod
1266 INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
1268 INPUT_TYPE prev = current_input_type;
1270 /* Flag not used yet */
1271 in_transition = FALSE;
1272 current_input_type = type;
1277 #ifdef HAVE_LIBXXF86DGA2
1278 /**********************************************************************
1279 * X11DRV_EVENT_SetDGAStatus
1281 void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
1283 if (event_base < 0) {
1289 DGAMotionEventType = event_base + MotionNotify;
1290 DGAButtonPressEventType = event_base + ButtonPress;
1291 DGAButtonReleaseEventType = event_base + ButtonRelease;
1292 DGAKeyPressEventType = event_base + KeyPress;
1293 DGAKeyReleaseEventType = event_base + KeyRelease;