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;
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, focus=%p, active=%p, fg=%p, last=%p\n",
428 hwnd
, IsWindowEnabled(hwnd
), GetFocus(), GetActiveWindow(),
429 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");
456 xev
.window
= DefaultRootWindow(xev
.display
);
457 XSendEvent(xev
.display
, xev
.window
, False
, SubstructureRedirectMask
| SubstructureNotifyMask
, (XEvent
*)&xev
);
458 /* this line is semi-stolen from gtk2 */
459 TRACE("NET_WM Pong\n");
464 static const char * const focus_details
[] =
470 "NotifyNonlinearVirtual",
476 /**********************************************************************
479 static void EVENT_FocusIn( HWND hwnd
, XEvent
*xev
)
481 XFocusChangeEvent
*event
= &xev
->xfocus
;
486 TRACE( "win %p xwin %lx detail=%s\n", hwnd
, event
->window
, focus_details
[event
->detail
] );
488 if (event
->detail
== NotifyPointer
) return;
490 if ((xic
= X11DRV_get_ic( hwnd
)))
496 if (use_take_focus
) return; /* ignore FocusIn if we are using take focus */
498 if (!can_activate_window(hwnd
))
500 HWND hwnd
= GetFocus();
501 if (hwnd
) hwnd
= GetAncestor( hwnd
, GA_ROOT
);
502 if (!hwnd
) hwnd
= GetActiveWindow();
503 if (!hwnd
) hwnd
= x11drv_thread_data()->last_focus
;
504 if (hwnd
&& can_activate_window(hwnd
)) set_focus( hwnd
, CurrentTime
);
506 else SetForegroundWindow( hwnd
);
510 /**********************************************************************
513 * Note: only top-level windows get FocusOut events.
515 static void EVENT_FocusOut( HWND hwnd
, XEvent
*xev
)
517 XFocusChangeEvent
*event
= &xev
->xfocus
;
525 TRACE( "win %p xwin %lx detail=%s\n", hwnd
, event
->window
, focus_details
[event
->detail
] );
527 if (event
->detail
== NotifyPointer
) return;
528 if (ximInComposeMode
) return;
530 x11drv_thread_data()->last_focus
= hwnd
;
531 if ((xic
= X11DRV_get_ic( hwnd
)))
534 XUnsetICFocus( xic
);
537 if (hwnd
!= GetForegroundWindow()) return;
538 SendMessageA( hwnd
, WM_CANCELMODE
, 0, 0 );
540 /* don't reset the foreground window, if the window which is
541 getting the focus is a Wine window */
544 XGetInputFocus( thread_display(), &focus_win
, &revert
);
547 if (XFindContext( thread_display(), focus_win
, winContext
, (char **)&hwnd_tmp
) != 0)
554 /* Abey : 6-Oct-99. Check again if the focus out window is the
555 Foreground window, because in most cases the messages sent
556 above must have already changed the foreground window, in which
557 case we don't have to change the foreground window to 0 */
558 if (hwnd
== GetForegroundWindow())
560 TRACE( "lost focus, setting fg to 0\n" );
561 SetForegroundWindow( 0 );
567 /***********************************************************************
568 * EVENT_PropertyNotify
569 * We use this to release resources like Pixmaps when a selection
570 * client no longer needs them.
572 static void EVENT_PropertyNotify( HWND hwnd
, XEvent
*xev
)
574 XPropertyEvent
*event
= &xev
->xproperty
;
575 /* Check if we have any resources to free */
576 TRACE("Received PropertyNotify event:\n");
582 TRACE("\tPropertyDelete for atom %ld on window %ld\n",
583 event
->atom
, (long)event
->window
);
587 case PropertyNewValue
:
589 TRACE("\tPropertyNewValue for atom %ld on window %ld\n\n",
590 event
->atom
, (long)event
->window
);
599 static HWND
find_drop_window( HWND hQueryWnd
, LPPOINT lpPt
)
603 if (!IsWindowEnabled(hQueryWnd
)) return 0;
605 GetWindowRect(hQueryWnd
, &tempRect
);
607 if(!PtInRect(&tempRect
, *lpPt
)) return 0;
609 if (!IsIconic( hQueryWnd
))
612 ScreenToClient( hQueryWnd
, &pt
);
613 GetClientRect( hQueryWnd
, &tempRect
);
615 if (PtInRect( &tempRect
, pt
))
617 HWND ret
= ChildWindowFromPointEx( hQueryWnd
, pt
, CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
);
618 if (ret
&& ret
!= hQueryWnd
)
620 ret
= find_drop_window( ret
, lpPt
);
626 if(!(GetWindowLongA( hQueryWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
)) return 0;
628 ScreenToClient(hQueryWnd
, lpPt
);
633 /**********************************************************************
634 * EVENT_DropFromOffix
636 * don't know if it still works (last Changlog is from 96/11/04)
638 static void EVENT_DropFromOffiX( HWND hWnd
, XClientMessageEvent
*event
)
640 unsigned long data_length
;
641 unsigned long aux_long
;
642 unsigned char* p_data
= NULL
;
646 Window win
, w_aux_root
, w_aux_child
;
650 win
= X11DRV_get_whole_window(hWnd
);
652 XQueryPointer( event
->display
, win
, &w_aux_root
, &w_aux_child
,
653 &x
, &y
, &dummy
, &dummy
, (unsigned int*)&aux_long
);
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
);
808 drop_len
+= sizeof(DROPFILES
) + 1;
809 hDrop
= GlobalAlloc( GMEM_SHARE
, drop_len
);
810 lpDrop
= (DROPFILES
*) GlobalLock( hDrop
);
813 WND
*pDropWnd
= WIN_GetPtr( hWnd
);
814 lpDrop
->pFiles
= sizeof(DROPFILES
);
815 lpDrop
->pt
.x
= (INT
)x
;
816 lpDrop
->pt
.y
= (INT
)y
;
818 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
819 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
820 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
821 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
822 lpDrop
->fWide
= FALSE
;
823 p_drop
= (char*)(lpDrop
+ 1);
824 WIN_ReleasePtr(pDropWnd
);
827 /* create message content */
830 next
= strchr(p
, '\n');
833 if (strncmp(p
,"file:",5) == 0 ) {
834 INT len
= GetShortPathNameA( p
+5, p_drop
, 65535 );
836 TRACE("drop file %s as %s\n", p
+5, p_drop
);
839 WARN("can't convert file %s to dos name\n", p
+5);
842 WARN("unknown mime type %s\n", p
);
847 next
= strchr(p
, '\n');
855 PostMessageA( hWnd
, WM_DROPFILES
, (WPARAM
)hDrop
, 0L );
859 if( p_data
) XFree(p_data
);
864 /**********************************************************************
865 * handle_dnd_protocol
867 static void handle_dnd_protocol( HWND hwnd
, XClientMessageEvent
*event
)
870 int root_x
, root_y
, child_x
, child_y
;
873 /* query window (drag&drop event contains only drag window) */
875 XQueryPointer( event
->display
, root_window
, &root
, &child
,
876 &root_x
, &root_y
, &child_x
, &child_y
, &u
);
877 if (XFindContext( event
->display
, child
, winContext
, (char **)&hwnd
) != 0) hwnd
= 0;
880 if (event
->data
.l
[0] == DndFile
|| event
->data
.l
[0] == DndFiles
)
881 EVENT_DropFromOffiX(hwnd
, event
);
882 else if (event
->data
.l
[0] == DndURL
)
883 EVENT_DropURLs(hwnd
, event
);
887 struct client_message_handler
889 int atom
; /* protocol atom */
890 void (*handler
)(HWND
, XClientMessageEvent
*); /* corresponding handler function */
893 static const struct client_message_handler client_messages
[] =
895 { XATOM_WM_PROTOCOLS
, handle_wm_protocols
},
896 { XATOM_DndProtocol
, handle_dnd_protocol
},
897 { XATOM_XdndEnter
, X11DRV_XDND_EnterEvent
},
898 { XATOM_XdndPosition
, X11DRV_XDND_PositionEvent
},
899 { XATOM_XdndDrop
, X11DRV_XDND_DropEvent
},
900 { XATOM_XdndLeave
, X11DRV_XDND_LeaveEvent
}
904 /**********************************************************************
905 * EVENT_ClientMessage
907 static void EVENT_ClientMessage( HWND hwnd
, XEvent
*xev
)
909 XClientMessageEvent
*event
= &xev
->xclient
;
914 if (event
->format
!= 32)
916 WARN( "Don't know how to handle format %d\n", event
->format
);
920 for (i
= 0; i
< sizeof(client_messages
)/sizeof(client_messages
[0]); i
++)
922 if (event
->message_type
== X11DRV_Atoms
[client_messages
[i
].atom
- FIRST_XATOM
])
924 client_messages
[i
].handler( hwnd
, event
);
928 TRACE( "no handler found for %ld\n", event
->message_type
);
932 /**********************************************************************
933 * X11DRV_WindowMessage (X11DRV.@)
935 LRESULT
X11DRV_WindowMessage( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
939 case WM_X11DRV_ACQUIRE_SELECTION
:
940 X11DRV_AcquireClipboard( hwnd
);
942 case WM_X11DRV_DELETE_WINDOW
:
943 return SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
945 FIXME( "got window msg %x hwnd %p wp %x lp %lx\n", msg
, hwnd
, wp
, lp
);
951 /***********************************************************************
952 * X11DRV_SendInput (X11DRV.@)
954 UINT
X11DRV_SendInput( UINT count
, LPINPUT inputs
, int size
)
958 for (i
= 0; i
< count
; i
++, inputs
++)
963 X11DRV_send_mouse_input( 0, inputs
->u
.mi
.dwFlags
, inputs
->u
.mi
.dx
, inputs
->u
.mi
.dy
,
964 inputs
->u
.mi
.mouseData
, inputs
->u
.mi
.time
,
965 inputs
->u
.mi
.dwExtraInfo
, LLMHF_INJECTED
);
968 X11DRV_send_keyboard_input( inputs
->u
.ki
.wVk
, inputs
->u
.ki
.wScan
, inputs
->u
.ki
.dwFlags
,
969 inputs
->u
.ki
.time
, inputs
->u
.ki
.dwExtraInfo
, LLKHF_INJECTED
);
972 FIXME( "INPUT_HARDWARE not supported\n" );