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 */
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(event);
51 WINE_DECLARE_DEBUG_CHANNEL(clipboard);
53 extern BOOL ximInComposeMode;
55 #define DndNotDnd -1 /* OffiX drag&drop */
67 #define DndURL 128 /* KDE drag&drop */
69 static const char * const event_names[] =
71 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
72 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
73 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
74 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
75 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
76 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
77 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
78 "ClientMessage", "MappingNotify"
82 static void EVENT_ProcessEvent( XEvent *event );
85 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
86 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
87 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
88 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
89 static void EVENT_PropertyNotify( XPropertyEvent *event );
90 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
92 #ifdef HAVE_LIBXXF86DGA2
93 static int DGAMotionEventType;
94 static int DGAButtonPressEventType;
95 static int DGAButtonReleaseEventType;
96 static int DGAKeyPressEventType;
97 static int DGAKeyReleaseEventType;
99 static BOOL DGAUsed = FALSE;
100 static HWND DGAhwnd = 0;
103 /* Static used for the current input method */
104 static INPUT_TYPE current_input_type = X11DRV_INPUT_ABSOLUTE;
105 static BOOL in_transition = FALSE; /* This is not used as for today */
108 /***********************************************************************
111 static int process_events( struct x11drv_thread_data *data )
117 while ( XPending( data->display ) )
121 XNextEvent( data->display, &event );
122 ignore = XFilterEvent( &event, None );
124 if (!ignore) EVENT_ProcessEvent( &event );
133 /***********************************************************************
134 * MsgWaitForMultipleObjectsEx (X11DRV.@)
136 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
137 DWORD timeout, DWORD mask, DWORD flags )
139 HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1]; /* FIXME! */
141 struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
143 if (!data || data->process_event_count)
144 return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
145 timeout, flags & MWMO_ALERTABLE );
147 /* check whether only server queue handle was passed in */
148 if (count < 2) flags &= ~MWMO_WAITALL;
150 for (i = 0; i < count; i++) new_handles[i] = handles[i];
151 new_handles[count] = data->display_fd;
154 XFlush( gdi_display );
155 XFlush( data->display );
158 data->process_event_count++;
159 if (process_events( data )) ret = count;
162 ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
163 timeout, flags & MWMO_ALERTABLE );
164 if (ret == count) process_events( data );
166 data->process_event_count--;
170 /***********************************************************************
171 * EVENT_x11_time_to_win32_time
173 * Make our timer and the X timer line up as best we can
174 * Pass 0 to retrieve the current adjustment value (times -1)
176 DWORD EVENT_x11_time_to_win32_time(Time time)
178 static DWORD adjust = 0;
179 DWORD now = GetTickCount();
182 if (! adjust && time != 0)
189 /* If we got an event in the 'future', then our clock is clearly wrong.
190 If we got it more than 10000 ms in the future, then it's most likely
191 that the clock has wrapped. */
194 if (ret > now && ((ret - now) < 10000) && time != 0)
205 /***********************************************************************
208 * Process an X event.
210 static void EVENT_ProcessEvent( XEvent *event )
213 Display *display = event->xany.display;
215 TRACE( "called.\n" );
219 case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
220 FIXME("Got SelectionNotify - must not happen!\n");
223 /* We get all these because of StructureNotifyMask.
224 This check is placed here to avoid getting error messages below,
225 as X might send some of these even for windows that have already
227 case CirculateNotify:
235 #ifdef HAVE_LIBXXF86DGA2
237 if (event->type == DGAMotionEventType) {
238 TRACE("DGAMotionEvent received.\n");
239 X11DRV_DGAMotionEvent( DGAhwnd, (XDGAMotionEvent *)event );
242 if (event->type == DGAButtonPressEventType) {
243 TRACE("DGAButtonPressEvent received.\n");
244 X11DRV_DGAButtonPressEvent( DGAhwnd, (XDGAButtonEvent *)event );
247 if (event->type == DGAButtonReleaseEventType) {
248 TRACE("DGAButtonReleaseEvent received.\n");
249 X11DRV_DGAButtonReleaseEvent( DGAhwnd, (XDGAButtonEvent *)event );
252 if ((event->type == DGAKeyPressEventType) ||
253 (event->type == DGAKeyReleaseEventType)) {
254 /* Fill a XKeyEvent to send to EVENT_Key */
256 XDGAKeyEvent *evt = (XDGAKeyEvent *) event;
258 TRACE("DGAKeyPress/ReleaseEvent received.\n");
260 if (evt->type == DGAKeyReleaseEventType)
261 ke.type = KeyRelease;
264 ke.serial = evt->serial;
265 ke.send_event = FALSE;
266 ke.display = evt->display;
275 ke.state = evt->state;
276 ke.keycode = evt->keycode;
277 ke.same_screen = TRUE;
278 X11DRV_KeyEvent( 0, &ke );
285 if (XFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
286 hWnd = 0; /* Not for a registered window */
288 if (!hWnd && event->xany.window == root_window) hWnd = GetDesktopWindow();
290 if (!hWnd && event->type != PropertyNotify &&
291 event->type != MappingNotify && event->type != KeymapNotify)
292 WARN( "Got event %s for unknown Window %08lx\n",
293 event_names[event->type], event->xany.window );
294 else if (event->type <= MappingNotify)
295 TRACE("Got event %s for hwnd/window %p/%lx, GetFocus()=%p\n",
296 event_names[event->type], hWnd, event->xany.window, GetFocus() );
298 TRACE("Got extension event for hwnd/window %p/%lx, GetFocus()=%p\n",
299 hWnd, event->xany.window, GetFocus() );
301 if (X11DRV_ProcessTabletEvent(hWnd, event))
303 TRACE("Return: filtered by tablet\n");
311 /* FIXME: should generate a motion event if event point is different from current pos */
312 X11DRV_KeyEvent( hWnd, (XKeyEvent*)event );
316 X11DRV_ButtonPress( hWnd, (XButtonEvent*)event );
320 X11DRV_ButtonRelease( hWnd, (XButtonEvent*)event );
324 X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
328 X11DRV_EnterNotify( hWnd, (XCrossingEvent*)event );
332 EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
336 EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
340 X11DRV_Expose( hWnd, &event->xexpose );
343 case ConfigureNotify:
345 X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
348 case SelectionRequest:
350 EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
355 EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
359 EVENT_PropertyNotify( (XPropertyEvent *)event );
364 EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
371 X11DRV_MapNotify( hWnd, (XMapEvent *)event );
375 X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
379 X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
383 X11DRV_MappingNotify( (XMappingEvent *) event );
387 WARN("Unprocessed event %s for hwnd %p\n", event_names[event->type], hWnd );
390 TRACE( "returns.\n" );
394 /*******************************************************************
395 * can_activate_window
397 * Check if we can activate the specified window.
399 inline static BOOL can_activate_window( HWND hwnd )
401 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
402 if (!(style & WS_VISIBLE)) return FALSE;
403 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
404 return !(style & WS_DISABLED);
408 /**********************************************************************
411 static void set_focus( HWND hwnd, Time time )
416 TRACE( "setting foreground window to %p\n", hwnd );
417 SetForegroundWindow( hwnd );
420 if (focus) focus = GetAncestor( focus, GA_ROOT );
421 win = X11DRV_get_whole_window(focus);
425 TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time );
427 XSetInputFocus( thread_display(), win, RevertToParent, time );
433 /**********************************************************************
434 * handle_wm_protocols_message
436 static void handle_wm_protocols_message( HWND hwnd, XClientMessageEvent *event )
438 Atom protocol = (Atom)event->data.l[0];
440 if (!protocol) return;
442 if (protocol == x11drv_atom(WM_DELETE_WINDOW))
444 /* Ignore the delete window request if the window has been disabled
445 * and we are in managed mode. This is to disallow applications from
446 * being closed by the window manager while in a modal state.
448 if (IsWindowEnabled(hwnd)) PostMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
450 else if (protocol == x11drv_atom(WM_TAKE_FOCUS))
452 Time event_time = (Time)event->data.l[1];
453 HWND last_focus = x11drv_thread_data()->last_focus;
455 TRACE( "got take focus msg for %p, enabled=%d, focus=%p, active=%p, fg=%p, last=%p\n",
456 hwnd, IsWindowEnabled(hwnd), GetFocus(), GetActiveWindow(),
457 GetForegroundWindow(), last_focus );
459 if (can_activate_window(hwnd))
461 /* simulate a mouse click on the caption to find out
462 * whether the window wants to be activated */
463 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
464 (WPARAM)GetAncestor( hwnd, GA_ROOT ),
465 MAKELONG(HTCAPTION,WM_LBUTTONDOWN) );
466 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) set_focus( hwnd, event_time );
467 else TRACE( "not setting focus to %p (%lx), ma=%ld\n", hwnd, event->window, ma );
472 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
473 if (!hwnd) hwnd = GetActiveWindow();
474 if (!hwnd) hwnd = last_focus;
475 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
478 else if (protocol == x11drv_atom(_NET_WM_PING))
480 XClientMessageEvent xev;
483 TRACE("NET_WM Ping\n");
484 xev.window = DefaultRootWindow(xev.display);
485 XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
486 /* this line is semi-stolen from gtk2 */
487 TRACE("NET_WM Pong\n");
492 static const char * const focus_details[] =
498 "NotifyNonlinearVirtual",
504 /**********************************************************************
507 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
513 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
515 if (event->detail == NotifyPointer) return;
517 if ((xic = X11DRV_get_ic( hwnd )))
523 if (use_take_focus) return; /* ignore FocusIn if we are using take focus */
525 if (!can_activate_window(hwnd))
527 HWND hwnd = GetFocus();
528 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
529 if (!hwnd) hwnd = GetActiveWindow();
530 if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
531 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
533 else SetForegroundWindow( hwnd );
537 /**********************************************************************
540 * Note: only top-level windows get FocusOut events.
542 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
551 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
553 if (event->detail == NotifyPointer) return;
554 if (ximInComposeMode) return;
556 x11drv_thread_data()->last_focus = hwnd;
557 if ((xic = X11DRV_get_ic( hwnd )))
560 XUnsetICFocus( xic );
563 if (hwnd != GetForegroundWindow()) return;
564 SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
566 /* don't reset the foreground window, if the window which is
567 getting the focus is a Wine window */
570 XGetInputFocus( thread_display(), &focus_win, &revert );
573 if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
580 /* Abey : 6-Oct-99. Check again if the focus out window is the
581 Foreground window, because in most cases the messages sent
582 above must have already changed the foreground window, in which
583 case we don't have to change the foreground window to 0 */
584 if (hwnd == GetForegroundWindow())
586 TRACE( "lost focus, setting fg to 0\n" );
587 SetForegroundWindow( 0 );
593 /***********************************************************************
594 * EVENT_SelectionRequest_AddTARGETS
595 * Utility function for EVENT_SelectionRequest_TARGETS.
597 static BOOL EVENT_SelectionRequest_AddTARGETS(Atom* targets, unsigned long cTargets, Atom prop)
602 /* Scan through what we have so far to avoid duplicates */
603 for (i = 0, bExists = FALSE; i < cTargets; i++)
605 if (targets[i] == prop)
613 targets[cTargets] = prop;
619 /***********************************************************************
620 * EVENT_SelectionRequest_TARGETS
621 * Service a TARGETS selection request event
623 static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
624 Atom target, Atom rprop )
630 LPWINE_CLIPFORMAT lpFormat;
633 * Count the number of items we wish to expose as selection targets.
634 * We include the TARGETS item, and property aliases
636 cTargets = X11DRV_CountClipboardFormats() + 1;
638 for (wFormat = 0; (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
640 lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
644 if (!lpFormat->lpDrvExportFunc)
647 if (X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData))
650 /* else most likely unregistered format such as CF_PRIVATE or CF_GDIOBJ */
653 TRACE_(clipboard)(" found %ld formats\n", cTargets);
655 /* Allocate temp buffer */
656 targets = (Atom*)HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
660 /* Create TARGETS property list (First item in list is TARGETS itself) */
661 for (targets[0] = x11drv_atom(TARGETS), cTargets = 1, wFormat = 0;
662 (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
664 lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
668 if (lpFormat->lpDrvExportFunc)
670 if (EVENT_SelectionRequest_AddTARGETS(targets, cTargets, lpFormat->drvData))
674 /* Check if any alias should be listed */
675 alias = X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData);
678 if (EVENT_SelectionRequest_AddTARGETS(targets, cTargets, alias))
686 if (TRACE_ON(clipboard))
689 for ( i = 0; i < cTargets; i++)
693 char *itemFmtName = XGetAtomName(display, targets[i]);
694 TRACE_(clipboard)("\tAtom# %d: Property %ld Type %s\n", i, targets[i], itemFmtName);
700 /* We may want to consider setting the type to xaTargets instead,
701 * in case some apps expect this instead of XA_ATOM */
702 XChangeProperty(display, requestor, rprop, XA_ATOM, 32,
703 PropModeReplace, (unsigned char *)targets, cTargets);
706 HeapFree(GetProcessHeap(), 0, targets);
712 /***********************************************************************
713 * EVENT_SelectionRequest_MULTIPLE
714 * Service a MULTIPLE selection request event
715 * rprop contains a list of (target,property) atom pairs.
716 * The first atom names a target and the second names a property.
717 * The effect is as if we have received a sequence of SelectionRequest events
718 * (one for each atom pair) except that:
719 * 1. We reply with a SelectionNotify only when all the requested conversions
720 * have been performed.
721 * 2. If we fail to convert the target named by an atom in the MULTIPLE property,
722 * we replace the atom in the property by None.
724 static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
726 Display *display = pevent->display;
728 Atom atype=AnyPropertyType;
730 unsigned long remain;
731 Atom* targetPropList=NULL;
732 unsigned long cTargetPropList = 0;
734 /* If the specified property is None the requestor is an obsolete client.
735 * We support these by using the specified target atom as the reply property.
737 rprop = pevent->property;
739 rprop = pevent->target;
743 /* Read the MULTIPLE property contents. This should contain a list of
744 * (target,property) atom pairs.
747 if(XGetWindowProperty(display, pevent->requestor, rprop,
748 0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
749 &cTargetPropList, &remain,
750 (unsigned char**)&targetPropList) != Success)
753 TRACE("\tCouldn't read MULTIPLE property\n");
757 TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
758 XGetAtomName(display, atype), aformat, cTargetPropList, remain);
762 * Make sure we got what we expect.
763 * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
764 * in a MULTIPLE selection request should be of type ATOM_PAIR.
765 * However some X apps(such as XPaint) are not compliant with this and return
766 * a user defined atom in atype when XGetWindowProperty is called.
767 * The data *is* an atom pair but is not denoted as such.
769 if(aformat == 32 /* atype == xAtomPair */ )
773 /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
774 * for each (target,property) pair */
776 for (i = 0; i < cTargetPropList; i+=2)
778 XSelectionRequestEvent event;
782 char *targetName, *propName;
784 targetName = XGetAtomName(display, targetPropList[i]);
785 propName = XGetAtomName(display, targetPropList[i+1]);
786 TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
787 i/2, targetName, propName);
793 /* We must have a non "None" property to service a MULTIPLE target atom */
794 if ( !targetPropList[i+1] )
796 TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
800 /* Set up an XSelectionRequestEvent for this (target,property) pair */
801 memcpy( &event, pevent, sizeof(XSelectionRequestEvent) );
802 event.target = targetPropList[i];
803 event.property = targetPropList[i+1];
805 /* Fire a SelectionRequest, informing the handler that we are processing
806 * a MULTIPLE selection request event.
808 EVENT_SelectionRequest( hWnd, &event, TRUE );
812 /* Free the list of targets/properties */
814 XFree(targetPropList);
823 /***********************************************************************
824 * EVENT_SelectionRequest
825 * Process an event selection request event.
826 * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
827 * recursively while servicing a "MULTIPLE" selection target.
829 * Note: We only receive this event when WINE owns the X selection
831 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
833 Display *display = event->display;
834 XSelectionEvent result;
836 Window request = event->requestor;
838 TRACE_(clipboard)("\n");
841 * We can only handle the selection request if :
842 * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
843 * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
844 * since this has been already done.
848 if (((event->selection != XA_PRIMARY) && (event->selection != x11drv_atom(CLIPBOARD))))
852 /* If the specified property is None the requestor is an obsolete client.
853 * We support these by using the specified target atom as the reply property.
855 rprop = event->property;
857 rprop = event->target;
859 if(event->target == x11drv_atom(TARGETS)) /* Return a list of all supported targets */
861 /* TARGETS selection request */
862 rprop = EVENT_SelectionRequest_TARGETS( display, request, event->target, rprop );
864 else if(event->target == x11drv_atom(MULTIPLE)) /* rprop contains a list of (target, property) atom pairs */
866 /* MULTIPLE selection request */
867 rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
871 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(event->target);
874 lpFormat = X11DRV_CLIPBOARD_LookupAliasProperty(event->target);
876 if (lpFormat && lpFormat->lpDrvExportFunc)
878 LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(lpFormat->wFormatID);
882 unsigned char* lpClipData;
884 HANDLE hClipData = lpFormat->lpDrvExportFunc(request, event->target,
885 rprop, lpData, &cBytes);
887 if (hClipData && (lpClipData = GlobalLock(hClipData)))
889 TRACE_(clipboard)("\tUpdating property %s, %ld bytes\n",
890 debugstr_w(lpFormat->Name), cBytes);
893 XChangeProperty(display, request, rprop, event->target,
894 8, PropModeReplace, (unsigned char *)lpClipData, cBytes);
897 GlobalUnlock(hClipData);
898 GlobalFree(hClipData);
906 * SelectionNotify should be sent only at the end of a MULTIPLE request
910 result.type = SelectionNotify;
911 result.display = display;
912 result.requestor = request;
913 result.selection = event->selection;
914 result.property = rprop;
915 result.target = event->target;
916 result.time = event->time;
917 TRACE("Sending SelectionNotify event...\n");
919 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
924 /***********************************************************************
925 * EVENT_SelectionClear
927 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
929 if (event->selection == XA_PRIMARY || event->selection == x11drv_atom(CLIPBOARD))
930 X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd, event->time );
933 /***********************************************************************
934 * EVENT_PropertyNotify
935 * We use this to release resources like Pixmaps when a selection
936 * client no longer needs them.
938 static void EVENT_PropertyNotify( XPropertyEvent *event )
940 /* Check if we have any resources to free */
941 TRACE("Received PropertyNotify event: \n");
947 TRACE("\tPropertyDelete for atom %ld on window %ld\n",
948 event->atom, (long)event->window);
952 case PropertyNewValue:
954 TRACE("\tPropertyNewValue for atom %ld on window %ld\n\n",
955 event->atom, (long)event->window);
964 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
968 if (!IsWindowEnabled(hQueryWnd)) return 0;
970 GetWindowRect(hQueryWnd, &tempRect);
972 if(!PtInRect(&tempRect, *lpPt)) return 0;
974 if (!IsIconic( hQueryWnd ))
976 GetClientRect( hQueryWnd, &tempRect );
977 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
979 if (PtInRect( &tempRect, *lpPt))
981 HWND *list = WIN_ListChildren( hQueryWnd );
988 for (i = 0; list[i]; i++)
990 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
992 GetWindowRect( list[i], &tempRect );
993 if (PtInRect( &tempRect, *lpPt )) break;
998 if (IsWindowEnabled( list[i] ))
999 bResult = find_drop_window( list[i], lpPt );
1001 HeapFree( GetProcessHeap(), 0, list );
1003 if(bResult) return bResult;
1007 if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
1009 ScreenToClient(hQueryWnd, lpPt);
1014 /**********************************************************************
1015 * EVENT_DropFromOffix
1017 * don't know if it still works (last Changlog is from 96/11/04)
1019 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
1021 unsigned long data_length;
1022 unsigned long aux_long;
1023 unsigned char* p_data = NULL;
1034 Window win, w_aux_root, w_aux_child;
1038 win = X11DRV_get_whole_window(hWnd);
1040 XQueryPointer( event->display, win, &w_aux_root, &w_aux_child,
1041 &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
1042 (unsigned int*)&aux_long);
1043 wine_tsx11_unlock();
1045 pWnd = WIN_GetPtr(hWnd);
1047 /* find out drop point and drop window */
1048 if( x < 0 || y < 0 ||
1049 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1050 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1052 bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES;
1058 POINT pt = { x, y };
1059 HWND hwndDrop = find_drop_window( hWnd, &pt );
1072 WIN_ReleasePtr(pWnd);
1074 if (!bAccept) return;
1077 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1078 x11drv_atom(DndSelection), 0, 65535, FALSE,
1079 AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1080 &data_length, &aux_long, &p_data);
1081 wine_tsx11_unlock();
1083 if( !aux_long && p_data) /* don't bother if > 64K */
1085 signed char *p = (signed char*) p_data;
1089 while( *p ) /* calculate buffer size */
1092 if((u.i = *p) != -1 )
1094 INT len = GetShortPathNameA( p, NULL, 0 );
1095 if (len) aux_long += len + 1;
1100 if( aux_long && aux_long < 65535 )
1105 aux_long += sizeof(DROPFILES) + 1;
1106 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
1107 lpDrop = (DROPFILES*)GlobalLock( hDrop );
1111 WND *pDropWnd = WIN_GetPtr( hScope );
1112 lpDrop->pFiles = sizeof(DROPFILES);
1116 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1117 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1118 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1119 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1120 lpDrop->fWide = FALSE;
1121 WIN_ReleasePtr(pDropWnd);
1122 p_drop = (char *)(lpDrop + 1);
1126 if( *p != -1 ) /* use only "good" entries */
1128 GetShortPathNameA( p, p_drop, 65535 );
1129 p_drop += strlen( p_drop ) + 1;
1134 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1139 if( p_data ) XFree(p_data);
1140 wine_tsx11_unlock();
1143 /**********************************************************************
1146 * drop items are separated by \n
1147 * each item is prefixed by its mime type
1149 * event->data.l[3], event->data.l[4] contains drop x,y position
1151 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
1153 unsigned long data_length;
1154 unsigned long aux_long, drop_len = 0;
1155 unsigned char *p_data = NULL; /* property data */
1156 char *p_drop = NULL;
1167 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
1170 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1171 x11drv_atom(DndSelection), 0, 65535, FALSE,
1172 AnyPropertyType, &u.atom_aux, &u.i,
1173 &data_length, &aux_long, &p_data);
1174 wine_tsx11_unlock();
1176 WARN("property too large, truncated!\n");
1177 TRACE("urls=%s\n", p_data);
1179 if( !aux_long && p_data) { /* don't bother if > 64K */
1180 /* calculate length */
1182 next = strchr(p, '\n');
1185 if (strncmp(p,"file:",5) == 0 ) {
1186 INT len = GetShortPathNameA( p+5, NULL, 0 );
1187 if (len) drop_len += len + 1;
1192 next = strchr(p, '\n');
1198 if( drop_len && drop_len < 65535 ) {
1200 XQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
1201 &x, &y, &u.i, &u.i, &u.i);
1202 wine_tsx11_unlock();
1204 drop_len += sizeof(DROPFILES) + 1;
1205 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
1206 lpDrop = (DROPFILES *) GlobalLock( hDrop );
1209 WND *pDropWnd = WIN_GetPtr( hWnd );
1210 lpDrop->pFiles = sizeof(DROPFILES);
1211 lpDrop->pt.x = (INT)x;
1212 lpDrop->pt.y = (INT)y;
1214 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1215 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1216 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1217 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1218 lpDrop->fWide = FALSE;
1219 p_drop = (char*)(lpDrop + 1);
1220 WIN_ReleasePtr(pDropWnd);
1223 /* create message content */
1226 next = strchr(p, '\n');
1229 if (strncmp(p,"file:",5) == 0 ) {
1230 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
1232 TRACE("drop file %s as %s\n", p+5, p_drop);
1235 WARN("can't convert file %s to dos name \n", p+5);
1238 WARN("unknown mime type %s\n", p);
1243 next = strchr(p, '\n');
1250 GlobalUnlock(hDrop);
1251 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1255 if( p_data ) XFree(p_data);
1256 wine_tsx11_unlock();
1260 /**********************************************************************
1261 * EVENT_ClientMessage
1263 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
1265 if (event->message_type != None && event->format == 32) {
1266 if (event->message_type == x11drv_atom(WM_PROTOCOLS))
1267 handle_wm_protocols_message( hWnd, event );
1268 else if (event->message_type == x11drv_atom(DndProtocol))
1270 /* query window (drag&drop event contains only drag window) */
1272 int root_x, root_y, child_x, child_y;
1276 XQueryPointer( event->display, root_window, &root, &child,
1277 &root_x, &root_y, &child_x, &child_y, &u);
1278 if (XFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) hWnd = 0;
1279 wine_tsx11_unlock();
1281 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
1282 EVENT_DropFromOffiX(hWnd, event);
1283 else if (event->data.l[0] == DndURL)
1284 EVENT_DropURLs(hWnd, event);
1286 else if (!X11DRV_XDND_Event(hWnd, event))
1289 /* enable this if you want to see the message */
1290 unsigned char* p_data = NULL;
1297 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1298 dndSelection, 0, 65535, FALSE,
1299 AnyPropertyType, &u.atom, &u.i,
1300 &u.l, &u.l, &p_data);
1301 wine_tsx11_unlock();
1302 TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1303 event->message_type, event->data.l[0], event->data.l[1],
1304 event->data.l[2], event->data.l[3], event->data.l[4],
1307 TRACE("unrecognized ClientMessage\n" );
1313 /**********************************************************************
1314 * X11DRV_EVENT_SetInputMethod
1316 INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
1318 INPUT_TYPE prev = current_input_type;
1320 /* Flag not used yet */
1321 in_transition = FALSE;
1322 current_input_type = type;
1327 #ifdef HAVE_LIBXXF86DGA2
1328 /**********************************************************************
1329 * X11DRV_EVENT_SetDGAStatus
1331 void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
1333 if (event_base < 0) {
1339 DGAMotionEventType = event_base + MotionNotify;
1340 DGAButtonPressEventType = event_base + ButtonPress;
1341 DGAButtonReleaseEventType = event_base + ButtonRelease;
1342 DGAKeyPressEventType = event_base + KeyPress;
1343 DGAKeyReleaseEventType = event_base + KeyRelease;