summaryrefslogtreecommitdiff
path: root/endless/eoswindow.c
diff options
context:
space:
mode:
Diffstat (limited to 'endless/eoswindow.c')
-rw-r--r--endless/eoswindow.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/endless/eoswindow.c b/endless/eoswindow.c
index f74911d..939d6e1 100644
--- a/endless/eoswindow.c
+++ b/endless/eoswindow.c
@@ -4,6 +4,7 @@
#include "eoswindow.h"
#include "eosapplication.h"
+#include "eostopbar-private.h"
#include <gtk/gtk.h>
@@ -38,6 +39,8 @@ G_DEFINE_TYPE (EosWindow, eos_window, GTK_TYPE_APPLICATION_WINDOW)
struct _EosWindowPrivate
{
EosApplication *application;
+
+ GtkWidget *top_bar;
};
enum
@@ -92,15 +95,142 @@ eos_window_set_property (GObject *object,
}
}
+/* Piggy-back on the parent class's get_preferred_height(), but add the
+height of our top bar. Do not assume any borders on the top bar. */
+static void
+eos_window_get_preferred_height (GtkWidget *widget,
+ int *minimum_height,
+ int *natural_height)
+{
+ EosWindow *self = EOS_WINDOW (widget);
+ int top_bar_minimum, top_bar_natural;
+
+ GTK_WIDGET_CLASS (eos_window_parent_class)->get_preferred_height (widget,
+ minimum_height, natural_height);
+ gtk_widget_get_preferred_height (self->priv->top_bar,
+ &top_bar_minimum, &top_bar_natural);
+ if (minimum_height != NULL)
+ *minimum_height += top_bar_minimum;
+ if (natural_height != NULL)
+ *natural_height += top_bar_natural;
+}
+
+/* Remove space for our top bar from the allocation before doing a normal
+size_allocate(). Do not assume any borders on the top bar. */
+static void
+eos_window_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ EosWindow *self = EOS_WINDOW (widget);
+ GtkWidget *child;
+ GtkAllocation child_allocation = *allocation;
+ unsigned border_width;
+
+ gtk_widget_set_allocation (widget, allocation);
+
+ if (self->priv->top_bar != NULL)
+ {
+ int top_bar_natural;
+ GtkAllocation top_bar_allocation = *allocation;
+
+ gtk_widget_get_preferred_height (self->priv->top_bar,
+ NULL, &top_bar_natural);
+ top_bar_allocation.height = MIN(top_bar_natural, allocation->height);
+ child_allocation.y += top_bar_allocation.height;
+ child_allocation.height -= top_bar_allocation.height;
+
+ gtk_widget_size_allocate (self->priv->top_bar, &top_bar_allocation);
+ }
+
+ /* We can't chain up to GtkWindow's implementation of size_allocate() here,
+ because it always assumes that its child begins at (0, 0). */
+ child = gtk_bin_get_child (GTK_BIN (self));
+ if (child != NULL)
+ {
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (self));
+ child_allocation.x += border_width;
+ child_allocation.y += border_width;
+ child_allocation.width -= 2 * border_width;
+ child_allocation.height -= 2 * border_width;
+ child_allocation.width = MAX(1, child_allocation.width);
+ child_allocation.height = MAX(1, child_allocation.height);
+ gtk_widget_size_allocate (child, &child_allocation);
+ }
+}
+
+static void
+eos_window_map (GtkWidget *widget)
+{
+ EosWindow *self = EOS_WINDOW (widget);
+
+ GTK_WIDGET_CLASS (eos_window_parent_class)->map (widget);
+ if (self->priv->top_bar != NULL
+ && gtk_widget_get_visible (self->priv->top_bar))
+ {
+ gtk_widget_map (self->priv->top_bar);
+ }
+}
+
+static void
+eos_window_unmap (GtkWidget *widget)
+{
+ EosWindow *self = EOS_WINDOW (widget);
+
+ GTK_WIDGET_CLASS (eos_window_parent_class)->unmap (widget);
+ if (self->priv->top_bar != NULL)
+ gtk_widget_unmap (self->priv->top_bar);
+}
+
+static void
+eos_window_show (GtkWidget *widget)
+{
+ EosWindow *self = EOS_WINDOW (widget);
+
+ GTK_WIDGET_CLASS (eos_window_parent_class)->show (widget);
+ if (self->priv->top_bar != NULL)
+ gtk_widget_show_all (self->priv->top_bar);
+}
+
+/* The top bar is an internal child, so include it in our list of internal
+children. */
+static void
+eos_window_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ EosWindow *self = EOS_WINDOW (container);
+
+ if (include_internals && self->priv->top_bar != NULL)
+ (*callback) (self->priv->top_bar, callback_data);
+ GTK_CONTAINER_CLASS (eos_window_parent_class)->forall (container,
+ include_internals,
+ callback,
+ callback_data);
+}
+
+
static void
eos_window_class_init (EosWindowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
g_type_class_add_private (klass, sizeof (EosWindowPrivate));
object_class->get_property = eos_window_get_property;
object_class->set_property = eos_window_set_property;
+ /* Overriding the following six functions is because we treat the top bar as
+ an "internal" child. This will not be necessary any more if we use
+ gtk_window_set_titlebar(), available from GTK >= 3.10. But for now we are
+ targeting GTK 3.8. Issue: [endlessm/eos-sdk#28] */
+ widget_class->get_preferred_height = eos_window_get_preferred_height;
+ widget_class->size_allocate = eos_window_size_allocate;
+ widget_class->map = eos_window_map;
+ widget_class->unmap = eos_window_unmap;
+ widget_class->show = eos_window_show;
+ container_class->forall = eos_window_forall;
/**
* EosWindow:application:
@@ -119,12 +249,40 @@ eos_window_class_init (EosWindowClass *klass)
}
static void
+on_minimize_clicked_cb (GtkWidget* top_bar,
+ gpointer user_data)
+{
+ if (user_data != NULL)
+ {
+ gtk_window_iconify (GTK_WINDOW (user_data));
+ }
+}
+
+static void
+on_close_clicked_cb (GtkWidget* top_bar,
+ gpointer user_data)
+{
+ if (user_data != NULL)
+ {
+ gtk_widget_destroy (GTK_WIDGET (user_data));
+ }
+}
+
+static void
eos_window_init (EosWindow *self)
{
self->priv = WINDOW_PRIVATE (self);
+ self->priv->top_bar = eos_top_bar_new ();
+ gtk_widget_set_parent (self->priv->top_bar, GTK_WIDGET (self));
+
gtk_window_set_decorated (GTK_WINDOW (self), FALSE);
gtk_window_maximize (GTK_WINDOW (self));
+
+ g_signal_connect (self->priv->top_bar, "minimize-clicked",
+ G_CALLBACK (on_minimize_clicked_cb), self);
+ g_signal_connect (self->priv->top_bar, "close-clicked",
+ G_CALLBACK (on_close_clicked_cb), self);
}
/* Public API */