summaryrefslogtreecommitdiff
path: root/mate-window-picker-applet/task-title.c
diff options
context:
space:
mode:
Diffstat (limited to 'mate-window-picker-applet/task-title.c')
-rw-r--r--mate-window-picker-applet/task-title.c528
1 files changed, 528 insertions, 0 deletions
diff --git a/mate-window-picker-applet/task-title.c b/mate-window-picker-applet/task-title.c
new file mode 100644
index 0000000..4795559
--- /dev/null
+++ b/mate-window-picker-applet/task-title.c
@@ -0,0 +1,528 @@
+/*
+ * Copyright (C) 2008 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by Neil Jagdish Patel <[email protected]>
+ *
+ */
+
+#include "task-title.h"
+
+#include <libmatewnck/libmatewnck.h>
+#include <mate-panel-applet.h>
+#include <mate-panel-applet-mateconf.h>
+
+#include <mateconf/mateconf.h>
+#include <mateconf/mateconf-client.h>
+
+#include "task-list.h"
+
+G_DEFINE_TYPE (TaskTitle, task_title, GTK_TYPE_EVENT_BOX);
+
+#define TASK_TITLE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\
+ TASK_TYPE_TITLE, \
+ TaskTitlePrivate))
+
+#define LOGOUT "mate-session-save --kill --gui"
+#define SHOW_HOME_TITLE_KEY "/apps/window-picker-applet/show_home_title"
+
+struct _TaskTitlePrivate
+{
+ MatewnckScreen *screen;
+ MatewnckWindow *window;
+ GtkWidget *align;
+ GtkWidget *box;
+ GtkWidget *label;
+ GtkWidget *button;
+ GtkWidget *button_image;
+ GdkPixbuf *quit_icon;
+
+ gboolean show_home_title;
+ gboolean mouse_in_close_button;
+};
+
+static void disconnect_window (TaskTitle *title);
+
+static gboolean
+on_close_clicked (GtkButton *button,
+ GdkEventButton *event,
+ TaskTitle *title)
+{
+ TaskTitlePrivate *priv;
+ MatewnckWindow *window;
+
+ g_return_val_if_fail (TASK_IS_TITLE (title), FALSE);
+ priv = title->priv;
+
+ if (event->button != 1 || !priv->mouse_in_close_button)
+ return FALSE;
+
+ window = matewnck_screen_get_active_window (priv->screen);
+
+ if (!MATEWNCK_IS_WINDOW (window)
+ || matewnck_window_get_window_type (window) == MATEWNCK_WINDOW_DESKTOP)
+ {
+ gdk_spawn_command_line_on_screen (gdk_screen_get_default (),
+ LOGOUT, NULL);
+ }
+ else
+ {
+ if (priv->window == window)
+ disconnect_window (title);
+ matewnck_window_close (window, GDK_CURRENT_TIME);
+ }
+ gtk_widget_queue_draw (GTK_WIDGET (title));
+
+ return TRUE;
+}
+
+static gboolean
+on_enter_notify (GtkWidget *widget,
+ GdkEventCrossing *event,
+ TaskTitle *title)
+{
+ g_return_val_if_fail (TASK_IS_TITLE (title), FALSE);
+
+ title->priv->mouse_in_close_button = TRUE;
+ gtk_widget_queue_draw (widget);
+
+ return FALSE;
+}
+
+static gboolean
+on_leave_notify (GtkWidget *widget,
+ GdkEventCrossing *event,
+ TaskTitle *title)
+{
+ g_return_val_if_fail (TASK_IS_TITLE (title), FALSE);
+
+ title->priv->mouse_in_close_button = FALSE;
+ gtk_widget_queue_draw (widget);
+
+ return FALSE;
+}
+
+static gboolean
+on_button_expose (GtkWidget *widget,
+ GdkEventExpose *event,
+ TaskTitle *title)
+{
+ g_return_val_if_fail (TASK_IS_TITLE (title), FALSE);
+
+ TaskTitlePrivate *priv;
+ priv = title->priv;
+
+ if (priv->mouse_in_close_button)
+ {
+ GtkStyle *style = gtk_widget_get_style (widget);
+ gtk_paint_box (style,
+ event->window,
+ GTK_STATE_PRELIGHT,
+ GTK_SHADOW_NONE,
+ NULL,
+ NULL,
+ NULL,
+ event->area.x,
+ event->area.y + 2,
+ event->area.width,
+ event->area.height - 4);
+ }
+ return FALSE;
+}
+
+static void
+on_name_changed (MatewnckWindow *window, TaskTitle *title)
+{
+ TaskTitlePrivate *priv;
+
+ g_return_if_fail (TASK_IS_TITLE (title));
+ g_return_if_fail (MATEWNCK_IS_WINDOW (window));
+
+ priv = title->priv;
+ if (priv->window != window)
+ return;
+
+ gtk_label_set_text (GTK_LABEL (title->priv->label),
+ matewnck_window_get_name (window));
+ gtk_widget_set_tooltip_text (GTK_WIDGET (title),
+ matewnck_window_get_name (window));
+ gtk_widget_queue_draw (GTK_WIDGET (title));
+}
+
+
+static void
+on_icon_changed (MatewnckWindow *window, TaskTitle *title)
+{
+ TaskTitlePrivate *priv;
+
+ g_return_if_fail (TASK_IS_TITLE (title));
+ g_return_if_fail (MATEWNCK_IS_WINDOW (window));
+
+ priv = title->priv;
+ if (priv->window != window)
+ return;
+
+ gtk_widget_queue_draw (GTK_WIDGET (title));
+}
+
+static void
+on_state_changed (MatewnckWindow *window,
+ MatewnckWindowState changed_mask,
+ MatewnckWindowState new_state,
+ TaskTitle *title)
+{
+ TaskTitlePrivate *priv;
+
+ g_return_if_fail (TASK_IS_TITLE (title));
+ g_return_if_fail (MATEWNCK_IS_WINDOW (window));
+
+ priv = title->priv;
+ if (priv->window != window)
+ return;
+
+ if (matewnck_window_is_maximized (window))
+ {
+ gtk_widget_set_state (GTK_WIDGET (title), GTK_STATE_ACTIVE);
+ gtk_widget_show (priv->box);
+ }
+ else
+ {
+ gtk_widget_set_state (GTK_WIDGET (title), GTK_STATE_NORMAL);
+ gtk_widget_hide (priv->box);
+ }
+}
+
+static void
+disconnect_window (TaskTitle *title)
+{
+ TaskTitlePrivate *priv = title->priv;
+ if (!priv->window)
+ return;
+ g_signal_handlers_disconnect_by_func (priv->window, on_name_changed, title);
+ g_signal_handlers_disconnect_by_func (priv->window, on_icon_changed, title);
+ g_signal_handlers_disconnect_by_func (priv->window, on_state_changed, title);
+ priv->window = NULL;
+}
+
+static void
+on_active_window_changed (MatewnckScreen *screen,
+ MatewnckWindow *old_window,
+ TaskTitle *title)
+{
+ TaskTitlePrivate *priv;
+ MatewnckWindow *act_window;
+ MatewnckWindowType type = MATEWNCK_WINDOW_NORMAL;
+
+ g_return_if_fail (TASK_IS_TITLE (title));
+ priv = title->priv;
+
+ act_window = matewnck_screen_get_active_window (screen);
+ if (act_window)
+ type = matewnck_window_get_window_type (act_window);
+
+ if (MATEWNCK_IS_WINDOW (act_window)
+ && matewnck_window_is_skip_tasklist (act_window)
+ && type != MATEWNCK_WINDOW_DESKTOP)
+ return;
+
+ if (type == MATEWNCK_WINDOW_DOCK
+ || type == MATEWNCK_WINDOW_SPLASHSCREEN
+ || type == MATEWNCK_WINDOW_MENU)
+ return;
+
+ disconnect_window (title);
+
+ if (!MATEWNCK_IS_WINDOW (act_window)
+ || matewnck_window_get_window_type (act_window) == MATEWNCK_WINDOW_DESKTOP)
+ {
+ if (priv->show_home_title)
+ {
+ gtk_label_set_text (GTK_LABEL (priv->label), _("Home"));
+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->button_image),
+ priv->quit_icon);
+ gtk_widget_set_tooltip_text (priv->button,
+ _("Log off, switch user, lock screen or power "
+ "down the computer"));
+ gtk_widget_set_tooltip_text (GTK_WIDGET (title),
+ _("Home")); gtk_widget_show (priv->box);
+ }
+ else
+ {
+ gtk_widget_set_state (GTK_WIDGET (title), GTK_STATE_NORMAL);
+ gtk_widget_set_tooltip_text (priv->button, NULL);
+ gtk_widget_set_tooltip_text (GTK_WIDGET (title), NULL);
+ gtk_widget_hide (priv->box);
+ }
+ }
+ else
+ {
+ gtk_label_set_text (GTK_LABEL (priv->label),
+ matewnck_window_get_name (act_window));
+ gtk_image_set_from_stock (GTK_IMAGE (priv->button_image),
+ GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
+
+ gtk_widget_set_tooltip_text (GTK_WIDGET (title),
+ matewnck_window_get_name (act_window));
+ gtk_widget_set_tooltip_text (priv->button, _("Close window"));
+
+ g_signal_connect (act_window, "name-changed",
+ G_CALLBACK (on_name_changed), title);
+ g_signal_connect (act_window, "icon-changed",
+ G_CALLBACK (on_icon_changed), title);
+ g_signal_connect_after (act_window, "state-changed",
+ G_CALLBACK (on_state_changed), title);
+ gtk_widget_show (priv->box);
+ priv->window = act_window;
+ }
+
+ if (MATEWNCK_IS_WINDOW (act_window)
+ && !matewnck_window_is_maximized (act_window)
+ && (priv->show_home_title ? type != MATEWNCK_WINDOW_DESKTOP : 1))
+ {
+ gtk_widget_set_state (GTK_WIDGET (title), GTK_STATE_NORMAL);
+ gtk_widget_hide (priv->box);
+ }
+ else if (!MATEWNCK_IS_WINDOW (act_window))
+ {
+ if (task_list_get_desktop_visible (TASK_LIST (task_list_get_default ()))
+ && priv->show_home_title)
+ {
+ gtk_label_set_text (GTK_LABEL (priv->label), _("Home"));
+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->button_image),
+ priv->quit_icon);
+ gtk_widget_set_tooltip_text (priv->button,
+ _("Log off, switch user, lock screen or power "
+ "down the computer"));
+ gtk_widget_set_tooltip_text (GTK_WIDGET (title),
+ _("Home"));
+ gtk_widget_show (priv->box);
+ }
+ else
+ {
+ gtk_widget_set_state (GTK_WIDGET (title), GTK_STATE_NORMAL);
+ gtk_widget_set_tooltip_text (priv->button, NULL);
+ gtk_widget_set_tooltip_text (GTK_WIDGET (title), NULL);
+ gtk_widget_hide (priv->box);
+ }
+ }
+ else
+ gtk_widget_set_state (GTK_WIDGET (title), GTK_STATE_ACTIVE);
+
+ gtk_widget_queue_draw (GTK_WIDGET (title));
+}
+
+static gboolean
+on_button_release (GtkWidget *title, GdkEventButton *event)
+{
+ TaskTitlePrivate *priv;
+ MatewnckWindow *window;
+ GtkWidget *menu;
+
+ g_return_val_if_fail (TASK_IS_TITLE (title), FALSE);
+ priv = TASK_TITLE_GET_PRIVATE (title);
+
+ window = matewnck_screen_get_active_window (priv->screen);
+
+ g_return_val_if_fail (MATEWNCK_IS_WINDOW (window), FALSE);
+
+ if (event->button == 3)
+ {
+ if (matewnck_window_get_window_type (window) != MATEWNCK_WINDOW_DESKTOP)
+ {
+ menu = matewnck_action_menu_new (window);
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
+ event->button, event->time);
+ return TRUE;
+ }
+ }
+ else if (event->button == 1)
+ {
+ if (event->type == GDK_2BUTTON_PRESS && matewnck_window_is_maximized (window))
+ {
+ matewnck_window_unmaximize (window);
+ }
+ }
+
+ return FALSE;
+}
+
+
+static gboolean
+on_expose (GtkWidget *eb, GdkEventExpose *event)
+{
+
+ if (eb->state == GTK_STATE_ACTIVE)
+ gtk_paint_box (eb->style, eb->window,
+ eb->state, GTK_SHADOW_NONE,
+ NULL, eb, "button",
+ eb->allocation.x, eb->allocation.y,
+ eb->allocation.width, eb->allocation.height);
+
+
+ gtk_container_propagate_expose (GTK_CONTAINER (eb),
+ gtk_bin_get_child (GTK_BIN (eb)),
+ event);
+ return TRUE;
+}
+
+/* GObject stuff */
+static void
+task_title_finalize (GObject *object)
+{
+ TaskTitlePrivate *priv;
+
+ priv = TASK_TITLE_GET_PRIVATE (object);
+ disconnect_window (TASK_TITLE (object));
+
+ g_object_unref (G_OBJECT (priv->quit_icon));
+
+ G_OBJECT_CLASS (task_title_parent_class)->finalize (object);
+}
+
+static void
+task_title_class_init (TaskTitleClass *klass)
+{
+ GObjectClass *obj_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *wid_class = GTK_WIDGET_CLASS (klass);
+
+ obj_class->finalize = task_title_finalize;
+ wid_class->expose_event = on_expose;
+
+ g_type_class_add_private (obj_class, sizeof (TaskTitlePrivate));
+}
+
+static void
+task_title_init (TaskTitle *title)
+{
+ TaskTitlePrivate *priv;
+ MateConfClient *client;
+ GdkScreen *gdkscreen;
+ GtkIconTheme *theme;
+ GtkSettings *settings;
+ GdkPixbuf *pixbuf;
+ AtkObject *atk;
+ int width, height;
+
+ priv = title->priv = TASK_TITLE_GET_PRIVATE (title);
+
+ priv->screen = matewnck_screen_get_default ();
+ priv->window = NULL;
+
+ client = mateconf_client_get_default ();
+ priv->show_home_title = mateconf_client_get_bool (client,
+ SHOW_HOME_TITLE_KEY,
+ NULL);
+ g_object_unref (client);
+
+ gtk_widget_add_events (GTK_WIDGET (title), GDK_ALL_EVENTS_MASK);
+
+ priv->align = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (priv->align),
+ 0, 0, 6, 6);
+ gtk_container_add (GTK_CONTAINER (title), priv->align);
+
+ priv->box = gtk_hbox_new (FALSE, 2);
+ gtk_container_add (GTK_CONTAINER (priv->align), priv->box);
+ gtk_widget_set_no_show_all (priv->box, TRUE);
+ gtk_widget_show (priv->box);
+
+ priv->label = gtk_label_new (_("Home"));
+ gtk_label_set_ellipsize (GTK_LABEL (priv->label), PANGO_ELLIPSIZE_END);
+ gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.5);
+
+ PangoAttrList *attr_list = pango_attr_list_new ();
+ PangoAttribute *attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
+ pango_attr_list_insert (attr_list, attr);
+ gtk_label_set_attributes (GTK_LABEL (priv->label), attr_list);
+
+ gtk_box_pack_start (GTK_BOX (priv->box), priv->label, TRUE, TRUE, 0);
+ gtk_widget_show (priv->label);
+
+ priv->button = g_object_new (GTK_TYPE_EVENT_BOX,
+ "visible-window", FALSE,
+ "above-child", TRUE,
+ NULL);
+ gtk_box_pack_start (GTK_BOX (priv->box), priv->button, FALSE, FALSE, 0);
+ gtk_widget_show (priv->button);
+
+ atk = gtk_widget_get_accessible (priv->button);
+ atk_object_set_name (atk, _("Close"));
+ atk_object_set_description (atk, _("Close current window."));
+ atk_object_set_role (atk, ATK_ROLE_PUSH_BUTTON);
+
+ g_signal_connect (priv->button, "button-release-event",
+ G_CALLBACK (on_close_clicked), title);
+ g_signal_connect (priv->button, "enter-notify-event",
+ G_CALLBACK (on_enter_notify), title);
+ g_signal_connect (priv->button, "leave-notify-event",
+ G_CALLBACK (on_leave_notify), title);
+ g_signal_connect (priv->button, "expose-event",
+ G_CALLBACK (on_button_expose), title);
+
+ /* Load the quit icon. We have to do this in such a god-forsaken way
+ because of http://bugzilla.mate.org/show_bug.cgi?id=581359 and the
+ fact that we support as far back as GTK+ 2.12 (which never passes
+ FORCE_SIZE in GtkImage). The only way to guarantee icon size is to
+ load and scale it ourselves. We don't do this for all the other icons
+ in the source just because we know that this icon doesn't come in the
+ size we want. */
+ gdkscreen = gtk_widget_get_screen (GTK_WIDGET (title));
+ theme = gtk_icon_theme_get_for_screen (gdkscreen);
+ settings = gtk_settings_get_for_screen (gdkscreen);
+ if (!gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU,
+&width, &height))
+ width = height = 16;
+ width = MIN(width, height);
+ pixbuf = gtk_icon_theme_load_icon (theme, "mate-logout", width, 0, NULL);
+ priv->quit_icon = gdk_pixbuf_scale_simple (pixbuf, width, width,
+ GDK_INTERP_BILINEAR);
+ g_object_unref (G_OBJECT (pixbuf));
+
+ priv->button_image = gtk_image_new_from_pixbuf (priv->quit_icon);
+ gtk_container_add (GTK_CONTAINER (priv->button), priv->button_image);
+ gtk_widget_show (priv->button_image);
+
+ gtk_widget_set_tooltip_text (priv->button,
+ _("Log off, switch user, lock screen or power "
+ "down the computer"));
+ gtk_widget_set_tooltip_text (GTK_WIDGET (title), _("Home"));
+
+ if (priv->show_home_title)
+ gtk_widget_set_state (GTK_WIDGET (title), GTK_STATE_ACTIVE);
+ else
+ gtk_widget_hide (priv->box);
+
+
+ gtk_widget_add_events (GTK_WIDGET (title), GDK_ALL_EVENTS_MASK);
+
+ g_signal_connect (priv->screen, "active-window-changed",
+ G_CALLBACK (on_active_window_changed), title);
+ g_signal_connect (title, "button-press-event",
+ G_CALLBACK (on_button_release), NULL);
+}
+
+GtkWidget *
+task_title_new (void)
+
+{
+ GtkWidget *title = NULL;
+
+ title = g_object_new (TASK_TYPE_TITLE,
+ "border-width", 0,
+ "name", "tasklist-button",
+ "visible-window", FALSE,
+ NULL);
+
+ return title;
+}