static bool xw_maybe_synthesize_crossing (struct xwidget_view *,
GdkWindow *, int, int, int,
- Time, unsigned int);
+ Time, unsigned int,
+ GdkCrossingMode, GdkCrossingMode);
static void xw_notify_virtual_upwards_until (struct xwidget_view *, GdkWindow *,
GdkWindow *, GdkWindow *, unsigned int,
- int, int, Time, GdkEventType, bool);
+ int, int, Time, GdkEventType, bool,
+ GdkCrossingMode);
static void window_coords_from_toplevel (GdkWindow *, GdkWindow *, int,
int, int *, int *);
#endif
{
xw_maybe_synthesize_crossing (view, gtk_widget_get_window (ungrab_target),
view_x, view_y, XW_CROSSING_NONE,
- time, modifier_state);
+ time, modifier_state, GDK_CROSSING_UNGRAB,
+ GDK_CROSSING_UNGRAB);
}
else
{
xw_notify_virtual_upwards_until (view, target_window, toplevel, toplevel,
modifier_state, view_x, view_y, time,
- GDK_LEAVE_NOTIFY, false);
+ GDK_LEAVE_NOTIFY, false,
+ GDK_CROSSING_UNGRAB);
if (target_window != toplevel)
{
}
else if (xw_maybe_synthesize_crossing (view, gtk_widget_get_window (target),
x + view->clip_left, y + view->clip_top,
- XW_CROSSING_NONE, time, state))
+ XW_CROSSING_NONE, time, state,
+ (view->passive_grab
+ ? GDK_CROSSING_GRAB
+ : GDK_CROSSING_NORMAL),
+ GDK_CROSSING_NORMAL))
return;
xg_event = gdk_event_new (GDK_MOTION_NOTIFY);
unsigned int state,
int x, int y, Time time,
GdkEventType type,
- bool nonlinear_p)
+ bool nonlinear_p,
+ GdkCrossingMode crossing)
{
GdkEvent *xg_event;
GdkWindow *tem;
xg_event->crossing.detail = (nonlinear_p
? GDK_NOTIFY_NONLINEAR_VIRTUAL
: GDK_NOTIFY_VIRTUAL);
- xg_event->crossing.mode = GDK_CROSSING_NORMAL;
+ xg_event->crossing.mode = crossing;
xg_event->crossing.window = g_object_ref (tem);
gtk_main_do_event (xg_event);
unsigned int state,
int x, int y, Time time,
GdkEventType type,
- bool nonlinear_p)
+ bool nonlinear_p,
+ GdkCrossingMode crossing)
{
GdkEvent *xg_event;
GdkWindow *tem;
xg_event->crossing.detail = (nonlinear_p
? GDK_NOTIFY_NONLINEAR_VIRTUAL
: GDK_NOTIFY_VIRTUAL);
- xg_event->crossing.mode = GDK_CROSSING_NORMAL;
+ xg_event->crossing.mode = crossing;
xg_event->crossing.window = g_object_ref (tem);
gtk_main_do_event (xg_event);
xw_maybe_synthesize_crossing (struct xwidget_view *view,
GdkWindow *current_window,
int x, int y, int crossing,
- Time time, unsigned int state)
+ Time time, unsigned int state,
+ GdkCrossingMode entry_crossing,
+ GdkCrossingMode exit_crossing)
{
GdkWindow *last_crossing, *toplevel, *ancestor;
GdkEvent *xg_event;
int cx, cy;
bool nonlinear_p;
+ bool retention_flag;
toplevel = gtk_widget_get_window (XXWIDGET (view->model)->widgetwindow_osr);
+ retention_flag = false;
if (crossing == XW_CROSSING_LEFT
&& (view->last_crossing_window
xw_notify_virtual_upwards_until (view, view->last_crossing_window,
toplevel, toplevel,
state, x, y, time,
- GDK_LEAVE_NOTIFY, false);
+ GDK_LEAVE_NOTIFY, false,
+ exit_crossing);
}
if (view->last_crossing_window
&& (gdk_window_is_destroyed (view->last_crossing_window)
|| crossing == XW_CROSSING_LEFT))
{
+ if (!gdk_window_is_destroyed (view->last_crossing_window)
+ && view->last_crossing_window != toplevel)
+ {
+ xg_event = gdk_event_new (GDK_LEAVE_NOTIFY);
+ window_coords_from_toplevel (view->last_crossing_window,
+ toplevel, x, y, &cx, &cy);
+
+ xg_event->crossing.x = cx;
+ xg_event->crossing.y = cy;
+ xg_event->crossing.time = time;
+ xg_event->crossing.focus = FALSE;
+ xg_event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+ xg_event->crossing.mode = exit_crossing;
+ xg_event->crossing.window = g_object_ref (view->last_crossing_window);
+ gdk_event_set_device (xg_event, find_suitable_pointer (view->frame));
+
+ gtk_main_do_event (xg_event);
+ gdk_event_free (xg_event);
+
+ xw_notify_virtual_upwards_until (view, view->last_crossing_window,
+ gdk_window_get_parent (toplevel),
+ toplevel, state, x, y, time,
+ GDK_LEAVE_NOTIFY, false, exit_crossing);
+ retention_flag = true;
+ }
+
g_signal_handler_disconnect (view->last_crossing_window,
view->last_crossing_cursor_signal);
g_clear_pointer (&view->last_crossing_window,
toplevel, toplevel,
state, x, y, time,
GDK_ENTER_NOTIFY,
- false);
+ false, entry_crossing);
}
- return false;
+ return retention_flag;
}
if (last_crossing != current_window)
ancestor, toplevel,
state, x, y, time,
GDK_LEAVE_NOTIFY,
- nonlinear_p);
+ nonlinear_p,
+ exit_crossing);
xg_event = gdk_event_new (GDK_LEAVE_NOTIFY);
gdk_event_set_device (xg_event, find_suitable_pointer (view->frame));
xg_event->crossing.time = time;
xg_event->crossing.focus = FALSE;
xg_event->crossing.state = state;
- /* TODO: actually calculate the event mode. */
xg_event->crossing.detail = (nonlinear_p
? GDK_NOTIFY_NONLINEAR
: (last_crossing == ancestor
? GDK_NOTIFY_INFERIOR
: GDK_NOTIFY_ANCESTOR));
- xg_event->crossing.mode = GDK_CROSSING_NORMAL;
+ xg_event->crossing.mode = exit_crossing;
xg_event->crossing.window = g_object_ref (last_crossing);
gtk_main_do_event (xg_event);
ancestor, toplevel,
state, x, y, time,
GDK_ENTER_NOTIFY,
- nonlinear_p);
+ nonlinear_p,
+ entry_crossing);
xg_event = gdk_event_new (GDK_ENTER_NOTIFY);
gdk_event_set_device (xg_event, find_suitable_pointer (view->frame));
: (current_window == ancestor
? GDK_NOTIFY_INFERIOR
: GDK_NOTIFY_ANCESTOR));
- xg_event->crossing.mode = GDK_CROSSING_NORMAL;
+ xg_event->crossing.mode = entry_crossing;
xg_event->crossing.window = g_object_ref (current_window);
gtk_main_do_event (xg_event);
if (!xw_maybe_synthesize_crossing (view, xg_event->any.window,
toplevel_x, toplevel_y,
XW_CROSSING_NONE, event->xmotion.time,
- event->xmotion.state))
+ event->xmotion.state,
+ (view->passive_grab
+ ? GDK_CROSSING_GRAB
+ : GDK_CROSSING_NORMAL),
+ GDK_CROSSING_NORMAL))
{
xg_event->motion.x = x;
xg_event->motion.y = y;
(xev->type == XI_Enter
? XW_CROSSING_ENTERED
: XW_CROSSING_LEFT),
- xev->time, xg_event->crossing.state))
+ xev->time, xg_event->crossing.state,
+ (view->passive_grab
+ ? GDK_CROSSING_GRAB
+ : GDK_CROSSING_NORMAL),
+ GDK_CROSSING_NORMAL))
{
gdk_event_free (xg_event);
return;
? XW_CROSSING_ENTERED
: XW_CROSSING_LEFT),
event->xcrossing.time,
- event->xcrossing.state))
+ event->xcrossing.state,
+ (view->passive_grab
+ ? GDK_CROSSING_GRAB
+ : GDK_CROSSING_NORMAL),
+ GDK_CROSSING_NORMAL))
{
gdk_event_free (xg_event);
return;