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>
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;
215 return (mask & QS_KEY) != 0;
218 return (mask & QS_MOUSEBUTTON) != 0;
222 return (mask & QS_MOUSEMOVE) != 0;
224 return (mask & QS_PAINT) != 0;
226 return (mask & QS_POSTMESSAGE) != 0;
228 return (mask & QS_SENDMESSAGE) != 0;
233 /***********************************************************************
236 static int process_events( Display *display, ULONG_PTR mask )
241 x11drv_event_handler handler;
244 while (XCheckIfEvent( display, &event, filter_event, (char *)mask ))
247 if (XFilterEvent( &event, None )) continue; /* filtered, ignore it */
249 if (!(handler = find_handler( event.type )))
251 TRACE( "%s, ignoring\n", dbgstr_event( event.type ));
252 continue; /* no handler, ignore it */
255 if (XFindContext( display, event.xany.window, winContext, (char **)&hwnd ) != 0)
256 hwnd = 0; /* not for a registered window */
257 if (!hwnd && event.xany.window == root_window) hwnd = GetDesktopWindow();
260 TRACE( "%s for hwnd/window %p/%lx\n",
261 dbgstr_event( event.type ), hwnd, event.xany.window );
262 handler( hwnd, &event );
266 if (count) TRACE( "processed %d events\n", count );
271 /***********************************************************************
272 * MsgWaitForMultipleObjectsEx (X11DRV.@)
274 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
275 DWORD timeout, DWORD mask, DWORD flags )
278 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
280 if (!data || data->process_event_count)
282 if (!count && !timeout) return WAIT_TIMEOUT;
283 return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
284 timeout, flags & MWMO_ALERTABLE );
287 /* check whether only server queue handle was passed in */
288 if (count < 2) flags &= ~MWMO_WAITALL;
291 XFlush( gdi_display );
292 XFlush( data->display );
295 data->process_event_count++;
297 if (process_events( data->display, mask )) ret = count;
298 else if (count || timeout)
300 HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1]; /* FIXME! */
302 for (i = 0; i < count; i++) new_handles[i] = handles[i];
303 new_handles[count] = data->display_fd;
305 ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
306 timeout, flags & MWMO_ALERTABLE );
307 if (ret == count) process_events( data->display, mask );
309 else ret = WAIT_TIMEOUT;
311 data->process_event_count--;
315 /***********************************************************************
316 * EVENT_x11_time_to_win32_time
318 * Make our timer and the X timer line up as best we can
319 * Pass 0 to retrieve the current adjustment value (times -1)
321 DWORD EVENT_x11_time_to_win32_time(Time time)
323 static DWORD adjust = 0;
324 DWORD now = GetTickCount();
327 if (! adjust && time != 0)
334 /* If we got an event in the 'future', then our clock is clearly wrong.
335 If we got it more than 10000 ms in the future, then it's most likely
336 that the clock has wrapped. */
339 if (ret > now && ((ret - now) < 10000) && time != 0)
350 /*******************************************************************
351 * can_activate_window
353 * Check if we can activate the specified window.
355 inline static BOOL can_activate_window( HWND hwnd )
357 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
358 if (!(style & WS_VISIBLE)) return FALSE;
359 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
360 return !(style & WS_DISABLED);
364 /**********************************************************************
367 static void set_focus( HWND hwnd, Time time )
372 TRACE( "setting foreground window to %p\n", hwnd );
373 SetForegroundWindow( hwnd );
376 if (focus) focus = GetAncestor( focus, GA_ROOT );
377 win = X11DRV_get_whole_window(focus);
381 TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time );
383 XSetInputFocus( thread_display(), win, RevertToParent, time );
389 /**********************************************************************
390 * handle_wm_protocols
392 static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event )
394 Atom protocol = (Atom)event->data.l[0];
396 if (!protocol) return;
398 if (protocol == x11drv_atom(WM_DELETE_WINDOW))
400 /* Ignore the delete window request if the window has been disabled
401 * and we are in managed mode. This is to disallow applications from
402 * being closed by the window manager while in a modal state.
404 if (IsWindowEnabled(hwnd))
408 if (GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE) return;
409 hSysMenu = GetSystemMenu(hwnd, FALSE);
412 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
413 if (state == 0xFFFFFFFF || (state & (MF_DISABLED | MF_GRAYED)))
416 PostMessageW( hwnd, WM_X11DRV_DELETE_WINDOW, 0, 0 );
419 else if (protocol == x11drv_atom(WM_TAKE_FOCUS))
421 Time event_time = (Time)event->data.l[1];
422 HWND last_focus = x11drv_thread_data()->last_focus;
424 TRACE( "got take focus msg for %p, enabled=%d, focus=%p, active=%p, fg=%p, last=%p\n",
425 hwnd, IsWindowEnabled(hwnd), GetFocus(), GetActiveWindow(),
426 GetForegroundWindow(), last_focus );
428 if (can_activate_window(hwnd))
430 /* simulate a mouse click on the caption to find out
431 * whether the window wants to be activated */
432 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
433 (WPARAM)GetAncestor( hwnd, GA_ROOT ),
434 MAKELONG(HTCAPTION,WM_LBUTTONDOWN) );
435 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) set_focus( hwnd, event_time );
436 else TRACE( "not setting focus to %p (%lx), ma=%ld\n", hwnd, event->window, ma );
441 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
442 if (!hwnd) hwnd = GetActiveWindow();
443 if (!hwnd) hwnd = last_focus;
444 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
447 else if (protocol == x11drv_atom(_NET_WM_PING))
449 XClientMessageEvent xev;
452 TRACE("NET_WM Ping\n");
453 xev.window = DefaultRootWindow(xev.display);
454 XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
455 /* this line is semi-stolen from gtk2 */
456 TRACE("NET_WM Pong\n");
461 static const char * const focus_details[] =
467 "NotifyNonlinearVirtual",
473 /**********************************************************************
476 static void EVENT_FocusIn( HWND hwnd, XEvent *xev )
478 XFocusChangeEvent *event = &xev->xfocus;
483 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
485 if (event->detail == NotifyPointer) return;
487 if ((xic = X11DRV_get_ic( hwnd )))
493 if (use_take_focus) return; /* ignore FocusIn if we are using take focus */
495 if (!can_activate_window(hwnd))
497 HWND hwnd = GetFocus();
498 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
499 if (!hwnd) hwnd = GetActiveWindow();
500 if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
501 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
503 else SetForegroundWindow( hwnd );
507 /**********************************************************************
510 * Note: only top-level windows get FocusOut events.
512 static void EVENT_FocusOut( HWND hwnd, XEvent *xev )
514 XFocusChangeEvent *event = &xev->xfocus;
522 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
524 if (event->detail == NotifyPointer) return;
525 if (ximInComposeMode) return;
527 x11drv_thread_data()->last_focus = hwnd;
528 if ((xic = X11DRV_get_ic( hwnd )))
531 XUnsetICFocus( xic );
534 if (hwnd != GetForegroundWindow()) return;
535 SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
537 /* don't reset the foreground window, if the window which is
538 getting the focus is a Wine window */
541 XGetInputFocus( thread_display(), &focus_win, &revert );
544 if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
551 /* Abey : 6-Oct-99. Check again if the focus out window is the
552 Foreground window, because in most cases the messages sent
553 above must have already changed the foreground window, in which
554 case we don't have to change the foreground window to 0 */
555 if (hwnd == GetForegroundWindow())
557 TRACE( "lost focus, setting fg to 0\n" );
558 SetForegroundWindow( 0 );
564 /***********************************************************************
565 * EVENT_PropertyNotify
566 * We use this to release resources like Pixmaps when a selection
567 * client no longer needs them.
569 static void EVENT_PropertyNotify( HWND hwnd, XEvent *xev )
571 XPropertyEvent *event = &xev->xproperty;
572 /* Check if we have any resources to free */
573 TRACE("Received PropertyNotify event:\n");
579 TRACE("\tPropertyDelete for atom %ld on window %ld\n",
580 event->atom, (long)event->window);
584 case PropertyNewValue:
586 TRACE("\tPropertyNewValue for atom %ld on window %ld\n\n",
587 event->atom, (long)event->window);
596 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
600 if (!IsWindowEnabled(hQueryWnd)) return 0;
602 GetWindowRect(hQueryWnd, &tempRect);
604 if(!PtInRect(&tempRect, *lpPt)) return 0;
606 if (!IsIconic( hQueryWnd ))
609 ScreenToClient( hQueryWnd, &pt );
610 GetClientRect( hQueryWnd, &tempRect );
612 if (PtInRect( &tempRect, pt))
614 HWND ret = ChildWindowFromPointEx( hQueryWnd, pt, CWP_SKIPINVISIBLE|CWP_SKIPDISABLED );
615 if (ret && ret != hQueryWnd)
617 ret = find_drop_window( ret, lpPt );
623 if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
625 ScreenToClient(hQueryWnd, lpPt);
630 /**********************************************************************
631 * EVENT_DropFromOffix
633 * don't know if it still works (last Changlog is from 96/11/04)
635 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
637 unsigned long data_length;
638 unsigned long aux_long;
639 unsigned char* p_data = NULL;
643 Window win, w_aux_root, w_aux_child;
647 win = X11DRV_get_whole_window(hWnd);
649 XQueryPointer( event->display, win, &w_aux_root, &w_aux_child,
650 &x, &y, &dummy, &dummy, (unsigned int*)&aux_long);
653 pWnd = WIN_GetPtr(hWnd);
655 /* find out drop point and drop window */
656 if( x < 0 || y < 0 ||
657 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
658 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
660 bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES;
667 HWND hwndDrop = find_drop_window( hWnd, &pt );
680 WIN_ReleasePtr(pWnd);
682 if (!bAccept) return;
685 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
686 x11drv_atom(DndSelection), 0, 65535, FALSE,
687 AnyPropertyType, &atom_aux, &dummy,
688 &data_length, &aux_long, &p_data);
691 if( !aux_long && p_data) /* don't bother if > 64K */
693 char *p = (char *)p_data;
697 while( *p ) /* calculate buffer size */
699 INT len = GetShortPathNameA( p, NULL, 0 );
700 if (len) aux_long += len + 1;
703 if( aux_long && aux_long < 65535 )
708 aux_long += sizeof(DROPFILES) + 1;
709 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
710 lpDrop = (DROPFILES*)GlobalLock( hDrop );
714 WND *pDropWnd = WIN_GetPtr( hScope );
715 lpDrop->pFiles = sizeof(DROPFILES);
719 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
720 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
721 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
722 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
723 lpDrop->fWide = FALSE;
724 WIN_ReleasePtr(pDropWnd);
725 p_drop = (char *)(lpDrop + 1);
729 if (GetShortPathNameA( p, p_drop, aux_long - (p_drop - (char *)lpDrop) ))
730 p_drop += strlen( p_drop ) + 1;
734 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
739 if( p_data ) XFree(p_data);
743 /**********************************************************************
746 * drop items are separated by \n
747 * each item is prefixed by its mime type
749 * event->data.l[3], event->data.l[4] contains drop x,y position
751 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
753 unsigned long data_length;
754 unsigned long aux_long, drop_len = 0;
755 unsigned char *p_data = NULL; /* property data */
768 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
771 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
772 x11drv_atom(DndSelection), 0, 65535, FALSE,
773 AnyPropertyType, &u.atom_aux, &u.i,
774 &data_length, &aux_long, &p_data);
777 WARN("property too large, truncated!\n");
778 TRACE("urls=%s\n", p_data);
780 if( !aux_long && p_data) { /* don't bother if > 64K */
781 /* calculate length */
783 next = strchr(p, '\n');
786 if (strncmp(p,"file:",5) == 0 ) {
787 INT len = GetShortPathNameA( p+5, NULL, 0 );
788 if (len) drop_len += len + 1;
793 next = strchr(p, '\n');
799 if( drop_len && drop_len < 65535 ) {
801 XQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
802 &x, &y, &u.i, &u.i, &u.u);
805 drop_len += sizeof(DROPFILES) + 1;
806 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
807 lpDrop = (DROPFILES *) GlobalLock( hDrop );
810 WND *pDropWnd = WIN_GetPtr( hWnd );
811 lpDrop->pFiles = sizeof(DROPFILES);
812 lpDrop->pt.x = (INT)x;
813 lpDrop->pt.y = (INT)y;
815 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
816 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
817 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
818 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
819 lpDrop->fWide = FALSE;
820 p_drop = (char*)(lpDrop + 1);
821 WIN_ReleasePtr(pDropWnd);
824 /* create message content */
827 next = strchr(p, '\n');
830 if (strncmp(p,"file:",5) == 0 ) {
831 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
833 TRACE("drop file %s as %s\n", p+5, p_drop);
836 WARN("can't convert file %s to dos name\n", p+5);
839 WARN("unknown mime type %s\n", p);
844 next = strchr(p, '\n');
852 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
856 if( p_data ) XFree(p_data);
861 /**********************************************************************
862 * handle_dnd_protocol
864 static void handle_dnd_protocol( HWND hwnd, XClientMessageEvent *event )
867 int root_x, root_y, child_x, child_y;
870 /* query window (drag&drop event contains only drag window) */
872 XQueryPointer( event->display, root_window, &root, &child,
873 &root_x, &root_y, &child_x, &child_y, &u);
874 if (XFindContext( event->display, child, winContext, (char **)&hwnd ) != 0) hwnd = 0;
877 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
878 EVENT_DropFromOffiX(hwnd, event);
879 else if (event->data.l[0] == DndURL)
880 EVENT_DropURLs(hwnd, event);
884 struct client_message_handler
886 int atom; /* protocol atom */
887 void (*handler)(HWND, XClientMessageEvent *); /* corresponding handler function */
890 static const struct client_message_handler client_messages[] =
892 { XATOM_WM_PROTOCOLS, handle_wm_protocols },
893 { XATOM_DndProtocol, handle_dnd_protocol },
894 { XATOM_XdndEnter, X11DRV_XDND_EnterEvent },
895 { XATOM_XdndPosition, X11DRV_XDND_PositionEvent },
896 { XATOM_XdndDrop, X11DRV_XDND_DropEvent },
897 { XATOM_XdndLeave, X11DRV_XDND_LeaveEvent }
901 /**********************************************************************
902 * EVENT_ClientMessage
904 static void EVENT_ClientMessage( HWND hwnd, XEvent *xev )
906 XClientMessageEvent *event = &xev->xclient;
911 if (event->format != 32)
913 WARN( "Don't know how to handle format %d\n", event->format );
917 for (i = 0; i < sizeof(client_messages)/sizeof(client_messages[0]); i++)
919 if (event->message_type == X11DRV_Atoms[client_messages[i].atom - FIRST_XATOM])
921 client_messages[i].handler( hwnd, event );
925 TRACE( "no handler found for %ld\n", event->message_type );
929 /**********************************************************************
930 * X11DRV_WindowMessage (X11DRV.@)
932 LRESULT X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
936 case WM_X11DRV_ACQUIRE_SELECTION:
937 X11DRV_AcquireClipboard( hwnd );
939 case WM_X11DRV_DELETE_WINDOW:
940 return SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
942 FIXME( "got window msg %x hwnd %p wp %x lp %lx\n", msg, hwnd, wp, lp );
948 /***********************************************************************
949 * X11DRV_SendInput (X11DRV.@)
951 UINT X11DRV_SendInput( UINT count, LPINPUT inputs, int size )
955 for (i = 0; i < count; i++, inputs++)
960 X11DRV_send_mouse_input( 0, inputs->u.mi.dwFlags, inputs->u.mi.dx, inputs->u.mi.dy,
961 inputs->u.mi.mouseData, inputs->u.mi.time,
962 inputs->u.mi.dwExtraInfo, LLMHF_INJECTED );
965 X11DRV_send_keyboard_input( inputs->u.ki.wVk, inputs->u.ki.wScan, inputs->u.ki.dwFlags,
966 inputs->u.ki.time, inputs->u.ki.dwExtraInfo, LLKHF_INJECTED );
969 FIXME( "INPUT_HARDWARE not supported\n" );