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"
50 WINE_DEFAULT_DEBUG_CHANNEL(event);
51 WINE_DECLARE_DEBUG_CHANNEL(win);
53 /* X context to associate a hwnd to an X window */
54 extern XContext winContext;
56 extern Atom wmProtocols;
57 extern Atom wmDeleteWindow;
58 extern Atom dndProtocol;
59 extern Atom dndSelection;
61 #define DndNotDnd -1 /* OffiX drag&drop */
73 #define DndURL 128 /* KDE drag&drop */
75 /* The last X window which had the focus */
76 static Window glastXFocusWin = 0;
78 static const char * const event_names[] =
80 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
81 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
82 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
83 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
84 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
85 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
86 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
87 "ClientMessage", "MappingNotify"
91 static void EVENT_ProcessEvent( XEvent *event );
92 static BOOL X11DRV_CheckFocus(void);
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 ) )
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 X11DRV_EnterNotify( hWnd, (XCrossingEvent*)event );
307 EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
311 EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
315 X11DRV_Expose( hWnd, &event->xexpose );
318 case ConfigureNotify:
320 X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
323 case SelectionRequest:
325 EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
330 EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
334 EVENT_PropertyNotify( (XPropertyEvent *)event );
339 EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
346 X11DRV_MapNotify( hWnd, (XMapEvent *)event );
350 X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
354 X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
358 X11DRV_MappingNotify( (XMappingEvent *) event );
362 WARN("Unprocessed event %s for hwnd %04x\n",
363 event_names[event->type], hWnd );
366 TRACE( "returns.\n" );
370 /**********************************************************************
373 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event )
376 XWindowAttributes win_attr;
381 bIsDisabled = GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED;
383 /* If the window has been disabled, revert the X focus back to the last
384 * focus window. This is to disallow the window manager from switching
385 * focus away while the app is in a modal state.
387 if (bIsDisabled && glastXFocusWin)
389 /* Change focus only if saved focus window is registered and viewable */
391 if (XFindContext( event->display, glastXFocusWin, winContext,
392 (char **)&pWndLastFocus ) == 0 )
394 if (XGetWindowAttributes( event->display, glastXFocusWin, &win_attr ) &&
395 (win_attr.map_state == IsViewable) )
397 XSetInputFocus( event->display, glastXFocusWin, RevertToParent, CurrentTime );
405 if (event->detail != NotifyPointer && hWnd != GetForegroundWindow())
406 SetForegroundWindow( hWnd );
410 /**********************************************************************
413 * Note: only top-level override-redirect windows get FocusOut events.
415 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event )
417 /* Save the last window which had the focus */
418 glastXFocusWin = event->window;
420 if (GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED) glastXFocusWin = 0;
422 if (event->detail != NotifyPointer && hWnd == GetForegroundWindow())
424 /* don't reset the foreground window, if the window which is
425 getting the focus is a Wine window */
426 if (!X11DRV_CheckFocus())
428 SendMessageA( hWnd, WM_CANCELMODE, 0, 0 );
429 /* Abey : 6-Oct-99. Check again if the focus out window is the
430 Foreground window, because in most cases the messages sent
431 above must have already changed the foreground window, in which
432 case we don't have to change the foreground window to 0 */
434 if (hWnd == GetForegroundWindow())
435 SetForegroundWindow( 0 );
440 /**********************************************************************
441 * CheckFocus (X11DRV.@)
443 static BOOL X11DRV_CheckFocus(void)
445 Display *display = thread_display();
450 TSXGetInputFocus(display, &xW, &state);
452 TSXFindContext(display, xW, winContext, (char **)&hWnd) )
458 /***********************************************************************
459 * EVENT_SelectionRequest_TARGETS
460 * Service a TARGETS selection request event
462 static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
463 Atom target, Atom rprop )
465 Atom xaTargets = TSXInternAtom(display, "TARGETS", False);
469 unsigned long cTargets;
473 TRACE("Request for %s\n", TSXGetAtomName(display, target));
476 * Count the number of items we wish to expose as selection targets.
477 * We include the TARGETS item, and a PIXMAP if we have CF_DIB or CF_BITMAP
479 cTargets = CountClipboardFormats() + 1;
480 if ( CLIPBOARD_IsPresent(CF_DIB) || CLIPBOARD_IsPresent(CF_BITMAP) )
483 /* Allocate temp buffer */
484 targets = (Atom*)HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
485 if(targets == NULL) return None;
487 /* Create TARGETS property list (First item in list is TARGETS itself) */
489 for ( targets[0] = xaTargets, cTargets = 1, wFormat = 0, bHavePixmap = FALSE;
490 (wFormat = EnumClipboardFormats( wFormat )); )
492 if ( (prop = X11DRV_CLIPBOARD_MapFormatToProperty(wFormat)) != None )
494 /* Scan through what we have so far to avoid duplicates */
497 for (i = 0, bExists = FALSE; i < cTargets; i++)
499 if (targets[i] == prop)
507 targets[cTargets++] = prop;
509 /* Add PIXMAP prop for bitmaps additionally */
510 if ( (wFormat == CF_DIB || wFormat == CF_BITMAP )
513 targets[cTargets++] = XA_PIXMAP;
523 for ( i = 0; i < cTargets; i++)
527 char *itemFmtName = TSXGetAtomName(display, targets[i]);
528 TRACE("\tAtom# %d: Type %s\n", i, itemFmtName);
529 TSXFree(itemFmtName);
534 /* Update the X property */
535 TRACE("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
537 /* We may want to consider setting the type to xaTargets instead,
538 * in case some apps expect this instead of XA_ATOM */
539 xRc = TSXChangeProperty(display, requestor, rprop,
540 XA_ATOM, 32, PropModeReplace,
541 (unsigned char *)targets, cTargets);
542 TRACE("(Rc=%d)\n", xRc);
544 HeapFree( GetProcessHeap(), 0, targets );
550 /***********************************************************************
551 * EVENT_SelectionRequest_STRING
552 * Service a STRING selection request event
554 static Atom EVENT_SelectionRequest_STRING( Display *display, Window requestor,
555 Atom target, Atom rprop )
557 static UINT text_cp = (UINT)-1;
566 if(text_cp == (UINT)-1)
571 if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\x11drv", &hkey))
574 DWORD type, count = sizeof(buf);
575 if(!RegQueryValueExA(hkey, "TextCP", 0, &type, buf, &count))
582 * Map the requested X selection property type atom name to a
583 * windows clipboard format ID.
585 itemFmtName = TSXGetAtomName(display, target);
586 TRACE("Request for %s (wFormat=%x %s)\n",
587 itemFmtName, CF_UNICODETEXT, CLIPBOARD_GetFormatName(CF_UNICODETEXT));
588 TSXFree(itemFmtName);
590 hUnicodeText = GetClipboardData(CF_UNICODETEXT);
593 uni_text = GlobalLock(hUnicodeText);
597 size = WideCharToMultiByte(text_cp, 0, uni_text, -1, NULL, 0, NULL, NULL);
598 text = HeapAlloc(GetProcessHeap(), 0, size);
601 WideCharToMultiByte(text_cp, 0, uni_text, -1, text, size, NULL, NULL);
603 /* remove carriage returns */
605 lpstr = (char*)HeapAlloc( GetProcessHeap(), 0, size-- );
606 if(lpstr == NULL) return None;
607 for(i=0,j=0; i < size && text[i]; i++ )
609 if( text[i] == '\r' &&
610 (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
611 lpstr[j++] = text[i];
615 /* Update the X property */
616 TRACE("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
617 xRc = TSXChangeProperty(display, requestor, rprop,
618 XA_STRING, 8, PropModeReplace,
620 TRACE("(Rc=%d)\n", xRc);
622 GlobalUnlock(hUnicodeText);
623 HeapFree(GetProcessHeap(), 0, text);
624 HeapFree( GetProcessHeap(), 0, lpstr );
629 /***********************************************************************
630 * EVENT_SelectionRequest_PIXMAP
631 * Service a PIXMAP selection request event
633 static Atom EVENT_SelectionRequest_PIXMAP( Display *display, Window requestor,
634 Atom target, Atom rprop )
636 HANDLE hClipData = 0;
642 XSetWindowAttributes win_attr;
643 XWindowAttributes win_attr_src;
647 * Map the requested X selection property type atom name to a
648 * windows clipboard format ID.
650 itemFmtName = TSXGetAtomName(display, target);
651 wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
652 TRACE("Request for %s (wFormat=%x %s)\n",
653 itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat));
654 TSXFree(itemFmtName);
656 hClipData = GetClipboardData(wFormat);
659 TRACE("Could not retrieve a Pixmap compatible format from clipboard!\n");
660 rprop = None; /* Fail the request */
664 if (wFormat == CF_DIB)
666 HWND hwnd = GetOpenClipboardWindow();
667 HDC hdc = GetDC(hwnd);
669 /* For convert from packed DIB to Pixmap */
670 pixmap = X11DRV_DIB_CreatePixmapFromDIB(hClipData, hdc);
672 ReleaseDC(hwnd, hdc);
674 else if (wFormat == CF_BITMAP)
676 HWND hwnd = GetOpenClipboardWindow();
677 HDC hdc = GetDC(hwnd);
679 pixmap = X11DRV_BITMAP_CreatePixmapFromBitmap(hClipData, hdc);
681 ReleaseDC(hwnd, hdc);
685 FIXME("%s to PIXMAP conversion not yet implemented!\n",
686 CLIPBOARD_GetFormatName(wFormat));
691 TRACE("\tUpdating property %s on Window %ld with %s %ld...\n",
692 TSXGetAtomName(display, rprop), (long)requestor,
693 TSXGetAtomName(display, target), pixmap);
695 /* Store the Pixmap handle in the property */
696 xRc = TSXChangeProperty(display, requestor, rprop, target,
698 (unsigned char *)&pixmap, 1);
699 TRACE("(Rc=%d)\n", xRc);
701 /* Enable the code below if you want to handle destroying Pixmap resources
702 * in response to property notify events. Clients like XPaint don't
703 * appear to be duplicating Pixmaps so they don't like us deleting,
704 * the resource in response to the property being deleted.
707 /* Express interest in property notify events so that we can delete the
708 * pixmap when the client deletes the property atom.
710 xRc = TSXGetWindowAttributes(display, requestor, &win_attr_src);
711 TRACE("Turning on PropertyChangeEvent notifications from window %ld\n",
713 win_attr.event_mask = win_attr_src.your_event_mask | PropertyChangeMask;
714 TSXChangeWindowAttributes(display, requestor, CWEventMask, &win_attr);
716 /* Register the Pixmap we created with the request property Atom.
717 * When this property is destroyed we also destroy the Pixmap in
718 * response to the PropertyNotify event.
720 X11DRV_CLIPBOARD_RegisterPixmapResource( rprop, pixmap );
728 /***********************************************************************
729 * EVENT_SelectionRequest_WCF
730 * Service a Wine Clipboard Format selection request event.
731 * For <WCF>* data types we simply copy the data to X without conversion.
733 static Atom EVENT_SelectionRequest_WCF( Display *display, Window requestor,
734 Atom target, Atom rprop )
736 HANDLE hClipData = 0;
744 * Map the requested X selection property type atom name to a
745 * windows clipboard format ID.
747 itemFmtName = TSXGetAtomName(display, target);
748 wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
749 TRACE("Request for %s (wFormat=%x %s)\n",
750 itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat));
751 TSXFree(itemFmtName);
753 hClipData = GetClipboardData(wFormat);
755 if( hClipData && (lpClipData = GlobalLock(hClipData)) )
757 cBytes = GlobalSize(hClipData);
759 TRACE("\tUpdating property %s, %d bytes...\n",
760 TSXGetAtomName(display, rprop), cBytes);
762 xRc = TSXChangeProperty(display, requestor, rprop,
763 target, 8, PropModeReplace,
764 (unsigned char *)lpClipData, cBytes);
765 TRACE("(Rc=%d)\n", xRc);
767 GlobalUnlock(hClipData);
771 TRACE("\tCould not retrieve native format!\n");
772 rprop = None; /* Fail the request */
779 /***********************************************************************
780 * EVENT_SelectionRequest_MULTIPLE
781 * Service a MULTIPLE selection request event
782 * rprop contains a list of (target,property) atom pairs.
783 * The first atom names a target and the second names a property.
784 * The effect is as if we have received a sequence of SelectionRequest events
785 * (one for each atom pair) except that:
786 * 1. We reply with a SelectionNotify only when all the requested conversions
787 * have been performed.
788 * 2. If we fail to convert the target named by an atom in the MULTIPLE property,
789 * we replace the atom in the property by None.
791 static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
793 Display *display = pevent->display;
795 Atom atype=AnyPropertyType;
797 unsigned long remain;
798 Atom* targetPropList=NULL;
799 unsigned long cTargetPropList = 0;
800 /* Atom xAtomPair = TSXInternAtom(display, "ATOM_PAIR", False); */
802 /* If the specified property is None the requestor is an obsolete client.
803 * We support these by using the specified target atom as the reply property.
805 rprop = pevent->property;
807 rprop = pevent->target;
811 /* Read the MULTIPLE property contents. This should contain a list of
812 * (target,property) atom pairs.
814 if(TSXGetWindowProperty(display, pevent->requestor, rprop,
815 0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
816 &cTargetPropList, &remain,
817 (unsigned char**)&targetPropList) != Success)
818 TRACE("\tCouldn't read MULTIPLE property\n");
821 TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
822 TSXGetAtomName(display, atype), aformat, cTargetPropList, remain);
825 * Make sure we got what we expect.
826 * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
827 * in a MULTIPLE selection request should be of type ATOM_PAIR.
828 * However some X apps(such as XPaint) are not compliant with this and return
829 * a user defined atom in atype when XGetWindowProperty is called.
830 * The data *is* an atom pair but is not denoted as such.
832 if(aformat == 32 /* atype == xAtomPair */ )
836 /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
837 * for each (target,property) pair */
839 for (i = 0; i < cTargetPropList; i+=2)
841 char *targetName = TSXGetAtomName(display, targetPropList[i]);
842 char *propName = TSXGetAtomName(display, targetPropList[i+1]);
843 XSelectionRequestEvent event;
845 TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
846 i/2, targetName, propName);
850 /* We must have a non "None" property to service a MULTIPLE target atom */
851 if ( !targetPropList[i+1] )
853 TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
857 /* Set up an XSelectionRequestEvent for this (target,property) pair */
858 memcpy( &event, pevent, sizeof(XSelectionRequestEvent) );
859 event.target = targetPropList[i];
860 event.property = targetPropList[i+1];
862 /* Fire a SelectionRequest, informing the handler that we are processing
863 * a MULTIPLE selection request event.
865 EVENT_SelectionRequest( hWnd, &event, TRUE );
869 /* Free the list of targets/properties */
870 TSXFree(targetPropList);
878 /***********************************************************************
879 * EVENT_SelectionRequest
880 * Process an event selection request event.
881 * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
882 * recursively while servicing a "MULTIPLE" selection target.
884 * Note: We only receive this event when WINE owns the X selection
886 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
888 Display *display = event->display;
889 XSelectionEvent result;
891 Window request = event->requestor;
892 BOOL couldOpen = FALSE;
893 Atom xaClipboard = TSXInternAtom(display, "CLIPBOARD", False);
894 Atom xaTargets = TSXInternAtom(display, "TARGETS", False);
895 Atom xaMultiple = TSXInternAtom(display, "MULTIPLE", False);
898 * We can only handle the selection request if :
899 * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
900 * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
901 * since this has been already done.
905 if ( ( (event->selection != XA_PRIMARY) && (event->selection != xaClipboard) )
906 || !(couldOpen = OpenClipboard(hWnd)) )
910 /* If the specified property is None the requestor is an obsolete client.
911 * We support these by using the specified target atom as the reply property.
913 rprop = event->property;
915 rprop = event->target;
917 if(event->target == xaTargets) /* Return a list of all supported targets */
919 /* TARGETS selection request */
920 rprop = EVENT_SelectionRequest_TARGETS( display, request, event->target, rprop );
922 else if(event->target == xaMultiple) /* rprop contains a list of (target, property) atom pairs */
924 /* MULTIPLE selection request */
925 rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
927 else if(event->target == XA_STRING) /* treat CF_TEXT as Unix text */
929 /* XA_STRING selection request */
930 rprop = EVENT_SelectionRequest_STRING( display, request, event->target, rprop );
932 else if(event->target == XA_PIXMAP) /* Convert DIB's to Pixmaps */
934 /* XA_PIXMAP selection request */
935 rprop = EVENT_SelectionRequest_PIXMAP( display, request, event->target, rprop );
937 else if(event->target == XA_BITMAP) /* Convert DIB's to 1-bit Pixmaps */
939 /* XA_BITMAP selection request - TODO: create a monochrome Pixmap */
940 rprop = EVENT_SelectionRequest_PIXMAP( display, request, XA_PIXMAP, rprop );
942 else if(X11DRV_CLIPBOARD_IsNativeProperty(event->target)) /* <WCF>* */
944 /* All <WCF> selection requests */
945 rprop = EVENT_SelectionRequest_WCF( display, request, event->target, rprop );
948 rprop = None; /* Don't support this format */
951 /* close clipboard only if we opened before */
952 if(couldOpen) CloseClipboard();
955 TRACE("\tRequest ignored\n");
958 * SelectionNotify should be sent only at the end of a MULTIPLE request
962 result.type = SelectionNotify;
963 result.display = display;
964 result.requestor = request;
965 result.selection = event->selection;
966 result.property = rprop;
967 result.target = event->target;
968 result.time = event->time;
969 TRACE("Sending SelectionNotify event...\n");
970 TSXSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
974 /***********************************************************************
975 * EVENT_SelectionClear
977 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
979 Atom xaClipboard = TSXInternAtom(event->display, "CLIPBOARD", False);
981 if (event->selection == XA_PRIMARY || event->selection == xaClipboard)
982 X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
985 /***********************************************************************
986 * EVENT_PropertyNotify
987 * We use this to release resources like Pixmaps when a selection
988 * client no longer needs them.
990 static void EVENT_PropertyNotify( XPropertyEvent *event )
992 /* Check if we have any resources to free */
993 TRACE("Received PropertyNotify event: \n");
999 TRACE("\tPropertyDelete for atom %s on window %ld\n",
1000 TSXGetAtomName(event->display, event->atom), (long)event->window);
1002 if (X11DRV_IsSelectionOwner())
1003 X11DRV_CLIPBOARD_FreeResources( event->atom );
1007 case PropertyNewValue:
1009 TRACE("\tPropertyNewValue for atom %s on window %ld\n\n",
1010 TSXGetAtomName(event->display, event->atom), (long)event->window);
1019 /**********************************************************************
1020 * EVENT_DropFromOffix
1022 * don't know if it still works (last Changlog is from 96/11/04)
1024 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
1026 unsigned long data_length;
1027 unsigned long aux_long;
1028 unsigned char* p_data = NULL;
1039 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO16));
1040 LPDRAGINFO16 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
1041 SEGPTR spDragInfo = K32WOWGlobalLock16(hDragInfo);
1042 Window w_aux_root, w_aux_child;
1045 if( !lpDragInfo || !spDragInfo ) return;
1047 pWnd = WIN_FindWndPtr(hWnd);
1049 TSXQueryPointer( event->display, get_whole_window(pWnd), &w_aux_root, &w_aux_child,
1050 &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
1051 (unsigned int*)&aux_long);
1053 lpDragInfo->hScope = hWnd;
1054 lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y;
1056 /* find out drop point and drop window */
1057 if( x < 0 || y < 0 ||
1058 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1059 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1060 { bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
1063 bAccept = DRAG_QueryUpdate( hWnd, spDragInfo, TRUE );
1064 x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
1066 WIN_ReleaseWndPtr(pWnd);
1068 GlobalFree16( hDragInfo );
1070 if (!bAccept) return;
1072 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1073 dndSelection, 0, 65535, FALSE,
1074 AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1075 &data_length, &aux_long, &p_data);
1077 if( !aux_long && p_data) /* don't bother if > 64K */
1079 signed char *p = (signed char*) p_data;
1083 while( *p ) /* calculate buffer size */
1086 if((u.i = *p) != -1 )
1088 INT len = GetShortPathNameA( p, NULL, 0 );
1089 if (len) aux_long += len + 1;
1094 if( aux_long && aux_long < 65535 )
1099 aux_long += sizeof(DROPFILES) + 1;
1100 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
1101 lpDrop = (DROPFILES*)GlobalLock( hDrop );
1105 WND *pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
1106 lpDrop->pFiles = sizeof(DROPFILES);
1110 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1111 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1112 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1113 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1114 lpDrop->fWide = FALSE;
1115 WIN_ReleaseWndPtr(pDropWnd);
1116 p_drop = (char *)(lpDrop + 1);
1120 if( *p != -1 ) /* use only "good" entries */
1122 GetShortPathNameA( p, p_drop, 65535 );
1123 p_drop += strlen( p_drop ) + 1;
1128 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1132 if( p_data ) TSXFree(p_data);
1135 /**********************************************************************
1138 * drop items are separated by \n
1139 * each item is prefixed by its mime type
1141 * event->data.l[3], event->data.l[4] contains drop x,y position
1143 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
1145 unsigned long data_length;
1146 unsigned long aux_long, drop_len = 0;
1147 unsigned char *p_data = NULL; /* property data */
1148 char *p_drop = NULL;
1159 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
1161 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1162 dndSelection, 0, 65535, FALSE,
1163 AnyPropertyType, &u.atom_aux, &u.i,
1164 &data_length, &aux_long, &p_data);
1166 WARN("property too large, truncated!\n");
1167 TRACE("urls=%s\n", p_data);
1169 if( !aux_long && p_data) { /* don't bother if > 64K */
1170 /* calculate length */
1172 next = strchr(p, '\n');
1175 if (strncmp(p,"file:",5) == 0 ) {
1176 INT len = GetShortPathNameA( p+5, NULL, 0 );
1177 if (len) drop_len += len + 1;
1182 next = strchr(p, '\n');
1188 if( drop_len && drop_len < 65535 ) {
1189 TSXQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
1190 &x, &y, &u.i, &u.i, &u.i);
1192 drop_len += sizeof(DROPFILES) + 1;
1193 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
1194 lpDrop = (DROPFILES *) GlobalLock( hDrop );
1197 WND *pDropWnd = WIN_FindWndPtr( hWnd );
1198 lpDrop->pFiles = sizeof(DROPFILES);
1199 lpDrop->pt.x = (INT)x;
1200 lpDrop->pt.y = (INT)y;
1202 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1203 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1204 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1205 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1206 lpDrop->fWide = FALSE;
1207 p_drop = (char*)(lpDrop + 1);
1208 WIN_ReleaseWndPtr(pDropWnd);
1211 /* create message content */
1214 next = strchr(p, '\n');
1217 if (strncmp(p,"file:",5) == 0 ) {
1218 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
1220 TRACE("drop file %s as %s\n", p+5, p_drop);
1223 WARN("can't convert file %s to dos name \n", p+5);
1226 WARN("unknown mime type %s\n", p);
1231 next = strchr(p, '\n');
1238 GlobalUnlock(hDrop);
1239 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1242 if( p_data ) TSXFree(p_data);
1246 /**********************************************************************
1247 * EVENT_ClientMessage
1249 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
1251 if (event->message_type != None && event->format == 32) {
1252 if ((event->message_type == wmProtocols) &&
1253 (((Atom) event->data.l[0]) == wmDeleteWindow))
1255 /* Ignore the delete window request if the window has been disabled */
1256 if (!(GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED))
1257 PostMessageA( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
1259 else if (event->message_type == dndProtocol)
1261 /* query window (drag&drop event contains only drag window) */
1263 int root_x, root_y, child_x, child_y;
1265 TSXQueryPointer( event->display, root_window, &root, &child,
1266 &root_x, &root_y, &child_x, &child_y, &u);
1267 if (TSXFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) return;
1268 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
1269 EVENT_DropFromOffiX(hWnd, event);
1270 else if (event->data.l[0] == DndURL)
1271 EVENT_DropURLs(hWnd, event);
1275 /* enable this if you want to see the message */
1276 unsigned char* p_data = NULL;
1282 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1283 dndSelection, 0, 65535, FALSE,
1284 AnyPropertyType, &u.atom, &u.i,
1285 &u.l, &u.l, &p_data);
1286 TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1287 event->message_type, event->data.l[0], event->data.l[1],
1288 event->data.l[2], event->data.l[3], event->data.l[4],
1291 TRACE("unrecognized ClientMessage\n" );
1297 /**********************************************************************
1298 * X11DRV_EVENT_SetInputMethod
1300 INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
1302 INPUT_TYPE prev = current_input_type;
1304 /* Flag not used yet */
1305 in_transition = FALSE;
1306 current_input_type = type;
1311 #ifdef HAVE_LIBXXF86DGA2
1312 /**********************************************************************
1313 * X11DRV_EVENT_SetDGAStatus
1315 void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
1317 if (event_base < 0) {
1323 DGAMotionEventType = event_base + MotionNotify;
1324 DGAButtonPressEventType = event_base + ButtonPress;
1325 DGAButtonReleaseEventType = event_base + ButtonRelease;
1326 DGAKeyPressEventType = event_base + KeyPress;
1327 DGAKeyReleaseEventType = event_base + KeyRelease;