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
24 #include <X11/Xatom.h>
25 #include <X11/keysym.h>
28 #include "ts_xresource.h"
30 #ifdef HAVE_LIBXXF86DGA2
31 #include "ts_xf86dga2.h"
36 #include "wine/winuser16.h"
37 #include "shlobj.h" /* DROPFILES */
39 #include "clipboard.h"
41 #include "wine/debug.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(event);
52 WINE_DECLARE_DEBUG_CHANNEL(win);
54 /* X context to associate a hwnd to an X window */
55 extern XContext winContext;
57 extern Atom wmProtocols;
58 extern Atom wmDeleteWindow;
59 extern Atom dndProtocol;
60 extern Atom dndSelection;
62 #define DndNotDnd -1 /* OffiX drag&drop */
74 #define DndURL 128 /* KDE drag&drop */
76 /* The last X window which had the focus */
77 static Window glastXFocusWin = 0;
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 );
93 static BOOL X11DRV_CheckFocus(void);
96 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
97 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
98 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
99 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
100 static void EVENT_PropertyNotify( XPropertyEvent *event );
101 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
103 extern void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event );
104 extern void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event );
105 extern void X11DRV_MotionNotify( HWND hwnd, XMotionEvent *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 ) )
145 XNextEvent( data->display, &event );
147 EVENT_ProcessEvent( &event );
156 /***********************************************************************
157 * MsgWaitForMultipleObjectsEx (X11DRV.@)
159 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
160 DWORD timeout, DWORD mask, DWORD flags )
162 HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1]; /* FIXME! */
164 struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
166 if (!data || data->process_event_count)
167 return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
168 timeout, flags & MWMO_ALERTABLE );
170 for (i = 0; i < count; i++) new_handles[i] = handles[i];
171 new_handles[count] = data->display_fd;
174 XFlush( gdi_display );
175 XFlush( data->display );
178 data->process_event_count++;
179 if (process_events( data )) ret = count;
182 ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
183 timeout, flags & MWMO_ALERTABLE );
184 if (ret == count) process_events( data );
186 data->process_event_count--;
191 /***********************************************************************
194 * Process an X event.
196 static void EVENT_ProcessEvent( XEvent *event )
199 Display *display = event->xany.display;
201 TRACE( "called.\n" );
205 case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
206 FIXME("Got SelectionNotify - must not happen!\n");
209 /* We get all these because of StructureNotifyMask.
210 This check is placed here to avoid getting error messages below,
211 as X might send some of these even for windows that have already
213 case CirculateNotify:
221 #ifdef HAVE_LIBXXF86DGA2
223 if (event->type == DGAMotionEventType) {
224 TRACE("DGAMotionEvent received.\n");
225 X11DRV_DGAMotionEvent( DGAhwnd, (XDGAMotionEvent *)event );
228 if (event->type == DGAButtonPressEventType) {
229 TRACE("DGAButtonPressEvent received.\n");
230 X11DRV_DGAButtonPressEvent( DGAhwnd, (XDGAButtonEvent *)event );
233 if (event->type == DGAButtonReleaseEventType) {
234 TRACE("DGAButtonReleaseEvent received.\n");
235 X11DRV_DGAButtonReleaseEvent( DGAhwnd, (XDGAButtonEvent *)event );
238 if ((event->type == DGAKeyPressEventType) ||
239 (event->type == DGAKeyReleaseEventType)) {
240 /* Fill a XKeyEvent to send to EVENT_Key */
242 XDGAKeyEvent *evt = (XDGAKeyEvent *) event;
244 TRACE("DGAKeyPress/ReleaseEvent received.\n");
246 if (evt->type == DGAKeyReleaseEventType)
247 ke.type = KeyRelease;
250 ke.serial = evt->serial;
251 ke.send_event = FALSE;
252 ke.display = evt->display;
261 ke.state = evt->state;
262 ke.keycode = evt->keycode;
263 ke.same_screen = TRUE;
264 X11DRV_KeyEvent( 0, &ke );
270 if (TSXFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
271 hWnd = 0; /* Not for a registered window */
273 if ( !hWnd && event->xany.window != root_window
274 && event->type != PropertyNotify
275 && event->type != MappingNotify)
276 WARN( "Got event %s for unknown Window %08lx\n",
277 event_names[event->type], event->xany.window );
279 TRACE("Got event %s for hwnd %04x\n",
280 event_names[event->type], hWnd );
286 /* FIXME: should generate a motion event if event point is different from current pos */
287 X11DRV_KeyEvent( hWnd, (XKeyEvent*)event );
291 X11DRV_ButtonPress( hWnd, (XButtonEvent*)event );
295 X11DRV_ButtonRelease( hWnd, (XButtonEvent*)event );
299 X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
303 EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
307 EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
311 X11DRV_Expose( hWnd, &event->xexpose );
314 case ConfigureNotify:
316 X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
319 case SelectionRequest:
321 EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
326 EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
330 EVENT_PropertyNotify( (XPropertyEvent *)event );
335 EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
342 X11DRV_MapNotify( hWnd, (XMapEvent *)event );
346 X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
350 X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
354 X11DRV_MappingNotify( (XMappingEvent *) event );
358 WARN("Unprocessed event %s for hwnd %04x\n",
359 event_names[event->type], hWnd );
362 TRACE( "returns.\n" );
366 /**********************************************************************
369 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event )
372 XWindowAttributes win_attr;
377 bIsDisabled = GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED;
379 /* If the window has been disabled and we are in managed mode,
380 * revert the X focus back to the last focus window. This is to disallow
381 * the window manager from switching focus away while the app is
384 if ( Options.managed && bIsDisabled && glastXFocusWin)
386 /* Change focus only if saved focus window is registered and viewable */
388 if (XFindContext( event->display, glastXFocusWin, winContext,
389 (char **)&pWndLastFocus ) == 0 )
391 if (XGetWindowAttributes( event->display, glastXFocusWin, &win_attr ) &&
392 (win_attr.map_state == IsViewable) )
394 XSetInputFocus( event->display, glastXFocusWin, RevertToParent, CurrentTime );
402 if (event->detail != NotifyPointer && hWnd != GetForegroundWindow())
403 SetForegroundWindow( hWnd );
407 /**********************************************************************
410 * Note: only top-level override-redirect windows get FocusOut events.
412 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event )
414 /* Save the last window which had the focus */
415 glastXFocusWin = event->window;
417 if (GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED) glastXFocusWin = 0;
419 if (event->detail != NotifyPointer && hWnd == GetForegroundWindow())
421 /* don't reset the foreground window, if the window which is
422 getting the focus is a Wine window */
423 if (!X11DRV_CheckFocus())
425 SendMessageA( hWnd, WM_CANCELMODE, 0, 0 );
426 /* Abey : 6-Oct-99. Check again if the focus out window is the
427 Foreground window, because in most cases the messages sent
428 above must have already changed the foreground window, in which
429 case we don't have to change the foreground window to 0 */
431 if (hWnd == GetForegroundWindow())
432 SetForegroundWindow( 0 );
437 /**********************************************************************
438 * CheckFocus (X11DRV.@)
440 static BOOL X11DRV_CheckFocus(void)
442 Display *display = thread_display();
447 TSXGetInputFocus(display, &xW, &state);
449 TSXFindContext(display, xW, winContext, (char **)&hWnd) )
455 /***********************************************************************
456 * EVENT_SelectionRequest_TARGETS
457 * Service a TARGETS selection request event
459 static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
460 Atom target, Atom rprop )
462 Atom xaTargets = TSXInternAtom(display, "TARGETS", False);
466 unsigned long cTargets;
470 TRACE("Request for %s\n", TSXGetAtomName(display, target));
473 * Count the number of items we wish to expose as selection targets.
474 * We include the TARGETS item, and a PIXMAP if we have CF_DIB or CF_BITMAP
476 cTargets = CountClipboardFormats() + 1;
477 if ( CLIPBOARD_IsPresent(CF_DIB) || CLIPBOARD_IsPresent(CF_BITMAP) )
480 /* Allocate temp buffer */
481 targets = (Atom*)HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
482 if(targets == NULL) return None;
484 /* Create TARGETS property list (First item in list is TARGETS itself) */
486 for ( targets[0] = xaTargets, cTargets = 1, wFormat = 0, bHavePixmap = FALSE;
487 (wFormat = EnumClipboardFormats( wFormat )); )
489 if ( (prop = X11DRV_CLIPBOARD_MapFormatToProperty(wFormat)) != None )
491 /* Scan through what we have so far to avoid duplicates */
494 for (i = 0, bExists = FALSE; i < cTargets; i++)
496 if (targets[i] == prop)
504 targets[cTargets++] = prop;
506 /* Add PIXMAP prop for bitmaps additionally */
507 if ( (wFormat == CF_DIB || wFormat == CF_BITMAP )
510 targets[cTargets++] = XA_PIXMAP;
520 for ( i = 0; i < cTargets; i++)
524 char *itemFmtName = TSXGetAtomName(display, targets[i]);
525 TRACE("\tAtom# %d: Type %s\n", i, itemFmtName);
526 TSXFree(itemFmtName);
531 /* Update the X property */
532 TRACE("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
534 /* We may want to consider setting the type to xaTargets instead,
535 * in case some apps expect this instead of XA_ATOM */
536 xRc = TSXChangeProperty(display, requestor, rprop,
537 XA_ATOM, 32, PropModeReplace,
538 (unsigned char *)targets, cTargets);
539 TRACE("(Rc=%d)\n", xRc);
541 HeapFree( GetProcessHeap(), 0, targets );
547 /***********************************************************************
548 * EVENT_SelectionRequest_STRING
549 * Service a STRING selection request event
551 static Atom EVENT_SelectionRequest_STRING( Display *display, Window requestor,
552 Atom target, Atom rprop )
554 static UINT text_cp = (UINT)-1;
563 if(text_cp == (UINT)-1)
568 if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\x11drv", &hkey))
571 DWORD type, count = sizeof(buf);
572 if(!RegQueryValueExA(hkey, "TextCP", 0, &type, buf, &count))
579 * Map the requested X selection property type atom name to a
580 * windows clipboard format ID.
582 itemFmtName = TSXGetAtomName(display, target);
583 TRACE("Request for %s (wFormat=%x %s)\n",
584 itemFmtName, CF_UNICODETEXT, CLIPBOARD_GetFormatName(CF_UNICODETEXT));
585 TSXFree(itemFmtName);
587 hUnicodeText = GetClipboardData(CF_UNICODETEXT);
590 uni_text = GlobalLock(hUnicodeText);
594 size = WideCharToMultiByte(text_cp, 0, uni_text, -1, NULL, 0, NULL, NULL);
595 text = HeapAlloc(GetProcessHeap(), 0, size);
598 WideCharToMultiByte(text_cp, 0, uni_text, -1, text, size, NULL, NULL);
600 /* remove carriage returns */
602 lpstr = (char*)HeapAlloc( GetProcessHeap(), 0, size-- );
603 if(lpstr == NULL) return None;
604 for(i=0,j=0; i < size && text[i]; i++ )
606 if( text[i] == '\r' &&
607 (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
608 lpstr[j++] = text[i];
612 /* Update the X property */
613 TRACE("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
614 xRc = TSXChangeProperty(display, requestor, rprop,
615 XA_STRING, 8, PropModeReplace,
617 TRACE("(Rc=%d)\n", xRc);
619 GlobalUnlock(hUnicodeText);
620 HeapFree(GetProcessHeap(), 0, text);
621 HeapFree( GetProcessHeap(), 0, lpstr );
626 /***********************************************************************
627 * EVENT_SelectionRequest_PIXMAP
628 * Service a PIXMAP selection request event
630 static Atom EVENT_SelectionRequest_PIXMAP( Display *display, Window requestor,
631 Atom target, Atom rprop )
633 HANDLE hClipData = 0;
639 XSetWindowAttributes win_attr;
640 XWindowAttributes win_attr_src;
644 * Map the requested X selection property type atom name to a
645 * windows clipboard format ID.
647 itemFmtName = TSXGetAtomName(display, target);
648 wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
649 TRACE("Request for %s (wFormat=%x %s)\n",
650 itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat));
651 TSXFree(itemFmtName);
653 hClipData = GetClipboardData(wFormat);
656 TRACE("Could not retrieve a Pixmap compatible format from clipboard!\n");
657 rprop = None; /* Fail the request */
661 if (wFormat == CF_DIB)
663 HWND hwnd = GetOpenClipboardWindow();
664 HDC hdc = GetDC(hwnd);
666 /* For convert from packed DIB to Pixmap */
667 pixmap = X11DRV_DIB_CreatePixmapFromDIB(hClipData, hdc);
669 ReleaseDC(hwnd, hdc);
671 else if (wFormat == CF_BITMAP)
673 HWND hwnd = GetOpenClipboardWindow();
674 HDC hdc = GetDC(hwnd);
676 pixmap = X11DRV_BITMAP_CreatePixmapFromBitmap(hClipData, hdc);
678 ReleaseDC(hwnd, hdc);
682 FIXME("%s to PIXMAP conversion not yet implemented!\n",
683 CLIPBOARD_GetFormatName(wFormat));
688 TRACE("\tUpdating property %s on Window %ld with %s %ld...\n",
689 TSXGetAtomName(display, rprop), (long)requestor,
690 TSXGetAtomName(display, target), pixmap);
692 /* Store the Pixmap handle in the property */
693 xRc = TSXChangeProperty(display, requestor, rprop, target,
695 (unsigned char *)&pixmap, 1);
696 TRACE("(Rc=%d)\n", xRc);
698 /* Enable the code below if you want to handle destroying Pixmap resources
699 * in response to property notify events. Clients like XPaint don't
700 * appear to be duplicating Pixmaps so they don't like us deleting,
701 * the resource in response to the property being deleted.
704 /* Express interest in property notify events so that we can delete the
705 * pixmap when the client deletes the property atom.
707 xRc = TSXGetWindowAttributes(display, requestor, &win_attr_src);
708 TRACE("Turning on PropertyChangeEvent notifications from window %ld\n",
710 win_attr.event_mask = win_attr_src.your_event_mask | PropertyChangeMask;
711 TSXChangeWindowAttributes(display, requestor, CWEventMask, &win_attr);
713 /* Register the Pixmap we created with the request property Atom.
714 * When this property is destroyed we also destroy the Pixmap in
715 * response to the PropertyNotify event.
717 X11DRV_CLIPBOARD_RegisterPixmapResource( rprop, pixmap );
725 /***********************************************************************
726 * EVENT_SelectionRequest_WCF
727 * Service a Wine Clipboard Format selection request event.
728 * For <WCF>* data types we simply copy the data to X without conversion.
730 static Atom EVENT_SelectionRequest_WCF( Display *display, Window requestor,
731 Atom target, Atom rprop )
733 HANDLE hClipData = 0;
741 * Map the requested X selection property type atom name to a
742 * windows clipboard format ID.
744 itemFmtName = TSXGetAtomName(display, target);
745 wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
746 TRACE("Request for %s (wFormat=%x %s)\n",
747 itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat));
748 TSXFree(itemFmtName);
750 hClipData = GetClipboardData(wFormat);
752 if( hClipData && (lpClipData = GlobalLock(hClipData)) )
754 cBytes = GlobalSize(hClipData);
756 TRACE("\tUpdating property %s, %d bytes...\n",
757 TSXGetAtomName(display, rprop), cBytes);
759 xRc = TSXChangeProperty(display, requestor, rprop,
760 target, 8, PropModeReplace,
761 (unsigned char *)lpClipData, cBytes);
762 TRACE("(Rc=%d)\n", xRc);
764 GlobalUnlock(hClipData);
768 TRACE("\tCould not retrieve native format!\n");
769 rprop = None; /* Fail the request */
776 /***********************************************************************
777 * EVENT_SelectionRequest_MULTIPLE
778 * Service a MULTIPLE selection request event
779 * rprop contains a list of (target,property) atom pairs.
780 * The first atom names a target and the second names a property.
781 * The effect is as if we have received a sequence of SelectionRequest events
782 * (one for each atom pair) except that:
783 * 1. We reply with a SelectionNotify only when all the requested conversions
784 * have been performed.
785 * 2. If we fail to convert the target named by an atom in the MULTIPLE property,
786 * we replace the atom in the property by None.
788 static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
790 Display *display = pevent->display;
792 Atom atype=AnyPropertyType;
794 unsigned long remain;
795 Atom* targetPropList=NULL;
796 unsigned long cTargetPropList = 0;
797 /* Atom xAtomPair = TSXInternAtom(display, "ATOM_PAIR", False); */
799 /* If the specified property is None the requestor is an obsolete client.
800 * We support these by using the specified target atom as the reply property.
802 rprop = pevent->property;
804 rprop = pevent->target;
808 /* Read the MULTIPLE property contents. This should contain a list of
809 * (target,property) atom pairs.
811 if(TSXGetWindowProperty(display, pevent->requestor, rprop,
812 0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
813 &cTargetPropList, &remain,
814 (unsigned char**)&targetPropList) != Success)
815 TRACE("\tCouldn't read MULTIPLE property\n");
818 TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
819 TSXGetAtomName(display, atype), aformat, cTargetPropList, remain);
822 * Make sure we got what we expect.
823 * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
824 * in a MULTIPLE selection request should be of type ATOM_PAIR.
825 * However some X apps(such as XPaint) are not compliant with this and return
826 * a user defined atom in atype when XGetWindowProperty is called.
827 * The data *is* an atom pair but is not denoted as such.
829 if(aformat == 32 /* atype == xAtomPair */ )
833 /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
834 * for each (target,property) pair */
836 for (i = 0; i < cTargetPropList; i+=2)
838 char *targetName = TSXGetAtomName(display, targetPropList[i]);
839 char *propName = TSXGetAtomName(display, targetPropList[i+1]);
840 XSelectionRequestEvent event;
842 TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
843 i/2, targetName, propName);
847 /* We must have a non "None" property to service a MULTIPLE target atom */
848 if ( !targetPropList[i+1] )
850 TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
854 /* Set up an XSelectionRequestEvent for this (target,property) pair */
855 memcpy( &event, pevent, sizeof(XSelectionRequestEvent) );
856 event.target = targetPropList[i];
857 event.property = targetPropList[i+1];
859 /* Fire a SelectionRequest, informing the handler that we are processing
860 * a MULTIPLE selection request event.
862 EVENT_SelectionRequest( hWnd, &event, TRUE );
866 /* Free the list of targets/properties */
867 TSXFree(targetPropList);
875 /***********************************************************************
876 * EVENT_SelectionRequest
877 * Process an event selection request event.
878 * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
879 * recursively while servicing a "MULTIPLE" selection target.
881 * Note: We only receive this event when WINE owns the X selection
883 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
885 Display *display = event->display;
886 XSelectionEvent result;
888 Window request = event->requestor;
889 BOOL couldOpen = FALSE;
890 Atom xaClipboard = TSXInternAtom(display, "CLIPBOARD", False);
891 Atom xaTargets = TSXInternAtom(display, "TARGETS", False);
892 Atom xaMultiple = TSXInternAtom(display, "MULTIPLE", False);
895 * We can only handle the selection request if :
896 * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
897 * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
898 * since this has been already done.
902 if ( ( (event->selection != XA_PRIMARY) && (event->selection != xaClipboard) )
903 || !(couldOpen = OpenClipboard(hWnd)) )
907 /* If the specified property is None the requestor is an obsolete client.
908 * We support these by using the specified target atom as the reply property.
910 rprop = event->property;
912 rprop = event->target;
914 if(event->target == xaTargets) /* Return a list of all supported targets */
916 /* TARGETS selection request */
917 rprop = EVENT_SelectionRequest_TARGETS( display, request, event->target, rprop );
919 else if(event->target == xaMultiple) /* rprop contains a list of (target, property) atom pairs */
921 /* MULTIPLE selection request */
922 rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
924 else if(event->target == XA_STRING) /* treat CF_TEXT as Unix text */
926 /* XA_STRING selection request */
927 rprop = EVENT_SelectionRequest_STRING( display, request, event->target, rprop );
929 else if(event->target == XA_PIXMAP) /* Convert DIB's to Pixmaps */
931 /* XA_PIXMAP selection request */
932 rprop = EVENT_SelectionRequest_PIXMAP( display, request, event->target, rprop );
934 else if(event->target == XA_BITMAP) /* Convert DIB's to 1-bit Pixmaps */
936 /* XA_BITMAP selection request - TODO: create a monochrome Pixmap */
937 rprop = EVENT_SelectionRequest_PIXMAP( display, request, XA_PIXMAP, rprop );
939 else if(X11DRV_CLIPBOARD_IsNativeProperty(event->target)) /* <WCF>* */
941 /* All <WCF> selection requests */
942 rprop = EVENT_SelectionRequest_WCF( display, request, event->target, rprop );
945 rprop = None; /* Don't support this format */
948 /* close clipboard only if we opened before */
949 if(couldOpen) CloseClipboard();
952 TRACE("\tRequest ignored\n");
955 * SelectionNotify should be sent only at the end of a MULTIPLE request
959 result.type = SelectionNotify;
960 result.display = display;
961 result.requestor = request;
962 result.selection = event->selection;
963 result.property = rprop;
964 result.target = event->target;
965 result.time = event->time;
966 TRACE("Sending SelectionNotify event...\n");
967 TSXSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
971 /***********************************************************************
972 * EVENT_SelectionClear
974 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
976 Atom xaClipboard = TSXInternAtom(event->display, "CLIPBOARD", False);
978 if (event->selection == XA_PRIMARY || event->selection == xaClipboard)
979 X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
982 /***********************************************************************
983 * EVENT_PropertyNotify
984 * We use this to release resources like Pixmaps when a selection
985 * client no longer needs them.
987 static void EVENT_PropertyNotify( XPropertyEvent *event )
989 /* Check if we have any resources to free */
990 TRACE("Received PropertyNotify event: \n");
996 TRACE("\tPropertyDelete for atom %s on window %ld\n",
997 TSXGetAtomName(event->display, event->atom), (long)event->window);
999 if (X11DRV_IsSelectionOwner())
1000 X11DRV_CLIPBOARD_FreeResources( event->atom );
1004 case PropertyNewValue:
1006 TRACE("\tPropertyNewValue for atom %s on window %ld\n\n",
1007 TSXGetAtomName(event->display, event->atom), (long)event->window);
1016 /**********************************************************************
1017 * EVENT_DropFromOffix
1019 * don't know if it still works (last Changlog is from 96/11/04)
1021 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
1023 unsigned long data_length;
1024 unsigned long aux_long;
1025 unsigned char* p_data = NULL;
1036 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO16));
1037 LPDRAGINFO16 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
1038 SEGPTR spDragInfo = K32WOWGlobalLock16(hDragInfo);
1039 Window w_aux_root, w_aux_child;
1042 if( !lpDragInfo || !spDragInfo ) return;
1044 pWnd = WIN_FindWndPtr(hWnd);
1046 TSXQueryPointer( event->display, get_whole_window(pWnd), &w_aux_root, &w_aux_child,
1047 &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
1048 (unsigned int*)&aux_long);
1050 lpDragInfo->hScope = hWnd;
1051 lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y;
1053 /* find out drop point and drop window */
1054 if( x < 0 || y < 0 ||
1055 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1056 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1057 { bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
1060 bAccept = DRAG_QueryUpdate( hWnd, spDragInfo, TRUE );
1061 x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
1063 WIN_ReleaseWndPtr(pWnd);
1065 GlobalFree16( hDragInfo );
1067 if (!bAccept) return;
1069 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1070 dndSelection, 0, 65535, FALSE,
1071 AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1072 &data_length, &aux_long, &p_data);
1074 if( !aux_long && p_data) /* don't bother if > 64K */
1076 signed char *p = (signed char*) p_data;
1080 while( *p ) /* calculate buffer size */
1083 if((u.i = *p) != -1 )
1085 INT len = GetShortPathNameA( p, NULL, 0 );
1086 if (len) aux_long += len + 1;
1091 if( aux_long && aux_long < 65535 )
1096 aux_long += sizeof(DROPFILES) + 1;
1097 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
1098 lpDrop = (DROPFILES*)GlobalLock( hDrop );
1102 WND *pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
1103 lpDrop->pFiles = sizeof(DROPFILES);
1107 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1108 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1109 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1110 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1111 lpDrop->fWide = FALSE;
1112 WIN_ReleaseWndPtr(pDropWnd);
1113 p_drop = (char *)(lpDrop + 1);
1117 if( *p != -1 ) /* use only "good" entries */
1119 GetShortPathNameA( p, p_drop, 65535 );
1120 p_drop += strlen( p_drop ) + 1;
1125 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1129 if( p_data ) TSXFree(p_data);
1132 /**********************************************************************
1135 * drop items are separated by \n
1136 * each item is prefixed by its mime type
1138 * event->data.l[3], event->data.l[4] contains drop x,y position
1140 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
1142 unsigned long data_length;
1143 unsigned long aux_long, drop_len = 0;
1144 unsigned char *p_data = NULL; /* property data */
1145 char *p_drop = NULL;
1156 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
1158 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1159 dndSelection, 0, 65535, FALSE,
1160 AnyPropertyType, &u.atom_aux, &u.i,
1161 &data_length, &aux_long, &p_data);
1163 WARN("property too large, truncated!\n");
1164 TRACE("urls=%s\n", p_data);
1166 if( !aux_long && p_data) { /* don't bother if > 64K */
1167 /* calculate length */
1169 next = strchr(p, '\n');
1172 if (strncmp(p,"file:",5) == 0 ) {
1173 INT len = GetShortPathNameA( p+5, NULL, 0 );
1174 if (len) drop_len += len + 1;
1179 next = strchr(p, '\n');
1185 if( drop_len && drop_len < 65535 ) {
1186 TSXQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
1187 &x, &y, &u.i, &u.i, &u.i);
1189 drop_len += sizeof(DROPFILES) + 1;
1190 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
1191 lpDrop = (DROPFILES *) GlobalLock( hDrop );
1194 WND *pDropWnd = WIN_FindWndPtr( hWnd );
1195 lpDrop->pFiles = sizeof(DROPFILES);
1196 lpDrop->pt.x = (INT)x;
1197 lpDrop->pt.y = (INT)y;
1199 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1200 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1201 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1202 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1203 lpDrop->fWide = FALSE;
1204 p_drop = (char*)(lpDrop + 1);
1205 WIN_ReleaseWndPtr(pDropWnd);
1208 /* create message content */
1211 next = strchr(p, '\n');
1214 if (strncmp(p,"file:",5) == 0 ) {
1215 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
1217 TRACE("drop file %s as %s\n", p+5, p_drop);
1220 WARN("can't convert file %s to dos name \n", p+5);
1223 WARN("unknown mime type %s\n", p);
1228 next = strchr(p, '\n');
1235 GlobalUnlock(hDrop);
1236 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1239 if( p_data ) TSXFree(p_data);
1243 /**********************************************************************
1244 * EVENT_ClientMessage
1246 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
1248 if (event->message_type != None && event->format == 32) {
1249 if ((event->message_type == wmProtocols) &&
1250 (((Atom) event->data.l[0]) == wmDeleteWindow))
1252 /* Ignore the delete window request if the window has been disabled */
1253 if (!(GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED))
1254 PostMessageA( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
1256 else if (event->message_type == dndProtocol)
1258 /* query window (drag&drop event contains only drag window) */
1260 int root_x, root_y, child_x, child_y;
1262 TSXQueryPointer( event->display, root_window, &root, &child,
1263 &root_x, &root_y, &child_x, &child_y, &u);
1264 if (TSXFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) return;
1265 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
1266 EVENT_DropFromOffiX(hWnd, event);
1267 else if (event->data.l[0] == DndURL)
1268 EVENT_DropURLs(hWnd, event);
1272 /* enable this if you want to see the message */
1273 unsigned char* p_data = NULL;
1279 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1280 dndSelection, 0, 65535, FALSE,
1281 AnyPropertyType, &u.atom, &u.i,
1282 &u.l, &u.l, &p_data);
1283 TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1284 event->message_type, event->data.l[0], event->data.l[1],
1285 event->data.l[2], event->data.l[3], event->data.l[4],
1288 TRACE("unrecognized ClientMessage\n" );
1294 /**********************************************************************
1295 * X11DRV_EVENT_SetInputMethod
1297 INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
1299 INPUT_TYPE prev = current_input_type;
1301 /* Flag not used yet */
1302 in_transition = FALSE;
1303 current_input_type = type;
1308 #ifdef HAVE_LIBXXF86DGA2
1309 /**********************************************************************
1310 * X11DRV_EVENT_SetDGAStatus
1312 void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
1314 if (event_base < 0) {
1320 DGAMotionEventType = event_base + MotionNotify;
1321 DGAButtonPressEventType = event_base + ButtonPress;
1322 DGAButtonReleaseEventType = event_base + ButtonRelease;
1323 DGAKeyPressEventType = event_base + KeyPress;
1324 DGAKeyReleaseEventType = event_base + KeyRelease;