4 * Copyright 1993 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define COM_NO_WINDOWS_H
25 #include <X11/Xatom.h>
26 #include <X11/keysym.h>
29 #include <X11/Xresource.h>
30 #include <X11/Xutil.h>
31 #ifdef HAVE_LIBXXF86DGA2
32 #include <X11/extensions/xf86dga.h>
37 #include "wine/winuser16.h"
38 #include "shlobj.h" /* DROPFILES */
40 #include "clipboard.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(event
);
50 WINE_DECLARE_DEBUG_CHANNEL(clipboard
);
52 /* X context to associate a hwnd to an X window */
53 extern XContext winContext
;
55 extern Atom wmProtocols
;
56 extern Atom wmDeleteWindow
;
57 extern Atom dndProtocol
;
58 extern Atom dndSelection
;
59 extern Atom netwmPing
;
61 #define DndNotDnd -1 /* OffiX drag&drop */
73 #define DndURL 128 /* KDE drag&drop */
75 static const char * const event_names
[] =
77 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
78 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
79 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
80 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
81 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
82 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
83 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
84 "ClientMessage", "MappingNotify"
88 static void EVENT_ProcessEvent( XEvent
*event
);
91 static void EVENT_FocusIn( HWND hWnd
, XFocusChangeEvent
*event
);
92 static void EVENT_FocusOut( HWND hWnd
, XFocusChangeEvent
*event
);
93 static void EVENT_SelectionRequest( HWND hWnd
, XSelectionRequestEvent
*event
, BOOL bIsMultiple
);
94 static void EVENT_SelectionClear( HWND hWnd
, XSelectionClearEvent
*event
);
95 static void EVENT_PropertyNotify( XPropertyEvent
*event
);
96 static void EVENT_ClientMessage( HWND hWnd
, XClientMessageEvent
*event
);
98 extern void X11DRV_ButtonPress( HWND hwnd
, XButtonEvent
*event
);
99 extern void X11DRV_ButtonRelease( HWND hwnd
, XButtonEvent
*event
);
100 extern void X11DRV_MotionNotify( HWND hwnd
, XMotionEvent
*event
);
101 extern void X11DRV_EnterNotify( HWND hwnd
, XCrossingEvent
*event
);
102 extern void X11DRV_KeyEvent( HWND hwnd
, XKeyEvent
*event
);
103 extern void X11DRV_KeymapNotify( HWND hwnd
, XKeymapEvent
*event
);
104 extern void X11DRV_Expose( HWND hwnd
, XExposeEvent
*event
);
105 extern void X11DRV_MapNotify( HWND hwnd
, XMapEvent
*event
);
106 extern void X11DRV_UnmapNotify( HWND hwnd
, XUnmapEvent
*event
);
107 extern void X11DRV_ConfigureNotify( HWND hwnd
, XConfigureEvent
*event
);
108 extern void X11DRV_MappingNotify( XMappingEvent
*event
);
110 #ifdef HAVE_LIBXXF86DGA2
111 static int DGAMotionEventType
;
112 static int DGAButtonPressEventType
;
113 static int DGAButtonReleaseEventType
;
114 static int DGAKeyPressEventType
;
115 static int DGAKeyReleaseEventType
;
117 static BOOL DGAUsed
= FALSE
;
118 static HWND DGAhwnd
= 0;
120 extern void X11DRV_DGAMotionEvent( HWND hwnd
, XDGAMotionEvent
*event
);
121 extern void X11DRV_DGAButtonPressEvent( HWND hwnd
, XDGAButtonEvent
*event
);
122 extern void X11DRV_DGAButtonReleaseEvent( HWND hwnd
, XDGAButtonEvent
*event
);
125 /* Static used for the current input method */
126 static INPUT_TYPE current_input_type
= X11DRV_INPUT_ABSOLUTE
;
127 static BOOL in_transition
= FALSE
; /* This is not used as for today */
130 /***********************************************************************
133 static int process_events( struct x11drv_thread_data
*data
)
139 while ( XPending( data
->display
) )
143 XNextEvent( data
->display
, &event
);
144 ignore
= XFilterEvent( &event
, None
);
146 if (!ignore
) EVENT_ProcessEvent( &event
);
155 /***********************************************************************
156 * MsgWaitForMultipleObjectsEx (X11DRV.@)
158 DWORD
X11DRV_MsgWaitForMultipleObjectsEx( DWORD count
, const HANDLE
*handles
,
159 DWORD timeout
, DWORD mask
, DWORD flags
)
161 HANDLE new_handles
[MAXIMUM_WAIT_OBJECTS
+1]; /* FIXME! */
163 struct x11drv_thread_data
*data
= NtCurrentTeb()->driver_data
;
165 if (!data
|| data
->process_event_count
)
166 return WaitForMultipleObjectsEx( count
, handles
, flags
& MWMO_WAITALL
,
167 timeout
, flags
& MWMO_ALERTABLE
);
169 /* check whether only server queue handle was passed in */
170 if (count
< 2) flags
&= ~MWMO_WAITALL
;
172 for (i
= 0; i
< count
; i
++) new_handles
[i
] = handles
[i
];
173 new_handles
[count
] = data
->display_fd
;
176 XFlush( gdi_display
);
177 XFlush( data
->display
);
180 data
->process_event_count
++;
181 if (process_events( data
)) ret
= count
;
184 ret
= WaitForMultipleObjectsEx( count
+1, new_handles
, flags
& MWMO_WAITALL
,
185 timeout
, flags
& MWMO_ALERTABLE
);
186 if (ret
== count
) process_events( data
);
188 data
->process_event_count
--;
193 /***********************************************************************
196 * Process an X event.
198 static void EVENT_ProcessEvent( XEvent
*event
)
201 Display
*display
= event
->xany
.display
;
203 TRACE( "called.\n" );
207 case SelectionNotify
: /* all of these should be caught by XCheckTypedWindowEvent() */
208 FIXME("Got SelectionNotify - must not happen!\n");
211 /* We get all these because of StructureNotifyMask.
212 This check is placed here to avoid getting error messages below,
213 as X might send some of these even for windows that have already
215 case CirculateNotify
:
223 #ifdef HAVE_LIBXXF86DGA2
225 if (event
->type
== DGAMotionEventType
) {
226 TRACE("DGAMotionEvent received.\n");
227 X11DRV_DGAMotionEvent( DGAhwnd
, (XDGAMotionEvent
*)event
);
230 if (event
->type
== DGAButtonPressEventType
) {
231 TRACE("DGAButtonPressEvent received.\n");
232 X11DRV_DGAButtonPressEvent( DGAhwnd
, (XDGAButtonEvent
*)event
);
235 if (event
->type
== DGAButtonReleaseEventType
) {
236 TRACE("DGAButtonReleaseEvent received.\n");
237 X11DRV_DGAButtonReleaseEvent( DGAhwnd
, (XDGAButtonEvent
*)event
);
240 if ((event
->type
== DGAKeyPressEventType
) ||
241 (event
->type
== DGAKeyReleaseEventType
)) {
242 /* Fill a XKeyEvent to send to EVENT_Key */
244 XDGAKeyEvent
*evt
= (XDGAKeyEvent
*) event
;
246 TRACE("DGAKeyPress/ReleaseEvent received.\n");
248 if (evt
->type
== DGAKeyReleaseEventType
)
249 ke
.type
= KeyRelease
;
252 ke
.serial
= evt
->serial
;
253 ke
.send_event
= FALSE
;
254 ke
.display
= evt
->display
;
263 ke
.state
= evt
->state
;
264 ke
.keycode
= evt
->keycode
;
265 ke
.same_screen
= TRUE
;
266 X11DRV_KeyEvent( 0, &ke
);
273 if (XFindContext( display
, event
->xany
.window
, winContext
, (char **)&hWnd
) != 0)
274 hWnd
= 0; /* Not for a registered window */
276 if (!hWnd
&& event
->xany
.window
== root_window
) hWnd
= GetDesktopWindow();
278 if (!hWnd
&& event
->type
!= PropertyNotify
&& event
->type
!= MappingNotify
)
279 WARN( "Got event %s for unknown Window %08lx\n",
280 event_names
[event
->type
], event
->xany
.window
);
282 TRACE("Got event %s for hwnd %p\n",
283 event_names
[event
->type
], hWnd
);
289 /* FIXME: should generate a motion event if event point is different from current pos */
290 X11DRV_KeyEvent( hWnd
, (XKeyEvent
*)event
);
294 X11DRV_ButtonPress( hWnd
, (XButtonEvent
*)event
);
298 X11DRV_ButtonRelease( hWnd
, (XButtonEvent
*)event
);
302 X11DRV_MotionNotify( hWnd
, (XMotionEvent
*)event
);
306 X11DRV_EnterNotify( hWnd
, (XCrossingEvent
*)event
);
310 EVENT_FocusIn( hWnd
, (XFocusChangeEvent
*)event
);
314 EVENT_FocusOut( hWnd
, (XFocusChangeEvent
*)event
);
318 X11DRV_Expose( hWnd
, &event
->xexpose
);
321 case ConfigureNotify
:
323 X11DRV_ConfigureNotify( hWnd
, &event
->xconfigure
);
326 case SelectionRequest
:
328 EVENT_SelectionRequest( hWnd
, (XSelectionRequestEvent
*)event
, FALSE
);
333 EVENT_SelectionClear( hWnd
, (XSelectionClearEvent
*) event
);
337 EVENT_PropertyNotify( (XPropertyEvent
*)event
);
342 EVENT_ClientMessage( hWnd
, (XClientMessageEvent
*) event
);
349 X11DRV_MapNotify( hWnd
, (XMapEvent
*)event
);
353 X11DRV_UnmapNotify( hWnd
, (XUnmapEvent
*)event
);
357 X11DRV_KeymapNotify( hWnd
, (XKeymapEvent
*)event
);
361 X11DRV_MappingNotify( (XMappingEvent
*) event
);
365 WARN("Unprocessed event %s for hwnd %p\n", event_names
[event
->type
], hWnd
);
368 TRACE( "returns.\n" );
372 /*******************************************************************
373 * can_activate_window
375 * Check if we can activate the specified window.
377 inline static BOOL
can_activate_window( HWND hwnd
)
379 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
380 if (!(style
& WS_VISIBLE
)) return FALSE
;
381 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
382 return !(style
& WS_DISABLED
);
386 /**********************************************************************
387 * set_focus_error_handler
389 * Handler for X errors happening during XSetInputFocus call.
391 static int set_focus_error_handler( Display
*display
, XErrorEvent
*event
, void *arg
)
393 return (event
->error_code
== BadMatch
);
397 /**********************************************************************
400 static void set_focus( HWND hwnd
, Time time
)
405 TRACE( "setting foreground window to %p\n", hwnd
);
406 SetForegroundWindow( hwnd
);
409 if (focus
) focus
= GetAncestor( focus
, GA_ROOT
);
410 win
= X11DRV_get_whole_window(focus
);
414 Display
*display
= thread_display();
415 TRACE( "setting focus to %p (%lx) time=%ld\n", focus
, win
, time
);
416 X11DRV_expect_error( display
, set_focus_error_handler
, NULL
);
417 XSetInputFocus( display
, win
, RevertToParent
, time
);
418 if (X11DRV_check_error()) TRACE("got BadMatch, ignoring\n" );
423 /**********************************************************************
424 * handle_wm_protocols_message
426 static void handle_wm_protocols_message( HWND hwnd
, XClientMessageEvent
*event
)
428 Atom protocol
= (Atom
)event
->data
.l
[0];
430 if (!protocol
) return;
432 if (protocol
== wmDeleteWindow
)
434 /* Ignore the delete window request if the window has been disabled
435 * and we are in managed mode. This is to disallow applications from
436 * being closed by the window manager while in a modal state.
438 if (IsWindowEnabled(hwnd
)) PostMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
440 else if (protocol
== wmTakeFocus
)
442 Time event_time
= (Time
)event
->data
.l
[1];
443 HWND last_focus
= x11drv_thread_data()->last_focus
;
445 TRACE( "got take focus msg for %p, enabled=%d, focus=%p, active=%p, fg=%p, last=%p\n",
446 hwnd
, IsWindowEnabled(hwnd
), GetFocus(), GetActiveWindow(),
447 GetForegroundWindow(), last_focus
);
449 if (can_activate_window(hwnd
))
451 /* simulate a mouse click on the caption to find out
452 * whether the window wants to be activated */
453 LRESULT ma
= SendMessageW( hwnd
, WM_MOUSEACTIVATE
,
454 (WPARAM
)GetAncestor( hwnd
, GA_ROOT
),
455 MAKELONG(HTCAPTION
,WM_LBUTTONDOWN
) );
456 if (ma
!= MA_NOACTIVATEANDEAT
&& ma
!= MA_NOACTIVATE
) set_focus( hwnd
, event_time
);
457 else TRACE( "not setting focus to %p (%lx), ma=%ld\n", hwnd
, event
->window
, ma
);
462 if (hwnd
) hwnd
= GetAncestor( hwnd
, GA_ROOT
);
463 if (!hwnd
) hwnd
= GetActiveWindow();
464 if (!hwnd
) hwnd
= last_focus
;
465 if (hwnd
&& can_activate_window(hwnd
)) set_focus( hwnd
, event_time
);
467 } else if (protocol
== netwmPing
) {
468 XClientMessageEvent xev
;
471 TRACE("NET_WM Ping\n");
472 xev
.window
= DefaultRootWindow(xev
.display
);
473 XSendEvent(xev
.display
, xev
.window
, False
, SubstructureRedirectMask
| SubstructureNotifyMask
, (XEvent
*)&xev
);
474 /* this line is semi-stolen from gtk2 */
475 TRACE("NET_WM Pong\n");
480 static const char * const focus_details
[] =
486 "NotifyNonlinearVirtual",
492 /**********************************************************************
495 static void EVENT_FocusIn( HWND hwnd
, XFocusChangeEvent
*event
)
501 TRACE( "win %p xwin %lx detail=%s\n", hwnd
, event
->window
, focus_details
[event
->detail
] );
503 if (event
->detail
== NotifyPointer
) return;
505 if ((xic
= X11DRV_get_ic( hwnd
)))
511 if (wmTakeFocus
) return; /* ignore FocusIn if we are using take focus */
513 if (!can_activate_window(hwnd
))
515 HWND hwnd
= GetFocus();
516 if (hwnd
) hwnd
= GetAncestor( hwnd
, GA_ROOT
);
517 if (!hwnd
) hwnd
= GetActiveWindow();
518 if (!hwnd
) hwnd
= x11drv_thread_data()->last_focus
;
519 if (hwnd
&& can_activate_window(hwnd
)) set_focus( hwnd
, CurrentTime
);
521 else SetForegroundWindow( hwnd
);
525 /**********************************************************************
528 * Note: only top-level windows get FocusOut events.
530 static void EVENT_FocusOut( HWND hwnd
, XFocusChangeEvent
*event
)
537 TRACE( "win %p xwin %lx detail=%s\n", hwnd
, event
->window
, focus_details
[event
->detail
] );
539 if (event
->detail
== NotifyPointer
) return;
540 x11drv_thread_data()->last_focus
= hwnd
;
541 if ((xic
= X11DRV_get_ic( hwnd
)))
544 XUnsetICFocus( xic
);
547 if (hwnd
!= GetForegroundWindow()) return;
548 SendMessageA( hwnd
, WM_CANCELMODE
, 0, 0 );
550 /* don't reset the foreground window, if the window which is
551 getting the focus is a Wine window */
554 XGetInputFocus( thread_display(), &focus_win
, &revert
);
557 if (XFindContext( thread_display(), focus_win
, winContext
, (char **)&hwnd_tmp
) != 0)
564 /* Abey : 6-Oct-99. Check again if the focus out window is the
565 Foreground window, because in most cases the messages sent
566 above must have already changed the foreground window, in which
567 case we don't have to change the foreground window to 0 */
568 if (hwnd
== GetForegroundWindow())
570 TRACE( "lost focus, setting fg to 0\n" );
571 SetForegroundWindow( 0 );
577 /***********************************************************************
578 * EVENT_SelectionRequest_AddTARGETS
579 * Utility function for EVENT_SelectionRequest_TARGETS.
581 static void EVENT_SelectionRequest_AddTARGETS(Atom
* targets
, unsigned long* cTargets
, Atom prop
)
586 /* Scan through what we have so far to avoid duplicates */
587 for (i
= 0, bExists
= FALSE
; i
< *cTargets
; i
++)
589 if (targets
[i
] == prop
)
597 targets
[(*cTargets
)++] = prop
;
601 /***********************************************************************
602 * EVENT_SelectionRequest_TARGETS
603 * Service a TARGETS selection request event
605 static Atom
EVENT_SelectionRequest_TARGETS( Display
*display
, Window requestor
,
606 Atom target
, Atom rprop
)
614 * Count the number of items we wish to expose as selection targets.
615 * We include the TARGETS item, and propery aliases
617 cTargets
= X11DRV_CountClipboardFormats() + 1;
619 for (wFormat
= 0; (wFormat
= X11DRV_EnumClipboardFormats(wFormat
));)
621 LPWINE_CLIPFORMAT lpFormat
= X11DRV_CLIPBOARD_LookupFormat(wFormat
);
622 if (lpFormat
&& X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat
->drvData
))
626 TRACE_(clipboard
)(" found %ld formats\n", cTargets
);
628 /* Allocate temp buffer */
629 targets
= (Atom
*)HeapAlloc( GetProcessHeap(), 0, cTargets
* sizeof(Atom
));
633 /* Create TARGETS property list (First item in list is TARGETS itself) */
634 for (targets
[0] = xaTargets
, cTargets
= 1, wFormat
= 0;
635 (wFormat
= X11DRV_EnumClipboardFormats(wFormat
));)
637 LPWINE_CLIPFORMAT lpFormat
= X11DRV_CLIPBOARD_LookupFormat(wFormat
);
639 EVENT_SelectionRequest_AddTARGETS(targets
, &cTargets
, lpFormat
->drvData
);
641 /* Check if any alias should be listed */
642 alias
= X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat
->drvData
);
644 EVENT_SelectionRequest_AddTARGETS(targets
, &cTargets
, alias
);
647 if (TRACE_ON(clipboard
))
650 for ( i
= 0; i
< cTargets
; i
++)
654 char *itemFmtName
= TSXGetAtomName(display
, targets
[i
]);
655 TRACE_(clipboard
)("\tAtom# %d: Property %ld Type %s\n", i
, targets
[i
], itemFmtName
);
656 TSXFree(itemFmtName
);
661 /* We may want to consider setting the type to xaTargets instead,
662 * in case some apps expect this instead of XA_ATOM */
663 TSXChangeProperty(display
, requestor
, rprop
, XA_ATOM
, 32,
664 PropModeReplace
, (unsigned char *)targets
, cTargets
);
666 HeapFree(GetProcessHeap(), 0, targets
);
672 /***********************************************************************
673 * EVENT_SelectionRequest_MULTIPLE
674 * Service a MULTIPLE selection request event
675 * rprop contains a list of (target,property) atom pairs.
676 * The first atom names a target and the second names a property.
677 * The effect is as if we have received a sequence of SelectionRequest events
678 * (one for each atom pair) except that:
679 * 1. We reply with a SelectionNotify only when all the requested conversions
680 * have been performed.
681 * 2. If we fail to convert the target named by an atom in the MULTIPLE property,
682 * we replace the atom in the property by None.
684 static Atom
EVENT_SelectionRequest_MULTIPLE( HWND hWnd
, XSelectionRequestEvent
*pevent
)
686 Display
*display
= pevent
->display
;
688 Atom atype
=AnyPropertyType
;
690 unsigned long remain
;
691 Atom
* targetPropList
=NULL
;
692 unsigned long cTargetPropList
= 0;
693 /* Atom xAtomPair = TSXInternAtom(display, "ATOM_PAIR", False); */
695 /* If the specified property is None the requestor is an obsolete client.
696 * We support these by using the specified target atom as the reply property.
698 rprop
= pevent
->property
;
700 rprop
= pevent
->target
;
704 /* Read the MULTIPLE property contents. This should contain a list of
705 * (target,property) atom pairs.
707 if(TSXGetWindowProperty(display
, pevent
->requestor
, rprop
,
708 0, 0x3FFF, False
, AnyPropertyType
, &atype
,&aformat
,
709 &cTargetPropList
, &remain
,
710 (unsigned char**)&targetPropList
) != Success
)
711 TRACE("\tCouldn't read MULTIPLE property\n");
714 TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
715 TSXGetAtomName(display
, atype
), aformat
, cTargetPropList
, remain
);
718 * Make sure we got what we expect.
719 * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
720 * in a MULTIPLE selection request should be of type ATOM_PAIR.
721 * However some X apps(such as XPaint) are not compliant with this and return
722 * a user defined atom in atype when XGetWindowProperty is called.
723 * The data *is* an atom pair but is not denoted as such.
725 if(aformat
== 32 /* atype == xAtomPair */ )
729 /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
730 * for each (target,property) pair */
732 for (i
= 0; i
< cTargetPropList
; i
+=2)
734 char *targetName
= TSXGetAtomName(display
, targetPropList
[i
]);
735 char *propName
= TSXGetAtomName(display
, targetPropList
[i
+1]);
736 XSelectionRequestEvent event
;
738 TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
739 i
/2, targetName
, propName
);
743 /* We must have a non "None" property to service a MULTIPLE target atom */
744 if ( !targetPropList
[i
+1] )
746 TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i
);
750 /* Set up an XSelectionRequestEvent for this (target,property) pair */
751 memcpy( &event
, pevent
, sizeof(XSelectionRequestEvent
) );
752 event
.target
= targetPropList
[i
];
753 event
.property
= targetPropList
[i
+1];
755 /* Fire a SelectionRequest, informing the handler that we are processing
756 * a MULTIPLE selection request event.
758 EVENT_SelectionRequest( hWnd
, &event
, TRUE
);
762 /* Free the list of targets/properties */
763 TSXFree(targetPropList
);
771 /***********************************************************************
772 * EVENT_SelectionRequest
773 * Process an event selection request event.
774 * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
775 * recursively while servicing a "MULTIPLE" selection target.
777 * Note: We only receive this event when WINE owns the X selection
779 static void EVENT_SelectionRequest( HWND hWnd
, XSelectionRequestEvent
*event
, BOOL bIsMultiple
)
781 Display
*display
= event
->display
;
782 XSelectionEvent result
;
784 Window request
= event
->requestor
;
786 TRACE_(clipboard
)("\n");
789 * We can only handle the selection request if :
790 * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
791 * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
792 * since this has been already done.
796 if (((event
->selection
!= XA_PRIMARY
) && (event
->selection
!= xaClipboard
)))
800 /* If the specified property is None the requestor is an obsolete client.
801 * We support these by using the specified target atom as the reply property.
803 rprop
= event
->property
;
805 rprop
= event
->target
;
807 if(event
->target
== xaTargets
) /* Return a list of all supported targets */
809 /* TARGETS selection request */
810 rprop
= EVENT_SelectionRequest_TARGETS( display
, request
, event
->target
, rprop
);
812 else if(event
->target
== xaMultiple
) /* rprop contains a list of (target, property) atom pairs */
814 /* MULTIPLE selection request */
815 rprop
= EVENT_SelectionRequest_MULTIPLE( hWnd
, event
);
819 LPWINE_CLIPFORMAT lpFormat
= X11DRV_CLIPBOARD_LookupProperty(event
->target
);
822 lpFormat
= X11DRV_CLIPBOARD_LookupAliasProperty(event
->target
);
826 LPWINE_CLIPDATA lpData
= X11DRV_CLIPBOARD_LookupData(lpFormat
->wFormatID
);
830 unsigned char* lpClipData
;
832 HANDLE hClipData
= lpFormat
->lpDrvExportFunc(lpData
, &cBytes
);
834 if (hClipData
&& (lpClipData
= GlobalLock(hClipData
)))
837 TRACE_(clipboard
)("\tUpdating property %s, %ld bytes\n",
838 lpFormat
->Name
, cBytes
);
840 TSXChangeProperty(display
, request
, rprop
, event
->target
,
841 8, PropModeReplace
, (unsigned char *)lpClipData
, cBytes
);
843 GlobalUnlock(hClipData
);
844 GlobalFree(hClipData
);
850 if (TRACE_ON(clipboard
))
852 TRACE_(clipboard
)("Request for property %s (%ld) failed\n",
853 TSXGetAtomName(display
, event
->target
), event
->target
);
860 * SelectionNotify should be sent only at the end of a MULTIPLE request
864 result
.type
= SelectionNotify
;
865 result
.display
= display
;
866 result
.requestor
= request
;
867 result
.selection
= event
->selection
;
868 result
.property
= rprop
;
869 result
.target
= event
->target
;
870 result
.time
= event
->time
;
871 TRACE("Sending SelectionNotify event...\n");
872 TSXSendEvent(display
,event
->requestor
,False
,NoEventMask
,(XEvent
*)&result
);
876 /***********************************************************************
877 * EVENT_SelectionClear
879 static void EVENT_SelectionClear( HWND hWnd
, XSelectionClearEvent
*event
)
881 if (event
->selection
== XA_PRIMARY
|| event
->selection
== xaClipboard
)
882 X11DRV_CLIPBOARD_ReleaseSelection( event
->selection
, event
->window
, hWnd
);
885 /***********************************************************************
886 * EVENT_PropertyNotify
887 * We use this to release resources like Pixmaps when a selection
888 * client no longer needs them.
890 static void EVENT_PropertyNotify( XPropertyEvent
*event
)
892 /* Check if we have any resources to free */
893 TRACE("Received PropertyNotify event: \n");
899 TRACE("\tPropertyDelete for atom %s on window %ld\n",
900 TSXGetAtomName(event
->display
, event
->atom
), (long)event
->window
);
904 case PropertyNewValue
:
906 TRACE("\tPropertyNewValue for atom %s on window %ld\n\n",
907 TSXGetAtomName(event
->display
, event
->atom
), (long)event
->window
);
916 static HWND
find_drop_window( HWND hQueryWnd
, LPPOINT lpPt
)
920 if (!IsWindowEnabled(hQueryWnd
)) return 0;
922 GetWindowRect(hQueryWnd
, &tempRect
);
924 if(!PtInRect(&tempRect
, *lpPt
)) return 0;
926 if (!IsIconic( hQueryWnd
))
928 GetClientRect( hQueryWnd
, &tempRect
);
929 MapWindowPoints( hQueryWnd
, 0, (LPPOINT
)&tempRect
, 2 );
931 if (PtInRect( &tempRect
, *lpPt
))
933 HWND
*list
= WIN_ListChildren( hQueryWnd
);
940 for (i
= 0; list
[i
]; i
++)
942 if (GetWindowLongW( list
[i
], GWL_STYLE
) & WS_VISIBLE
)
944 GetWindowRect( list
[i
], &tempRect
);
945 if (PtInRect( &tempRect
, *lpPt
)) break;
950 if (IsWindowEnabled( list
[i
] ))
951 bResult
= find_drop_window( list
[i
], lpPt
);
953 HeapFree( GetProcessHeap(), 0, list
);
955 if(bResult
) return bResult
;
959 if(!(GetWindowLongA( hQueryWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
)) return 0;
961 ScreenToClient(hQueryWnd
, lpPt
);
966 /**********************************************************************
967 * EVENT_DropFromOffix
969 * don't know if it still works (last Changlog is from 96/11/04)
971 static void EVENT_DropFromOffiX( HWND hWnd
, XClientMessageEvent
*event
)
973 unsigned long data_length
;
974 unsigned long aux_long
;
975 unsigned char* p_data
= NULL
;
986 Window w_aux_root
, w_aux_child
;
990 pWnd
= WIN_FindWndPtr(hWnd
);
992 TSXQueryPointer( event
->display
, get_whole_window(pWnd
), &w_aux_root
, &w_aux_child
,
993 &x
, &y
, (int *) &u
.pt_aux
.x
, (int *) &u
.pt_aux
.y
,
994 (unsigned int*)&aux_long
);
996 /* find out drop point and drop window */
997 if( x
< 0 || y
< 0 ||
998 x
> (pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) ||
999 y
> (pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
) )
1001 bAccept
= pWnd
->dwExStyle
& WS_EX_ACCEPTFILES
;
1007 POINT pt
= { x
, y
};
1008 HWND hwndDrop
= find_drop_window( hWnd
, &pt
);
1021 WIN_ReleaseWndPtr(pWnd
);
1023 if (!bAccept
) return;
1025 TSXGetWindowProperty( event
->display
, DefaultRootWindow(event
->display
),
1026 dndSelection
, 0, 65535, FALSE
,
1027 AnyPropertyType
, &u
.atom_aux
, (int *) &u
.pt_aux
.y
,
1028 &data_length
, &aux_long
, &p_data
);
1030 if( !aux_long
&& p_data
) /* don't bother if > 64K */
1032 signed char *p
= (signed char*) p_data
;
1036 while( *p
) /* calculate buffer size */
1039 if((u
.i
= *p
) != -1 )
1041 INT len
= GetShortPathNameA( p
, NULL
, 0 );
1042 if (len
) aux_long
+= len
+ 1;
1047 if( aux_long
&& aux_long
< 65535 )
1052 aux_long
+= sizeof(DROPFILES
) + 1;
1053 hDrop
= GlobalAlloc( GMEM_SHARE
, aux_long
);
1054 lpDrop
= (DROPFILES
*)GlobalLock( hDrop
);
1058 WND
*pDropWnd
= WIN_FindWndPtr( hScope
);
1059 lpDrop
->pFiles
= sizeof(DROPFILES
);
1063 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
1064 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
1065 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
1066 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
1067 lpDrop
->fWide
= FALSE
;
1068 WIN_ReleaseWndPtr(pDropWnd
);
1069 p_drop
= (char *)(lpDrop
+ 1);
1073 if( *p
!= -1 ) /* use only "good" entries */
1075 GetShortPathNameA( p
, p_drop
, 65535 );
1076 p_drop
+= strlen( p_drop
) + 1;
1081 PostMessageA( hWnd
, WM_DROPFILES
, (WPARAM
)hDrop
, 0L );
1085 if( p_data
) TSXFree(p_data
);
1088 /**********************************************************************
1091 * drop items are separated by \n
1092 * each item is prefixed by its mime type
1094 * event->data.l[3], event->data.l[4] contains drop x,y position
1096 static void EVENT_DropURLs( HWND hWnd
, XClientMessageEvent
*event
)
1098 unsigned long data_length
;
1099 unsigned long aux_long
, drop_len
= 0;
1100 unsigned char *p_data
= NULL
; /* property data */
1101 char *p_drop
= NULL
;
1112 if (!(GetWindowLongW( hWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
)) return;
1114 TSXGetWindowProperty( event
->display
, DefaultRootWindow(event
->display
),
1115 dndSelection
, 0, 65535, FALSE
,
1116 AnyPropertyType
, &u
.atom_aux
, &u
.i
,
1117 &data_length
, &aux_long
, &p_data
);
1119 WARN("property too large, truncated!\n");
1120 TRACE("urls=%s\n", p_data
);
1122 if( !aux_long
&& p_data
) { /* don't bother if > 64K */
1123 /* calculate length */
1125 next
= strchr(p
, '\n');
1128 if (strncmp(p
,"file:",5) == 0 ) {
1129 INT len
= GetShortPathNameA( p
+5, NULL
, 0 );
1130 if (len
) drop_len
+= len
+ 1;
1135 next
= strchr(p
, '\n');
1141 if( drop_len
&& drop_len
< 65535 ) {
1142 TSXQueryPointer( event
->display
, root_window
, &u
.w_aux
, &u
.w_aux
,
1143 &x
, &y
, &u
.i
, &u
.i
, &u
.i
);
1145 drop_len
+= sizeof(DROPFILES
) + 1;
1146 hDrop
= GlobalAlloc( GMEM_SHARE
, drop_len
);
1147 lpDrop
= (DROPFILES
*) GlobalLock( hDrop
);
1150 WND
*pDropWnd
= WIN_FindWndPtr( hWnd
);
1151 lpDrop
->pFiles
= sizeof(DROPFILES
);
1152 lpDrop
->pt
.x
= (INT
)x
;
1153 lpDrop
->pt
.y
= (INT
)y
;
1155 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
1156 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
1157 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
1158 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
1159 lpDrop
->fWide
= FALSE
;
1160 p_drop
= (char*)(lpDrop
+ 1);
1161 WIN_ReleaseWndPtr(pDropWnd
);
1164 /* create message content */
1167 next
= strchr(p
, '\n');
1170 if (strncmp(p
,"file:",5) == 0 ) {
1171 INT len
= GetShortPathNameA( p
+5, p_drop
, 65535 );
1173 TRACE("drop file %s as %s\n", p
+5, p_drop
);
1176 WARN("can't convert file %s to dos name \n", p
+5);
1179 WARN("unknown mime type %s\n", p
);
1184 next
= strchr(p
, '\n');
1191 GlobalUnlock(hDrop
);
1192 PostMessageA( hWnd
, WM_DROPFILES
, (WPARAM
)hDrop
, 0L );
1195 if( p_data
) TSXFree(p_data
);
1199 /**********************************************************************
1200 * EVENT_ClientMessage
1202 static void EVENT_ClientMessage( HWND hWnd
, XClientMessageEvent
*event
)
1204 if (event
->message_type
!= None
&& event
->format
== 32) {
1205 if (event
->message_type
== wmProtocols
)
1206 handle_wm_protocols_message( hWnd
, event
);
1207 else if (event
->message_type
== dndProtocol
)
1209 /* query window (drag&drop event contains only drag window) */
1211 int root_x
, root_y
, child_x
, child_y
;
1215 XQueryPointer( event
->display
, root_window
, &root
, &child
,
1216 &root_x
, &root_y
, &child_x
, &child_y
, &u
);
1217 if (XFindContext( event
->display
, child
, winContext
, (char **)&hWnd
) != 0) hWnd
= 0;
1218 wine_tsx11_unlock();
1220 if (event
->data
.l
[0] == DndFile
|| event
->data
.l
[0] == DndFiles
)
1221 EVENT_DropFromOffiX(hWnd
, event
);
1222 else if (event
->data
.l
[0] == DndURL
)
1223 EVENT_DropURLs(hWnd
, event
);
1227 /* enable this if you want to see the message */
1228 unsigned char* p_data
= NULL
;
1234 TSXGetWindowProperty( event
->display
, DefaultRootWindow(event
->display
),
1235 dndSelection
, 0, 65535, FALSE
,
1236 AnyPropertyType
, &u
.atom
, &u
.i
,
1237 &u
.l
, &u
.l
, &p_data
);
1238 TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1239 event
->message_type
, event
->data
.l
[0], event
->data
.l
[1],
1240 event
->data
.l
[2], event
->data
.l
[3], event
->data
.l
[4],
1243 TRACE("unrecognized ClientMessage\n" );
1249 /**********************************************************************
1250 * X11DRV_EVENT_SetInputMethod
1252 INPUT_TYPE
X11DRV_EVENT_SetInputMethod(INPUT_TYPE type
)
1254 INPUT_TYPE prev
= current_input_type
;
1256 /* Flag not used yet */
1257 in_transition
= FALSE
;
1258 current_input_type
= type
;
1263 #ifdef HAVE_LIBXXF86DGA2
1264 /**********************************************************************
1265 * X11DRV_EVENT_SetDGAStatus
1267 void X11DRV_EVENT_SetDGAStatus(HWND hwnd
, int event_base
)
1269 if (event_base
< 0) {
1275 DGAMotionEventType
= event_base
+ MotionNotify
;
1276 DGAButtonPressEventType
= event_base
+ ButtonPress
;
1277 DGAButtonReleaseEventType
= event_base
+ ButtonRelease
;
1278 DGAKeyPressEventType
= event_base
+ KeyPress
;
1279 DGAKeyReleaseEventType
= event_base
+ KeyRelease
;