Index: he-fullscreen-button.c =================================================================== --- he-fullscreen-button.c (revision 11) +++ he-fullscreen-button.c (working copy) @@ -40,15 +40,35 @@ */ #include +#include #include "he-fullscreen-button.h" #define FULLSCREEN_BUTTON_WIDTH 80 #define FULLSCREEN_BUTTON_HEIGHT 70 #define FULLSCREEN_BUTTON_HIDE_DELAY 5000 #define FULLSCREEN_BUTTON_CORNER_RADIUS 20 +#define FULLSCREEN_BUTTON_ICON "general_fullsize" +#define FULLSCREEN_BUTTON_ICON_SIZE 48 #define OFFSET 0 +typedef struct _HeFullscreenButtonPrivate HeFullscreenButtonPrivate; +struct _HeFullscreenButtonPrivate +{ + gboolean release_event; + guint32 last_event_time; + + guint button_press_signal_id; + guint button_release_signal_id; + + gulong button_press_hook_id; + gulong button_release_hook_id; +}; + +#define HE_FULLSCREEN_BUTTON_GET_PRIVATE(object) \ + (G_TYPE_INSTANCE_GET_PRIVATE((object), \ + HE_TYPE_FULLSCREEN_BUTTON, HeFullscreenButtonPrivate)) + G_DEFINE_TYPE(HeFullscreenButton, he_fullscreen_button, G_TYPE_OBJECT) @@ -78,13 +98,11 @@ GtkWidget *parent = GTK_WIDGET (self->parent_window); GtkWidget *overlay = GTK_WIDGET (self->overlay); - /* For some reason I have to call hide/show to make it appear at the new position */ gint x = parent->allocation.width - overlay->allocation.width; gint y = parent->allocation.height - overlay->allocation.height - OFFSET; - gtk_widget_hide (overlay); gtk_window_move (GTK_WINDOW (overlay), x, y); - gtk_widget_show (overlay); + gdk_window_reparent (overlay->window, parent->window, x, y); /* qwerty12 note: Not sure if calling this multiple times is good? But a reparent of its GdkWindow is required for the button to stay in the application's window, and not escape onto the task switcher and desktop. And you don't need to hide/show for the position to be changed :) */ } @@ -109,11 +127,14 @@ g_return_if_fail (self != NULL); g_return_if_fail (GTK_IS_WIDGET (self->overlay)); + HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self); + g_return_if_fail (priv != NULL); + /* Stop return button hide timeout */ g_source_remove_by_user_data ((gpointer) self); /* Only show overlay if we come here through a button release event, not a button press event */ - if (self->release_event) { + if (priv->release_event) { fullscreen_button_set_position (self); gtk_widget_show (self->overlay); @@ -130,7 +151,7 @@ * button release on the parent window. */ static gboolean -fullscreen_button_input_activity_hook (GSignalInvocationHint *ihint, +fullscreen_button_input_activity_hook (GSignalInvocationHint *ihint G_GNUC_UNUSED, guint n_param_values, const GValue *param_values, gpointer data) @@ -138,6 +159,9 @@ HeFullscreenButton *self = HE_FULLSCREEN_BUTTON (data); g_return_val_if_fail (self, FALSE); + HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self); + g_return_val_if_fail (priv != NULL, FALSE); + GdkEventAny *event = NULL; if (n_param_values >= 2) @@ -162,15 +186,15 @@ /* We're likely to get events multiple times as they're propagated, so filter out events that we've already seen. */ - if (time == self->last_event_time) { + if (time == priv->last_event_time) { return TRUE; } - self->last_event_time = time; + priv->last_event_time = time; if (event && (event->type == GDK_BUTTON_PRESS)) { - self->release_event = FALSE; + priv->release_event = FALSE; } else { - self->release_event = TRUE; + priv->release_event = TRUE; } fullscreen_button_show (self); @@ -189,20 +213,23 @@ { g_return_if_fail(HE_IS_FULLSCREEN_BUTTON(self)); - if (self->button_press_hook_id == 0) { - self->button_press_signal_id = + HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self); + g_return_if_fail (priv != NULL); + + if (priv->button_press_hook_id == 0) { + priv->button_press_signal_id = g_signal_lookup ("button-press-event", GTK_TYPE_WIDGET); - self->button_press_hook_id = - g_signal_add_emission_hook (self->button_press_signal_id, 0, + priv->button_press_hook_id = + g_signal_add_emission_hook (priv->button_press_signal_id, 0, fullscreen_button_input_activity_hook, (gpointer) self, NULL); } - if (self->button_release_hook_id == 0) { - self->button_release_signal_id = + if (priv->button_release_hook_id == 0) { + priv->button_release_signal_id = g_signal_lookup ("button-release-event", GTK_TYPE_WIDGET); - self->button_release_hook_id = - g_signal_add_emission_hook (self->button_release_signal_id, 0, + priv->button_release_hook_id = + g_signal_add_emission_hook (priv->button_release_signal_id, 0, fullscreen_button_input_activity_hook, (gpointer) self, NULL); } @@ -220,18 +247,21 @@ { g_return_if_fail (HE_IS_FULLSCREEN_BUTTON (self)); + HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self); + g_return_if_fail (priv != NULL); + fullscreen_button_hide (self); - if (self->button_release_hook_id > 0) { - g_signal_remove_emission_hook (self->button_release_signal_id, - self->button_release_hook_id); - self->button_release_hook_id = 0; + if (priv->button_release_hook_id > 0) { + g_signal_remove_emission_hook (priv->button_release_signal_id, + priv->button_release_hook_id); + priv->button_release_hook_id = 0; } - if (self->button_press_hook_id > 0) { - g_signal_remove_emission_hook (self->button_press_signal_id, - self->button_press_hook_id); - self->button_press_hook_id = 0; + if (priv->button_press_hook_id > 0) { + g_signal_remove_emission_hook (priv->button_press_signal_id, + priv->button_press_hook_id); + priv->button_press_hook_id = 0; } } @@ -240,10 +270,12 @@ * Everytime the button is clicked, be emmit the "clicked" signal. */ static gboolean -fullscreen_button_on_clicked (GtkWidget *widget, GdkEventButton *event, gpointer data) +fullscreen_button_on_clicked (GtkWidget *widget, GdkEventButton *event G_GNUC_UNUSED, gpointer data) { HeFullscreenButton *self = HE_FULLSCREEN_BUTTON (data); g_signal_emit_by_name (self, "clicked"); + + return TRUE; } @@ -268,7 +300,7 @@ * Does the actuall drawing of the semi transparent button graphic. */ static gboolean -fullscreen_button_on_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer data) +fullscreen_button_on_expose_event (GtkWidget *widget, GdkEventExpose *event G_GNUC_UNUSED, gpointer data) { cairo_t *ctx; GdkPixbuf *pixbuf = GDK_PIXBUF (data); @@ -304,7 +336,7 @@ { g_return_val_if_fail(HE_IS_FULLSCREEN_BUTTON(self), NULL); - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ("/usr/share/icons/hicolor/48x48/hildon/general_fullsize.png", NULL); + GdkPixbuf *pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), FULLSCREEN_BUTTON_ICON, FULLSCREEN_BUTTON_ICON_SIZE, 0, NULL); GtkWidget *img = gtk_image_new_from_pixbuf (pixbuf); gtk_widget_show (img); g_object_unref (pixbuf); @@ -338,7 +370,7 @@ * If it is fullscreen, we enable the fullscreen button. If not, not. */ static gboolean -fullscreen_button_on_window_state_changed (GtkWidget *widget, +fullscreen_button_on_window_state_changed (GtkWidget *widget G_GNUC_UNUSED, GdkEventWindowState *event, gpointer data) { @@ -362,7 +394,7 @@ * Destroys the fullscreen button and disconnects itself from the parent window. */ static void -fullscreen_button_destroy (GtkWidget *parent_window, HeFullscreenButton *self) +fullscreen_button_destroy (GtkWidget *parent_window G_GNUC_UNUSED, HeFullscreenButton *self) { g_return_if_fail (self != NULL); @@ -456,6 +488,14 @@ g_signal_connect_after (parent_window, "size-allocate", G_CALLBACK(fullscreen_button_on_parent_size_changed), self); +#if 0 /* qwerty12 note: Not sure if iterating GTK's main loop is the way to go, so I've commented it out. Please review. This snippet enables the button if the window is already in fullscreen mode. :) */ + if ((GTK_WIDGET_DRAWABLE (parent_window)) && (GTK_WIDGET (parent_window)->window) && (gdk_window_get_state (GTK_WIDGET (parent_window)->window) & GDK_WINDOW_STATE_FULLSCREEN)) { + while (gtk_events_pending ()) + gtk_main_iteration (); + fullscreen_button_enable (self); + } +#endif + return self; } @@ -505,6 +545,8 @@ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + g_type_class_add_private (klass, sizeof (HeFullscreenButtonPrivate)); } @@ -513,14 +555,20 @@ { g_return_if_fail (self != NULL); + HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self); + g_return_if_fail (priv != NULL); + + memset (priv, 0, sizeof (HeFullscreenButtonPrivate)); + self->parent_window = NULL; self->overlay = NULL; - self->release_event = TRUE; - self->last_event_time = 0; + priv->release_event = TRUE; + priv->last_event_time = 0; - self->button_press_signal_id = 0; - self->button_release_signal_id = 0; + priv->button_press_signal_id = 0; + priv->button_release_signal_id = 0; - self->button_press_hook_id = 0; - self->button_release_hook_id = 0; + priv->button_press_hook_id = 0; + priv->button_release_hook_id = 0; } + Index: he-fullscreen-button.h =================================================================== --- he-fullscreen-button.h (revision 11) +++ he-fullscreen-button.h (working copy) @@ -18,6 +18,8 @@ #include +G_BEGIN_DECLS + #define HE_TYPE_FULLSCREEN_BUTTON \ (he_fullscreen_button_get_type()) @@ -52,24 +54,12 @@ GtkWindow *parent_window; GtkWidget *overlay; - - gboolean release_event; - guint32 last_event_time; - - guint button_press_signal_id; - guint button_release_signal_id; - - gulong button_press_hook_id; - gulong button_release_hook_id; }; struct _HeFullscreenButtonClass { GObjectClass parent_class; - guint signal_id_fullscreen_mode_enabled; - guint signal_id_fullscreen_mode_disabled; - void (*clicked) (HeFullscreenButton *manager); }; @@ -83,5 +73,6 @@ GtkWindow * he_fullscreen_button_get_window (HeFullscreenButton *manager); +G_END_DECLS #endif /* _HE_FULLSCREEN_BUTTON_ */