[Xfce4-commits] <xfce4-panel:devel> Improved panel window code.
Nick Schermer
nick at xfce.org
Tue Aug 11 20:32:07 CEST 2009
Updating branch refs/heads/devel
to e880cd58799da5d8210ffec4d9ac3b5eb110e7a1 (commit)
from 44ea6d39ab089aad38255a9bad67644a572d0e26 (commit)
commit e880cd58799da5d8210ffec4d9ac3b5eb110e7a1
Author: Nick Schermer <nick at xfce.org>
Date: Sun May 17 20:51:35 2009 +0200
Improved panel window code.
Not entirely finished but good enough for normal usage. The code
basically splits the window layer in two: a base window class that
is used for the normal window and the auto hide window and
a panel window class.
The screen positioning code has been improved too and should work
a lot better with multi screen setups and randr.
Also dropped the last bits of the glue code.
panel/Makefile.am | 4 +-
panel/panel-application.c | 70 +-
panel/panel-base-window.c | 628 ++++++++
panel/panel-base-window.h | 87 ++
panel/panel-glue.c | 129 --
panel/panel-glue.h | 37 -
panel/panel-plugin-external.c | 3 +-
panel/panel-preferences-dialog.c | 11 +-
panel/panel-preferences-dialog.glade | 2 +-
panel/panel-window.c | 2759 ++++++++++++++++------------------
panel/panel-window.h | 63 +-
11 files changed, 2039 insertions(+), 1754 deletions(-)
diff --git a/panel/Makefile.am b/panel/Makefile.am
index 8fb29ef..894f83b 100644
--- a/panel/Makefile.am
+++ b/panel/Makefile.am
@@ -27,14 +27,14 @@ xfce4_panel_SOURCES = \
main.c \
panel-application.c \
panel-application.h \
+ panel-base-window.c \
+ panel-base-window.h \
panel-dbus-client.c \
panel-dbus-client.h \
panel-dbus-service.c \
panel-dbus-service.h \
panel-dialogs.c \
panel-dialogs.h \
- panel-glue.c \
- panel-glue.h \
panel-item-dialog.c \
panel-item-dialog.h \
panel-itembar.c \
diff --git a/panel/panel-application.c b/panel/panel-application.c
index ddb0fe7..5263dcb 100644
--- a/panel/panel-application.c
+++ b/panel/panel-application.c
@@ -42,7 +42,6 @@
#include <panel/panel-preferences-dialog.h>
#include <panel/panel-item-dialog.h>
#include <panel/panel-dialogs.h>
-#include <panel/panel-glue.h>
#include <panel/panel-plugin-external.h>
#define AUTOSAVE_INTERVAL (10 * 60)
@@ -248,55 +247,46 @@ panel_application_xfconf_window_bindings (PanelApplication *application,
guint i;
guint panel_n = g_slist_index (application->windows, window);
GValue value = { 0, };
- const gchar *bool_properties[] = { "locked", "autohide", "span-monitors",
- "horizontal" };
- const gchar *uint_properties[] = { "size", "length", "x-offset",
- "y-offset", "enter-opacity",
- "leave-opacity", "snap-edge",
- "background-alpha" };
+ const struct
+ {
+ const gchar *name;
+ GType type;
+ } properties[] =
+ {
+ { "locked", G_TYPE_BOOLEAN },
+ { "autohide", G_TYPE_BOOLEAN },
+ { "span-monitors", G_TYPE_BOOLEAN },
+ { "horizontal", G_TYPE_BOOLEAN },
+ { "horizontal", G_TYPE_BOOLEAN },
+ { "size", G_TYPE_UINT },
+ { "length", G_TYPE_UINT },
+ { "enter-opacity", G_TYPE_UINT },
+ { "leave-opacity", G_TYPE_UINT },
+ { "background-alpha", G_TYPE_UINT },
+ { "output-name", G_TYPE_STRING },
+ { "position", G_TYPE_STRING }
+ };
/* connect the boolean properties */
- for (i = 0; i < G_N_ELEMENTS (bool_properties); i++)
+ for (i = 0; i < G_N_ELEMENTS (properties); i++)
{
/* create xfconf property name */
g_snprintf (buf, sizeof (buf), "/panels/panel-%u/%s",
- panel_n, bool_properties[i]);
+ panel_n, properties[i].name);
/* store the window settings in the channel before we create the binding,
* so we don't loose the panel settings */
if (store_settings)
{
- g_value_init (&value, G_TYPE_BOOLEAN);
- g_object_get_property (G_OBJECT (window), bool_properties[i], &value);
+ g_value_init (&value, properties[i].type);
+ g_object_get_property (G_OBJECT (window), properties[i].name, &value);
xfconf_channel_set_property (channel, buf, &value);
g_value_unset (&value);
}
/* create binding */
- xfconf_g_property_bind (channel, buf, G_TYPE_BOOLEAN,
- window, bool_properties[i]);
- }
-
- /* connect the unsigned intergets */
- for (i = 0; i < G_N_ELEMENTS (uint_properties); i++)
- {
- /* create xfconf property name */
- g_snprintf (buf, sizeof (buf), "/panels/panel-%u/%s",
- panel_n, uint_properties[i]);
-
- /* store the window settings in the channel before we create the binding,
- * so we don't loose the panel settings */
- if (store_settings)
- {
- g_value_init(&value, G_TYPE_UINT);
- g_object_get_property (G_OBJECT (window), uint_properties[i], &value);
- xfconf_channel_set_property (channel, buf, &value);
- g_value_unset (&value);
- }
-
- /* create binding */
- xfconf_g_property_bind (channel, buf, G_TYPE_UINT,
- window, uint_properties[i]);
+ xfconf_g_property_bind (channel, buf, properties[i].type,
+ window, properties[i].name);
}
}
@@ -332,7 +322,7 @@ panel_application_load (PanelApplication *application)
/* get the plugin module name */
g_snprintf (buf, sizeof (buf), "/panels/panel-%u/plugins/plugin-%u/module", i, j);
name = xfconf_channel_get_string (channel, buf, NULL);
- if (G_LIKELY (name))
+ if (IS_STRING (name))
{
/* read the plugin id */
g_snprintf (buf, sizeof (buf), "/panels/panel-%u/plugins/plugin-%u/id", i, j);
@@ -573,7 +563,7 @@ panel_application_plugin_insert (PanelApplication *application,
GTK_WIDGET (provider), position);
/* send all the needed info about the panel to the plugin */
- panel_glue_set_provider_info (XFCE_PANEL_PLUGIN_PROVIDER (provider), window);
+ panel_window_set_povider_info (window, provider);
/* show the plugin */
gtk_widget_show (provider);
@@ -807,7 +797,7 @@ panel_application_drag_data_received (GtkWidget *itembar,
panel_itembar_reorder_child (PANEL_ITEMBAR (itembar), provider, position);
/* send all the needed panel information to the plugin */
- panel_glue_set_provider_info (XFCE_PANEL_PLUGIN_PROVIDER (provider), window);
+ panel_window_set_povider_info (window, provider);
}
/* everything went fine */
@@ -1130,7 +1120,7 @@ panel_application_new_window (PanelApplication *application,
panel_return_val_if_fail (XFCONF_IS_CHANNEL (application->xfconf), NULL);
/* create panel window */
- window = g_object_new (PANEL_TYPE_WINDOW, NULL);
+ window = panel_window_new ();
/* realize */
gtk_widget_realize (window);
@@ -1227,7 +1217,7 @@ panel_application_window_select (PanelApplication *application,
/* update state for all windows */
for (li = application->windows; li != NULL; li = li->next)
- panel_window_set_active_panel (PANEL_WINDOW (li->data), !!(li->data == window));
+ g_object_set (G_OBJECT (li->data), "active", li->data == window, NULL);
}
diff --git a/panel/panel-base-window.c b/panel/panel-base-window.c
new file mode 100644
index 0000000..16c36b2
--- /dev/null
+++ b/panel/panel-base-window.c
@@ -0,0 +1,628 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2009 Nick Schermer <nick at xfce.org>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+
+#include <exo/exo.h>
+#include <libxfce4panel/libxfce4panel.h>
+#include <libxfce4panel/xfce-panel-plugin-provider.h>
+#include <common/panel-private.h>
+#include <panel/panel-base-window.h>
+#include <panel/panel-plugin-external.h>
+
+
+
+#define PANEL_BASE_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
+ PANEL_TYPE_BASE_WINDOW, \
+ PanelBaseWindowPrivate))
+
+
+
+static void panel_base_window_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void panel_base_window_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void panel_base_window_finalize (GObject *object);
+static gboolean panel_base_window_expose_event (GtkWidget *widget,
+ GdkEventExpose *event);
+static gboolean panel_base_window_enter_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gboolean panel_base_window_leave_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event);
+static void panel_base_window_composited_changed (GtkWidget *widget);
+static gboolean panel_base_window_active_timeout (gpointer user_data);
+static void panel_base_window_active_timeout_destroyed (gpointer user_data);
+static void panel_base_window_set_plugin_background_alpha (GtkWidget *widget,
+ gpointer user_data);
+
+
+
+enum
+{
+ PROP_0,
+ PROP_ENTER_OPACITY,
+ PROP_LEAVE_OPACITY,
+ PROP_BACKGROUND_ALPHA,
+ PROP_BORDERS,
+ PROP_ACTIVE,
+ PROP_COMPOSITED,
+};
+
+struct _PanelBaseWindowPrivate
+{
+ /* borders */
+ PanelBorders borders;
+
+ /* settings */
+ gdouble enter_opacity;
+ gdouble leave_opacity;
+
+ /* active window timeout id */
+ guint active_timeout_id;
+};
+
+
+
+G_DEFINE_TYPE (PanelBaseWindow, panel_base_window, GTK_TYPE_WINDOW)
+
+
+
+static void
+panel_base_window_class_init (PanelBaseWindowClass *klass)
+{
+ GObjectClass *gobject_class;
+ GtkWidgetClass *gtkwidget_class;
+
+ /* add private data */
+ g_type_class_add_private (klass, sizeof (PanelBaseWindowPrivate));
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->get_property = panel_base_window_get_property;
+ gobject_class->set_property = panel_base_window_set_property;
+ gobject_class->finalize = panel_base_window_finalize;
+
+ gtkwidget_class = GTK_WIDGET_CLASS (klass);
+ gtkwidget_class->expose_event = panel_base_window_expose_event;
+ gtkwidget_class->enter_notify_event = panel_base_window_enter_notify_event;
+ gtkwidget_class->leave_notify_event = panel_base_window_leave_notify_event;
+ gtkwidget_class->composited_changed = panel_base_window_composited_changed;
+
+ g_object_class_install_property (gobject_class,
+ PROP_ENTER_OPACITY,
+ g_param_spec_uint ("enter-opacity", NULL, NULL,
+ 0, 100, 100,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_LEAVE_OPACITY,
+ g_param_spec_uint ("leave-opacity", NULL, NULL,
+ 0, 100, 100,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_BACKGROUND_ALPHA,
+ g_param_spec_uint ("background-alpha", NULL, NULL,
+ 0, 100, 100,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_BORDERS,
+ g_param_spec_uint ("borders", NULL, NULL,
+ 0, G_MAXUINT,
+ PANEL_BORDER_NONE,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_ACTIVE,
+ g_param_spec_boolean ("active", NULL, NULL,
+ FALSE,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_COMPOSITED,
+ g_param_spec_boolean ("composited", NULL, NULL,
+ FALSE,
+ EXO_PARAM_READABLE));
+}
+
+
+
+static void
+panel_base_window_init (PanelBaseWindow *window)
+{
+ /* set window properties */
+ gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
+ gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
+ gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DOCK);
+ gtk_window_set_gravity (GTK_WINDOW (window), GDK_GRAVITY_STATIC);
+
+ /* set private pointer */
+ window->priv = PANEL_BASE_WINDOW_GET_PRIVATE (window);
+
+ /* init */
+ window->is_composited = FALSE;
+ window->background_alpha = 1.00;
+
+ window->priv->enter_opacity = 1.00;
+ window->priv->leave_opacity = 1.00;
+ window->priv->borders = PANEL_BORDER_MASK;
+ window->priv->active_timeout_id = 0;
+
+ /* set compositing */
+ panel_base_window_composited_changed (GTK_WIDGET (window));
+}
+
+
+
+static void
+panel_base_window_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PanelBaseWindow *window = PANEL_BASE_WINDOW (object);
+ PanelBaseWindowPrivate *priv = window->priv;
+
+ switch (prop_id)
+ {
+ case PROP_ENTER_OPACITY:
+ g_value_set_uint (value, rint (priv->enter_opacity * 100.00));
+ break;
+
+ case PROP_LEAVE_OPACITY:
+ g_value_set_uint (value, rint (priv->leave_opacity * 100.00));
+ break;
+
+ case PROP_BACKGROUND_ALPHA:
+ g_value_set_uint (value, rint (window->background_alpha * 100.00));
+ break;
+
+ case PROP_BORDERS:
+ g_value_set_uint (value, priv->borders);
+ break;
+
+ case PROP_ACTIVE:
+ g_value_set_boolean (value, !!(priv->active_timeout_id != 0));
+ break;
+
+ case PROP_COMPOSITED:
+ g_value_set_boolean (value, window->is_composited);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+panel_base_window_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PanelBaseWindow *window = PANEL_BASE_WINDOW (object);
+ PanelBaseWindowPrivate *priv = window->priv;
+ GtkWidget *itembar;
+
+ switch (prop_id)
+ {
+ case PROP_ENTER_OPACITY:
+ /* set the new enter opacity */
+ priv->enter_opacity = g_value_get_uint (value) / 100.00;
+ break;
+
+ case PROP_LEAVE_OPACITY:
+ /* set the new leave opacity */
+ priv->leave_opacity = g_value_get_uint (value) / 100.00;
+ if (window->is_composited)
+ gtk_window_set_opacity (GTK_WINDOW (object), priv->leave_opacity);
+ break;
+
+ case PROP_BACKGROUND_ALPHA:
+ /* set the new background alpha */
+ window->background_alpha = g_value_get_uint (value) / 100.00;
+ if (window->is_composited)
+ gtk_widget_queue_draw (GTK_WIDGET (object));
+
+ /* send the new background alpha to the external plugins */
+ itembar = gtk_bin_get_child (GTK_BIN (window));
+ if (G_LIKELY (itembar != NULL))
+ gtk_container_foreach (GTK_CONTAINER (itembar),
+ panel_base_window_set_plugin_background_alpha, window);
+ break;
+
+ case PROP_BORDERS:
+ /* set new window borders and redraw the widget */
+ panel_base_window_set_borders (PANEL_BASE_WINDOW (object),
+ g_value_get_uint (value));
+ break;
+
+ case PROP_ACTIVE:
+ if (g_value_get_boolean (value))
+ {
+ /* start new timeout if not already running */
+ if (priv->active_timeout_id == 0)
+ priv->active_timeout_id = g_timeout_add_seconds_full (
+ G_PRIORITY_DEFAULT_IDLE, 1,
+ panel_base_window_active_timeout, object,
+ panel_base_window_active_timeout_destroyed);
+ }
+ else if (priv->active_timeout_id != 0)
+ {
+ /* stop timeout */
+ g_source_remove (priv->active_timeout_id);
+ }
+
+ /* queue a draw */
+ gtk_widget_queue_resize (GTK_WIDGET (object));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+panel_base_window_finalize (GObject *object)
+{
+ PanelBaseWindowPrivate *priv = PANEL_BASE_WINDOW (object)->priv;
+
+ /* stop running active timeout */
+ if (priv->active_timeout_id != 0)
+ g_source_remove (priv->active_timeout_id);
+
+ (*G_OBJECT_CLASS (panel_base_window_parent_class)->finalize) (object);
+}
+
+
+
+static gboolean
+panel_base_window_expose_event (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ cairo_t *cr;
+ GdkColor *color;
+ PanelBaseWindow *window = PANEL_BASE_WINDOW (widget);
+ PanelBaseWindowPrivate *priv = window->priv;
+ gdouble alpha;
+ gdouble width = widget->allocation.width;
+ gdouble height = widget->allocation.height;
+ const gdouble dashes[] = { 4.00, 4.00 };
+ GTimeVal timeval;
+ gboolean result;
+
+ /* let gtk do it's thing */
+ result = (*GTK_WIDGET_CLASS (panel_base_window_parent_class)->expose_event) (widget, event);
+
+ if (!GTK_WIDGET_DRAWABLE (widget))
+ return result;
+
+ /* create cairo context and set some default properties */
+ cr = gdk_cairo_create (widget->window);
+ panel_return_val_if_fail (cr != NULL, result);
+ cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_set_line_width (cr, 1.00);
+
+ /* clip the drawing area */
+ gdk_cairo_rectangle (cr, &event->area);
+
+ /* get background alpha */
+ alpha = window->is_composited ? window->background_alpha : 1.00;
+
+ /* only do something with the background when compositing is enabled */
+ if (G_UNLIKELY (alpha < 1.00))
+ {
+ /* clip the drawing area, but preserve the rectangle */
+ cairo_clip_preserve (cr);
+
+ /* make the background transparent */
+ color = &(widget->style->bg[GTK_STATE_NORMAL]);
+ panel_util_set_source_rgba (cr, color, alpha);
+ cairo_fill (cr);
+ }
+ else
+ {
+ /* clip the drawing area */
+ cairo_clip (cr);
+ }
+
+ if (G_UNLIKELY (priv->active_timeout_id != 0))
+ {
+ /* set black color, no alpha */
+ color = &(widget->style->dark[GTK_STATE_SELECTED]);
+ panel_util_set_source_rgba (cr, color, 1.00);
+
+ /* set dash based on time (odd/even) */
+ g_get_current_time (&timeval);
+ cairo_set_dash (cr, dashes, G_N_ELEMENTS (dashes),
+ (timeval.tv_sec % 4) * 2);
+
+ /* draw rectangle */
+ cairo_rectangle (cr, 0, 0, width - 1.00, height - 1.00);
+ cairo_stroke (cr);
+ }
+ else
+ {
+ /* safe some time if the bottom and right borders are not drawn */
+ if (PANEL_HAS_FLAG (priv->borders, PANEL_BORDER_BOTTOM | PANEL_BORDER_RIGHT))
+ {
+ /* set dark color */
+ color = &(widget->style->dark[GTK_STATE_NORMAL]);
+ panel_util_set_source_rgba (cr, color, alpha);
+
+ /* bottom line */
+ if (PANEL_HAS_FLAG (priv->borders, PANEL_BORDER_BOTTOM))
+ {
+ cairo_move_to (cr, 0.00, height - 1.00);
+ cairo_rel_line_to (cr, width, 0.00);
+ }
+
+ /* right line */
+ if (PANEL_HAS_FLAG (priv->borders, PANEL_BORDER_RIGHT))
+ {
+ cairo_move_to (cr, width - 1.00, 0.00);
+ cairo_rel_line_to (cr, 0.00, height);
+ }
+
+ /* stroke the dark lines */
+ cairo_stroke (cr);
+ }
+
+ /* safe some time if the top and left borders are not drawn */
+ if (PANEL_HAS_FLAG (priv->borders, PANEL_BORDER_TOP | PANEL_BORDER_LEFT))
+ {
+ /* set light color */
+ color = &(widget->style->light[GTK_STATE_NORMAL]);
+ panel_util_set_source_rgba (cr, color, alpha);
+
+ /* left line */
+ if (PANEL_HAS_FLAG (priv->borders, PANEL_BORDER_LEFT))
+ {
+ cairo_move_to (cr, 0.00, 0.00);
+ cairo_rel_line_to (cr, 0.00, height);
+ }
+
+ /* top line */
+ if (PANEL_HAS_FLAG (priv->borders, PANEL_BORDER_TOP))
+ {
+ cairo_move_to (cr, 0.00, 0.00);
+ cairo_rel_line_to (cr, width, 0.00);
+ }
+
+ /* stroke the light lines */
+ cairo_stroke (cr);
+ }
+ }
+
+ /* destroy cairo context */
+ cairo_destroy (cr);
+
+ return result;
+}
+
+
+
+static gboolean
+panel_base_window_enter_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ PanelBaseWindow *window = PANEL_BASE_WINDOW (widget);
+
+ /* set the opacity (when they differ) */
+ if (event->detail != GDK_NOTIFY_INFERIOR
+ && window->is_composited
+ && window->priv->leave_opacity != window->priv->enter_opacity)
+ gtk_window_set_opacity (GTK_WINDOW (widget), window->priv->enter_opacity);
+
+ return FALSE;
+}
+
+
+
+static gboolean
+panel_base_window_leave_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ PanelBaseWindow *window = PANEL_BASE_WINDOW (widget);
+
+ /* set the opacity (when they differ) */
+ if (event->detail != GDK_NOTIFY_INFERIOR
+ && window->is_composited
+ && window->priv->leave_opacity != window->priv->enter_opacity)
+ gtk_window_set_opacity (GTK_WINDOW (widget), window->priv->leave_opacity);
+
+ return FALSE;
+}
+
+
+
+static void
+panel_base_window_composited_changed (GtkWidget *widget)
+{
+ PanelBaseWindow *window = PANEL_BASE_WINDOW (widget);
+ GdkColormap *colormap = NULL;
+ gboolean was_composited = window->is_composited;
+ gboolean was_visible;
+ GdkScreen *screen;
+
+ panel_return_if_fail (PANEL_IS_BASE_WINDOW (widget));
+
+ /* check if the window is visible, if so, hide and unrealize it */
+ was_visible = GTK_WIDGET_VISIBLE (widget);
+ if (was_visible)
+ {
+ gtk_widget_hide (widget);
+ gtk_widget_unrealize (widget);
+ }
+
+ /* get the widget screen */
+ screen = gtk_window_get_screen (GTK_WINDOW (widget));
+ panel_return_if_fail (GDK_IS_SCREEN (screen));
+
+ /* get the rgba colormap if compositing is supported */
+ if (gtk_widget_is_composited (widget))
+ colormap = gdk_screen_get_rgba_colormap (screen);
+
+ /* fallback to the old colormap */
+ if (colormap == NULL)
+ {
+ window->is_composited = FALSE;
+ colormap = gdk_screen_get_rgb_colormap (screen);
+ }
+ else
+ {
+ window->is_composited = TRUE;
+ gtk_window_set_opacity (GTK_WINDOW (widget), window->priv->leave_opacity);
+ }
+
+ /* set the new colormap */
+ panel_return_if_fail (GDK_IS_COLORMAP (colormap));
+ gtk_widget_set_colormap (widget, colormap);
+
+ if (was_visible)
+ {
+ /* restore the window */
+ gtk_widget_realize (widget);
+ gtk_widget_show (widget);
+ }
+
+ /* emit the property if it changed */
+ if (window->is_composited != was_composited)
+ g_object_notify (G_OBJECT (widget), "composited");
+}
+
+
+
+static gboolean
+panel_base_window_active_timeout (gpointer user_data)
+{
+ /* queue a redraw */
+ gtk_widget_queue_draw (GTK_WIDGET (user_data));
+
+ return TRUE;
+}
+
+
+
+static void
+panel_base_window_active_timeout_destroyed (gpointer user_data)
+{
+ PANEL_BASE_WINDOW (user_data)->priv->active_timeout_id = 0;
+}
+
+
+
+static void
+panel_base_window_set_plugin_background_alpha (GtkWidget *widget,
+ gpointer user_data)
+{
+ panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (widget));
+ panel_return_if_fail (PANEL_IS_BASE_WINDOW (user_data));
+
+ if (PANEL_IS_PLUGIN_EXTERNAL (widget))
+ panel_plugin_external_set_background_alpha (PANEL_PLUGIN_EXTERNAL (widget),
+ rint (PANEL_BASE_WINDOW (user_data)->background_alpha * 100.00));
+}
+
+
+
+void
+panel_base_window_move_resize (PanelBaseWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ panel_return_if_fail (PANEL_IS_BASE_WINDOW (window));
+
+ /* resize the window if needed */
+ if (width > 0 && height > 0)
+ gtk_window_resize (GTK_WINDOW (window), width, height);
+
+ /* move the window to the new position */
+ gtk_window_move (GTK_WINDOW (window), x, y);
+}
+
+
+
+void
+panel_base_window_set_borders (PanelBaseWindow *window,
+ PanelBorders borders)
+{
+ PanelBaseWindowPrivate *priv = window->priv;
+
+ panel_return_if_fail (PANEL_IS_BASE_WINDOW (window));
+
+ if (priv->borders != borders)
+ {
+ priv->borders = borders;
+ gtk_widget_queue_resize (GTK_WIDGET (window));
+ }
+}
+
+
+
+PanelBorders
+panel_base_window_get_borders (PanelBaseWindow *window)
+{
+ PanelBaseWindowPrivate *priv = window->priv;
+
+ panel_return_val_if_fail (PANEL_IS_BASE_WINDOW (window), PANEL_BORDER_NONE);
+
+ if (priv->active_timeout_id != 0)
+ return PANEL_BORDER_MASK;
+
+ return priv->borders;
+}
+
+
+
+void
+panel_util_set_source_rgba (cairo_t *cr,
+ GdkColor *color,
+ gdouble alpha)
+{
+ panel_return_if_fail (alpha >= 0.00 && alpha <= 1.00);
+
+ if (G_LIKELY (alpha == 1.00))
+ cairo_set_source_rgb (cr, color->red / 65535.00,
+ color->green / 65535.00,
+ color->blue / 65535.00);
+ else
+ cairo_set_source_rgba (cr, color->red / 65535.00,
+ color->green / 65535.00,
+ color->blue / 65535.00, alpha);
+}
diff --git a/panel/panel-base-window.h b/panel/panel-base-window.h
new file mode 100644
index 0000000..2c50eb8
--- /dev/null
+++ b/panel/panel-base-window.h
@@ -0,0 +1,87 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2009 Nick Schermer <nick at xfce.org>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __PANEL_BASE_WINDOW_H__
+#define __PANEL_BASE_WINDOW_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PanelBaseWindowClass PanelBaseWindowClass;
+typedef struct _PanelBaseWindow PanelBaseWindow;
+typedef struct _PanelBaseWindowPrivate PanelBaseWindowPrivate;
+typedef enum _PanelBorders PanelBorders;
+
+#define PANEL_TYPE_BASE_WINDOW (panel_base_window_get_type ())
+#define PANEL_BASE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_BASE_WINDOW, PanelBaseWindow))
+#define PANEL_BASE_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANEL_TYPE_BASE_WINDOW, PanelBaseWindowClass))
+#define PANEL_IS_BASE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PANEL_TYPE_BASE_WINDOW))
+#define PANEL_IS_BASE_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_BASE_WINDOW))
+#define PANEL_BASE_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANEL_TYPE_BASE_WINDOW, PanelBaseWindowClass))
+
+enum _PanelBorders
+{
+ PANEL_BORDER_NONE = 0,
+ PANEL_BORDER_LEFT = 1 << 0,
+ PANEL_BORDER_RIGHT = 1 << 1,
+ PANEL_BORDER_TOP = 1 << 2,
+ PANEL_BORDER_BOTTOM = 1 << 3,
+ PANEL_BORDER_MASK = 0x0f
+};
+
+struct _PanelBaseWindowClass
+{
+ GtkWindowClass __parent__;
+};
+
+struct _PanelBaseWindow
+{
+ GtkWindow __parent__;
+
+ /*< private >*/
+ PanelBaseWindowPrivate *priv;
+
+ /*< private >*/
+ guint is_composited : 1;
+ gdouble background_alpha;
+};
+
+GType panel_base_window_get_type (void) G_GNUC_CONST;
+
+void panel_base_window_move_resize (PanelBaseWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+
+void panel_base_window_set_borders (PanelBaseWindow *window,
+ PanelBorders borders);
+PanelBorders panel_base_window_get_borders (PanelBaseWindow *window);
+
+void panel_base_window_set_active (PanelBaseWindow *window,
+ gboolean active);
+
+void panel_util_set_source_rgba (cairo_t *cr,
+ GdkColor *color,
+ gdouble alpha);
+
+G_END_DECLS
+
+#endif /* !__PANEL_BASE_WINDOW_H__ */
diff --git a/panel/panel-glue.c b/panel/panel-glue.c
deleted file mode 100644
index 43f335e..0000000
--- a/panel/panel-glue.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2008-2009 Nick Schermer <nick at xfce.org>
- *
- * This program 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.
- *
- * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include <exo/exo.h>
-#include <libxfce4util/libxfce4util.h>
-#include <libxfce4panel/libxfce4panel.h>
-#include <libxfce4panel/xfce-panel-plugin-provider.h>
-
-#include <panel/panel-glue.h>
-#include <panel/panel-item-dialog.h>
-#include <panel/panel-preferences-dialog.h>
-#include <panel/panel-dialogs.h>
-#include <panel/panel-dbus-service.h>
-#include <panel/panel-plugin-external.h>
-#include <panel/panel-window.h>
-
-
-
-
-XfceScreenPosition
-panel_glue_get_screen_position (PanelWindow *window)
-{
- gboolean horizontal;
- PanelWindowSnapEdge snap_edge;
-
- panel_return_val_if_fail (PANEL_IS_WINDOW (window), XFCE_SCREEN_POSITION_NONE);
-
- g_object_get (G_OBJECT (window), "horizontal", &horizontal,
- "snap-edge", &snap_edge, NULL);
-
- /* return the screen position */
- switch (snap_edge)
- {
- case PANEL_SNAP_EGDE_NONE:
- return horizontal ? XFCE_SCREEN_POSITION_FLOATING_H :
- XFCE_SCREEN_POSITION_FLOATING_V;
-
- case PANEL_SNAP_EGDE_NW:
- return horizontal ? XFCE_SCREEN_POSITION_NW_H :
- XFCE_SCREEN_POSITION_NW_V;
-
- case PANEL_SNAP_EGDE_NE:
- return horizontal ? XFCE_SCREEN_POSITION_NE_H :
- XFCE_SCREEN_POSITION_NE_V;
-
- case PANEL_SNAP_EGDE_SW:
- return horizontal ? XFCE_SCREEN_POSITION_SW_H :
- XFCE_SCREEN_POSITION_SW_V;
-
- case PANEL_SNAP_EGDE_SE:
- return horizontal ? XFCE_SCREEN_POSITION_SE_H :
- XFCE_SCREEN_POSITION_SE_V;
-
- case PANEL_SNAP_EGDE_W:
- case PANEL_SNAP_EGDE_WC:
- return horizontal ? XFCE_SCREEN_POSITION_FLOATING_H :
- XFCE_SCREEN_POSITION_W;
-
- case PANEL_SNAP_EGDE_E:
- case PANEL_SNAP_EGDE_EC:
- return horizontal ? XFCE_SCREEN_POSITION_FLOATING_H :
- XFCE_SCREEN_POSITION_E;
-
- case PANEL_SNAP_EGDE_S:
- case PANEL_SNAP_EGDE_SC:
- return horizontal ? XFCE_SCREEN_POSITION_S :
- XFCE_SCREEN_POSITION_FLOATING_V;
-
- case PANEL_SNAP_EGDE_N:
- case PANEL_SNAP_EGDE_NC:
- return horizontal ? XFCE_SCREEN_POSITION_N :
- XFCE_SCREEN_POSITION_FLOATING_V;
- }
-
- return XFCE_SCREEN_POSITION_NONE;
-}
-
-
-/* TODO move to window */
-void
-panel_glue_set_provider_info (XfcePanelPluginProvider *provider,
- PanelWindow *window)
-{
- guint size;
- gboolean horizontal;
- guint background_alpha;
-
- panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
- panel_return_if_fail (PANEL_IS_WINDOW (window));
-
- /* read settings from the window */
- g_object_get (G_OBJECT (window), "size", &size,
- "horizontal", &horizontal, "background-alpha",
- &background_alpha, NULL);
-
- /* set the background alpha if the plugin is external */
- if (PANEL_IS_PLUGIN_EXTERNAL (provider))
- panel_plugin_external_set_background_alpha (PANEL_PLUGIN_EXTERNAL (provider), background_alpha);
-
- /* send plugin information */
- xfce_panel_plugin_provider_set_screen_position (provider, panel_glue_get_screen_position (window));
- xfce_panel_plugin_provider_set_size (provider, size);
- xfce_panel_plugin_provider_set_orientation (provider, horizontal ? GTK_ORIENTATION_HORIZONTAL
- : GTK_ORIENTATION_VERTICAL);
-}
diff --git a/panel/panel-glue.h b/panel/panel-glue.h
deleted file mode 100644
index a32fc10..0000000
--- a/panel/panel-glue.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2008-2009 Nick Schermer <nick at xfce.org>
- *
- * This program 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.
- *
- * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef __PANEL_GLUE_H__
-#define __PANEL_GLUE_H__
-
-#include <gtk/gtk.h>
-#include <panel/panel-window.h>
-#include <libxfce4panel/libxfce4panel.h>
-#include <libxfce4panel/xfce-panel-plugin-provider.h>
-
-G_BEGIN_DECLS
-
-XfceScreenPosition panel_glue_get_screen_position (PanelWindow *window);
-
-void panel_glue_set_provider_info (XfcePanelPluginProvider *provider,
- PanelWindow *window);
-
-G_END_DECLS
-
-#endif /* !__PANEL_GLUE_H__ */
diff --git a/panel/panel-plugin-external.c b/panel/panel-plugin-external.c
index 3502387..a0b673a 100644
--- a/panel/panel-plugin-external.c
+++ b/panel/panel-plugin-external.c
@@ -32,7 +32,6 @@
#include <panel/panel-module.h>
#include <panel/panel-plugin-external.h>
#include <panel/panel-window.h>
-#include <panel/panel-glue.h>
#include <panel/panel-dbus-service.h>
/* Number of automatic plugin restarts before the
@@ -361,7 +360,7 @@ panel_plugin_external_plug_removed (GtkSocket *socket)
window = PANEL_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (socket)));
/* send panel information to the plugin */
- panel_glue_set_provider_info (XFCE_PANEL_PLUGIN_PROVIDER (external), window);
+ panel_window_set_povider_info (window, GTK_WIDGET (external));
/* show the socket again (realize will spawn the plugin) */
gtk_widget_show (GTK_WIDGET (socket));
diff --git a/panel/panel-preferences-dialog.c b/panel/panel-preferences-dialog.c
index 7e1a7f2..b3e3ab8 100644
--- a/panel/panel-preferences-dialog.c
+++ b/panel/panel-preferences-dialog.c
@@ -28,7 +28,6 @@
#include <libxfce4panel/xfce-panel-plugin-provider.h>
#include <panel/panel-window.h>
-#include <panel/panel-glue.h>
#include <panel/panel-application.h>
#include <panel/panel-module.h>
#include <panel/panel-itembar.h>
@@ -302,12 +301,11 @@ panel_preferences_dialog_bindings_add (PanelPreferencesDialog *dialog,
static void
panel_preferences_dialog_bindings_update (PanelPreferencesDialog *dialog)
{
- panel_return_if_fail (G_IS_OBJECT (dialog->active));
-
/* remove all the active bindings */
panel_preferences_dialog_bindings_unbind (dialog);
/* leave when there is no active panel */
+ panel_return_if_fail (G_IS_OBJECT (dialog->active));
if (dialog->active == NULL)
return;
@@ -320,6 +318,7 @@ panel_preferences_dialog_bindings_update (PanelPreferencesDialog *dialog)
panel_preferences_dialog_bindings_add (dialog, "background-alpha", "value");
panel_preferences_dialog_bindings_add (dialog, "enter-opacity", "value");
panel_preferences_dialog_bindings_add (dialog, "leave-opacity", "value");
+ panel_preferences_dialog_bindings_add (dialog, "composited", "visible");
}
@@ -380,7 +379,8 @@ panel_preferences_dialog_panel_combobox_rebuild (PanelPreferencesDialog *dialog)
panel_return_if_fail (GTK_IS_COMBO_BOX (combo));
/* block signal */
- g_signal_handlers_block_by_func (combo, panel_preferences_dialog_panel_combobox_changed, dialog);
+ g_signal_handlers_block_by_func (combo,
+ panel_preferences_dialog_panel_combobox_changed, dialog);
/* empty the combo box */
gtk_list_store_clear (GTK_LIST_STORE (store));
@@ -404,7 +404,8 @@ panel_preferences_dialog_panel_combobox_rebuild (PanelPreferencesDialog *dialog)
gtk_widget_set_sensitive (GTK_WIDGET (object), !!(n_items > 1));
/* unblock signal */
- g_signal_handlers_unblock_by_func (combo, panel_preferences_dialog_panel_combobox_changed, dialog);
+ g_signal_handlers_unblock_by_func (combo,
+ panel_preferences_dialog_panel_combobox_changed, dialog);
}
diff --git a/panel/panel-preferences-dialog.glade b/panel/panel-preferences-dialog.glade
index eab25f4..c54f02f 100644
--- a/panel/panel-preferences-dialog.glade
+++ b/panel/panel-preferences-dialog.glade
@@ -311,7 +311,7 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox4">
+ <object class="GtkVBox" id="composited">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="spacing">6</property>
diff --git a/panel/panel-window.c b/panel/panel-window.c
index d0b442f..25a8867 100644
--- a/panel/panel-window.c
+++ b/panel/panel-window.c
@@ -1,6 +1,6 @@
/* $Id$ */
/*
- * Copyright (C) 2008-2009 Nick Schermer <nick at xfce.org>
+ * Copyright (C) 2009 Nick Schermer <nick at xfce.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,63 +21,103 @@
#include <config.h>
#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
#ifdef HAVE_MATH_H
#include <math.h>
#endif
#include <exo/exo.h>
-#include <libxfce4panel/libxfce4panel.h>
#include <common/panel-private.h>
+#include <libxfce4panel/libxfce4panel.h>
+#include <libxfce4panel/xfce-panel-plugin-provider.h>
+#include <panel/panel-base-window.h>
#include <panel/panel-window.h>
-#include <panel/panel-glue.h>
-#include <panel/panel-application.h>
-#include <panel/panel-plugin-external.h>
#include <panel/panel-item-dialog.h>
#include <panel/panel-preferences-dialog.h>
#include <panel/panel-dialogs.h>
#include <panel/panel-dbus-service.h>
+#include <panel/panel-plugin-external.h>
+
+
+
+#define SNAP_DISTANCE (10)
+#define SET_OLD_WM_STRUTS (FALSE)
+#define STRUTS_DEBUGGING (FALSE)
+#define POPUP_DELAY (225)
+#define POPDOWN_DELAY (350)
+#define HANDLE_SPACING (4)
+#define HANDLE_DOTS (2)
+#define HANDLE_PIXELS (2)
+#define HANDLE_PIXEL_SPACE (1)
+#define HANDLE_SIZE (HANDLE_DOTS * (HANDLE_PIXELS + \
+ HANDLE_PIXEL_SPACE) - HANDLE_PIXEL_SPACE)
+#define HANDLE_SIZE_TOTAL (2 * HANDLE_SPACING + HANDLE_SIZE)
+
+
+
+typedef enum _StrutsEgde StrutsEgde;
+typedef enum _AutohideState AutohideState;
+typedef enum _SnapPosition SnapPosition;
+
+
+
+static void panel_window_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void panel_window_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void panel_window_finalize (GObject *object);
+static gboolean panel_window_expose_event (GtkWidget *widget,
+ GdkEventExpose *event);
+static gboolean panel_window_enter_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gboolean panel_window_leave_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gboolean panel_window_motion_notify_event (GtkWidget *widget,
+ GdkEventMotion *event);
+static gboolean panel_window_button_press_event (GtkWidget *widget,
+ GdkEventButton *event);
+static gboolean panel_window_button_release_event (GtkWidget *widget,
+ GdkEventButton *event);
+static void panel_window_grab_notify (GtkWidget *widget,
+ gboolean was_grabbed);
+static void panel_window_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void panel_window_size_allocate (GtkWidget *widget,
+ GtkAllocation *alloc);
+static void panel_window_size_allocate_set_xy (PanelWindow *window,
+ gint window_width,
+ gint window_height,
+ gint *return_x,
+ gint *return_y);
+static void panel_window_screen_changed (GtkWidget *widget,
+ GdkScreen *previous_screen);
+static StrutsEgde panel_window_screen_struts_edge (PanelWindow *window);
+static void panel_window_screen_struts_set (PanelWindow *window);
+static void panel_window_screen_force_update (PanelWindow *window);
+static void panel_window_screen_update_borders (PanelWindow *window);
+static SnapPosition panel_window_snap_position (PanelWindow *window);
+static void panel_window_screen_layout_changed (GdkScreen *screen,
+ PanelWindow *window);
+static void panel_window_autohide_queue (PanelWindow *window,
+ AutohideState new_state);
+static void panel_window_set_autohide (PanelWindow *window,
+ gboolean autohide);
+static void panel_window_menu_popup (PanelWindow *window,
+ guint32 event_time);
+static void panel_window_set_plugin_orientation (GtkWidget *widget,
+ gpointer user_data);
+static void panel_window_set_plugin_size (GtkWidget *widget,
+ gpointer user_data);
+static void panel_window_set_screen_position (GtkWidget *widget,
+ gpointer user_data);
+
-#define HANDLE_SIZE (8)
-#define HANDLE_SPACING (2)
-#define HANDLE_SIZE_TOTAL ((HANDLE_SIZE + HANDLE_SPACING) * 2)
-#define SNAP_DISTANCE (10)
-#define POPUP_DELAY (225)
-#define POPDOWN_DELAY (350)
-#define HIDDEN_PANEL_SIZE (2)
-#define OFFSCREEN (-9999)
-
-
-
-static void panel_window_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
-static void panel_window_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
-static void panel_window_finalize (GObject *object);
-static void panel_window_realize (GtkWidget *widget);
-static gboolean panel_window_expose_event (GtkWidget *widget, GdkEventExpose *event);
-static gboolean panel_window_motion_notify (GtkWidget *widget, GdkEventMotion *event);
-static gboolean panel_window_button_press_event (GtkWidget *widget, GdkEventButton *event);
-static gboolean panel_window_button_release_event (GtkWidget *widget, GdkEventButton *event);
-static gboolean panel_window_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event);
-static gboolean panel_window_leave_notify_event (GtkWidget *widget, GdkEventCrossing *event);
-static void panel_window_grab_notify (GtkWidget *widget, gboolean was_grabbed);
-static void panel_window_size_request (GtkWidget *widget, GtkRequisition *requisition);
-static void panel_window_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
-static void panel_window_screen_changed (GtkWidget *widget, GdkScreen *previous_screen);
-static void panel_window_paint_handle (PanelWindow *window, gboolean start, GtkStateType state, cairo_t *rc);
-static void panel_window_paint_borders (PanelWindow *window, GtkStateType state, cairo_t *rc);
-static void panel_window_calculate_position (PanelWindow *window, gint width, gint height, gint *x, gint *y);
-static void panel_window_working_area (PanelWindow *window, gint root_x, gint root_y, GdkRectangle *dest);
-static gboolean panel_window_struts_are_possible (PanelWindow *window, gint x, gint y, gint width, gint height);
-static void panel_window_struts_update (PanelWindow *window, gint x, gint y, gint width, gint height);
-static void panel_window_set_colormap (PanelWindow *window);
-static void panel_window_get_position (PanelWindow *window, gint *root_x, gint *root_y);
-static void panel_window_set_borders (PanelWindow *window);
-static void panel_window_set_autohide (PanelWindow *window, gboolean autohide);
-static void panel_window_menu_quit (gpointer boolean);
-static void panel_window_menu_deactivate (GtkMenu *menu, PanelWindow *window);
-static void panel_window_menu_popup (PanelWindow *window);
-static void panel_window_set_plugin_background_alpha (GtkWidget *widget, gpointer user_data);
-static void panel_window_set_plugin_size (GtkWidget *widget, gpointer user_data);
-static void panel_window_set_plugin_orientation (GtkWidget *widget, gpointer user_data);
enum
{
@@ -86,35 +126,62 @@ enum
PROP_SIZE,
PROP_LENGTH,
PROP_LOCKED,
- PROP_X_OFFSET,
- PROP_Y_OFFSET,
- PROP_ENTER_OPACITY,
- PROP_LEAVE_OPACITY,
- PROP_SNAP_EDGE,
- PROP_BACKGROUND_ALPHA,
+ PROP_AUTOHIDE,
PROP_SPAN_MONITORS,
- PROP_AUTOHIDE
+ PROP_OUTPUT_NAME,
+ PROP_POSITION
+};
+
+enum _AutohideState
+{
+ AUTOHIDE_DISABLED = 0, /* autohide is disabled */
+ AUTOHIDE_VISIBLE, /* visible */
+ AUTOHIDE_POPDOWN, /* visible, but hide timeout is running */
+ AUTOHIDE_POPDOWN_SLOW, /* same as popdown, but timeout is 4x longer */
+ AUTOHIDE_HIDDEN, /* invisible */
+ AUTOHIDE_POPUP /* invisible, but show timeout is running */
+};
+
+enum _SnapPosition
+{
+ /* no snapping */
+ SNAP_POSITION_NONE, /* snapping */
+
+ /* right edge */
+ SNAP_POSITION_E, /* right */
+ SNAP_POSITION_NE, /* top right */
+ SNAP_POSITION_EC, /* right center */
+ SNAP_POSITION_SE, /* bottom right */
+
+ /* left edge */
+ SNAP_POSITION_W, /* left */
+ SNAP_POSITION_NW, /* top left */
+ SNAP_POSITION_WC, /* left center */
+ SNAP_POSITION_SW, /* bottom left */
+
+ /* top and bottom */
+ SNAP_POSITION_NC, /* top center */
+ SNAP_POSITION_SC, /* bottom center */
+ SNAP_POSITION_N, /* top */
+ SNAP_POSITION_S, /* bottom */
};
enum
{
- SNAP_NONE,
- SNAP_START,
- SNAP_CENTER,
- SNAP_END
+ EDGE_GRAVITY_NONE = 0,
+ EDGE_GRAVITY_START = (SNAP_POSITION_NE - SNAP_POSITION_E),
+ EDGE_GRAVITY_CENTER = (SNAP_POSITION_EC - SNAP_POSITION_E),
+ EDGE_GRAVITY_END = (SNAP_POSITION_SE - SNAP_POSITION_E)
};
-typedef enum
+enum _StrutsEgde
{
- DISABLED,
- BLOCKED,
- VISIBLE,
- POPUP_QUEUED,
- HIDDEN,
- POPDOWN_QUEUED,
- POPDOWN_QUEUED_SLOW
-}
-AutohideStatus;
+ STRUTS_EDGE_NONE = 0,
+ STRUTS_EDGE_LEFT,
+ STRUTS_EDGE_RIGHT,
+ STRUTS_EDGE_TOP,
+ STRUTS_EDGE_BOTTOM
+};
enum
{
@@ -135,80 +202,62 @@ enum
struct _PanelWindowClass
{
- GtkWindowClass __parent__;
+ PanelBaseWindowClass __parent__;
};
struct _PanelWindow
{
- GtkWindow __parent__;
-
- /* last allocated size, for recentering */
- GtkAllocation prev_allocation;
-
- /* snapping edge of the window */
- PanelWindowSnapEdge snap_edge;
-
- /* the borders we're going to draw */
- PanelWindowBorders borders;
+ PanelBaseWindow __parent__;
- /* whether we should apply struts for this screen position */
- gint struts_possible;
+ /* screen and working area of this panel */
+ GdkScreen *screen;
+ GdkRectangle area;
- /* the last used struts for this window */
+ /* struts information */
+ StrutsEgde struts_edge;
gulong struts[N_STRUTS];
- /* the last calculated panel working area */
- GdkRectangle working_area;
-
- /* whether we span monitors */
- guint span_monitors : 1;
-
- /* whether the panel has a rgba colormap */
- guint is_composited : 1;
-
- /* whether the panel is locked */
- guint locked : 1;
-
- /* active panel redraw timeout id */
- guint active_timeout_id;
-
- /* panel orientation */
- guint horizontal : 1;
-
- /* panel size (px) and length (%) */
+ /* window positioning */
guint size;
gdouble length;
+ guint horizontal : 1;
+ SnapPosition snap_position;
+ guint span_monitors : 1;
+ gchar *output_name;
- /* autohide */
- AutohideStatus autohide_status;
- guint autohide_timer;
- gint autohide_block;
+ /* allocated position of the panel */
+ GdkRectangle alloc;
- /* the window we use to show during autohide */
+ /* autohiding */
GtkWidget *autohide_window;
+ AutohideState autohide_state;
+ guint autohide_timeout_id;
+ gint autohide_block;
- /* background alpha */
- gdouble background_alpha;
+ /* whether the window is locked */
+ guint locked : 1;
- /* panel enter/leave opacity */
- gdouble enter_opacity;
- gdouble leave_opacity;
+ /* window base point */
+ gint base_x;
+ gint base_y;
- /* variables for dragging the panel */
- guint drag_motion : 1;
- gint drag_start_x;
- gint drag_start_y;
+ /* window drag information */
+ guint32 grab_time;
+ gint grab_x;
+ gint grab_y;
};
-static GdkAtom cardinal_atom = GDK_NONE;
-static GdkAtom net_wm_strut_atom = GDK_NONE;
-static GdkAtom net_wm_strut_partial_atom = GDK_NONE;
+static GdkAtom cardinal_atom = 0;
+#if SET_OLD_WM_STRUTS
+static GdkAtom net_wm_strut_atom = 0;
+#endif
+static GdkAtom net_wm_strut_partial_atom = 0;
-G_DEFINE_TYPE (PanelWindow, panel_window, GTK_TYPE_WINDOW);
+G_DEFINE_TYPE (PanelWindow, panel_window, PANEL_TYPE_BASE_WINDOW)
@@ -224,13 +273,12 @@ panel_window_class_init (PanelWindowClass *klass)
gobject_class->finalize = panel_window_finalize;
gtkwidget_class = GTK_WIDGET_CLASS (klass);
- gtkwidget_class->realize = panel_window_realize;
gtkwidget_class->expose_event = panel_window_expose_event;
- gtkwidget_class->motion_notify_event = panel_window_motion_notify;
- gtkwidget_class->button_press_event = panel_window_button_press_event;
- gtkwidget_class->button_release_event = panel_window_button_release_event;
gtkwidget_class->enter_notify_event = panel_window_enter_notify_event;
gtkwidget_class->leave_notify_event = panel_window_leave_notify_event;
+ gtkwidget_class->motion_notify_event = panel_window_motion_notify_event;
+ gtkwidget_class->button_press_event = panel_window_button_press_event;
+ gtkwidget_class->button_release_event = panel_window_button_release_event;
gtkwidget_class->grab_notify = panel_window_grab_notify;
gtkwidget_class->size_request = panel_window_size_request;
gtkwidget_class->size_allocate = panel_window_size_allocate;
@@ -261,36 +309,6 @@ panel_window_class_init (PanelWindowClass *klass)
EXO_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
- PROP_X_OFFSET,
- g_param_spec_uint ("x-offset", NULL, NULL,
- 0, G_MAXUINT, 0,
- EXO_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class,
- PROP_Y_OFFSET,
- g_param_spec_uint ("y-offset", NULL, NULL,
- 0, G_MAXUINT, 0,
- EXO_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class,
- PROP_ENTER_OPACITY,
- g_param_spec_uint ("enter-opacity", NULL, NULL,
- 0, 100, 100,
- EXO_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class,
- PROP_LEAVE_OPACITY,
- g_param_spec_uint ("leave-opacity", NULL, NULL,
- 0, 100, 100,
- EXO_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class,
- PROP_BACKGROUND_ALPHA,
- g_param_spec_uint ("background-alpha", NULL, NULL,
- 0, 100, 100,
- EXO_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class,
PROP_AUTOHIDE,
g_param_spec_boolean ("autohide", NULL, NULL,
FALSE,
@@ -303,17 +321,23 @@ panel_window_class_init (PanelWindowClass *klass)
EXO_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
- PROP_SNAP_EDGE,
- g_param_spec_uint ("snap-edge", NULL, NULL,
- PANEL_SNAP_EGDE_NONE,
- PANEL_SNAP_EGDE_S,
- PANEL_SNAP_EGDE_NONE,
- EXO_PARAM_READWRITE));
+ PROP_OUTPUT_NAME,
+ g_param_spec_string ("output-name", NULL, NULL,
+ NULL,
+ EXO_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_POSITION,
+ g_param_spec_string ("position", NULL, NULL,
+ NULL,
+ EXO_PARAM_READWRITE));
/* initialize the atoms */
cardinal_atom = gdk_atom_intern_static_string ("CARDINAL");
- net_wm_strut_atom = gdk_atom_intern_static_string ("_NET_WM_STRUT");
net_wm_strut_partial_atom = gdk_atom_intern_static_string ("_NET_WM_STRUT_PARTIAL");
+#if SET_OLD_WM_STRUTS
+ net_wm_strut_atom = gdk_atom_intern_static_string ("_NET_WM_STRUT");
+#endif
}
@@ -321,50 +345,41 @@ panel_window_class_init (PanelWindowClass *klass)
static void
panel_window_init (PanelWindow *window)
{
- GdkScreen *screen;
-
- /* set window properties */
+ /* no resizable, so allocation will follow size request */
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
- gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
- gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DOCK);
- gtk_window_set_gravity (GTK_WINDOW (window), GDK_GRAVITY_STATIC);
+
+ /* set additional events */
+ gtk_widget_add_events (GTK_WIDGET (window), GDK_BUTTON_PRESS_MASK);
/* init vars */
- window->is_composited = FALSE;
- window->drag_motion = FALSE;
- window->struts_possible = -1;
- window->size = 48;
- window->snap_edge = PANEL_SNAP_EGDE_NONE;
- window->borders = 0;
- window->span_monitors = FALSE;
- window->length = 0.25;
+ window->screen = NULL;
+ window->struts_edge = STRUTS_EDGE_NONE;
+
window->horizontal = TRUE;
- window->background_alpha = 1.00;
- window->enter_opacity = 1.00;
- window->leave_opacity = 1.00;
- window->autohide_timer = 0;
- window->autohide_status = DISABLED;
- window->autohide_block = 0;
- window->autohide_window = NULL;
- window->active_timeout_id = 0;
+ window->size = 30;
+ window->length = 0.10;
+ window->snap_position = SNAP_POSITION_NONE;
+ window->span_monitors = FALSE;
- /* set additional events we want to have */
- gtk_widget_add_events (GTK_WIDGET (window), GDK_BUTTON_PRESS_MASK);
+ window->locked = FALSE;
+
+ window->autohide_state = AUTOHIDE_DISABLED;
+ window->autohide_timeout_id = 0;
+ window->autohide_block = 0;
- /* connect signal to monitor the compositor changes */
- g_signal_connect (G_OBJECT (window), "composited-changed", G_CALLBACK (panel_window_set_colormap), NULL);
+ window->base_x = 100;
+ window->base_y = 100;
- /* set the colormap */
- panel_window_set_colormap (window);
+ window->grab_time = 0;
+ window->grab_x = 0;
+ window->grab_y = 0;
- /* get the window screen */
- screen = gtk_window_get_screen (GTK_WINDOW (window));
+ /* set the screen */
+ panel_window_screen_changed (GTK_WIDGET (window), NULL);
- /* connect screen update signals */
- g_signal_connect_swapped (G_OBJECT (screen), "size-changed", G_CALLBACK (panel_window_screen_changed), window);
-#if GTK_CHECK_VERSION (2,14,0)
- g_signal_connect_swapped (G_OBJECT (screen), "monitors-changed", G_CALLBACK (panel_window_screen_changed), window);
-#endif
+ /* watch changes in the compositing */
+ g_signal_connect (G_OBJECT (window), "notify::composited",
+ G_CALLBACK (panel_window_screen_force_update), NULL);
}
@@ -376,7 +391,7 @@ panel_window_get_property (GObject *object,
GParamSpec *pspec)
{
PanelWindow *window = PANEL_WINDOW (object);
- //gint pos;
+ gchar *position;
switch (prop_id)
{
@@ -396,40 +411,24 @@ panel_window_get_property (GObject *object,
g_value_set_boolean (value, window->locked);
break;
- case PROP_X_OFFSET:
- //panel_window_get_position (window, &pos, NULL);
- //g_value_set_uint (value, pos);
- g_value_set_uint (value, 0);
- break;
-
- case PROP_Y_OFFSET:
- //panel_window_get_position (window, NULL, &pos);
- //g_value_set_uint (value, pos);
- g_value_set_uint (value, 0);
- break;
-
- case PROP_ENTER_OPACITY:
- g_value_set_uint (value, rint (window->enter_opacity * 100.00));
- break;
-
- case PROP_LEAVE_OPACITY:
- g_value_set_uint (value, rint (window->leave_opacity * 100.00));
- break;
-
- case PROP_BACKGROUND_ALPHA:
- g_value_set_uint (value, rint (window->background_alpha * 100.00));
- break;
-
- case PROP_SNAP_EDGE:
- g_value_set_uint (value, window->snap_edge);
+ case PROP_AUTOHIDE:
+ g_value_set_boolean (value, !!(window->autohide_state != AUTOHIDE_DISABLED));
break;
case PROP_SPAN_MONITORS:
g_value_set_boolean (value, window->span_monitors);
break;
- case PROP_AUTOHIDE:
- g_value_set_boolean (value, !!(window->autohide_status != DISABLED));
+ case PROP_OUTPUT_NAME:
+ g_value_set_static_string (value, window->output_name);
+ break;
+
+ case PROP_POSITION:
+ position = g_strdup_printf ("p=%d;x=%d;y=%d",
+ window->snap_position,
+ window->base_x,
+ window->base_y);
+ g_value_take_string (value, position);
break;
default:
@@ -447,116 +446,107 @@ panel_window_set_property (GObject *object,
GParamSpec *pspec)
{
PanelWindow *window = PANEL_WINDOW (object);
- //gint pos;
+ gboolean val_bool;
+ guint val_uint;
+ gdouble val_double;
+ const gchar *val_string;
+ gboolean update = FALSE;
+ gint x, y, snap_position;
+ GtkWidget *itembar;
switch (prop_id)
{
case PROP_HORIZONTAL:
- /* set whether the panel */
- window->horizontal = g_value_get_boolean (value);
-
- /* update all the panel plugins */
- gtk_container_foreach (GTK_CONTAINER (gtk_bin_get_child (GTK_BIN (window))),
- panel_window_set_plugin_orientation,
- GUINT_TO_POINTER (window->horizontal ? GTK_ORIENTATION_HORIZONTAL:
- GTK_ORIENTATION_VERTICAL));
-
- /* queue a resize */
- gtk_widget_queue_resize (GTK_WIDGET (window));
+ val_bool = g_value_get_boolean (value);
+ if (window->horizontal != val_bool)
+ {
+ window->horizontal = !!val_bool;
+ panel_window_screen_layout_changed (window->screen, window);
+ }
+
+ /* send the new orientation to the panel plugins */
+ itembar = gtk_bin_get_child (GTK_BIN (window));
+ gtk_container_foreach (GTK_CONTAINER (itembar),
+ panel_window_set_plugin_orientation, window);
break;
case PROP_SIZE:
- /* update the panel size */
- window->size = g_value_get_uint (value);
-
- /* update all the panel plugins */
- gtk_container_foreach (GTK_CONTAINER (gtk_bin_get_child (GTK_BIN (window))),
- panel_window_set_plugin_size,
- GUINT_TO_POINTER (window->size));
-
- /* queue a resize */
- gtk_widget_queue_resize (GTK_WIDGET (window));
+ val_uint = g_value_get_uint (value);
+ if (window->size != val_uint)
+ {
+ window->size = val_uint;
+ gtk_widget_queue_resize (GTK_WIDGET (window));
+ }
+
+ /* send the new size to the panel plugins */
+ itembar = gtk_bin_get_child (GTK_BIN (window));
+ gtk_container_foreach (GTK_CONTAINER (itembar),
+ panel_window_set_plugin_size, window);
break;
case PROP_LENGTH:
- /* set the new length */
- window->length = g_value_get_uint (value) / 100.00;
-
- /* update the border and resize */
- panel_window_set_borders (window);
- gtk_widget_queue_resize (GTK_WIDGET (window));
- break;
-
- case PROP_LOCKED:
- /* set new lock value and resize */
- window->locked = g_value_get_boolean (value);
- gtk_widget_queue_resize (GTK_WIDGET (window));
- break;
-
- case PROP_X_OFFSET:
- /* get window position */
- //gtk_window_get_position (GTK_WINDOW (window), NULL, &pos);
- //gtk_window_move (GTK_WINDOW (window), g_value_get_uint (value), pos);
- break;
-
- case PROP_Y_OFFSET:
- /* get window position */
- //gtk_window_get_position (GTK_WINDOW (window), &pos, NULL);
- //gtk_window_move (GTK_WINDOW (window), pos, g_value_get_uint (value));
- break;
-
- case PROP_ENTER_OPACITY:
- /* set the new enter opacity */
- window->enter_opacity = g_value_get_uint (value) / 100.00;
- break;
+ val_double = g_value_get_uint (value) / 100.00;
+ if (window->length != val_double)
+ {
+ if (window->length == 1.00 || val_double == 1.00)
+ update = TRUE;
- case PROP_LEAVE_OPACITY:
- /* set the new leave opacity */
- window->leave_opacity = g_value_get_uint (value) / 100.00;
+ window->length = val_double;
- /* set the autohide window opacity if created */
- if (window->autohide_window)
- gtk_window_set_opacity (GTK_WINDOW (window->autohide_window), window->leave_opacity);
+ if (update)
+ panel_window_screen_update_borders (window);
- /* update the panel window opacity */
- gtk_window_set_opacity (GTK_WINDOW (window), window->leave_opacity);
+ gtk_widget_queue_resize (GTK_WIDGET (window));
+ }
break;
- case PROP_BACKGROUND_ALPHA:
- /* set the new value and redraw the panel */
- window->background_alpha = g_value_get_uint (value) / 100.00;
- gtk_widget_queue_draw (GTK_WIDGET (window));
-
- /* update the external plugins */
- gtk_container_foreach (GTK_CONTAINER (gtk_bin_get_child (GTK_BIN (window))),
- panel_window_set_plugin_background_alpha,
- GUINT_TO_POINTER (g_value_get_uint (value)));
+ case PROP_LOCKED:
+ val_bool = g_value_get_boolean (value);
+ if (window->locked != val_bool)
+ {
+ window->locked = !!val_bool;
+ gtk_widget_queue_resize (GTK_WIDGET (window));
+ }
break;
- case PROP_SNAP_EDGE:
- /* set snap edge value */
- window->snap_edge = g_value_get_uint (value);
-
- /* update the window borders */
- panel_window_set_borders (window);
-
- /* queue a resize */
- gtk_widget_queue_resize (GTK_WIDGET (window));
+ case PROP_AUTOHIDE:
+ panel_window_set_autohide (window, g_value_get_boolean (value));
break;
case PROP_SPAN_MONITORS:
- /* store new value */
- window->span_monitors = g_value_get_boolean (value);
-
- /* update the working area */
- panel_window_working_area (window, -1, -1, &window->working_area);
+ val_bool = g_value_get_boolean (value);
+ if (window->span_monitors == val_bool)
+ {
+ window->span_monitors = !!val_bool;
+ panel_window_screen_layout_changed (window->screen, window);
+ }
+ break;
- /* resize the panel */
- gtk_widget_queue_resize (GTK_WIDGET (window));
+ case PROP_OUTPUT_NAME:
+ g_free (window->output_name);
+ window->output_name = g_value_dup_string (value);
+ panel_window_screen_layout_changed (window->screen, window);
break;
- case PROP_AUTOHIDE:
- panel_window_set_autohide (window, g_value_get_boolean (value));
+ case PROP_POSITION:
+ val_string = g_value_get_string (value);
+ if (sscanf (val_string, "p=%d;x=%d;y=%d", &snap_position, &x, &y) == 3)
+ {
+ window->snap_position = CLAMP (snap_position, SNAP_POSITION_NONE, SNAP_POSITION_S);
+ window->base_x = x;
+ window->base_y = y;
+
+ panel_window_screen_layout_changed (window->screen, window);
+
+ /* send the new screen position to the panel plugins */
+ itembar = gtk_bin_get_child (GTK_BIN (window));
+ gtk_container_foreach (GTK_CONTAINER (itembar),
+ panel_window_set_screen_position, window);
+ }
+ else
+ {
+ g_message ("no valid position defined");
+ }
break;
default:
@@ -572,31 +562,18 @@ panel_window_finalize (GObject *object)
{
PanelWindow *window = PANEL_WINDOW (object);
- /* stop a running active timeout id */
- if (window->active_timeout_id != 0)
- g_source_remove (window->active_timeout_id);
-
- /* stop the autohide timeout */
- if (window->autohide_timer != 0)
- g_source_remove (window->autohide_timer);
+ /* stop running autohide timeout */
+ if (G_UNLIKELY (window->autohide_timeout_id != 0))
+ g_source_remove (window->autohide_timeout_id);
- /* destroy autohide window */
+ /* destroy the autohide window */
if (window->autohide_window != NULL)
gtk_widget_destroy (window->autohide_window);
- (*G_OBJECT_CLASS (panel_window_parent_class)->finalize) (object);
-}
-
+ /* cleanup */
+ g_free (window->output_name);
-
-static void
-panel_window_realize (GtkWidget *widget)
-{
- /* realize the window */
- (*GTK_WIDGET_CLASS (panel_window_parent_class)->realize) (widget);
-
- /* initialize the working area */
- panel_window_working_area (PANEL_WINDOW (widget), -1, -1, &PANEL_WINDOW (widget)->working_area);
+ (*G_OBJECT_CLASS (panel_window_parent_class)->finalize) (object);
}
@@ -608,182 +585,90 @@ panel_window_expose_event (GtkWidget *widget,
PanelWindow *window = PANEL_WINDOW (widget);
cairo_t *cr;
GdkColor *color;
- GtkStateType state = GTK_STATE_NORMAL;
- gdouble alpha = window->is_composited ? window->background_alpha : 1.00;
+ guint xx, yy, i;
+ gint xs, xe, ys, ye;
+ gint handle_w, handle_h;
+ gdouble alpha = 1.00;
+ GtkWidget *child;
- if (GTK_WIDGET_DRAWABLE (widget))
- {
- /* create cairo context */
- cr = gdk_cairo_create (widget->window);
-
- /* clip the drawing area */
- gdk_cairo_rectangle (cr, &event->area);
- cairo_clip (cr);
-
- if (alpha < 1.00 || window->active_timeout_id != 0)
- {
- /* get the background gdk color */
- color = &(widget->style->bg[state]);
-
- /* set the cairo source color */
- xfce_panel_cairo_set_source_rgba (cr, color, alpha);
+ /* expose the background and borders */
+ (*GTK_WIDGET_CLASS (panel_window_parent_class)->expose_event) (widget, event);
- /* create retangle */
- cairo_rectangle (cr, event->area.x, event->area.y,
- event->area.width, event->area.height);
+ if (window->locked || !GTK_WIDGET_DRAWABLE (widget))
+ goto end;
- /* draw on source */
- cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-
- /* paint rectangle */
- cairo_fill (cr);
- }
-
- /* paint handles */
- if (window->locked == FALSE)
- {
- panel_window_paint_handle (window, TRUE, state, cr);
- panel_window_paint_handle (window, FALSE, state, cr);
- }
+ if (window->horizontal)
+ {
+ handle_h = window->alloc.height / 2;
+ handle_w = HANDLE_SIZE;
- /* paint the panel borders */
- panel_window_paint_borders (window, state, cr);
+ xs = HANDLE_SPACING + 1;
+ xe = window->alloc.width - HANDLE_SIZE - HANDLE_SIZE;
+ ys = ye = (window->alloc.height - handle_h) / 2;
- /* destroy cairo context */
- cairo_destroy (cr);
+ /* dirty check if we have to redraw the handles */
+ if (event->area.x > xs + HANDLE_SIZE
+ && event->area.x + event->area.width < xe)
+ goto end;
}
-
- /* send expose event to child too */
- if (GTK_BIN (widget)->child)
- gtk_container_propagate_expose (GTK_CONTAINER (widget), GTK_BIN (widget)->child, event);
-
- return FALSE;
-}
-
-
-
-static guint
-panel_window_motion_notify_snap (gint value,
- gint length,
- gint start,
- gint end,
- gint *return_value)
-{
- gint tmp;
-
- /* snap in the center */
- tmp = start + ((end - start) - length) / 2;
- if (value >= tmp - SNAP_DISTANCE && value <= tmp + SNAP_DISTANCE)
+ else
{
- *return_value = tmp;
- return SNAP_CENTER;
- }
+ handle_h = HANDLE_SIZE;
+ handle_w = window->alloc.width / 2;
- /* snap on the start */
- if (value >= start && value <= start + SNAP_DISTANCE)
- {
- *return_value = start;
- return SNAP_START;
- }
+ xs = xe = (window->alloc.width - handle_w) / 2;
+ ys = HANDLE_SPACING + 1;
+ ye = window->alloc.height - HANDLE_SIZE - HANDLE_SIZE;
- /* snap on the end */
- tmp = end - length;
- if (value >= tmp - SNAP_DISTANCE && value <= tmp)
- {
- *return_value = tmp;
- return SNAP_END;
+ /* dirty check if we have to redraw the handles */
+ if (event->area.y > ys + HANDLE_SIZE
+ && event->area.y + event->area.height < ye)
+ goto end;
}
- /* set value as return value */
- *return_value = value;
-
- return SNAP_NONE;
-}
-
+ /* create cairo context and set some default properties */
+ cr = gdk_cairo_create (widget->window);
+ panel_return_val_if_fail (cr != NULL, FALSE);
+ cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ /* clip the drawing area */
+ gdk_cairo_rectangle (cr, &event->area);
+ cairo_clip (cr);
-static gboolean
-panel_window_motion_notify (GtkWidget *widget,
- GdkEventMotion *event)
-{
- PanelWindow *window = PANEL_WINDOW (widget);
- gint clamp_x, clamp_y;
- gint window_width, window_height;
- gint window_x, window_y;
- GdkRectangle area;
- gint snap_x, snap_y;
- guint snap_horizontal;
- guint snap_vertical;
- PanelWindowSnapEdge snap_edge = PANEL_SNAP_EGDE_NONE;
+ /* alpha color */
+ if (PANEL_BASE_WINDOW (window)->is_composited)
+ alpha = MAX (0.50, PANEL_BASE_WINDOW (window)->background_alpha);
- if (window->drag_motion)
+ for (i = HANDLE_PIXELS; i >= HANDLE_PIXELS - 1; i--)
{
- /* get the pointer position */
- window_x = event->x_root;
- window_y = event->y_root;
-
- /* get the maximum panel area on this coordinate */
- panel_window_working_area (window, window_x, window_y, &area);
-
- /* convert to corner offset */
- window_x -= window->drag_start_x;
- window_y -= window->drag_start_y;
-
- /* get allocated window size, but make sure it fits in the maximum area */
- window_width = MIN (widget->allocation.width, area.width);
- window_height = MIN (widget->allocation.height, area.height);
-
- /* keep the panel inside the maximum area */
- clamp_x = CLAMP (window_x, area.x, area.x + area.width - window_width);
- clamp_y = CLAMP (window_y, area.y, area.y + area.height - window_height);
-
- /* update the drag coordinates, so dragging feels responsive when the user hits a screen edge */
- window->drag_start_x += window_x - clamp_x;
- window->drag_start_y += window_y - clamp_y;
-
- /* try to find snapping edges */
- snap_horizontal = panel_window_motion_notify_snap (clamp_x, window_width, area.x, area.x + area.width, &snap_x);
- snap_vertical = panel_window_motion_notify_snap (clamp_y, window_height, area.y, area.y + area.height, &snap_y);
-
- /* detect the snap mode */
- if (snap_horizontal == SNAP_START)
- snap_edge = PANEL_SNAP_EGDE_W + snap_vertical;
- else if (snap_horizontal == SNAP_END)
- snap_edge = PANEL_SNAP_EGDE_E + snap_vertical;
- else if (snap_horizontal == SNAP_CENTER && snap_vertical == SNAP_START)
- snap_edge = PANEL_SNAP_EGDE_NC;
- else if (snap_horizontal == SNAP_CENTER && snap_vertical == SNAP_END)
- snap_edge = PANEL_SNAP_EGDE_SC;
- else if (snap_horizontal == SNAP_NONE && snap_vertical == SNAP_START)
- snap_edge = PANEL_SNAP_EGDE_N;
- else if (snap_horizontal == SNAP_NONE && snap_vertical == SNAP_END)
- snap_edge = PANEL_SNAP_EGDE_S;
-
- /* when snapping succeeded, set the snap coordinates for visual feedback */
- if (snap_edge != PANEL_SNAP_EGDE_NONE)
- {
- clamp_x = snap_x;
- clamp_y = snap_y;
- }
-
- /* move and resize the window */
- gdk_window_move_resize (widget->window, clamp_x, clamp_y, window_width, window_height);
+ /* set the source color */
+ if (i == HANDLE_PIXELS)
+ color = &(widget->style->light[GTK_STATE_NORMAL]);
+ else
+ color = &(widget->style->dark[GTK_STATE_NORMAL]);
+ panel_util_set_source_rgba (cr, color, alpha);
- /* if the snap edge changed, update the border */
- if (window->snap_edge != snap_edge)
- {
- /* set the new value */
- window->snap_edge = snap_edge;
+ /* draw the dots */
+ for (xx = 0; xx < (guint) handle_w; xx += HANDLE_PIXELS + HANDLE_PIXEL_SPACE)
+ for (yy = 0; yy < (guint) handle_h; yy += HANDLE_PIXELS + HANDLE_PIXEL_SPACE)
+ {
+ cairo_rectangle (cr, xs + xx, ys + yy, i, i);
+ cairo_rectangle (cr, xe + xx, ye + yy, i, i);
+ }
- /* notify the property */
- g_object_notify (G_OBJECT (window), "snap-edge");
+ /* fill the rectangles */
+ cairo_fill (cr);
+ }
- /* update the borders */
- panel_window_set_borders (window);
- }
+ /* destroy cairo context */
+ cairo_destroy (cr);
- return TRUE;
- }
+end:
+ /* send the expose event to the child */
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ if (G_LIKELY (child != NULL))
+ gtk_container_propagate_expose (GTK_CONTAINER (widget), child, event);
return FALSE;
}
@@ -791,234 +676,163 @@ panel_window_motion_notify (GtkWidget *widget,
static gboolean
-panel_window_button_press_event (GtkWidget *widget,
- GdkEventButton *event)
+panel_window_enter_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event)
{
PanelWindow *window = PANEL_WINDOW (widget);
- GdkCursor *cursor;
- guint modifiers;
-
- /* get the modifiers */
- modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
-
- if (event->button == 1
- && event->window == widget->window
- && window->locked == FALSE
- && modifiers == 0)
- {
- /* set initial start coordinates */
- window->drag_start_x = event->x;
- window->drag_start_y = event->y;
-
- /* create a moving cursor */
- cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), GDK_FLEUR);
-
- /* try to drab the pointer */
- window->drag_motion = (gdk_pointer_grab (widget->window, FALSE,
- GDK_BUTTON_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
- NULL, cursor, event->time) == GDK_GRAB_SUCCESS);
-
- /* release the cursor */
- gdk_cursor_unref (cursor);
- return TRUE;
- }
- else if (event->button == 3 || (event->button == 1 && modifiers == GDK_CONTROL_MASK))
+ /* update autohide status */
+ if (event->detail != GDK_NOTIFY_INFERIOR
+ && window->autohide_state != AUTOHIDE_DISABLED)
{
- /* popup the panel menu */
- panel_window_menu_popup (window);
+ /* stop a running autohide timeout */
+ if (window->autohide_timeout_id != 0)
+ g_source_remove (window->autohide_timeout_id);
- return TRUE;
+ /* update autohide status */
+ if (window->autohide_state == AUTOHIDE_POPDOWN)
+ window->autohide_state = AUTOHIDE_VISIBLE;
}
- return FALSE;
+ return (*GTK_WIDGET_CLASS (panel_window_parent_class)->enter_notify_event) (widget, event);
}
static gboolean
-panel_window_button_release_event (GtkWidget *widget,
- GdkEventButton *event)
+panel_window_leave_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event)
{
PanelWindow *window = PANEL_WINDOW (widget);
- if (window->drag_motion)
- {
- /* unset the drag */
- window->drag_motion = FALSE;
-
- /* release the pointer */
- gdk_pointer_ungrab (event->time);
-
- /* update the borders */
- panel_window_set_borders (window);
-
- /* update working area, struts and reallocate */
- panel_window_screen_changed (widget, gtk_window_get_screen (GTK_WINDOW (widget)));
-
- /* update the plugins */
- /* TODO panel function for this */
-
- return TRUE;
- }
+ /* queue a new autohide time if needed */
+ if (event->detail != GDK_NOTIFY_INFERIOR
+ && window->autohide_state != AUTOHIDE_DISABLED)
+ panel_window_autohide_queue (window, AUTOHIDE_POPDOWN);
- return FALSE;
+ return (*GTK_WIDGET_CLASS (panel_window_parent_class)->leave_notify_event) (widget, event);
}
static gboolean
-panel_window_autohide_timeout (gpointer user_data)
-{
- PanelWindow *window = PANEL_WINDOW (user_data);
-
- panel_return_val_if_fail (window->autohide_status != DISABLED
- && window->autohide_status != BLOCKED, FALSE);
-
- /* change status */
- if (window->autohide_status == POPDOWN_QUEUED || window->autohide_status == POPDOWN_QUEUED_SLOW)
- window->autohide_status = HIDDEN;
- else if (window->autohide_status == POPUP_QUEUED)
- window->autohide_status = VISIBLE;
-
- gtk_widget_queue_resize (GTK_WIDGET (window));
-
- return FALSE;
-}
-
-
-
-static void
-panel_window_autohide_timeout_destroy (gpointer user_data)
-{
- PANEL_WINDOW (user_data)->autohide_timer = 0;
-}
-
-
-
-static void
-panel_window_autohide_queue (PanelWindow *window,
- AutohideStatus status)
+panel_window_motion_notify_event (GtkWidget *widget,
+ GdkEventMotion *event)
{
- guint delay;
-
- panel_return_if_fail (PANEL_IS_WINDOW (window));
+ PanelWindow *window = PANEL_WINDOW (widget);
+ gint pointer_x, pointer_y;
+ gint window_x, window_y;
+ gint high;
- /* stop a running autohide timeout */
- if (window->autohide_timer != 0)
- g_source_remove (window->autohide_timer);
+ /* leave when the pointer is not grabbed */
+ if (G_UNLIKELY (window->grab_time == 0))
+ return FALSE;
- /* set new autohide status */
- window->autohide_status = status;
+ /* get the pointer position from the event */
+ pointer_x = event->x_root;
+ pointer_y = event->y_root;
- /* leave when the autohide is disabled */
- if (status == DISABLED || status == BLOCKED)
- {
- /* queue a resize to make sure everything is visible */
- gtk_widget_queue_resize (GTK_WIDGET (window));
- }
- else
+ /* check if the pointer moved to another monitor */
+ if (window->span_monitors == FALSE
+ && (pointer_x < window->area.x
+ || pointer_y < window->area.y
+ || pointer_x > window->area.x + window->area.width
+ || pointer_y > window->area.y + window->area.height))
{
- /* get the delay */
- if (status == POPDOWN_QUEUED)
- delay = POPDOWN_DELAY;
- else if (status == POPDOWN_QUEUED_SLOW)
- delay = POPDOWN_DELAY * 3;
- else
- delay = POPUP_DELAY;
-
- /* schedule a new timeout */
- window->autohide_timer = g_timeout_add_full (G_PRIORITY_LOW, delay,
- panel_window_autohide_timeout, window,
- panel_window_autohide_timeout_destroy);
+ /* set base point to cursor position and update working area */
+ window->base_x = pointer_x;
+ window->base_y = pointer_y;
+ panel_window_screen_layout_changed (window->screen, window);
}
-}
-
-
-
-static gboolean
-panel_window_autohide_enter_notify_event (GtkWidget *widget,
- GdkEventCrossing *event,
- PanelWindow *window)
-{
- panel_return_val_if_fail (PANEL_IS_WINDOW (window), FALSE);
- /* queue a hide timeout */
- panel_window_autohide_queue (window, POPUP_QUEUED);
+ /* calculate the new window position, but keep it inside the working geometry */
+ window_x = pointer_x - window->grab_x;
+ high = window->area.x + window->area.width - window->alloc.width;
+ window_x = CLAMP (window_x, window->area.x, high);
- return TRUE;
-}
+ window_y = pointer_y - window->grab_y;
+ high = window->area.y + window->area.height - window->alloc.height;
+ window_y = CLAMP (window_y, window->area.y, high);
+ /* update the grab coordinates */
+ window->grab_x = pointer_x - window_x;
+ window->grab_y = pointer_y - window_y;
+ /* update the base coordinates */
+ window->base_x = window_x + window->alloc.width / 2;
+ window->base_y = window_y + window->alloc.height / 2;
-static gboolean
-panel_window_autohide_leave_notify_event (GtkWidget *widget,
- GdkEventCrossing *event,
- PanelWindow *window)
-{
- panel_return_val_if_fail (PANEL_IS_WINDOW (window), FALSE);
+ /* update the allocation */
+ window->alloc.x = window_x;
+ window->alloc.y = window_y;
- /* stop a running autohide timeout */
- if (window->autohide_timer != 0)
- g_source_remove (window->autohide_timer);
+ /* update the snapping position */
+ window->snap_position = panel_window_snap_position (window);
- /* update the status */
- if (window->autohide_status == POPUP_QUEUED)
- window->autohide_status = HIDDEN;
+ /* update the working area */
+ panel_window_screen_layout_changed (window->screen, window);
return TRUE;
}
-static GtkWidget *
-panel_window_autohide_window (PanelWindow *window)
+static gboolean
+panel_window_button_press_event (GtkWidget *widget,
+ GdkEventButton *event)
{
- GtkWidget *popup;
-
- /* create window */
- popup = gtk_window_new (GTK_WINDOW_POPUP);
- gtk_window_set_gravity (GTK_WINDOW (popup), GDK_GRAVITY_STATIC);
-
- /* connect signals to monitor enter/leave events */
- g_signal_connect (G_OBJECT (popup), "enter-notify-event", G_CALLBACK (panel_window_autohide_enter_notify_event), window);
- g_signal_connect (G_OBJECT (popup), "leave-notify-event", G_CALLBACK (panel_window_autohide_leave_notify_event), window);
-
- /* put the window offscreen */
- gtk_window_move (GTK_WINDOW (popup), OFFSCREEN, OFFSCREEN);
-
- /* set window opacity */
- gtk_window_set_opacity (GTK_WINDOW (popup), window->leave_opacity);
+ PanelWindow *window = PANEL_WINDOW (widget);
+ GdkCursor *cursor;
+ GdkGrabStatus status;
+ GdkDisplay *display;
+ guint modifiers;
- /* show the window */
- gtk_widget_show (popup);
+ /* leave if the event is not for this window */
+ if (event->window != widget->window)
+ return FALSE;
- return popup;
-}
+ /* get the modifiers */
+ modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
+ if (event->button == 1
+ && event->type == GDK_BUTTON_PRESS
+ && window->locked == FALSE
+ && modifiers == 0)
+ {
+ /* debug check */
+ panel_return_val_if_fail (window->grab_time == 0, FALSE);
+ /* create a cursor */
+ display = gdk_screen_get_display (window->screen);
+ cursor = gdk_cursor_new_for_display (display, GDK_FLEUR);
-static gboolean
-panel_window_enter_notify_event (GtkWidget *widget,
- GdkEventCrossing *event)
-{
- PanelWindow *window = PANEL_WINDOW (widget);
+ /* grab the pointer for dragging the window */
+ status = gdk_pointer_grab (event->window, FALSE,
+ GDK_BUTTON_MOTION_MASK
+ | GDK_BUTTON_RELEASE_MASK,
+ NULL, cursor, event->time);
- /* ignore event when entered from an inferior */
- if (event->detail == GDK_NOTIFY_INFERIOR)
- return FALSE;
+ /* release the cursor */
+ gdk_cursor_unref (cursor);
- /* set the opacity (when they differ) */
- if (window->leave_opacity != window->enter_opacity)
- gtk_window_set_opacity (GTK_WINDOW (window), window->enter_opacity);
+ /* set the grab info if the grab was successfully made */
+ if (G_LIKELY (status == GDK_GRAB_SUCCESS))
+ {
+ window->grab_time = event->time;
+ window->grab_x = event->x;
+ window->grab_y = event->y;
+ }
- /* stop a running autohide timeout */
- if (window->autohide_timer != 0)
- g_source_remove (window->autohide_timer);
+ return !!(status == GDK_GRAB_SUCCESS);
+ }
+ else if (event->button == 3
+ || (event->button == 1 && modifiers == GDK_CONTROL_MASK))
+ {
+ /* popup the panel menu */
+ panel_window_menu_popup (window, event->time);
- /* update autohide status */
- if (window->autohide_status == POPDOWN_QUEUED)
- window->autohide_status = VISIBLE;
+ return TRUE;
+ }
return FALSE;
}
@@ -1026,26 +840,24 @@ panel_window_enter_notify_event (GtkWidget *widget,
static gboolean
-panel_window_leave_notify_event (GtkWidget *widget,
- GdkEventCrossing *event)
+panel_window_button_release_event (GtkWidget *widget,
+ GdkEventButton *event)
{
PanelWindow *window = PANEL_WINDOW (widget);
+ GdkDisplay *display;
- /* ignore event when left towards an inferior */
- if (event->detail == GDK_NOTIFY_INFERIOR)
- return FALSE;
-
- /* set the opacity (when they differ) */
- if (window->leave_opacity != window->enter_opacity)
- gtk_window_set_opacity (GTK_WINDOW (window), window->leave_opacity);
+ if (window->grab_time != 0)
+ {
+ /* ungrab the pointer */
+ display = gdk_screen_get_display (window->screen);
+ gdk_display_pointer_ungrab (display, window->grab_time);
+ window->grab_time = 0;
- /* stop a running autohide timeout */
- if (window->autohide_timer != 0)
- g_source_remove (window->autohide_timer);
+ /* update the position property */
+ g_object_notify (G_OBJECT (widget), "position");
- /* queue a new autohide time if needed */
- if (window->autohide_status > BLOCKED && window->snap_edge != PANEL_SNAP_EGDE_NONE)
- panel_window_autohide_queue (window, POPDOWN_QUEUED);
+ return TRUE;
+ }
return FALSE;
}
@@ -1056,6 +868,7 @@ static void
panel_window_grab_notify (GtkWidget *widget,
gboolean was_grabbed)
{
+#if 0
PanelWindow *window = PANEL_WINDOW (widget);
/* avoid hiding the panel when the window is grabbed. this
@@ -1065,236 +878,242 @@ panel_window_grab_notify (GtkWidget *widget,
panel_window_thaw_autohide (window);
else
panel_window_freeze_autohide (window);
+#endif
}
-/**
- * panel_window_size_request:
- * @widget : the panel window.
- * @requisition : the size we're requesting and receiving on
- * allocation.
- *
- * In this function we request the panel size, this size must fit
- * on the screen and match all the settings. It's not nessecarily
- * that all the plugins fit (based on their requisition that is),
- * they have to respect the size we allocate, requesting is only
- * being kind to plugins (actually the itembar), and we're not ;).
- **/
static void
panel_window_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
PanelWindow *window = PANEL_WINDOW (widget);
- GtkRequisition child_requisition;
+ GtkRequisition child_requisition = { 0, 0 };
+ gint value, length;
gint extra_width = 0, extra_height = 0;
+ PanelBorders borders;
- if (GTK_WIDGET_REALIZED (widget))
- {
- /* poke the itembar to request it's size */
- if (G_LIKELY (GTK_BIN (widget)->child))
- gtk_widget_size_request (GTK_BIN (widget)->child, &child_requisition);
- else
- child_requisition.width = child_requisition.height = 0;
-
- /* add the handle size */
- if (window->locked == FALSE)
- {
- if (window->horizontal)
- extra_width += HANDLE_SIZE_TOTAL;
- else
- extra_height += HANDLE_SIZE_TOTAL;
- }
-
- /* handle the borders */
- if (PANEL_HAS_FLAG (window->borders, PANEL_BORDER_LEFT))
- extra_width++;
-
- /* handle the borders */
- if (PANEL_HAS_FLAG (window->borders, PANEL_BORDER_RIGHT))
- extra_width++;
-
- /* handle the borders */
- if (PANEL_HAS_FLAG (window->borders, PANEL_BORDER_TOP))
- extra_height++;
-
- /* handle the borders */
- if (PANEL_HAS_FLAG (window->borders, PANEL_BORDER_BOTTOM))
- extra_height++;
+ /* get the child requisition */
+ if (GTK_BIN (widget)->child != NULL)
+ gtk_widget_size_request (GTK_BIN (widget)->child, &child_requisition);
- /* get the real allocated size */
+ /* handle size */
+ if (!window->locked)
+ {
if (window->horizontal)
- {
- /* calculate the panel width (fits content, fits on the screen, and extands to user size) */
- requisition->width = CLAMP (child_requisition.width + extra_width,
- window->working_area.width * window->length,
- window->working_area.width);
-
- /* set height based on user setting */
- requisition->height = window->size + extra_height;
- }
+ extra_width += 2 * HANDLE_SIZE_TOTAL;
else
- {
- /* calculate the panel width (fits content, fits on the screen, and extands to user size) */
- requisition->height = CLAMP (child_requisition.height + extra_height,
- window->working_area.height * window->length,
- window->working_area.height);
+ extra_height += 2 * HANDLE_SIZE_TOTAL;
+ }
- /* set width based on user setting */
- requisition->width = window->size + extra_width;
- }
+ /* get the active borders */
+ borders = panel_base_window_get_borders (PANEL_BASE_WINDOW (window));
+ if (PANEL_HAS_FLAG (borders, PANEL_BORDER_LEFT))
+ extra_width++;
+ if (PANEL_HAS_FLAG (borders, PANEL_BORDER_RIGHT))
+ extra_width++;
+ if (PANEL_HAS_FLAG (borders, PANEL_BORDER_TOP))
+ extra_height++;
+ if (PANEL_HAS_FLAG (borders, PANEL_BORDER_BOTTOM))
+ extra_height++;
+
+ /* set the window requisition */
+ if (window->horizontal)
+ {
+ requisition->height = window->size + extra_height;
+ length = window->area.width * window->length;
+ value = child_requisition.width + extra_width;
+ requisition->width = CLAMP (value, length, window->area.width);
+ }
+ else
+ {
+ requisition->width = window->size + extra_width;
+ length = window->area.height * window->length;
+ value = child_requisition.height + extra_height;
+ requisition->height = CLAMP (value, length, window->area.height);
}
}
-/**
- * panel_window_size_allocate:
- * @widget : the panel window.
- * @allocation : the allocation.
- *
- * Here we position the window on the monitor/screen. The width and
- * height of the allocation cannot be changed, it's determend in
- * panel_window_size_request, so if it's wrong: fix things there.
- *
- * Because the panel window is a GtkWindow, the allocation x and y
- * are 0, which is fine for the child, but not for screen, so we
- * calculate the new screen position move and resize we window (at
- * once to avoid strange visual effects).
- *
- * The child allocation is basiclly the same, only a small change
- * to keep the handles free, when the panel is locked.
- **/
static void
panel_window_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
+ GtkAllocation *alloc)
{
PanelWindow *window = PANEL_WINDOW (widget);
- GtkAllocation child_allocation;
- gint root_x, root_y;
- gint width = HIDDEN_PANEL_SIZE, height = HIDDEN_PANEL_SIZE;
- gint hidden_root_x, hidden_root_y;
+ GtkAllocation child_alloc;
+ gint w, h, x, y;
+ PanelBorders borders;
+ GtkWidget *child;
- if (GTK_WIDGET_REALIZED (widget))
+ widget->allocation = *alloc;
+ window->alloc = *alloc;
+
+ if (G_UNLIKELY (window->autohide_state == AUTOHIDE_HIDDEN
+ || window->autohide_state == AUTOHIDE_POPUP))
+ {
+ /* window is invisible */
+ window->alloc.x = window->alloc.y = -9999;
+
+ /* set hidden window size */
+ w = h = 3;
+ if (window->horizontal)
+ w = alloc->width;
+ else
+ h = alloc->height;
+
+ /* position the autohide window */
+ panel_window_size_allocate_set_xy (window, w, h, &x, &y);
+ panel_base_window_move_resize (PANEL_BASE_WINDOW (window->autohide_window),
+ x, y, w, h);
+ }
+ else
{
- /* set the widget allocation */
- widget->allocation = *allocation;
+ /* update the allocation */
+ panel_window_size_allocate_set_xy (window, alloc->width,
+ alloc->height, &window->alloc.x, &window->alloc.y);
+
+ /* update the struts if needed, leave when nothing changed */
+ if (window->struts_edge != STRUTS_EDGE_NONE
+ && window->autohide_state == AUTOHIDE_DISABLED)
+ panel_window_screen_struts_set (window);
+
+ /* move the autohide window offscreen */
+ if (window->autohide_window != NULL)
+ panel_base_window_move_resize (PANEL_BASE_WINDOW (window->autohide_window),
+ -9999, -9999, -1, -1);
+ }
+
+ /* move the window */
+ gtk_window_move (GTK_WINDOW (window), window->alloc.x, window->alloc.y);
- /* get coordinates for the panel window */
- panel_window_calculate_position (window, allocation->width, allocation->height, &root_x, &root_y);
+ /* position the child */
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ if (G_LIKELY (child != NULL))
+ {
+ /* init child allocation */
+ child_alloc.x = 0;
+ child_alloc.y = 0;
+ child_alloc.width = alloc->width;
+ child_alloc.height = alloc->height;
+
+ /* set position against the borders */
+ borders = panel_base_window_get_borders (PANEL_BASE_WINDOW (window));
+ if (PANEL_HAS_FLAG (borders, PANEL_BORDER_LEFT))
+ {
+ child_alloc.x++;
+ child_alloc.width--;
+ }
+ if (PANEL_HAS_FLAG (borders, PANEL_BORDER_TOP))
+ {
+ child_alloc.y++;
+ child_alloc.height--;
+ }
+ if (PANEL_HAS_FLAG (borders, PANEL_BORDER_RIGHT))
+ child_alloc.width--;
+ if (PANEL_HAS_FLAG (borders, PANEL_BORDER_BOTTOM))
+ child_alloc.height--;
- /* handle hidden windows */
- if (window->autohide_status != DISABLED
- && window->autohide_window != NULL
- && window->snap_edge != PANEL_SNAP_EGDE_NONE)
+ /* keep space for the panel handles if not locked */
+ if (!window->locked)
{
- if (window->autohide_status == VISIBLE
- || window->autohide_status == POPDOWN_QUEUED
- || window->autohide_status == POPDOWN_QUEUED_SLOW
- || window->autohide_status == BLOCKED)
+ if (window->horizontal)
{
- /* put the hidden window offscreen */
- gtk_window_move (GTK_WINDOW (window->autohide_window), OFFSCREEN, OFFSCREEN);
+ child_alloc.width -= 2 * HANDLE_SIZE_TOTAL;
+ child_alloc.x += HANDLE_SIZE_TOTAL;
}
else
{
- /* init width and height */
- width = height = HIDDEN_PANEL_SIZE;
-
- /* get hidden panel size */
- switch (window->snap_edge)
- {
- case PANEL_SNAP_EGDE_E:
- case PANEL_SNAP_EGDE_EC:
- case PANEL_SNAP_EGDE_W:
- case PANEL_SNAP_EGDE_WC:
- height = allocation->height;
- break;
-
- case PANEL_SNAP_EGDE_NC:
- case PANEL_SNAP_EGDE_SC:
- case PANEL_SNAP_EGDE_N:
- case PANEL_SNAP_EGDE_S:
- width = allocation->width;
- break;
-
- default:
- if (window->horizontal)
- width = allocation->width;
- else
- height = allocation->height;
- break;
- }
-
- /* get coordinates for the hidden window */
- panel_window_calculate_position (window, width, height, &hidden_root_x, &hidden_root_y);
-
- /* position the hidden window */
- gtk_window_move (GTK_WINDOW (window->autohide_window), hidden_root_x, hidden_root_y);
- gtk_window_resize (GTK_WINDOW (window->autohide_window), width, height);
-
- /* put the panel window offscreen */
- root_x = root_y = OFFSCREEN;
+ child_alloc.height -= 2 * HANDLE_SIZE_TOTAL;
+ child_alloc.y += HANDLE_SIZE_TOTAL;
}
}
- /* move and resize the panel window */
- gdk_window_move_resize (widget->window, root_x, root_y, allocation->width, allocation->height);
+ /* allocate the itembar */
+ gtk_widget_size_allocate (child, &child_alloc);
+ }
+}
- if (GTK_BIN (widget)->child)
- {
- /* set the child allocation */
- child_allocation = *allocation;
- /* extract the border sizes from the allocation */
- if (PANEL_HAS_FLAG (window->borders, PANEL_BORDER_LEFT))
- {
- child_allocation.x++;
- child_allocation.width--;
- }
- if (PANEL_HAS_FLAG (window->borders, PANEL_BORDER_TOP))
- {
- child_allocation.y++;
- child_allocation.height--;
- }
+static void
+panel_window_size_allocate_set_xy (PanelWindow *window,
+ gint window_width,
+ gint window_height,
+ gint *return_x,
+ gint *return_y)
+{
+ gint value, hight;
- if (PANEL_HAS_FLAG (window->borders, PANEL_BORDER_RIGHT))
- child_allocation.width--;
+ /* x-position */
+ switch (window->snap_position)
+ {
+ case SNAP_POSITION_NONE:
+ case SNAP_POSITION_N:
+ case SNAP_POSITION_S:
+ /* clamp base point on screen */
+ value = window->base_x - (window_width / 2);
+ hight = window->area.x + window->area.width - window_width;
+ *return_x = CLAMP (value, window->area.x, hight);
+ break;
- if (PANEL_HAS_FLAG (window->borders, PANEL_BORDER_BOTTOM))
- child_allocation.height--;
+ case SNAP_POSITION_W:
+ case SNAP_POSITION_NW:
+ case SNAP_POSITION_WC:
+ case SNAP_POSITION_SW:
+ /* left */
+ *return_x = window->area.x;
+ break;
- /* keep free space for the handles if needed */
- if (window->locked == FALSE)
- {
- if (window->horizontal)
- {
- child_allocation.width -= HANDLE_SIZE_TOTAL;
- child_allocation.x += HANDLE_SIZE + HANDLE_SPACING;
- }
- else
- {
- child_allocation.height -= HANDLE_SIZE_TOTAL;
- child_allocation.y += HANDLE_SIZE + HANDLE_SPACING;
- }
- }
+ case SNAP_POSITION_E:
+ case SNAP_POSITION_NE:
+ case SNAP_POSITION_EC:
+ case SNAP_POSITION_SE:
+ /* right */
+ *return_x = window->area.x + window->area.width - window_width;
+ break;
- /* keep things positive */
- child_allocation.width = MAX (0, child_allocation.width);
- child_allocation.height = MAX (0, child_allocation.height);
+ case SNAP_POSITION_NC:
+ case SNAP_POSITION_SC:
+ /* center */
+ *return_x = window->area.x + (window->area.width - window_width) / 2;
+ break;
+ }
- /* allocate the child */
- gtk_widget_size_allocate (GTK_BIN (widget)->child, &child_allocation);
- }
+ /* y-position */
+ switch (window->snap_position)
+ {
+ case SNAP_POSITION_NONE:
+ case SNAP_POSITION_E:
+ case SNAP_POSITION_W:
+ /* clamp base point on screen */
+ value = window->base_y - (window_height / 2);
+ hight = window->area.y + window->area.height - window_height;
+ *return_y = CLAMP (value, window->area.y, hight);
+ break;
- /* update struts if possible */
- if (window->struts_possible != 0)
- panel_window_struts_update (window, root_x, root_y, allocation->width, allocation->height);
- }
+ case SNAP_POSITION_NE:
+ case SNAP_POSITION_NW:
+ case SNAP_POSITION_NC:
+ case SNAP_POSITION_N:
+ /* top */
+ *return_y = window->area.y;
+ break;
+
+ case SNAP_POSITION_SE:
+ case SNAP_POSITION_SW:
+ case SNAP_POSITION_SC:
+ case SNAP_POSITION_S:
+ /* bottom */
+ *return_y = window->area.y + window->area.height - window_height;
+ break;
- /* update previous allocation */
- window->prev_allocation = *allocation;
+ case SNAP_POSITION_EC:
+ case SNAP_POSITION_WC:
+ /* center */
+ *return_y = window->area.y + (window->area.height - window_height) / 2;
+ break;
+ }
}
@@ -1303,679 +1122,598 @@ static void
panel_window_screen_changed (GtkWidget *widget,
GdkScreen *previous_screen)
{
- GdkScreen *screen;
PanelWindow *window = PANEL_WINDOW (widget);
-
- panel_return_if_fail (PANEL_IS_WINDOW (widget));
- panel_return_if_fail (GDK_IS_SCREEN (previous_screen));
+ GdkScreen *screen;
/* get the new screen */
screen = gtk_window_get_screen (GTK_WINDOW (widget));
+ panel_return_if_fail (GDK_IS_SCREEN (screen));
+ if (G_UNLIKELY (window->screen == screen))
+ return;
+
+ /* disconnect from previous screen */
+ if (G_UNLIKELY (window->screen != NULL))
+ g_signal_handlers_disconnect_by_func (G_OBJECT (window->screen),
+ panel_window_screen_layout_changed, window);
+
+ /* set the new screen */
+ window->screen = screen;
+ g_signal_connect (G_OBJECT (window->screen), "monitors-changed",
+ G_CALLBACK (panel_window_screen_layout_changed), window);
+ g_signal_connect (G_OBJECT (window->screen), "size-changed",
+ G_CALLBACK (panel_window_screen_layout_changed), window);
+
+ /* update the screen layout */
+ panel_window_screen_layout_changed (screen, window);
+}
+
+
+
+static StrutsEgde
+panel_window_screen_struts_edge (PanelWindow *window)
+{
+ panel_return_val_if_fail (PANEL_IS_WINDOW (window), STRUTS_EDGE_NONE);
- if (screen != previous_screen)
+ /* no struts when autohide is active */
+ if (window->autohide_state != AUTOHIDE_DISABLED)
+ return STRUTS_EDGE_NONE;
+
+ /* return the screen edge on which the window is
+ * visually snapped and where the struts are set */
+ switch (window->snap_position)
{
- /* disconnect old screen changed handles */
- g_signal_handlers_disconnect_by_func (G_OBJECT (previous_screen), G_CALLBACK (panel_window_screen_changed), widget);
+ case SNAP_POSITION_NONE:
+ return STRUTS_EDGE_NONE;
- /* connect new screen update signals */
- g_signal_connect_swapped (G_OBJECT (screen), "size-changed", G_CALLBACK (panel_window_screen_changed), widget);
-#if GTK_CHECK_VERSION (2,14,0)
- g_signal_connect_swapped (G_OBJECT (screen), "monitors-changed", G_CALLBACK (panel_window_screen_changed), widget);
-#endif
- }
+ case SNAP_POSITION_E:
+ case SNAP_POSITION_EC:
+ return window->horizontal ? STRUTS_EDGE_NONE : STRUTS_EDGE_RIGHT;
- /* update the panel working area */
- panel_window_working_area (window, -1, -1, &window->working_area);
+ case SNAP_POSITION_NE:
+ return window->horizontal ? STRUTS_EDGE_TOP : STRUTS_EDGE_RIGHT;
- /* check if struts are needed on the next resize */
- window->struts_possible = -1;
+ case SNAP_POSITION_SE:
+ return window->horizontal ? STRUTS_EDGE_BOTTOM : STRUTS_EDGE_RIGHT;
- /* queue a resize */
- gtk_widget_queue_resize (widget);
+ case SNAP_POSITION_W:
+ case SNAP_POSITION_WC:
+ return window->horizontal ? STRUTS_EDGE_NONE : STRUTS_EDGE_LEFT;
+
+ case SNAP_POSITION_NW:
+ return window->horizontal ? STRUTS_EDGE_TOP : STRUTS_EDGE_LEFT;
+
+ case SNAP_POSITION_SW:
+ return window->horizontal ? STRUTS_EDGE_BOTTOM : STRUTS_EDGE_LEFT;
+
+ case SNAP_POSITION_NC:
+ case SNAP_POSITION_N:
+ return window->horizontal ? STRUTS_EDGE_TOP : STRUTS_EDGE_NONE;
+
+ case SNAP_POSITION_SC:
+ case SNAP_POSITION_S:
+ return window->horizontal ? STRUTS_EDGE_BOTTOM : STRUTS_EDGE_NONE;
+ }
+
+ return STRUTS_EDGE_NONE;
}
static void
-panel_window_paint_handle (PanelWindow *window,
- gboolean start,
- GtkStateType state,
- cairo_t *cr)
+panel_window_screen_struts_set (PanelWindow *window)
{
- GtkWidget *widget = GTK_WIDGET (window);
- GtkAllocation *alloc = &(widget->allocation);
- gint x, y, width, height;
- guint i, xx, yy;
- GdkColor *color;
- gdouble alpha = 1.00;
-
- /* set the alpha (always show to handle for atleast 50%) */
- if (window->active_timeout_id == 0 && window->is_composited)
- alpha = 0.50 + window->background_alpha / 2.00;
+ gulong struts[N_STRUTS] = { 0, };
+ GdkRectangle *alloc = &window->alloc;
+ guint i;
+ gboolean update_struts = FALSE;
+#if STRUTS_DEBUGGING
+ gint n;
+ const gchar *names1[] = { "left", "right", "top", "bottom" };
+ const gchar *names2[] = { "y", "y", "x", "x" };
+#endif
- /* set initial numbers */
- x = alloc->x + 2;
- y = alloc->y + 2;
+ panel_return_if_fail (PANEL_IS_WINDOW (window));
+ panel_return_if_fail (GDK_IS_WINDOW (GTK_WIDGET (window)->window));
+ panel_return_if_fail (cardinal_atom != 0 && net_wm_strut_partial_atom != 0);
+ panel_return_if_fail (GDK_IS_SCREEN (window->screen));
- if (window->horizontal)
+ /* set the struts */
+ /* note that struts are relative to the screen edge! */
+ if (window->struts_edge == STRUTS_EDGE_TOP)
{
- width = HANDLE_SIZE / 3 * 3;
- height = alloc->height / 2;
- y += height / 2 - 1;
- x += (HANDLE_SIZE - width);
-
- /* draw handle on the right */
- if (!start)
- x += alloc->width - HANDLE_SIZE - 4;
+ /* the window is snapped on the top screen edge */
+ struts[STRUT_TOP] = alloc->y + alloc->height;
+ struts[STRUT_TOP_START_X] = alloc->x;
+ struts[STRUT_TOP_END_X] = alloc->x + alloc->width;
}
- else
+ else if (window->struts_edge == STRUTS_EDGE_BOTTOM)
+ {
+ /* the window is snapped on the bottom screen edge */
+ struts[STRUT_BOTTOM] = gdk_screen_get_height (window->screen) - alloc->y;
+ struts[STRUT_BOTTOM_START_X] = alloc->x;
+ struts[STRUT_BOTTOM_END_X] = alloc->x + alloc->width;
+ }
+ else if (window->struts_edge == STRUTS_EDGE_LEFT)
+ {
+ /* the window is snapped on the left screen edge */
+ struts[STRUT_LEFT] = alloc->x + alloc->width;
+ struts[STRUT_LEFT_START_Y] = alloc->y;
+ struts[STRUT_LEFT_END_Y] = alloc->y + alloc->height;
+ }
+ else if (window->struts_edge == STRUTS_EDGE_RIGHT)
{
- height = HANDLE_SIZE / 3 * 3;
- width = alloc->width / 2;
- x += width / 2 - 1;
- y += (HANDLE_SIZE - height);
-
- /* draw handle on the bottom */
- if (!start)
- y += alloc->height - HANDLE_SIZE - 4;
+ /* the window is snapped on the right screen edge */
+ struts[STRUT_RIGHT] = gdk_screen_get_width (window->screen) - alloc->x;
+ struts[STRUT_RIGHT_START_Y] = alloc->y;
+ struts[STRUT_RIGHT_END_Y] = alloc->y + alloc->height;
}
- /* draw handler */
- for (i = 2; i > 0; i--)
+ /* store the new struts */
+ for (i = 0; i < N_STRUTS; i++)
{
- /* get the color for the job */
- if (i == 2)
- color = &(widget->style->light[state]);
- else
- color = &(widget->style->dark[state]);
+ /* check if we need to update */
+ if (G_LIKELY (struts[i] == window->struts[i]))
+ continue;
- /* set source color */
- xfce_panel_cairo_set_source_rgba (cr, color, alpha);
+ /* set new value */
+ update_struts = TRUE;
+ window->struts[i] = struts[i];
+ }
- /* draw the dots */
- for (xx = 0; xx < (guint) width; xx += 3)
- for (yy = 0; yy < (guint) height; yy += 3)
- cairo_rectangle (cr, x + xx, y + yy, i, i);
+ /* leave when there is nothing to update */
+ if (update_struts == FALSE)
+ return;
+
+ /* don't crash on x errors */
+ gdk_error_trap_push ();
+
+ /* set the wm strut partial */
+ gdk_property_change (GTK_WIDGET (window)->window,
+ net_wm_strut_partial_atom,
+ cardinal_atom, 32, GDK_PROP_MODE_REPLACE,
+ (guchar *) &struts, N_STRUTS);
+
+#if SET_OLD_WM_STRUTS
+ /* set the wm strut (old window managers) */
+ gdk_property_change (GTK_WIDGET (window)->window,
+ net_wm_strut_atom,
+ cardinal_atom, 32, GDK_PROP_MODE_REPLACE,
+ (guchar *) &struts, 4);
+#endif
- /* fill the rectangles */
- cairo_fill (cr);
- }
+ /* release the trap */
+ if (gdk_error_trap_pop () != 0)
+ g_critical ("Failed to set the struts");
+
+#if STRUTS_DEBUGGING
+ /* debugging output */
+ if (struts[STRUT_LEFT] != 0)
+ n = STRUT_LEFT;
+ else if (struts[STRUT_RIGHT] != 0)
+ n = STRUT_RIGHT;
+ else if (struts[STRUT_TOP] != 0)
+ n = STRUT_TOP;
+ else if (struts[STRUT_BOTTOM] != 0)
+ n = STRUT_BOTTOM;
+ else
+ n = -1;
+
+ if (n == -1)
+ g_message ("Struts updated: Reset to zero.");
+ else
+ g_message ("Struts updated: %s = %ld, start_%s = %ld, end_%s = %ld.",
+ names1[n], struts[n], names2[n], struts[4 + n * 2],
+ names2[n], struts[5 + n * 2]);
+#endif
}
static void
-panel_window_paint_borders (PanelWindow *window,
- GtkStateType state,
- cairo_t *cr)
+panel_window_screen_force_update (PanelWindow *window)
{
- GtkWidget *widget = GTK_WIDGET (window);
- GtkAllocation *alloc = &(widget->allocation);
- GdkColor *color;
- gdouble alpha = 1.00;
- const gdouble dashes[] = {4.00, 4.00};
- GTimeVal timeval;
-
- /* 1px line (1.5 results in a sharp 1px line) */
- cairo_set_line_width (cr, 1.5);
-
- if (G_UNLIKELY (window->active_timeout_id != 0))
- g_get_current_time (&timeval);
- else if (window->is_composited)
- alpha = window->background_alpha;
-
- /* possibly save some time */
- if (PANEL_HAS_FLAG (window->borders, (PANEL_BORDER_BOTTOM | PANEL_BORDER_RIGHT)))
- {
- /* dark color */
- if (G_UNLIKELY (window->active_timeout_id != 0))
- color = &(widget->style->black);
- else
- color = &(widget->style->dark[state]);
- xfce_panel_cairo_set_source_rgba (cr, color, alpha);
-
- /* move the cursor the the bottom left */
- cairo_move_to (cr, alloc->x, alloc->y + alloc->height);
-
- /* bottom line */
- if (PANEL_HAS_FLAG (window->borders, PANEL_BORDER_BOTTOM))
- cairo_rel_line_to (cr, alloc->width, 0);
- else
- cairo_rel_move_to (cr, alloc->width, 0);
-
- /* right line */
- if (PANEL_HAS_FLAG (window->borders, PANEL_BORDER_RIGHT))
- cairo_rel_line_to (cr, 0, -alloc->height);
- else
- cairo_rel_move_to (cr, 0, -alloc->height);
-
- if (G_UNLIKELY (window->active_timeout_id != 0))
- cairo_set_dash (cr, dashes, G_N_ELEMENTS (dashes),
- timeval.tv_sec % 2 ? 0.00 : 4.00);
-
- /* stroke this part */
- cairo_stroke (cr);
- }
+ panel_return_if_fail (PANEL_IS_WINDOW (window));
- /* possibly save some time */
- if (PANEL_HAS_FLAG (window->borders, (PANEL_BORDER_TOP | PANEL_BORDER_LEFT)))
+ if (GTK_WIDGET_VISIBLE (window))
{
- /* light color */
- if (G_UNLIKELY (window->active_timeout_id != 0))
- color = &(widget->style->black);
- else
- color = &(widget->style->light[state]);
- xfce_panel_cairo_set_source_rgba (cr, color, alpha);
-
- /* move the cursor the the bottom left */
- cairo_move_to (cr, alloc->x, alloc->y + alloc->height);
-
- /* left line */
- if (PANEL_HAS_FLAG (window->borders, PANEL_BORDER_LEFT))
- cairo_rel_line_to (cr, 0, -alloc->height);
- else
- cairo_rel_move_to (cr, 0, -alloc->height);
+ /* make sure the struts are set again, when enabled */
+ if (window->struts_edge != STRUTS_EDGE_NONE
+ && window->autohide_state == AUTOHIDE_DISABLED)
+ window->struts[0] = -1;
- /* top line */
- if (PANEL_HAS_FLAG (window->borders, PANEL_BORDER_TOP))
- cairo_rel_line_to (cr, alloc->width, 0);
- else
- cairo_rel_move_to (cr, alloc->width, 0);
-
- if (G_UNLIKELY (window->active_timeout_id != 0))
- cairo_set_dash (cr, dashes, G_N_ELEMENTS (dashes),
- timeval.tv_sec % 2 ? 0.00 : -4.00);
-
- /* stroke the lines */
- cairo_stroke (cr);
+ /* update the panel position */
+ panel_window_screen_layout_changed (window->screen, window);
}
}
static void
-panel_window_calculate_position (PanelWindow *window,
- gint width,
- gint height,
- gint *x,
- gint *y)
+panel_window_screen_update_borders (PanelWindow *window)
{
- gint root_x, root_y;
- GdkRectangle *area = &window->working_area;
+ PanelBorders borders = PANEL_BORDER_MASK;
+ PanelBorders unset_borders = 0;
- /* get the panel window position */
- panel_window_get_position (window, &root_x, &root_y);
+ panel_return_if_fail (PANEL_IS_WINDOW (window));
- /* x position of the window */
- switch (window->snap_edge)
+ /* the border we want to hide */
+ switch (window->snap_position)
{
- /* left */
- case PANEL_SNAP_EGDE_W:
- case PANEL_SNAP_EGDE_NW:
- case PANEL_SNAP_EGDE_WC:
- case PANEL_SNAP_EGDE_SW:
- *x = area->x;
+ case SNAP_POSITION_NONE:
break;
- /* right */
- case PANEL_SNAP_EGDE_E:
- case PANEL_SNAP_EGDE_NE:
- case PANEL_SNAP_EGDE_EC:
- case PANEL_SNAP_EGDE_SE:
- *x = area->x + area->width - width;
+ case SNAP_POSITION_E:
+ case SNAP_POSITION_EC:
+ unset_borders = PANEL_BORDER_RIGHT;
break;
- /* center */
- case PANEL_SNAP_EGDE_NC:
- case PANEL_SNAP_EGDE_SC:
- *x = area->x + (area->width - width) / 2;
+ case SNAP_POSITION_W:
+ case SNAP_POSITION_WC:
+ unset_borders = PANEL_BORDER_LEFT;
break;
- /* other, recenter based on previous allocation */
- default:
- *x = root_x + (window->prev_allocation.width - width) / 2;
- *x = CLAMP (*x, area->x, area->x + area->width - width);
+ case SNAP_POSITION_N:
+ case SNAP_POSITION_NC:
+ unset_borders = PANEL_BORDER_TOP;
break;
- }
- /* y position of the window */
- switch (window->snap_edge)
- {
- /* north */
- case PANEL_SNAP_EGDE_NE:
- case PANEL_SNAP_EGDE_NW:
- case PANEL_SNAP_EGDE_NC:
- case PANEL_SNAP_EGDE_N:
- *y = area->y;
+ case SNAP_POSITION_S:
+ case SNAP_POSITION_SC:
+ unset_borders = PANEL_BORDER_BOTTOM;
break;
- /* south */
- case PANEL_SNAP_EGDE_SE:
- case PANEL_SNAP_EGDE_SW:
- case PANEL_SNAP_EGDE_SC:
- case PANEL_SNAP_EGDE_S:
- *y = area->y + area->height - height;
+ case SNAP_POSITION_NE:
+ unset_borders = PANEL_BORDER_RIGHT | PANEL_BORDER_TOP;
break;
- /* center */
- case PANEL_SNAP_EGDE_EC:
- case PANEL_SNAP_EGDE_WC:
- *y = area->y + (area->height - height) / 2;
+ case SNAP_POSITION_SE:
+ unset_borders = PANEL_BORDER_RIGHT | PANEL_BORDER_BOTTOM;
break;
- /* other, recenter based on previous allocation */
- default:
- *y = root_y + (window->prev_allocation.height - height) / 2;
- *y = CLAMP (*y, area->y, area->y + area->height - height);
+ case SNAP_POSITION_NW:
+ unset_borders = PANEL_BORDER_LEFT | PANEL_BORDER_TOP;
break;
- }
-}
-
+ case SNAP_POSITION_SW:
+ unset_borders = PANEL_BORDER_LEFT | PANEL_BORDER_BOTTOM;
+ break;
+ }
-static void
-panel_window_working_area (PanelWindow *window,
- gint root_x,
- gint root_y,
- GdkRectangle *dest)
-{
- GdkScreen *screen;
- gint monitor_num;
- gint n_monitors;
- GdkRectangle geometry;
- gint i;
+ /* the visible borders */
+ PANEL_UNSET_FLAG (borders, unset_borders);
- panel_return_if_fail (PANEL_IS_WINDOW (window));
- panel_return_if_fail (GDK_IS_WINDOW (GTK_WIDGET (window)->window));
+ /* don't show the side borders if the length is 100% */
+ if (window->length == 1.00)
+ {
+ if (window->horizontal)
+ PANEL_UNSET_FLAG (borders, PANEL_BORDER_LEFT | PANEL_BORDER_RIGHT);
+ else
+ PANEL_UNSET_FLAG (borders, PANEL_BORDER_TOP | PANEL_BORDER_BOTTOM);
+ }
- /* get valid coordinates if not set */
- if (root_x == -1 && root_y == -1)
- gtk_window_get_position (GTK_WINDOW (window), &root_x, &root_y);
+ /* set the borders */
+ panel_base_window_set_borders (PANEL_BASE_WINDOW (window), borders);
+}
- /* get panel screen */
- screen = gtk_window_get_screen (GTK_WINDOW (window));
- /* get the monitor number */
- monitor_num = gdk_screen_get_monitor_at_point (screen, root_x, root_y);
- /* get the root monitor geometry */
- gdk_screen_get_monitor_geometry (screen, monitor_num, dest);
+static inline guint
+panel_window_snap_edge_gravity (gint value,
+ gint start,
+ gint end)
+{
+ gint center;
- if (window->span_monitors)
- {
- /* get the number of monitors */
- n_monitors = gdk_screen_get_n_monitors (screen);
+ /* snap at the start */
+ if (value >= start && value <= start + SNAP_DISTANCE)
+ return EDGE_GRAVITY_START;
- /* only try to extend when there are more then 2 monitors */
- if (G_LIKELY (n_monitors > 1))
- {
- for (i = 0; i < n_monitors; i++)
- {
- /* skip the origional monitor */
- if (i == monitor_num)
- continue;
+ /* snap at the end */
+ if (value <= end && value >= end - SNAP_DISTANCE)
+ return EDGE_GRAVITY_END;
- /* get the monitor geometry */
- gdk_screen_get_monitor_geometry (screen, i, &geometry);
+ /* calculate the center of start and end */
+ center = start + (end - start) / 2;
- g_message ("monitor %d, x=%d, y=%d, w=%d, h=%d", i, geometry.x, geometry.y, geometry.width, geometry.height);
+ /* snap at the center */
+ if (value >= center - 10 && value <= center + SNAP_DISTANCE)
+ return EDGE_GRAVITY_CENTER;
- /* try to extend the dest geometry from the root coordinate's point of view */
- if (window->horizontal
- && root_y >= geometry.y
- && root_y <= geometry.y + geometry.height
- && (dest->x + dest->width == geometry.x
- || dest->x == geometry.x + geometry.width))
- {
- /* extend the maximum area horizontally */
- dest->x = MIN (dest->x, geometry.x);
- dest->width += geometry.width;
- }
- else if (window->horizontal == FALSE
- && root_x >= geometry.x
- && root_x <= geometry.x + geometry.width
- && (dest->y + dest->height == geometry.y
- || dest->y == geometry.y + geometry.height))
- {
- /* extend the maximum area vertically */
- dest->y = MIN (dest->y, geometry.y);
- dest->height += geometry.height;
- }
- }
- }
- }
+ return EDGE_GRAVITY_NONE;
}
-static gboolean
-panel_window_struts_are_possible (PanelWindow *window,
- gint x,
- gint y,
- gint width,
- gint height)
+static SnapPosition
+panel_window_snap_position (PanelWindow *window)
{
- GdkScreen *screen;
- gint n_monitors;
- gint i;
- GdkRectangle geometry;
+ guint snap_horz, snap_vert;
+ GdkRectangle *alloc = &window->alloc;
+
+ /* get the snap offsets */
+ snap_horz = panel_window_snap_edge_gravity (alloc->x, window->area.x,
+ window->area.x + window->area.width - alloc->width);
+ snap_vert = panel_window_snap_edge_gravity (alloc->y, window->area.y,
+ window->area.y + window->area.height - alloc->height);
+
+ /* detect the snap mode */
+ if (snap_horz == EDGE_GRAVITY_START)
+ return SNAP_POSITION_W + snap_vert;
+ else if (snap_horz == EDGE_GRAVITY_END)
+ return SNAP_POSITION_E + snap_vert;
+ else if (snap_horz == EDGE_GRAVITY_CENTER && snap_vert == EDGE_GRAVITY_START)
+ return SNAP_POSITION_NC;
+ else if (snap_horz == EDGE_GRAVITY_CENTER && snap_vert == EDGE_GRAVITY_END)
+ return SNAP_POSITION_SC;
+ else if (snap_horz == EDGE_GRAVITY_NONE && snap_vert == EDGE_GRAVITY_START)
+ return SNAP_POSITION_N;
+ else if (snap_horz == EDGE_GRAVITY_NONE && snap_vert == EDGE_GRAVITY_END)
+ return SNAP_POSITION_S;
+
+ return SNAP_POSITION_NONE;
+}
- panel_return_val_if_fail (PANEL_IS_WINDOW (window), FALSE);
- /* never set struts when we don't snap or when autohide is enabled */
- if (window->snap_edge == PANEL_SNAP_EGDE_NONE || window->autohide_status != DISABLED)
- return FALSE;
- /* always set struts on the following condition */
- if ((window->horizontal && y == 0) || (!window->horizontal && x == 0))
- return TRUE;
+static void
+panel_window_screen_layout_changed (GdkScreen *screen,
+ PanelWindow *window)
+{
+ GdkRectangle a, b;
+ gint monitor_num, n_monitors, n;
+ gint dest_x, dest_y;
+ gint dest_w, dest_h;
+ gchar *name;
+ StrutsEgde struts_edge;
+ gboolean force_struts_update = FALSE;
+/* TODO test how many times this function is called */
+ panel_return_if_fail (PANEL_IS_WINDOW (window));
+ panel_return_if_fail (GDK_IS_SCREEN (screen));
+ panel_return_if_fail (window->screen == screen);
- /* get panel screen */
- screen = gtk_window_get_screen (GTK_WINDOW (window));
+ /* update the struts edge of this window and check if we need to force
+ * a struts update (ie. remove struts that are currently set) */
+ struts_edge = panel_window_screen_struts_edge (window);
+ if (window->struts_edge != struts_edge && struts_edge == STRUTS_EDGE_NONE)
+ force_struts_update = TRUE;
+ window->struts_edge = struts_edge;
/* get the number of monitors */
n_monitors = gdk_screen_get_n_monitors (screen);
+ panel_return_if_fail (n_monitors > 0);
- if (G_LIKELY (n_monitors == 1))
+ if (window->span_monitors
+ || (n_monitors == 1 && window->output_name == NULL))
{
- /* don't set the struts when we're not at a screen edge */
- if ((window->horizontal && y + height != gdk_screen_get_height (screen))
- || (!window->horizontal && x + width != gdk_screen_get_width (screen)))
- return FALSE;
+ /* get the screen geometry */
+ a.x = a.y = 0;
+ a.width = gdk_screen_get_width (screen);
+ a.height = gdk_screen_get_height (screen);
+ panel_return_if_fail (a.width > 0 && a.height > 0);
}
else
{
- for (i = 0; i < n_monitors; i++)
+ if (window->output_name == NULL)
{
- /* get the monitor geometry */
- gdk_screen_get_monitor_geometry (screen, i, &geometry);
-
- if (window->horizontal
- && x >= geometry.x
- && x + width <= geometry.x + geometry.width
- && y + height < geometry.y + geometry.height)
- return FALSE;
-
- if (window->horizontal == FALSE
- && y >= geometry.y
- && y + height <= geometry.y + geometry.height
- && x + width < geometry.x + geometry.width)
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
+ normal_monitor_positioning:
+ /* get the monitor geometry based on the panel position */
+ monitor_num = gdk_screen_get_monitor_at_point (screen, window->base_x,
+ window->base_y);
+ gdk_screen_get_monitor_geometry (screen, monitor_num, &a);
+ panel_return_if_fail (a.width > 0 && a.height > 0);
+ }
+ else
+ {
+ /* check if the monitor of this panel is present */
+ for (n = 0, monitor_num = -1; n < n_monitors && monitor_num == -1; n++)
+ {
+ name = gdk_screen_get_monitor_plug_name (screen, n);
-static void
-panel_window_struts_update (PanelWindow *window,
- gint x,
- gint y,
- gint width,
- gint height)
-{
- gulong struts[N_STRUTS] = { 0, };
- GdkScreen *screen;
- guint i;
- gboolean update_struts = FALSE;
+ /* check if this driver supports output names */
+ if (G_UNLIKELY (name == NULL))
+ {
+ /* send a warnings why this went wrong */
+ g_critical ("An output is set on the panel window (%s), "
+ "but it looks like the driver does not "
+ "support output names. Falling back to normal "
+ "monitor positioning, you have to set the output "
+ "again in the preferences to activate this feature.",
+ window->output_name);
+
+ /* cleanup */
+ g_free (window->output_name);
+ window->output_name = NULL;
+
+ /* fall back to normal positioning */
+ goto normal_monitor_positioning;
+ }
- panel_return_if_fail (PANEL_IS_WINDOW (window));
- panel_return_if_fail (GDK_IS_WINDOW (GTK_WIDGET (window)->window));
- panel_return_if_fail (N_STRUTS == 12);
- panel_return_if_fail (cardinal_atom != GDK_NONE);
- panel_return_if_fail (net_wm_strut_atom != GDK_NONE);
- panel_return_if_fail (net_wm_strut_partial_atom != GDK_NONE);
+ /* check if this is the monitor we're looking for */
+ if (strcmp (window->output_name, name) == 0)
+ {
+ /* store the monitor number, get the geometry */
+ monitor_num = n;
+ gdk_screen_get_monitor_geometry (screen, n, &a);
+ panel_return_if_fail (a.width > 0 && a.height > 0);
+ }
- if (G_UNLIKELY (window->struts_possible == -1))
- {
- /* check whether struts are possible, skip to apply if not */
- window->struts_possible = panel_window_struts_are_possible (window, x, y, width, height);
+ /* cleanup */
+ g_free (name);
+ }
- /* struts are not possible, reset them only this time */
- if (window->struts_possible == 0)
- goto reset_only;
- }
+ /* check if a monitor was found */
+ if (monitor_num == -1)
+ {
+ if (GTK_WIDGET_VISIBLE (window))
+ gtk_widget_hide (GTK_WIDGET (window));
+ return;
+ }
+ else if (!GTK_WIDGET_VISIBLE (window))
+ {
+ gtk_widget_show (GTK_WIDGET (window));
+ }
+ }
- /* get the panel window screen */
- screen = gtk_window_get_screen (GTK_WINDOW (window));
+ /* don't do the check if we're not setting struts anyways */
+ if (window->struts_edge == STRUTS_EDGE_NONE)
+ goto done;
- if (window->horizontal)
- {
- if (snap_edge_is_top (window->snap_edge))
- {
- /* the window is snapped on the top screen edge */
- struts[STRUT_TOP] = y + height;
- struts[STRUT_TOP_START_X] = x;
- struts[STRUT_TOP_END_X] = x + width;
- }
- else if (snap_edge_is_bottom (window->snap_edge))
- {
- /* the window is snapped on the bottom screen edge */
- struts[STRUT_BOTTOM] = gdk_screen_get_height (screen) - y;
- struts[STRUT_BOTTOM_START_X] = x;
- struts[STRUT_BOTTOM_END_X] = x + width;
- }
- }
- else /* vertical */
- {
- if (snap_edge_is_left (window->snap_edge))
+ /* traverse the monitors */
+ for (n = 0; n < n_monitors; n++)
{
- /* the window is snapped on the left screen edge */
- struts[STRUT_LEFT] = x + width;
- struts[STRUT_LEFT_START_Y] = y;
- struts[STRUT_LEFT_END_Y] = y + height;
- }
- else if (snap_edge_is_right (window->snap_edge))
- {
- /* the window is snapped on the right screen edge */
- struts[STRUT_RIGHT] = gdk_screen_get_width (screen) - x;
- struts[STRUT_RIGHT_START_Y] = y;
- struts[STRUT_RIGHT_END_Y] = y + height;
- }
- }
+ /* stop if another window prevent us from settings struts */
+ if (window->struts_edge == STRUTS_EDGE_NONE)
+ break;
- reset_only:
+ /* skip the active monitor */
+ if (monitor_num == n)
+ continue;
- for (i = 0; i < N_STRUTS; i++)
- {
- /* check if we need to update */
- if (struts[i] != window->struts[i])
- update_struts = TRUE;
+ /* get other monitor geometry */
+ gdk_screen_get_monitor_geometry (screen, n, &b);
- /* store new strut */
- window->struts[i] = struts[i];
+ /* check if this monitor prevents us from setting struts */
+ if ((window->struts_edge == STRUTS_EDGE_LEFT && b.x < a.x)
+ || (window->struts_edge == STRUTS_EDGE_RIGHT
+ && b.x + b.width > a.x + a.width))
+ {
+ dest_y = MAX (a.y, b.y);
+ dest_h = MIN (a.y + a.height, b.y + b.height) - dest_y;
+ if (dest_h > 0)
+ window->struts_edge = STRUTS_EDGE_NONE;
+ }
+ else if ((window->struts_edge == STRUTS_EDGE_TOP && b.y < a.y)
+ || (window->struts_edge == STRUTS_EDGE_BOTTOM
+ && b.y + b.height > a.y + a.height))
+ {
+ dest_x = MAX (a.x, b.x);
+ dest_w = MIN (a.x + a.width, b.x + b.width) - dest_x;
+ if (dest_w > 0)
+ window->struts_edge = STRUTS_EDGE_NONE;
+ }
+ }
}
- if (update_struts)
- {
- /* don't crash on x errors */
- gdk_error_trap_push ();
-
- /* set the wm strut partial */
- gdk_property_change (GTK_WIDGET (window)->window, net_wm_strut_partial_atom,
- cardinal_atom, 32, GDK_PROP_MODE_REPLACE, (guchar *) &struts, 12);
+done:
+ /* set the new working area of the panel */
+ window->area = a;
- /* set the wm strut (old window managers) */
- /* gdk_property_change (GTK_WIDGET (window)->window, net_wm_strut_atom,
- * cardinal_atom, 32, GDK_PROP_MODE_REPLACE, (guchar *) &struts, 4);
- */
+ /* update panel borders */
+ panel_window_screen_update_borders (window);
- /* release the trap push */
- gdk_error_trap_pop ();
+ /* queue a resize */
+ gtk_widget_queue_resize (GTK_WIDGET (window));
-#if 0
- gint n = -1;
- const gchar *names1[] = { "left", "right", "top", "bottom" };
- const gchar *names2[] = { "y", "y", "x", "x" };
-
- if (struts[STRUT_LEFT] != 0)
- n = STRUT_LEFT;
- else if (struts[STRUT_RIGHT] != 0)
- n = STRUT_RIGHT;
- else if (struts[STRUT_TOP] != 0)
- n = STRUT_TOP;
- else if (struts[STRUT_BOTTOM] != 0)
- n = STRUT_BOTTOM;
-
- if (n == -1)
- g_print ("Struts: All set to zero\n");
- else
- g_print ("Struts: %s = %ld, start_%s = %ld, end_%s = %ld\n", names1[n],
- struts[n], names2[n], struts[4 + n * 2], names2[n], struts[5 + n * 2]);
-#endif
- }
+ /* update the struts if needed, ie. we need to reset the struts */
+ if (force_struts_update)
+ panel_window_screen_struts_set (window);
}
-static void
-panel_window_set_colormap (PanelWindow *window)
+static gboolean
+panel_window_autohide_timeout (gpointer user_data)
{
- GdkColormap *colormap = NULL;
- GdkScreen *screen;
- gboolean restore;
- GtkWidget *widget = GTK_WIDGET (window);
- gint root_x, root_y;
-
- panel_return_if_fail (PANEL_IS_WINDOW (window));
-
- /* whether the widget was previously visible */
- restore = GTK_WIDGET_REALIZED (widget);
-
- /* unrealize the window if needed */
- if (restore)
- {
- /* store the window position */
- gtk_window_get_position (GTK_WINDOW (window), &root_x, &root_y);
-
- /* reset the struts */
- if (window->struts_possible == 1)
- panel_window_struts_update (window, 0, 0, 0, 0);
-
- /* hide the widget */
- gtk_widget_hide (widget);
- gtk_widget_unrealize (widget);
- }
-
- /* set bool */
- window->is_composited = gtk_widget_is_composited (widget);
-
- /* get the screen */
- screen = gtk_window_get_screen (GTK_WINDOW (window));
-
- /* try to get the rgba colormap */
- if (window->is_composited)
- colormap = gdk_screen_get_rgba_colormap (screen);
-
- /* get the default colormap */
- if (colormap == NULL)
- {
- colormap = gdk_screen_get_rgb_colormap (screen);
- window->is_composited = FALSE;
- }
+ PanelWindow *window = PANEL_WINDOW (user_data);
- /* set the colormap */
- if (colormap)
- gtk_widget_set_colormap (widget, colormap);
+ panel_return_val_if_fail (window->autohide_state != AUTOHIDE_DISABLED, FALSE);
- /* restore the window */
- if (restore)
- {
- /* restore the position */
- gtk_window_move (GTK_WINDOW (window), root_x, root_y);
+ /* update the status */
+ if (window->autohide_state == AUTOHIDE_POPDOWN
+ || window->autohide_state == AUTOHIDE_POPDOWN_SLOW)
+ window->autohide_state = AUTOHIDE_HIDDEN;
+ else if (window->autohide_state == AUTOHIDE_POPUP)
+ window->autohide_state = AUTOHIDE_VISIBLE;
- /* show the widget again */
- gtk_widget_realize (widget);
- gtk_widget_show (widget);
+ /* resize the panel */
+ gtk_widget_queue_resize (GTK_WIDGET (window));
- /* set the struts again */
- if (window->struts_possible == 1)
- panel_window_struts_update (window, root_x, root_y, widget->allocation.width, widget->allocation.height);
- }
+ return FALSE;
}
static void
-panel_window_get_position (PanelWindow *window,
- gint *root_x,
- gint *root_y)
+panel_window_autohide_timeout_destroy (gpointer user_data)
{
- panel_return_if_fail (PANEL_IS_WINDOW (window));
-
- /* get the window position of the visible window */
- if (G_UNLIKELY (window->autohide_window
- && (window->autohide_status == HIDDEN || window->autohide_status == POPUP_QUEUED)))
- gtk_window_get_position (GTK_WINDOW (window->autohide_window), root_x, root_y);
- else
- gtk_window_get_position (GTK_WINDOW (window), root_x, root_y);
+ PANEL_WINDOW (user_data)->autohide_timeout_id = 0;
}
static void
-panel_window_set_borders (PanelWindow *window)
+panel_window_autohide_queue (PanelWindow *window,
+ AutohideState new_state)
{
- PanelWindowBorders borders = 0;
+ guint delay;
panel_return_if_fail (PANEL_IS_WINDOW (window));
- if (window->horizontal)
- {
- /* only attempt to show the side borders if we're not filling the area */
- if (window->length < 1.00)
- {
- /* show the left border if we don't snap to the left */
- if (snap_edge_is_left (window->snap_edge) == FALSE)
- PANEL_SET_FLAG (borders, PANEL_BORDER_LEFT);
+ /* stop pending timeout */
+ if (window->autohide_timeout_id != 0)
+ g_source_remove (window->autohide_timeout_id);
- /* show the right border if we don't snap to the right */
- if (snap_edge_is_right (window->snap_edge) == FALSE)
- PANEL_SET_FLAG (borders, PANEL_BORDER_RIGHT);
- }
+ /* set new autohide state */
+ window->autohide_state = new_state;
- /* show the top border if not snapped to the top */
- if (snap_edge_is_top (window->snap_edge) == FALSE)
- PANEL_SET_FLAG (borders, PANEL_BORDER_TOP);
+ /* force a layout update to disable struts */
+ if (window->struts_edge != STRUTS_EDGE_NONE
+ || window->snap_position != SNAP_POSITION_NONE)
+ panel_window_screen_layout_changed (window->screen, window);
- /* show the bottom border if not snapped to the bottom */
- if (snap_edge_is_bottom (window->snap_edge) == FALSE)
- PANEL_SET_FLAG (borders, PANEL_BORDER_BOTTOM);
+ if (new_state == AUTOHIDE_DISABLED)
+ {
+ /* queue a resize to make sure the panel is visible */
+ gtk_widget_queue_resize (GTK_WIDGET (window));
}
else
{
- /* only attempt to show the top borders if we're not filling the area */
- if (window->length < 1.00)
- {
- /* show the top border if we don't snap to the top */
- if (snap_edge_is_top (window->snap_edge) == FALSE)
- PANEL_SET_FLAG (borders, PANEL_BORDER_TOP);
+ /* timeout delay */
+ if (new_state == AUTOHIDE_POPDOWN)
+ delay = POPDOWN_DELAY;
+ else if (new_state == AUTOHIDE_POPDOWN_SLOW)
+ delay = POPDOWN_DELAY * 4;
+ else
+ delay = POPUP_DELAY;
- /* show the bottom border if we don't snap to the bottom */
- if (snap_edge_is_bottom (window->snap_edge) == FALSE)
- PANEL_SET_FLAG (borders, PANEL_BORDER_BOTTOM);
- }
+ /* start a new timeout to hide the panel */
+ window->autohide_timeout_id =
+ g_timeout_add_full (G_PRIORITY_LOW, delay,
+ panel_window_autohide_timeout, window,
+ panel_window_autohide_timeout_destroy);
+ }
+}
- /* show the left border if not snapped to the left */
- if (snap_edge_is_left (window->snap_edge) == FALSE)
- PANEL_SET_FLAG (borders, PANEL_BORDER_LEFT);
- /* show the right border if not snapped to the right */
- if (snap_edge_is_right (window->snap_edge) == FALSE)
- PANEL_SET_FLAG (borders, PANEL_BORDER_RIGHT);
- }
- /* set the new value and queue a resize if needed */
- if (window->borders != borders)
+static gboolean
+panel_window_autohide_event (GtkWidget *widget,
+ GdkEventCrossing *event,
+ PanelWindow *window)
+{
+ gboolean enter = !!(event->type == GDK_ENTER_NOTIFY);
+
+ panel_return_val_if_fail (PANEL_IS_WINDOW (window), FALSE);
+ panel_return_val_if_fail (window->autohide_window == widget, FALSE);
+
+ if (enter)
+ {
+ /* queue a popup */
+ panel_window_autohide_queue (window, AUTOHIDE_POPUP);
+ }
+ else
{
- /* set the new value */
- window->borders = borders;
+ /* we left the window before it was hidden, stop the queue */
+ if (window->autohide_timeout_id != 0)
+ g_source_remove (window->autohide_timeout_id);
- /* queue a resize */
- gtk_widget_queue_resize (GTK_WIDGET (window));
+ /* update the status */
+ if (window->autohide_state == AUTOHIDE_POPUP)
+ window->autohide_state = AUTOHIDE_HIDDEN;
}
+
+ return FALSE;
}
@@ -1984,40 +1722,53 @@ static void
panel_window_set_autohide (PanelWindow *window,
gboolean autohide)
{
- AutohideStatus status;
+ GtkWidget *popup;
+ guint i;
+ const gchar *properties[] = { "enter-opacity", "leave-opacity",
+ "background-alpha", "borders" };
panel_return_if_fail (PANEL_IS_WINDOW (window));
- if (G_LIKELY ((window->autohide_status != DISABLED) != autohide))
- {
- /* determ whether struts are possible on the next resize */
- window->struts_possible = -1;
-
- if (autohide)
- {
- /* create popup window if needed */
- if (window->autohide_window == NULL)
- window->autohide_window = panel_window_autohide_window (window);
-
- /* get the correct status */
- status = window->autohide_block == 0 ? POPDOWN_QUEUED_SLOW : BLOCKED;
-
- /* queue a popdown */
- panel_window_autohide_queue (window, status);
- }
- else
- {
- /* disable autohiding */
- panel_window_autohide_queue (window, DISABLED);
+ if ((window->autohide_state != AUTOHIDE_DISABLED) == autohide)
+ return;
- /* destroy the autohide window */
- if (window->autohide_window)
- {
- gtk_widget_destroy (window->autohide_window);
- window->autohide_window = NULL;
- }
- }
+ if (autohide)
+ {
+ /* create the window */
+ panel_return_if_fail (window->autohide_window == NULL);
+ popup = g_object_new (PANEL_TYPE_BASE_WINDOW, "type",
+ GTK_WINDOW_POPUP, NULL);
+
+ /* move the window offscreen */
+ panel_base_window_move_resize (PANEL_BASE_WINDOW (popup),
+ -9999, -9999, 3, 3);
+
+ /* bind some properties to sync the two windows */
+ for (i = 0; i < G_N_ELEMENTS (properties); i++)
+ exo_binding_new (G_OBJECT (window), properties[i],
+ G_OBJECT (popup), properties[i]);
+
+ /* signals for pointer enter/leave events */
+ g_signal_connect (G_OBJECT (popup), "enter-notify-event",
+ G_CALLBACK (panel_window_autohide_event), window);
+ g_signal_connect (G_OBJECT (popup), "leave-notify-event",
+ G_CALLBACK (panel_window_autohide_event), window);
+
+ /* show the window */
+ window->autohide_window = popup;
+ gtk_widget_show (popup);
}
+ else if (window->autohide_window != NULL)
+ {
+ /* destroy the autohide window */
+ panel_return_if_fail (GTK_IS_WINDOW (window->autohide_window));
+ gtk_widget_destroy (window->autohide_window);
+ window->autohide_window = NULL;
+ }
+
+ /* start or stop autohiding */
+ panel_window_autohide_queue (window,
+ autohide ? AUTOHIDE_POPDOWN_SLOW : AUTOHIDE_DISABLED);
}
@@ -2051,7 +1802,8 @@ panel_window_menu_deactivate (GtkMenu *menu,
static void
-panel_window_menu_popup (PanelWindow *window)
+panel_window_menu_popup (PanelWindow *window,
+ guint32 event_time)
{
GtkWidget *menu;
GtkWidget *item;
@@ -2067,10 +1819,11 @@ panel_window_menu_popup (PanelWindow *window)
/* sink the menu and add unref on deactivate */
g_object_ref_sink (G_OBJECT (menu));
- g_signal_connect (G_OBJECT (menu), "deactivate", G_CALLBACK (panel_window_menu_deactivate), window);
+ g_signal_connect (G_OBJECT (menu), "deactivate",
+ G_CALLBACK (panel_window_menu_deactivate), window);
/* label */
- item = gtk_image_menu_item_new_with_label (_("Xfce Panel"));
+ item = gtk_image_menu_item_new_with_label ("Xfce Panel");
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_set_sensitive (item, FALSE);
gtk_widget_show (item);
@@ -2082,7 +1835,8 @@ panel_window_menu_popup (PanelWindow *window)
/* add new items */
item = gtk_image_menu_item_new_with_mnemonic (_("Add _New Items..."));
- g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (panel_item_dialog_show), window);
+ g_signal_connect_swapped (G_OBJECT (item), "activate",
+ G_CALLBACK (panel_item_dialog_show), window);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show (item);
@@ -2092,7 +1846,8 @@ panel_window_menu_popup (PanelWindow *window)
/* customize panel */
item = gtk_image_menu_item_new_with_mnemonic (_("Panel Pr_eferences..."));
- g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (panel_preferences_dialog_show), window);
+ g_signal_connect_swapped (G_OBJECT (item), "activate",
+ G_CALLBACK (panel_preferences_dialog_show), window);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show (item);
@@ -2107,13 +1862,15 @@ panel_window_menu_popup (PanelWindow *window)
/* quit item */
item = gtk_image_menu_item_new_from_stock (GTK_STOCK_QUIT, NULL);
- g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (panel_window_menu_quit), GUINT_TO_POINTER (0));
+ g_signal_connect_swapped (G_OBJECT (item), "activate",
+ G_CALLBACK (panel_window_menu_quit), GUINT_TO_POINTER (0));
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show (item);
/* restart item */
item = gtk_image_menu_item_new_with_mnemonic (_("_Restart"));
- g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (panel_window_menu_quit), GUINT_TO_POINTER (1));
+ g_signal_connect_swapped (G_OBJECT (item), "activate",
+ G_CALLBACK (panel_window_menu_quit), GUINT_TO_POINTER (1));
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show (item);
@@ -2128,27 +1885,27 @@ panel_window_menu_popup (PanelWindow *window)
/* about item */
item = gtk_image_menu_item_new_from_stock (GTK_STOCK_ABOUT, NULL);
- g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (panel_dialogs_show_about), NULL);
+ g_signal_connect (G_OBJECT (item), "activate",
+ G_CALLBACK (panel_dialogs_show_about), NULL);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show (item);
/* popup the menu */
- gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
- 0, gtk_get_current_event_time ());
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, event_time);
}
static void
-panel_window_set_plugin_background_alpha (GtkWidget *widget,
- gpointer user_data)
+panel_window_set_plugin_orientation (GtkWidget *widget,
+ gpointer user_data)
{
panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (widget));
+ panel_return_if_fail (PANEL_IS_WINDOW (user_data));
- /* we only have to send the alpha to external plugins */
- if (PANEL_IS_PLUGIN_EXTERNAL (widget))
- panel_plugin_external_set_background_alpha (PANEL_PLUGIN_EXTERNAL (widget),
- GPOINTER_TO_UINT (user_data));
+ xfce_panel_plugin_provider_set_orientation (XFCE_PANEL_PLUGIN_PROVIDER (widget),
+ PANEL_WINDOW (user_data)->horizontal ? GTK_ORIENTATION_HORIZONTAL:
+ GTK_ORIENTATION_VERTICAL);
}
@@ -2158,60 +1915,110 @@ panel_window_set_plugin_size (GtkWidget *widget,
gpointer user_data)
{
panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (widget));
+ panel_return_if_fail (PANEL_IS_WINDOW (user_data));
- /* set the new plugin size */
xfce_panel_plugin_provider_set_size (XFCE_PANEL_PLUGIN_PROVIDER (widget),
- GPOINTER_TO_INT (user_data));
+ PANEL_WINDOW (user_data)->size);
}
static void
-panel_window_set_plugin_orientation (GtkWidget *widget,
- gpointer user_data)
+panel_window_set_screen_position (GtkWidget *widget,
+ gpointer user_data)
{
+ PanelWindow *window = PANEL_WINDOW (user_data);
+ XfceScreenPosition position;
+
panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (widget));
+ panel_return_if_fail (PANEL_IS_WINDOW (user_data));
- /* set the new plugin orientation */
- xfce_panel_plugin_provider_set_orientation (XFCE_PANEL_PLUGIN_PROVIDER (widget),
- GPOINTER_TO_INT (user_data));
+ switch (window->snap_position)
+ {
+ case SNAP_POSITION_NONE:
+ position = window->horizontal ? XFCE_SCREEN_POSITION_FLOATING_H :
+ XFCE_SCREEN_POSITION_FLOATING_V;
+ break;
+
+ case SNAP_POSITION_NW:
+ position = window->horizontal ? XFCE_SCREEN_POSITION_NW_H :
+ XFCE_SCREEN_POSITION_NW_V;
+ break;
+
+ case SNAP_POSITION_NE:
+ position = window->horizontal ? XFCE_SCREEN_POSITION_NE_H :
+ XFCE_SCREEN_POSITION_NE_V;
+ break;
+
+ case SNAP_POSITION_SW:
+ position = window->horizontal ? XFCE_SCREEN_POSITION_SW_H :
+ XFCE_SCREEN_POSITION_SW_V;
+ break;
+
+ case SNAP_POSITION_SE:
+ position = window->horizontal ? XFCE_SCREEN_POSITION_SE_H :
+ XFCE_SCREEN_POSITION_SE_V;
+ break;
+
+ case SNAP_POSITION_W:
+ case SNAP_POSITION_WC:
+ position = window->horizontal ? XFCE_SCREEN_POSITION_FLOATING_H :
+ XFCE_SCREEN_POSITION_W;
+ break;
+
+ case SNAP_POSITION_E:
+ case SNAP_POSITION_EC:
+ position = window->horizontal ? XFCE_SCREEN_POSITION_FLOATING_H :
+ XFCE_SCREEN_POSITION_E;
+ break;
+
+ case SNAP_POSITION_S:
+ case SNAP_POSITION_SC:
+ position = window->horizontal ? XFCE_SCREEN_POSITION_S :
+ XFCE_SCREEN_POSITION_FLOATING_V;
+ break;
+
+ case SNAP_POSITION_N:
+ case SNAP_POSITION_NC:
+ position = window->horizontal ? XFCE_SCREEN_POSITION_N :
+ XFCE_SCREEN_POSITION_FLOATING_V;
+ break;
+
+ default:
+ panel_assert_not_reached ();
+ break;
+ }
+
+ xfce_panel_plugin_provider_set_screen_position (XFCE_PANEL_PLUGIN_PROVIDER (widget),
+ position);
}
-gboolean
-panel_window_is_composited (PanelWindow *window)
+GtkWidget *
+panel_window_new (void)
{
- panel_return_val_if_fail (PANEL_IS_WINDOW (window), FALSE);
-
- return window->is_composited;
+ return g_object_new (PANEL_TYPE_WINDOW,
+ "type", GTK_WINDOW_TOPLEVEL,
+ NULL);
}
void
-panel_window_set_active_panel (PanelWindow *window,
- gboolean active)
+panel_window_set_povider_info (PanelWindow *window,
+ GtkWidget *provider)
{
panel_return_if_fail (PANEL_IS_WINDOW (window));
+ panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
- if (G_UNLIKELY ((window->active_timeout_id != 0) != active))
- {
- /* set new value */
- if (active)
- {
- window->active_timeout_id = g_timeout_add_seconds (1,
- (GSourceFunc) gtk_widget_queue_draw, window);
- }
- else
- {
- g_source_remove (window->active_timeout_id);
- window->active_timeout_id = 0;
- }
+ panel_window_set_plugin_size (provider, window);
+ panel_window_set_plugin_orientation (provider, window);
+ panel_window_set_screen_position (provider, window);
- /* queue a redraw */
- gtk_widget_queue_draw (GTK_WIDGET (window));
- }
+ if (PANEL_IS_PLUGIN_EXTERNAL (provider))
+ panel_plugin_external_set_background_alpha (PANEL_PLUGIN_EXTERNAL (provider),
+ rint (PANEL_BASE_WINDOW (window)->background_alpha * 100.00));
}
@@ -2220,14 +2027,6 @@ void
panel_window_freeze_autohide (PanelWindow *window)
{
panel_return_if_fail (PANEL_IS_WINDOW (window));
- panel_return_if_fail (window->autohide_block >= 0);
-
- /* increase autohide block counter */
- window->autohide_block++;
-
- /* block autohide */
- if (window->autohide_block == 1 && window->autohide_status != DISABLED)
- panel_window_autohide_queue (window, BLOCKED);
}
@@ -2236,12 +2035,4 @@ void
panel_window_thaw_autohide (PanelWindow *window)
{
panel_return_if_fail (PANEL_IS_WINDOW (window));
- panel_return_if_fail (window->autohide_block > 0);
-
- /* decrease autohide block counter */
- window->autohide_block--;
-
- /* queue an autohide when needed */
- if (window->autohide_block == 0 && window->autohide_status != DISABLED)
- panel_window_autohide_queue (window, POPDOWN_QUEUED);
}
diff --git a/panel/panel-window.h b/panel/panel-window.h
index 68990b8..21dfe68 100644
--- a/panel/panel-window.h
+++ b/panel/panel-window.h
@@ -1,6 +1,6 @@
/* $Id$ */
/*
- * Copyright (C) 2008-2009 Nick Schermer <nick at xfce.org>
+ * Copyright (C) 2008 Nick Schermer <nick at xfce.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,10 +24,8 @@
G_BEGIN_DECLS
-typedef struct _PanelWindowClass PanelWindowClass;
-typedef struct _PanelWindow PanelWindow;
-typedef enum _PanelWindowSnapEdge PanelWindowSnapEdge;
-typedef enum _PanelWindowBorders PanelWindowBorders;
+typedef struct _PanelWindowClass PanelWindowClass;
+typedef struct _PanelWindow PanelWindow;
#define PANEL_TYPE_WINDOW (panel_window_get_type ())
#define PANEL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_WINDOW, PanelWindow))
@@ -36,59 +34,16 @@ typedef enum _PanelWindowBorders PanelWindowBorders;
#define PANEL_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_WINDOW))
#define PANEL_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANEL_TYPE_WINDOW, PanelWindowClass))
-#define snap_edge_is_top(snap_edge) (snap_edge == PANEL_SNAP_EGDE_NE || snap_edge == PANEL_SNAP_EGDE_NW || \
- snap_edge == PANEL_SNAP_EGDE_NC || snap_edge == PANEL_SNAP_EGDE_N)
-#define snap_edge_is_bottom(snap_edge) (snap_edge == PANEL_SNAP_EGDE_SE || snap_edge == PANEL_SNAP_EGDE_SW || \
- snap_edge == PANEL_SNAP_EGDE_SC || snap_edge == PANEL_SNAP_EGDE_S)
-#define snap_edge_is_left(snap_edge) (snap_edge >= PANEL_SNAP_EGDE_W && snap_edge <= PANEL_SNAP_EGDE_SW)
-#define snap_edge_is_right(snap_edge) (snap_edge >= PANEL_SNAP_EGDE_E && snap_edge <= PANEL_SNAP_EGDE_SE)
+GType panel_window_get_type (void) G_GNUC_CONST;
-#define PANEL_BORDER_ALL (PANEL_BORDER_LEFT | PANEL_BORDER_RIGHT | PANEL_BORDER_TOP | PANEL_BORDER_BOTTOM)
+GtkWidget *panel_window_new (void);
+void panel_window_set_povider_info (PanelWindow *window,
+ GtkWidget *provider);
-enum _PanelWindowSnapEdge
-{
- /* no snapping */
- PANEL_SNAP_EGDE_NONE, /* 0 no snapping */
+void panel_window_freeze_autohide (PanelWindow *window);
- /* right edge */
- PANEL_SNAP_EGDE_E, /* 1 right */
- PANEL_SNAP_EGDE_NE, /* 2 top right */
- PANEL_SNAP_EGDE_EC, /* 3 right center */
- PANEL_SNAP_EGDE_SE, /* 4 bottom right */
-
- /* left edge */
- PANEL_SNAP_EGDE_W, /* 5 left */
- PANEL_SNAP_EGDE_NW, /* 6 top left */
- PANEL_SNAP_EGDE_WC, /* 7 left center */
- PANEL_SNAP_EGDE_SW, /* 8 bottom left */
-
- /* top and bottom */
- PANEL_SNAP_EGDE_NC, /* 9 top center */
- PANEL_SNAP_EGDE_SC, /* 10 bottom center */
- PANEL_SNAP_EGDE_N, /* 11 top */
- PANEL_SNAP_EGDE_S, /* 12 bottom */
-};
-
-enum _PanelWindowBorders
-{
- PANEL_BORDER_LEFT = 1 << 0,
- PANEL_BORDER_RIGHT = 1 << 1,
- PANEL_BORDER_TOP = 1 << 2,
- PANEL_BORDER_BOTTOM = 1 << 3,
-};
-
-
-GType panel_window_get_type (void) G_GNUC_CONST;
-
-gboolean panel_window_is_composited (PanelWindow *window);
-
-void panel_window_set_active_panel (PanelWindow *window,
- gboolean selected);
-
-void panel_window_freeze_autohide (PanelWindow *window);
-
-void panel_window_thaw_autohide (PanelWindow *window);
+void panel_window_thaw_autohide (PanelWindow *window);
G_END_DECLS
More information about the Xfce4-commits
mailing list