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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #ifdef HAVE_SYS_POLL_H
30 #include <X11/Xatom.h>
31 #include <X11/keysym.h>
33 #include <X11/Xresource.h>
34 #include <X11/Xutil.h>
40 #define NONAMELESSUNION
41 #define NONAMELESSSTRUCT
49 /* avoid conflict with field names in included win32 headers */
51 #include "shlobj.h" /* DROPFILES */
54 #include "wine/debug.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(event);
58 extern BOOL ximInComposeMode;
60 #define DndNotDnd -1 /* OffiX drag&drop */
72 #define DndURL 128 /* KDE drag&drop */
75 static void EVENT_FocusIn( HWND hwnd, XEvent *event );
76 static void EVENT_FocusOut( HWND hwnd, XEvent *event );
77 static void EVENT_PropertyNotify( HWND hwnd, XEvent *event );
78 static void EVENT_ClientMessage( HWND hwnd, XEvent *event );
82 int type; /* event type */
83 x11drv_event_handler handler; /* corresponding handler function */
86 #define MAX_EVENT_HANDLERS 64
88 static struct event_handler handlers[MAX_EVENT_HANDLERS] =
90 /* list must be sorted by event type */
91 { KeyPress, X11DRV_KeyEvent },
92 { KeyRelease, X11DRV_KeyEvent },
93 { ButtonPress, X11DRV_ButtonPress },
94 { ButtonRelease, X11DRV_ButtonRelease },
95 { MotionNotify, X11DRV_MotionNotify },
96 { EnterNotify, X11DRV_EnterNotify },
98 { FocusIn, EVENT_FocusIn },
99 { FocusOut, EVENT_FocusOut },
100 { KeymapNotify, X11DRV_KeymapNotify },
101 { Expose, X11DRV_Expose },
104 /* VisibilityNotify */
106 { DestroyNotify, X11DRV_DestroyNotify },
107 { UnmapNotify, X11DRV_UnmapNotify },
108 { MapNotify, X11DRV_MapNotify },
111 { ConfigureNotify, X11DRV_ConfigureNotify },
112 /* ConfigureRequest */
115 /* CirculateNotify */
116 /* CirculateRequest */
117 { PropertyNotify, EVENT_PropertyNotify },
118 { SelectionClear, X11DRV_SelectionClear },
119 { SelectionRequest, X11DRV_SelectionRequest },
120 /* SelectionNotify */
122 { ClientMessage, EVENT_ClientMessage },
123 { MappingNotify, X11DRV_MappingNotify },
126 static int nb_event_handlers = 19; /* change this if you add handlers above */
129 /* return the name of an X event */
130 static const char *dbgstr_event( int type )
132 static const char * const event_names[] =
134 "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
135 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
136 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
137 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
138 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
139 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
140 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
141 "ClientMessage", "MappingNotify"
144 if (type >= KeyPress && type <= MappingNotify) return event_names[type - KeyPress];
145 return wine_dbg_sprintf( "Extension event %d", type );
149 /***********************************************************************
152 * Find the handler for a given event type. Caller must hold the x11 lock.
154 static inline x11drv_event_handler find_handler( int type )
156 int min = 0, max = nb_event_handlers - 1;
160 int pos = (min + max) / 2;
161 if (handlers[pos].type == type) return handlers[pos].handler;
162 if (handlers[pos].type > type) max = pos - 1;
169 /***********************************************************************
170 * X11DRV_register_event_handler
172 * Register a handler for a given event type.
173 * If already registered, overwrite the previous handler.
175 void X11DRV_register_event_handler( int type, x11drv_event_handler handler )
181 max = nb_event_handlers - 1;
184 int pos = (min + max) / 2;
185 if (handlers[pos].type == type)
187 handlers[pos].handler = handler;
190 if (handlers[pos].type > type) max = pos - 1;
193 /* insert it between max and min */
194 memmove( &handlers[min+1], &handlers[min], (nb_event_handlers - min) * sizeof(handlers[0]) );
195 handlers[min].type = type;
196 handlers[min].handler = handler;
198 assert( nb_event_handlers <= MAX_EVENT_HANDLERS );
201 TRACE("registered handler %p for event %d count %d\n", handler, type, nb_event_handlers );
205 /***********************************************************************
208 static Bool filter_event( Display *display, XEvent *event, char *arg )
210 ULONG_PTR mask = (ULONG_PTR)arg;
212 if ((mask & QS_ALLINPUT) == QS_ALLINPUT) return 1;
220 return (mask & QS_KEY) != 0;
223 return (mask & QS_MOUSEBUTTON) != 0;
227 return (mask & QS_MOUSEMOVE) != 0;
229 return (mask & QS_PAINT) != 0;
234 case ConfigureNotify:
237 return (mask & QS_POSTMESSAGE) != 0;
239 return (mask & QS_SENDMESSAGE) != 0;
244 enum event_merge_action
246 MERGE_DISCARD, /* discard the old event */
247 MERGE_HANDLE, /* handle the old event */
248 MERGE_KEEP /* keep the old event for future merging */
251 /***********************************************************************
254 * Try to merge 2 consecutive events.
256 static enum event_merge_action merge_events( XEvent *prev, XEvent *next )
260 case ConfigureNotify:
263 case ConfigureNotify:
264 if (prev->xany.window == next->xany.window)
266 TRACE( "discarding duplicate ConfigureNotify for window %lx\n", prev->xany.window );
267 return MERGE_DISCARD;
276 if (prev->xany.window == next->xany.window && next->type == MotionNotify)
278 TRACE( "discarding duplicate MotionNotify for window %lx\n", prev->xany.window );
279 return MERGE_DISCARD;
287 /***********************************************************************
290 static inline void call_event_handler( Display *display, XEvent *event )
293 x11drv_event_handler handler;
295 struct x11drv_thread_data *thread_data;
297 if (!(handler = find_handler( event->type )))
299 TRACE( "%s for win %lx, ignoring\n", dbgstr_event( event->type ), event->xany.window );
300 return; /* no handler, ignore it */
303 if (XFindContext( display, event->xany.window, winContext, (char **)&hwnd ) != 0)
304 hwnd = 0; /* not for a registered window */
305 if (!hwnd && event->xany.window == root_window) hwnd = GetDesktopWindow();
307 TRACE( "%s for hwnd/window %p/%lx\n",
308 dbgstr_event( event->type ), hwnd, event->xany.window );
310 thread_data = x11drv_thread_data();
311 prev = thread_data->current_event;
312 thread_data->current_event = event;
313 handler( hwnd, event );
314 thread_data->current_event = prev;
319 /***********************************************************************
322 static int process_events( Display *display, Bool (*filter)(), ULONG_PTR arg )
324 XEvent event, prev_event;
326 enum event_merge_action action = MERGE_DISCARD;
330 while (XCheckIfEvent( display, &event, filter, (char *)arg ))
333 if (XFilterEvent( &event, None )) continue; /* filtered, ignore it */
334 if (prev_event.type) action = merge_events( &prev_event, &event );
337 case MERGE_DISCARD: /* discard prev, keep new */
340 case MERGE_HANDLE: /* handle prev, keep new */
341 call_event_handler( display, &prev_event );
344 case MERGE_KEEP: /* handle new, keep prev for future merging */
345 call_event_handler( display, &event );
349 XFlush( gdi_display );
350 if (prev_event.type) call_event_handler( display, &prev_event );
352 if (count) TRACE( "processed %d events\n", count );
357 /***********************************************************************
358 * MsgWaitForMultipleObjectsEx (X11DRV.@)
360 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
361 DWORD timeout, DWORD mask, DWORD flags )
364 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
368 if (!count && !timeout) return WAIT_TIMEOUT;
369 return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
370 timeout, flags & MWMO_ALERTABLE );
373 if (data->current_event) mask = 0; /* don't process nested events */
375 if (process_events( data->display, filter_event, mask )) ret = count - 1;
376 else if (count || timeout)
378 ret = WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
379 timeout, flags & MWMO_ALERTABLE );
380 if (ret == count - 1) process_events( data->display, filter_event, mask );
382 else ret = WAIT_TIMEOUT;
387 /***********************************************************************
388 * EVENT_x11_time_to_win32_time
390 * Make our timer and the X timer line up as best we can
391 * Pass 0 to retrieve the current adjustment value (times -1)
393 DWORD EVENT_x11_time_to_win32_time(Time time)
395 static DWORD adjust = 0;
396 DWORD now = GetTickCount();
399 if (! adjust && time != 0)
406 /* If we got an event in the 'future', then our clock is clearly wrong.
407 If we got it more than 10000 ms in the future, then it's most likely
408 that the clock has wrapped. */
411 if (ret > now && ((ret - now) < 10000) && time != 0)
422 /*******************************************************************
423 * can_activate_window
425 * Check if we can activate the specified window.
427 static inline BOOL can_activate_window( HWND hwnd )
429 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
430 if (!(style & WS_VISIBLE)) return FALSE;
431 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
432 if (hwnd == GetDesktopWindow()) return FALSE;
433 return !(style & WS_DISABLED);
437 /**********************************************************************
440 static void set_focus( HWND hwnd, Time time )
445 TRACE( "setting foreground window to %p\n", hwnd );
446 SetForegroundWindow( hwnd );
449 if (focus) focus = GetAncestor( focus, GA_ROOT );
450 win = X11DRV_get_whole_window(focus);
454 TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time );
456 XSetInputFocus( thread_display(), win, RevertToParent, time );
462 /**********************************************************************
463 * handle_wm_protocols
465 static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event )
467 Atom protocol = (Atom)event->data.l[0];
469 if (!protocol) return;
471 if (protocol == x11drv_atom(WM_DELETE_WINDOW))
473 /* Ignore the delete window request if the window has been disabled
474 * and we are in managed mode. This is to disallow applications from
475 * being closed by the window manager while in a modal state.
477 if (IsWindowEnabled(hwnd))
481 if (GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE) return;
482 hSysMenu = GetSystemMenu(hwnd, FALSE);
485 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
486 if (state == 0xFFFFFFFF || (state & (MF_DISABLED | MF_GRAYED)))
489 if (GetActiveWindow() != hwnd)
491 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
492 (WPARAM)GetAncestor( hwnd, GA_ROOT ),
493 MAKELONG(HTCLOSE,WM_LBUTTONDOWN) );
496 case MA_NOACTIVATEANDEAT:
497 case MA_ACTIVATEANDEAT:
503 SetActiveWindow(hwnd);
506 WARN( "unknown WM_MOUSEACTIVATE code %d\n", (int) ma );
510 PostMessageW( hwnd, WM_X11DRV_DELETE_WINDOW, 0, 0 );
513 else if (protocol == x11drv_atom(WM_TAKE_FOCUS))
515 Time event_time = (Time)event->data.l[1];
516 HWND last_focus = x11drv_thread_data()->last_focus;
518 TRACE( "got take focus msg for %p, enabled=%d, visible=%d (style %08x), focus=%p, active=%p, fg=%p, last=%p\n",
519 hwnd, IsWindowEnabled(hwnd), IsWindowVisible(hwnd), GetWindowLongW(hwnd, GWL_STYLE),
520 GetFocus(), GetActiveWindow(), GetForegroundWindow(), last_focus );
522 if (can_activate_window(hwnd))
524 /* simulate a mouse click on the caption to find out
525 * whether the window wants to be activated */
526 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
527 (WPARAM)GetAncestor( hwnd, GA_ROOT ),
528 MAKELONG(HTCAPTION,WM_LBUTTONDOWN) );
529 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE)
531 set_focus( hwnd, event_time );
535 /* try to find some other window to give the focus to */
537 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
538 if (!hwnd) hwnd = GetActiveWindow();
539 if (!hwnd) hwnd = last_focus;
540 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
542 else if (protocol == x11drv_atom(_NET_WM_PING))
544 XClientMessageEvent xev;
547 TRACE("NET_WM Ping\n");
549 xev.window = DefaultRootWindow(xev.display);
550 XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
552 /* this line is semi-stolen from gtk2 */
553 TRACE("NET_WM Pong\n");
558 static const char * const focus_details[] =
564 "NotifyNonlinearVirtual",
570 /**********************************************************************
573 static void EVENT_FocusIn( HWND hwnd, XEvent *xev )
575 XFocusChangeEvent *event = &xev->xfocus;
580 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
582 if (event->detail == NotifyPointer) return;
584 if ((xic = X11DRV_get_ic( hwnd )))
590 if (use_take_focus) return; /* ignore FocusIn if we are using take focus */
592 if (!can_activate_window(hwnd))
594 HWND hwnd = GetFocus();
595 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
596 if (!hwnd) hwnd = GetActiveWindow();
597 if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
598 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
600 else SetForegroundWindow( hwnd );
604 /**********************************************************************
607 * Note: only top-level windows get FocusOut events.
609 static void EVENT_FocusOut( HWND hwnd, XEvent *xev )
611 XFocusChangeEvent *event = &xev->xfocus;
619 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
621 if (event->detail == NotifyPointer) return;
622 if (ximInComposeMode) return;
624 x11drv_thread_data()->last_focus = hwnd;
625 if ((xic = X11DRV_get_ic( hwnd )))
628 XUnsetICFocus( xic );
631 if (hwnd != GetForegroundWindow()) return;
632 SendMessageW( hwnd, WM_CANCELMODE, 0, 0 );
634 /* don't reset the foreground window, if the window which is
635 getting the focus is a Wine window */
638 XGetInputFocus( thread_display(), &focus_win, &revert );
641 if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
648 /* Abey : 6-Oct-99. Check again if the focus out window is the
649 Foreground window, because in most cases the messages sent
650 above must have already changed the foreground window, in which
651 case we don't have to change the foreground window to 0 */
652 if (hwnd == GetForegroundWindow())
654 TRACE( "lost focus, setting fg to desktop\n" );
655 SetForegroundWindow( GetDesktopWindow() );
661 /***********************************************************************
662 * get_window_wm_state
664 int get_window_wm_state( Display *display, struct x11drv_win_data *data )
672 int format, ret = -1;
673 unsigned long count, remaining;
676 if (!XGetWindowProperty( display, data->whole_window, x11drv_atom(WM_STATE), 0,
677 sizeof(*state)/sizeof(CARD32), False, x11drv_atom(WM_STATE),
678 &type, &format, &count, &remaining, (unsigned char **)&state ))
680 if (type == x11drv_atom(WM_STATE) && format && count >= sizeof(*state)/(format/8))
689 /***********************************************************************
690 * EVENT_PropertyNotify
692 static void EVENT_PropertyNotify( HWND hwnd, XEvent *xev )
694 XPropertyEvent *event = &xev->xproperty;
695 struct x11drv_win_data *data;
698 if (!(data = X11DRV_get_win_data( hwnd ))) return;
703 if (event->atom == x11drv_atom(WM_STATE))
705 data->wm_state = WithdrawnState;
706 TRACE( "%p/%lx: WM_STATE deleted\n", data->hwnd, data->whole_window );
710 case PropertyNewValue:
711 if (event->atom == x11drv_atom(WM_STATE))
713 int new_state = get_window_wm_state( event->display, data );
714 if (new_state != -1 && new_state != data->wm_state)
716 TRACE( "%p/%lx: new WM_STATE %d\n", data->hwnd, data->whole_window, new_state );
717 data->wm_state = new_state;
725 /* event filter to wait for a WM_STATE change notification on a window */
726 static Bool is_wm_state_notify( Display *display, XEvent *event, XPointer arg )
728 if (event->xany.window != (Window)arg) return 0;
729 return (event->type == DestroyNotify ||
730 (event->type == PropertyNotify && event->xproperty.atom == x11drv_atom(WM_STATE)));
733 /***********************************************************************
734 * wait_for_withdrawn_state
736 void wait_for_withdrawn_state( Display *display, struct x11drv_win_data *data, BOOL set )
738 DWORD end = GetTickCount() + 2000;
740 if (!data->managed) return;
742 TRACE( "waiting for window %p/%lx to become %swithdrawn\n",
743 data->hwnd, data->whole_window, set ? "" : "not " );
745 while (data->whole_window && ((data->wm_state == WithdrawnState) == !set))
747 if (!process_events( display, is_wm_state_notify, data->whole_window ))
750 int timeout = end - GetTickCount();
752 pfd.fd = ConnectionNumber(display);
754 if (timeout <= 0 || poll( &pfd, 1, timeout ) != 1)
756 FIXME( "window %p/%lx wait timed out\n", data->hwnd, data->whole_window );
761 TRACE( "window %p/%lx state now %d\n", data->hwnd, data->whole_window, data->wm_state );
765 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
769 if (!IsWindowEnabled(hQueryWnd)) return 0;
771 GetWindowRect(hQueryWnd, &tempRect);
773 if(!PtInRect(&tempRect, *lpPt)) return 0;
775 if (!IsIconic( hQueryWnd ))
778 ScreenToClient( hQueryWnd, &pt );
779 GetClientRect( hQueryWnd, &tempRect );
781 if (PtInRect( &tempRect, pt))
783 HWND ret = ChildWindowFromPointEx( hQueryWnd, pt, CWP_SKIPINVISIBLE|CWP_SKIPDISABLED );
784 if (ret && ret != hQueryWnd)
786 ret = find_drop_window( ret, lpPt );
792 if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
794 ScreenToClient(hQueryWnd, lpPt);
799 /**********************************************************************
800 * EVENT_DropFromOffix
802 * don't know if it still works (last Changelog is from 96/11/04)
804 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
806 struct x11drv_win_data *data;
807 unsigned long data_length;
808 unsigned long aux_long;
809 unsigned char* p_data = NULL;
813 Window win, w_aux_root, w_aux_child;
816 win = X11DRV_get_whole_window(hWnd);
818 XQueryPointer( event->display, win, &w_aux_root, &w_aux_child,
819 &x, &y, &dummy, &dummy, (unsigned int*)&aux_long);
820 x += virtual_screen_rect.left;
821 y += virtual_screen_rect.top;
824 if (!(data = X11DRV_get_win_data( hWnd ))) return;
826 /* find out drop point and drop window */
827 if( x < 0 || y < 0 ||
828 x > (data->whole_rect.right - data->whole_rect.left) ||
829 y > (data->whole_rect.bottom - data->whole_rect.top) )
831 bAccept = GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES;
838 HWND hwndDrop = find_drop_window( hWnd, &pt );
852 if (!bAccept) return;
855 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
856 x11drv_atom(DndSelection), 0, 65535, FALSE,
857 AnyPropertyType, &atom_aux, &dummy,
858 &data_length, &aux_long, &p_data);
861 if( !aux_long && p_data) /* don't bother if > 64K */
863 char *p = (char *)p_data;
867 while( *p ) /* calculate buffer size */
869 INT len = GetShortPathNameA( p, NULL, 0 );
870 if (len) aux_long += len + 1;
873 if( aux_long && aux_long < 65535 )
878 aux_long += sizeof(DROPFILES) + 1;
879 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
880 lpDrop = (DROPFILES*)GlobalLock( hDrop );
884 lpDrop->pFiles = sizeof(DROPFILES);
888 lpDrop->fWide = FALSE;
889 p_drop = (char *)(lpDrop + 1);
893 if (GetShortPathNameA( p, p_drop, aux_long - (p_drop - (char *)lpDrop) ))
894 p_drop += strlen( p_drop ) + 1;
898 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
903 if( p_data ) XFree(p_data);
907 /**********************************************************************
910 * drop items are separated by \n
911 * each item is prefixed by its mime type
913 * event->data.l[3], event->data.l[4] contains drop x,y position
915 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
917 struct x11drv_win_data *win_data;
918 unsigned long data_length;
919 unsigned long aux_long, drop_len = 0;
920 unsigned char *p_data = NULL; /* property data */
933 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
936 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
937 x11drv_atom(DndSelection), 0, 65535, FALSE,
938 AnyPropertyType, &u.atom_aux, &u.i,
939 &data_length, &aux_long, &p_data);
942 WARN("property too large, truncated!\n");
943 TRACE("urls=%s\n", p_data);
945 if( !aux_long && p_data) { /* don't bother if > 64K */
946 /* calculate length */
948 next = strchr(p, '\n');
951 if (strncmp(p,"file:",5) == 0 ) {
952 INT len = GetShortPathNameA( p+5, NULL, 0 );
953 if (len) drop_len += len + 1;
958 next = strchr(p, '\n');
964 if( drop_len && drop_len < 65535 ) {
966 XQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
967 &x, &y, &u.i, &u.i, &u.u);
968 x += virtual_screen_rect.left;
969 y += virtual_screen_rect.top;
972 drop_len += sizeof(DROPFILES) + 1;
973 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
974 lpDrop = (DROPFILES *) GlobalLock( hDrop );
976 if( lpDrop && (win_data = X11DRV_get_win_data( hWnd )))
978 lpDrop->pFiles = sizeof(DROPFILES);
982 ( x < (win_data->client_rect.left - win_data->whole_rect.left) ||
983 y < (win_data->client_rect.top - win_data->whole_rect.top) ||
984 x > (win_data->client_rect.right - win_data->whole_rect.left) ||
985 y > (win_data->client_rect.bottom - win_data->whole_rect.top) );
986 lpDrop->fWide = FALSE;
987 p_drop = (char*)(lpDrop + 1);
990 /* create message content */
993 next = strchr(p, '\n');
996 if (strncmp(p,"file:",5) == 0 ) {
997 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
999 TRACE("drop file %s as %s\n", p+5, p_drop);
1002 WARN("can't convert file %s to dos name\n", p+5);
1005 WARN("unknown mime type %s\n", p);
1010 next = strchr(p, '\n');
1017 GlobalUnlock(hDrop);
1018 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1022 if( p_data ) XFree(p_data);
1023 wine_tsx11_unlock();
1027 /**********************************************************************
1028 * handle_dnd_protocol
1030 static void handle_dnd_protocol( HWND hwnd, XClientMessageEvent *event )
1033 int root_x, root_y, child_x, child_y;
1036 /* query window (drag&drop event contains only drag window) */
1038 XQueryPointer( event->display, root_window, &root, &child,
1039 &root_x, &root_y, &child_x, &child_y, &u);
1040 if (XFindContext( event->display, child, winContext, (char **)&hwnd ) != 0) hwnd = 0;
1041 wine_tsx11_unlock();
1043 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
1044 EVENT_DropFromOffiX(hwnd, event);
1045 else if (event->data.l[0] == DndURL)
1046 EVENT_DropURLs(hwnd, event);
1050 struct client_message_handler
1052 int atom; /* protocol atom */
1053 void (*handler)(HWND, XClientMessageEvent *); /* corresponding handler function */
1056 static const struct client_message_handler client_messages[] =
1058 { XATOM_WM_PROTOCOLS, handle_wm_protocols },
1059 { XATOM_DndProtocol, handle_dnd_protocol },
1060 { XATOM_XdndEnter, X11DRV_XDND_EnterEvent },
1061 { XATOM_XdndPosition, X11DRV_XDND_PositionEvent },
1062 { XATOM_XdndDrop, X11DRV_XDND_DropEvent },
1063 { XATOM_XdndLeave, X11DRV_XDND_LeaveEvent }
1067 /**********************************************************************
1068 * EVENT_ClientMessage
1070 static void EVENT_ClientMessage( HWND hwnd, XEvent *xev )
1072 XClientMessageEvent *event = &xev->xclient;
1077 if (event->format != 32)
1079 WARN( "Don't know how to handle format %d\n", event->format );
1083 for (i = 0; i < sizeof(client_messages)/sizeof(client_messages[0]); i++)
1085 if (event->message_type == X11DRV_Atoms[client_messages[i].atom - FIRST_XATOM])
1087 client_messages[i].handler( hwnd, event );
1091 TRACE( "no handler found for %ld\n", event->message_type );
1095 /**********************************************************************
1096 * X11DRV_WindowMessage (X11DRV.@)
1098 LRESULT X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
1102 case WM_X11DRV_ACQUIRE_SELECTION:
1103 return X11DRV_AcquireClipboard( hwnd );
1104 case WM_X11DRV_DELETE_WINDOW:
1105 return SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
1106 case WM_X11DRV_SET_WIN_FORMAT:
1107 return X11DRV_set_win_format( hwnd, (XID)wp );
1108 case WM_X11DRV_RESIZE_DESKTOP:
1109 X11DRV_resize_desktop( LOWORD(lp), HIWORD(lp) );
1112 FIXME( "got window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, wp, lp );
1118 /***********************************************************************
1119 * X11DRV_SendInput (X11DRV.@)
1121 UINT X11DRV_SendInput( UINT count, LPINPUT inputs, int size )
1125 for (i = 0; i < count; i++, inputs++)
1127 switch(inputs->type)
1130 X11DRV_send_mouse_input( 0, inputs->u.mi.dwFlags, inputs->u.mi.dx, inputs->u.mi.dy,
1131 inputs->u.mi.mouseData, inputs->u.mi.time,
1132 inputs->u.mi.dwExtraInfo, LLMHF_INJECTED );
1134 case INPUT_KEYBOARD:
1135 X11DRV_send_keyboard_input( inputs->u.ki.wVk, inputs->u.ki.wScan, inputs->u.ki.dwFlags,
1136 inputs->u.ki.time, inputs->u.ki.dwExtraInfo, LLKHF_INJECTED );
1138 case INPUT_HARDWARE:
1139 FIXME( "INPUT_HARDWARE not supported\n" );