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>
35 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
41 #include "shlobj.h" /* DROPFILES */
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(event);
51 extern BOOL ximInComposeMode;
53 #define DndNotDnd -1 /* OffiX drag&drop */
65 #define DndURL 128 /* KDE drag&drop */
68 static void EVENT_FocusIn( HWND hwnd, XEvent *event );
69 static void EVENT_FocusOut( HWND hwnd, XEvent *event );
70 static void EVENT_PropertyNotify( HWND hwnd, XEvent *event );
71 static void EVENT_ClientMessage( HWND hwnd, XEvent *event );
75 int type; /* event type */
76 x11drv_event_handler handler; /* corresponding handler function */
79 #define MAX_EVENT_HANDLERS 64
81 static struct event_handler handlers[MAX_EVENT_HANDLERS] =
83 /* list must be sorted by event type */
84 { KeyPress, X11DRV_KeyEvent },
85 { KeyRelease, X11DRV_KeyEvent },
86 { ButtonPress, X11DRV_ButtonPress },
87 { ButtonRelease, X11DRV_ButtonRelease },
88 { MotionNotify, X11DRV_MotionNotify },
89 { EnterNotify, X11DRV_EnterNotify },
91 { FocusIn, EVENT_FocusIn },
92 { FocusOut, EVENT_FocusOut },
93 { KeymapNotify, X11DRV_KeymapNotify },
94 { Expose, X11DRV_Expose },
97 /* VisibilityNotify */
100 { UnmapNotify, X11DRV_UnmapNotify },
101 { MapNotify, X11DRV_MapNotify },
104 { ConfigureNotify, X11DRV_ConfigureNotify },
105 /* ConfigureRequest */
108 /* CirculateNotify */
109 /* CirculateRequest */
110 { PropertyNotify, EVENT_PropertyNotify },
111 { SelectionClear, X11DRV_SelectionClear },
112 { SelectionRequest, X11DRV_SelectionRequest },
113 /* SelectionNotify */
115 { ClientMessage, EVENT_ClientMessage },
116 { MappingNotify, X11DRV_MappingNotify },
119 static int nb_event_handlers = 18; /* change this if you add handlers above */
122 /* return the name of an X event */
123 static const char *dbgstr_event( int type )
125 static const char * const event_names[] =
127 "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
128 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
129 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
130 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
131 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
132 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
133 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
134 "ClientMessage", "MappingNotify"
137 if (type >= KeyPress && type <= MappingNotify) return event_names[type - KeyPress];
138 return wine_dbg_sprintf( "Extension event %d", type );
142 /***********************************************************************
145 * Find the handler for a given event type. Caller must hold the x11 lock.
147 static inline x11drv_event_handler find_handler( int type )
149 int min = 0, max = nb_event_handlers - 1;
153 int pos = (min + max) / 2;
154 if (handlers[pos].type == type) return handlers[pos].handler;
155 if (handlers[pos].type > type) max = pos - 1;
162 /***********************************************************************
163 * X11DRV_register_event_handler
165 * Register a handler for a given event type.
166 * If already registered, overwrite the previous handler.
168 void X11DRV_register_event_handler( int type, x11drv_event_handler handler )
174 max = nb_event_handlers - 1;
177 int pos = (min + max) / 2;
178 if (handlers[pos].type == type)
180 handlers[pos].handler = handler;
183 if (handlers[pos].type > type) max = pos - 1;
186 /* insert it between max and min */
187 memmove( &handlers[min+1], &handlers[min], (nb_event_handlers - min) * sizeof(handlers[0]) );
188 handlers[min].type = type;
189 handlers[min].handler = handler;
191 assert( nb_event_handlers <= MAX_EVENT_HANDLERS );
194 TRACE("registered handler %p for event %d count %d\n", handler, type, nb_event_handlers );
198 /***********************************************************************
201 static Bool filter_event( Display *display, XEvent *event, char *arg )
203 ULONG_PTR mask = (ULONG_PTR)arg;
205 if ((mask & QS_ALLINPUT) == QS_ALLINPUT) return 1;
213 return (mask & QS_KEY) != 0;
216 return (mask & QS_MOUSEBUTTON) != 0;
220 return (mask & QS_MOUSEMOVE) != 0;
222 return (mask & QS_PAINT) != 0;
227 case ConfigureNotify:
230 return (mask & QS_POSTMESSAGE) != 0;
232 return (mask & QS_SENDMESSAGE) != 0;
237 /***********************************************************************
240 static int process_events( Display *display, ULONG_PTR mask )
245 x11drv_event_handler handler;
248 while (XCheckIfEvent( display, &event, filter_event, (char *)mask ))
251 if (XFilterEvent( &event, None )) continue; /* filtered, ignore it */
253 if (!(handler = find_handler( event.type )))
255 TRACE( "%s, ignoring\n", dbgstr_event( event.type ));
256 continue; /* no handler, ignore it */
259 if (XFindContext( display, event.xany.window, winContext, (char **)&hwnd ) != 0)
260 hwnd = 0; /* not for a registered window */
261 if (!hwnd && event.xany.window == root_window) hwnd = GetDesktopWindow();
264 TRACE( "%s for hwnd/window %p/%lx\n",
265 dbgstr_event( event.type ), hwnd, event.xany.window );
266 handler( hwnd, &event );
269 XFlush( gdi_display );
271 if (count) TRACE( "processed %d events\n", count );
276 /***********************************************************************
277 * MsgWaitForMultipleObjectsEx (X11DRV.@)
279 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
280 DWORD timeout, DWORD mask, DWORD flags )
283 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
285 if (!data || data->process_event_count)
287 if (!count && !timeout) return WAIT_TIMEOUT;
288 return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
289 timeout, flags & MWMO_ALERTABLE );
292 /* check whether only server queue handle was passed in */
293 if (count < 2) flags &= ~MWMO_WAITALL;
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, visible=%d (style %08x), focus=%p, active=%p, fg=%p, last=%p\n",
425 hwnd, IsWindowEnabled(hwnd), IsWindowVisible(hwnd), GetWindowLongW(hwnd, GWL_STYLE),
426 GetFocus(), GetActiveWindow(), 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");
454 xev.window = DefaultRootWindow(xev.display);
455 XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
457 /* this line is semi-stolen from gtk2 */
458 TRACE("NET_WM Pong\n");
463 static const char * const focus_details[] =
469 "NotifyNonlinearVirtual",
475 /**********************************************************************
478 static void EVENT_FocusIn( HWND hwnd, XEvent *xev )
480 XFocusChangeEvent *event = &xev->xfocus;
485 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
487 if (event->detail == NotifyPointer) return;
489 if ((xic = X11DRV_get_ic( hwnd )))
495 if (use_take_focus) return; /* ignore FocusIn if we are using take focus */
497 if (!can_activate_window(hwnd))
499 HWND hwnd = GetFocus();
500 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
501 if (!hwnd) hwnd = GetActiveWindow();
502 if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
503 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
505 else SetForegroundWindow( hwnd );
509 /**********************************************************************
512 * Note: only top-level windows get FocusOut events.
514 static void EVENT_FocusOut( HWND hwnd, XEvent *xev )
516 XFocusChangeEvent *event = &xev->xfocus;
524 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
526 if (event->detail == NotifyPointer) return;
527 if (ximInComposeMode) return;
529 x11drv_thread_data()->last_focus = hwnd;
530 if ((xic = X11DRV_get_ic( hwnd )))
533 XUnsetICFocus( xic );
536 if (hwnd != GetForegroundWindow()) return;
537 SendMessageW( hwnd, WM_CANCELMODE, 0, 0 );
539 /* don't reset the foreground window, if the window which is
540 getting the focus is a Wine window */
543 XGetInputFocus( thread_display(), &focus_win, &revert );
546 if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
553 /* Abey : 6-Oct-99. Check again if the focus out window is the
554 Foreground window, because in most cases the messages sent
555 above must have already changed the foreground window, in which
556 case we don't have to change the foreground window to 0 */
557 if (hwnd == GetForegroundWindow())
559 TRACE( "lost focus, setting fg to 0\n" );
560 SetForegroundWindow( 0 );
566 /***********************************************************************
567 * EVENT_PropertyNotify
568 * We use this to release resources like Pixmaps when a selection
569 * client no longer needs them.
571 static void EVENT_PropertyNotify( HWND hwnd, XEvent *xev )
573 XPropertyEvent *event = &xev->xproperty;
574 /* Check if we have any resources to free */
575 TRACE("Received PropertyNotify event:\n");
581 TRACE("\tPropertyDelete for atom %ld on window %ld\n",
582 event->atom, (long)event->window);
586 case PropertyNewValue:
588 TRACE("\tPropertyNewValue for atom %ld on window %ld\n\n",
589 event->atom, (long)event->window);
598 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
602 if (!IsWindowEnabled(hQueryWnd)) return 0;
604 GetWindowRect(hQueryWnd, &tempRect);
606 if(!PtInRect(&tempRect, *lpPt)) return 0;
608 if (!IsIconic( hQueryWnd ))
611 ScreenToClient( hQueryWnd, &pt );
612 GetClientRect( hQueryWnd, &tempRect );
614 if (PtInRect( &tempRect, pt))
616 HWND ret = ChildWindowFromPointEx( hQueryWnd, pt, CWP_SKIPINVISIBLE|CWP_SKIPDISABLED );
617 if (ret && ret != hQueryWnd)
619 ret = find_drop_window( ret, lpPt );
625 if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
627 ScreenToClient(hQueryWnd, lpPt);
632 /**********************************************************************
633 * EVENT_DropFromOffix
635 * don't know if it still works (last Changlog is from 96/11/04)
637 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
639 unsigned long data_length;
640 unsigned long aux_long;
641 unsigned char* p_data = NULL;
645 Window win, w_aux_root, w_aux_child;
649 win = X11DRV_get_whole_window(hWnd);
651 XQueryPointer( event->display, win, &w_aux_root, &w_aux_child,
652 &x, &y, &dummy, &dummy, (unsigned int*)&aux_long);
655 pWnd = WIN_GetPtr(hWnd);
657 /* find out drop point and drop window */
658 if( x < 0 || y < 0 ||
659 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
660 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
662 bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES;
669 HWND hwndDrop = find_drop_window( hWnd, &pt );
682 WIN_ReleasePtr(pWnd);
684 if (!bAccept) return;
687 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
688 x11drv_atom(DndSelection), 0, 65535, FALSE,
689 AnyPropertyType, &atom_aux, &dummy,
690 &data_length, &aux_long, &p_data);
693 if( !aux_long && p_data) /* don't bother if > 64K */
695 char *p = (char *)p_data;
699 while( *p ) /* calculate buffer size */
701 INT len = GetShortPathNameA( p, NULL, 0 );
702 if (len) aux_long += len + 1;
705 if( aux_long && aux_long < 65535 )
710 aux_long += sizeof(DROPFILES) + 1;
711 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
712 lpDrop = (DROPFILES*)GlobalLock( hDrop );
716 WND *pDropWnd = WIN_GetPtr( hScope );
717 lpDrop->pFiles = sizeof(DROPFILES);
721 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
722 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
723 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
724 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
725 lpDrop->fWide = FALSE;
726 WIN_ReleasePtr(pDropWnd);
727 p_drop = (char *)(lpDrop + 1);
731 if (GetShortPathNameA( p, p_drop, aux_long - (p_drop - (char *)lpDrop) ))
732 p_drop += strlen( p_drop ) + 1;
736 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
741 if( p_data ) XFree(p_data);
745 /**********************************************************************
748 * drop items are separated by \n
749 * each item is prefixed by its mime type
751 * event->data.l[3], event->data.l[4] contains drop x,y position
753 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
755 unsigned long data_length;
756 unsigned long aux_long, drop_len = 0;
757 unsigned char *p_data = NULL; /* property data */
770 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
773 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
774 x11drv_atom(DndSelection), 0, 65535, FALSE,
775 AnyPropertyType, &u.atom_aux, &u.i,
776 &data_length, &aux_long, &p_data);
779 WARN("property too large, truncated!\n");
780 TRACE("urls=%s\n", p_data);
782 if( !aux_long && p_data) { /* don't bother if > 64K */
783 /* calculate length */
785 next = strchr(p, '\n');
788 if (strncmp(p,"file:",5) == 0 ) {
789 INT len = GetShortPathNameA( p+5, NULL, 0 );
790 if (len) drop_len += len + 1;
795 next = strchr(p, '\n');
801 if( drop_len && drop_len < 65535 ) {
803 XQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
804 &x, &y, &u.i, &u.i, &u.u);
807 drop_len += sizeof(DROPFILES) + 1;
808 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
809 lpDrop = (DROPFILES *) GlobalLock( hDrop );
812 WND *pDropWnd = WIN_GetPtr( hWnd );
813 lpDrop->pFiles = sizeof(DROPFILES);
814 lpDrop->pt.x = (INT)x;
815 lpDrop->pt.y = (INT)y;
817 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
818 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
819 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
820 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
821 lpDrop->fWide = FALSE;
822 p_drop = (char*)(lpDrop + 1);
823 WIN_ReleasePtr(pDropWnd);
826 /* create message content */
829 next = strchr(p, '\n');
832 if (strncmp(p,"file:",5) == 0 ) {
833 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
835 TRACE("drop file %s as %s\n", p+5, p_drop);
838 WARN("can't convert file %s to dos name\n", p+5);
841 WARN("unknown mime type %s\n", p);
846 next = strchr(p, '\n');
854 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
858 if( p_data ) XFree(p_data);
863 /**********************************************************************
864 * handle_dnd_protocol
866 static void handle_dnd_protocol( HWND hwnd, XClientMessageEvent *event )
869 int root_x, root_y, child_x, child_y;
872 /* query window (drag&drop event contains only drag window) */
874 XQueryPointer( event->display, root_window, &root, &child,
875 &root_x, &root_y, &child_x, &child_y, &u);
876 if (XFindContext( event->display, child, winContext, (char **)&hwnd ) != 0) hwnd = 0;
879 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
880 EVENT_DropFromOffiX(hwnd, event);
881 else if (event->data.l[0] == DndURL)
882 EVENT_DropURLs(hwnd, event);
886 struct client_message_handler
888 int atom; /* protocol atom */
889 void (*handler)(HWND, XClientMessageEvent *); /* corresponding handler function */
892 static const struct client_message_handler client_messages[] =
894 { XATOM_WM_PROTOCOLS, handle_wm_protocols },
895 { XATOM_DndProtocol, handle_dnd_protocol },
896 { XATOM_XdndEnter, X11DRV_XDND_EnterEvent },
897 { XATOM_XdndPosition, X11DRV_XDND_PositionEvent },
898 { XATOM_XdndDrop, X11DRV_XDND_DropEvent },
899 { XATOM_XdndLeave, X11DRV_XDND_LeaveEvent }
903 /**********************************************************************
904 * EVENT_ClientMessage
906 static void EVENT_ClientMessage( HWND hwnd, XEvent *xev )
908 XClientMessageEvent *event = &xev->xclient;
913 if (event->format != 32)
915 WARN( "Don't know how to handle format %d\n", event->format );
919 for (i = 0; i < sizeof(client_messages)/sizeof(client_messages[0]); i++)
921 if (event->message_type == X11DRV_Atoms[client_messages[i].atom - FIRST_XATOM])
923 client_messages[i].handler( hwnd, event );
927 TRACE( "no handler found for %ld\n", event->message_type );
931 /**********************************************************************
932 * X11DRV_WindowMessage (X11DRV.@)
934 LRESULT X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
938 case WM_X11DRV_ACQUIRE_SELECTION:
939 return X11DRV_AcquireClipboard( hwnd );
940 case WM_X11DRV_DELETE_WINDOW:
941 return SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
943 FIXME( "got window msg %x hwnd %p wp %x lp %lx\n", msg, hwnd, wp, lp );
949 /***********************************************************************
950 * X11DRV_SendInput (X11DRV.@)
952 UINT X11DRV_SendInput( UINT count, LPINPUT inputs, int size )
956 for (i = 0; i < count; i++, inputs++)
961 X11DRV_send_mouse_input( 0, inputs->u.mi.dwFlags, inputs->u.mi.dx, inputs->u.mi.dy,
962 inputs->u.mi.mouseData, inputs->u.mi.time,
963 inputs->u.mi.dwExtraInfo, LLMHF_INJECTED );
966 X11DRV_send_keyboard_input( inputs->u.ki.wVk, inputs->u.ki.wScan, inputs->u.ki.dwFlags,
967 inputs->u.ki.time, inputs->u.ki.dwExtraInfo, LLKHF_INJECTED );
970 FIXME( "INPUT_HARDWARE not supported\n" );