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 /* X context to associate a hwnd to an X window */
54 extern XContext winContext;
56 extern BOOL ximInComposeMode;
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 #ifdef HAVE_LIBXXF86DGA2
96 static int DGAMotionEventType;
97 static int DGAButtonPressEventType;
98 static int DGAButtonReleaseEventType;
99 static int DGAKeyPressEventType;
100 static int DGAKeyReleaseEventType;
102 static BOOL DGAUsed = FALSE;
103 static HWND DGAhwnd = 0;
106 /* Static used for the current input method */
107 static INPUT_TYPE current_input_type = X11DRV_INPUT_ABSOLUTE;
108 static BOOL in_transition = FALSE; /* This is not used as for today */
111 /***********************************************************************
114 static int process_events( struct x11drv_thread_data *data )
120 while ( XPending( data->display ) )
124 XNextEvent( data->display, &event );
125 ignore = XFilterEvent( &event, None );
127 if (!ignore) EVENT_ProcessEvent( &event );
136 /***********************************************************************
137 * MsgWaitForMultipleObjectsEx (X11DRV.@)
139 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
140 DWORD timeout, DWORD mask, DWORD flags )
142 HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1]; /* FIXME! */
144 struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
146 if (!data || data->process_event_count)
147 return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
148 timeout, flags & MWMO_ALERTABLE );
150 /* check whether only server queue handle was passed in */
151 if (count < 2) flags &= ~MWMO_WAITALL;
153 for (i = 0; i < count; i++) new_handles[i] = handles[i];
154 new_handles[count] = data->display_fd;
157 XFlush( gdi_display );
158 XFlush( data->display );
161 data->process_event_count++;
162 if (process_events( data )) ret = count;
165 ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
166 timeout, flags & MWMO_ALERTABLE );
167 if (ret == count) process_events( data );
169 data->process_event_count--;
173 /***********************************************************************
174 * EVENT_x11_time_to_win32_time
176 * Make our timer and the X timer line up as best we can
177 * Pass 0 to retrieve the current adjustment value (times -1)
179 DWORD EVENT_x11_time_to_win32_time(Time time)
181 static DWORD adjust = 0;
182 DWORD now = GetTickCount();
185 if (! adjust && time != 0)
192 /* If we got an event in the 'future', then our clock is clearly wrong.
193 If we got it more than 10000 ms in the future, then it's most likely
194 that the clock has wrapped. */
197 if (ret > now && ((ret - now) < 10000) && time != 0)
208 /***********************************************************************
211 * Process an X event.
213 static void EVENT_ProcessEvent( XEvent *event )
216 Display *display = event->xany.display;
218 TRACE( "called.\n" );
222 case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
223 FIXME("Got SelectionNotify - must not happen!\n");
226 /* We get all these because of StructureNotifyMask.
227 This check is placed here to avoid getting error messages below,
228 as X might send some of these even for windows that have already
230 case CirculateNotify:
238 #ifdef HAVE_LIBXXF86DGA2
240 if (event->type == DGAMotionEventType) {
241 TRACE("DGAMotionEvent received.\n");
242 X11DRV_DGAMotionEvent( DGAhwnd, (XDGAMotionEvent *)event );
245 if (event->type == DGAButtonPressEventType) {
246 TRACE("DGAButtonPressEvent received.\n");
247 X11DRV_DGAButtonPressEvent( DGAhwnd, (XDGAButtonEvent *)event );
250 if (event->type == DGAButtonReleaseEventType) {
251 TRACE("DGAButtonReleaseEvent received.\n");
252 X11DRV_DGAButtonReleaseEvent( DGAhwnd, (XDGAButtonEvent *)event );
255 if ((event->type == DGAKeyPressEventType) ||
256 (event->type == DGAKeyReleaseEventType)) {
257 /* Fill a XKeyEvent to send to EVENT_Key */
259 XDGAKeyEvent *evt = (XDGAKeyEvent *) event;
261 TRACE("DGAKeyPress/ReleaseEvent received.\n");
263 if (evt->type == DGAKeyReleaseEventType)
264 ke.type = KeyRelease;
267 ke.serial = evt->serial;
268 ke.send_event = FALSE;
269 ke.display = evt->display;
278 ke.state = evt->state;
279 ke.keycode = evt->keycode;
280 ke.same_screen = TRUE;
281 X11DRV_KeyEvent( 0, &ke );
288 if (XFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
289 hWnd = 0; /* Not for a registered window */
291 if (!hWnd && event->xany.window == root_window) hWnd = GetDesktopWindow();
293 if (!hWnd && event->type != PropertyNotify &&
294 event->type != MappingNotify && event->type != KeymapNotify)
295 WARN( "Got event %s for unknown Window %08lx\n",
296 event_names[event->type], event->xany.window );
297 else if (event->type <= MappingNotify)
298 TRACE("Got event %s for hwnd/window %p/%lx, GetFocus()=%p\n",
299 event_names[event->type], hWnd, event->xany.window, GetFocus() );
301 TRACE("Got extension event for hwnd/window %p/%lx, GetFocus()=%p\n",
302 hWnd, event->xany.window, GetFocus() );
304 if (X11DRV_ProcessTabletEvent(hWnd, event))
306 TRACE("Return: filtered by tablet\n");
314 /* FIXME: should generate a motion event if event point is different from current pos */
315 X11DRV_KeyEvent( hWnd, (XKeyEvent*)event );
319 X11DRV_ButtonPress( hWnd, (XButtonEvent*)event );
323 X11DRV_ButtonRelease( hWnd, (XButtonEvent*)event );
327 X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
331 X11DRV_EnterNotify( hWnd, (XCrossingEvent*)event );
335 EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
339 EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
343 X11DRV_Expose( hWnd, &event->xexpose );
346 case ConfigureNotify:
348 X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
351 case SelectionRequest:
353 EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
358 EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
362 EVENT_PropertyNotify( (XPropertyEvent *)event );
367 EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
374 X11DRV_MapNotify( hWnd, (XMapEvent *)event );
378 X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
382 X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
386 X11DRV_MappingNotify( (XMappingEvent *) event );
390 WARN("Unprocessed event %s for hwnd %p\n", event_names[event->type], hWnd );
393 TRACE( "returns.\n" );
397 /*******************************************************************
398 * can_activate_window
400 * Check if we can activate the specified window.
402 inline static BOOL can_activate_window( HWND hwnd )
404 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
405 if (!(style & WS_VISIBLE)) return FALSE;
406 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
407 return !(style & WS_DISABLED);
411 /**********************************************************************
414 static void set_focus( HWND hwnd, Time time )
419 TRACE( "setting foreground window to %p\n", hwnd );
420 SetForegroundWindow( hwnd );
423 if (focus) focus = GetAncestor( focus, GA_ROOT );
424 win = X11DRV_get_whole_window(focus);
428 TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time );
430 XSetInputFocus( thread_display(), win, RevertToParent, time );
436 /**********************************************************************
437 * handle_wm_protocols_message
439 static void handle_wm_protocols_message( HWND hwnd, XClientMessageEvent *event )
441 Atom protocol = (Atom)event->data.l[0];
443 if (!protocol) return;
445 if (protocol == x11drv_atom(WM_DELETE_WINDOW))
447 /* Ignore the delete window request if the window has been disabled
448 * and we are in managed mode. This is to disallow applications from
449 * being closed by the window manager while in a modal state.
451 if (IsWindowEnabled(hwnd)) PostMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
453 else if (protocol == x11drv_atom(WM_TAKE_FOCUS))
455 Time event_time = (Time)event->data.l[1];
456 HWND last_focus = x11drv_thread_data()->last_focus;
458 TRACE( "got take focus msg for %p, enabled=%d, focus=%p, active=%p, fg=%p, last=%p\n",
459 hwnd, IsWindowEnabled(hwnd), GetFocus(), GetActiveWindow(),
460 GetForegroundWindow(), last_focus );
462 if (can_activate_window(hwnd))
464 /* simulate a mouse click on the caption to find out
465 * whether the window wants to be activated */
466 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
467 (WPARAM)GetAncestor( hwnd, GA_ROOT ),
468 MAKELONG(HTCAPTION,WM_LBUTTONDOWN) );
469 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) set_focus( hwnd, event_time );
470 else TRACE( "not setting focus to %p (%lx), ma=%ld\n", hwnd, event->window, ma );
475 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
476 if (!hwnd) hwnd = GetActiveWindow();
477 if (!hwnd) hwnd = last_focus;
478 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
481 else if (protocol == x11drv_atom(_NET_WM_PING))
483 XClientMessageEvent xev;
486 TRACE("NET_WM Ping\n");
487 xev.window = DefaultRootWindow(xev.display);
488 XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
489 /* this line is semi-stolen from gtk2 */
490 TRACE("NET_WM Pong\n");
495 static const char * const focus_details[] =
501 "NotifyNonlinearVirtual",
507 /**********************************************************************
510 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
516 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
518 if (event->detail == NotifyPointer) return;
520 if ((xic = X11DRV_get_ic( hwnd )))
526 if (use_take_focus) return; /* ignore FocusIn if we are using take focus */
528 if (!can_activate_window(hwnd))
530 HWND hwnd = GetFocus();
531 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
532 if (!hwnd) hwnd = GetActiveWindow();
533 if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
534 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
536 else SetForegroundWindow( hwnd );
540 /**********************************************************************
543 * Note: only top-level windows get FocusOut events.
545 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
554 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
556 if (event->detail == NotifyPointer) return;
557 if (ximInComposeMode) return;
559 x11drv_thread_data()->last_focus = hwnd;
560 if ((xic = X11DRV_get_ic( hwnd )))
563 XUnsetICFocus( xic );
566 if (hwnd != GetForegroundWindow()) return;
567 SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
569 /* don't reset the foreground window, if the window which is
570 getting the focus is a Wine window */
573 XGetInputFocus( thread_display(), &focus_win, &revert );
576 if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
583 /* Abey : 6-Oct-99. Check again if the focus out window is the
584 Foreground window, because in most cases the messages sent
585 above must have already changed the foreground window, in which
586 case we don't have to change the foreground window to 0 */
587 if (hwnd == GetForegroundWindow())
589 TRACE( "lost focus, setting fg to 0\n" );
590 SetForegroundWindow( 0 );
596 /***********************************************************************
597 * EVENT_SelectionRequest_AddTARGETS
598 * Utility function for EVENT_SelectionRequest_TARGETS.
600 static BOOL EVENT_SelectionRequest_AddTARGETS(Atom* targets, unsigned long cTargets, Atom prop)
605 /* Scan through what we have so far to avoid duplicates */
606 for (i = 0, bExists = FALSE; i < cTargets; i++)
608 if (targets[i] == prop)
616 targets[cTargets] = prop;
622 /***********************************************************************
623 * EVENT_SelectionRequest_TARGETS
624 * Service a TARGETS selection request event
626 static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
627 Atom target, Atom rprop )
633 LPWINE_CLIPFORMAT lpFormat;
636 * Count the number of items we wish to expose as selection targets.
637 * We include the TARGETS item, and property aliases
639 cTargets = X11DRV_CountClipboardFormats() + 1;
641 for (wFormat = 0; (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
643 lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
647 if (!lpFormat->lpDrvExportFunc)
650 if (X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData))
653 /* else most likely unregistered format such as CF_PRIVATE or CF_GDIOBJ */
656 TRACE_(clipboard)(" found %ld formats\n", cTargets);
658 /* Allocate temp buffer */
659 targets = (Atom*)HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
663 /* Create TARGETS property list (First item in list is TARGETS itself) */
664 for (targets[0] = x11drv_atom(TARGETS), cTargets = 1, wFormat = 0;
665 (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
667 lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
671 if (lpFormat->lpDrvExportFunc)
673 if (EVENT_SelectionRequest_AddTARGETS(targets, cTargets, lpFormat->drvData))
677 /* Check if any alias should be listed */
678 alias = X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData);
681 if (EVENT_SelectionRequest_AddTARGETS(targets, cTargets, alias))
689 if (TRACE_ON(clipboard))
692 for ( i = 0; i < cTargets; i++)
696 char *itemFmtName = XGetAtomName(display, targets[i]);
697 TRACE_(clipboard)("\tAtom# %d: Property %ld Type %s\n", i, targets[i], itemFmtName);
703 /* We may want to consider setting the type to xaTargets instead,
704 * in case some apps expect this instead of XA_ATOM */
705 XChangeProperty(display, requestor, rprop, XA_ATOM, 32,
706 PropModeReplace, (unsigned char *)targets, cTargets);
709 HeapFree(GetProcessHeap(), 0, targets);
715 /***********************************************************************
716 * EVENT_SelectionRequest_MULTIPLE
717 * Service a MULTIPLE selection request event
718 * rprop contains a list of (target,property) atom pairs.
719 * The first atom names a target and the second names a property.
720 * The effect is as if we have received a sequence of SelectionRequest events
721 * (one for each atom pair) except that:
722 * 1. We reply with a SelectionNotify only when all the requested conversions
723 * have been performed.
724 * 2. If we fail to convert the target named by an atom in the MULTIPLE property,
725 * we replace the atom in the property by None.
727 static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
729 Display *display = pevent->display;
731 Atom atype=AnyPropertyType;
733 unsigned long remain;
734 Atom* targetPropList=NULL;
735 unsigned long cTargetPropList = 0;
737 /* If the specified property is None the requestor is an obsolete client.
738 * We support these by using the specified target atom as the reply property.
740 rprop = pevent->property;
742 rprop = pevent->target;
746 /* Read the MULTIPLE property contents. This should contain a list of
747 * (target,property) atom pairs.
750 if(XGetWindowProperty(display, pevent->requestor, rprop,
751 0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
752 &cTargetPropList, &remain,
753 (unsigned char**)&targetPropList) != Success)
756 TRACE("\tCouldn't read MULTIPLE property\n");
760 TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
761 XGetAtomName(display, atype), aformat, cTargetPropList, remain);
765 * Make sure we got what we expect.
766 * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
767 * in a MULTIPLE selection request should be of type ATOM_PAIR.
768 * However some X apps(such as XPaint) are not compliant with this and return
769 * a user defined atom in atype when XGetWindowProperty is called.
770 * The data *is* an atom pair but is not denoted as such.
772 if(aformat == 32 /* atype == xAtomPair */ )
776 /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
777 * for each (target,property) pair */
779 for (i = 0; i < cTargetPropList; i+=2)
781 XSelectionRequestEvent event;
785 char *targetName, *propName;
787 targetName = XGetAtomName(display, targetPropList[i]);
788 propName = XGetAtomName(display, targetPropList[i+1]);
789 TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
790 i/2, targetName, propName);
796 /* We must have a non "None" property to service a MULTIPLE target atom */
797 if ( !targetPropList[i+1] )
799 TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
803 /* Set up an XSelectionRequestEvent for this (target,property) pair */
804 memcpy( &event, pevent, sizeof(XSelectionRequestEvent) );
805 event.target = targetPropList[i];
806 event.property = targetPropList[i+1];
808 /* Fire a SelectionRequest, informing the handler that we are processing
809 * a MULTIPLE selection request event.
811 EVENT_SelectionRequest( hWnd, &event, TRUE );
815 /* Free the list of targets/properties */
817 XFree(targetPropList);
826 /***********************************************************************
827 * EVENT_SelectionRequest
828 * Process an event selection request event.
829 * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
830 * recursively while servicing a "MULTIPLE" selection target.
832 * Note: We only receive this event when WINE owns the X selection
834 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
836 Display *display = event->display;
837 XSelectionEvent result;
839 Window request = event->requestor;
841 TRACE_(clipboard)("\n");
844 * We can only handle the selection request if :
845 * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
846 * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
847 * since this has been already done.
851 if (((event->selection != XA_PRIMARY) && (event->selection != x11drv_atom(CLIPBOARD))))
855 /* If the specified property is None the requestor is an obsolete client.
856 * We support these by using the specified target atom as the reply property.
858 rprop = event->property;
860 rprop = event->target;
862 if(event->target == x11drv_atom(TARGETS)) /* Return a list of all supported targets */
864 /* TARGETS selection request */
865 rprop = EVENT_SelectionRequest_TARGETS( display, request, event->target, rprop );
867 else if(event->target == x11drv_atom(MULTIPLE)) /* rprop contains a list of (target, property) atom pairs */
869 /* MULTIPLE selection request */
870 rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
874 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(event->target);
877 lpFormat = X11DRV_CLIPBOARD_LookupAliasProperty(event->target);
879 if (lpFormat && lpFormat->lpDrvExportFunc)
881 LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(lpFormat->wFormatID);
885 unsigned char* lpClipData;
887 HANDLE hClipData = lpFormat->lpDrvExportFunc(request, event->target,
888 rprop, lpData, &cBytes);
890 if (hClipData && (lpClipData = GlobalLock(hClipData)))
892 TRACE_(clipboard)("\tUpdating property %s, %ld bytes\n",
893 debugstr_w(lpFormat->Name), cBytes);
896 XChangeProperty(display, request, rprop, event->target,
897 8, PropModeReplace, (unsigned char *)lpClipData, cBytes);
900 GlobalUnlock(hClipData);
901 GlobalFree(hClipData);
909 * SelectionNotify should be sent only at the end of a MULTIPLE request
913 result.type = SelectionNotify;
914 result.display = display;
915 result.requestor = request;
916 result.selection = event->selection;
917 result.property = rprop;
918 result.target = event->target;
919 result.time = event->time;
920 TRACE("Sending SelectionNotify event...\n");
922 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
927 /***********************************************************************
928 * EVENT_SelectionClear
930 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
932 if (event->selection == XA_PRIMARY || event->selection == x11drv_atom(CLIPBOARD))
933 X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd, event->time );
936 /***********************************************************************
937 * EVENT_PropertyNotify
938 * We use this to release resources like Pixmaps when a selection
939 * client no longer needs them.
941 static void EVENT_PropertyNotify( XPropertyEvent *event )
943 /* Check if we have any resources to free */
944 TRACE("Received PropertyNotify event: \n");
950 TRACE("\tPropertyDelete for atom %ld on window %ld\n",
951 event->atom, (long)event->window);
955 case PropertyNewValue:
957 TRACE("\tPropertyNewValue for atom %ld on window %ld\n\n",
958 event->atom, (long)event->window);
967 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
971 if (!IsWindowEnabled(hQueryWnd)) return 0;
973 GetWindowRect(hQueryWnd, &tempRect);
975 if(!PtInRect(&tempRect, *lpPt)) return 0;
977 if (!IsIconic( hQueryWnd ))
979 GetClientRect( hQueryWnd, &tempRect );
980 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
982 if (PtInRect( &tempRect, *lpPt))
984 HWND *list = WIN_ListChildren( hQueryWnd );
991 for (i = 0; list[i]; i++)
993 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
995 GetWindowRect( list[i], &tempRect );
996 if (PtInRect( &tempRect, *lpPt )) break;
1001 if (IsWindowEnabled( list[i] ))
1002 bResult = find_drop_window( list[i], lpPt );
1004 HeapFree( GetProcessHeap(), 0, list );
1006 if(bResult) return bResult;
1010 if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
1012 ScreenToClient(hQueryWnd, lpPt);
1017 /**********************************************************************
1018 * EVENT_DropFromOffix
1020 * don't know if it still works (last Changlog is from 96/11/04)
1022 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
1024 unsigned long data_length;
1025 unsigned long aux_long;
1026 unsigned char* p_data = NULL;
1037 Window win, w_aux_root, w_aux_child;
1041 win = X11DRV_get_whole_window(hWnd);
1043 XQueryPointer( event->display, win, &w_aux_root, &w_aux_child,
1044 &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
1045 (unsigned int*)&aux_long);
1046 wine_tsx11_unlock();
1048 pWnd = WIN_GetPtr(hWnd);
1050 /* find out drop point and drop window */
1051 if( x < 0 || y < 0 ||
1052 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1053 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1055 bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES;
1061 POINT pt = { x, y };
1062 HWND hwndDrop = find_drop_window( hWnd, &pt );
1075 WIN_ReleasePtr(pWnd);
1077 if (!bAccept) return;
1080 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1081 x11drv_atom(DndSelection), 0, 65535, FALSE,
1082 AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1083 &data_length, &aux_long, &p_data);
1084 wine_tsx11_unlock();
1086 if( !aux_long && p_data) /* don't bother if > 64K */
1088 signed char *p = (signed char*) p_data;
1092 while( *p ) /* calculate buffer size */
1095 if((u.i = *p) != -1 )
1097 INT len = GetShortPathNameA( p, NULL, 0 );
1098 if (len) aux_long += len + 1;
1103 if( aux_long && aux_long < 65535 )
1108 aux_long += sizeof(DROPFILES) + 1;
1109 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
1110 lpDrop = (DROPFILES*)GlobalLock( hDrop );
1114 WND *pDropWnd = WIN_GetPtr( hScope );
1115 lpDrop->pFiles = sizeof(DROPFILES);
1119 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1120 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1121 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1122 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1123 lpDrop->fWide = FALSE;
1124 WIN_ReleasePtr(pDropWnd);
1125 p_drop = (char *)(lpDrop + 1);
1129 if( *p != -1 ) /* use only "good" entries */
1131 GetShortPathNameA( p, p_drop, 65535 );
1132 p_drop += strlen( p_drop ) + 1;
1137 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1142 if( p_data ) XFree(p_data);
1143 wine_tsx11_unlock();
1146 /**********************************************************************
1149 * drop items are separated by \n
1150 * each item is prefixed by its mime type
1152 * event->data.l[3], event->data.l[4] contains drop x,y position
1154 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
1156 unsigned long data_length;
1157 unsigned long aux_long, drop_len = 0;
1158 unsigned char *p_data = NULL; /* property data */
1159 char *p_drop = NULL;
1170 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
1173 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1174 x11drv_atom(DndSelection), 0, 65535, FALSE,
1175 AnyPropertyType, &u.atom_aux, &u.i,
1176 &data_length, &aux_long, &p_data);
1177 wine_tsx11_unlock();
1179 WARN("property too large, truncated!\n");
1180 TRACE("urls=%s\n", p_data);
1182 if( !aux_long && p_data) { /* don't bother if > 64K */
1183 /* calculate length */
1185 next = strchr(p, '\n');
1188 if (strncmp(p,"file:",5) == 0 ) {
1189 INT len = GetShortPathNameA( p+5, NULL, 0 );
1190 if (len) drop_len += len + 1;
1195 next = strchr(p, '\n');
1201 if( drop_len && drop_len < 65535 ) {
1203 XQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
1204 &x, &y, &u.i, &u.i, &u.i);
1205 wine_tsx11_unlock();
1207 drop_len += sizeof(DROPFILES) + 1;
1208 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
1209 lpDrop = (DROPFILES *) GlobalLock( hDrop );
1212 WND *pDropWnd = WIN_GetPtr( hWnd );
1213 lpDrop->pFiles = sizeof(DROPFILES);
1214 lpDrop->pt.x = (INT)x;
1215 lpDrop->pt.y = (INT)y;
1217 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1218 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1219 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1220 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1221 lpDrop->fWide = FALSE;
1222 p_drop = (char*)(lpDrop + 1);
1223 WIN_ReleasePtr(pDropWnd);
1226 /* create message content */
1229 next = strchr(p, '\n');
1232 if (strncmp(p,"file:",5) == 0 ) {
1233 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
1235 TRACE("drop file %s as %s\n", p+5, p_drop);
1238 WARN("can't convert file %s to dos name \n", p+5);
1241 WARN("unknown mime type %s\n", p);
1246 next = strchr(p, '\n');
1253 GlobalUnlock(hDrop);
1254 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1258 if( p_data ) XFree(p_data);
1259 wine_tsx11_unlock();
1263 /**********************************************************************
1264 * EVENT_ClientMessage
1266 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
1268 if (event->message_type != None && event->format == 32) {
1269 if (event->message_type == x11drv_atom(WM_PROTOCOLS))
1270 handle_wm_protocols_message( hWnd, event );
1271 else if (event->message_type == x11drv_atom(DndProtocol))
1273 /* query window (drag&drop event contains only drag window) */
1275 int root_x, root_y, child_x, child_y;
1279 XQueryPointer( event->display, root_window, &root, &child,
1280 &root_x, &root_y, &child_x, &child_y, &u);
1281 if (XFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) hWnd = 0;
1282 wine_tsx11_unlock();
1284 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
1285 EVENT_DropFromOffiX(hWnd, event);
1286 else if (event->data.l[0] == DndURL)
1287 EVENT_DropURLs(hWnd, event);
1289 else if (!X11DRV_XDND_Event(hWnd, event))
1292 /* enable this if you want to see the message */
1293 unsigned char* p_data = NULL;
1300 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
1301 dndSelection, 0, 65535, FALSE,
1302 AnyPropertyType, &u.atom, &u.i,
1303 &u.l, &u.l, &p_data);
1304 wine_tsx11_unlock();
1305 TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1306 event->message_type, event->data.l[0], event->data.l[1],
1307 event->data.l[2], event->data.l[3], event->data.l[4],
1310 TRACE("unrecognized ClientMessage\n" );
1316 /**********************************************************************
1317 * X11DRV_EVENT_SetInputMethod
1319 INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
1321 INPUT_TYPE prev = current_input_type;
1323 /* Flag not used yet */
1324 in_transition = FALSE;
1325 current_input_type = type;
1330 #ifdef HAVE_LIBXXF86DGA2
1331 /**********************************************************************
1332 * X11DRV_EVENT_SetDGAStatus
1334 void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
1336 if (event_base < 0) {
1342 DGAMotionEventType = event_base + MotionNotify;
1343 DGAButtonPressEventType = event_base + ButtonPress;
1344 DGAButtonReleaseEventType = event_base + ButtonRelease;
1345 DGAKeyPressEventType = event_base + KeyPress;
1346 DGAKeyReleaseEventType = event_base + KeyRelease;