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
24 #include <X11/Xatom.h>
25 #include <X11/keysym.h>
27 #include <X11/Xresource.h>
28 #include <X11/Xutil.h>
34 #define NONAMELESSUNION
35 #define NONAMELESSSTRUCT
44 /* avoid conflict with field names in included win32 headers */
46 #include "shlobj.h" /* DROPFILES */
49 #include "wine/debug.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(event);
53 extern BOOL ximInComposeMode;
55 #define DndNotDnd -1 /* OffiX drag&drop */
67 #define DndURL 128 /* KDE drag&drop */
70 static void EVENT_FocusIn( HWND hwnd, XEvent *event );
71 static void EVENT_FocusOut( HWND hwnd, XEvent *event );
72 static void EVENT_PropertyNotify( HWND hwnd, XEvent *event );
73 static void EVENT_ClientMessage( HWND hwnd, XEvent *event );
77 int type; /* event type */
78 x11drv_event_handler handler; /* corresponding handler function */
81 #define MAX_EVENT_HANDLERS 64
83 static struct event_handler handlers[MAX_EVENT_HANDLERS] =
85 /* list must be sorted by event type */
86 { KeyPress, X11DRV_KeyEvent },
87 { KeyRelease, X11DRV_KeyEvent },
88 { ButtonPress, X11DRV_ButtonPress },
89 { ButtonRelease, X11DRV_ButtonRelease },
90 { MotionNotify, X11DRV_MotionNotify },
91 { EnterNotify, X11DRV_EnterNotify },
93 { FocusIn, EVENT_FocusIn },
94 { FocusOut, EVENT_FocusOut },
95 { KeymapNotify, X11DRV_KeymapNotify },
96 { Expose, X11DRV_Expose },
99 /* VisibilityNotify */
102 { UnmapNotify, X11DRV_UnmapNotify },
103 { MapNotify, X11DRV_MapNotify },
106 { ConfigureNotify, X11DRV_ConfigureNotify },
107 /* ConfigureRequest */
110 /* CirculateNotify */
111 /* CirculateRequest */
112 { PropertyNotify, EVENT_PropertyNotify },
113 { SelectionClear, X11DRV_SelectionClear },
114 { SelectionRequest, X11DRV_SelectionRequest },
115 /* SelectionNotify */
117 { ClientMessage, EVENT_ClientMessage },
118 { MappingNotify, X11DRV_MappingNotify },
121 static int nb_event_handlers = 18; /* change this if you add handlers above */
124 /* return the name of an X event */
125 static const char *dbgstr_event( int type )
127 static const char * const event_names[] =
129 "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
130 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
131 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
132 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
133 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
134 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
135 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
136 "ClientMessage", "MappingNotify"
139 if (type >= KeyPress && type <= MappingNotify) return event_names[type - KeyPress];
140 return wine_dbg_sprintf( "Extension event %d", type );
144 /***********************************************************************
147 * Find the handler for a given event type. Caller must hold the x11 lock.
149 static inline x11drv_event_handler find_handler( int type )
151 int min = 0, max = nb_event_handlers - 1;
155 int pos = (min + max) / 2;
156 if (handlers[pos].type == type) return handlers[pos].handler;
157 if (handlers[pos].type > type) max = pos - 1;
164 /***********************************************************************
165 * X11DRV_register_event_handler
167 * Register a handler for a given event type.
168 * If already registered, overwrite the previous handler.
170 void X11DRV_register_event_handler( int type, x11drv_event_handler handler )
176 max = nb_event_handlers - 1;
179 int pos = (min + max) / 2;
180 if (handlers[pos].type == type)
182 handlers[pos].handler = handler;
185 if (handlers[pos].type > type) max = pos - 1;
188 /* insert it between max and min */
189 memmove( &handlers[min+1], &handlers[min], (nb_event_handlers - min) * sizeof(handlers[0]) );
190 handlers[min].type = type;
191 handlers[min].handler = handler;
193 assert( nb_event_handlers <= MAX_EVENT_HANDLERS );
196 TRACE("registered handler %p for event %d count %d\n", handler, type, nb_event_handlers );
200 /***********************************************************************
203 static Bool filter_event( Display *display, XEvent *event, char *arg )
205 ULONG_PTR mask = (ULONG_PTR)arg;
207 if ((mask & QS_ALLINPUT) == QS_ALLINPUT) return 1;
215 return (mask & QS_KEY) != 0;
218 return (mask & QS_MOUSEBUTTON) != 0;
222 return (mask & QS_MOUSEMOVE) != 0;
224 return (mask & QS_PAINT) != 0;
229 case ConfigureNotify:
232 return (mask & QS_POSTMESSAGE) != 0;
234 return (mask & QS_SENDMESSAGE) != 0;
239 /***********************************************************************
242 static int process_events( Display *display, ULONG_PTR mask )
247 x11drv_event_handler handler;
250 while (XCheckIfEvent( display, &event, filter_event, (char *)mask ))
253 if (XFilterEvent( &event, None )) continue; /* filtered, ignore it */
255 if (!(handler = find_handler( event.type )))
257 TRACE( "%s, ignoring\n", dbgstr_event( event.type ));
258 continue; /* no handler, ignore it */
261 if (XFindContext( display, event.xany.window, winContext, (char **)&hwnd ) != 0)
262 hwnd = 0; /* not for a registered window */
263 if (!hwnd && event.xany.window == root_window) hwnd = GetDesktopWindow();
266 TRACE( "%s for hwnd/window %p/%lx\n",
267 dbgstr_event( event.type ), hwnd, event.xany.window );
268 handler( hwnd, &event );
271 XFlush( gdi_display );
273 if (count) TRACE( "processed %d events\n", count );
278 /***********************************************************************
279 * MsgWaitForMultipleObjectsEx (X11DRV.@)
281 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
282 DWORD timeout, DWORD mask, DWORD flags )
285 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
289 if (!count && !timeout) return WAIT_TIMEOUT;
290 return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
291 timeout, flags & MWMO_ALERTABLE );
294 if (data->process_event_count) mask = 0; /* don't process nested events */
296 data->process_event_count++;
298 if (process_events( data->display, mask )) ret = count - 1;
299 else if (count || timeout)
301 ret = WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
302 timeout, flags & MWMO_ALERTABLE );
303 if (ret == count - 1) process_events( data->display, mask );
305 else ret = WAIT_TIMEOUT;
307 data->process_event_count--;
311 /***********************************************************************
312 * EVENT_x11_time_to_win32_time
314 * Make our timer and the X timer line up as best we can
315 * Pass 0 to retrieve the current adjustment value (times -1)
317 DWORD EVENT_x11_time_to_win32_time(Time time)
319 static DWORD adjust = 0;
320 DWORD now = GetTickCount();
323 if (! adjust && time != 0)
330 /* If we got an event in the 'future', then our clock is clearly wrong.
331 If we got it more than 10000 ms in the future, then it's most likely
332 that the clock has wrapped. */
335 if (ret > now && ((ret - now) < 10000) && time != 0)
346 /*******************************************************************
347 * can_activate_window
349 * Check if we can activate the specified window.
351 static inline BOOL can_activate_window( HWND hwnd )
353 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
354 if (!(style & WS_VISIBLE)) return FALSE;
355 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
356 if (hwnd == GetDesktopWindow()) return FALSE;
357 return !(style & WS_DISABLED);
361 /**********************************************************************
364 static void set_focus( HWND hwnd, Time time )
369 TRACE( "setting foreground window to %p\n", hwnd );
370 SetForegroundWindow( hwnd );
373 if (focus) focus = GetAncestor( focus, GA_ROOT );
374 win = X11DRV_get_whole_window(focus);
378 TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time );
380 XSetInputFocus( thread_display(), win, RevertToParent, time );
386 /**********************************************************************
387 * handle_wm_protocols
389 static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event )
391 Atom protocol = (Atom)event->data.l[0];
393 if (!protocol) return;
395 if (protocol == x11drv_atom(WM_DELETE_WINDOW))
397 /* Ignore the delete window request if the window has been disabled
398 * and we are in managed mode. This is to disallow applications from
399 * being closed by the window manager while in a modal state.
401 if (IsWindowEnabled(hwnd))
405 if (GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE) return;
406 hSysMenu = GetSystemMenu(hwnd, FALSE);
409 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
410 if (state == 0xFFFFFFFF || (state & (MF_DISABLED | MF_GRAYED)))
413 if (GetActiveWindow() != hwnd)
415 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
416 (WPARAM)GetAncestor( hwnd, GA_ROOT ),
417 MAKELONG(HTCLOSE,WM_LBUTTONDOWN) );
420 case MA_NOACTIVATEANDEAT:
421 case MA_ACTIVATEANDEAT:
427 SetActiveWindow(hwnd);
430 WARN( "unknown WM_MOUSEACTIVATE code %d\n", (int) ma );
434 PostMessageW( hwnd, WM_X11DRV_DELETE_WINDOW, 0, 0 );
437 else if (protocol == x11drv_atom(WM_TAKE_FOCUS))
439 Time event_time = (Time)event->data.l[1];
440 HWND last_focus = x11drv_thread_data()->last_focus;
442 TRACE( "got take focus msg for %p, enabled=%d, visible=%d (style %08x), focus=%p, active=%p, fg=%p, last=%p\n",
443 hwnd, IsWindowEnabled(hwnd), IsWindowVisible(hwnd), GetWindowLongW(hwnd, GWL_STYLE),
444 GetFocus(), GetActiveWindow(), GetForegroundWindow(), last_focus );
446 if (can_activate_window(hwnd))
448 /* simulate a mouse click on the caption to find out
449 * whether the window wants to be activated */
450 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
451 (WPARAM)GetAncestor( hwnd, GA_ROOT ),
452 MAKELONG(HTCAPTION,WM_LBUTTONDOWN) );
453 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE)
455 set_focus( hwnd, event_time );
459 /* try to find some other window to give the focus to */
461 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
462 if (!hwnd) hwnd = GetActiveWindow();
463 if (!hwnd) hwnd = last_focus;
464 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
466 else if (protocol == x11drv_atom(_NET_WM_PING))
468 XClientMessageEvent xev;
471 TRACE("NET_WM Ping\n");
473 xev.window = DefaultRootWindow(xev.display);
474 XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
476 /* this line is semi-stolen from gtk2 */
477 TRACE("NET_WM Pong\n");
482 static const char * const focus_details[] =
488 "NotifyNonlinearVirtual",
494 /**********************************************************************
497 static void EVENT_FocusIn( HWND hwnd, XEvent *xev )
499 XFocusChangeEvent *event = &xev->xfocus;
504 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
506 if (event->detail == NotifyPointer) return;
508 if ((xic = X11DRV_get_ic( hwnd )))
514 if (use_take_focus) return; /* ignore FocusIn if we are using take focus */
516 if (!can_activate_window(hwnd))
518 HWND hwnd = GetFocus();
519 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
520 if (!hwnd) hwnd = GetActiveWindow();
521 if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
522 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
524 else SetForegroundWindow( hwnd );
528 /**********************************************************************
531 * Note: only top-level windows get FocusOut events.
533 static void EVENT_FocusOut( HWND hwnd, XEvent *xev )
535 XFocusChangeEvent *event = &xev->xfocus;
543 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
545 if (event->detail == NotifyPointer) return;
546 if (ximInComposeMode) return;
548 x11drv_thread_data()->last_focus = hwnd;
549 if ((xic = X11DRV_get_ic( hwnd )))
552 XUnsetICFocus( xic );
555 if (hwnd != GetForegroundWindow()) return;
556 SendMessageW( hwnd, WM_CANCELMODE, 0, 0 );
558 /* don't reset the foreground window, if the window which is
559 getting the focus is a Wine window */
562 XGetInputFocus( thread_display(), &focus_win, &revert );
565 if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
572 /* Abey : 6-Oct-99. Check again if the focus out window is the
573 Foreground window, because in most cases the messages sent
574 above must have already changed the foreground window, in which
575 case we don't have to change the foreground window to 0 */
576 if (hwnd == GetForegroundWindow())
578 TRACE( "lost focus, setting fg to desktop\n" );
579 SetForegroundWindow( GetDesktopWindow() );
585 /***********************************************************************
586 * EVENT_PropertyNotify
587 * We use this to release resources like Pixmaps when a selection
588 * client no longer needs them.
590 static void EVENT_PropertyNotify( HWND hwnd, XEvent *xev )
592 XPropertyEvent *event = &xev->xproperty;
593 /* Check if we have any resources to free */
594 TRACE("Received PropertyNotify event:\n");
600 TRACE("\tPropertyDelete for atom %ld on window %ld\n",
601 event->atom, (long)event->window);
605 case PropertyNewValue:
607 TRACE("\tPropertyNewValue for atom %ld on window %ld\n\n",
608 event->atom, (long)event->window);
617 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
621 if (!IsWindowEnabled(hQueryWnd)) return 0;
623 GetWindowRect(hQueryWnd, &tempRect);
625 if(!PtInRect(&tempRect, *lpPt)) return 0;
627 if (!IsIconic( hQueryWnd ))
630 ScreenToClient( hQueryWnd, &pt );
631 GetClientRect( hQueryWnd, &tempRect );
633 if (PtInRect( &tempRect, pt))
635 HWND ret = ChildWindowFromPointEx( hQueryWnd, pt, CWP_SKIPINVISIBLE|CWP_SKIPDISABLED );
636 if (ret && ret != hQueryWnd)
638 ret = find_drop_window( ret, lpPt );
644 if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
646 ScreenToClient(hQueryWnd, lpPt);
651 /**********************************************************************
652 * EVENT_DropFromOffix
654 * don't know if it still works (last Changelog is from 96/11/04)
656 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
658 unsigned long data_length;
659 unsigned long aux_long;
660 unsigned char* p_data = NULL;
664 Window win, w_aux_root, w_aux_child;
668 win = X11DRV_get_whole_window(hWnd);
670 XQueryPointer( event->display, win, &w_aux_root, &w_aux_child,
671 &x, &y, &dummy, &dummy, (unsigned int*)&aux_long);
672 x += virtual_screen_rect.left;
673 y += virtual_screen_rect.top;
676 pWnd = WIN_GetPtr(hWnd);
678 /* find out drop point and drop window */
679 if( x < 0 || y < 0 ||
680 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
681 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
683 bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES;
690 HWND hwndDrop = find_drop_window( hWnd, &pt );
703 WIN_ReleasePtr(pWnd);
705 if (!bAccept) return;
708 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
709 x11drv_atom(DndSelection), 0, 65535, FALSE,
710 AnyPropertyType, &atom_aux, &dummy,
711 &data_length, &aux_long, &p_data);
714 if( !aux_long && p_data) /* don't bother if > 64K */
716 char *p = (char *)p_data;
720 while( *p ) /* calculate buffer size */
722 INT len = GetShortPathNameA( p, NULL, 0 );
723 if (len) aux_long += len + 1;
726 if( aux_long && aux_long < 65535 )
731 aux_long += sizeof(DROPFILES) + 1;
732 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
733 lpDrop = (DROPFILES*)GlobalLock( hDrop );
737 WND *pDropWnd = WIN_GetPtr( hScope );
738 lpDrop->pFiles = sizeof(DROPFILES);
742 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
743 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
744 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
745 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
746 lpDrop->fWide = FALSE;
747 WIN_ReleasePtr(pDropWnd);
748 p_drop = (char *)(lpDrop + 1);
752 if (GetShortPathNameA( p, p_drop, aux_long - (p_drop - (char *)lpDrop) ))
753 p_drop += strlen( p_drop ) + 1;
757 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
762 if( p_data ) XFree(p_data);
766 /**********************************************************************
769 * drop items are separated by \n
770 * each item is prefixed by its mime type
772 * event->data.l[3], event->data.l[4] contains drop x,y position
774 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
776 unsigned long data_length;
777 unsigned long aux_long, drop_len = 0;
778 unsigned char *p_data = NULL; /* property data */
791 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
794 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
795 x11drv_atom(DndSelection), 0, 65535, FALSE,
796 AnyPropertyType, &u.atom_aux, &u.i,
797 &data_length, &aux_long, &p_data);
800 WARN("property too large, truncated!\n");
801 TRACE("urls=%s\n", p_data);
803 if( !aux_long && p_data) { /* don't bother if > 64K */
804 /* calculate length */
806 next = strchr(p, '\n');
809 if (strncmp(p,"file:",5) == 0 ) {
810 INT len = GetShortPathNameA( p+5, NULL, 0 );
811 if (len) drop_len += len + 1;
816 next = strchr(p, '\n');
822 if( drop_len && drop_len < 65535 ) {
824 XQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
825 &x, &y, &u.i, &u.i, &u.u);
826 x += virtual_screen_rect.left;
827 y += virtual_screen_rect.top;
830 drop_len += sizeof(DROPFILES) + 1;
831 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
832 lpDrop = (DROPFILES *) GlobalLock( hDrop );
835 WND *pDropWnd = WIN_GetPtr( hWnd );
836 lpDrop->pFiles = sizeof(DROPFILES);
837 lpDrop->pt.x = (INT)x;
838 lpDrop->pt.y = (INT)y;
840 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
841 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
842 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
843 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
844 lpDrop->fWide = FALSE;
845 p_drop = (char*)(lpDrop + 1);
846 WIN_ReleasePtr(pDropWnd);
849 /* create message content */
852 next = strchr(p, '\n');
855 if (strncmp(p,"file:",5) == 0 ) {
856 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
858 TRACE("drop file %s as %s\n", p+5, p_drop);
861 WARN("can't convert file %s to dos name\n", p+5);
864 WARN("unknown mime type %s\n", p);
869 next = strchr(p, '\n');
877 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
881 if( p_data ) XFree(p_data);
886 /**********************************************************************
887 * handle_dnd_protocol
889 static void handle_dnd_protocol( HWND hwnd, XClientMessageEvent *event )
892 int root_x, root_y, child_x, child_y;
895 /* query window (drag&drop event contains only drag window) */
897 XQueryPointer( event->display, root_window, &root, &child,
898 &root_x, &root_y, &child_x, &child_y, &u);
899 if (XFindContext( event->display, child, winContext, (char **)&hwnd ) != 0) hwnd = 0;
902 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
903 EVENT_DropFromOffiX(hwnd, event);
904 else if (event->data.l[0] == DndURL)
905 EVENT_DropURLs(hwnd, event);
909 struct client_message_handler
911 int atom; /* protocol atom */
912 void (*handler)(HWND, XClientMessageEvent *); /* corresponding handler function */
915 static const struct client_message_handler client_messages[] =
917 { XATOM_WM_PROTOCOLS, handle_wm_protocols },
918 { XATOM_DndProtocol, handle_dnd_protocol },
919 { XATOM_XdndEnter, X11DRV_XDND_EnterEvent },
920 { XATOM_XdndPosition, X11DRV_XDND_PositionEvent },
921 { XATOM_XdndDrop, X11DRV_XDND_DropEvent },
922 { XATOM_XdndLeave, X11DRV_XDND_LeaveEvent }
926 /**********************************************************************
927 * EVENT_ClientMessage
929 static void EVENT_ClientMessage( HWND hwnd, XEvent *xev )
931 XClientMessageEvent *event = &xev->xclient;
936 if (event->format != 32)
938 WARN( "Don't know how to handle format %d\n", event->format );
942 for (i = 0; i < sizeof(client_messages)/sizeof(client_messages[0]); i++)
944 if (event->message_type == X11DRV_Atoms[client_messages[i].atom - FIRST_XATOM])
946 client_messages[i].handler( hwnd, event );
950 TRACE( "no handler found for %ld\n", event->message_type );
954 /**********************************************************************
955 * X11DRV_WindowMessage (X11DRV.@)
957 LRESULT X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
961 case WM_X11DRV_ACQUIRE_SELECTION:
962 return X11DRV_AcquireClipboard( hwnd );
963 case WM_X11DRV_DELETE_WINDOW:
964 return SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
965 case WM_X11DRV_SET_WIN_FORMAT:
966 return X11DRV_set_win_format( hwnd, (XID)wp );
967 case WM_X11DRV_RESIZE_DESKTOP:
968 X11DRV_resize_desktop( LOWORD(lp), HIWORD(lp) );
971 FIXME( "got window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, wp, lp );
977 /***********************************************************************
978 * X11DRV_SendInput (X11DRV.@)
980 UINT X11DRV_SendInput( UINT count, LPINPUT inputs, int size )
984 for (i = 0; i < count; i++, inputs++)
989 X11DRV_send_mouse_input( 0, inputs->u.mi.dwFlags, inputs->u.mi.dx, inputs->u.mi.dy,
990 inputs->u.mi.mouseData, inputs->u.mi.time,
991 inputs->u.mi.dwExtraInfo, LLMHF_INJECTED );
994 X11DRV_send_keyboard_input( inputs->u.ki.wVk, inputs->u.ki.wScan, inputs->u.ki.dwFlags,
995 inputs->u.ki.time, inputs->u.ki.dwExtraInfo, LLKHF_INJECTED );
998 FIXME( "INPUT_HARDWARE not supported\n" );