#include <gtk/gtkentry.h>
#include <gtk/gtktextview.h>
#include <gtk/gtkscrolledwindow.h>
+#include <gtk/gtkmain.h>
#include <gdk/gdkkeysyms.h>
#include <gdk/gdk.h>
hildon_window_key_press_event (GtkWidget *widget,
GdkEventKey *event);
static gboolean
+hildon_window_key_release_event (GtkWidget *widget,
+ GdkEventKey *event);
+static gboolean
hildon_window_window_state_event (GtkWidget *widget,
GdkEventWindowState *event,
gpointer null);
GParamSpec *property_spec,
gpointer null);
-static void
+static gboolean
+hildon_window_vbox_expose_event (GtkWidget *vbox,
+ GdkEventExpose *event,
+ gpointer window);
+
+static gboolean
hildon_window_toggle_menu (HildonWindow * self);
-static void get_client_area(GtkWidget * widget,
- GtkAllocation * allocation);
-static GdkFilterReturn hildon_window_event_filter( GdkXEvent *xevent, GdkEvent *event, gpointer data );
-static GdkFilterReturn hildon_window_root_window_event_filter( GdkXEvent *xevent, GdkEvent *event, gpointer data );
+static gboolean
+hildon_window_escape_timeout (gpointer data);
+
+static GdkFilterReturn
+hildon_window_event_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data );
+
+static GdkFilterReturn
+hildon_window_root_window_event_filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data );
static void
hildon_window_get_borders (HildonWindow *window);
GtkAllocation allocation;
- guint fullscreen : 1;
- guint is_topmost: 1;
- /* For future expansion. We might use the below variables
- * for disabling keyrepeat
- * if we need it someday. */
+ guint fullscreen;
+ guint is_topmost;
+ guint escape_timeout;
gint visible_toolbars;
+ gint previous_vbox_y;
HildonProgram *program;
};
widget_class->realize = hildon_window_realize;
widget_class->unrealize = hildon_window_unrealize;
widget_class->key_press_event = hildon_window_key_press_event;
+ widget_class->key_release_event = hildon_window_key_release_event;
/* now the object stuff */
object_class->finalize = hildon_window_finalize;
priv->is_topmost = FALSE;
priv->borders = NULL;
priv->toolbar_borders = NULL;
+ priv->escape_timeout = 0;
priv->fullscreen = FALSE;
gtk_widget_set_events (GTK_WIDGET(self), GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
+ /* Handle the drawing of the vbox (add the pixmap borders) */
+ g_signal_connect (G_OBJECT (self->priv->vbox), "expose-event",
+ G_CALLBACK (hildon_window_vbox_expose_event),
+ self);
+
/* Used to keep track of fullscreen / unfullscreen */
g_signal_connect (G_OBJECT (self), "window_state_event",
G_CALLBACK (hildon_window_window_state_event), self);
HildonWindow *self;
g_return_if_fail (HILDON_WINDOW (obj_self));
self = HILDON_WINDOW (obj_self);
-
- if (self->priv->program)
- {
- hildon_program_remove_window (self->priv->program, self);
- }
- gdk_window_remove_filter (gdk_get_default_root_window(),
- hildon_window_root_window_event_filter,
- obj_self);
if (G_OBJECT_CLASS (parent_class)->finalize)
G_OBJECT_CLASS (parent_class)->finalize (obj_self);
+
}
static void
XFree(old_atoms);
g_free(new_atoms);
-
- gdk_window_set_events (widget->window,
- gdk_window_get_events (widget->window) | GDK_SUBSTRUCTURE_MASK);
-
/* rely on GDK to set the window group to its default */
gdk_window_set_group (widget->window, NULL);
active_window = hildon_window_get_active_window();
hildon_window_update_topmost (HILDON_WINDOW (widget), active_window);
+ /* Update the window title */
+ hildon_window_update_title(HILDON_WINDOW (widget));
+
}
static void
}
static void
-shown_children(gpointer data, gpointer user_data)
+visible_toolbars (gpointer data, gpointer user_data)
{
if (GTK_WIDGET_VISIBLE (GTK_WIDGET (((GtkBoxChild *)data)->widget)))
- *((gboolean *)user_data) = TRUE;
+ (*((gint *)user_data)) ++;
}
static gboolean
GtkBorder *b = HILDON_WINDOW(widget)->priv->borders;
GtkBorder *tb = HILDON_WINDOW(widget)->priv->toolbar_borders;
gint tb_height = 0;
- gint height_decrement = 0;
- gboolean draw_toolbar = FALSE;
+ gint currently_visible_toolbars = 0;
if (!priv->borders)
{
tb_height = bx->allocation.height + tb->top + tb->bottom;
- g_list_foreach (box->children, shown_children, &draw_toolbar);
+ g_list_foreach (box->children, visible_toolbars,
+ ¤tly_visible_toolbars);
- if (HILDON_WINDOW (widget)->priv->fullscreen)
+ if (priv->previous_vbox_y != priv->vbox->allocation.y)
{
- if(draw_toolbar)
- {
- paint_toolbar (widget, box, event, TRUE);
- }
+ gint draw_from_y = priv->previous_vbox_y < priv->vbox->allocation.y?
+ priv->previous_vbox_y - tb->top:
+ priv->vbox->allocation.y - tb->top;
+
+ gtk_widget_queue_draw_area (widget, 0, draw_from_y,
+ widget->allocation.width,
+ widget->allocation.height - draw_from_y);
+
+ priv->previous_vbox_y = priv->vbox->allocation.y;
}
- else
+
+ if (!HILDON_WINDOW (widget)->priv->fullscreen)
{
- if (draw_toolbar)
+
+ /* Draw the left and right window border */
+ gint side_borders_height = widget->allocation.height - b->top;
+
+ if (currently_visible_toolbars)
+ side_borders_height -= tb_height;
+ else
+ side_borders_height -= b->bottom;
+
+ if (b->left > 0)
{
- paint_toolbar (widget, box, event, FALSE);
- height_decrement = tb_height;
+ gtk_paint_box (widget->style, widget->window,
+ GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT,
+ &event->area, widget, "left-border",
+ widget->allocation.x, widget->allocation.y +
+ b->top, b->left, side_borders_height);
}
- else if (b->bottom > 0)
+
+ if (b->right > 0)
+ {
+ gtk_paint_box (widget->style, widget->window,
+ GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT,
+ &event->area, widget, "right-border",
+ widget->allocation.x + widget->allocation.width -
+ b->right, widget->allocation.y + b->top,
+ b->right, side_borders_height);
+ }
+
+ /* If no toolbar, draw the bottom window border */
+ if (!currently_visible_toolbars &&b->bottom > 0)
{
- height_decrement = b->bottom;
gtk_paint_box (widget->style, widget->window,
GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT,
&event->area, widget, "bottom-border",
widget->allocation.width, b->bottom);
}
+ /* Draw the top border */
if (b->top > 0)
{
- height_decrement += b->top;
gtk_paint_box (widget->style, widget->window,
GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT,
&event->area, widget, "top-border",
widget->allocation.x, widget->allocation.y,
widget->allocation.width, b->top);
}
- if (b->left > 0)
- {
- gtk_paint_box (widget->style, widget->window,
- GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT,
- &event->area, widget, "left-border",
- widget->allocation.x, widget->allocation.y +
- b->top, b->left, widget->allocation.height -
- height_decrement);
- }
- if (b->right > 0)
- {
- gtk_paint_box (widget->style, widget->window,
- GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT,
- &event->area, widget, "right-border",
- widget->allocation.x + widget->allocation.width -
- b->right, widget->allocation.y + b->top,
- b->right, widget->allocation.height -
- height_decrement);
- }
+
+
}
/* don't draw the window stuff as it overwrites our borders with a blank
alloc.y += b->top;
alloc.height -= b->top;
- if (box_alloc.height <= 0)
- alloc.height -= b->bottom;
- else
- alloc.height -= (tb->top + tb->bottom);
}
+ if (box_alloc.height <= 0 &&
+ !(HILDON_WINDOW (widget)->priv->fullscreen))
+ alloc.height -= b->bottom;
+ else
+ alloc.height -= (tb->top + tb->bottom);
+
gtk_widget_size_allocate (bin->child, &alloc);
}
}
- menu_list = gtk_menu_get_for_attach_widget (GTK_WIDGET (obj));
+ menu_list = g_list_copy (gtk_menu_get_for_attach_widget (GTK_WIDGET (obj)));
while (menu_list)
{
- if (menu_list->data)
+ if (GTK_IS_MENU(menu_list->data))
{
if (GTK_WIDGET_VISIBLE (GTK_WIDGET (menu_list->data)))
{
menu_list = menu_list->next;
}
+ g_list_free (menu_list);
+
+ if (self->priv->program)
+ {
+ hildon_program_remove_window (self->priv->program, self);
+ }
+
+ gdk_window_remove_filter (gdk_get_default_root_window(),
+ hildon_window_root_window_event_filter,
+ obj);
+
+ gtk_widget_set_events (GTK_WIDGET(obj), 0);
+
GTK_OBJECT_CLASS (parent_class)->destroy (obj);
}
gpointer null)
{
HildonWindow *window = HILDON_WINDOW (self);
-
+
if (window->priv->is_topmost)
{
hildon_window_take_common_toolbar (window);
}
+
+ else
+ {
+ /* If the window lost focus while the user started to press
+ * the ESC key, we won't get the release event. We need to
+ * stop the timeout*/
+ if (window->priv->escape_timeout)
+ {
+ g_source_remove (window->priv->escape_timeout);
+ window->priv->escape_timeout = 0;
+ }
+ }
+}
+
+
+static gboolean
+hildon_window_vbox_expose_event (GtkWidget *vbox,
+ GdkEventExpose *event,
+ gpointer window)
+{
+ HildonWindowPrivate *priv = HILDON_WINDOW (window)->priv;
+
+ hildon_window_get_borders (HILDON_WINDOW(window));
+
+ event->area.x -= priv->toolbar_borders->left;
+ event->area.y -= priv->toolbar_borders->top;
+ event->area.width += (priv->toolbar_borders->left +
+ priv->toolbar_borders->right);
+ event->area.height += (priv->toolbar_borders->top +
+ priv->toolbar_borders->bottom);
+
+ paint_toolbar (GTK_WIDGET (window), GTK_BOX (vbox), event, priv->fullscreen);
+
+ GTK_WIDGET_CLASS (G_TYPE_INSTANCE_GET_CLASS (vbox, GTK_TYPE_VBOX, GtkVBox))
+ ->expose_event (vbox, event);
+
+ event->area = GTK_WIDGET(window)->allocation;
+
+
+ return TRUE;
}
/* Utilities */
switch (event->keyval)
{
case HILDON_HARDKEY_MENU:
- hildon_window_toggle_menu (HILDON_WINDOW (widget));
- return TRUE;
+ if (hildon_window_toggle_menu (HILDON_WINDOW (widget)))
+ return TRUE;
+ break;
+ case HILDON_HARDKEY_ESC:
+ if (!priv->escape_timeout)
+ {
+ priv->escape_timeout = g_timeout_add
+ (HILDON_WINDOW_LONG_PRESS_TIME,
+ hildon_window_escape_timeout, widget);
+ }
break;
}
- return FALSE;
+ return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
+
+}
+
+static gboolean
+hildon_window_key_release_event (GtkWidget *widget, GdkEventKey *event)
+{
+ HildonWindowPrivate *priv;
+
+ g_return_val_if_fail (HILDON_IS_WINDOW (widget),FALSE);
+
+ priv = HILDON_WINDOW (widget)->priv;
+
+ switch (event->keyval)
+ {
+ case HILDON_HARDKEY_ESC:
+ if (priv->escape_timeout)
+ {
+ g_source_remove (priv->escape_timeout);
+ priv->escape_timeout = 0;
+ }
+ break;
+ }
+
+ return GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
}
/* General */
/*******************/
-/* TODO: Clean those ... */
-
-/*
- * queries a window for the root window coordinates and size of its
- * client area (i.e. minus the title borders etc.
- */
-static void
-get_client_area (GtkWidget * widget, GtkAllocation * allocation)
-{
- GdkWindow *window = widget->window;
-
- if (window)
- gdk_window_get_origin (window, &allocation->x, &allocation->y);
- else
- memset (allocation, 0, sizeof(GtkAllocation));
-}
-
/*The menu popuping needs a menu popup-function*/
static void
hildon_window_menupopupfunc (GtkMenu *menu, gint *x, gint *y,
gboolean *push_in, GtkWidget *widget)
{
- GtkAllocation client_area = { 0, 0, 0, 0 };
-
- get_client_area (GTK_WIDGET (widget), &client_area);
+ gint window_x = 0;
+ gint window_y = 0;
+ GdkWindow *window = GTK_WIDGET(widget)->window;
+
+ if (window)
+ {
+ gdk_window_get_origin (window, &window_x, &window_y);
+ }
gtk_widget_style_get (GTK_WIDGET (menu), "horizontal-offset", x,
"vertical-offset", y, NULL);
- *x += client_area.x;
- *y += client_area.y;
+ *x += window_x;
+ *y += window_y;
}
gdk_window_add_filter (gdk_get_default_root_window (),
hildon_window_root_window_event_filter, self );
}
+
+ self->priv->program = NULL;
}
/*
}
gtk_box_pack_end (GTK_BOX(self->priv->vbox), common_toolbar,
- TRUE, TRUE, 7);
+ TRUE, TRUE, 0);
g_object_unref (common_toolbar);
- gtk_widget_show_all (self->priv->vbox);
+ gtk_widget_set_size_request (common_toolbar, -1, TOOLBAR_HEIGHT);
+
+ gtk_widget_show (self->priv->vbox);
}
}
const gchar * application_name;
g_return_if_fail (window && HILDON_IS_WINDOW (window));
+ if (!GTK_WIDGET_REALIZED (window))
+ {
+ return;
+ }
+
application_name = g_get_application_name ();
if (application_name && application_name[0])
}
/*
* Toggles the display of the HildonWindow menu.
+ * Returns whether or not something was done (whether or not we had a menu
+ * to toggle)
*/
-static void
+static gboolean
hildon_window_toggle_menu (HildonWindow * self)
{
GtkMenu *menu_to_use = NULL;
if (!menu_to_use)
{
- return;
+ return FALSE;
}
{
gtk_menu_popdown (menu_to_use);
gtk_menu_shell_deactivate (GTK_MENU_SHELL (menu_to_use));
- return;
+ return TRUE;
}
if (gtk_container_get_children (GTK_CONTAINER (menu_to_use)) != NULL)
{
+ /* Apply right theming */
+ gtk_widget_set_name (GTK_WIDGET (menu_to_use),
+ "menu_force_with_corners");
+
if (self->priv->fullscreen)
{
gtk_menu_popup (menu_to_use, NULL, NULL,
(GtkMenuPositionFunc)
hildon_window_menupopupfuncfull,
- self, 0, 0);
+ self, 0,
+ gtk_get_current_event_time ());
}
else
{
gtk_menu_popup (menu_to_use, NULL, NULL,
(GtkMenuPositionFunc)
hildon_window_menupopupfunc,
- self, 0, 0);
+ self, 0,
+ gtk_get_current_event_time ());
}
gtk_menu_shell_select_first (GTK_MENU_SHELL (menu_to_use), TRUE);
}
+ return TRUE;
+}
+
+/*
+ * If the ESC key was not released when the timeout expires,
+ * close the window
+ */
+static gboolean
+hildon_window_escape_timeout (gpointer data)
+{
+ HildonWindowPrivate *priv;
+ GdkEvent *event;
+
+ GDK_THREADS_ENTER ();
+
+ priv = HILDON_WINDOW(data)->priv;
+
+ /* Send fake event, simulation a situation that user
+ pressed 'x' from the corner */
+ event = gdk_event_new(GDK_DELETE);
+ ((GdkEventAny *)event)->window = GTK_WIDGET(data)->window;
+ gtk_main_do_event(event);
+ gdk_event_free(event);
+
+ priv->escape_timeout = 0;
+
+ GDK_THREADS_LEAVE ();
+
+ return FALSE;
}
vbox = GTK_BOX (self->priv->vbox);
- gtk_box_pack_start (vbox, GTK_WIDGET(toolbar), TRUE, TRUE, 7);
+ gtk_box_pack_start (vbox, GTK_WIDGET(toolbar), TRUE, TRUE, 0);
+ gtk_box_reorder_child (vbox, GTK_WIDGET(toolbar), 0);
+ gtk_widget_set_size_request (GTK_WIDGET (toolbar), -1, TOOLBAR_HEIGHT);
gtk_widget_queue_resize (GTK_WIDGET(self));
}
g_return_if_fail (self && HILDON_IS_WINDOW (self));
gtk_container_remove (vbox, GTK_WIDGET(toolbar));
+ /* FIXME: As the toolbar border graphics go beyond the VBox, we
+ * need to trigger a manual redraw */
+ gtk_widget_queue_draw_area (GTK_WIDGET (self) , 0, 0,
+ GTK_WIDGET(self)->allocation.width,
+ GTK_WIDGET(self)->allocation.height);
}
/**
self->priv->menu = GTK_WIDGET (menu);
gtk_widget_set_name (GTK_WIDGET (self->priv->menu),
- "menu_force_with_corners");
+ "menu_force_with_corners");
gtk_widget_show_all (self->priv->menu);
gtk_menu_attach_to_widget (menu, GTK_WIDGET (self), &detach_menu_func);
return self->priv->is_topmost;
}
+