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 struct x11drv_win_data
*data
= X11DRV_get_win_data( hwnd
);
524 LONG style
= GetWindowLongW( hwnd
, GWL_STYLE
);
526 if (!(style
& WS_VISIBLE
)) return FALSE
;
527 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
528 if (style
& WS_MINIMIZE
) return FALSE
;
529 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_NOACTIVATE
) return FALSE
;
530 if (hwnd
== GetDesktopWindow()) return FALSE
;
531 if (data
&& IsRectEmpty( &data
->window_rect
)) return FALSE
;
532 return !(style
& WS_DISABLED
);
536 /**********************************************************************
539 static void set_focus( Display
*display
, HWND hwnd
, Time time
)
543 GUITHREADINFO threadinfo
;
545 TRACE( "setting foreground window to %p\n", hwnd
);
546 SetForegroundWindow( hwnd
);
548 threadinfo
.cbSize
= sizeof(threadinfo
);
549 GetGUIThreadInfo(0, &threadinfo
);
550 focus
= threadinfo
.hwndFocus
;
551 if (!focus
) focus
= threadinfo
.hwndActive
;
552 if (focus
) focus
= GetAncestor( focus
, GA_ROOT
);
553 win
= X11DRV_get_whole_window(focus
);
557 TRACE( "setting focus to %p (%lx) time=%ld\n", focus
, win
, time
);
559 XSetInputFocus( display
, win
, RevertToParent
, time
);
565 /**********************************************************************
566 * handle_manager_message
568 static void handle_manager_message( HWND hwnd
, XClientMessageEvent
*event
)
570 if (hwnd
!= GetDesktopWindow()) return;
571 if (systray_atom
&& event
->data
.l
[1] == systray_atom
)
572 change_systray_owner( event
->display
, event
->data
.l
[2] );
576 /**********************************************************************
577 * handle_wm_protocols
579 static void handle_wm_protocols( HWND hwnd
, XClientMessageEvent
*event
)
581 Atom protocol
= (Atom
)event
->data
.l
[0];
582 Time event_time
= (Time
)event
->data
.l
[1];
584 if (!protocol
) return;
586 if (protocol
== x11drv_atom(WM_DELETE_WINDOW
))
588 update_user_time( event_time
);
590 if (hwnd
== GetDesktopWindow())
592 /* The desktop window does not have a close button that we can
593 * pretend to click. Therefore, we simply send it a close command. */
594 SendMessageW(hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
598 /* Ignore the delete window request if the window has been disabled
599 * and we are in managed mode. This is to disallow applications from
600 * being closed by the window manager while in a modal state.
602 if (IsWindowEnabled(hwnd
))
606 if (GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
) return;
607 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
610 UINT state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
611 if (state
== 0xFFFFFFFF || (state
& (MF_DISABLED
| MF_GRAYED
)))
614 if (GetActiveWindow() != hwnd
)
616 LRESULT ma
= SendMessageW( hwnd
, WM_MOUSEACTIVATE
,
617 (WPARAM
)GetAncestor( hwnd
, GA_ROOT
),
618 MAKELPARAM( HTCLOSE
, WM_NCLBUTTONDOWN
) );
621 case MA_NOACTIVATEANDEAT
:
622 case MA_ACTIVATEANDEAT
:
628 SetActiveWindow(hwnd
);
631 WARN( "unknown WM_MOUSEACTIVATE code %d\n", (int) ma
);
636 PostMessageW( hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
639 else if (protocol
== x11drv_atom(WM_TAKE_FOCUS
))
641 HWND last_focus
= x11drv_thread_data()->last_focus
;
643 TRACE( "got take focus msg for %p, enabled=%d, visible=%d (style %08x), focus=%p, active=%p, fg=%p, last=%p\n",
644 hwnd
, IsWindowEnabled(hwnd
), IsWindowVisible(hwnd
), GetWindowLongW(hwnd
, GWL_STYLE
),
645 GetFocus(), GetActiveWindow(), GetForegroundWindow(), last_focus
);
647 if (can_activate_window(hwnd
))
649 /* simulate a mouse click on the caption to find out
650 * whether the window wants to be activated */
651 LRESULT ma
= SendMessageW( hwnd
, WM_MOUSEACTIVATE
,
652 (WPARAM
)GetAncestor( hwnd
, GA_ROOT
),
653 MAKELONG(HTCAPTION
,WM_LBUTTONDOWN
) );
654 if (ma
!= MA_NOACTIVATEANDEAT
&& ma
!= MA_NOACTIVATE
)
656 set_focus( event
->display
, hwnd
, event_time
);
660 else if (hwnd
== GetDesktopWindow())
662 hwnd
= GetForegroundWindow();
663 if (!hwnd
) hwnd
= last_focus
;
664 if (!hwnd
) hwnd
= GetDesktopWindow();
665 set_focus( event
->display
, hwnd
, event_time
);
668 /* try to find some other window to give the focus to */
670 if (hwnd
) hwnd
= GetAncestor( hwnd
, GA_ROOT
);
671 if (!hwnd
) hwnd
= GetActiveWindow();
672 if (!hwnd
) hwnd
= last_focus
;
673 if (hwnd
&& can_activate_window(hwnd
)) set_focus( event
->display
, hwnd
, event_time
);
675 else if (protocol
== x11drv_atom(_NET_WM_PING
))
677 XClientMessageEvent xev
;
680 TRACE("NET_WM Ping\n");
682 xev
.window
= DefaultRootWindow(xev
.display
);
683 XSendEvent(xev
.display
, xev
.window
, False
, SubstructureRedirectMask
| SubstructureNotifyMask
, (XEvent
*)&xev
);
685 /* this line is semi-stolen from gtk2 */
686 TRACE("NET_WM Pong\n");
691 static const char * const focus_details
[] =
697 "NotifyNonlinearVirtual",
703 /**********************************************************************
706 static void X11DRV_FocusIn( HWND hwnd
, XEvent
*xev
)
708 XFocusChangeEvent
*event
= &xev
->xfocus
;
713 TRACE( "win %p xwin %lx detail=%s\n", hwnd
, event
->window
, focus_details
[event
->detail
] );
715 if (event
->detail
== NotifyPointer
) return;
716 if (hwnd
== GetDesktopWindow()) return;
718 if ((xic
= X11DRV_get_ic( hwnd
)))
726 if (hwnd
== GetForegroundWindow()) clip_fullscreen_window( hwnd
, FALSE
);
730 if (!can_activate_window(hwnd
))
732 HWND hwnd
= GetFocus();
733 if (hwnd
) hwnd
= GetAncestor( hwnd
, GA_ROOT
);
734 if (!hwnd
) hwnd
= GetActiveWindow();
735 if (!hwnd
) hwnd
= x11drv_thread_data()->last_focus
;
736 if (hwnd
&& can_activate_window(hwnd
)) set_focus( event
->display
, hwnd
, CurrentTime
);
738 else SetForegroundWindow( hwnd
);
742 /**********************************************************************
745 * Note: only top-level windows get FocusOut events.
747 static void X11DRV_FocusOut( HWND hwnd
, XEvent
*xev
)
749 XFocusChangeEvent
*event
= &xev
->xfocus
;
755 TRACE( "win %p xwin %lx detail=%s\n", hwnd
, event
->window
, focus_details
[event
->detail
] );
757 if (event
->detail
== NotifyPointer
)
759 if (!hwnd
&& event
->window
== x11drv_thread_data()->clip_window
) reset_clipping_window();
762 if (ximInComposeMode
) return;
764 x11drv_thread_data()->last_focus
= hwnd
;
765 if ((xic
= X11DRV_get_ic( hwnd
)))
768 XUnsetICFocus( xic
);
771 if (root_window
!= DefaultRootWindow(event
->display
))
773 if (hwnd
== GetDesktopWindow()) reset_clipping_window();
776 if (hwnd
!= GetForegroundWindow()) return;
777 SendMessageW( hwnd
, WM_CANCELMODE
, 0, 0 );
779 /* don't reset the foreground window, if the window which is
780 getting the focus is a Wine window */
783 XGetInputFocus( event
->display
, &focus_win
, &revert
);
786 if (XFindContext( event
->display
, focus_win
, winContext
, (char **)&hwnd_tmp
) != 0)
793 /* Abey : 6-Oct-99. Check again if the focus out window is the
794 Foreground window, because in most cases the messages sent
795 above must have already changed the foreground window, in which
796 case we don't have to change the foreground window to 0 */
797 if (hwnd
== GetForegroundWindow())
799 TRACE( "lost focus, setting fg to desktop\n" );
800 SetForegroundWindow( GetDesktopWindow() );
806 /***********************************************************************
809 static void X11DRV_Expose( HWND hwnd
, XEvent
*xev
)
811 XExposeEvent
*event
= &xev
->xexpose
;
813 struct x11drv_win_data
*data
;
814 int flags
= RDW_INVALIDATE
| RDW_ERASE
;
816 TRACE( "win %p (%lx) %d,%d %dx%d\n",
817 hwnd
, event
->window
, event
->x
, event
->y
, event
->width
, event
->height
);
819 if (!(data
= X11DRV_get_win_data( hwnd
))) return;
821 rect
.left
= event
->x
;
823 rect
.right
= event
->x
+ event
->width
;
824 rect
.bottom
= event
->y
+ event
->height
;
825 if (event
->window
== data
->whole_window
)
827 OffsetRect( &rect
, data
->whole_rect
.left
- data
->client_rect
.left
,
828 data
->whole_rect
.top
- data
->client_rect
.top
);
832 if (event
->window
!= root_window
)
834 if (GetWindowLongW( data
->hwnd
, GWL_EXSTYLE
) & WS_EX_LAYOUTRTL
)
835 mirror_rect( &data
->client_rect
, &rect
);
837 SERVER_START_REQ( update_window_zorder
)
839 req
->window
= wine_server_user_handle( hwnd
);
840 req
->rect
.left
= rect
.left
;
841 req
->rect
.top
= rect
.top
;
842 req
->rect
.right
= rect
.right
;
843 req
->rect
.bottom
= rect
.bottom
;
844 wine_server_call( req
);
848 flags
|= RDW_ALLCHILDREN
;
850 else OffsetRect( &rect
, virtual_screen_rect
.left
, virtual_screen_rect
.top
);
852 RedrawWindow( hwnd
, &rect
, 0, flags
);
856 /**********************************************************************
859 static void X11DRV_MapNotify( HWND hwnd
, XEvent
*event
)
861 struct x11drv_win_data
*data
;
863 if (event
->xany
.window
== x11drv_thread_data()->clip_window
)
868 if (!(data
= X11DRV_get_win_data( hwnd
))) return;
869 if (!data
->mapped
|| data
->embedded
) return;
873 HWND hwndFocus
= GetFocus();
874 if (hwndFocus
&& IsChild( hwnd
, hwndFocus
)) X11DRV_SetFocus(hwndFocus
); /* FIXME */
879 /**********************************************************************
882 static void X11DRV_UnmapNotify( HWND hwnd
, XEvent
*event
)
884 if (event
->xany
.window
== x11drv_thread_data()->clip_window
) clipping_cursor
= 0;
888 /***********************************************************************
889 * is_net_wm_state_maximized
891 static BOOL
is_net_wm_state_maximized( Display
*display
, struct x11drv_win_data
*data
)
895 unsigned long i
, count
, remaining
;
897 if (!data
->whole_window
) return FALSE
;
900 if (!XGetWindowProperty( display
, data
->whole_window
, x11drv_atom(_NET_WM_STATE
), 0,
901 65536/sizeof(CARD32
), False
, XA_ATOM
, &type
, &format
, &count
,
902 &remaining
, (unsigned char **)&state
))
904 if (type
== XA_ATOM
&& format
== 32)
906 for (i
= 0; i
< count
; i
++)
908 if (state
[i
] == x11drv_atom(_NET_WM_STATE_MAXIMIZED_VERT
) ||
909 state
[i
] == x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ
))
920 /***********************************************************************
921 * X11DRV_ReparentNotify
923 static void X11DRV_ReparentNotify( HWND hwnd
, XEvent
*xev
)
925 XReparentEvent
*event
= &xev
->xreparent
;
926 struct x11drv_win_data
*data
;
927 HWND parent
, old_parent
;
930 if (!(data
= X11DRV_get_win_data( hwnd
))) return;
931 if (!data
->embedded
) return;
933 if (data
->whole_window
)
935 if (event
->parent
== root_window
)
937 TRACE( "%p/%lx reparented to root\n", hwnd
, data
->whole_window
);
939 SendMessageW( hwnd
, WM_CLOSE
, 0, 0 );
942 data
->embedder
= event
->parent
;
945 TRACE( "%p/%lx reparented to %lx\n", hwnd
, data
->whole_window
, event
->parent
);
947 style
= GetWindowLongW( hwnd
, GWL_STYLE
);
948 if (event
->parent
== root_window
)
950 parent
= GetDesktopWindow();
951 style
= (style
& ~WS_CHILD
) | WS_POPUP
;
955 if (!(parent
= create_foreign_window( event
->display
, event
->parent
))) return;
956 style
= (style
& ~WS_POPUP
) | WS_CHILD
;
959 ShowWindow( hwnd
, SW_HIDE
);
960 old_parent
= SetParent( hwnd
, parent
);
961 SetWindowLongW( hwnd
, GWL_STYLE
, style
);
962 SetWindowPos( hwnd
, HWND_TOP
, event
->x
, event
->y
, 0, 0,
963 SWP_NOACTIVATE
| SWP_NOSIZE
| SWP_NOCOPYBITS
|
964 ((style
& WS_VISIBLE
) ? SWP_SHOWWINDOW
: 0) );
966 /* make old parent destroy itself if it no longer has children */
967 if (old_parent
!= GetDesktopWindow()) PostMessageW( old_parent
, WM_CLOSE
, 0, 0 );
971 /***********************************************************************
972 * X11DRV_ConfigureNotify
974 void X11DRV_ConfigureNotify( HWND hwnd
, XEvent
*xev
)
976 XConfigureEvent
*event
= &xev
->xconfigure
;
977 struct x11drv_win_data
*data
;
982 int cx
, cy
, x
= event
->x
, y
= event
->y
;
985 if (!(data
= X11DRV_get_win_data( hwnd
))) return;
986 if (!data
->mapped
|| data
->iconic
) return;
987 if (data
->whole_window
&& !data
->managed
) return;
988 /* ignore synthetic events on foreign windows */
989 if (event
->send_event
&& !data
->whole_window
) return;
990 if (data
->configure_serial
&& (long)(data
->configure_serial
- event
->serial
) > 0)
992 TRACE( "win %p/%lx event %d,%d,%dx%d ignoring old serial %lu/%lu\n",
993 hwnd
, data
->whole_window
, event
->x
, event
->y
, event
->width
, event
->height
,
994 event
->serial
, data
->configure_serial
);
1000 parent
= GetAncestor( hwnd
, GA_PARENT
);
1001 root_coords
= event
->send_event
; /* synthetic events are always in root coords */
1003 if (!root_coords
&& parent
== GetDesktopWindow()) /* normal event, map coordinates to the root */
1007 XTranslateCoordinates( event
->display
, event
->window
, root_window
,
1008 0, 0, &x
, &y
, &child
);
1009 wine_tsx11_unlock();
1014 rect
.right
= x
+ event
->width
;
1015 rect
.bottom
= y
+ event
->height
;
1016 if (root_coords
) OffsetRect( &rect
, virtual_screen_rect
.left
, virtual_screen_rect
.top
);
1017 TRACE( "win %p/%lx new X rect %d,%d,%dx%d (event %d,%d,%dx%d)\n",
1018 hwnd
, data
->whole_window
, rect
.left
, rect
.top
, rect
.right
-rect
.left
, rect
.bottom
-rect
.top
,
1019 event
->x
, event
->y
, event
->width
, event
->height
);
1021 X11DRV_X_to_window_rect( data
, &rect
);
1022 if (root_coords
) MapWindowPoints( 0, parent
, (POINT
*)&rect
, 2 );
1024 /* Compare what has changed */
1028 cx
= rect
.right
- rect
.left
;
1029 cy
= rect
.bottom
- rect
.top
;
1030 flags
= SWP_NOACTIVATE
| SWP_NOZORDER
;
1032 if (!data
->whole_window
) flags
|= SWP_NOCOPYBITS
; /* we can't copy bits of foreign windows */
1034 if (data
->window_rect
.left
== x
&& data
->window_rect
.top
== y
) flags
|= SWP_NOMOVE
;
1036 TRACE( "%p moving from (%d,%d) to (%d,%d)\n",
1037 hwnd
, data
->window_rect
.left
, data
->window_rect
.top
, x
, y
);
1039 if ((data
->window_rect
.right
- data
->window_rect
.left
== cx
&&
1040 data
->window_rect
.bottom
- data
->window_rect
.top
== cy
) ||
1041 (IsRectEmpty( &data
->window_rect
) && event
->width
== 1 && event
->height
== 1))
1043 if (flags
& SWP_NOMOVE
) /* if nothing changed, don't do anything */
1045 TRACE( "Nothing has changed, ignoring event\n" );
1048 flags
|= SWP_NOSIZE
;
1051 TRACE( "%p resizing from (%dx%d) to (%dx%d)\n",
1052 hwnd
, data
->window_rect
.right
- data
->window_rect
.left
,
1053 data
->window_rect
.bottom
- data
->window_rect
.top
, cx
, cy
);
1055 if (is_net_wm_state_maximized( event
->display
, data
))
1057 if (!IsZoomed( data
->hwnd
))
1059 TRACE( "win %p/%lx is maximized\n", data
->hwnd
, data
->whole_window
);
1060 SendMessageW( data
->hwnd
, WM_SYSCOMMAND
, SC_MAXIMIZE
, 0 );
1066 if (IsZoomed( data
->hwnd
))
1068 TRACE( "window %p/%lx is no longer maximized\n", data
->hwnd
, data
->whole_window
);
1069 SendMessageW( data
->hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0 );
1074 SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
1078 /**********************************************************************
1079 * X11DRV_GravityNotify
1081 static void X11DRV_GravityNotify( HWND hwnd
, XEvent
*xev
)
1083 XGravityEvent
*event
= &xev
->xgravity
;
1084 struct x11drv_win_data
*data
= X11DRV_get_win_data( hwnd
);
1087 if (!data
|| data
->whole_window
) return; /* only handle this for foreign windows */
1089 rect
.left
= event
->x
;
1090 rect
.top
= event
->y
;
1091 rect
.right
= rect
.left
+ data
->whole_rect
.right
- data
->whole_rect
.left
;
1092 rect
.bottom
= rect
.top
+ data
->whole_rect
.bottom
- data
->whole_rect
.top
;
1094 TRACE( "win %p/%lx new X rect %d,%d,%dx%d (event %d,%d)\n",
1095 hwnd
, data
->whole_window
, rect
.left
, rect
.top
, rect
.right
-rect
.left
, rect
.bottom
-rect
.top
,
1096 event
->x
, event
->y
);
1098 X11DRV_X_to_window_rect( data
, &rect
);
1100 if (data
->window_rect
.left
!= rect
.left
|| data
->window_rect
.top
!= rect
.top
)
1101 SetWindowPos( hwnd
, 0, rect
.left
, rect
.top
, 0, 0,
1102 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOCOPYBITS
);
1106 /***********************************************************************
1107 * get_window_wm_state
1109 static int get_window_wm_state( Display
*display
, struct x11drv_win_data
*data
)
1117 int format
, ret
= -1;
1118 unsigned long count
, remaining
;
1121 if (!XGetWindowProperty( display
, data
->whole_window
, x11drv_atom(WM_STATE
), 0,
1122 sizeof(*state
)/sizeof(CARD32
), False
, x11drv_atom(WM_STATE
),
1123 &type
, &format
, &count
, &remaining
, (unsigned char **)&state
))
1125 if (type
== x11drv_atom(WM_STATE
) && get_property_size( format
, count
) >= sizeof(*state
))
1129 wine_tsx11_unlock();
1134 /***********************************************************************
1135 * handle_wm_state_notify
1137 * Handle a PropertyNotify for WM_STATE.
1139 static void handle_wm_state_notify( struct x11drv_win_data
*data
, XPropertyEvent
*event
,
1140 BOOL update_window
)
1144 switch(event
->state
)
1146 case PropertyDelete
:
1147 TRACE( "%p/%lx: WM_STATE deleted from %d\n", data
->hwnd
, data
->whole_window
, data
->wm_state
);
1148 data
->wm_state
= WithdrawnState
;
1150 case PropertyNewValue
:
1152 int old_state
= data
->wm_state
;
1153 int new_state
= get_window_wm_state( event
->display
, data
);
1154 if (new_state
!= -1 && new_state
!= data
->wm_state
)
1156 TRACE( "%p/%lx: new WM_STATE %d from %d\n",
1157 data
->hwnd
, data
->whole_window
, new_state
, old_state
);
1158 data
->wm_state
= new_state
;
1159 /* ignore the initial state transition out of withdrawn state */
1160 /* metacity does Withdrawn->NormalState->IconicState when mapping an iconic window */
1161 if (!old_state
) return;
1167 if (!update_window
|| !data
->managed
|| !data
->mapped
) return;
1169 style
= GetWindowLongW( data
->hwnd
, GWL_STYLE
);
1171 if (data
->iconic
&& data
->wm_state
== NormalState
) /* restore window */
1173 data
->iconic
= FALSE
;
1174 if (is_net_wm_state_maximized( event
->display
, data
))
1176 if ((style
& WS_MAXIMIZEBOX
) && !(style
& WS_DISABLED
))
1178 TRACE( "restoring to max %p/%lx\n", data
->hwnd
, data
->whole_window
);
1179 SendMessageW( data
->hwnd
, WM_SYSCOMMAND
, SC_MAXIMIZE
, 0 );
1181 else TRACE( "not restoring to max win %p/%lx style %08x\n",
1182 data
->hwnd
, data
->whole_window
, style
);
1184 else if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1186 TRACE( "restoring win %p/%lx\n", data
->hwnd
, data
->whole_window
);
1187 SendMessageW( data
->hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0 );
1189 else TRACE( "not restoring win %p/%lx style %08x\n", data
->hwnd
, data
->whole_window
, style
);
1191 else if (!data
->iconic
&& data
->wm_state
== IconicState
)
1193 data
->iconic
= TRUE
;
1194 if ((style
& WS_MINIMIZEBOX
) && !(style
& WS_DISABLED
))
1196 TRACE( "minimizing win %p/%lx\n", data
->hwnd
, data
->whole_window
);
1197 SendMessageW( data
->hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, 0 );
1199 else TRACE( "not minimizing win %p/%lx style %08x\n", data
->hwnd
, data
->whole_window
, style
);
1204 /***********************************************************************
1205 * X11DRV_PropertyNotify
1207 static void X11DRV_PropertyNotify( HWND hwnd
, XEvent
*xev
)
1209 XPropertyEvent
*event
= &xev
->xproperty
;
1210 struct x11drv_win_data
*data
;
1213 if (!(data
= X11DRV_get_win_data( hwnd
))) return;
1215 if (event
->atom
== x11drv_atom(WM_STATE
)) handle_wm_state_notify( data
, event
, TRUE
);
1219 /* event filter to wait for a WM_STATE change notification on a window */
1220 static Bool
is_wm_state_notify( Display
*display
, XEvent
*event
, XPointer arg
)
1222 if (event
->xany
.window
!= (Window
)arg
) return 0;
1223 return (event
->type
== DestroyNotify
||
1224 (event
->type
== PropertyNotify
&& event
->xproperty
.atom
== x11drv_atom(WM_STATE
)));
1227 /***********************************************************************
1228 * wait_for_withdrawn_state
1230 void wait_for_withdrawn_state( Display
*display
, struct x11drv_win_data
*data
, BOOL set
)
1232 DWORD end
= GetTickCount() + 2000;
1234 if (!data
->managed
) return;
1236 TRACE( "waiting for window %p/%lx to become %swithdrawn\n",
1237 data
->hwnd
, data
->whole_window
, set
? "" : "not " );
1239 while (data
->whole_window
&& ((data
->wm_state
== WithdrawnState
) == !set
))
1245 while (XCheckIfEvent( display
, &event
, is_wm_state_notify
, (char *)data
->whole_window
))
1248 if (XFilterEvent( &event
, None
)) continue; /* filtered, ignore it */
1249 if (event
.type
== DestroyNotify
) call_event_handler( display
, &event
);
1252 wine_tsx11_unlock();
1253 handle_wm_state_notify( data
, &event
.xproperty
, FALSE
);
1257 wine_tsx11_unlock();
1262 int timeout
= end
- GetTickCount();
1264 pfd
.fd
= ConnectionNumber(display
);
1265 pfd
.events
= POLLIN
;
1266 if (timeout
<= 0 || poll( &pfd
, 1, timeout
) != 1)
1268 FIXME( "window %p/%lx wait timed out\n", data
->hwnd
, data
->whole_window
);
1273 TRACE( "window %p/%lx state now %d\n", data
->hwnd
, data
->whole_window
, data
->wm_state
);
1277 static HWND
find_drop_window( HWND hQueryWnd
, LPPOINT lpPt
)
1281 if (!IsWindowEnabled(hQueryWnd
)) return 0;
1283 GetWindowRect(hQueryWnd
, &tempRect
);
1285 if(!PtInRect(&tempRect
, *lpPt
)) return 0;
1287 if (!IsIconic( hQueryWnd
))
1290 ScreenToClient( hQueryWnd
, &pt
);
1291 GetClientRect( hQueryWnd
, &tempRect
);
1293 if (PtInRect( &tempRect
, pt
))
1295 HWND ret
= ChildWindowFromPointEx( hQueryWnd
, pt
, CWP_SKIPINVISIBLE
|CWP_SKIPDISABLED
);
1296 if (ret
&& ret
!= hQueryWnd
)
1298 ret
= find_drop_window( ret
, lpPt
);
1299 if (ret
) return ret
;
1304 if(!(GetWindowLongA( hQueryWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
)) return 0;
1306 ScreenToClient(hQueryWnd
, lpPt
);
1311 /**********************************************************************
1312 * EVENT_DropFromOffix
1314 * don't know if it still works (last Changelog is from 96/11/04)
1316 static void EVENT_DropFromOffiX( HWND hWnd
, XClientMessageEvent
*event
)
1318 struct x11drv_win_data
*data
;
1319 unsigned long data_length
;
1320 unsigned long aux_long
;
1321 unsigned char* p_data
= NULL
;
1325 Window win
, w_aux_root
, w_aux_child
;
1327 win
= X11DRV_get_whole_window(hWnd
);
1329 XQueryPointer( event
->display
, win
, &w_aux_root
, &w_aux_child
,
1330 &x
, &y
, &dummy
, &dummy
, (unsigned int*)&aux_long
);
1331 x
+= virtual_screen_rect
.left
;
1332 y
+= virtual_screen_rect
.top
;
1333 wine_tsx11_unlock();
1335 if (!(data
= X11DRV_get_win_data( hWnd
))) return;
1337 /* find out drop point and drop window */
1338 if( x
< 0 || y
< 0 ||
1339 x
> (data
->whole_rect
.right
- data
->whole_rect
.left
) ||
1340 y
> (data
->whole_rect
.bottom
- data
->whole_rect
.top
) )
1342 bAccept
= GetWindowLongW( hWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
;
1348 POINT pt
= { x
, y
};
1349 HWND hwndDrop
= find_drop_window( hWnd
, &pt
);
1362 if (!bAccept
) return;
1365 XGetWindowProperty( event
->display
, DefaultRootWindow(event
->display
),
1366 x11drv_atom(DndSelection
), 0, 65535, FALSE
,
1367 AnyPropertyType
, &atom_aux
, &dummy
,
1368 &data_length
, &aux_long
, &p_data
);
1369 wine_tsx11_unlock();
1371 if( !aux_long
&& p_data
) /* don't bother if > 64K */
1373 char *p
= (char *)p_data
;
1377 while( *p
) /* calculate buffer size */
1379 INT len
= GetShortPathNameA( p
, NULL
, 0 );
1380 if (len
) aux_long
+= len
+ 1;
1383 if( aux_long
&& aux_long
< 65535 )
1388 aux_long
+= sizeof(DROPFILES
) + 1;
1389 hDrop
= GlobalAlloc( GMEM_SHARE
, aux_long
);
1390 lpDrop
= GlobalLock( hDrop
);
1394 lpDrop
->pFiles
= sizeof(DROPFILES
);
1397 lpDrop
->fNC
= FALSE
;
1398 lpDrop
->fWide
= FALSE
;
1399 p_drop
= (char *)(lpDrop
+ 1);
1403 if (GetShortPathNameA( p
, p_drop
, aux_long
- (p_drop
- (char *)lpDrop
) ))
1404 p_drop
+= strlen( p_drop
) + 1;
1408 PostMessageA( hWnd
, WM_DROPFILES
, (WPARAM
)hDrop
, 0L );
1413 if( p_data
) XFree(p_data
);
1414 wine_tsx11_unlock();
1417 /**********************************************************************
1420 * drop items are separated by \n
1421 * each item is prefixed by its mime type
1423 * event->data.l[3], event->data.l[4] contains drop x,y position
1425 static void EVENT_DropURLs( HWND hWnd
, XClientMessageEvent
*event
)
1427 struct x11drv_win_data
*win_data
;
1428 unsigned long data_length
;
1429 unsigned long aux_long
, drop_len
= 0;
1430 unsigned char *p_data
= NULL
; /* property data */
1431 char *p_drop
= NULL
;
1443 if (!(GetWindowLongW( hWnd
, GWL_EXSTYLE
) & WS_EX_ACCEPTFILES
)) return;
1446 XGetWindowProperty( event
->display
, DefaultRootWindow(event
->display
),
1447 x11drv_atom(DndSelection
), 0, 65535, FALSE
,
1448 AnyPropertyType
, &u
.atom_aux
, &u
.i
,
1449 &data_length
, &aux_long
, &p_data
);
1450 wine_tsx11_unlock();
1452 WARN("property too large, truncated!\n");
1453 TRACE("urls=%s\n", p_data
);
1455 if( !aux_long
&& p_data
) { /* don't bother if > 64K */
1456 /* calculate length */
1458 next
= strchr(p
, '\n');
1461 if (strncmp(p
,"file:",5) == 0 ) {
1462 INT len
= GetShortPathNameA( p
+5, NULL
, 0 );
1463 if (len
) drop_len
+= len
+ 1;
1468 next
= strchr(p
, '\n');
1474 if( drop_len
&& drop_len
< 65535 ) {
1476 XQueryPointer( event
->display
, root_window
, &u
.w_aux
, &u
.w_aux
,
1477 &x
, &y
, &u
.i
, &u
.i
, &u
.u
);
1478 x
+= virtual_screen_rect
.left
;
1479 y
+= virtual_screen_rect
.top
;
1480 wine_tsx11_unlock();
1482 drop_len
+= sizeof(DROPFILES
) + 1;
1483 hDrop
= GlobalAlloc( GMEM_SHARE
, drop_len
);
1484 lpDrop
= GlobalLock( hDrop
);
1486 if( lpDrop
&& (win_data
= X11DRV_get_win_data( hWnd
)))
1488 lpDrop
->pFiles
= sizeof(DROPFILES
);
1492 ( x
< (win_data
->client_rect
.left
- win_data
->whole_rect
.left
) ||
1493 y
< (win_data
->client_rect
.top
- win_data
->whole_rect
.top
) ||
1494 x
> (win_data
->client_rect
.right
- win_data
->whole_rect
.left
) ||
1495 y
> (win_data
->client_rect
.bottom
- win_data
->whole_rect
.top
) );
1496 lpDrop
->fWide
= FALSE
;
1497 p_drop
= (char*)(lpDrop
+ 1);
1500 /* create message content */
1503 next
= strchr(p
, '\n');
1506 if (strncmp(p
,"file:",5) == 0 ) {
1507 INT len
= GetShortPathNameA( p
+5, p_drop
, 65535 );
1509 TRACE("drop file %s as %s\n", p
+5, p_drop
);
1512 WARN("can't convert file %s to dos name\n", p
+5);
1515 WARN("unknown mime type %s\n", p
);
1520 next
= strchr(p
, '\n');
1527 GlobalUnlock(hDrop
);
1528 PostMessageA( hWnd
, WM_DROPFILES
, (WPARAM
)hDrop
, 0L );
1532 if( p_data
) XFree(p_data
);
1533 wine_tsx11_unlock();
1538 /**********************************************************************
1539 * handle_xembed_protocol
1541 static void handle_xembed_protocol( HWND hwnd
, XClientMessageEvent
*event
)
1543 struct x11drv_win_data
*data
= X11DRV_get_win_data( hwnd
);
1547 switch (event
->data
.l
[1])
1549 case XEMBED_EMBEDDED_NOTIFY
:
1550 TRACE( "win %p/%lx XEMBED_EMBEDDED_NOTIFY owner %lx\n", hwnd
, event
->window
, event
->data
.l
[3] );
1551 data
->embedder
= event
->data
.l
[3];
1554 TRACE( "win %p/%lx XEMBED message %lu(%lu)\n",
1555 hwnd
, event
->window
, event
->data
.l
[1], event
->data
.l
[2] );
1561 /**********************************************************************
1562 * handle_dnd_protocol
1564 static void handle_dnd_protocol( HWND hwnd
, XClientMessageEvent
*event
)
1567 int root_x
, root_y
, child_x
, child_y
;
1570 /* query window (drag&drop event contains only drag window) */
1572 XQueryPointer( event
->display
, root_window
, &root
, &child
,
1573 &root_x
, &root_y
, &child_x
, &child_y
, &u
);
1574 if (XFindContext( event
->display
, child
, winContext
, (char **)&hwnd
) != 0) hwnd
= 0;
1575 wine_tsx11_unlock();
1577 if (event
->data
.l
[0] == DndFile
|| event
->data
.l
[0] == DndFiles
)
1578 EVENT_DropFromOffiX(hwnd
, event
);
1579 else if (event
->data
.l
[0] == DndURL
)
1580 EVENT_DropURLs(hwnd
, event
);
1584 struct client_message_handler
1586 int atom
; /* protocol atom */
1587 void (*handler
)(HWND
, XClientMessageEvent
*); /* corresponding handler function */
1590 static const struct client_message_handler client_messages
[] =
1592 { XATOM_MANAGER
, handle_manager_message
},
1593 { XATOM_WM_PROTOCOLS
, handle_wm_protocols
},
1594 { XATOM__XEMBED
, handle_xembed_protocol
},
1595 { XATOM_DndProtocol
, handle_dnd_protocol
},
1596 { XATOM_XdndEnter
, X11DRV_XDND_EnterEvent
},
1597 { XATOM_XdndPosition
, X11DRV_XDND_PositionEvent
},
1598 { XATOM_XdndDrop
, X11DRV_XDND_DropEvent
},
1599 { XATOM_XdndLeave
, X11DRV_XDND_LeaveEvent
}
1603 /**********************************************************************
1604 * X11DRV_ClientMessage
1606 static void X11DRV_ClientMessage( HWND hwnd
, XEvent
*xev
)
1608 XClientMessageEvent
*event
= &xev
->xclient
;
1613 if (event
->format
!= 32)
1615 WARN( "Don't know how to handle format %d\n", event
->format
);
1619 for (i
= 0; i
< sizeof(client_messages
)/sizeof(client_messages
[0]); i
++)
1621 if (event
->message_type
== X11DRV_Atoms
[client_messages
[i
].atom
- FIRST_XATOM
])
1623 client_messages
[i
].handler( hwnd
, event
);
1627 TRACE( "no handler found for %ld\n", event
->message_type
);