[gnome-documents] nav-bar: implement hover logic for controls
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-documents] nav-bar: implement hover logic for controls
- Date: Tue, 15 Apr 2014 02:06:40 +0000 (UTC)
commit 74dd32170d3aca20bbce1282bd24193807306603
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Mon Apr 14 19:01:59 2014 -0700
nav-bar: implement hover logic for controls
Use a full I/O window for GdNavBar, so we can get notified of inferior
events meaningfully and expose a "hover" property on the widget, which
will be TRUE regardless of any sub-widget the pointer might be in.
http://bugzilla.gnome.org/show_bug.cgi?id=725369
src/lib/gd-nav-bar.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++----
src/lib/gd-nav-bar.h | 1 +
src/preview.js | 8 ++-
3 files changed, 134 insertions(+), 12 deletions(-)
---
diff --git a/src/lib/gd-nav-bar.c b/src/lib/gd-nav-bar.c
index 8264dd8..721d9f4 100644
--- a/src/lib/gd-nav-bar.c
+++ b/src/lib/gd-nav-bar.c
@@ -39,6 +39,7 @@ G_DEFINE_TYPE (GdNavBar, gd_nav_bar, GTK_TYPE_BOX);
enum {
PROP_DOCUMENT_MODEL = 1,
+ PROP_HOVER,
NUM_PROPERTIES
};
@@ -81,7 +82,9 @@ struct _GdNavBarPrivate {
int preview_page;
int page_start;
int page_end;
+
gboolean scrubbing;
+ gboolean hover;
};
/* Thumbnails dimensions cache */
@@ -560,6 +563,9 @@ gd_nav_bar_get_property (GObject *object,
case PROP_DOCUMENT_MODEL:
g_value_set_object (value, self->priv->model);
break;
+ case PROP_HOVER:
+ g_value_set_boolean (value, gd_nav_bar_get_hover (self));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -612,6 +618,102 @@ gd_nav_bar_dispose (GObject *object)
G_OBJECT_CLASS (gd_nav_bar_parent_class)->dispose (object);
}
+static void
+gd_nav_bar_set_hover (GdNavBar *self,
+ gboolean hover)
+{
+ if (self->priv->hover == hover) {
+ return;
+ }
+
+ self->priv->hover = hover;
+ g_object_notify (G_OBJECT (self), "hover");
+}
+
+static gboolean
+gd_nav_bar_enter_notify (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ GdNavBar *self = GD_NAV_BAR (widget);
+ GdNavBarPrivate *priv = self->priv;
+
+ if (event->detail != GDK_NOTIFY_INFERIOR) {
+ gd_nav_bar_set_hover (self, TRUE);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+gd_nav_bar_leave_notify (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ GdNavBar *self = GD_NAV_BAR (widget);
+ GdNavBarPrivate *priv = self->priv;
+
+ if (event->detail != GDK_NOTIFY_INFERIOR) {
+ gd_nav_bar_set_hover (self, FALSE);
+ }
+
+ return FALSE;
+}
+
+static void
+gd_nav_bar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GdNavBar *self = GD_NAV_BAR (widget);
+ GdNavBarPrivate *priv = self->priv;
+
+ GTK_WIDGET_CLASS (gd_nav_bar_parent_class)->size_allocate (widget, allocation);
+
+ if (gtk_widget_get_realized (widget)) {
+ gdk_window_move_resize (gtk_widget_get_window (widget),
+ allocation->x,
+ allocation->y,
+ allocation->width,
+ allocation->height);
+ }
+}
+
+static void
+gd_nav_bar_realize (GtkWidget *widget)
+{
+ GdNavBar *self = GD_NAV_BAR (widget);
+ GdNavBarPrivate *priv = self->priv;
+ GtkAllocation allocation;
+ GdkWindow *window;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ gtk_widget_set_realized (widget, TRUE);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = allocation.x;
+ attributes.y = allocation.y;
+ attributes.width = allocation.width;
+ attributes.height = allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_TOUCH_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
+
+ window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
+ gtk_widget_set_window (widget, window);
+ gtk_widget_register_window (widget, window);
+
+ gtk_style_context_set_background (gtk_widget_get_style_context (widget), window);
+}
+
static gboolean
gd_nav_bar_draw (GtkWidget *widget,
cairo_t *cr)
@@ -640,7 +742,12 @@ gd_nav_bar_class_init (GdNavBarClass *class)
oclass->dispose = gd_nav_bar_dispose;
oclass->get_property = gd_nav_bar_get_property;
oclass->set_property = gd_nav_bar_set_property;
+
wclass->draw = gd_nav_bar_draw;
+ wclass->realize = gd_nav_bar_realize;
+ wclass->enter_notify_event = gd_nav_bar_enter_notify;
+ wclass->leave_notify_event = gd_nav_bar_leave_notify;
+ wclass->size_allocate = gd_nav_bar_size_allocate;
g_object_class_install_property (oclass,
PROP_DOCUMENT_MODEL,
@@ -651,6 +758,14 @@ gd_nav_bar_class_init (GdNavBarClass *class)
G_PARAM_CONSTRUCT |
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (oclass,
+ PROP_HOVER,
+ g_param_spec_boolean ("hover",
+ "Hover",
+ "Whether the widget is hovered",
+ FALSE,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
g_type_class_add_private (oclass, sizeof (GdNavBarPrivate));
}
@@ -683,12 +798,10 @@ hide_preview (GdNavBar *self)
static void
show_preview (GdNavBar *self)
{
- GdkWindow *window, *toplevel_window;
- GtkWidget *toplevel;
+ GdkWindow *window;
int x, y;
int width, height;
int bx, by;
- int tx, ty;
gtk_widget_realize (self->priv->preview_window);
@@ -696,14 +809,10 @@ show_preview (GdNavBar *self)
height = gtk_widget_get_allocated_height (GTK_WIDGET (self->priv->preview_window));
window = gtk_widget_get_window (GTK_WIDGET (self));
- gdk_window_get_position (window, &bx, &by);
+ gdk_window_get_origin (window, &bx, &by);
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
- toplevel_window = gtk_widget_get_window (toplevel);
- gdk_window_get_origin (toplevel_window, &tx, &ty);
-
- x = tx + bx + (gdk_window_get_width (window) - width) / 2;
- y = ty + by - height - 10;
+ x = bx + (gdk_window_get_width (window) - width) / 2;
+ y = by - height - 10;
gtk_window_move (GTK_WINDOW (self->priv->preview_window), x, y);
gtk_window_present (GTK_WINDOW (self->priv->preview_window));
@@ -899,6 +1008,8 @@ gd_nav_bar_init (GdNavBar *self)
priv = self->priv;
+ gtk_widget_set_has_window (GTK_WIDGET (self), TRUE);
+
priv->loading_icons = g_hash_table_new_full (g_str_hash,
g_str_equal,
(GDestroyNotify)g_free,
@@ -953,6 +1064,12 @@ gd_nav_bar_init (GdNavBar *self)
create_preview_window (self);
}
+gboolean
+gd_nav_bar_get_hover (GdNavBar *bar)
+{
+ return bar->priv->hover;
+}
+
/**
* gd_nav_bar_new:
* @model: the #EvDocumentModel
diff --git a/src/lib/gd-nav-bar.h b/src/lib/gd-nav-bar.h
index 93ca0f7..6b5c94d 100644
--- a/src/lib/gd-nav-bar.h
+++ b/src/lib/gd-nav-bar.h
@@ -53,6 +53,7 @@ GType gd_nav_bar_get_type (void) G_GNUC_CONST;
GtkWidget *gd_nav_bar_new (EvDocumentModel *model);
GtkWidget *gd_nav_bar_get_button_area (GdNavBar *bar);
+gboolean gd_nav_bar_get_hover (GdNavBar *bar);
G_END_DECLS
diff --git a/src/preview.js b/src/preview.js
index 295991d..92fe2c0 100644
--- a/src/preview.js
+++ b/src/preview.js
@@ -589,8 +589,12 @@ const PreviewNavControls = new Lang.Class({
opacity: 0 });
this.bar_widget.get_style_context().add_class('osd');
this._overlay.add_overlay(this.bar_widget);
- this.bar_widget.connect('enter-notify-event', Lang.bind(this, this._onEnterNotify));
- this.bar_widget.connect('leave-notify-event', Lang.bind(this, this._onLeaveNotify));
+ this.bar_widget.connect('notify::hover', Lang.bind(this, function() {
+ if (this.bar_widget.hover)
+ this._onEnterNotify();
+ else
+ this._onLeaveNotify();
+ }));
let buttonArea = this.bar_widget.get_button_area();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]