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
22 #define COM_NO_WINDOWS_H
25 #include <X11/Xatom.h>
26 #include <X11/keysym.h>
28 #include <X11/Xresource.h>
29 #include <X11/Xutil.h>
30 #ifdef HAVE_LIBXXF86DGA2
31 #include <X11/extensions/xf86dga.h>
38 #define NONAMELESSUNION
39 #define NONAMELESSSTRUCT
44 #include "shlobj.h" /* DROPFILES */
50 #include "wine/debug.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(event);
54 extern BOOL ximInComposeMode;
56 #define DndNotDnd -1 /* OffiX drag&drop */
68 #define DndURL 128 /* KDE drag&drop */
71 static void EVENT_FocusIn( HWND hwnd, XEvent *event );
72 static void EVENT_FocusOut( HWND hwnd, XEvent *event );
73 static void EVENT_PropertyNotify( HWND hwnd, XEvent *event );
74 static void EVENT_ClientMessage( HWND hwnd, XEvent *event );
78 int type; /* event type */
79 x11drv_event_handler handler; /* corresponding handler function */
82 #define MAX_EVENT_HANDLERS 64
84 static struct event_handler handlers[MAX_EVENT_HANDLERS] =
86 /* list must be sorted by event type */
87 { KeyPress, X11DRV_KeyEvent },
88 { KeyRelease, X11DRV_KeyEvent },
89 { ButtonPress, X11DRV_ButtonPress },
90 { ButtonRelease, X11DRV_ButtonRelease },
91 { MotionNotify, X11DRV_MotionNotify },
92 { EnterNotify, X11DRV_EnterNotify },
94 { FocusIn, EVENT_FocusIn },
95 { FocusOut, EVENT_FocusOut },
96 { KeymapNotify, X11DRV_KeymapNotify },
97 { Expose, X11DRV_Expose },
100 /* VisibilityNotify */
103 { UnmapNotify, X11DRV_UnmapNotify },
104 { MapNotify, X11DRV_MapNotify },
107 { ConfigureNotify, X11DRV_ConfigureNotify },
108 /* ConfigureRequest */
111 /* CirculateNotify */
112 /* CirculateRequest */
113 { PropertyNotify, EVENT_PropertyNotify },
114 { SelectionClear, X11DRV_SelectionClear },
115 { SelectionRequest, X11DRV_SelectionRequest },
116 /* SelectionNotify */
118 { ClientMessage, EVENT_ClientMessage },
119 { MappingNotify, X11DRV_MappingNotify },
122 static int nb_event_handlers = 18; /* change this if you add handlers above */
125 /* return the name of an X event */
126 static const char *dbgstr_event( int type )
128 static const char * const event_names[] =
130 "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
131 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
132 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
133 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
134 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
135 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
136 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
137 "ClientMessage", "MappingNotify"
140 if (type >= KeyPress && type <= MappingNotify) return event_names[type - KeyPress];
141 return wine_dbg_sprintf( "Extension event %d", type );
145 /***********************************************************************
148 * Find the handler for a given event type. Caller must hold the x11 lock.
150 static inline x11drv_event_handler find_handler( int type )
152 int min = 0, max = nb_event_handlers - 1;
156 int pos = (min + max) / 2;
157 if (handlers[pos].type == type) return handlers[pos].handler;
158 if (handlers[pos].type > type) max = pos - 1;
165 /***********************************************************************
166 * X11DRV_register_event_handler
168 * Register a handler for a given event type.
169 * If already registered, overwrite the previous handler.
171 void X11DRV_register_event_handler( int type, x11drv_event_handler handler )
177 max = nb_event_handlers - 1;
180 int pos = (min + max) / 2;
181 if (handlers[pos].type == type)
183 handlers[pos].handler = handler;
186 if (handlers[pos].type > type) max = pos - 1;
189 /* insert it between max and min */
190 memmove( &handlers[min+1], &handlers[min], (nb_event_handlers - min) * sizeof(handlers[0]) );
191 handlers[min].type = type;
192 handlers[min].handler = handler;
194 assert( nb_event_handlers <= MAX_EVENT_HANDLERS );
197 TRACE("registered handler %p for event %d count %d\n", handler, type, nb_event_handlers );
201 /***********************************************************************
204 static Bool filter_event( Display *display, XEvent *event, char *arg )
206 ULONG_PTR mask = (ULONG_PTR)arg;
208 if ((mask & QS_ALLINPUT) == QS_ALLINPUT) return 1;
216 return (mask & QS_KEY) != 0;
219 return (mask & QS_MOUSEBUTTON) != 0;
223 return (mask & QS_MOUSEMOVE) != 0;
225 return (mask & QS_PAINT) != 0;
230 case ConfigureNotify:
233 return (mask & QS_POSTMESSAGE) != 0;
235 return (mask & QS_SENDMESSAGE) != 0;
240 /***********************************************************************
243 static int process_events( Display *display, ULONG_PTR mask )
248 x11drv_event_handler handler;
251 while (XCheckIfEvent( display, &event, filter_event, (char *)mask ))
254 if (XFilterEvent( &event, None )) continue; /* filtered, ignore it */
256 if (!(handler = find_handler( event.type )))
258 TRACE( "%s, ignoring\n", dbgstr_event( event.type ));
259 continue; /* no handler, ignore it */
262 if (XFindContext( display, event.xany.window, winContext, (char **)&hwnd ) != 0)
263 hwnd = 0; /* not for a registered window */
264 if (!hwnd && event.xany.window == root_window) hwnd = GetDesktopWindow();
267 TRACE( "%s for hwnd/window %p/%lx\n",
268 dbgstr_event( event.type ), hwnd, event.xany.window );
269 handler( hwnd, &event );
272 XFlush( gdi_display );
274 if (count) TRACE( "processed %d events\n", count );
279 /***********************************************************************
280 * MsgWaitForMultipleObjectsEx (X11DRV.@)
282 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
283 DWORD timeout, DWORD mask, DWORD flags )
286 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
288 if (!data || data->process_event_count)
290 if (!count && !timeout) return WAIT_TIMEOUT;
291 return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
292 timeout, flags & MWMO_ALERTABLE );
295 /* check whether only server queue handle was passed in */
296 if (count < 2) flags &= ~MWMO_WAITALL;
298 data->process_event_count++;
300 if (process_events( data->display, mask )) ret = count;
301 else if (count || timeout)
303 HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1]; /* FIXME! */
305 for (i = 0; i < count; i++) new_handles[i] = handles[i];
306 new_handles[count] = data->display_fd;
308 ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
309 timeout, flags & MWMO_ALERTABLE );
310 if (ret == count) process_events( data->display, mask );
312 else ret = WAIT_TIMEOUT;
314 data->process_event_count--;
318 /***********************************************************************
319 * EVENT_x11_time_to_win32_time
321 * Make our timer and the X timer line up as best we can
322 * Pass 0 to retrieve the current adjustment value (times -1)
324 DWORD EVENT_x11_time_to_win32_time(Time time)
326 static DWORD adjust = 0;
327 DWORD now = GetTickCount();
330 if (! adjust && time != 0)
337 /* If we got an event in the 'future', then our clock is clearly wrong.
338 If we got it more than 10000 ms in the future, then it's most likely
339 that the clock has wrapped. */
342 if (ret > now && ((ret - now) < 10000) && time != 0)
353 /*******************************************************************
354 * can_activate_window
356 * Check if we can activate the specified window.
358 inline static BOOL can_activate_window( HWND hwnd )
360 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
361 if (!(style & WS_VISIBLE)) return FALSE;
362 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
363 return !(style & WS_DISABLED);
367 /**********************************************************************
370 static void set_focus( HWND hwnd, Time time )
375 TRACE( "setting foreground window to %p\n", hwnd );
376 SetForegroundWindow( hwnd );
379 if (focus) focus = GetAncestor( focus, GA_ROOT );
380 win = X11DRV_get_whole_window(focus);
384 TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time );
386 XSetInputFocus( thread_display(), win, RevertToParent, time );
392 /**********************************************************************
393 * handle_wm_protocols
395 static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event )
397 Atom protocol = (Atom)event->data.l[0];
399 if (!protocol) return;
401 if (protocol == x11drv_atom(WM_DELETE_WINDOW))
403 /* Ignore the delete window request if the window has been disabled
404 * and we are in managed mode. This is to disallow applications from
405 * being closed by the window manager while in a modal state.
407 if (IsWindowEnabled(hwnd))
411 if (GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE) return;
412 hSysMenu = GetSystemMenu(hwnd, FALSE);
415 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
416 if (state == 0xFFFFFFFF || (state & (MF_DISABLED | MF_GRAYED)))
419 PostMessageW( hwnd, WM_X11DRV_DELETE_WINDOW, 0, 0 );
422 else if (protocol == x11drv_atom(WM_TAKE_FOCUS))
424 Time event_time = (Time)event->data.l[1];
425 HWND last_focus = x11drv_thread_data()->last_focus;
427 TRACE( "got take focus msg for %p, enabled=%d, visible=%d (style %08lx), focus=%p, active=%p, fg=%p, last=%p\n",
428 hwnd, IsWindowEnabled(hwnd), IsWindowVisible(hwnd), GetWindowLongW(hwnd, GWL_STYLE),
429 GetFocus(), GetActiveWindow(), GetForegroundWindow(), last_focus );
431 if (can_activate_window(hwnd))
433 /* simulate a mouse click on the caption to find out
434 * whether the window wants to be activated */
435 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
436 (WPARAM)GetAncestor( hwnd, GA_ROOT ),
437 MAKELONG(HTCAPTION,WM_LBUTTONDOWN) );
438 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) set_focus( hwnd, event_time );
439 else TRACE( "not setting focus to %p (%lx), ma=%ld\n", hwnd, event->window, ma );
444 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
445 if (!hwnd) hwnd = GetActiveWindow();
446 if (!hwnd) hwnd = last_focus;
447 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
450 else if (protocol == x11drv_atom(_NET_WM_PING))
452 XClientMessageEvent xev;
455 TRACE("NET_WM Ping\n");
457 xev.window = DefaultRootWindow(xev.display);
458 XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
460 /* this line is semi-stolen from gtk2 */
461 TRACE("NET_WM Pong\n");
466 static const char * const focus_details[] =
472 "NotifyNonlinearVirtual",
478 /**********************************************************************
481 static void EVENT_FocusIn( HWND hwnd, XEvent *xev )
483 XFocusChangeEvent *event = &xev->xfocus;
488 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
490 if (event->detail == NotifyPointer) return;
492 if ((xic = X11DRV_get_ic( hwnd )))
498 if (use_take_focus) return; /* ignore FocusIn if we are using take focus */
500 if (!can_activate_window(hwnd))
502 HWND hwnd = GetFocus();
503 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
504 if (!hwnd) hwnd = GetActiveWindow();
505 if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
506 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
508 else SetForegroundWindow( hwnd );
512 /**********************************************************************
515 * Note: only top-level windows get FocusOut events.
517 static void EVENT_FocusOut( HWND hwnd, XEvent *xev )
519 XFocusChangeEvent *event = &xev->xfocus;
527 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
529 if (event->detail == NotifyPointer) return;
530 if (ximInComposeMode) return;
532 x11drv_thread_data()->last_focus = hwnd;
533 if ((xic = X11DRV_get_ic( hwnd )))
536 XUnsetICFocus( xic );
539 if (hwnd != GetForegroundWindow()) return;
540 SendMessageW( hwnd, WM_CANCELMODE, 0, 0 );
542 /* don't reset the foreground window, if the window which is
543 getting the focus is a Wine window */
546 XGetInputFocus( thread_display(), &focus_win, &revert );
549 if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
556 /* Abey : 6-Oct-99. Check again if the focus out window is the
557 Foreground window, because in most cases the messages sent
558 above must have already changed the foreground window, in which
559 case we don't have to change the foreground window to 0 */
560 if (hwnd == GetForegroundWindow())
562 TRACE( "lost focus, setting fg to 0\n" );
563 SetForegroundWindow( 0 );
569 /***********************************************************************
570 * EVENT_PropertyNotify
571 * We use this to release resources like Pixmaps when a selection
572 * client no longer needs them.
574 static void EVENT_PropertyNotify( HWND hwnd, XEvent *xev )
576 XPropertyEvent *event = &xev->xproperty;
577 /* Check if we have any resources to free */
578 TRACE("Received PropertyNotify event:\n");
584 TRACE("\tPropertyDelete for atom %ld on window %ld\n",
585 event->atom, (long)event->window);
589 case PropertyNewValue:
591 TRACE("\tPropertyNewValue for atom %ld on window %ld\n\n",
592 event->atom, (long)event->window);
601 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
605 if (!IsWindowEnabled(hQueryWnd)) return 0;
607 GetWindowRect(hQueryWnd, &tempRect);
609 if(!PtInRect(&tempRect, *lpPt)) return 0;
611 if (!IsIconic( hQueryWnd ))
614 ScreenToClient( hQueryWnd, &pt );
615 GetClientRect( hQueryWnd, &tempRect );
617 if (PtInRect( &tempRect, pt))
619 HWND ret = ChildWindowFromPointEx( hQueryWnd, pt, CWP_SKIPINVISIBLE|CWP_SKIPDISABLED );
620 if (ret && ret != hQueryWnd)
622 ret = find_drop_window( ret, lpPt );
628 if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
630 ScreenToClient(hQueryWnd, lpPt);
635 /**********************************************************************
636 * EVENT_DropFromOffix
638 * don't know if it still works (last Changlog is from 96/11/04)
640 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
642 unsigned long data_length;
643 unsigned long aux_long;
644 unsigned char* p_data = NULL;
648 Window win, w_aux_root, w_aux_child;
652 win = X11DRV_get_whole_window(hWnd);
654 XQueryPointer( event->display, win, &w_aux_root, &w_aux_child,
655 &x, &y, &dummy, &dummy, (unsigned int*)&aux_long);
658 pWnd = WIN_GetPtr(hWnd);
660 /* find out drop point and drop window */
661 if( x < 0 || y < 0 ||
662 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
663 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
665 bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES;
672 HWND hwndDrop = find_drop_window( hWnd, &pt );
685 WIN_ReleasePtr(pWnd);
687 if (!bAccept) return;
690 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
691 x11drv_atom(DndSelection), 0, 65535, FALSE,
692 AnyPropertyType, &atom_aux, &dummy,
693 &data_length, &aux_long, &p_data);
696 if( !aux_long && p_data) /* don't bother if > 64K */
698 char *p = (char *)p_data;
702 while( *p ) /* calculate buffer size */
704 INT len = GetShortPathNameA( p, NULL, 0 );
705 if (len) aux_long += len + 1;
708 if( aux_long && aux_long < 65535 )
713 aux_long += sizeof(DROPFILES) + 1;
714 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
715 lpDrop = (DROPFILES*)GlobalLock( hDrop );
719 WND *pDropWnd = WIN_GetPtr( hScope );
720 lpDrop->pFiles = sizeof(DROPFILES);
724 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
725 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
726 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
727 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
728 lpDrop->fWide = FALSE;
729 WIN_ReleasePtr(pDropWnd);
730 p_drop = (char *)(lpDrop + 1);
734 if (GetShortPathNameA( p, p_drop, aux_long - (p_drop - (char *)lpDrop) ))
735 p_drop += strlen( p_drop ) + 1;
739 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
744 if( p_data ) XFree(p_data);
748 /**********************************************************************
751 * drop items are separated by \n
752 * each item is prefixed by its mime type
754 * event->data.l[3], event->data.l[4] contains drop x,y position
756 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
758 unsigned long data_length;
759 unsigned long aux_long, drop_len = 0;
760 unsigned char *p_data = NULL; /* property data */
773 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
776 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
777 x11drv_atom(DndSelection), 0, 65535, FALSE,
778 AnyPropertyType, &u.atom_aux, &u.i,
779 &data_length, &aux_long, &p_data);
782 WARN("property too large, truncated!\n");
783 TRACE("urls=%s\n", p_data);
785 if( !aux_long && p_data) { /* don't bother if > 64K */
786 /* calculate length */
788 next = strchr(p, '\n');
791 if (strncmp(p,"file:",5) == 0 ) {
792 INT len = GetShortPathNameA( p+5, NULL, 0 );
793 if (len) drop_len += len + 1;
798 next = strchr(p, '\n');
804 if( drop_len && drop_len < 65535 ) {
806 XQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
807 &x, &y, &u.i, &u.i, &u.u);
810 drop_len += sizeof(DROPFILES) + 1;
811 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
812 lpDrop = (DROPFILES *) GlobalLock( hDrop );
815 WND *pDropWnd = WIN_GetPtr( hWnd );
816 lpDrop->pFiles = sizeof(DROPFILES);
817 lpDrop->pt.x = (INT)x;
818 lpDrop->pt.y = (INT)y;
820 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
821 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
822 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
823 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
824 lpDrop->fWide = FALSE;
825 p_drop = (char*)(lpDrop + 1);
826 WIN_ReleasePtr(pDropWnd);
829 /* create message content */
832 next = strchr(p, '\n');
835 if (strncmp(p,"file:",5) == 0 ) {
836 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
838 TRACE("drop file %s as %s\n", p+5, p_drop);
841 WARN("can't convert file %s to dos name\n", p+5);
844 WARN("unknown mime type %s\n", p);
849 next = strchr(p, '\n');
857 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
861 if( p_data ) XFree(p_data);
866 /**********************************************************************
867 * handle_dnd_protocol
869 static void handle_dnd_protocol( HWND hwnd, XClientMessageEvent *event )
872 int root_x, root_y, child_x, child_y;
875 /* query window (drag&drop event contains only drag window) */
877 XQueryPointer( event->display, root_window, &root, &child,
878 &root_x, &root_y, &child_x, &child_y, &u);
879 if (XFindContext( event->display, child, winContext, (char **)&hwnd ) != 0) hwnd = 0;
882 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
883 EVENT_DropFromOffiX(hwnd, event);
884 else if (event->data.l[0] == DndURL)
885 EVENT_DropURLs(hwnd, event);
889 struct client_message_handler
891 int atom; /* protocol atom */
892 void (*handler)(HWND, XClientMessageEvent *); /* corresponding handler function */
895 static const struct client_message_handler client_messages[] =
897 { XATOM_WM_PROTOCOLS, handle_wm_protocols },
898 { XATOM_DndProtocol, handle_dnd_protocol },
899 { XATOM_XdndEnter, X11DRV_XDND_EnterEvent },
900 { XATOM_XdndPosition, X11DRV_XDND_PositionEvent },
901 { XATOM_XdndDrop, X11DRV_XDND_DropEvent },
902 { XATOM_XdndLeave, X11DRV_XDND_LeaveEvent }
906 /**********************************************************************
907 * EVENT_ClientMessage
909 static void EVENT_ClientMessage( HWND hwnd, XEvent *xev )
911 XClientMessageEvent *event = &xev->xclient;
916 if (event->format != 32)
918 WARN( "Don't know how to handle format %d\n", event->format );
922 for (i = 0; i < sizeof(client_messages)/sizeof(client_messages[0]); i++)
924 if (event->message_type == X11DRV_Atoms[client_messages[i].atom - FIRST_XATOM])
926 client_messages[i].handler( hwnd, event );
930 TRACE( "no handler found for %ld\n", event->message_type );
934 /**********************************************************************
935 * X11DRV_WindowMessage (X11DRV.@)
937 LRESULT X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
941 case WM_X11DRV_ACQUIRE_SELECTION:
942 return X11DRV_AcquireClipboard( hwnd );
943 case WM_X11DRV_DELETE_WINDOW:
944 return SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
946 FIXME( "got window msg %x hwnd %p wp %x lp %lx\n", msg, hwnd, wp, lp );
952 /***********************************************************************
953 * X11DRV_SendInput (X11DRV.@)
955 UINT X11DRV_SendInput( UINT count, LPINPUT inputs, int size )
959 for (i = 0; i < count; i++, inputs++)
964 X11DRV_send_mouse_input( 0, inputs->u.mi.dwFlags, inputs->u.mi.dx, inputs->u.mi.dy,
965 inputs->u.mi.mouseData, inputs->u.mi.time,
966 inputs->u.mi.dwExtraInfo, LLMHF_INJECTED );
969 X11DRV_send_keyboard_input( inputs->u.ki.wVk, inputs->u.ki.wScan, inputs->u.ki.dwFlags,
970 inputs->u.ki.time, inputs->u.ki.dwExtraInfo, LLKHF_INJECTED );
973 FIXME( "INPUT_HARDWARE not supported\n" );