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
);
71 static void EVENT_GravityNotify( 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 */
99 { DestroyNotify
, X11DRV_DestroyNotify
},
100 { UnmapNotify
, X11DRV_UnmapNotify
},
101 { MapNotify
, X11DRV_MapNotify
},
104 { ConfigureNotify
, X11DRV_ConfigureNotify
},
105 /* ConfigureRequest */
106 { GravityNotify
, EVENT_GravityNotify
},
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
= 20; /* 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 static inline 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 );
562 if (forcealtrelease
&& GetAsyncKeyState(VK_MENU
)<0)
564 INPUT fake_alt_release
;
565 fake_alt_release
.type
= INPUT_KEYBOARD
;
566 fake_alt_release
.u
.ki
.wVk
= VK_MENU
;
567 fake_alt_release
.u
.ki
.wScan
= 0;
568 fake_alt_release
.u
.ki
.dwFlags
= KEYEVENTF_KEYUP
;
569 fake_alt_release
.u
.ki
.time
= GetTickCount(); /* is it really this kind of timestamp ? */
570 fake_alt_release
.u
.ki
.dwExtraInfo
= 0;
571 SendInput(1, &fake_alt_release
, sizeof(INPUT
));
577 /***********************************************************************
578 * EVENT_PropertyNotify
579 * We use this to release resources like Pixmaps when a selection
580 * client no longer needs them.
582 static void EVENT_PropertyNotify( HWND hwnd
, XEvent
*xev
)
584 XPropertyEvent
*event
= &xev
->xproperty
;
585 /* Check if we have any resources to free */
586 TRACE("Received PropertyNotify event:\n");
592 TRACE("\tPropertyDelete for atom %ld on window %ld\n",
593 event
->atom
, (long)event
->window
);
597 case PropertyNewValue
:
599 TRACE("\tPropertyNewValue for atom %ld on window %ld\n\n",
600 event
->atom
, (long)event
->window
);
609 static HWND
find_drop_window( HWND hQueryWnd
, LPPOINT lpPt
)
613 if (!IsWindowEnabled(hQueryWnd
)) return 0;
615 GetWindowRect(hQueryWnd
, &tempRect
);
617 if(!PtInRect(&tempRect
, *lpPt
)) return 0;
619 if (!IsIconic( hQueryWnd
))
622 ScreenToClient( hQueryWnd
, &pt
);
623 GetClientRect( hQueryWnd
, &tempRect
);
625 if (PtInRect( &tempRect
, pt
))
627 HWND ret
= ChildWindowFromPointEx( hQueryWnd
, pt
, CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
);
628 if (ret
&& ret
!= hQueryWnd
)
630 ret
= find_drop_window( ret
, lpPt
);
636 if(!(GetWindowLongA( hQueryWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
)) return 0;
638 ScreenToClient(hQueryWnd
, lpPt
);
643 /**********************************************************************
644 * EVENT_DropFromOffix
646 * don't know if it still works (last Changlog is from 96/11/04)
648 static void EVENT_DropFromOffiX( HWND hWnd
, XClientMessageEvent
*event
)
650 unsigned long data_length
;
651 unsigned long aux_long
;
652 unsigned char* p_data
= NULL
;
656 Window win
, w_aux_root
, w_aux_child
;
660 win
= X11DRV_get_whole_window(hWnd
);
662 XQueryPointer( event
->display
, win
, &w_aux_root
, &w_aux_child
,
663 &x
, &y
, &dummy
, &dummy
, (unsigned int*)&aux_long
);
664 x
+= virtual_screen_rect
.left
;
665 y
+= virtual_screen_rect
.top
;
668 pWnd
= WIN_GetPtr(hWnd
);
670 /* find out drop point and drop window */
671 if( x
< 0 || y
< 0 ||
672 x
> (pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) ||
673 y
> (pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
) )
675 bAccept
= pWnd
->dwExStyle
& WS_EX_ACCEPTFILES
;
682 HWND hwndDrop
= find_drop_window( hWnd
, &pt
);
695 WIN_ReleasePtr(pWnd
);
697 if (!bAccept
) return;
700 XGetWindowProperty( event
->display
, DefaultRootWindow(event
->display
),
701 x11drv_atom(DndSelection
), 0, 65535, FALSE
,
702 AnyPropertyType
, &atom_aux
, &dummy
,
703 &data_length
, &aux_long
, &p_data
);
706 if( !aux_long
&& p_data
) /* don't bother if > 64K */
708 char *p
= (char *)p_data
;
712 while( *p
) /* calculate buffer size */
714 INT len
= GetShortPathNameA( p
, NULL
, 0 );
715 if (len
) aux_long
+= len
+ 1;
718 if( aux_long
&& aux_long
< 65535 )
723 aux_long
+= sizeof(DROPFILES
) + 1;
724 hDrop
= GlobalAlloc( GMEM_SHARE
, aux_long
);
725 lpDrop
= (DROPFILES
*)GlobalLock( hDrop
);
729 WND
*pDropWnd
= WIN_GetPtr( hScope
);
730 lpDrop
->pFiles
= sizeof(DROPFILES
);
734 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
735 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
736 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
737 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
738 lpDrop
->fWide
= FALSE
;
739 WIN_ReleasePtr(pDropWnd
);
740 p_drop
= (char *)(lpDrop
+ 1);
744 if (GetShortPathNameA( p
, p_drop
, aux_long
- (p_drop
- (char *)lpDrop
) ))
745 p_drop
+= strlen( p_drop
) + 1;
749 PostMessageA( hWnd
, WM_DROPFILES
, (WPARAM
)hDrop
, 0L );
754 if( p_data
) XFree(p_data
);
758 /**********************************************************************
761 * drop items are separated by \n
762 * each item is prefixed by its mime type
764 * event->data.l[3], event->data.l[4] contains drop x,y position
766 static void EVENT_DropURLs( HWND hWnd
, XClientMessageEvent
*event
)
768 unsigned long data_length
;
769 unsigned long aux_long
, drop_len
= 0;
770 unsigned char *p_data
= NULL
; /* property data */
783 if (!(GetWindowLongW( hWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
)) return;
786 XGetWindowProperty( event
->display
, DefaultRootWindow(event
->display
),
787 x11drv_atom(DndSelection
), 0, 65535, FALSE
,
788 AnyPropertyType
, &u
.atom_aux
, &u
.i
,
789 &data_length
, &aux_long
, &p_data
);
792 WARN("property too large, truncated!\n");
793 TRACE("urls=%s\n", p_data
);
795 if( !aux_long
&& p_data
) { /* don't bother if > 64K */
796 /* calculate length */
798 next
= strchr(p
, '\n');
801 if (strncmp(p
,"file:",5) == 0 ) {
802 INT len
= GetShortPathNameA( p
+5, NULL
, 0 );
803 if (len
) drop_len
+= len
+ 1;
808 next
= strchr(p
, '\n');
814 if( drop_len
&& drop_len
< 65535 ) {
816 XQueryPointer( event
->display
, root_window
, &u
.w_aux
, &u
.w_aux
,
817 &x
, &y
, &u
.i
, &u
.i
, &u
.u
);
818 x
+= virtual_screen_rect
.left
;
819 y
+= virtual_screen_rect
.top
;
822 drop_len
+= sizeof(DROPFILES
) + 1;
823 hDrop
= GlobalAlloc( GMEM_SHARE
, drop_len
);
824 lpDrop
= (DROPFILES
*) GlobalLock( hDrop
);
827 WND
*pDropWnd
= WIN_GetPtr( hWnd
);
828 lpDrop
->pFiles
= sizeof(DROPFILES
);
829 lpDrop
->pt
.x
= (INT
)x
;
830 lpDrop
->pt
.y
= (INT
)y
;
832 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
833 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
834 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
835 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
836 lpDrop
->fWide
= FALSE
;
837 p_drop
= (char*)(lpDrop
+ 1);
838 WIN_ReleasePtr(pDropWnd
);
841 /* create message content */
844 next
= strchr(p
, '\n');
847 if (strncmp(p
,"file:",5) == 0 ) {
848 INT len
= GetShortPathNameA( p
+5, p_drop
, 65535 );
850 TRACE("drop file %s as %s\n", p
+5, p_drop
);
853 WARN("can't convert file %s to dos name\n", p
+5);
856 WARN("unknown mime type %s\n", p
);
861 next
= strchr(p
, '\n');
869 PostMessageA( hWnd
, WM_DROPFILES
, (WPARAM
)hDrop
, 0L );
873 if( p_data
) XFree(p_data
);
878 /**********************************************************************
879 * handle_dnd_protocol
881 static void handle_dnd_protocol( HWND hwnd
, XClientMessageEvent
*event
)
884 int root_x
, root_y
, child_x
, child_y
;
887 /* query window (drag&drop event contains only drag window) */
889 XQueryPointer( event
->display
, root_window
, &root
, &child
,
890 &root_x
, &root_y
, &child_x
, &child_y
, &u
);
891 if (XFindContext( event
->display
, child
, winContext
, (char **)&hwnd
) != 0) hwnd
= 0;
894 if (event
->data
.l
[0] == DndFile
|| event
->data
.l
[0] == DndFiles
)
895 EVENT_DropFromOffiX(hwnd
, event
);
896 else if (event
->data
.l
[0] == DndURL
)
897 EVENT_DropURLs(hwnd
, event
);
901 struct client_message_handler
903 int atom
; /* protocol atom */
904 void (*handler
)(HWND
, XClientMessageEvent
*); /* corresponding handler function */
907 static const struct client_message_handler client_messages
[] =
909 { XATOM_WM_PROTOCOLS
, handle_wm_protocols
},
910 { XATOM_DndProtocol
, handle_dnd_protocol
},
911 { XATOM_XdndEnter
, X11DRV_XDND_EnterEvent
},
912 { XATOM_XdndPosition
, X11DRV_XDND_PositionEvent
},
913 { XATOM_XdndDrop
, X11DRV_XDND_DropEvent
},
914 { XATOM_XdndLeave
, X11DRV_XDND_LeaveEvent
}
918 /**********************************************************************
919 * EVENT_ClientMessage
921 static void EVENT_ClientMessage( HWND hwnd
, XEvent
*xev
)
923 XClientMessageEvent
*event
= &xev
->xclient
;
928 if (event
->format
!= 32)
930 WARN( "Don't know how to handle format %d\n", event
->format
);
934 for (i
= 0; i
< sizeof(client_messages
)/sizeof(client_messages
[0]); i
++)
936 if (event
->message_type
== X11DRV_Atoms
[client_messages
[i
].atom
- FIRST_XATOM
])
938 client_messages
[i
].handler( hwnd
, event
);
942 TRACE( "no handler found for %ld\n", event
->message_type
);
946 /**********************************************************************
947 * EVENT_GravityNotify
949 static void EVENT_GravityNotify( HWND hwnd
, XEvent
*event
)
951 struct x11drv_win_data
*data
= X11DRV_get_win_data( hwnd
);
953 /* In this case we don't get a ConfigureNotify so we fake it */
956 int flags
= SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
;
957 WND
*pWnd
= WIN_GetPtr(hwnd
);
959 if (event
->xgravity
.x
== pWnd
->rectWindow
.left
&& event
->xgravity
.y
== pWnd
->rectWindow
.top
)
962 WIN_ReleasePtr( pWnd
);
964 if (~flags
& SWP_NOMOVE
)
966 data
->lock_changes
++;
967 SetWindowPos( hwnd
, 0, event
->xgravity
.x
, event
->xgravity
.y
, 0, 0, flags
);
968 data
->lock_changes
--;
974 /**********************************************************************
975 * X11DRV_WindowMessage (X11DRV.@)
977 LRESULT
X11DRV_WindowMessage( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
981 case WM_X11DRV_ACQUIRE_SELECTION
:
982 return X11DRV_AcquireClipboard( hwnd
);
983 case WM_X11DRV_DELETE_WINDOW
:
984 return SendMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
986 FIXME( "got window msg %x hwnd %p wp %x lp %lx\n", msg
, hwnd
, wp
, lp
);
992 /***********************************************************************
993 * X11DRV_SendInput (X11DRV.@)
995 UINT
X11DRV_SendInput( UINT count
, LPINPUT inputs
, int size
)
999 for (i
= 0; i
< count
; i
++, inputs
++)
1001 switch(inputs
->type
)
1004 X11DRV_send_mouse_input( 0, inputs
->u
.mi
.dwFlags
, inputs
->u
.mi
.dx
, inputs
->u
.mi
.dy
,
1005 inputs
->u
.mi
.mouseData
, inputs
->u
.mi
.time
,
1006 inputs
->u
.mi
.dwExtraInfo
, LLMHF_INJECTED
);
1008 case INPUT_KEYBOARD
:
1009 X11DRV_send_keyboard_input( inputs
->u
.ki
.wVk
, inputs
->u
.ki
.wScan
, inputs
->u
.ki
.dwFlags
,
1010 inputs
->u
.ki
.time
, inputs
->u
.ki
.dwExtraInfo
, LLKHF_INJECTED
);
1012 case INPUT_HARDWARE
:
1013 FIXME( "INPUT_HARDWARE not supported\n" );