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 DWORD 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
, DWORD 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
)
277 HANDLE new_handles
[MAXIMUM_WAIT_OBJECTS
+1]; /* FIXME! */
279 struct x11drv_thread_data
*data
= NtCurrentTeb()->driver_data
;
281 if (!data
|| data
->process_event_count
)
282 return WaitForMultipleObjectsEx( count
, handles
, flags
& MWMO_WAITALL
,
283 timeout
, flags
& MWMO_ALERTABLE
);
285 /* check whether only server queue handle was passed in */
286 if (count
< 2) flags
&= ~MWMO_WAITALL
;
288 for (i
= 0; i
< count
; i
++) new_handles
[i
] = handles
[i
];
289 new_handles
[count
] = data
->display_fd
;
292 XFlush( gdi_display
);
293 XFlush( data
->display
);
296 data
->process_event_count
++;
297 if (process_events( data
->display
, mask
)) ret
= count
;
300 ret
= WaitForMultipleObjectsEx( count
+1, new_handles
, flags
& MWMO_WAITALL
,
301 timeout
, flags
& MWMO_ALERTABLE
);
302 if (ret
== count
) process_events( data
->display
, mask
);
304 data
->process_event_count
--;
308 /***********************************************************************
309 * EVENT_x11_time_to_win32_time
311 * Make our timer and the X timer line up as best we can
312 * Pass 0 to retrieve the current adjustment value (times -1)
314 DWORD
EVENT_x11_time_to_win32_time(Time time
)
316 static DWORD adjust
= 0;
317 DWORD now
= GetTickCount();
320 if (! adjust
&& time
!= 0)
327 /* If we got an event in the 'future', then our clock is clearly wrong.
328 If we got it more than 10000 ms in the future, then it's most likely
329 that the clock has wrapped. */
332 if (ret
> now
&& ((ret
- now
) < 10000) && time
!= 0)
343 /*******************************************************************
344 * can_activate_window
346 * Check if we can activate the specified window.
348 inline static BOOL
can_activate_window( HWND hwnd
)
350 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
351 if (!(style
& WS_VISIBLE
)) return FALSE
;
352 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
353 return !(style
& WS_DISABLED
);
357 /**********************************************************************
360 static void set_focus( HWND hwnd
, Time time
)
365 TRACE( "setting foreground window to %p\n", hwnd
);
366 SetForegroundWindow( hwnd
);
369 if (focus
) focus
= GetAncestor( focus
, GA_ROOT
);
370 win
= X11DRV_get_whole_window(focus
);
374 TRACE( "setting focus to %p (%lx) time=%ld\n", focus
, win
, time
);
376 XSetInputFocus( thread_display(), win
, RevertToParent
, time
);
382 /**********************************************************************
383 * handle_wm_protocols
385 static void handle_wm_protocols( HWND hwnd
, XClientMessageEvent
*event
)
387 Atom protocol
= (Atom
)event
->data
.l
[0];
389 if (!protocol
) return;
391 if (protocol
== x11drv_atom(WM_DELETE_WINDOW
))
393 /* Ignore the delete window request if the window has been disabled
394 * and we are in managed mode. This is to disallow applications from
395 * being closed by the window manager while in a modal state.
397 if (IsWindowEnabled(hwnd
)) PostMessageW( hwnd
, WM_X11DRV_DELETE_WINDOW
, 0, 0 );
399 else if (protocol
== x11drv_atom(WM_TAKE_FOCUS
))
401 Time event_time
= (Time
)event
->data
.l
[1];
402 HWND last_focus
= x11drv_thread_data()->last_focus
;
404 TRACE( "got take focus msg for %p, enabled=%d, focus=%p, active=%p, fg=%p, last=%p\n",
405 hwnd
, IsWindowEnabled(hwnd
), GetFocus(), GetActiveWindow(),
406 GetForegroundWindow(), last_focus
);
408 if (can_activate_window(hwnd
))
410 /* simulate a mouse click on the caption to find out
411 * whether the window wants to be activated */
412 LRESULT ma
= SendMessageW( hwnd
, WM_MOUSEACTIVATE
,
413 (WPARAM
)GetAncestor( hwnd
, GA_ROOT
),
414 MAKELONG(HTCAPTION
,WM_LBUTTONDOWN
) );
415 if (ma
!= MA_NOACTIVATEANDEAT
&& ma
!= MA_NOACTIVATE
) set_focus( hwnd
, event_time
);
416 else TRACE( "not setting focus to %p (%lx), ma=%ld\n", hwnd
, event
->window
, ma
);
421 if (hwnd
) hwnd
= GetAncestor( hwnd
, GA_ROOT
);
422 if (!hwnd
) hwnd
= GetActiveWindow();
423 if (!hwnd
) hwnd
= last_focus
;
424 if (hwnd
&& can_activate_window(hwnd
)) set_focus( hwnd
, event_time
);
427 else if (protocol
== x11drv_atom(_NET_WM_PING
))
429 XClientMessageEvent xev
;
432 TRACE("NET_WM Ping\n");
433 xev
.window
= DefaultRootWindow(xev
.display
);
434 XSendEvent(xev
.display
, xev
.window
, False
, SubstructureRedirectMask
| SubstructureNotifyMask
, (XEvent
*)&xev
);
435 /* this line is semi-stolen from gtk2 */
436 TRACE("NET_WM Pong\n");
441 static const char * const focus_details
[] =
447 "NotifyNonlinearVirtual",
453 /**********************************************************************
456 static void EVENT_FocusIn( HWND hwnd
, XEvent
*xev
)
458 XFocusChangeEvent
*event
= &xev
->xfocus
;
463 TRACE( "win %p xwin %lx detail=%s\n", hwnd
, event
->window
, focus_details
[event
->detail
] );
465 if (event
->detail
== NotifyPointer
) return;
467 if ((xic
= X11DRV_get_ic( hwnd
)))
473 if (use_take_focus
) return; /* ignore FocusIn if we are using take focus */
475 if (!can_activate_window(hwnd
))
477 HWND hwnd
= GetFocus();
478 if (hwnd
) hwnd
= GetAncestor( hwnd
, GA_ROOT
);
479 if (!hwnd
) hwnd
= GetActiveWindow();
480 if (!hwnd
) hwnd
= x11drv_thread_data()->last_focus
;
481 if (hwnd
&& can_activate_window(hwnd
)) set_focus( hwnd
, CurrentTime
);
483 else SetForegroundWindow( hwnd
);
487 /**********************************************************************
490 * Note: only top-level windows get FocusOut events.
492 static void EVENT_FocusOut( HWND hwnd
, XEvent
*xev
)
494 XFocusChangeEvent
*event
= &xev
->xfocus
;
502 TRACE( "win %p xwin %lx detail=%s\n", hwnd
, event
->window
, focus_details
[event
->detail
] );
504 if (event
->detail
== NotifyPointer
) return;
505 if (ximInComposeMode
) return;
507 x11drv_thread_data()->last_focus
= hwnd
;
508 if ((xic
= X11DRV_get_ic( hwnd
)))
511 XUnsetICFocus( xic
);
514 if (hwnd
!= GetForegroundWindow()) return;
515 SendMessageA( hwnd
, WM_CANCELMODE
, 0, 0 );
517 /* don't reset the foreground window, if the window which is
518 getting the focus is a Wine window */
521 XGetInputFocus( thread_display(), &focus_win
, &revert
);
524 if (XFindContext( thread_display(), focus_win
, winContext
, (char **)&hwnd_tmp
) != 0)
531 /* Abey : 6-Oct-99. Check again if the focus out window is the
532 Foreground window, because in most cases the messages sent
533 above must have already changed the foreground window, in which
534 case we don't have to change the foreground window to 0 */
535 if (hwnd
== GetForegroundWindow())
537 TRACE( "lost focus, setting fg to 0\n" );
538 SetForegroundWindow( 0 );
544 /***********************************************************************
545 * EVENT_PropertyNotify
546 * We use this to release resources like Pixmaps when a selection
547 * client no longer needs them.
549 static void EVENT_PropertyNotify( HWND hwnd
, XEvent
*xev
)
551 XPropertyEvent
*event
= &xev
->xproperty
;
552 /* Check if we have any resources to free */
553 TRACE("Received PropertyNotify event: \n");
559 TRACE("\tPropertyDelete for atom %ld on window %ld\n",
560 event
->atom
, (long)event
->window
);
564 case PropertyNewValue
:
566 TRACE("\tPropertyNewValue for atom %ld on window %ld\n\n",
567 event
->atom
, (long)event
->window
);
576 static HWND
find_drop_window( HWND hQueryWnd
, LPPOINT lpPt
)
580 if (!IsWindowEnabled(hQueryWnd
)) return 0;
582 GetWindowRect(hQueryWnd
, &tempRect
);
584 if(!PtInRect(&tempRect
, *lpPt
)) return 0;
586 if (!IsIconic( hQueryWnd
))
589 ScreenToClient( hQueryWnd
, &pt
);
590 GetClientRect( hQueryWnd
, &tempRect
);
592 if (PtInRect( &tempRect
, pt
))
594 HWND ret
= ChildWindowFromPointEx( hQueryWnd
, pt
, CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
);
595 if (ret
&& ret
!= hQueryWnd
)
597 ret
= find_drop_window( ret
, lpPt
);
603 if(!(GetWindowLongA( hQueryWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
)) return 0;
605 ScreenToClient(hQueryWnd
, lpPt
);
610 /**********************************************************************
611 * EVENT_DropFromOffix
613 * don't know if it still works (last Changlog is from 96/11/04)
615 static void EVENT_DropFromOffiX( HWND hWnd
, XClientMessageEvent
*event
)
617 unsigned long data_length
;
618 unsigned long aux_long
;
619 unsigned char* p_data
= NULL
;
630 Window win
, w_aux_root
, w_aux_child
;
634 win
= X11DRV_get_whole_window(hWnd
);
636 XQueryPointer( event
->display
, win
, &w_aux_root
, &w_aux_child
,
637 &x
, &y
, (int *) &u
.pt_aux
.x
, (int *) &u
.pt_aux
.y
,
638 (unsigned int*)&aux_long
);
641 pWnd
= WIN_GetPtr(hWnd
);
643 /* find out drop point and drop window */
644 if( x
< 0 || y
< 0 ||
645 x
> (pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) ||
646 y
> (pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
) )
648 bAccept
= pWnd
->dwExStyle
& WS_EX_ACCEPTFILES
;
655 HWND hwndDrop
= find_drop_window( hWnd
, &pt
);
668 WIN_ReleasePtr(pWnd
);
670 if (!bAccept
) return;
673 XGetWindowProperty( event
->display
, DefaultRootWindow(event
->display
),
674 x11drv_atom(DndSelection
), 0, 65535, FALSE
,
675 AnyPropertyType
, &u
.atom_aux
, (int *) &u
.pt_aux
.y
,
676 &data_length
, &aux_long
, &p_data
);
679 if( !aux_long
&& p_data
) /* don't bother if > 64K */
681 signed char *p
= (signed char*) p_data
;
685 while( *p
) /* calculate buffer size */
688 if((u
.i
= *p
) != -1 )
690 INT len
= GetShortPathNameA( p
, NULL
, 0 );
691 if (len
) aux_long
+= len
+ 1;
696 if( aux_long
&& aux_long
< 65535 )
701 aux_long
+= sizeof(DROPFILES
) + 1;
702 hDrop
= GlobalAlloc( GMEM_SHARE
, aux_long
);
703 lpDrop
= (DROPFILES
*)GlobalLock( hDrop
);
707 WND
*pDropWnd
= WIN_GetPtr( hScope
);
708 lpDrop
->pFiles
= sizeof(DROPFILES
);
712 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
713 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
714 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
715 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
716 lpDrop
->fWide
= FALSE
;
717 WIN_ReleasePtr(pDropWnd
);
718 p_drop
= (char *)(lpDrop
+ 1);
722 if( *p
!= -1 ) /* use only "good" entries */
724 GetShortPathNameA( p
, p_drop
, 65535 );
725 p_drop
+= strlen( p_drop
) + 1;
730 PostMessageA( hWnd
, WM_DROPFILES
, (WPARAM
)hDrop
, 0L );
735 if( p_data
) XFree(p_data
);
739 /**********************************************************************
742 * drop items are separated by \n
743 * each item is prefixed by its mime type
745 * event->data.l[3], event->data.l[4] contains drop x,y position
747 static void EVENT_DropURLs( HWND hWnd
, XClientMessageEvent
*event
)
749 unsigned long data_length
;
750 unsigned long aux_long
, drop_len
= 0;
751 unsigned char *p_data
= NULL
; /* property data */
763 if (!(GetWindowLongW( hWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
)) return;
766 XGetWindowProperty( event
->display
, DefaultRootWindow(event
->display
),
767 x11drv_atom(DndSelection
), 0, 65535, FALSE
,
768 AnyPropertyType
, &u
.atom_aux
, &u
.i
,
769 &data_length
, &aux_long
, &p_data
);
772 WARN("property too large, truncated!\n");
773 TRACE("urls=%s\n", p_data
);
775 if( !aux_long
&& p_data
) { /* don't bother if > 64K */
776 /* calculate length */
778 next
= strchr(p
, '\n');
781 if (strncmp(p
,"file:",5) == 0 ) {
782 INT len
= GetShortPathNameA( p
+5, NULL
, 0 );
783 if (len
) drop_len
+= len
+ 1;
788 next
= strchr(p
, '\n');
794 if( drop_len
&& drop_len
< 65535 ) {
796 XQueryPointer( event
->display
, root_window
, &u
.w_aux
, &u
.w_aux
,
797 &x
, &y
, &u
.i
, &u
.i
, &u
.i
);
800 drop_len
+= sizeof(DROPFILES
) + 1;
801 hDrop
= GlobalAlloc( GMEM_SHARE
, drop_len
);
802 lpDrop
= (DROPFILES
*) GlobalLock( hDrop
);
805 WND
*pDropWnd
= WIN_GetPtr( hWnd
);
806 lpDrop
->pFiles
= sizeof(DROPFILES
);
807 lpDrop
->pt
.x
= (INT
)x
;
808 lpDrop
->pt
.y
= (INT
)y
;
810 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
811 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
812 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
813 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
814 lpDrop
->fWide
= FALSE
;
815 p_drop
= (char*)(lpDrop
+ 1);
816 WIN_ReleasePtr(pDropWnd
);
819 /* create message content */
822 next
= strchr(p
, '\n');
825 if (strncmp(p
,"file:",5) == 0 ) {
826 INT len
= GetShortPathNameA( p
+5, p_drop
, 65535 );
828 TRACE("drop file %s as %s\n", p
+5, p_drop
);
831 WARN("can't convert file %s to dos name \n", p
+5);
834 WARN("unknown mime type %s\n", p
);
839 next
= strchr(p
, '\n');
847 PostMessageA( hWnd
, WM_DROPFILES
, (WPARAM
)hDrop
, 0L );
851 if( p_data
) XFree(p_data
);
856 /**********************************************************************
857 * handle_dnd_protocol
859 static void handle_dnd_protocol( HWND hwnd
, XClientMessageEvent
*event
)
862 int root_x
, root_y
, child_x
, child_y
;
865 /* query window (drag&drop event contains only drag window) */
867 XQueryPointer( event
->display
, root_window
, &root
, &child
,
868 &root_x
, &root_y
, &child_x
, &child_y
, &u
);
869 if (XFindContext( event
->display
, child
, winContext
, (char **)&hwnd
) != 0) hwnd
= 0;
872 if (event
->data
.l
[0] == DndFile
|| event
->data
.l
[0] == DndFiles
)
873 EVENT_DropFromOffiX(hwnd
, event
);
874 else if (event
->data
.l
[0] == DndURL
)
875 EVENT_DropURLs(hwnd
, event
);
879 struct client_message_handler
881 int atom
; /* protocol atom */
882 void (*handler
)(HWND
, XClientMessageEvent
*); /* corresponding handler function */
885 static const struct client_message_handler client_messages
[] =
887 { XATOM_WM_PROTOCOLS
, handle_wm_protocols
},
888 { XATOM_DndProtocol
, handle_dnd_protocol
},
889 { XATOM_XdndEnter
, X11DRV_XDND_EnterEvent
},
890 { XATOM_XdndPosition
, X11DRV_XDND_PositionEvent
},
891 { XATOM_XdndDrop
, X11DRV_XDND_DropEvent
},
892 { XATOM_XdndLeave
, X11DRV_XDND_LeaveEvent
}
896 /**********************************************************************
897 * EVENT_ClientMessage
899 static void EVENT_ClientMessage( HWND hwnd
, XEvent
*xev
)
901 XClientMessageEvent
*event
= &xev
->xclient
;
906 if (event
->format
!= 32)
908 WARN( "Don't know how to handle format %d\n", event
->format
);
912 for (i
= 0; i
< sizeof(client_messages
)/sizeof(client_messages
[0]); i
++)
914 if (event
->message_type
== X11DRV_Atoms
[client_messages
[i
].atom
- FIRST_XATOM
])
916 client_messages
[i
].handler( hwnd
, event
);
920 TRACE( "no handler found for %ld\n", event
->message_type
);
924 /**********************************************************************
925 * X11DRV_WindowMessage (X11DRV.@)
927 LRESULT
X11DRV_WindowMessage( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
931 case WM_X11DRV_ACQUIRE_SELECTION
:
932 X11DRV_AcquireClipboard( hwnd
);
934 case WM_X11DRV_DELETE_WINDOW
:
935 return SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
937 FIXME( "got window msg %x hwnd %p wp %x lp %lx\n", msg
, hwnd
, wp
, lp
);
943 /***********************************************************************
944 * X11DRV_SendInput (X11DRV.@)
946 UINT
X11DRV_SendInput( UINT count
, LPINPUT inputs
, int size
)
950 for (i
= 0; i
< count
; i
++, inputs
++)
955 X11DRV_send_mouse_input( 0, inputs
->u
.mi
.dwFlags
, inputs
->u
.mi
.dx
, inputs
->u
.mi
.dy
,
956 inputs
->u
.mi
.mouseData
, inputs
->u
.mi
.time
,
957 inputs
->u
.mi
.dwExtraInfo
, LLMHF_INJECTED
);
960 X11DRV_send_keyboard_input( inputs
->u
.ki
.wVk
, inputs
->u
.ki
.wScan
, inputs
->u
.ki
.dwFlags
,
961 inputs
->u
.ki
.time
, inputs
->u
.ki
.dwExtraInfo
, LLKHF_INJECTED
);
964 FIXME( "INPUT_HARDWARE not supported\n" );