4 * Copyright 1993 Alexandre Julliard
10 #include <X11/Xatom.h>
11 #include <X11/keysym.h>
14 #include "ts_xresource.h"
16 #ifdef HAVE_LIBXXF86DGA2
17 #include "ts_xf86dga2.h"
22 #include "wine/winuser16.h"
23 #include "shlobj.h" /* DROPFILES */
25 #include "clipboard.h"
27 #include "debugtools.h"
37 DEFAULT_DEBUG_CHANNEL(event
);
38 DECLARE_DEBUG_CHANNEL(win
);
40 /* X context to associate a hwnd to an X window */
41 extern XContext winContext
;
43 extern Atom wmProtocols
;
44 extern Atom wmDeleteWindow
;
45 extern Atom dndProtocol
;
46 extern Atom dndSelection
;
48 #define DndNotDnd -1 /* OffiX drag&drop */
60 #define DndURL 128 /* KDE drag&drop */
62 /* The last X window which had the focus */
63 static Window glastXFocusWin
= 0;
65 static const char * const event_names
[] =
67 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
68 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
69 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
70 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
71 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
72 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
73 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
74 "ClientMessage", "MappingNotify"
78 static void EVENT_ProcessEvent( XEvent
*event
);
79 static BOOL
X11DRV_CheckFocus(void);
82 static void EVENT_FocusIn( HWND hWnd
, XFocusChangeEvent
*event
);
83 static void EVENT_FocusOut( HWND hWnd
, XFocusChangeEvent
*event
);
84 static void EVENT_SelectionRequest( HWND hWnd
, XSelectionRequestEvent
*event
, BOOL bIsMultiple
);
85 static void EVENT_SelectionClear( HWND hWnd
, XSelectionClearEvent
*event
);
86 static void EVENT_PropertyNotify( XPropertyEvent
*event
);
87 static void EVENT_ClientMessage( HWND hWnd
, XClientMessageEvent
*event
);
89 extern void X11DRV_ButtonPress( HWND hwnd
, XButtonEvent
*event
);
90 extern void X11DRV_ButtonRelease( HWND hwnd
, XButtonEvent
*event
);
91 extern void X11DRV_MotionNotify( HWND hwnd
, XMotionEvent
*event
);
92 extern void X11DRV_KeyEvent( HWND hwnd
, XKeyEvent
*event
);
93 extern void X11DRV_KeymapNotify( HWND hwnd
, XKeymapEvent
*event
);
94 extern void X11DRV_Expose( HWND hwnd
, XExposeEvent
*event
);
95 extern void X11DRV_MapNotify( HWND hwnd
, XMapEvent
*event
);
96 extern void X11DRV_UnmapNotify( HWND hwnd
, XUnmapEvent
*event
);
97 extern void X11DRV_ConfigureNotify( HWND hwnd
, XConfigureEvent
*event
);
98 extern void X11DRV_MappingNotify( XMappingEvent
*event
);
100 #ifdef HAVE_LIBXXF86DGA2
101 static int DGAMotionEventType
;
102 static int DGAButtonPressEventType
;
103 static int DGAButtonReleaseEventType
;
104 static int DGAKeyPressEventType
;
105 static int DGAKeyReleaseEventType
;
107 static BOOL DGAUsed
= FALSE
;
108 static HWND DGAhwnd
= 0;
110 extern void X11DRV_DGAMotionEvent( HWND hwnd
, XDGAMotionEvent
*event
);
111 extern void X11DRV_DGAButtonPressEvent( HWND hwnd
, XDGAButtonEvent
*event
);
112 extern void X11DRV_DGAButtonReleaseEvent( HWND hwnd
, XDGAButtonEvent
*event
);
115 /* Static used for the current input method */
116 static INPUT_TYPE current_input_type
= X11DRV_INPUT_ABSOLUTE
;
117 static BOOL in_transition
= FALSE
; /* This is not used as for today */
120 /***********************************************************************
123 static int process_events( struct x11drv_thread_data
*data
)
129 while ( XPending( data
->display
) )
131 XNextEvent( data
->display
, &event
);
133 EVENT_ProcessEvent( &event
);
142 /***********************************************************************
143 * MsgWaitForMultipleObjectsEx (X11DRV.@)
145 DWORD
X11DRV_MsgWaitForMultipleObjectsEx( DWORD count
, const HANDLE
*handles
,
146 DWORD timeout
, DWORD mask
, DWORD flags
)
148 HANDLE new_handles
[MAXIMUM_WAIT_OBJECTS
+1]; /* FIXME! */
150 struct x11drv_thread_data
*data
= NtCurrentTeb()->driver_data
;
152 if (!data
|| data
->process_event_count
)
153 return WaitForMultipleObjectsEx( count
, handles
, flags
& MWMO_WAITALL
,
154 timeout
, flags
& MWMO_ALERTABLE
);
156 for (i
= 0; i
< count
; i
++) new_handles
[i
] = handles
[i
];
157 new_handles
[count
] = data
->display_fd
;
160 XFlush( gdi_display
);
161 XFlush( data
->display
);
164 data
->process_event_count
++;
165 if (process_events( data
)) ret
= count
;
168 ret
= WaitForMultipleObjectsEx( count
+1, new_handles
, flags
& MWMO_WAITALL
,
169 timeout
, flags
& MWMO_ALERTABLE
);
170 if (ret
== count
) process_events( data
);
172 data
->process_event_count
--;
177 /***********************************************************************
180 * Process an X event.
182 static void EVENT_ProcessEvent( XEvent
*event
)
185 Display
*display
= event
->xany
.display
;
187 TRACE( "called.\n" );
191 case SelectionNotify
: /* all of these should be caught by XCheckTypedWindowEvent() */
192 FIXME("Got SelectionNotify - must not happen!\n");
195 /* We get all these because of StructureNotifyMask.
196 This check is placed here to avoid getting error messages below,
197 as X might send some of these even for windows that have already
199 case CirculateNotify
:
207 #ifdef HAVE_LIBXXF86DGA2
209 if (event
->type
== DGAMotionEventType
) {
210 TRACE("DGAMotionEvent received.\n");
211 X11DRV_DGAMotionEvent( DGAhwnd
, (XDGAMotionEvent
*)event
);
214 if (event
->type
== DGAButtonPressEventType
) {
215 TRACE("DGAButtonPressEvent received.\n");
216 X11DRV_DGAButtonPressEvent( DGAhwnd
, (XDGAButtonEvent
*)event
);
219 if (event
->type
== DGAButtonReleaseEventType
) {
220 TRACE("DGAButtonReleaseEvent received.\n");
221 X11DRV_DGAButtonReleaseEvent( DGAhwnd
, (XDGAButtonEvent
*)event
);
224 if ((event
->type
== DGAKeyPressEventType
) ||
225 (event
->type
== DGAKeyReleaseEventType
)) {
226 /* Fill a XKeyEvent to send to EVENT_Key */
228 XDGAKeyEvent
*evt
= (XDGAKeyEvent
*) event
;
230 TRACE("DGAKeyPress/ReleaseEvent received.\n");
232 if (evt
->type
== DGAKeyReleaseEventType
)
233 ke
.type
= KeyRelease
;
236 ke
.serial
= evt
->serial
;
237 ke
.send_event
= FALSE
;
238 ke
.display
= evt
->display
;
247 ke
.state
= evt
->state
;
248 ke
.keycode
= evt
->keycode
;
249 ke
.same_screen
= TRUE
;
250 X11DRV_KeyEvent( 0, &ke
);
256 if (TSXFindContext( display
, event
->xany
.window
, winContext
, (char **)&hWnd
) != 0)
257 hWnd
= 0; /* Not for a registered window */
259 if ( !hWnd
&& event
->xany
.window
!= root_window
260 && event
->type
!= PropertyNotify
261 && event
->type
!= MappingNotify
)
262 WARN( "Got event %s for unknown Window %08lx\n",
263 event_names
[event
->type
], event
->xany
.window
);
265 TRACE("Got event %s for hwnd %04x\n",
266 event_names
[event
->type
], hWnd
);
272 /* FIXME: should generate a motion event if event point is different from current pos */
273 X11DRV_KeyEvent( hWnd
, (XKeyEvent
*)event
);
277 X11DRV_ButtonPress( hWnd
, (XButtonEvent
*)event
);
281 X11DRV_ButtonRelease( hWnd
, (XButtonEvent
*)event
);
285 X11DRV_MotionNotify( hWnd
, (XMotionEvent
*)event
);
289 EVENT_FocusIn( hWnd
, (XFocusChangeEvent
*)event
);
293 EVENT_FocusOut( hWnd
, (XFocusChangeEvent
*)event
);
297 X11DRV_Expose( hWnd
, &event
->xexpose
);
300 case ConfigureNotify
:
302 X11DRV_ConfigureNotify( hWnd
, &event
->xconfigure
);
305 case SelectionRequest
:
307 EVENT_SelectionRequest( hWnd
, (XSelectionRequestEvent
*)event
, FALSE
);
312 EVENT_SelectionClear( hWnd
, (XSelectionClearEvent
*) event
);
316 EVENT_PropertyNotify( (XPropertyEvent
*)event
);
321 EVENT_ClientMessage( hWnd
, (XClientMessageEvent
*) event
);
328 X11DRV_MapNotify( hWnd
, (XMapEvent
*)event
);
332 X11DRV_UnmapNotify( hWnd
, (XUnmapEvent
*)event
);
336 X11DRV_KeymapNotify( hWnd
, (XKeymapEvent
*)event
);
340 X11DRV_MappingNotify( (XMappingEvent
*) event
);
344 WARN("Unprocessed event %s for hwnd %04x\n",
345 event_names
[event
->type
], hWnd
);
348 TRACE( "returns.\n" );
352 /**********************************************************************
355 static void EVENT_FocusIn( HWND hWnd
, XFocusChangeEvent
*event
)
358 XWindowAttributes win_attr
;
363 bIsDisabled
= GetWindowLongA( hWnd
, GWL_STYLE
) & WS_DISABLED
;
365 /* If the window has been disabled and we are in managed mode,
366 * revert the X focus back to the last focus window. This is to disallow
367 * the window manager from switching focus away while the app is
370 if ( Options
.managed
&& bIsDisabled
&& glastXFocusWin
)
372 /* Change focus only if saved focus window is registered and viewable */
374 if (XFindContext( event
->display
, glastXFocusWin
, winContext
,
375 (char **)&pWndLastFocus
) == 0 )
377 if (XGetWindowAttributes( event
->display
, glastXFocusWin
, &win_attr
) &&
378 (win_attr
.map_state
== IsViewable
) )
380 XSetInputFocus( event
->display
, glastXFocusWin
, RevertToParent
, CurrentTime
);
388 if (event
->detail
!= NotifyPointer
&& event
->detail
!= NotifyNonlinear
&& hWnd
!= GetForegroundWindow())
389 SetForegroundWindow( hWnd
);
393 /**********************************************************************
396 * Note: only top-level override-redirect windows get FocusOut events.
398 static void EVENT_FocusOut( HWND hWnd
, XFocusChangeEvent
*event
)
400 /* Save the last window which had the focus */
401 glastXFocusWin
= event
->window
;
403 if (GetWindowLongA( hWnd
, GWL_STYLE
) & WS_DISABLED
) glastXFocusWin
= 0;
405 if (event
->detail
!= NotifyPointer
&& hWnd
== GetForegroundWindow())
407 /* don't reset the foreground window, if the window which is
408 getting the focus is a Wine window */
409 if (!X11DRV_CheckFocus())
411 SendMessageA( hWnd
, WM_CANCELMODE
, 0, 0 );
412 /* Abey : 6-Oct-99. Check again if the focus out window is the
413 Foreground window, because in most cases the messages sent
414 above must have already changed the foreground window, in which
415 case we don't have to change the foreground window to 0 */
417 if (hWnd
== GetForegroundWindow())
418 SetForegroundWindow( 0 );
423 /**********************************************************************
424 * CheckFocus (X11DRV.@)
426 static BOOL
X11DRV_CheckFocus(void)
428 Display
*display
= thread_display();
433 TSXGetInputFocus(display
, &xW
, &state
);
435 TSXFindContext(display
, xW
, winContext
, (char **)&hWnd
) )
441 /***********************************************************************
442 * EVENT_SelectionRequest_TARGETS
443 * Service a TARGETS selection request event
445 static Atom
EVENT_SelectionRequest_TARGETS( Display
*display
, Window requestor
,
446 Atom target
, Atom rprop
)
448 Atom xaTargets
= TSXInternAtom(display
, "TARGETS", False
);
452 unsigned long cTargets
;
456 TRACE("Request for %s\n", TSXGetAtomName(display
, target
));
459 * Count the number of items we wish to expose as selection targets.
460 * We include the TARGETS item, and a PIXMAP if we have CF_DIB or CF_BITMAP
462 cTargets
= CountClipboardFormats() + 1;
463 if ( CLIPBOARD_IsPresent(CF_DIB
) || CLIPBOARD_IsPresent(CF_BITMAP
) )
466 /* Allocate temp buffer */
467 targets
= (Atom
*)HeapAlloc( GetProcessHeap(), 0, cTargets
* sizeof(Atom
));
468 if(targets
== NULL
) return None
;
470 /* Create TARGETS property list (First item in list is TARGETS itself) */
472 for ( targets
[0] = xaTargets
, cTargets
= 1, wFormat
= 0, bHavePixmap
= FALSE
;
473 (wFormat
= EnumClipboardFormats( wFormat
)); )
475 if ( (prop
= X11DRV_CLIPBOARD_MapFormatToProperty(wFormat
)) != None
)
477 /* Scan through what we have so far to avoid duplicates */
480 for (i
= 0, bExists
= FALSE
; i
< cTargets
; i
++)
482 if (targets
[i
] == prop
)
490 targets
[cTargets
++] = prop
;
492 /* Add PIXMAP prop for bitmaps additionally */
493 if ( (wFormat
== CF_DIB
|| wFormat
== CF_BITMAP
)
496 targets
[cTargets
++] = XA_PIXMAP
;
506 for ( i
= 0; i
< cTargets
; i
++)
510 char *itemFmtName
= TSXGetAtomName(display
, targets
[i
]);
511 TRACE("\tAtom# %d: Type %s\n", i
, itemFmtName
);
512 TSXFree(itemFmtName
);
517 /* Update the X property */
518 TRACE("\tUpdating property %s...\n", TSXGetAtomName(display
, rprop
));
520 /* We may want to consider setting the type to xaTargets instead,
521 * in case some apps expect this instead of XA_ATOM */
522 xRc
= TSXChangeProperty(display
, requestor
, rprop
,
523 XA_ATOM
, 32, PropModeReplace
,
524 (unsigned char *)targets
, cTargets
);
525 TRACE("(Rc=%d)\n", xRc
);
527 HeapFree( GetProcessHeap(), 0, targets
);
533 /***********************************************************************
534 * EVENT_SelectionRequest_STRING
535 * Service a STRING selection request event
537 static Atom
EVENT_SelectionRequest_STRING( Display
*display
, Window requestor
,
538 Atom target
, Atom rprop
)
540 static UINT text_cp
= (UINT
)-1;
549 if(text_cp
== (UINT
)-1)
554 if(!RegOpenKeyA(HKEY_LOCAL_MACHINE
, "Software\\Wine\\Wine\\Config\\x11drv", &hkey
))
557 DWORD type
, count
= sizeof(buf
);
558 if(!RegQueryValueExA(hkey
, "TextCP", 0, &type
, buf
, &count
))
565 * Map the requested X selection property type atom name to a
566 * windows clipboard format ID.
568 itemFmtName
= TSXGetAtomName(display
, target
);
569 TRACE("Request for %s (wFormat=%x %s)\n",
570 itemFmtName
, CF_UNICODETEXT
, CLIPBOARD_GetFormatName(CF_UNICODETEXT
));
571 TSXFree(itemFmtName
);
573 hUnicodeText
= GetClipboardData(CF_UNICODETEXT
);
576 uni_text
= GlobalLock(hUnicodeText
);
580 size
= WideCharToMultiByte(text_cp
, 0, uni_text
, -1, NULL
, 0, NULL
, NULL
);
581 text
= HeapAlloc(GetProcessHeap(), 0, size
);
584 WideCharToMultiByte(text_cp
, 0, uni_text
, -1, text
, size
, NULL
, NULL
);
586 /* remove carriage returns */
588 lpstr
= (char*)HeapAlloc( GetProcessHeap(), 0, size
-- );
589 if(lpstr
== NULL
) return None
;
590 for(i
=0,j
=0; i
< size
&& text
[i
]; i
++ )
592 if( text
[i
] == '\r' &&
593 (text
[i
+1] == '\n' || text
[i
+1] == '\0') ) continue;
594 lpstr
[j
++] = text
[i
];
598 /* Update the X property */
599 TRACE("\tUpdating property %s...\n", TSXGetAtomName(display
, rprop
));
600 xRc
= TSXChangeProperty(display
, requestor
, rprop
,
601 XA_STRING
, 8, PropModeReplace
,
603 TRACE("(Rc=%d)\n", xRc
);
605 GlobalUnlock(hUnicodeText
);
606 HeapFree(GetProcessHeap(), 0, text
);
607 HeapFree( GetProcessHeap(), 0, lpstr
);
612 /***********************************************************************
613 * EVENT_SelectionRequest_PIXMAP
614 * Service a PIXMAP selection request event
616 static Atom
EVENT_SelectionRequest_PIXMAP( Display
*display
, Window requestor
,
617 Atom target
, Atom rprop
)
619 HANDLE hClipData
= 0;
625 XSetWindowAttributes win_attr
;
626 XWindowAttributes win_attr_src
;
630 * Map the requested X selection property type atom name to a
631 * windows clipboard format ID.
633 itemFmtName
= TSXGetAtomName(display
, target
);
634 wFormat
= X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName
);
635 TRACE("Request for %s (wFormat=%x %s)\n",
636 itemFmtName
, wFormat
, CLIPBOARD_GetFormatName( wFormat
));
637 TSXFree(itemFmtName
);
639 hClipData
= GetClipboardData(wFormat
);
642 TRACE("Could not retrieve a Pixmap compatible format from clipboard!\n");
643 rprop
= None
; /* Fail the request */
647 if (wFormat
== CF_DIB
)
649 HWND hwnd
= GetOpenClipboardWindow();
650 HDC hdc
= GetDC(hwnd
);
652 /* For convert from packed DIB to Pixmap */
653 pixmap
= X11DRV_DIB_CreatePixmapFromDIB(hClipData
, hdc
);
655 ReleaseDC(hwnd
, hdc
);
657 else if (wFormat
== CF_BITMAP
)
659 HWND hwnd
= GetOpenClipboardWindow();
660 HDC hdc
= GetDC(hwnd
);
662 pixmap
= X11DRV_BITMAP_CreatePixmapFromBitmap(hClipData
, hdc
);
664 ReleaseDC(hwnd
, hdc
);
668 FIXME("%s to PIXMAP conversion not yet implemented!\n",
669 CLIPBOARD_GetFormatName(wFormat
));
674 TRACE("\tUpdating property %s on Window %ld with %s %ld...\n",
675 TSXGetAtomName(display
, rprop
), (long)requestor
,
676 TSXGetAtomName(display
, target
), pixmap
);
678 /* Store the Pixmap handle in the property */
679 xRc
= TSXChangeProperty(display
, requestor
, rprop
, target
,
681 (unsigned char *)&pixmap
, 1);
682 TRACE("(Rc=%d)\n", xRc
);
684 /* Enable the code below if you want to handle destroying Pixmap resources
685 * in response to property notify events. Clients like XPaint don't
686 * appear to be duplicating Pixmaps so they don't like us deleting,
687 * the resource in response to the property being deleted.
690 /* Express interest in property notify events so that we can delete the
691 * pixmap when the client deletes the property atom.
693 xRc
= TSXGetWindowAttributes(display
, requestor
, &win_attr_src
);
694 TRACE("Turning on PropertyChangeEvent notifications from window %ld\n",
696 win_attr
.event_mask
= win_attr_src
.your_event_mask
| PropertyChangeMask
;
697 TSXChangeWindowAttributes(display
, requestor
, CWEventMask
, &win_attr
);
699 /* Register the Pixmap we created with the request property Atom.
700 * When this property is destroyed we also destroy the Pixmap in
701 * response to the PropertyNotify event.
703 X11DRV_CLIPBOARD_RegisterPixmapResource( rprop
, pixmap
);
711 /***********************************************************************
712 * EVENT_SelectionRequest_WCF
713 * Service a Wine Clipboard Format selection request event.
714 * For <WCF>* data types we simply copy the data to X without conversion.
716 static Atom
EVENT_SelectionRequest_WCF( Display
*display
, Window requestor
,
717 Atom target
, Atom rprop
)
719 HANDLE hClipData
= 0;
727 * Map the requested X selection property type atom name to a
728 * windows clipboard format ID.
730 itemFmtName
= TSXGetAtomName(display
, target
);
731 wFormat
= X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName
);
732 TRACE("Request for %s (wFormat=%x %s)\n",
733 itemFmtName
, wFormat
, CLIPBOARD_GetFormatName( wFormat
));
734 TSXFree(itemFmtName
);
736 hClipData
= GetClipboardData(wFormat
);
738 if( hClipData
&& (lpClipData
= GlobalLock(hClipData
)) )
740 cBytes
= GlobalSize(hClipData
);
742 TRACE("\tUpdating property %s, %d bytes...\n",
743 TSXGetAtomName(display
, rprop
), cBytes
);
745 xRc
= TSXChangeProperty(display
, requestor
, rprop
,
746 target
, 8, PropModeReplace
,
747 (unsigned char *)lpClipData
, cBytes
);
748 TRACE("(Rc=%d)\n", xRc
);
750 GlobalUnlock(hClipData
);
754 TRACE("\tCould not retrieve native format!\n");
755 rprop
= None
; /* Fail the request */
762 /***********************************************************************
763 * EVENT_SelectionRequest_MULTIPLE
764 * Service a MULTIPLE selection request event
765 * rprop contains a list of (target,property) atom pairs.
766 * The first atom names a target and the second names a property.
767 * The effect is as if we have received a sequence of SelectionRequest events
768 * (one for each atom pair) except that:
769 * 1. We reply with a SelectionNotify only when all the requested conversions
770 * have been performed.
771 * 2. If we fail to convert the target named by an atom in the MULTIPLE property,
772 * we replace the atom in the property by None.
774 static Atom
EVENT_SelectionRequest_MULTIPLE( HWND hWnd
, XSelectionRequestEvent
*pevent
)
776 Display
*display
= pevent
->display
;
778 Atom atype
=AnyPropertyType
;
780 unsigned long remain
;
781 Atom
* targetPropList
=NULL
;
782 unsigned long cTargetPropList
= 0;
783 /* Atom xAtomPair = TSXInternAtom(display, "ATOM_PAIR", False); */
785 /* If the specified property is None the requestor is an obsolete client.
786 * We support these by using the specified target atom as the reply property.
788 rprop
= pevent
->property
;
790 rprop
= pevent
->target
;
794 /* Read the MULTIPLE property contents. This should contain a list of
795 * (target,property) atom pairs.
797 if(TSXGetWindowProperty(display
, pevent
->requestor
, rprop
,
798 0, 0x3FFF, False
, AnyPropertyType
, &atype
,&aformat
,
799 &cTargetPropList
, &remain
,
800 (unsigned char**)&targetPropList
) != Success
)
801 TRACE("\tCouldn't read MULTIPLE property\n");
804 TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
805 TSXGetAtomName(display
, atype
), aformat
, cTargetPropList
, remain
);
808 * Make sure we got what we expect.
809 * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
810 * in a MULTIPLE selection request should be of type ATOM_PAIR.
811 * However some X apps(such as XPaint) are not compliant with this and return
812 * a user defined atom in atype when XGetWindowProperty is called.
813 * The data *is* an atom pair but is not denoted as such.
815 if(aformat
== 32 /* atype == xAtomPair */ )
819 /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
820 * for each (target,property) pair */
822 for (i
= 0; i
< cTargetPropList
; i
+=2)
824 char *targetName
= TSXGetAtomName(display
, targetPropList
[i
]);
825 char *propName
= TSXGetAtomName(display
, targetPropList
[i
+1]);
826 XSelectionRequestEvent event
;
828 TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
829 i
/2, targetName
, propName
);
833 /* We must have a non "None" property to service a MULTIPLE target atom */
834 if ( !targetPropList
[i
+1] )
836 TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i
);
840 /* Set up an XSelectionRequestEvent for this (target,property) pair */
841 memcpy( &event
, pevent
, sizeof(XSelectionRequestEvent
) );
842 event
.target
= targetPropList
[i
];
843 event
.property
= targetPropList
[i
+1];
845 /* Fire a SelectionRequest, informing the handler that we are processing
846 * a MULTIPLE selection request event.
848 EVENT_SelectionRequest( hWnd
, &event
, TRUE
);
852 /* Free the list of targets/properties */
853 TSXFree(targetPropList
);
861 /***********************************************************************
862 * EVENT_SelectionRequest
863 * Process an event selection request event.
864 * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
865 * recursively while servicing a "MULTIPLE" selection target.
867 * Note: We only receive this event when WINE owns the X selection
869 static void EVENT_SelectionRequest( HWND hWnd
, XSelectionRequestEvent
*event
, BOOL bIsMultiple
)
871 Display
*display
= event
->display
;
872 XSelectionEvent result
;
874 Window request
= event
->requestor
;
875 BOOL couldOpen
= FALSE
;
876 Atom xaClipboard
= TSXInternAtom(display
, "CLIPBOARD", False
);
877 Atom xaTargets
= TSXInternAtom(display
, "TARGETS", False
);
878 Atom xaMultiple
= TSXInternAtom(display
, "MULTIPLE", False
);
881 * We can only handle the selection request if :
882 * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
883 * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
884 * since this has been already done.
888 if ( ( (event
->selection
!= XA_PRIMARY
) && (event
->selection
!= xaClipboard
) )
889 || !(couldOpen
= OpenClipboard(hWnd
)) )
893 /* If the specified property is None the requestor is an obsolete client.
894 * We support these by using the specified target atom as the reply property.
896 rprop
= event
->property
;
898 rprop
= event
->target
;
900 if(event
->target
== xaTargets
) /* Return a list of all supported targets */
902 /* TARGETS selection request */
903 rprop
= EVENT_SelectionRequest_TARGETS( display
, request
, event
->target
, rprop
);
905 else if(event
->target
== xaMultiple
) /* rprop contains a list of (target, property) atom pairs */
907 /* MULTIPLE selection request */
908 rprop
= EVENT_SelectionRequest_MULTIPLE( hWnd
, event
);
910 else if(event
->target
== XA_STRING
) /* treat CF_TEXT as Unix text */
912 /* XA_STRING selection request */
913 rprop
= EVENT_SelectionRequest_STRING( display
, request
, event
->target
, rprop
);
915 else if(event
->target
== XA_PIXMAP
) /* Convert DIB's to Pixmaps */
917 /* XA_PIXMAP selection request */
918 rprop
= EVENT_SelectionRequest_PIXMAP( display
, request
, event
->target
, rprop
);
920 else if(event
->target
== XA_BITMAP
) /* Convert DIB's to 1-bit Pixmaps */
922 /* XA_BITMAP selection request - TODO: create a monochrome Pixmap */
923 rprop
= EVENT_SelectionRequest_PIXMAP( display
, request
, XA_PIXMAP
, rprop
);
925 else if(X11DRV_CLIPBOARD_IsNativeProperty(event
->target
)) /* <WCF>* */
927 /* All <WCF> selection requests */
928 rprop
= EVENT_SelectionRequest_WCF( display
, request
, event
->target
, rprop
);
931 rprop
= None
; /* Don't support this format */
934 /* close clipboard only if we opened before */
935 if(couldOpen
) CloseClipboard();
938 TRACE("\tRequest ignored\n");
941 * SelectionNotify should be sent only at the end of a MULTIPLE request
945 result
.type
= SelectionNotify
;
946 result
.display
= display
;
947 result
.requestor
= request
;
948 result
.selection
= event
->selection
;
949 result
.property
= rprop
;
950 result
.target
= event
->target
;
951 result
.time
= event
->time
;
952 TRACE("Sending SelectionNotify event...\n");
953 TSXSendEvent(display
,event
->requestor
,False
,NoEventMask
,(XEvent
*)&result
);
957 /***********************************************************************
958 * EVENT_SelectionClear
960 static void EVENT_SelectionClear( HWND hWnd
, XSelectionClearEvent
*event
)
962 Atom xaClipboard
= TSXInternAtom(event
->display
, "CLIPBOARD", False
);
964 if (event
->selection
== XA_PRIMARY
|| event
->selection
== xaClipboard
)
965 X11DRV_CLIPBOARD_ReleaseSelection( event
->selection
, event
->window
, hWnd
);
968 /***********************************************************************
969 * EVENT_PropertyNotify
970 * We use this to release resources like Pixmaps when a selection
971 * client no longer needs them.
973 static void EVENT_PropertyNotify( XPropertyEvent
*event
)
975 /* Check if we have any resources to free */
976 TRACE("Received PropertyNotify event: \n");
982 TRACE("\tPropertyDelete for atom %s on window %ld\n",
983 TSXGetAtomName(event
->display
, event
->atom
), (long)event
->window
);
985 if (X11DRV_IsSelectionOwner())
986 X11DRV_CLIPBOARD_FreeResources( event
->atom
);
990 case PropertyNewValue
:
992 TRACE("\tPropertyNewValue for atom %s on window %ld\n\n",
993 TSXGetAtomName(event
->display
, event
->atom
), (long)event
->window
);
1002 /**********************************************************************
1003 * EVENT_DropFromOffix
1005 * don't know if it still works (last Changlog is from 96/11/04)
1007 static void EVENT_DropFromOffiX( HWND hWnd
, XClientMessageEvent
*event
)
1009 unsigned long data_length
;
1010 unsigned long aux_long
;
1011 unsigned char* p_data
= NULL
;
1022 HGLOBAL16 hDragInfo
= GlobalAlloc16( GMEM_SHARE
| GMEM_ZEROINIT
, sizeof(DRAGINFO16
));
1023 LPDRAGINFO16 lpDragInfo
= (LPDRAGINFO16
) GlobalLock16(hDragInfo
);
1024 SEGPTR spDragInfo
= K32WOWGlobalLock16(hDragInfo
);
1025 Window w_aux_root
, w_aux_child
;
1028 if( !lpDragInfo
|| !spDragInfo
) return;
1030 pWnd
= WIN_FindWndPtr(hWnd
);
1032 TSXQueryPointer( event
->display
, get_whole_window(pWnd
), &w_aux_root
, &w_aux_child
,
1033 &x
, &y
, (int *) &u
.pt_aux
.x
, (int *) &u
.pt_aux
.y
,
1034 (unsigned int*)&aux_long
);
1036 lpDragInfo
->hScope
= hWnd
;
1037 lpDragInfo
->pt
.x
= (INT16
)x
; lpDragInfo
->pt
.y
= (INT16
)y
;
1039 /* find out drop point and drop window */
1040 if( x
< 0 || y
< 0 ||
1041 x
> (pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) ||
1042 y
> (pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
) )
1043 { bAccept
= pWnd
->dwExStyle
& WS_EX_ACCEPTFILES
; x
= y
= 0; }
1046 bAccept
= DRAG_QueryUpdate( hWnd
, spDragInfo
, TRUE
);
1047 x
= lpDragInfo
->pt
.x
; y
= lpDragInfo
->pt
.y
;
1049 WIN_ReleaseWndPtr(pWnd
);
1051 GlobalFree16( hDragInfo
);
1053 if (!bAccept
) return;
1055 TSXGetWindowProperty( event
->display
, DefaultRootWindow(event
->display
),
1056 dndSelection
, 0, 65535, FALSE
,
1057 AnyPropertyType
, &u
.atom_aux
, (int *) &u
.pt_aux
.y
,
1058 &data_length
, &aux_long
, &p_data
);
1060 if( !aux_long
&& p_data
) /* don't bother if > 64K */
1062 signed char *p
= (signed char*) p_data
;
1066 while( *p
) /* calculate buffer size */
1069 if((u
.i
= *p
) != -1 )
1071 INT len
= GetShortPathNameA( p
, NULL
, 0 );
1072 if (len
) aux_long
+= len
+ 1;
1077 if( aux_long
&& aux_long
< 65535 )
1082 aux_long
+= sizeof(DROPFILES
) + 1;
1083 hDrop
= GlobalAlloc( GMEM_SHARE
, aux_long
);
1084 lpDrop
= (DROPFILES
*)GlobalLock( hDrop
);
1088 WND
*pDropWnd
= WIN_FindWndPtr( lpDragInfo
->hScope
);
1089 lpDrop
->pFiles
= sizeof(DROPFILES
);
1093 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
1094 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
1095 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
1096 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
1097 lpDrop
->fWide
= FALSE
;
1098 WIN_ReleaseWndPtr(pDropWnd
);
1099 p_drop
= (char *)(lpDrop
+ 1);
1103 if( *p
!= -1 ) /* use only "good" entries */
1105 GetShortPathNameA( p
, p_drop
, 65535 );
1106 p_drop
+= strlen( p_drop
) + 1;
1111 PostMessageA( hWnd
, WM_DROPFILES
, (WPARAM
)hDrop
, 0L );
1115 if( p_data
) TSXFree(p_data
);
1118 /**********************************************************************
1121 * drop items are separated by \n
1122 * each item is prefixed by its mime type
1124 * event->data.l[3], event->data.l[4] contains drop x,y position
1126 static void EVENT_DropURLs( HWND hWnd
, XClientMessageEvent
*event
)
1128 unsigned long data_length
;
1129 unsigned long aux_long
, drop_len
= 0;
1130 unsigned char *p_data
= NULL
; /* property data */
1131 char *p_drop
= NULL
;
1142 if (!(GetWindowLongW( hWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
)) return;
1144 TSXGetWindowProperty( event
->display
, DefaultRootWindow(event
->display
),
1145 dndSelection
, 0, 65535, FALSE
,
1146 AnyPropertyType
, &u
.atom_aux
, &u
.i
,
1147 &data_length
, &aux_long
, &p_data
);
1149 WARN("property too large, truncated!\n");
1150 TRACE("urls=%s\n", p_data
);
1152 if( !aux_long
&& p_data
) { /* don't bother if > 64K */
1153 /* calculate length */
1155 next
= strchr(p
, '\n');
1158 if (strncmp(p
,"file:",5) == 0 ) {
1159 INT len
= GetShortPathNameA( p
+5, NULL
, 0 );
1160 if (len
) drop_len
+= len
+ 1;
1165 next
= strchr(p
, '\n');
1171 if( drop_len
&& drop_len
< 65535 ) {
1172 TSXQueryPointer( event
->display
, root_window
, &u
.w_aux
, &u
.w_aux
,
1173 &x
, &y
, &u
.i
, &u
.i
, &u
.i
);
1175 drop_len
+= sizeof(DROPFILES
) + 1;
1176 hDrop
= GlobalAlloc( GMEM_SHARE
, drop_len
);
1177 lpDrop
= (DROPFILES
*) GlobalLock( hDrop
);
1180 WND
*pDropWnd
= WIN_FindWndPtr( hWnd
);
1181 lpDrop
->pFiles
= sizeof(DROPFILES
);
1182 lpDrop
->pt
.x
= (INT
)x
;
1183 lpDrop
->pt
.y
= (INT
)y
;
1185 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
1186 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
1187 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
1188 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
1189 lpDrop
->fWide
= FALSE
;
1190 p_drop
= (char*)(lpDrop
+ 1);
1191 WIN_ReleaseWndPtr(pDropWnd
);
1194 /* create message content */
1197 next
= strchr(p
, '\n');
1200 if (strncmp(p
,"file:",5) == 0 ) {
1201 INT len
= GetShortPathNameA( p
+5, p_drop
, 65535 );
1203 TRACE("drop file %s as %s\n", p
+5, p_drop
);
1206 WARN("can't convert file %s to dos name \n", p
+5);
1209 WARN("unknown mime type %s\n", p
);
1214 next
= strchr(p
, '\n');
1221 GlobalUnlock(hDrop
);
1222 PostMessageA( hWnd
, WM_DROPFILES
, (WPARAM
)hDrop
, 0L );
1225 if( p_data
) TSXFree(p_data
);
1229 /**********************************************************************
1230 * EVENT_ClientMessage
1232 static void EVENT_ClientMessage( HWND hWnd
, XClientMessageEvent
*event
)
1234 if (event
->message_type
!= None
&& event
->format
== 32) {
1235 if ((event
->message_type
== wmProtocols
) &&
1236 (((Atom
) event
->data
.l
[0]) == wmDeleteWindow
))
1238 /* Ignore the delete window request if the window has been disabled */
1239 if (!(GetWindowLongA( hWnd
, GWL_STYLE
) & WS_DISABLED
))
1240 PostMessageA( hWnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
1242 else if (event
->message_type
== dndProtocol
)
1244 /* query window (drag&drop event contains only drag window) */
1246 int root_x
, root_y
, child_x
, child_y
;
1248 TSXQueryPointer( event
->display
, root_window
, &root
, &child
,
1249 &root_x
, &root_y
, &child_x
, &child_y
, &u
);
1250 if (TSXFindContext( event
->display
, child
, winContext
, (char **)&hWnd
) != 0) return;
1251 if (event
->data
.l
[0] == DndFile
|| event
->data
.l
[0] == DndFiles
)
1252 EVENT_DropFromOffiX(hWnd
, event
);
1253 else if (event
->data
.l
[0] == DndURL
)
1254 EVENT_DropURLs(hWnd
, event
);
1258 /* enable this if you want to see the message */
1259 unsigned char* p_data
= NULL
;
1265 TSXGetWindowProperty( event
->display
, DefaultRootWindow(event
->display
),
1266 dndSelection
, 0, 65535, FALSE
,
1267 AnyPropertyType
, &u
.atom
, &u
.i
,
1268 &u
.l
, &u
.l
, &p_data
);
1269 TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1270 event
->message_type
, event
->data
.l
[0], event
->data
.l
[1],
1271 event
->data
.l
[2], event
->data
.l
[3], event
->data
.l
[4],
1274 TRACE("unrecognized ClientMessage\n" );
1280 /**********************************************************************
1281 * X11DRV_EVENT_SetInputMethod
1283 INPUT_TYPE
X11DRV_EVENT_SetInputMethod(INPUT_TYPE type
)
1285 INPUT_TYPE prev
= current_input_type
;
1287 /* Flag not used yet */
1288 in_transition
= FALSE
;
1289 current_input_type
= type
;
1294 #ifdef HAVE_LIBXXF86DGA2
1295 /**********************************************************************
1296 * X11DRV_EVENT_SetDGAStatus
1298 void X11DRV_EVENT_SetDGAStatus(HWND hwnd
, int event_base
)
1300 if (event_base
< 0) {
1306 DGAMotionEventType
= event_base
+ MotionNotify
;
1307 DGAButtonPressEventType
= event_base
+ ButtonPress
;
1308 DGAButtonReleaseEventType
= event_base
+ ButtonRelease
;
1309 DGAKeyPressEventType
= event_base
+ KeyPress
;
1310 DGAKeyReleaseEventType
= event_base
+ KeyRelease
;