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
27 #ifdef HAVE_SYS_POLL_H
30 #include <X11/Xatom.h>
31 #include <X11/keysym.h>
33 #include <X11/Xresource.h>
34 #include <X11/Xutil.h>
35 #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
36 #include <X11/extensions/XInput2.h>
43 #define NONAMELESSUNION
44 #define NONAMELESSSTRUCT
52 /* avoid conflict with field names in included win32 headers */
54 #include "shlobj.h" /* DROPFILES */
57 #include "wine/server.h"
58 #include "wine/debug.h"
60 WINE_DEFAULT_DEBUG_CHANNEL(event
);
62 extern BOOL ximInComposeMode
;
64 #define DndNotDnd -1 /* OffiX drag&drop */
76 #define DndURL 128 /* KDE drag&drop */
78 #define XEMBED_EMBEDDED_NOTIFY 0
79 #define XEMBED_WINDOW_ACTIVATE 1
80 #define XEMBED_WINDOW_DEACTIVATE 2
81 #define XEMBED_REQUEST_FOCUS 3
82 #define XEMBED_FOCUS_IN 4
83 #define XEMBED_FOCUS_OUT 5
84 #define XEMBED_FOCUS_NEXT 6
85 #define XEMBED_FOCUS_PREV 7
86 #define XEMBED_MODALITY_ON 10
87 #define XEMBED_MODALITY_OFF 11
88 #define XEMBED_REGISTER_ACCELERATOR 12
89 #define XEMBED_UNREGISTER_ACCELERATOR 13
90 #define XEMBED_ACTIVATE_ACCELERATOR 14
92 Bool (*pXGetEventData
)( Display
*display
, XEvent
/*XGenericEventCookie*/ *event
) = NULL
;
93 void (*pXFreeEventData
)( Display
*display
, XEvent
/*XGenericEventCookie*/ *event
) = NULL
;
96 static void X11DRV_FocusIn( HWND hwnd
, XEvent
*event
);
97 static void X11DRV_FocusOut( HWND hwnd
, XEvent
*event
);
98 static void X11DRV_Expose( HWND hwnd
, XEvent
*event
);
99 static void X11DRV_MapNotify( HWND hwnd
, XEvent
*event
);
100 static void X11DRV_UnmapNotify( HWND hwnd
, XEvent
*event
);
101 static void X11DRV_ReparentNotify( HWND hwnd
, XEvent
*event
);
102 static void X11DRV_ConfigureNotify( HWND hwnd
, XEvent
*event
);
103 static void X11DRV_PropertyNotify( HWND hwnd
, XEvent
*event
);
104 static void X11DRV_ClientMessage( HWND hwnd
, XEvent
*event
);
105 static void X11DRV_GravityNotify( HWND hwnd
, XEvent
*event
);
107 #define MAX_EVENT_HANDLERS 128
109 static x11drv_event_handler handlers
[MAX_EVENT_HANDLERS
] =
111 NULL
, /* 0 reserved */
112 NULL
, /* 1 reserved */
113 X11DRV_KeyEvent
, /* 2 KeyPress */
114 X11DRV_KeyEvent
, /* 3 KeyRelease */
115 X11DRV_ButtonPress
, /* 4 ButtonPress */
116 X11DRV_ButtonRelease
, /* 5 ButtonRelease */
117 X11DRV_MotionNotify
, /* 6 MotionNotify */
118 X11DRV_EnterNotify
, /* 7 EnterNotify */
119 NULL
, /* 8 LeaveNotify */
120 X11DRV_FocusIn
, /* 9 FocusIn */
121 X11DRV_FocusOut
, /* 10 FocusOut */
122 X11DRV_KeymapNotify
, /* 11 KeymapNotify */
123 X11DRV_Expose
, /* 12 Expose */
124 NULL
, /* 13 GraphicsExpose */
125 NULL
, /* 14 NoExpose */
126 NULL
, /* 15 VisibilityNotify */
127 NULL
, /* 16 CreateNotify */
128 X11DRV_DestroyNotify
, /* 17 DestroyNotify */
129 X11DRV_UnmapNotify
, /* 18 UnmapNotify */
130 X11DRV_MapNotify
, /* 19 MapNotify */
131 NULL
, /* 20 MapRequest */
132 X11DRV_ReparentNotify
, /* 21 ReparentNotify */
133 X11DRV_ConfigureNotify
, /* 22 ConfigureNotify */
134 NULL
, /* 23 ConfigureRequest */
135 X11DRV_GravityNotify
, /* 24 GravityNotify */
136 NULL
, /* 25 ResizeRequest */
137 NULL
, /* 26 CirculateNotify */
138 NULL
, /* 27 CirculateRequest */
139 X11DRV_PropertyNotify
, /* 28 PropertyNotify */
140 X11DRV_SelectionClear
, /* 29 SelectionClear */
141 X11DRV_SelectionRequest
, /* 30 SelectionRequest */
142 NULL
, /* 31 SelectionNotify */
143 NULL
, /* 32 ColormapNotify */
144 X11DRV_ClientMessage
, /* 33 ClientMessage */
145 X11DRV_MappingNotify
, /* 34 MappingNotify */
146 X11DRV_GenericEvent
/* 35 GenericEvent */
149 static const char * event_names
[MAX_EVENT_HANDLERS
] =
151 NULL
, NULL
, "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
152 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
153 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
154 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
155 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify", "ResizeRequest",
156 "CirculateNotify", "CirculateRequest", "PropertyNotify", "SelectionClear", "SelectionRequest",
157 "SelectionNotify", "ColormapNotify", "ClientMessage", "MappingNotify", "GenericEvent"
160 int xinput2_opcode
= 0;
162 /* return the name of an X event */
163 static const char *dbgstr_event( int type
)
165 if (type
< MAX_EVENT_HANDLERS
&& event_names
[type
]) return event_names
[type
];
166 return wine_dbg_sprintf( "Unknown event %d", type
);
169 static inline void get_event_data( XEvent
*event
)
171 #if defined(GenericEvent) && defined(HAVE_XEVENT_XCOOKIE)
172 if (event
->xany
.type
!= GenericEvent
) return;
173 if (!pXGetEventData
|| !pXGetEventData( event
->xany
.display
, event
)) event
->xcookie
.data
= NULL
;
177 static inline void free_event_data( XEvent
*event
)
179 #if defined(GenericEvent) && defined(HAVE_XEVENT_XCOOKIE)
180 if (event
->xany
.type
!= GenericEvent
) return;
181 if (event
->xcookie
.data
) pXFreeEventData( event
->xany
.display
, event
);
185 /***********************************************************************
186 * X11DRV_register_event_handler
188 * Register a handler for a given event type.
189 * If already registered, overwrite the previous handler.
191 void X11DRV_register_event_handler( int type
, x11drv_event_handler handler
, const char *name
)
193 assert( type
< MAX_EVENT_HANDLERS
);
194 assert( !handlers
[type
] || handlers
[type
] == handler
);
195 handlers
[type
] = handler
;
196 event_names
[type
] = name
;
197 TRACE("registered handler %p for event %d %s\n", handler
, type
, debugstr_a(name
) );
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
|QS_HOTKEY
)) != 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 enum event_merge_action
242 MERGE_DISCARD
, /* discard the old event */
243 MERGE_HANDLE
, /* handle the old event */
244 MERGE_KEEP
, /* keep the old event for future merging */
245 MERGE_IGNORE
/* ignore the new event, keep the old one */
248 /***********************************************************************
249 * merge_raw_motion_events
251 #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
252 static enum event_merge_action
merge_raw_motion_events( XIRawEvent
*prev
, XIRawEvent
*next
)
257 if (!prev
->valuators
.mask_len
) return MERGE_HANDLE
;
258 if (!next
->valuators
.mask_len
) return MERGE_HANDLE
;
260 mask
= prev
->valuators
.mask
[0] | next
->valuators
.mask
[0];
261 if (mask
== next
->valuators
.mask
[0]) /* keep next */
263 for (i
= j
= k
= 0; i
< 8; i
++)
265 if (XIMaskIsSet( prev
->valuators
.mask
, i
))
266 next
->valuators
.values
[j
] += prev
->valuators
.values
[k
++];
267 if (XIMaskIsSet( next
->valuators
.mask
, i
)) j
++;
269 TRACE( "merging duplicate GenericEvent\n" );
270 return MERGE_DISCARD
;
272 if (mask
== prev
->valuators
.mask
[0]) /* keep prev */
274 for (i
= j
= k
= 0; i
< 8; i
++)
276 if (XIMaskIsSet( next
->valuators
.mask
, i
))
277 prev
->valuators
.values
[j
] += next
->valuators
.values
[k
++];
278 if (XIMaskIsSet( prev
->valuators
.mask
, i
)) j
++;
280 TRACE( "merging duplicate GenericEvent\n" );
283 /* can't merge events with disjoint masks */
288 /***********************************************************************
291 * Try to merge 2 consecutive events.
293 static enum event_merge_action
merge_events( XEvent
*prev
, XEvent
*next
)
297 case ConfigureNotify
:
300 case ConfigureNotify
:
301 if (prev
->xany
.window
== next
->xany
.window
)
303 TRACE( "discarding duplicate ConfigureNotify for window %lx\n", prev
->xany
.window
);
304 return MERGE_DISCARD
;
316 if (prev
->xany
.window
== next
->xany
.window
)
318 TRACE( "discarding duplicate MotionNotify for window %lx\n", prev
->xany
.window
);
319 return MERGE_DISCARD
;
322 #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
324 if (next
->xcookie
.extension
!= xinput2_opcode
) break;
325 if (next
->xcookie
.evtype
!= XI_RawMotion
) break;
326 if (x11drv_thread_data()->warp_serial
) break;
331 if (prev
->xcookie
.extension
!= xinput2_opcode
) break;
332 if (prev
->xcookie
.evtype
!= XI_RawMotion
) break;
336 if (next
->xcookie
.extension
!= xinput2_opcode
) break;
337 if (next
->xcookie
.evtype
!= XI_RawMotion
) break;
338 if (x11drv_thread_data()->warp_serial
) break;
339 return merge_raw_motion_events( prev
->xcookie
.data
, next
->xcookie
.data
);
348 /***********************************************************************
351 static inline void call_event_handler( Display
*display
, XEvent
*event
)
355 struct x11drv_thread_data
*thread_data
;
357 if (!handlers
[event
->type
])
359 TRACE( "%s for win %lx, ignoring\n", dbgstr_event( event
->type
), event
->xany
.window
);
360 return; /* no handler, ignore it */
363 if (XFindContext( display
, event
->xany
.window
, winContext
, (char **)&hwnd
) != 0)
364 hwnd
= 0; /* not for a registered window */
365 if (!hwnd
&& event
->xany
.window
== root_window
) hwnd
= GetDesktopWindow();
367 TRACE( "%lu %s for hwnd/window %p/%lx\n",
368 event
->xany
.serial
, dbgstr_event( event
->type
), hwnd
, event
->xany
.window
);
370 thread_data
= x11drv_thread_data();
371 prev
= thread_data
->current_event
;
372 thread_data
->current_event
= event
;
373 handlers
[event
->type
]( hwnd
, event
);
374 thread_data
->current_event
= prev
;
379 /***********************************************************************
382 static int process_events( Display
*display
, Bool (*filter
)(Display
*, XEvent
*,XPointer
), ULONG_PTR arg
)
384 XEvent event
, prev_event
;
386 enum event_merge_action action
= MERGE_DISCARD
;
390 while (XCheckIfEvent( display
, &event
, filter
, (char *)arg
))
393 if (XFilterEvent( &event
, None
))
396 * SCIM on linux filters key events strangely. It does not filter the
397 * KeyPress events for these keys however it does filter the
398 * KeyRelease events. This causes wine to become very confused as
399 * to the keyboard state.
401 * We need to let those KeyRelease events be processed so that the
402 * keyboard state is correct.
404 if (event
.type
== KeyRelease
)
407 XKeyEvent
*keyevent
= &event
.xkey
;
409 XLookupString(keyevent
, NULL
, 0, &keysym
, NULL
);
410 if (!(keysym
== XK_Shift_L
||
411 keysym
== XK_Shift_R
||
412 keysym
== XK_Control_L
||
413 keysym
== XK_Control_R
||
414 keysym
== XK_Alt_R
||
415 keysym
== XK_Alt_L
||
416 keysym
== XK_Meta_R
||
417 keysym
== XK_Meta_L
))
418 continue; /* not a key we care about, ignore it */
421 continue; /* filtered, ignore it */
423 get_event_data( &event
);
424 if (prev_event
.type
) action
= merge_events( &prev_event
, &event
);
427 case MERGE_HANDLE
: /* handle prev, keep new */
428 call_event_handler( display
, &prev_event
);
430 case MERGE_DISCARD
: /* discard prev, keep new */
431 free_event_data( &prev_event
);
434 case MERGE_KEEP
: /* handle new, keep prev for future merging */
435 call_event_handler( display
, &event
);
437 case MERGE_IGNORE
: /* ignore new, keep prev for future merging */
438 free_event_data( &event
);
442 if (prev_event
.type
) call_event_handler( display
, &prev_event
);
443 free_event_data( &prev_event
);
444 XFlush( gdi_display
);
446 if (count
) TRACE( "processed %d events\n", count
);
451 /***********************************************************************
452 * MsgWaitForMultipleObjectsEx (X11DRV.@)
454 DWORD CDECL
X11DRV_MsgWaitForMultipleObjectsEx( DWORD count
, const HANDLE
*handles
,
455 DWORD timeout
, DWORD mask
, DWORD flags
)
458 struct x11drv_thread_data
*data
= TlsGetValue( thread_data_tls_index
);
462 if (!count
&& !timeout
) return WAIT_TIMEOUT
;
463 return WaitForMultipleObjectsEx( count
, handles
, flags
& MWMO_WAITALL
,
464 timeout
, flags
& MWMO_ALERTABLE
);
467 if (data
->current_event
) mask
= 0; /* don't process nested events */
469 if (process_events( data
->display
, filter_event
, mask
)) ret
= count
- 1;
470 else if (count
|| timeout
)
472 ret
= WaitForMultipleObjectsEx( count
, handles
, flags
& MWMO_WAITALL
,
473 timeout
, flags
& MWMO_ALERTABLE
);
474 if (ret
== count
- 1) process_events( data
->display
, filter_event
, mask
);
476 else ret
= WAIT_TIMEOUT
;
481 /***********************************************************************
482 * EVENT_x11_time_to_win32_time
484 * Make our timer and the X timer line up as best we can
485 * Pass 0 to retrieve the current adjustment value (times -1)
487 DWORD
EVENT_x11_time_to_win32_time(Time time
)
489 static DWORD adjust
= 0;
490 DWORD now
= GetTickCount();
493 if (! adjust
&& time
!= 0)
500 /* If we got an event in the 'future', then our clock is clearly wrong.
501 If we got it more than 10000 ms in the future, then it's most likely
502 that the clock has wrapped. */
505 if (ret
> now
&& ((ret
- now
) < 10000) && time
!= 0)
516 /*******************************************************************
517 * can_activate_window
519 * Check if we can activate the specified window.
521 static inline BOOL
can_activate_window( HWND hwnd
)
523 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
524 if (!(style
& WS_VISIBLE
)) return FALSE
;
525 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
526 if (style
& WS_MINIMIZE
) return FALSE
;
527 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_NOACTIVATE
) return FALSE
;
528 if (hwnd
== GetDesktopWindow()) return FALSE
;
529 return !(style
& WS_DISABLED
);
533 /**********************************************************************
536 static void set_focus( Display
*display
, HWND hwnd
, Time time
)
540 GUITHREADINFO threadinfo
;
542 TRACE( "setting foreground window to %p\n", hwnd
);
543 SetForegroundWindow( hwnd
);
545 threadinfo
.cbSize
= sizeof(threadinfo
);
546 GetGUIThreadInfo(0, &threadinfo
);
547 focus
= threadinfo
.hwndFocus
;
548 if (!focus
) focus
= threadinfo
.hwndActive
;
549 if (focus
) focus
= GetAncestor( focus
, GA_ROOT
);
550 win
= X11DRV_get_whole_window(focus
);
554 TRACE( "setting focus to %p (%lx) time=%ld\n", focus
, win
, time
);
556 XSetInputFocus( display
, win
, RevertToParent
, time
);
562 /**********************************************************************
563 * handle_manager_message
565 static void handle_manager_message( HWND hwnd
, XClientMessageEvent
*event
)
567 if (hwnd
!= GetDesktopWindow()) return;
568 if (systray_atom
&& event
->data
.l
[1] == systray_atom
)
569 change_systray_owner( event
->display
, event
->data
.l
[2] );
573 /**********************************************************************
574 * handle_wm_protocols
576 static void handle_wm_protocols( HWND hwnd
, XClientMessageEvent
*event
)
578 Atom protocol
= (Atom
)event
->data
.l
[0];
579 Time event_time
= (Time
)event
->data
.l
[1];
581 if (!protocol
) return;
583 if (protocol
== x11drv_atom(WM_DELETE_WINDOW
))
585 update_user_time( event_time
);
587 if (hwnd
== GetDesktopWindow())
589 /* The desktop window does not have a close button that we can
590 * pretend to click. Therefore, we simply send it a close command. */
591 SendMessageW(hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
595 /* Ignore the delete window request if the window has been disabled
596 * and we are in managed mode. This is to disallow applications from
597 * being closed by the window manager while in a modal state.
599 if (IsWindowEnabled(hwnd
))
603 if (GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
) return;
604 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
607 UINT state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
608 if (state
== 0xFFFFFFFF || (state
& (MF_DISABLED
| MF_GRAYED
)))
611 if (GetActiveWindow() != hwnd
)
613 LRESULT ma
= SendMessageW( hwnd
, WM_MOUSEACTIVATE
,
614 (WPARAM
)GetAncestor( hwnd
, GA_ROOT
),
615 MAKELPARAM( HTCLOSE
, WM_NCLBUTTONDOWN
) );
618 case MA_NOACTIVATEANDEAT
:
619 case MA_ACTIVATEANDEAT
:
625 SetActiveWindow(hwnd
);
628 WARN( "unknown WM_MOUSEACTIVATE code %d\n", (int) ma
);
633 PostMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
636 else if (protocol
== x11drv_atom(WM_TAKE_FOCUS
))
638 HWND last_focus
= x11drv_thread_data()->last_focus
;
640 TRACE( "got take focus msg for %p, enabled=%d, visible=%d (style %08x), focus=%p, active=%p, fg=%p, last=%p\n",
641 hwnd
, IsWindowEnabled(hwnd
), IsWindowVisible(hwnd
), GetWindowLongW(hwnd
, GWL_STYLE
),
642 GetFocus(), GetActiveWindow(), GetForegroundWindow(), last_focus
);
644 if (can_activate_window(hwnd
))
646 /* simulate a mouse click on the caption to find out
647 * whether the window wants to be activated */
648 LRESULT ma
= SendMessageW( hwnd
, WM_MOUSEACTIVATE
,
649 (WPARAM
)GetAncestor( hwnd
, GA_ROOT
),
650 MAKELONG(HTCAPTION
,WM_LBUTTONDOWN
) );
651 if (ma
!= MA_NOACTIVATEANDEAT
&& ma
!= MA_NOACTIVATE
)
653 set_focus( event
->display
, hwnd
, event_time
);
657 else if (hwnd
== GetDesktopWindow())
659 hwnd
= GetForegroundWindow();
660 if (!hwnd
) hwnd
= last_focus
;
661 if (!hwnd
) hwnd
= GetDesktopWindow();
662 set_focus( event
->display
, hwnd
, event_time
);
665 /* try to find some other window to give the focus to */
667 if (hwnd
) hwnd
= GetAncestor( hwnd
, GA_ROOT
);
668 if (!hwnd
) hwnd
= GetActiveWindow();
669 if (!hwnd
) hwnd
= last_focus
;
670 if (hwnd
&& can_activate_window(hwnd
)) set_focus( event
->display
, hwnd
, event_time
);
672 else if (protocol
== x11drv_atom(_NET_WM_PING
))
674 XClientMessageEvent xev
;
677 TRACE("NET_WM Ping\n");
679 xev
.window
= DefaultRootWindow(xev
.display
);
680 XSendEvent(xev
.display
, xev
.window
, False
, SubstructureRedirectMask
| SubstructureNotifyMask
, (XEvent
*)&xev
);
682 /* this line is semi-stolen from gtk2 */
683 TRACE("NET_WM Pong\n");
688 static const char * const focus_details
[] =
694 "NotifyNonlinearVirtual",
700 /**********************************************************************
703 static void X11DRV_FocusIn( HWND hwnd
, XEvent
*xev
)
705 XFocusChangeEvent
*event
= &xev
->xfocus
;
710 TRACE( "win %p xwin %lx detail=%s\n", hwnd
, event
->window
, focus_details
[event
->detail
] );
712 if (event
->detail
== NotifyPointer
) return;
713 if (hwnd
== GetDesktopWindow()) return;
715 if ((xic
= X11DRV_get_ic( hwnd
)))
723 if (hwnd
== GetForegroundWindow()) clip_fullscreen_window( hwnd
, FALSE
);
727 if (!can_activate_window(hwnd
))
729 HWND hwnd
= GetFocus();
730 if (hwnd
) hwnd
= GetAncestor( hwnd
, GA_ROOT
);
731 if (!hwnd
) hwnd
= GetActiveWindow();
732 if (!hwnd
) hwnd
= x11drv_thread_data()->last_focus
;
733 if (hwnd
&& can_activate_window(hwnd
)) set_focus( event
->display
, hwnd
, CurrentTime
);
735 else SetForegroundWindow( hwnd
);
739 /**********************************************************************
742 * Note: only top-level windows get FocusOut events.
744 static void X11DRV_FocusOut( HWND hwnd
, XEvent
*xev
)
746 XFocusChangeEvent
*event
= &xev
->xfocus
;
752 TRACE( "win %p xwin %lx detail=%s\n", hwnd
, event
->window
, focus_details
[event
->detail
] );
754 if (event
->detail
== NotifyPointer
)
756 if (!hwnd
&& event
->window
== x11drv_thread_data()->clip_window
) reset_clipping_window();
759 if (ximInComposeMode
) return;
761 x11drv_thread_data()->last_focus
= hwnd
;
762 if ((xic
= X11DRV_get_ic( hwnd
)))
765 XUnsetICFocus( xic
);
768 if (root_window
!= DefaultRootWindow(event
->display
))
770 if (hwnd
== GetDesktopWindow()) reset_clipping_window();
773 if (hwnd
!= GetForegroundWindow()) return;
774 SendMessageW( hwnd
, WM_CANCELMODE
, 0, 0 );
776 /* don't reset the foreground window, if the window which is
777 getting the focus is a Wine window */
780 XGetInputFocus( event
->display
, &focus_win
, &revert
);
783 if (XFindContext( event
->display
, focus_win
, winContext
, (char **)&hwnd_tmp
) != 0)
790 /* Abey : 6-Oct-99. Check again if the focus out window is the
791 Foreground window, because in most cases the messages sent
792 above must have already changed the foreground window, in which
793 case we don't have to change the foreground window to 0 */
794 if (hwnd
== GetForegroundWindow())
796 TRACE( "lost focus, setting fg to desktop\n" );
797 SetForegroundWindow( GetDesktopWindow() );
803 /***********************************************************************
806 static void X11DRV_Expose( HWND hwnd
, XEvent
*xev
)
808 XExposeEvent
*event
= &xev
->xexpose
;
810 struct x11drv_win_data
*data
;
811 int flags
= RDW_INVALIDATE
| RDW_ERASE
;
813 TRACE( "win %p (%lx) %d,%d %dx%d\n",
814 hwnd
, event
->window
, event
->x
, event
->y
, event
->width
, event
->height
);
816 if (!(data
= X11DRV_get_win_data( hwnd
))) return;
818 rect
.left
= event
->x
;
820 rect
.right
= event
->x
+ event
->width
;
821 rect
.bottom
= event
->y
+ event
->height
;
822 if (event
->window
== data
->whole_window
)
824 OffsetRect( &rect
, data
->whole_rect
.left
- data
->client_rect
.left
,
825 data
->whole_rect
.top
- data
->client_rect
.top
);
829 if (event
->window
!= root_window
)
831 if (GetWindowLongW( data
->hwnd
, GWL_EXSTYLE
) & WS_EX_LAYOUTRTL
)
832 mirror_rect( &data
->client_rect
, &rect
);
834 SERVER_START_REQ( update_window_zorder
)
836 req
->window
= wine_server_user_handle( hwnd
);
837 req
->rect
.left
= rect
.left
;
838 req
->rect
.top
= rect
.top
;
839 req
->rect
.right
= rect
.right
;
840 req
->rect
.bottom
= rect
.bottom
;
841 wine_server_call( req
);
845 flags
|= RDW_ALLCHILDREN
;
847 else OffsetRect( &rect
, virtual_screen_rect
.left
, virtual_screen_rect
.top
);
849 RedrawWindow( hwnd
, &rect
, 0, flags
);
853 /**********************************************************************
856 static void X11DRV_MapNotify( HWND hwnd
, XEvent
*event
)
858 struct x11drv_win_data
*data
;
860 if (event
->xany
.window
== x11drv_thread_data()->clip_window
)
865 if (!(data
= X11DRV_get_win_data( hwnd
))) return;
866 if (!data
->mapped
|| data
->embedded
) return;
870 HWND hwndFocus
= GetFocus();
871 if (hwndFocus
&& IsChild( hwnd
, hwndFocus
)) X11DRV_SetFocus(hwndFocus
); /* FIXME */
876 /**********************************************************************
879 static void X11DRV_UnmapNotify( HWND hwnd
, XEvent
*event
)
881 if (event
->xany
.window
== x11drv_thread_data()->clip_window
) clipping_cursor
= 0;
885 /***********************************************************************
886 * is_net_wm_state_maximized
888 static BOOL
is_net_wm_state_maximized( Display
*display
, struct x11drv_win_data
*data
)
892 unsigned long i
, count
, remaining
;
894 if (!data
->whole_window
) return FALSE
;
897 if (!XGetWindowProperty( display
, data
->whole_window
, x11drv_atom(_NET_WM_STATE
), 0,
898 65536/sizeof(CARD32
), False
, XA_ATOM
, &type
, &format
, &count
,
899 &remaining
, (unsigned char **)&state
))
901 if (type
== XA_ATOM
&& format
== 32)
903 for (i
= 0; i
< count
; i
++)
905 if (state
[i
] == x11drv_atom(_NET_WM_STATE_MAXIMIZED_VERT
) ||
906 state
[i
] == x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ
))
917 /***********************************************************************
918 * X11DRV_ReparentNotify
920 static void X11DRV_ReparentNotify( HWND hwnd
, XEvent
*xev
)
922 XReparentEvent
*event
= &xev
->xreparent
;
923 struct x11drv_win_data
*data
;
924 HWND parent
, old_parent
;
927 if (!(data
= X11DRV_get_win_data( hwnd
))) return;
928 if (!data
->embedded
) return;
930 if (data
->whole_window
)
932 if (event
->parent
== root_window
)
934 TRACE( "%p/%lx reparented to root\n", hwnd
, data
->whole_window
);
936 SendMessageW( hwnd
, WM_CLOSE
, 0, 0 );
939 data
->embedder
= event
->parent
;
942 TRACE( "%p/%lx reparented to %lx\n", hwnd
, data
->whole_window
, event
->parent
);
944 style
= GetWindowLongW( hwnd
, GWL_STYLE
);
945 if (event
->parent
== root_window
)
947 parent
= GetDesktopWindow();
948 style
= (style
& ~WS_CHILD
) | WS_POPUP
;
952 if (!(parent
= create_foreign_window( event
->display
, event
->parent
))) return;
953 style
= (style
& ~WS_POPUP
) | WS_CHILD
;
956 ShowWindow( hwnd
, SW_HIDE
);
957 old_parent
= SetParent( hwnd
, parent
);
958 SetWindowLongW( hwnd
, GWL_STYLE
, style
);
959 SetWindowPos( hwnd
, HWND_TOP
, event
->x
, event
->y
, 0, 0,
960 SWP_NOACTIVATE
| SWP_NOSIZE
| SWP_NOCOPYBITS
|
961 ((style
& WS_VISIBLE
) ? SWP_SHOWWINDOW
: 0) );
963 /* make old parent destroy itself if it no longer has children */
964 if (old_parent
!= GetDesktopWindow()) PostMessageW( old_parent
, WM_CLOSE
, 0, 0 );
968 /***********************************************************************
969 * X11DRV_ConfigureNotify
971 void X11DRV_ConfigureNotify( HWND hwnd
, XEvent
*xev
)
973 XConfigureEvent
*event
= &xev
->xconfigure
;
974 struct x11drv_win_data
*data
;
979 int cx
, cy
, x
= event
->x
, y
= event
->y
;
982 if (!(data
= X11DRV_get_win_data( hwnd
))) return;
983 if (!data
->mapped
|| data
->iconic
) return;
984 if (data
->whole_window
&& !data
->managed
) return;
985 /* ignore synthetic events on foreign windows */
986 if (event
->send_event
&& !data
->whole_window
) return;
987 if (data
->configure_serial
&& (long)(data
->configure_serial
- event
->serial
) > 0)
989 TRACE( "win %p/%lx event %d,%d,%dx%d ignoring old serial %lu/%lu\n",
990 hwnd
, data
->whole_window
, event
->x
, event
->y
, event
->width
, event
->height
,
991 event
->serial
, data
->configure_serial
);
997 parent
= GetAncestor( hwnd
, GA_PARENT
);
998 root_coords
= event
->send_event
; /* synthetic events are always in root coords */
1000 if (!root_coords
&& parent
== GetDesktopWindow()) /* normal event, map coordinates to the root */
1004 XTranslateCoordinates( event
->display
, event
->window
, root_window
,
1005 0, 0, &x
, &y
, &child
);
1006 wine_tsx11_unlock();
1011 rect
.right
= x
+ event
->width
;
1012 rect
.bottom
= y
+ event
->height
;
1013 if (root_coords
) OffsetRect( &rect
, virtual_screen_rect
.left
, virtual_screen_rect
.top
);
1014 TRACE( "win %p/%lx new X rect %d,%d,%dx%d (event %d,%d,%dx%d)\n",
1015 hwnd
, data
->whole_window
, rect
.left
, rect
.top
, rect
.right
-rect
.left
, rect
.bottom
-rect
.top
,
1016 event
->x
, event
->y
, event
->width
, event
->height
);
1018 X11DRV_X_to_window_rect( data
, &rect
);
1019 if (root_coords
) MapWindowPoints( 0, parent
, (POINT
*)&rect
, 2 );
1021 /* Compare what has changed */
1025 cx
= rect
.right
- rect
.left
;
1026 cy
= rect
.bottom
- rect
.top
;
1027 flags
= SWP_NOACTIVATE
| SWP_NOZORDER
;
1029 if (!data
->whole_window
) flags
|= SWP_NOCOPYBITS
; /* we can't copy bits of foreign windows */
1031 if (data
->window_rect
.left
== x
&& data
->window_rect
.top
== y
) flags
|= SWP_NOMOVE
;
1033 TRACE( "%p moving from (%d,%d) to (%d,%d)\n",
1034 hwnd
, data
->window_rect
.left
, data
->window_rect
.top
, x
, y
);
1036 if ((data
->window_rect
.right
- data
->window_rect
.left
== cx
&&
1037 data
->window_rect
.bottom
- data
->window_rect
.top
== cy
) ||
1038 (IsRectEmpty( &data
->window_rect
) && event
->width
== 1 && event
->height
== 1))
1040 if (flags
& SWP_NOMOVE
) /* if nothing changed, don't do anything */
1042 TRACE( "Nothing has changed, ignoring event\n" );
1045 flags
|= SWP_NOSIZE
;
1048 TRACE( "%p resizing from (%dx%d) to (%dx%d)\n",
1049 hwnd
, data
->window_rect
.right
- data
->window_rect
.left
,
1050 data
->window_rect
.bottom
- data
->window_rect
.top
, cx
, cy
);
1052 if (is_net_wm_state_maximized( event
->display
, data
))
1054 if (!IsZoomed( data
->hwnd
))
1056 TRACE( "win %p/%lx is maximized\n", data
->hwnd
, data
->whole_window
);
1057 SendMessageW( data
->hwnd
, WM_SYSCOMMAND
, SC_MAXIMIZE
, 0 );
1063 if (IsZoomed( data
->hwnd
))
1065 TRACE( "window %p/%lx is no longer maximized\n", data
->hwnd
, data
->whole_window
);
1066 SendMessageW( data
->hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0 );
1071 SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
1075 /**********************************************************************
1076 * X11DRV_GravityNotify
1078 static void X11DRV_GravityNotify( HWND hwnd
, XEvent
*xev
)
1080 XGravityEvent
*event
= &xev
->xgravity
;
1081 struct x11drv_win_data
*data
= X11DRV_get_win_data( hwnd
);
1084 if (!data
|| data
->whole_window
) return; /* only handle this for foreign windows */
1086 rect
.left
= event
->x
;
1087 rect
.top
= event
->y
;
1088 rect
.right
= rect
.left
+ data
->whole_rect
.right
- data
->whole_rect
.left
;
1089 rect
.bottom
= rect
.top
+ data
->whole_rect
.bottom
- data
->whole_rect
.top
;
1091 TRACE( "win %p/%lx new X rect %d,%d,%dx%d (event %d,%d)\n",
1092 hwnd
, data
->whole_window
, rect
.left
, rect
.top
, rect
.right
-rect
.left
, rect
.bottom
-rect
.top
,
1093 event
->x
, event
->y
);
1095 X11DRV_X_to_window_rect( data
, &rect
);
1097 if (data
->window_rect
.left
!= rect
.left
|| data
->window_rect
.top
!= rect
.top
)
1098 SetWindowPos( hwnd
, 0, rect
.left
, rect
.top
, 0, 0,
1099 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOCOPYBITS
);
1103 /***********************************************************************
1104 * get_window_wm_state
1106 static int get_window_wm_state( Display
*display
, struct x11drv_win_data
*data
)
1114 int format
, ret
= -1;
1115 unsigned long count
, remaining
;
1118 if (!XGetWindowProperty( display
, data
->whole_window
, x11drv_atom(WM_STATE
), 0,
1119 sizeof(*state
)/sizeof(CARD32
), False
, x11drv_atom(WM_STATE
),
1120 &type
, &format
, &count
, &remaining
, (unsigned char **)&state
))
1122 if (type
== x11drv_atom(WM_STATE
) && get_property_size( format
, count
) >= sizeof(*state
))
1126 wine_tsx11_unlock();
1131 /***********************************************************************
1132 * handle_wm_state_notify
1134 * Handle a PropertyNotify for WM_STATE.
1136 static void handle_wm_state_notify( struct x11drv_win_data
*data
, XPropertyEvent
*event
,
1137 BOOL update_window
)
1141 switch(event
->state
)
1143 case PropertyDelete
:
1144 TRACE( "%p/%lx: WM_STATE deleted from %d\n", data
->hwnd
, data
->whole_window
, data
->wm_state
);
1145 data
->wm_state
= WithdrawnState
;
1147 case PropertyNewValue
:
1149 int old_state
= data
->wm_state
;
1150 int new_state
= get_window_wm_state( event
->display
, data
);
1151 if (new_state
!= -1 && new_state
!= data
->wm_state
)
1153 TRACE( "%p/%lx: new WM_STATE %d from %d\n",
1154 data
->hwnd
, data
->whole_window
, new_state
, old_state
);
1155 data
->wm_state
= new_state
;
1156 /* ignore the initial state transition out of withdrawn state */
1157 /* metacity does Withdrawn->NormalState->IconicState when mapping an iconic window */
1158 if (!old_state
) return;
1164 if (!update_window
|| !data
->managed
|| !data
->mapped
) return;
1166 style
= GetWindowLongW( data
->hwnd
, GWL_STYLE
);
1168 if (data
->iconic
&& data
->wm_state
== NormalState
) /* restore window */
1170 data
->iconic
= FALSE
;
1171 if (is_net_wm_state_maximized( event
->display
, data
))
1173 if ((style
& WS_MAXIMIZEBOX
) && !(style
& WS_DISABLED
))
1175 TRACE( "restoring to max %p/%lx\n", data
->hwnd
, data
->whole_window
);
1176 SendMessageW( data
->hwnd
, WM_SYSCOMMAND
, SC_MAXIMIZE
, 0 );
1178 else TRACE( "not restoring to max win %p/%lx style %08x\n",
1179 data
->hwnd
, data
->whole_window
, style
);
1181 else if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1183 TRACE( "restoring win %p/%lx\n", data
->hwnd
, data
->whole_window
);
1184 SendMessageW( data
->hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0 );
1186 else TRACE( "not restoring win %p/%lx style %08x\n", data
->hwnd
, data
->whole_window
, style
);
1188 else if (!data
->iconic
&& data
->wm_state
== IconicState
)
1190 data
->iconic
= TRUE
;
1191 if ((style
& WS_MINIMIZEBOX
) && !(style
& WS_DISABLED
))
1193 TRACE( "minimizing win %p/%lx\n", data
->hwnd
, data
->whole_window
);
1194 SendMessageW( data
->hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, 0 );
1196 else TRACE( "not minimizing win %p/%lx style %08x\n", data
->hwnd
, data
->whole_window
, style
);
1201 /***********************************************************************
1202 * X11DRV_PropertyNotify
1204 static void X11DRV_PropertyNotify( HWND hwnd
, XEvent
*xev
)
1206 XPropertyEvent
*event
= &xev
->xproperty
;
1207 struct x11drv_win_data
*data
;
1210 if (!(data
= X11DRV_get_win_data( hwnd
))) return;
1212 if (event
->atom
== x11drv_atom(WM_STATE
)) handle_wm_state_notify( data
, event
, TRUE
);
1216 /* event filter to wait for a WM_STATE change notification on a window */
1217 static Bool
is_wm_state_notify( Display
*display
, XEvent
*event
, XPointer arg
)
1219 if (event
->xany
.window
!= (Window
)arg
) return 0;
1220 return (event
->type
== DestroyNotify
||
1221 (event
->type
== PropertyNotify
&& event
->xproperty
.atom
== x11drv_atom(WM_STATE
)));
1224 /***********************************************************************
1225 * wait_for_withdrawn_state
1227 void wait_for_withdrawn_state( Display
*display
, struct x11drv_win_data
*data
, BOOL set
)
1229 DWORD end
= GetTickCount() + 2000;
1231 if (!data
->managed
) return;
1233 TRACE( "waiting for window %p/%lx to become %swithdrawn\n",
1234 data
->hwnd
, data
->whole_window
, set
? "" : "not " );
1236 while (data
->whole_window
&& ((data
->wm_state
== WithdrawnState
) == !set
))
1242 while (XCheckIfEvent( display
, &event
, is_wm_state_notify
, (char *)data
->whole_window
))
1245 if (XFilterEvent( &event
, None
)) continue; /* filtered, ignore it */
1246 if (event
.type
== DestroyNotify
) call_event_handler( display
, &event
);
1249 wine_tsx11_unlock();
1250 handle_wm_state_notify( data
, &event
.xproperty
, FALSE
);
1254 wine_tsx11_unlock();
1259 int timeout
= end
- GetTickCount();
1261 pfd
.fd
= ConnectionNumber(display
);
1262 pfd
.events
= POLLIN
;
1263 if (timeout
<= 0 || poll( &pfd
, 1, timeout
) != 1)
1265 FIXME( "window %p/%lx wait timed out\n", data
->hwnd
, data
->whole_window
);
1270 TRACE( "window %p/%lx state now %d\n", data
->hwnd
, data
->whole_window
, data
->wm_state
);
1274 static HWND
find_drop_window( HWND hQueryWnd
, LPPOINT lpPt
)
1278 if (!IsWindowEnabled(hQueryWnd
)) return 0;
1280 GetWindowRect(hQueryWnd
, &tempRect
);
1282 if(!PtInRect(&tempRect
, *lpPt
)) return 0;
1284 if (!IsIconic( hQueryWnd
))
1287 ScreenToClient( hQueryWnd
, &pt
);
1288 GetClientRect( hQueryWnd
, &tempRect
);
1290 if (PtInRect( &tempRect
, pt
))
1292 HWND ret
= ChildWindowFromPointEx( hQueryWnd
, pt
, CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
);
1293 if (ret
&& ret
!= hQueryWnd
)
1295 ret
= find_drop_window( ret
, lpPt
);
1296 if (ret
) return ret
;
1301 if(!(GetWindowLongA( hQueryWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
)) return 0;
1303 ScreenToClient(hQueryWnd
, lpPt
);
1308 /**********************************************************************
1309 * EVENT_DropFromOffix
1311 * don't know if it still works (last Changelog is from 96/11/04)
1313 static void EVENT_DropFromOffiX( HWND hWnd
, XClientMessageEvent
*event
)
1315 struct x11drv_win_data
*data
;
1316 unsigned long data_length
;
1317 unsigned long aux_long
;
1318 unsigned char* p_data
= NULL
;
1322 Window win
, w_aux_root
, w_aux_child
;
1324 win
= X11DRV_get_whole_window(hWnd
);
1326 XQueryPointer( event
->display
, win
, &w_aux_root
, &w_aux_child
,
1327 &x
, &y
, &dummy
, &dummy
, (unsigned int*)&aux_long
);
1328 x
+= virtual_screen_rect
.left
;
1329 y
+= virtual_screen_rect
.top
;
1330 wine_tsx11_unlock();
1332 if (!(data
= X11DRV_get_win_data( hWnd
))) return;
1334 /* find out drop point and drop window */
1335 if( x
< 0 || y
< 0 ||
1336 x
> (data
->whole_rect
.right
- data
->whole_rect
.left
) ||
1337 y
> (data
->whole_rect
.bottom
- data
->whole_rect
.top
) )
1339 bAccept
= GetWindowLongW( hWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
;
1345 POINT pt
= { x
, y
};
1346 HWND hwndDrop
= find_drop_window( hWnd
, &pt
);
1359 if (!bAccept
) return;
1362 XGetWindowProperty( event
->display
, DefaultRootWindow(event
->display
),
1363 x11drv_atom(DndSelection
), 0, 65535, FALSE
,
1364 AnyPropertyType
, &atom_aux
, &dummy
,
1365 &data_length
, &aux_long
, &p_data
);
1366 wine_tsx11_unlock();
1368 if( !aux_long
&& p_data
) /* don't bother if > 64K */
1370 char *p
= (char *)p_data
;
1374 while( *p
) /* calculate buffer size */
1376 INT len
= GetShortPathNameA( p
, NULL
, 0 );
1377 if (len
) aux_long
+= len
+ 1;
1380 if( aux_long
&& aux_long
< 65535 )
1385 aux_long
+= sizeof(DROPFILES
) + 1;
1386 hDrop
= GlobalAlloc( GMEM_SHARE
, aux_long
);
1387 lpDrop
= GlobalLock( hDrop
);
1391 lpDrop
->pFiles
= sizeof(DROPFILES
);
1394 lpDrop
->fNC
= FALSE
;
1395 lpDrop
->fWide
= FALSE
;
1396 p_drop
= (char *)(lpDrop
+ 1);
1400 if (GetShortPathNameA( p
, p_drop
, aux_long
- (p_drop
- (char *)lpDrop
) ))
1401 p_drop
+= strlen( p_drop
) + 1;
1405 PostMessageA( hWnd
, WM_DROPFILES
, (WPARAM
)hDrop
, 0L );
1410 if( p_data
) XFree(p_data
);
1411 wine_tsx11_unlock();
1414 /**********************************************************************
1417 * drop items are separated by \n
1418 * each item is prefixed by its mime type
1420 * event->data.l[3], event->data.l[4] contains drop x,y position
1422 static void EVENT_DropURLs( HWND hWnd
, XClientMessageEvent
*event
)
1424 struct x11drv_win_data
*win_data
;
1425 unsigned long data_length
;
1426 unsigned long aux_long
, drop_len
= 0;
1427 unsigned char *p_data
= NULL
; /* property data */
1428 char *p_drop
= NULL
;
1440 if (!(GetWindowLongW( hWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
)) return;
1443 XGetWindowProperty( event
->display
, DefaultRootWindow(event
->display
),
1444 x11drv_atom(DndSelection
), 0, 65535, FALSE
,
1445 AnyPropertyType
, &u
.atom_aux
, &u
.i
,
1446 &data_length
, &aux_long
, &p_data
);
1447 wine_tsx11_unlock();
1449 WARN("property too large, truncated!\n");
1450 TRACE("urls=%s\n", p_data
);
1452 if( !aux_long
&& p_data
) { /* don't bother if > 64K */
1453 /* calculate length */
1455 next
= strchr(p
, '\n');
1458 if (strncmp(p
,"file:",5) == 0 ) {
1459 INT len
= GetShortPathNameA( p
+5, NULL
, 0 );
1460 if (len
) drop_len
+= len
+ 1;
1465 next
= strchr(p
, '\n');
1471 if( drop_len
&& drop_len
< 65535 ) {
1473 XQueryPointer( event
->display
, root_window
, &u
.w_aux
, &u
.w_aux
,
1474 &x
, &y
, &u
.i
, &u
.i
, &u
.u
);
1475 x
+= virtual_screen_rect
.left
;
1476 y
+= virtual_screen_rect
.top
;
1477 wine_tsx11_unlock();
1479 drop_len
+= sizeof(DROPFILES
) + 1;
1480 hDrop
= GlobalAlloc( GMEM_SHARE
, drop_len
);
1481 lpDrop
= GlobalLock( hDrop
);
1483 if( lpDrop
&& (win_data
= X11DRV_get_win_data( hWnd
)))
1485 lpDrop
->pFiles
= sizeof(DROPFILES
);
1489 ( x
< (win_data
->client_rect
.left
- win_data
->whole_rect
.left
) ||
1490 y
< (win_data
->client_rect
.top
- win_data
->whole_rect
.top
) ||
1491 x
> (win_data
->client_rect
.right
- win_data
->whole_rect
.left
) ||
1492 y
> (win_data
->client_rect
.bottom
- win_data
->whole_rect
.top
) );
1493 lpDrop
->fWide
= FALSE
;
1494 p_drop
= (char*)(lpDrop
+ 1);
1497 /* create message content */
1500 next
= strchr(p
, '\n');
1503 if (strncmp(p
,"file:",5) == 0 ) {
1504 INT len
= GetShortPathNameA( p
+5, p_drop
, 65535 );
1506 TRACE("drop file %s as %s\n", p
+5, p_drop
);
1509 WARN("can't convert file %s to dos name\n", p
+5);
1512 WARN("unknown mime type %s\n", p
);
1517 next
= strchr(p
, '\n');
1524 GlobalUnlock(hDrop
);
1525 PostMessageA( hWnd
, WM_DROPFILES
, (WPARAM
)hDrop
, 0L );
1529 if( p_data
) XFree(p_data
);
1530 wine_tsx11_unlock();
1535 /**********************************************************************
1536 * handle_xembed_protocol
1538 static void handle_xembed_protocol( HWND hwnd
, XClientMessageEvent
*event
)
1540 struct x11drv_win_data
*data
= X11DRV_get_win_data( hwnd
);
1544 switch (event
->data
.l
[1])
1546 case XEMBED_EMBEDDED_NOTIFY
:
1547 TRACE( "win %p/%lx XEMBED_EMBEDDED_NOTIFY owner %lx\n", hwnd
, event
->window
, event
->data
.l
[3] );
1548 data
->embedder
= event
->data
.l
[3];
1551 TRACE( "win %p/%lx XEMBED message %lu(%lu)\n",
1552 hwnd
, event
->window
, event
->data
.l
[1], event
->data
.l
[2] );
1558 /**********************************************************************
1559 * handle_dnd_protocol
1561 static void handle_dnd_protocol( HWND hwnd
, XClientMessageEvent
*event
)
1564 int root_x
, root_y
, child_x
, child_y
;
1567 /* query window (drag&drop event contains only drag window) */
1569 XQueryPointer( event
->display
, root_window
, &root
, &child
,
1570 &root_x
, &root_y
, &child_x
, &child_y
, &u
);
1571 if (XFindContext( event
->display
, child
, winContext
, (char **)&hwnd
) != 0) hwnd
= 0;
1572 wine_tsx11_unlock();
1574 if (event
->data
.l
[0] == DndFile
|| event
->data
.l
[0] == DndFiles
)
1575 EVENT_DropFromOffiX(hwnd
, event
);
1576 else if (event
->data
.l
[0] == DndURL
)
1577 EVENT_DropURLs(hwnd
, event
);
1581 struct client_message_handler
1583 int atom
; /* protocol atom */
1584 void (*handler
)(HWND
, XClientMessageEvent
*); /* corresponding handler function */
1587 static const struct client_message_handler client_messages
[] =
1589 { XATOM_MANAGER
, handle_manager_message
},
1590 { XATOM_WM_PROTOCOLS
, handle_wm_protocols
},
1591 { XATOM__XEMBED
, handle_xembed_protocol
},
1592 { XATOM_DndProtocol
, handle_dnd_protocol
},
1593 { XATOM_XdndEnter
, X11DRV_XDND_EnterEvent
},
1594 { XATOM_XdndPosition
, X11DRV_XDND_PositionEvent
},
1595 { XATOM_XdndDrop
, X11DRV_XDND_DropEvent
},
1596 { XATOM_XdndLeave
, X11DRV_XDND_LeaveEvent
}
1600 /**********************************************************************
1601 * X11DRV_ClientMessage
1603 static void X11DRV_ClientMessage( HWND hwnd
, XEvent
*xev
)
1605 XClientMessageEvent
*event
= &xev
->xclient
;
1610 if (event
->format
!= 32)
1612 WARN( "Don't know how to handle format %d\n", event
->format
);
1616 for (i
= 0; i
< sizeof(client_messages
)/sizeof(client_messages
[0]); i
++)
1618 if (event
->message_type
== X11DRV_Atoms
[client_messages
[i
].atom
- FIRST_XATOM
])
1620 client_messages
[i
].handler( hwnd
, event
);
1624 TRACE( "no handler found for %ld\n", event
->message_type
);