summaryrefslogtreecommitdiff
path: root/eel/eel-image-table.c
diff options
context:
space:
mode:
Diffstat (limited to 'eel/eel-image-table.c')
-rw-r--r--eel/eel-image-table.c387
1 files changed, 233 insertions, 154 deletions
diff --git a/eel/eel-image-table.c b/eel/eel-image-table.c
index 8f87660b..205fc70a 100644
--- a/eel/eel-image-table.c
+++ b/eel/eel-image-table.c
@@ -29,7 +29,6 @@
#include "eel-art-gtk-extensions.h"
#include "eel-debug-drawing.h"
#include "eel-gtk-extensions.h"
-#include "eel-gtk-macros.h"
#include "eel-labeled-image.h"
#include "eel-marshal.h"
#include <gtk/gtk.h>
@@ -46,7 +45,6 @@ struct EelImageTableDetails
{
GtkWidget *child_under_pointer;
GtkWidget *child_being_pressed;
- GdkGC *clear_gc;
};
/* Signals */
@@ -63,31 +61,17 @@ typedef enum
/* Signals */
static guint image_table_signals[LAST_SIGNAL] = { 0 };
-static void eel_image_table_class_init (EelImageTableClass *image_table_class);
-static void eel_image_table_init (EelImageTable *image);
-
-/* GObjectClass methods */
-static void eel_image_table_finalize (GObject *object);
-
-/* GtkWidgetClass methods */
-static void eel_image_table_realize (GtkWidget *widget);
-static void eel_image_table_unrealize (GtkWidget *widget);
-
-/* GtkContainerClass methods */
-static void eel_image_table_remove (GtkContainer *container,
- GtkWidget *widget);
-static GType eel_image_table_child_type (GtkContainer *container);
-
-/* Private EelImageTable methods */
-static void image_table_emit_signal (EelImageTable *image_table,
- GtkWidget *child,
- guint signal_index,
- int x,
- int y,
- int button,
- guint state,
- GdkEvent *event);
-
+/* Ancestor methods */
+GtkWidget * find_windowed_ancestor (GtkWidget *widget);
+#if GTK_CHECK_VERSION (3, 0, 0)
+static void signal_connect_while_realized (GtkWidget *object,
+#else
+static void signal_connect_while_realized (GtkObject *object,
+#endif
+ const char *name,
+ GCallback callback,
+ gpointer callback_data,
+ GtkWidget *realized_widget);
/* Ancestor callbacks */
static int ancestor_enter_notify_event (GtkWidget *widget,
GdkEventCrossing *event,
@@ -105,85 +89,16 @@ static int ancestor_button_release_event (GtkWidget *widget,
GdkEventButton *event,
gpointer event_data);
-EEL_CLASS_BOILERPLATE (EelImageTable, eel_image_table, EEL_TYPE_WRAP_TABLE)
-
-static void
-eel_image_table_class_init (EelImageTableClass *image_table_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (image_table_class);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (image_table_class);
- GtkContainerClass *container_class = GTK_CONTAINER_CLASS (image_table_class);
-
- /* GObjectClass */
- object_class->finalize = eel_image_table_finalize;
-
- /* GtkWidgetClass */
- widget_class->realize = eel_image_table_realize;
- widget_class->unrealize = eel_image_table_unrealize;
-
- /* GtkContainerClass */
- container_class->remove = eel_image_table_remove;
- container_class->child_type = eel_image_table_child_type;
-
- /* Signals */
- image_table_signals[CHILD_ENTER] = g_signal_new ("child_enter",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EelImageTableClass, child_enter),
- NULL, NULL,
- eel_marshal_VOID__OBJECT_POINTER,
- G_TYPE_NONE,
- 2,
- GTK_TYPE_WIDGET,
- G_TYPE_POINTER);
- image_table_signals[CHILD_LEAVE] = g_signal_new ("child_leave",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EelImageTableClass, child_leave),
- NULL, NULL,
- eel_marshal_VOID__OBJECT_POINTER,
- G_TYPE_NONE,
- 2,
- GTK_TYPE_WIDGET,
- G_TYPE_POINTER);
- image_table_signals[CHILD_PRESSED] = g_signal_new ("child_pressed",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EelImageTableClass, child_pressed),
- NULL, NULL,
- eel_marshal_VOID__OBJECT_POINTER,
- G_TYPE_NONE,
- 2,
- GTK_TYPE_WIDGET,
- G_TYPE_POINTER);
- image_table_signals[CHILD_RELEASED] = g_signal_new ("child_released",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EelImageTableClass, child_released),
- NULL, NULL,
- eel_marshal_VOID__OBJECT_POINTER,
- G_TYPE_NONE,
- 2,
- GTK_TYPE_WIDGET,
- G_TYPE_POINTER);
- image_table_signals[CHILD_CLICKED] = g_signal_new ("child_clicked",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EelImageTableClass, child_clicked),
- NULL, NULL,
- eel_marshal_VOID__OBJECT_POINTER,
- G_TYPE_NONE,
- 2,
- GTK_TYPE_WIDGET,
- G_TYPE_POINTER);
-}
+G_DEFINE_TYPE (EelImageTable, eel_image_table, EEL_TYPE_WRAP_TABLE)
static void
eel_image_table_init (EelImageTable *image_table)
{
gtk_widget_set_has_window (GTK_WIDGET (image_table), FALSE);
- image_table->details = g_new0 (EelImageTableDetails, 1);
+ image_table->details = G_TYPE_INSTANCE_GET_PRIVATE (image_table,
+ EEL_TYPE_IMAGE_TABLE,
+ EelImageTableDetails);
}
/* GObjectClass methods */
@@ -194,9 +109,7 @@ eel_image_table_finalize (GObject *object)
image_table = EEL_IMAGE_TABLE (object);
- g_free (image_table->details);
-
- EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
+ G_OBJECT_CLASS (eel_image_table_parent_class)->finalize (object);
}
static void
@@ -207,9 +120,9 @@ eel_image_table_realize (GtkWidget *widget)
g_assert (EEL_IS_IMAGE_TABLE (widget));
/* Chain realize */
- EEL_CALL_PARENT (GTK_WIDGET_CLASS, realize, (widget));
+ GTK_WIDGET_CLASS (eel_image_table_parent_class)->realize (widget);
- windowed_ancestor = eel_gtk_widget_find_windowed_ancestor (widget);
+ windowed_ancestor = find_windowed_ancestor (widget);
g_assert (GTK_IS_WIDGET (windowed_ancestor));
gtk_widget_add_events (windowed_ancestor,
@@ -220,54 +133,39 @@ eel_image_table_realize (GtkWidget *widget)
| GDK_LEAVE_NOTIFY_MASK
| GDK_POINTER_MOTION_MASK);
- eel_gtk_signal_connect_while_realized (GTK_OBJECT (windowed_ancestor),
- "enter_notify_event",
- G_CALLBACK (ancestor_enter_notify_event),
- widget,
- widget);
-
- eel_gtk_signal_connect_while_realized (GTK_OBJECT (windowed_ancestor),
- "leave_notify_event",
- G_CALLBACK (ancestor_leave_notify_event),
- widget,
- widget);
-
- eel_gtk_signal_connect_while_realized (GTK_OBJECT (windowed_ancestor),
- "motion_notify_event",
- G_CALLBACK (ancestor_motion_notify_event),
- widget,
- widget);
-
- eel_gtk_signal_connect_while_realized (GTK_OBJECT (windowed_ancestor),
- "button_press_event",
- G_CALLBACK (ancestor_button_press_event),
- widget,
- widget);
-
- eel_gtk_signal_connect_while_realized (GTK_OBJECT (windowed_ancestor),
- "button_release_event",
- G_CALLBACK (ancestor_button_release_event),
- widget,
- widget);
-}
-
-static void
-eel_image_table_unrealize (GtkWidget *widget)
-{
- EelImageTable *image_table;
-
- g_assert (EEL_IS_IMAGE_TABLE (widget));
-
- image_table = EEL_IMAGE_TABLE (widget);
-
- if (image_table->details->clear_gc != NULL)
- {
- g_object_unref (image_table->details->clear_gc);
- image_table->details->clear_gc = NULL;
- }
-
- /* Chain unrealize */
- EEL_CALL_PARENT (GTK_WIDGET_CLASS, unrealize, (widget));
+#if !GTK_CHECK_VERSION (3, 0, 0)
+#define windowed_ancestor GTK_OBJECT(windowed_ancestor)
+#endif
+
+ signal_connect_while_realized (windowed_ancestor,
+ "enter_notify_event",
+ G_CALLBACK (ancestor_enter_notify_event),
+ widget,
+ widget);
+
+ signal_connect_while_realized (windowed_ancestor,
+ "leave_notify_event",
+ G_CALLBACK (ancestor_leave_notify_event),
+ widget,
+ widget);
+
+ signal_connect_while_realized (windowed_ancestor,
+ "motion_notify_event",
+ G_CALLBACK (ancestor_motion_notify_event),
+ widget,
+ widget);
+
+ signal_connect_while_realized (windowed_ancestor,
+ "button_press_event",
+ G_CALLBACK (ancestor_button_press_event),
+ widget,
+ widget);
+
+ signal_connect_while_realized (windowed_ancestor,
+ "button_release_event",
+ G_CALLBACK (ancestor_button_release_event),
+ widget,
+ widget);
}
/* GtkContainerClass methods */
@@ -292,7 +190,7 @@ eel_image_table_remove (GtkContainer *container,
image_table->details->child_being_pressed = NULL;
}
- EEL_CALL_PARENT (GTK_CONTAINER_CLASS, remove, (container, child));
+ GTK_CONTAINER_CLASS (eel_image_table_parent_class)->remove (container, child);
}
static GType
@@ -333,6 +231,78 @@ image_table_emit_signal (EelImageTable *image_table,
}
static void
+eel_image_table_class_init (EelImageTableClass *image_table_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (image_table_class);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (image_table_class);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (image_table_class);
+
+ /* GObjectClass */
+ object_class->finalize = eel_image_table_finalize;
+
+ /* GtkWidgetClass */
+ widget_class->realize = eel_image_table_realize;
+
+ /* GtkContainerClass */
+ container_class->remove = eel_image_table_remove;
+ container_class->child_type = eel_image_table_child_type;
+
+ /* Signals */
+ image_table_signals[CHILD_ENTER] = g_signal_new ("child_enter",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EelImageTableClass, child_enter),
+ NULL, NULL,
+ eel_marshal_VOID__OBJECT_POINTER,
+ G_TYPE_NONE,
+ 2,
+ GTK_TYPE_WIDGET,
+ G_TYPE_POINTER);
+ image_table_signals[CHILD_LEAVE] = g_signal_new ("child_leave",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EelImageTableClass, child_leave),
+ NULL, NULL,
+ eel_marshal_VOID__OBJECT_POINTER,
+ G_TYPE_NONE,
+ 2,
+ GTK_TYPE_WIDGET,
+ G_TYPE_POINTER);
+ image_table_signals[CHILD_PRESSED] = g_signal_new ("child_pressed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EelImageTableClass, child_pressed),
+ NULL, NULL,
+ eel_marshal_VOID__OBJECT_POINTER,
+ G_TYPE_NONE,
+ 2,
+ GTK_TYPE_WIDGET,
+ G_TYPE_POINTER);
+ image_table_signals[CHILD_RELEASED] = g_signal_new ("child_released",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EelImageTableClass, child_released),
+ NULL, NULL,
+ eel_marshal_VOID__OBJECT_POINTER,
+ G_TYPE_NONE,
+ 2,
+ GTK_TYPE_WIDGET,
+ G_TYPE_POINTER);
+ image_table_signals[CHILD_CLICKED] = g_signal_new ("child_clicked",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EelImageTableClass, child_clicked),
+ NULL, NULL,
+ eel_marshal_VOID__OBJECT_POINTER,
+ G_TYPE_NONE,
+ 2,
+ GTK_TYPE_WIDGET,
+ G_TYPE_POINTER);
+
+ g_type_class_add_private (image_table_class, sizeof (EelImageTableDetails));
+}
+
+static void
image_table_handle_motion (EelImageTable *image_table,
int x,
int y,
@@ -401,6 +371,115 @@ image_table_handle_motion (EelImageTable *image_table,
}
}
+GtkWidget *
+find_windowed_ancestor (GtkWidget *widget)
+{
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+ while (widget && !gtk_widget_get_has_window (widget))
+ {
+ widget = gtk_widget_get_parent (widget);
+ }
+
+ return widget;
+}
+
+typedef struct
+{
+ GObject *object;
+ guint object_destroy_handler;
+
+ GtkWidget *realized_widget;
+ guint realized_widget_destroy_handler;
+ guint realized_widget_unrealized_handler;
+
+ guint signal_handler;
+} RealizeDisconnectInfo;
+
+static void
+while_realized_disconnecter (GObject *object,
+ RealizeDisconnectInfo *info)
+{
+ g_assert (G_IS_OBJECT (object));
+ g_assert (info != NULL);
+ g_assert (G_IS_OBJECT (info->object));
+ g_assert (info->object_destroy_handler != 0);
+ g_assert (info->object_destroy_handler != 0);
+ g_assert (info->realized_widget_destroy_handler != 0);
+ g_assert (info->realized_widget_unrealized_handler != 0);
+
+ g_signal_handler_disconnect (info->object, info->object_destroy_handler);
+ g_signal_handler_disconnect (info->object, info->signal_handler);
+ g_signal_handler_disconnect (info->realized_widget, info->realized_widget_destroy_handler);
+ g_signal_handler_disconnect (info->realized_widget, info->realized_widget_unrealized_handler);
+ g_free (info);
+}
+
+/**
+ * signal_connect_while_realized:
+ *
+ * @object: Object to connect to.
+ * @name: Name of signal to connect to.
+ * @callback: Caller's callback.
+ * @callback_data: Caller's callback_data.
+ * @realized_widget: Widget to monitor for realized state. Signal is connected
+ * while this wigget is realized.
+ *
+ * Connect to a signal of an object while another widget is realized. This is
+ * useful for non windowed widgets that need to monitor events in their ancestored
+ * windowed widget. The signal is automatically disconnected when &widget is
+ * unrealized. Also, the signal is automatically disconnected when either &object
+ * or &widget are destroyed.
+ **/
+static void
+#if GTK_CHECK_VERSION (3, 0, 0)
+signal_connect_while_realized (GtkWidget *object,
+#else
+signal_connect_while_realized (GtkObject *object,
+#endif
+ const char *name,
+ GCallback callback,
+ gpointer callback_data,
+ GtkWidget *realized_widget)
+{
+ RealizeDisconnectInfo *info;
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+ g_return_if_fail (GTK_IS_WIDGET (object));
+#else
+ g_return_if_fail (GTK_IS_OBJECT (object));
+#endif
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (name[0] != '\0');
+ g_return_if_fail (callback != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (realized_widget));
+ g_return_if_fail (gtk_widget_get_realized (realized_widget));
+
+ info = g_new0 (RealizeDisconnectInfo, 1);
+
+ info->object = object;
+ info->object_destroy_handler =
+ g_signal_connect (G_OBJECT (info->object),
+ "destroy",
+ G_CALLBACK (while_realized_disconnecter),
+ info);
+
+ info->realized_widget = realized_widget;
+ info->realized_widget_destroy_handler =
+ g_signal_connect (G_OBJECT (info->realized_widget),
+ "destroy",
+ G_CALLBACK (while_realized_disconnecter),
+ info);
+ info->realized_widget_unrealized_handler =
+ g_signal_connect_after (G_OBJECT (info->realized_widget),
+ "unrealize",
+ G_CALLBACK (while_realized_disconnecter),
+ info);
+
+ info->signal_handler = g_signal_connect (G_OBJECT (info->object),
+ name, callback, callback_data);
+}
+
static int
ancestor_enter_notify_event (GtkWidget *widget,
GdkEventCrossing *event,