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
40 #include "shlobj.h" /* DROPFILES */
46 #include "wine/debug.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(event);
50 extern BOOL ximInComposeMode;
52 #define DndNotDnd -1 /* OffiX drag&drop */
64 #define DndURL 128 /* KDE drag&drop */
67 static void EVENT_FocusIn( HWND hwnd, XEvent *event );
68 static void EVENT_FocusOut( HWND hwnd, XEvent *event );
69 static void EVENT_PropertyNotify( HWND hwnd, XEvent *event );
70 static void EVENT_ClientMessage( HWND hwnd, XEvent *event );
74 int type; /* event type */
75 x11drv_event_handler handler; /* corresponding handler function */
78 #define MAX_EVENT_HANDLERS 64
80 static struct event_handler handlers[MAX_EVENT_HANDLERS] =
82 /* list must be sorted by event type */
83 { KeyPress, X11DRV_KeyEvent },
84 { KeyRelease, X11DRV_KeyEvent },
85 { ButtonPress, X11DRV_ButtonPress },
86 { ButtonRelease, X11DRV_ButtonRelease },
87 { MotionNotify, X11DRV_MotionNotify },
88 { EnterNotify, X11DRV_EnterNotify },
90 { FocusIn, EVENT_FocusIn },
91 { FocusOut, EVENT_FocusOut },
92 { KeymapNotify, X11DRV_KeymapNotify },
93 { Expose, X11DRV_Expose },
96 /* VisibilityNotify */
99 { UnmapNotify, X11DRV_UnmapNotify },
100 { MapNotify, X11DRV_MapNotify },
103 { ConfigureNotify, X11DRV_ConfigureNotify },
104 /* ConfigureRequest */
107 /* CirculateNotify */
108 /* CirculateRequest */
109 { PropertyNotify, EVENT_PropertyNotify },
110 { SelectionClear, X11DRV_SelectionClear },
111 { SelectionRequest, X11DRV_SelectionRequest },
112 /* SelectionNotify */
114 { ClientMessage, EVENT_ClientMessage },
115 { MappingNotify, X11DRV_MappingNotify },
118 static int nb_event_handlers = 18; /* change this if you add handlers above */
121 /* return the name of an X event */
122 static const char *dbgstr_event( int type )
124 static const char * const event_names[] =
126 "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
127 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
128 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
129 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
130 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
131 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
132 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
133 "ClientMessage", "MappingNotify"
136 if (type >= KeyPress && type <= MappingNotify) return event_names[type - KeyPress];
137 return wine_dbg_sprintf( "Extension event %d", type );
141 /***********************************************************************
144 * Find the handler for a given event type. Caller must hold the x11 lock.
146 static inline x11drv_event_handler find_handler( int type )
148 int min = 0, max = nb_event_handlers - 1;
152 int pos = (min + max) / 2;
153 if (handlers[pos].type == type) return handlers[pos].handler;
154 if (handlers[pos].type > type) max = pos - 1;
161 /***********************************************************************
162 * X11DRV_register_event_handler
164 * Register a handler for a given event type.
165 * If already registered, overwrite the previous handler.
167 void X11DRV_register_event_handler( int type, x11drv_event_handler handler )
173 max = nb_event_handlers - 1;
176 int pos = (min + max) / 2;
177 if (handlers[pos].type == type)
179 handlers[pos].handler = handler;
182 if (handlers[pos].type > type) max = pos - 1;
185 /* insert it between max and min */
186 memmove( &handlers[min+1], &handlers[min], (nb_event_handlers - min) * sizeof(handlers[0]) );
187 handlers[min].type = type;
188 handlers[min].handler = handler;
190 assert( nb_event_handlers <= MAX_EVENT_HANDLERS );
193 TRACE("registered handler %p for event %d count %d\n", handler, type, nb_event_handlers );
197 /***********************************************************************
200 static Bool filter_event( Display *display, XEvent *event, char *arg )
202 ULONG_PTR mask = (ULONG_PTR)arg;
204 if ((mask & QS_ALLINPUT) == QS_ALLINPUT) return 1;
212 return (mask & QS_KEY) != 0;
215 return (mask & QS_MOUSEBUTTON) != 0;
219 return (mask & QS_MOUSEMOVE) != 0;
221 return (mask & QS_PAINT) != 0;
226 case ConfigureNotify:
229 return (mask & QS_POSTMESSAGE) != 0;
231 return (mask & QS_SENDMESSAGE) != 0;
236 /***********************************************************************
239 static int process_events( Display *display, ULONG_PTR mask )
244 x11drv_event_handler handler;
247 while (XCheckIfEvent( display, &event, filter_event, (char *)mask ))
250 if (XFilterEvent( &event, None )) continue; /* filtered, ignore it */
252 if (!(handler = find_handler( event.type )))
254 TRACE( "%s, ignoring\n", dbgstr_event( event.type ));
255 continue; /* no handler, ignore it */
258 if (XFindContext( display, event.xany.window, winContext, (char **)&hwnd ) != 0)
259 hwnd = 0; /* not for a registered window */
260 if (!hwnd && event.xany.window == root_window) hwnd = GetDesktopWindow();
263 TRACE( "%s for hwnd/window %p/%lx\n",
264 dbgstr_event( event.type ), hwnd, event.xany.window );
265 handler( hwnd, &event );
268 XFlush( gdi_display );
270 if (count) TRACE( "processed %d events\n", count );
275 /***********************************************************************
276 * MsgWaitForMultipleObjectsEx (X11DRV.@)
278 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
279 DWORD timeout, DWORD mask, DWORD flags )
282 struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index );
284 if (!data || data->process_event_count)
286 if (!count && !timeout) return WAIT_TIMEOUT;
287 return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
288 timeout, flags & MWMO_ALERTABLE );
291 /* check whether only server queue handle was passed in */
292 if (count < 2) flags &= ~MWMO_WAITALL;
294 data->process_event_count++;
296 if (process_events( data->display, mask )) ret = count;
297 else if (count || timeout)
299 HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1]; /* FIXME! */
301 for (i = 0; i < count; i++) new_handles[i] = handles[i];
302 new_handles[count] = data->display_fd;
304 ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
305 timeout, flags & MWMO_ALERTABLE );
306 if (ret == count) process_events( data->display, mask );
308 else ret = WAIT_TIMEOUT;
310 data->process_event_count--;
314 /***********************************************************************
315 * EVENT_x11_time_to_win32_time
317 * Make our timer and the X timer line up as best we can
318 * Pass 0 to retrieve the current adjustment value (times -1)
320 DWORD EVENT_x11_time_to_win32_time(Time time)
322 static DWORD adjust = 0;
323 DWORD now = GetTickCount();
326 if (! adjust && time != 0)
333 /* If we got an event in the 'future', then our clock is clearly wrong.
334 If we got it more than 10000 ms in the future, then it's most likely
335 that the clock has wrapped. */
338 if (ret > now && ((ret - now) < 10000) && time != 0)
349 /*******************************************************************
350 * can_activate_window
352 * Check if we can activate the specified window.
354 inline static BOOL can_activate_window( HWND hwnd )
356 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
357 if (!(style & WS_VISIBLE)) return FALSE;
358 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
359 return !(style & WS_DISABLED);
363 /**********************************************************************
366 static void set_focus( HWND hwnd, Time time )
371 TRACE( "setting foreground window to %p\n", hwnd );
372 SetForegroundWindow( hwnd );
375 if (focus) focus = GetAncestor( focus, GA_ROOT );
376 win = X11DRV_get_whole_window(focus);
380 TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time );
382 XSetInputFocus( thread_display(), win, RevertToParent, time );
388 /**********************************************************************
389 * handle_wm_protocols
391 static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event )
393 Atom protocol = (Atom)event->data.l[0];
395 if (!protocol) return;
397 if (protocol == x11drv_atom(WM_DELETE_WINDOW))
399 /* Ignore the delete window request if the window has been disabled
400 * and we are in managed mode. This is to disallow applications from
401 * being closed by the window manager while in a modal state.
403 if (IsWindowEnabled(hwnd))
407 if (GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE) return;
408 hSysMenu = GetSystemMenu(hwnd, FALSE);
411 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
412 if (state == 0xFFFFFFFF || (state & (MF_DISABLED | MF_GRAYED)))
415 PostMessageW( hwnd, WM_X11DRV_DELETE_WINDOW, 0, 0 );
418 else if (protocol == x11drv_atom(WM_TAKE_FOCUS))
420 Time event_time = (Time)event->data.l[1];
421 HWND last_focus = x11drv_thread_data()->last_focus;
423 TRACE( "got take focus msg for %p, enabled=%d, visible=%d (style %08x), focus=%p, active=%p, fg=%p, last=%p\n",
424 hwnd, IsWindowEnabled(hwnd), IsWindowVisible(hwnd), GetWindowLongW(hwnd, GWL_STYLE),
425 GetFocus(), GetActiveWindow(), GetForegroundWindow(), last_focus );
427 if (can_activate_window(hwnd))
429 /* simulate a mouse click on the caption to find out
430 * whether the window wants to be activated */
431 LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
432 (WPARAM)GetAncestor( hwnd, GA_ROOT ),
433 MAKELONG(HTCAPTION,WM_LBUTTONDOWN) );
434 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) set_focus( hwnd, event_time );
435 else TRACE( "not setting focus to %p (%lx), ma=%ld\n", hwnd, event->window, ma );
440 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
441 if (!hwnd) hwnd = GetActiveWindow();
442 if (!hwnd) hwnd = last_focus;
443 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
446 else if (protocol == x11drv_atom(_NET_WM_PING))
448 XClientMessageEvent xev;
451 TRACE("NET_WM Ping\n");
453 xev.window = DefaultRootWindow(xev.display);
454 XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
456 /* this line is semi-stolen from gtk2 */
457 TRACE("NET_WM Pong\n");
462 static const char * const focus_details[] =
468 "NotifyNonlinearVirtual",
474 /**********************************************************************
477 static void EVENT_FocusIn( HWND hwnd, XEvent *xev )
479 XFocusChangeEvent *event = &xev->xfocus;
484 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
486 if (event->detail == NotifyPointer) return;
488 if ((xic = X11DRV_get_ic( hwnd )))
494 if (use_take_focus) return; /* ignore FocusIn if we are using take focus */
496 if (!can_activate_window(hwnd))
498 HWND hwnd = GetFocus();
499 if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
500 if (!hwnd) hwnd = GetActiveWindow();
501 if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
502 if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
504 else SetForegroundWindow( hwnd );
508 /**********************************************************************
511 * Note: only top-level windows get FocusOut events.
513 static void EVENT_FocusOut( HWND hwnd, XEvent *xev )
515 XFocusChangeEvent *event = &xev->xfocus;
523 TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
525 if (event->detail == NotifyPointer) return;
526 if (ximInComposeMode) return;
528 x11drv_thread_data()->last_focus = hwnd;
529 if ((xic = X11DRV_get_ic( hwnd )))
532 XUnsetICFocus( xic );
535 if (hwnd != GetForegroundWindow()) return;
536 SendMessageW( hwnd, WM_CANCELMODE, 0, 0 );
538 /* don't reset the foreground window, if the window which is
539 getting the focus is a Wine window */
542 XGetInputFocus( thread_display(), &focus_win, &revert );
545 if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
552 /* Abey : 6-Oct-99. Check again if the focus out window is the
553 Foreground window, because in most cases the messages sent
554 above must have already changed the foreground window, in which
555 case we don't have to change the foreground window to 0 */
556 if (hwnd == GetForegroundWindow())
558 TRACE( "lost focus, setting fg to 0\n" );
559 SetForegroundWindow( 0 );
565 /***********************************************************************
566 * EVENT_PropertyNotify
567 * We use this to release resources like Pixmaps when a selection
568 * client no longer needs them.
570 static void EVENT_PropertyNotify( HWND hwnd, XEvent *xev )
572 XPropertyEvent *event = &xev->xproperty;
573 /* Check if we have any resources to free */
574 TRACE("Received PropertyNotify event:\n");
580 TRACE("\tPropertyDelete for atom %ld on window %ld\n",
581 event->atom, (long)event->window);
585 case PropertyNewValue:
587 TRACE("\tPropertyNewValue for atom %ld on window %ld\n\n",
588 event->atom, (long)event->window);
597 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
601 if (!IsWindowEnabled(hQueryWnd)) return 0;
603 GetWindowRect(hQueryWnd, &tempRect);
605 if(!PtInRect(&tempRect, *lpPt)) return 0;
607 if (!IsIconic( hQueryWnd ))
610 ScreenToClient( hQueryWnd, &pt );
611 GetClientRect( hQueryWnd, &tempRect );
613 if (PtInRect( &tempRect, pt))
615 HWND ret = ChildWindowFromPointEx( hQueryWnd, pt, CWP_SKIPINVISIBLE|CWP_SKIPDISABLED );
616 if (ret && ret != hQueryWnd)
618 ret = find_drop_window( ret, lpPt );
624 if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
626 ScreenToClient(hQueryWnd, lpPt);
631 /**********************************************************************
632 * EVENT_DropFromOffix
634 * don't know if it still works (last Changlog is from 96/11/04)
636 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
638 unsigned long data_length;
639 unsigned long aux_long;
640 unsigned char* p_data = NULL;
644 Window win, w_aux_root, w_aux_child;
648 win = X11DRV_get_whole_window(hWnd);
650 XQueryPointer( event->display, win, &w_aux_root, &w_aux_child,
651 &x, &y, &dummy, &dummy, (unsigned int*)&aux_long);
652 x += virtual_screen_rect.left;
653 y += virtual_screen_rect.top;
656 pWnd = WIN_GetPtr(hWnd);
658 /* find out drop point and drop window */
659 if( x < 0 || y < 0 ||
660 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
661 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
663 bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES;
670 HWND hwndDrop = find_drop_window( hWnd, &pt );
683 WIN_ReleasePtr(pWnd);
685 if (!bAccept) return;
688 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
689 x11drv_atom(DndSelection), 0, 65535, FALSE,
690 AnyPropertyType, &atom_aux, &dummy,
691 &data_length, &aux_long, &p_data);
694 if( !aux_long && p_data) /* don't bother if > 64K */
696 char *p = (char *)p_data;
700 while( *p ) /* calculate buffer size */
702 INT len = GetShortPathNameA( p, NULL, 0 );
703 if (len) aux_long += len + 1;
706 if( aux_long && aux_long < 65535 )
711 aux_long += sizeof(DROPFILES) + 1;
712 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
713 lpDrop = (DROPFILES*)GlobalLock( hDrop );
717 WND *pDropWnd = WIN_GetPtr( hScope );
718 lpDrop->pFiles = sizeof(DROPFILES);
722 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
723 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
724 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
725 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
726 lpDrop->fWide = FALSE;
727 WIN_ReleasePtr(pDropWnd);
728 p_drop = (char *)(lpDrop + 1);
732 if (GetShortPathNameA( p, p_drop, aux_long - (p_drop - (char *)lpDrop) ))
733 p_drop += strlen( p_drop ) + 1;
737 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
742 if( p_data ) XFree(p_data);
746 /**********************************************************************
749 * drop items are separated by \n
750 * each item is prefixed by its mime type
752 * event->data.l[3], event->data.l[4] contains drop x,y position
754 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
756 unsigned long data_length;
757 unsigned long aux_long, drop_len = 0;
758 unsigned char *p_data = NULL; /* property data */
771 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
774 XGetWindowProperty( event->display, DefaultRootWindow(event->display),
775 x11drv_atom(DndSelection), 0, 65535, FALSE,
776 AnyPropertyType, &u.atom_aux, &u.i,
777 &data_length, &aux_long, &p_data);
780 WARN("property too large, truncated!\n");
781 TRACE("urls=%s\n", p_data);
783 if( !aux_long && p_data) { /* don't bother if > 64K */
784 /* calculate length */
786 next = strchr(p, '\n');
789 if (strncmp(p,"file:",5) == 0 ) {
790 INT len = GetShortPathNameA( p+5, NULL, 0 );
791 if (len) drop_len += len + 1;
796 next = strchr(p, '\n');
802 if( drop_len && drop_len < 65535 ) {
804 XQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
805 &x, &y, &u.i, &u.i, &u.u);
806 x += virtual_screen_rect.left;
807 y += virtual_screen_rect.top;
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" );