[totem] player: Use GdFullscreenFilter to simplify popups



commit b443b96be9d9308c13f6999a3404b6c6331cdc0a
Author: Bastien Nocera <hadess hadess net>
Date:   Wed Mar 28 12:22:39 2012 +0200

    player: Use GdFullscreenFilter to simplify popups
    
    This fixes the case where we couldn't get the popups to show
    up in fullscreen in some cases.

 data/fullscreen.ui         |    4 -
 src/Makefile.am            |    2 +
 src/gd-fullscreen-filter.c |  132 ++++++++++++++++++++++++++++++++++++++++++++
 src/gd-fullscreen-filter.h |   75 +++++++++++++++++++++++++
 src/totem-fullscreen.c     |   56 ++++++++-----------
 5 files changed, 233 insertions(+), 36 deletions(-)
---
diff --git a/data/fullscreen.ui b/data/fullscreen.ui
index 8f26f65..f0cc498 100644
--- a/data/fullscreen.ui
+++ b/data/fullscreen.ui
@@ -17,7 +17,6 @@
   <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
   <property name="focus_on_map">True</property>
   <property name="urgency_hint">False</property>
-  <signal name="motion-notify-event" handler="totem_fullscreen_motion_notify"/>
   <signal name="enter-notify-event" handler="totem_fullscreen_control_enter_notify"/>
   <signal name="leave-notify-event" handler="totem_fullscreen_control_leave_notify"/>
 
@@ -27,7 +26,6 @@
       <property name="can_focus">True</property>
       <property name="relief">GTK_RELIEF_NORMAL</property>
       <property name="focus_on_click">True</property>
-      <signal name="motion-notify-event" handler="totem_fullscreen_motion_notify"/>
 
       <child>
 	<object class="GtkAlignment" id="tefw_alignment">
@@ -110,7 +108,6 @@
   <property name="gravity">GDK_GRAVITY_SOUTH_WEST</property>
   <property name="focus_on_map">True</property>
   <property name="urgency_hint">False</property>
-  <signal name="motion-notify-event" handler="totem_fullscreen_motion_notify"/>
   <signal name="enter-notify-event" handler="totem_fullscreen_control_enter_notify"/>
   <signal name="leave-notify-event" handler="totem_fullscreen_control_leave_notify"/>
 
@@ -184,7 +181,6 @@
 	      <property name="adjustment">tcw_seek_adjustment</property>
 	      <signal name="button-press-event" handler="totem_fullscreen_seek_slider_pressed_cb"/>
 	      <signal name="button-release-event" handler="totem_fullscreen_seek_slider_released_cb"/>
-	      <signal name="motion-notify-event" handler="totem_fullscreen_motion_notify"/>
 	    </object>
 	    <packing>
 	      <property name="padding">0</property>
diff --git a/src/Makefile.am b/src/Makefile.am
index 210b921..318c2dd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -40,6 +40,8 @@ libtotem_player_la_SOURCES = \
 	totem-interface.c	\
 	totem-fullscreen.c	\
 	totem-fullscreen.h	\
+	gd-fullscreen-filter.c	\
+	gd-fullscreen-filter.h	\
 	gsd-media-keys-window.c	\
 	gsd-media-keys-window.h	\
 	gsd-osd-window.c	\
diff --git a/src/gd-fullscreen-filter.c b/src/gd-fullscreen-filter.c
new file mode 100644
index 0000000..6206d42
--- /dev/null
+++ b/src/gd-fullscreen-filter.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2012 Red Hat, Inc.
+ *
+ * Gnome Documents is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Gnome Documents is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with Gnome Documents; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#include "gd-fullscreen-filter.h"
+
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#include <X11/extensions/XInput2.h>
+
+G_DEFINE_TYPE (GdFullscreenFilter, gd_fullscreen_filter, G_TYPE_OBJECT)
+
+enum {
+  MOTION_EVENT = 1,
+  NUM_SIGNALS
+};
+
+static guint signals[NUM_SIGNALS] = { 0, };
+
+struct _GdFullscreenFilterPrivate {
+  gboolean is_filtering;
+};
+
+static void
+gd_fullscreen_filter_dispose (GObject *object)
+{
+  GdFullscreenFilter *self = GD_FULLSCREEN_FILTER (object);
+
+  gd_fullscreen_filter_stop (self);
+
+  G_OBJECT_CLASS (gd_fullscreen_filter_parent_class)->dispose (object);
+}
+
+static void
+gd_fullscreen_filter_init (GdFullscreenFilter *self)
+{
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GD_TYPE_FULLSCREEN_FILTER,
+                                            GdFullscreenFilterPrivate);
+}
+
+static void
+gd_fullscreen_filter_class_init (GdFullscreenFilterClass *klass)
+{
+  GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+  oclass->dispose = gd_fullscreen_filter_dispose;
+
+  signals[MOTION_EVENT] =
+    g_signal_new ("motion-event",
+                  GD_TYPE_FULLSCREEN_FILTER,
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
+  g_type_class_add_private (klass, sizeof (GdFullscreenFilterPrivate));
+}
+
+static GdkFilterReturn
+event_filter_func (GdkXEvent *gdk_xevent,
+                   GdkEvent *event,
+                   gpointer user_data)
+{
+  GdFullscreenFilter *self = user_data;
+  XEvent *xevent = (XEvent *) gdk_xevent;
+
+  if (xevent->xany.type == ButtonPress ||
+      xevent->xany.type == ButtonRelease ||
+      xevent->xany.type == MotionNotify)
+    {
+      g_signal_emit (self, signals[MOTION_EVENT], 0);
+    }
+  else if (xevent->xany.type == GenericEvent)
+    {
+        /* we just assume this is an XI2 event */
+        XIEvent *ev = (XIEvent *) xevent->xcookie.data;
+
+        if (ev->evtype == XI_Motion ||
+            ev->evtype == XI_ButtonRelease ||
+            ev->evtype == XI_ButtonPress)
+          {
+            g_signal_emit (self, signals[MOTION_EVENT], 0);
+          }
+    }
+
+  return GDK_FILTER_CONTINUE;
+}
+
+void
+gd_fullscreen_filter_start (GdFullscreenFilter *self)
+{
+  if (self->priv->is_filtering)
+    return;
+
+  self->priv->is_filtering = TRUE;
+  gdk_window_add_filter (NULL,
+                         event_filter_func, self);
+}
+
+void
+gd_fullscreen_filter_stop (GdFullscreenFilter *self)
+{
+  if (!self->priv->is_filtering)
+    return;
+
+  self->priv->is_filtering = FALSE;
+  gdk_window_remove_filter (NULL,
+                            event_filter_func, self);
+}
+
+GdFullscreenFilter *
+gd_fullscreen_filter_new (void)
+{
+  return g_object_new (GD_TYPE_FULLSCREEN_FILTER, NULL);
+}
diff --git a/src/gd-fullscreen-filter.h b/src/gd-fullscreen-filter.h
new file mode 100644
index 0000000..d2a6b9c
--- /dev/null
+++ b/src/gd-fullscreen-filter.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011 Red Hat, Inc.
+ *
+ * Gnome Documents is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Gnome Documents is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with Gnome Documents; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#ifndef __GD_FULLSCREEN_FILTER_H__
+#define __GD_FULLSCREEN_FILTER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GD_TYPE_FULLSCREEN_FILTER gd_fullscreen_filter_get_type()
+
+#define GD_FULLSCREEN_FILTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+   GD_TYPE_FULLSCREEN_FILTER, GdFullscreenFilter))
+
+#define GD_FULLSCREEN_FILTER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+   GD_TYPE_FULLSCREEN_FILTER, GdFullscreenFilterClass))
+
+#define GD_IS_FULLSCREEN_FILTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+   GD_TYPE_FULLSCREEN_FILTER))
+
+#define GD_IS_FULLSCREEN_FILTER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+   GD_TYPE_FULLSCREEN_FILTER))
+
+#define GD_FULLSCREEN_FILTER_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+   GD_TYPE_FULLSCREEN_FILTER, GdFullscreenFilterClass))
+
+typedef struct _GdFullscreenFilter GdFullscreenFilter;
+typedef struct _GdFullscreenFilterClass GdFullscreenFilterClass;
+typedef struct _GdFullscreenFilterPrivate GdFullscreenFilterPrivate;
+
+struct _GdFullscreenFilter
+{
+  GObject parent;
+
+  GdFullscreenFilterPrivate *priv;
+};
+
+struct _GdFullscreenFilterClass
+{
+  GObjectClass parent_class;
+};
+
+GType gd_fullscreen_filter_get_type (void) G_GNUC_CONST;
+
+GdFullscreenFilter *gd_fullscreen_filter_new (void);
+void gd_fullscreen_filter_start (GdFullscreenFilter *self);
+void gd_fullscreen_filter_stop (GdFullscreenFilter *self);
+
+G_END_DECLS
+
+#endif /* __GD_FULLSCREEN_FILTER_H__ */
diff --git a/src/totem-fullscreen.c b/src/totem-fullscreen.c
index 893f983..3ef5040 100644
--- a/src/totem-fullscreen.c
+++ b/src/totem-fullscreen.c
@@ -36,6 +36,7 @@
 #include "totem-interface.h"
 #include "totem-time-label.h"
 #include "bacon-video-widget.h"
+#include "gd-fullscreen-filter.h"
 #include "gsd-media-keys-window.h"
 
 #define FULLSCREEN_POPUP_TIMEOUT 5
@@ -51,7 +52,6 @@ G_MODULE_EXPORT gboolean totem_fullscreen_vol_slider_pressed_cb (GtkWidget *widg
 G_MODULE_EXPORT gboolean totem_fullscreen_vol_slider_released_cb (GtkWidget *widget, GdkEventButton *event, TotemFullscreen *fs);
 G_MODULE_EXPORT gboolean totem_fullscreen_seek_slider_pressed_cb (GtkWidget *widget, GdkEventButton *event, TotemFullscreen *fs);
 G_MODULE_EXPORT gboolean totem_fullscreen_seek_slider_released_cb (GtkWidget *widget, GdkEventButton *event, TotemFullscreen *fs);
-G_MODULE_EXPORT gboolean totem_fullscreen_motion_notify (GtkWidget *widget, GdkEventMotion *event, TotemFullscreen *fs);
 G_MODULE_EXPORT gboolean totem_fullscreen_control_enter_notify (GtkWidget *widget, GdkEventCrossing *event, TotemFullscreen *fs);
 G_MODULE_EXPORT gboolean totem_fullscreen_control_leave_notify (GtkWidget *widget, GdkEventCrossing *event, TotemFullscreen *fs);
 
@@ -71,9 +71,9 @@ struct _TotemFullscreenPrivate {
 	guint             popup_timeout;
 	gboolean          popup_in_progress;
 	gboolean          pointer_on_control;
-	guint             motion_handler_id;
-	guint             motion_start_time;
-	guint             motion_num_events;
+	GdFullscreenFilter *filter;
+	gint64             motion_start_time;
+	guint              motion_num_events;
 
 	gboolean          is_fullscreen;
 
@@ -275,24 +275,25 @@ totem_fullscreen_popup_hide (TotemFullscreen *fs)
 	return FALSE;
 }
 
-G_MODULE_EXPORT gboolean
-totem_fullscreen_motion_notify (GtkWidget *widget,
-				GdkEventMotion *event,
-				TotemFullscreen *fs)
+static void
+totem_fullscreen_motion_notify (GdFullscreenFilter *filter,
+				TotemFullscreen    *fs)
 {
-	int motion_delay;
+	gint64 motion_delay;
+	gint64 curr;
 
+	curr = g_get_monotonic_time ();
 	/* Only after FULLSCREEN_MOTION_NUM_EVENTS motion events,
 	   in FULLSCREEN_MOTION_TIME milliseconds will we show
 	   the popups */
-	motion_delay = event->time - fs->priv->motion_start_time;
+	motion_delay = (curr - fs->priv->motion_start_time) / 1000;
 
 	if (fs->priv->motion_start_time == 0 ||
 	    motion_delay < 0 ||
 	    motion_delay > FULLSCREEN_MOTION_TIME) {
-		fs->priv->motion_start_time = event->time;
+		fs->priv->motion_start_time = curr;
 		fs->priv->motion_num_events = 0;
-		return FALSE;
+		return;
 	}
 
 	fs->priv->motion_num_events++;
@@ -301,8 +302,6 @@ totem_fullscreen_motion_notify (GtkWidget *widget,
 	    fs->priv->motion_num_events > FULLSCREEN_MOTION_NUM_EVENTS) {
 		totem_fullscreen_show_popups (fs, TRUE);
 	}
-
-	return FALSE;
 }
 
 void
@@ -416,14 +415,10 @@ totem_fullscreen_set_fullscreen (TotemFullscreen *fs,
 
 	fs->priv->is_fullscreen = fullscreen;
 
-	if (fullscreen == FALSE && fs->priv->motion_handler_id != 0) {
-		g_signal_handler_disconnect (G_OBJECT (fs->priv->bvw),
-					     fs->priv->motion_handler_id);
-		fs->priv->motion_handler_id = 0;
-	} else if (fullscreen != FALSE && fs->priv->motion_handler_id == 0 && fs->priv->bvw != NULL) {
-		fs->priv->motion_handler_id = g_signal_connect (G_OBJECT (fs->priv->bvw), "motion-notify-event",
-								G_CALLBACK (totem_fullscreen_motion_notify), fs);
-	}
+	if (fullscreen == FALSE)
+		gd_fullscreen_filter_stop (fs->priv->filter);
+	else
+		gd_fullscreen_filter_start (fs->priv->filter);
 }
 
 static void
@@ -469,11 +464,14 @@ totem_fullscreen_new (GtkWindow *toplevel_window)
 
 	/* Volume */
 	fs->volume = GTK_WIDGET (gtk_builder_get_object (fs->priv->xml, "tcw_volume_button"));
-	
+
 	/* Seek */
 	fs->seek = GTK_WIDGET (gtk_builder_get_object (fs->priv->xml, "tcw_seek_hscale"));
 
 	/* Motion notify */
+	fs->priv->filter = gd_fullscreen_filter_new ();
+	g_signal_connect (G_OBJECT (fs->priv->filter), "motion-event",
+			  G_CALLBACK (totem_fullscreen_motion_notify), fs);
 	gtk_widget_add_events (fs->seek, GDK_POINTER_MOTION_MASK);
 	gtk_widget_add_events (fs->exit_button, GDK_POINTER_MOTION_MASK);
 
@@ -489,11 +487,6 @@ totem_fullscreen_set_video_widget (TotemFullscreen *fs,
 	g_return_if_fail (fs->priv->bvw == NULL);
 
 	fs->priv->bvw = bvw;
-
-	if (fs->priv->is_fullscreen != FALSE && fs->priv->motion_handler_id == 0) {
-		fs->priv->motion_handler_id = g_signal_connect (G_OBJECT (fs->priv->bvw), "motion-notify-event",
-								G_CALLBACK (totem_fullscreen_motion_notify), fs);
-	}
 }
 
 void
@@ -561,10 +554,9 @@ totem_fullscreen_finalize (GObject *object)
         TotemFullscreen *fs = TOTEM_FULLSCREEN (object);
 
 	totem_fullscreen_popup_timeout_remove (fs);
-	if (fs->priv->motion_handler_id != 0) {
-		g_signal_handler_disconnect (G_OBJECT (fs->priv->bvw),
-					     fs->priv->motion_handler_id);
-		fs->priv->motion_handler_id = 0;
+	if (fs->priv->filter) {
+		g_object_unref (fs->priv->filter);
+		fs->priv->filter = NULL;
 	}
 
 	if (fs->priv->osd != NULL) {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]