st-scroll-bar: use clutter_grab_pointer()

StScrollBar was intercepting motion events by using captured-event on
the stage, which required additional dirty tricks, which required
additional hacks. Simplify it by just using clutter_grab_pointer()
instead.

https://bugzilla.gnome.org/show_bug.cgi?id=671001
This commit is contained in:
Dan Winship 2011-10-28 17:32:32 -04:00 committed by Jasper St. Pierre
parent b36029f6c4
commit c540cb5e16
2 changed files with 27 additions and 70 deletions

View File

@ -863,10 +863,6 @@ const PopupMenuBase = new Lang.Class({
// for the menu which causes its prelight state to freeze // for the menu which causes its prelight state to freeze
this.blockSourceEvents = false; this.blockSourceEvents = false;
// Can be set while a menu is up to let all events through without special
// menu handling useful for scrollbars in menus, and probably not otherwise.
this.passEvents = false;
this._activeMenuItem = null; this._activeMenuItem = null;
this._childMenus = []; this._childMenus = [];
this._settingsActions = { }; this._settingsActions = { };
@ -1285,24 +1281,6 @@ const PopupSubMenu = new Lang.Class({
hscrollbar_policy: Gtk.PolicyType.NEVER, hscrollbar_policy: Gtk.PolicyType.NEVER,
vscrollbar_policy: Gtk.PolicyType.NEVER }); vscrollbar_policy: Gtk.PolicyType.NEVER });
// StScrollbar plays dirty tricks with events, calling
// clutter_set_motion_events_enabled (FALSE) during the scroll; this
// confuses our event tracking, so we just turn it off during the
// scroll.
let vscroll = this.actor.get_vscroll_bar();
vscroll.connect('scroll-start',
Lang.bind(this, function() {
let topMenu = this._getTopMenu();
if (topMenu)
topMenu.passEvents = true;
}));
vscroll.connect('scroll-stop',
Lang.bind(this, function() {
let topMenu = this._getTopMenu();
if (topMenu)
topMenu.passEvents = false;
}));
this.actor.add_actor(this.box); this.actor.add_actor(this.box);
this.actor._delegate = this; this.actor._delegate = this;
this.actor.clip_to_allocation = true; this.actor.clip_to_allocation = true;
@ -2279,9 +2257,6 @@ const PopupMenuManager = new Lang.Class({
this._owner.menuEventFilter(event)) this._owner.menuEventFilter(event))
return true; return true;
if (this._activeMenu != null && this._activeMenu.passEvents)
return false;
if (this._didPop) { if (this._didPop) {
this._didPop = false; this._didPop = false;
return true; return true;

View File

@ -52,7 +52,7 @@ struct _StScrollBarPrivate
{ {
StAdjustment *adjustment; StAdjustment *adjustment;
gulong capture_handler; gboolean grabbed;
gfloat x_origin; gfloat x_origin;
gfloat y_origin; gfloat y_origin;
@ -586,52 +586,37 @@ move_slider (StScrollBar *bar,
static void static void
stop_scrolling (StScrollBar *bar) stop_scrolling (StScrollBar *bar)
{ {
ClutterStage *stage; if (!bar->priv->grabbed)
if (!bar->priv->capture_handler)
return; return;
st_widget_remove_style_pseudo_class (ST_WIDGET (bar->priv->handle), "active"); st_widget_remove_style_pseudo_class (ST_WIDGET (bar->priv->handle), "active");
stage = CLUTTER_STAGE (clutter_actor_get_stage (bar->priv->trough)); clutter_ungrab_pointer ();
g_signal_handler_disconnect (stage, bar->priv->capture_handler); bar->priv->grabbed = FALSE;
bar->priv->capture_handler = 0;
clutter_stage_set_motion_events_enabled (stage, TRUE);
g_signal_emit (bar, signals[SCROLL_STOP], 0); g_signal_emit (bar, signals[SCROLL_STOP], 0);
} }
static gboolean static gboolean
handle_capture_event_cb (ClutterActor *trough, handle_motion_event_cb (ClutterActor *trough,
ClutterEvent *event, ClutterMotionEvent *event,
StScrollBar *bar) StScrollBar *bar)
{ {
if (clutter_event_type (event) == CLUTTER_MOTION) if (!bar->priv->grabbed)
{ return FALSE;
move_slider (bar,
((ClutterMotionEvent*) event)->x, move_slider (bar, event->x, event->y);
((ClutterMotionEvent*) event)->y); return TRUE;
} }
else if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE
&& ((ClutterButtonEvent*) event)->button == 1) static gboolean
{ handle_button_release_event_cb (ClutterActor *trough,
ClutterActor *stage, *target; ClutterButtonEvent *event,
StScrollBar *bar)
{
if (event->button != 1)
return FALSE;
stop_scrolling (bar); stop_scrolling (bar);
/* check if the mouse pointer has left the handle during the drag and
* remove the hover state if it has */
stage = clutter_actor_get_stage (bar->priv->trough);
target = clutter_stage_get_actor_at_pos ((ClutterStage*) stage,
CLUTTER_PICK_REACTIVE,
((ClutterButtonEvent*) event)->x,
((ClutterButtonEvent*) event)->y);
if (target != bar->priv->handle)
{
st_widget_remove_style_pseudo_class ((StWidget*) bar->priv->handle, "hover");
}
}
return TRUE; return TRUE;
} }
@ -640,7 +625,6 @@ handle_button_press_event_cb (ClutterActor *actor,
ClutterButtonEvent *event, ClutterButtonEvent *event,
StScrollBar *bar) StScrollBar *bar)
{ {
ClutterStage *stage;
StScrollBarPrivate *priv = bar->priv; StScrollBarPrivate *priv = bar->priv;
if (event->button != 1) if (event->button != 1)
@ -659,16 +643,10 @@ handle_button_press_event_cb (ClutterActor *actor,
priv->x_origin += clutter_actor_get_x (priv->trough); priv->x_origin += clutter_actor_get_x (priv->trough);
priv->y_origin += clutter_actor_get_y (priv->trough); priv->y_origin += clutter_actor_get_y (priv->trough);
stage = CLUTTER_STAGE (clutter_actor_get_stage (bar->priv->trough)); g_assert (!priv->grabbed);
/* Turn off picking for motion events */ clutter_grab_pointer (priv->handle);
clutter_stage_set_motion_events_enabled (stage, FALSE); priv->grabbed = TRUE;
priv->capture_handler = g_signal_connect_after (
clutter_actor_get_stage (priv->trough),
"captured-event",
G_CALLBACK (handle_capture_event_cb),
bar);
g_signal_emit (bar, signals[SCROLL_START], 0); g_signal_emit (bar, signals[SCROLL_START], 0);
return TRUE; return TRUE;
@ -885,6 +863,10 @@ st_scroll_bar_init (StScrollBar *self)
CLUTTER_ACTOR (self->priv->handle)); CLUTTER_ACTOR (self->priv->handle));
g_signal_connect (self->priv->handle, "button-press-event", g_signal_connect (self->priv->handle, "button-press-event",
G_CALLBACK (handle_button_press_event_cb), self); G_CALLBACK (handle_button_press_event_cb), self);
g_signal_connect (self->priv->handle, "button-release-event",
G_CALLBACK (handle_button_release_event_cb), self);
g_signal_connect (self->priv->handle, "motion-event",
G_CALLBACK (handle_motion_event_cb), self);
clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE); clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);