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>
29 #include <X11/Xresource.h>
30 #include <X11/Xutil.h>
31 #ifdef HAVE_LIBXXF86DGA2
32 #include <X11/extensions/xf86dga.h>
38 #include "wine/winuser16.h"
43 #include "shlobj.h" /* DROPFILES */
45 #include "clipboard.h"
51 #include "wine/debug.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(event);
54 WINE_DECLARE_DEBUG_CHANNEL(clipboard);
56 /* X context to associate a hwnd to an X window */
57 extern XContext winContext;
59 extern Atom wmProtocols;
60 extern Atom wmDeleteWindow;
61 extern Atom dndProtocol;
62 extern Atom dndSelection;
63 extern Atom netwmPing;
65 #define DndNotDnd -1 /* OffiX drag&drop */
77 #define DndURL 128 /* KDE drag&drop */
79 static const char * const event_names[] =
81 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
82 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
83 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
84 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
85 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
86 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
87 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
88 "ClientMessage", "MappingNotify"
92 static void EVENT_ProcessEvent( XEvent *event );
95 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
96 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
97 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
98 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
99 static void EVENT_PropertyNotify( XPropertyEvent *event );
100 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
102 extern void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event );
103 extern void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event );
104 extern void X11DRV_MotionNotify( HWND hwnd, XMotionEvent *event );
105 extern void X11DRV_EnterNotify( HWND hwnd, XCrossingEvent *event );
106 extern void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event );
107 extern void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event );
108 extern void X11DRV_Expose( HWND hwnd, XExposeEvent *event );
109 extern void X11DRV_MapNotify( HWND hwnd, XMapEvent *event );
110 extern void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event );
111 extern void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
112 extern void X11DRV_MappingNotify( XMappingEvent *event );
114 #ifdef HAVE_LIBXXF86DGA2
115 static int DGAMotionEventType;
116 static int DGAButtonPressEventType;
117 static int DGAButtonReleaseEventType;
118 static int DGAKeyPressEventType;
119 static int DGAKeyReleaseEventType;
121 static BOOL DGAUsed = FALSE;
122 static HWND DGAhwnd = 0;
124 extern void X11DRV_DGAMotionEvent( HWND hwnd, XDGAMotionEvent *event );
125 extern void X11DRV_DGAButtonPressEvent( HWND hwnd, XDGAButtonEvent *event );
126 extern void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XDGAButtonEvent *event );
129 /* Static used for the current input method */
130 static INPUT_TYPE current_input_type = X11DRV_INPUT_ABSOLUTE;
131 static BOOL in_transition = FALSE; /* This is not used as for today */
134 /***********************************************************************
137 static int process_events( struct x11drv_thread_data *data )
143 while ( XPending( data->display ) )
147 XNextEvent( data->display, &event );
148 ignore = XFilterEvent( &event, None );
150 if (!ignore) EVENT_ProcessEvent( &event );
159 /***********************************************************************
160 * MsgWaitForMultipleObjectsEx (X11DRV.@)
162 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
163 DWORD timeout, DWORD mask, DWORD flags )
165 HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1]; /* FIXME! */
167 struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
169 if (!data || data->process_event_count)
170 return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
171 timeout, flags & MWMO_ALERTABLE );
173 /* check whether only server queue handle was passed in */
174 if (count < 2) flags &= ~MWMO_WAITALL;
176 for (i = 0; i < count; i++) new_handles[i] = handles[i];
177 new_handles[count] = data->display_fd;
180 XFlush( gdi_display );
181 XFlush( data->display );
184 data->process_event_count++;
185 if (process_events( data )) ret = count;
188 ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
189 timeout, flags & MWMO_ALERTABLE );
190 if (ret == count) process_events( data );
192 data->process_event_count--;
197 /***********************************************************************
200 * Process an X event.
202 static void EVENT_ProcessEvent( XEvent *event )
205 Display *display = event->xany.display;
207 TRACE( "called.\n" );
211 case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
212 FIXME("Got SelectionNotify - must not happen!\n");
215 /* We get all these because of StructureNotifyMask.
216 This check is placed here to avoid getting error messages below,
217 as X might send some of these even for windows that have already
219 case CirculateNotify:
227 #ifdef HAVE_LIBXXF86DGA2
229 if (event->type == DGAMotionEventType) {
230 TRACE("DGAMotionEvent received.\n");
231 X11DRV_DGAMotionEvent( DGAhwnd, (XDGAMotionEvent *)event );
234 if (event->type == DGAButtonPressEventType) {
235 TRACE("DGAButtonPressEvent received.\n");
236 X11DRV_DGAButtonPressEvent( DGAhwnd, (XDGAButtonEvent *)event );
239 if (event->type == DGAButtonReleaseEventType) {
240 TRACE("DGAButtonReleaseEvent received.\n");
241 X11DRV_DGAButtonReleaseEvent( DGAhwnd, (XDGAButtonEvent *)event );
244 if ((event->type == DGAKeyPressEventType) ||
245 (event->type == DGAKeyReleaseEventType)) {
246 /* Fill a XKeyEvent to send to EVENT_Key */
248 XDGAKeyEvent *evt = (XDGAKeyEvent *) event;
250 TRACE("DGAKeyPress/ReleaseEvent received.\n");
252 if (evt->type == DGAKeyReleaseEventType)
253 ke.type = KeyRelease;
256 ke.serial = evt->serial;
257 ke.send_event = FALSE;
258 ke.display = evt->display;
267 ke.state = evt->state;
268 ke.keycode = evt->keycode;
269 ke.same_screen = TRUE;
270 X11DRV_KeyEvent( 0, &ke );
277 if (XFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
278 hWnd = 0; /* Not for a registered window */
280 if (!hWnd && event->xany.window == root_window) hWnd = GetDesktopWindow();
282 if (!hWnd && event->type != PropertyNotify && event->type != MappingNotify)
283 WARN( "Got event %s for unknown Window %08lx\n",
284 event_names[event->type], event->xany.window );
286 TRACE("Got event %s for hwnd %p\n",
287 event_names[event->type], hWnd );
293 /* FIXME: should generate a motion event if event point is different from current pos */
294 X11DRV_KeyEvent( hWnd, (XKeyEvent*)event );
298 X11DRV_ButtonPress( hWnd, (XButtonEvent*)event );
302 X11DRV_ButtonRelease( hWnd, (XButtonEvent*)event );
306 X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
310 X11DRV_EnterNotify( hWnd, (XCrossingEvent*)event );
314 EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
318 EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
322 X11DRV_Expose( hWnd, &event->xexpose );
325 case ConfigureNotify:
327 X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
330 case SelectionRequest:
332 EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
337 EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
341 EVENT_PropertyNotify( (XPropertyEvent *)event );
346 EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
353 X11DRV_MapNotify( hWnd, (XMapEvent *)event );
357 X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
361 X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
365 X11DRV_MappingNotify( (XMappingEvent *) event );
369 WARN("Unprocessed event %s for hwnd %p\n", event_names[event->type], hWnd );
372 TRACE( "returns.\n" );
376 /*******************************************************************
377 * can_activate_window
379 * Check if we can activate the specified window.
381 inline static BOOL can_activate_window( HWND hwnd )
383 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
384 if (!(style & WS_VISIBLE)) return FALSE;
385 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
386 return !(style & WS_DISABLED);
390 /**********************************************************************
391 * set_focus_error_handler
393 * Handler for X errors happening during XSetInputFocus call.
395 static int set_focus_error_handler( Display *display, XErrorEvent *event, void *arg )
397 return (event->error_code == BadMatch);
401 /**********************************************************************
404 static void set_focus( HWND hwnd, Time time )
409 TRACE( "setting foreground window to %p\n", hwnd );
410 SetForegroundWindow( hwnd );
413 if (focus) focus = GetAncestor( focus, GA_ROOT );
414 win = X11DRV_get_whole_window(focus);
418 Display *display = thread_display();
419 TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time );
420 X11DRV_expect_error( display, set_focus_error_handler, NULL );
421 XSetInputFocus( display, win, RevertToParent, time );
422 XSync( display, False );
423 if (X11DRV_check_error()) TRACE("got BadMatch, ignoring\n" );
428 /**********************************************************************
429 * handle_wm_protocols_message
431 static void handle_wm_protocols_message( HWND hwnd, XClientMessageEvent *event )
433 Atom protocol = (Atom)event->data.l[0];
435 if (!protocol) return;
437 if (protocol == wmDeleteWindow)
439 /* Ignore the delete window request if the window has been disabled
440 * and we are in managed mode. This is to disallow applications from
441 * being closed by the window manager while in a modal state.
443 if (IsWindowEnabled(hwnd)) PostMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
445 else if (protocol == wmTakeFocus)
447 Time event_time = (Time)event->data.l[1];
448 HWND last_focus = x11drv_thread_data()->last_focus;
450 TRACE( "got take focus msg for %p, enabled=%d, focus=%p, active=%p, fg=%p, last=%p\n",
451 hwnd, IsWindowEnabled(hwnd), GetFocus(), GetActiveWindow(),
452 GetForegroundWindow(), last_focus );
454 if (can_activate_window(hwnd))
456 /* simulate a mouse click on the caption to find out
457 * whether the window wants to be activated */
458 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
459 (WPARAM)GetAncestor( hwnd, GA_ROOT ),
460 MAKELONG(HTCAPTION,WM_LBUTTONDOWN) );
461 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) set_focus( hwnd, event_time );
462 else TRACE( "not setting focus to %p (%lx), ma=%ld\n", hwnd, event->window, ma );
467 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
468 if (!hwnd) hwnd = GetActiveWindow();
469 if (!hwnd) hwnd = last_focus;
470 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
472 } else if (protocol == netwmPing) {
473 XClientMessageEvent xev;
476 TRACE("NET_WM Ping\n");
477 xev.window = DefaultRootWindow(xev.display);
478 XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
479 /* this line is semi-stolen from gtk2 */
480 TRACE("NET_WM Pong\n");
485 static const char * const focus_details[] =
491 "NotifyNonlinearVirtual",
497 /**********************************************************************
500 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
506 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
508 if (event->detail == NotifyPointer) return;
510 if ((xic = X11DRV_get_ic( hwnd )))
516 if (wmTakeFocus) return; /* ignore FocusIn if we are using take focus */
518 if (!can_activate_window(hwnd))
520 HWND hwnd = GetFocus();
521 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
522 if (!hwnd) hwnd = GetActiveWindow();
523 if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
524 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
526 else SetForegroundWindow( hwnd );
530 /**********************************************************************
533 * Note: only top-level windows get FocusOut events.
535 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
542 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
544 if (event->detail == NotifyPointer) return;
545 x11drv_thread_data()->last_focus = hwnd;
546 if ((xic = X11DRV_get_ic( hwnd )))
549 XUnsetICFocus( xic );
552 if (hwnd != GetForegroundWindow()) return;
553 SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
555 /* don't reset the foreground window, if the window which is
556 getting the focus is a Wine window */
559 XGetInputFocus( thread_display(), &focus_win, &revert );
562 if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
569 /* Abey : 6-Oct-99. Check again if the focus out window is the
570 Foreground window, because in most cases the messages sent
571 above must have already changed the foreground window, in which
572 case we don't have to change the foreground window to 0 */
573 if (hwnd == GetForegroundWindow())
575 TRACE( "lost focus, setting fg to 0\n" );
576 SetForegroundWindow( 0 );
582 /***********************************************************************
583 * EVENT_SelectionRequest_AddTARGETS
584 * Utility function for EVENT_SelectionRequest_TARGETS.
586 static void EVENT_SelectionRequest_AddTARGETS(Atom* targets, unsigned long* cTargets, Atom prop)
591 /* Scan through what we have so far to avoid duplicates */
592 for (i = 0, bExists = FALSE; i < *cTargets; i++)
594 if (targets[i] == prop)
602 targets[(*cTargets)++] = prop;
606 /***********************************************************************
607 * EVENT_SelectionRequest_TARGETS
608 * Service a TARGETS selection request event
610 static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
611 Atom target, Atom rprop )
619 * Count the number of items we wish to expose as selection targets.
620 * We include the TARGETS item, and propery aliases
622 cTargets = X11DRV_CountClipboardFormats() + 1;
624 for (wFormat = 0; (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
626 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
627 if (lpFormat && X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData))
631 TRACE_(clipboard)(" found %ld formats\n", cTargets);
633 /* Allocate temp buffer */
634 targets = (Atom*)HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
638 /* Create TARGETS property list (First item in list is TARGETS itself) */
639 for (targets[0] = xaTargets, cTargets = 1, wFormat = 0;
640 (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
642 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
644 EVENT_SelectionRequest_AddTARGETS(targets, &cTargets, lpFormat->drvData);
646 /* Check if any alias should be listed */
647 alias = X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData);
649 EVENT_SelectionRequest_AddTARGETS(targets, &cTargets, alias);
652 if (TRACE_ON(clipboard))
655 for ( i = 0; i < cTargets; i++)
659 char *itemFmtName = TSXGetAtomName(display, targets[i]);
660 TRACE_(clipboard)("\tAtom# %d: Property %ld Type %s\n", i, targets[i], itemFmtName);
661 TSXFree(itemFmtName);
666 /* We may want to consider setting the type to xaTargets instead,
667 * in case some apps expect this instead of XA_ATOM */
668 TSXChangeProperty(display, requestor, rprop, XA_ATOM, 32,
669 PropModeReplace, (unsigned char *)targets, cTargets);
671 HeapFree(GetProcessHeap(), 0, targets);
677 /***********************************************************************
678 * EVENT_SelectionRequest_MULTIPLE
679 * Service a MULTIPLE selection request event
680 * rprop contains a list of (target,property) atom pairs.
681 * The first atom names a target and the second names a property.
682 * The effect is as if we have received a sequence of SelectionRequest events
683 * (one for each atom pair) except that:
684 * 1. We reply with a SelectionNotify only when all the requested conversions
685 * have been performed.
686 * 2. If we fail to convert the target named by an atom in the MULTIPLE property,
687 * we replace the atom in the property by None.
689 static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
691 Display *display = pevent->display;
693 Atom atype=AnyPropertyType;
695 unsigned long remain;
696 Atom* targetPropList=NULL;
697 unsigned long cTargetPropList = 0;
698 /* Atom xAtomPair = TSXInternAtom(display, "ATOM_PAIR", False); */
700 /* If the specified property is None the requestor is an obsolete client.
701 * We support these by using the specified target atom as the reply property.
703 rprop = pevent->property;
705 rprop = pevent->target;
709 /* Read the MULTIPLE property contents. This should contain a list of
710 * (target,property) atom pairs.
712 if(TSXGetWindowProperty(display, pevent->requestor, rprop,
713 0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
714 &cTargetPropList, &remain,
715 (unsigned char**)&targetPropList) != Success)
716 TRACE("\tCouldn't read MULTIPLE property\n");
719 TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
720 TSXGetAtomName(display, atype), aformat, cTargetPropList, remain);
723 * Make sure we got what we expect.
724 * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
725 * in a MULTIPLE selection request should be of type ATOM_PAIR.
726 * However some X apps(such as XPaint) are not compliant with this and return
727 * a user defined atom in atype when XGetWindowProperty is called.
728 * The data *is* an atom pair but is not denoted as such.
730 if(aformat == 32 /* atype == xAtomPair */ )
734 /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
735 * for each (target,property) pair */
737 for (i = 0; i < cTargetPropList; i+=2)
739 char *targetName = TSXGetAtomName(display, targetPropList[i]);
740 char *propName = TSXGetAtomName(display, targetPropList[i+1]);
741 XSelectionRequestEvent event;
743 TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
744 i/2, targetName, propName);
748 /* We must have a non "None" property to service a MULTIPLE target atom */
749 if ( !targetPropList[i+1] )
751 TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
755 /* Set up an XSelectionRequestEvent for this (target,property) pair */
756 memcpy( &event, pevent, sizeof(XSelectionRequestEvent) );
757 event.target = targetPropList[i];
758 event.property = targetPropList[i+1];
760 /* Fire a SelectionRequest, informing the handler that we are processing
761 * a MULTIPLE selection request event.
763 EVENT_SelectionRequest( hWnd, &event, TRUE );
767 /* Free the list of targets/properties */
768 TSXFree(targetPropList);
776 /***********************************************************************
777 * EVENT_SelectionRequest
778 * Process an event selection request event.
779 * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
780 * recursively while servicing a "MULTIPLE" selection target.
782 * Note: We only receive this event when WINE owns the X selection
784 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
786 Display *display = event->display;
787 XSelectionEvent result;
789 Window request = event->requestor;
791 TRACE_(clipboard)("\n");
794 * We can only handle the selection request if :
795 * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
796 * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
797 * since this has been already done.
801 if (((event->selection != XA_PRIMARY) && (event->selection != xaClipboard)))
805 /* If the specified property is None the requestor is an obsolete client.
806 * We support these by using the specified target atom as the reply property.
808 rprop = event->property;
810 rprop = event->target;
812 if(event->target == xaTargets) /* Return a list of all supported targets */
814 /* TARGETS selection request */
815 rprop = EVENT_SelectionRequest_TARGETS( display, request, event->target, rprop );
817 else if(event->target == xaMultiple) /* rprop contains a list of (target, property) atom pairs */
819 /* MULTIPLE selection request */
820 rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
824 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(event->target);
827 lpFormat = X11DRV_CLIPBOARD_LookupAliasProperty(event->target);
831 LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(lpFormat->wFormatID);
835 unsigned char* lpClipData;
837 HANDLE hClipData = lpFormat->lpDrvExportFunc(request, event->target,
838 rprop, lpData, &cBytes);
840 if (hClipData && (lpClipData = GlobalLock(hClipData)))
843 TRACE_(clipboard)("\tUpdating property %s, %ld bytes\n",
844 lpFormat->Name, cBytes);
846 TSXChangeProperty(display, request, rprop, event->target,
847 8, PropModeReplace, (unsigned char *)lpClipData, cBytes);
849 GlobalUnlock(hClipData);
850 GlobalFree(hClipData);
856 if (TRACE_ON(clipboard))
858 TRACE_(clipboard)("Request for property %s (%ld) failed\n",
859 TSXGetAtomName(display, event->target), event->target);
866 * SelectionNotify should be sent only at the end of a MULTIPLE request
870 result.type = SelectionNotify;
871 result.display = display;
872 result.requestor = request;
873 result.selection = event->selection;
874 result.property = rprop;
875 result.target = event->target;
876 result.time = event->time;
877 TRACE("Sending SelectionNotify event...\n");
878 TSXSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
882 /***********************************************************************
883 * EVENT_SelectionClear
885 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
887 if (event->selection == XA_PRIMARY || event->selection == xaClipboard)
888 X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
891 /***********************************************************************
892 * EVENT_PropertyNotify
893 * We use this to release resources like Pixmaps when a selection
894 * client no longer needs them.
896 static void EVENT_PropertyNotify( XPropertyEvent *event )
898 /* Check if we have any resources to free */
899 TRACE("Received PropertyNotify event: \n");
905 TRACE("\tPropertyDelete for atom %s on window %ld\n",
906 TSXGetAtomName(event->display, event->atom), (long)event->window);
910 case PropertyNewValue:
912 TRACE("\tPropertyNewValue for atom %s on window %ld\n\n",
913 TSXGetAtomName(event->display, event->atom), (long)event->window);
922 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
926 if (!IsWindowEnabled(hQueryWnd)) return 0;
928 GetWindowRect(hQueryWnd, &tempRect);
930 if(!PtInRect(&tempRect, *lpPt)) return 0;
932 if (!IsIconic( hQueryWnd ))
934 GetClientRect( hQueryWnd, &tempRect );
935 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
937 if (PtInRect( &tempRect, *lpPt))
939 HWND *list = WIN_ListChildren( hQueryWnd );
946 for (i = 0; list[i]; i++)
948 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
950 GetWindowRect( list[i], &tempRect );
951 if (PtInRect( &tempRect, *lpPt )) break;
956 if (IsWindowEnabled( list[i] ))
957 bResult = find_drop_window( list[i], lpPt );
959 HeapFree( GetProcessHeap(), 0, list );
961 if(bResult) return bResult;
965 if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
967 ScreenToClient(hQueryWnd, lpPt);
972 /**********************************************************************
973 * EVENT_DropFromOffix
975 * don't know if it still works (last Changlog is from 96/11/04)
977 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
979 unsigned long data_length;
980 unsigned long aux_long;
981 unsigned char* p_data = NULL;
992 Window w_aux_root, w_aux_child;
996 pWnd = WIN_FindWndPtr(hWnd);
998 TSXQueryPointer( event->display, get_whole_window(pWnd), &w_aux_root, &w_aux_child,
999 &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
1000 (unsigned int*)&aux_long);
1002 /* find out drop point and drop window */
1003 if( x < 0 || y < 0 ||
1004 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1005 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1007 bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES;
1013 POINT pt = { x, y };
1014 HWND hwndDrop = find_drop_window( hWnd, &pt );
1027 WIN_ReleaseWndPtr(pWnd);
1029 if (!bAccept) return;
1031 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1032 dndSelection, 0, 65535, FALSE,
1033 AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1034 &data_length, &aux_long, &p_data);
1036 if( !aux_long && p_data) /* don't bother if > 64K */
1038 signed char *p = (signed char*) p_data;
1042 while( *p ) /* calculate buffer size */
1045 if((u.i = *p) != -1 )
1047 INT len = GetShortPathNameA( p, NULL, 0 );
1048 if (len) aux_long += len + 1;
1053 if( aux_long && aux_long < 65535 )
1058 aux_long += sizeof(DROPFILES) + 1;
1059 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
1060 lpDrop = (DROPFILES*)GlobalLock( hDrop );
1064 WND *pDropWnd = WIN_FindWndPtr( hScope );
1065 lpDrop->pFiles = sizeof(DROPFILES);
1069 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1070 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1071 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1072 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1073 lpDrop->fWide = FALSE;
1074 WIN_ReleaseWndPtr(pDropWnd);
1075 p_drop = (char *)(lpDrop + 1);
1079 if( *p != -1 ) /* use only "good" entries */
1081 GetShortPathNameA( p, p_drop, 65535 );
1082 p_drop += strlen( p_drop ) + 1;
1087 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1091 if( p_data ) TSXFree(p_data);
1094 /**********************************************************************
1097 * drop items are separated by \n
1098 * each item is prefixed by its mime type
1100 * event->data.l[3], event->data.l[4] contains drop x,y position
1102 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
1104 unsigned long data_length;
1105 unsigned long aux_long, drop_len = 0;
1106 unsigned char *p_data = NULL; /* property data */
1107 char *p_drop = NULL;
1118 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
1120 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1121 dndSelection, 0, 65535, FALSE,
1122 AnyPropertyType, &u.atom_aux, &u.i,
1123 &data_length, &aux_long, &p_data);
1125 WARN("property too large, truncated!\n");
1126 TRACE("urls=%s\n", p_data);
1128 if( !aux_long && p_data) { /* don't bother if > 64K */
1129 /* calculate length */
1131 next = strchr(p, '\n');
1134 if (strncmp(p,"file:",5) == 0 ) {
1135 INT len = GetShortPathNameA( p+5, NULL, 0 );
1136 if (len) drop_len += len + 1;
1141 next = strchr(p, '\n');
1147 if( drop_len && drop_len < 65535 ) {
1148 TSXQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
1149 &x, &y, &u.i, &u.i, &u.i);
1151 drop_len += sizeof(DROPFILES) + 1;
1152 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
1153 lpDrop = (DROPFILES *) GlobalLock( hDrop );
1156 WND *pDropWnd = WIN_FindWndPtr( hWnd );
1157 lpDrop->pFiles = sizeof(DROPFILES);
1158 lpDrop->pt.x = (INT)x;
1159 lpDrop->pt.y = (INT)y;
1161 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1162 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1163 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1164 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1165 lpDrop->fWide = FALSE;
1166 p_drop = (char*)(lpDrop + 1);
1167 WIN_ReleaseWndPtr(pDropWnd);
1170 /* create message content */
1173 next = strchr(p, '\n');
1176 if (strncmp(p,"file:",5) == 0 ) {
1177 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
1179 TRACE("drop file %s as %s\n", p+5, p_drop);
1182 WARN("can't convert file %s to dos name \n", p+5);
1185 WARN("unknown mime type %s\n", p);
1190 next = strchr(p, '\n');
1197 GlobalUnlock(hDrop);
1198 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1201 if( p_data ) TSXFree(p_data);
1205 /**********************************************************************
1206 * EVENT_ClientMessage
1208 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
1210 if (event->message_type != None && event->format == 32) {
1211 if (event->message_type == wmProtocols)
1212 handle_wm_protocols_message( hWnd, event );
1213 else if (event->message_type == dndProtocol)
1215 /* query window (drag&drop event contains only drag window) */
1217 int root_x, root_y, child_x, child_y;
1221 XQueryPointer( event->display, root_window, &root, &child,
1222 &root_x, &root_y, &child_x, &child_y, &u);
1223 if (XFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) hWnd = 0;
1224 wine_tsx11_unlock();
1226 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
1227 EVENT_DropFromOffiX(hWnd, event);
1228 else if (event->data.l[0] == DndURL)
1229 EVENT_DropURLs(hWnd, event);
1233 /* enable this if you want to see the message */
1234 unsigned char* p_data = NULL;
1240 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1241 dndSelection, 0, 65535, FALSE,
1242 AnyPropertyType, &u.atom, &u.i,
1243 &u.l, &u.l, &p_data);
1244 TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1245 event->message_type, event->data.l[0], event->data.l[1],
1246 event->data.l[2], event->data.l[3], event->data.l[4],
1249 TRACE("unrecognized ClientMessage\n" );
1255 /**********************************************************************
1256 * X11DRV_EVENT_SetInputMethod
1258 INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
1260 INPUT_TYPE prev = current_input_type;
1262 /* Flag not used yet */
1263 in_transition = FALSE;
1264 current_input_type = type;
1269 #ifdef HAVE_LIBXXF86DGA2
1270 /**********************************************************************
1271 * X11DRV_EVENT_SetDGAStatus
1273 void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
1275 if (event_base < 0) {
1281 DGAMotionEventType = event_base + MotionNotify;
1282 DGAButtonPressEventType = event_base + ButtonPress;
1283 DGAButtonReleaseEventType = event_base + ButtonRelease;
1284 DGAKeyPressEventType = event_base + KeyPress;
1285 DGAKeyReleaseEventType = event_base + KeyRelease;