summaryrefslogtreecommitdiff
path: root/mate-window-picker-applet
diff options
context:
space:
mode:
Diffstat (limited to 'mate-window-picker-applet')
-rw-r--r--mate-window-picker-applet/Makefile.am65
-rw-r--r--mate-window-picker-applet/applet.c351
-rw-r--r--mate-window-picker-applet/mate-window-picker-applet-menu.xml2
-rw-r--r--mate-window-picker-applet/mate-window-picker-applet.schemas.in13
-rw-r--r--mate-window-picker-applet/org.mate.panel.MateWindowPicker.mate-panel-applet.in.in11
-rw-r--r--mate-window-picker-applet/org.mate.panel.applet.MateWindowPickerFactory.service.in3
-rw-r--r--mate-window-picker-applet/task-item.c779
-rw-r--r--mate-window-picker-applet/task-item.h72
-rw-r--r--mate-window-picker-applet/task-list.c246
-rw-r--r--mate-window-picker-applet/task-list.h70
-rw-r--r--mate-window-picker-applet/task-title.c528
-rw-r--r--mate-window-picker-applet/task-title.h66
12 files changed, 2206 insertions, 0 deletions
diff --git a/mate-window-picker-applet/Makefile.am b/mate-window-picker-applet/Makefile.am
new file mode 100644
index 0000000..20b39bd
--- /dev/null
+++ b/mate-window-picker-applet/Makefile.am
@@ -0,0 +1,65 @@
+libexec_PROGRAMS=mate-window-picker-applet
+
+PKGDATADIR = $(datadir)/mate-window-picker-applet
+AM_CFLAGS=\
+ $(MATEWINDOWPICKER_DEPS_CFLAGS) \
+ $(GCC_FLAGS) \
+ -I$(top_builddir) \
+ -I$(top_srcdir) \
+ -D_GNU_SOURCE \
+ -DMATELOCALEDIR=\""$(datadir)/locale"\" \
+ -DPKGDATADIR=\"$(PKGDATADIR)\" \
+ -DMATEWINDOWPICKER_MENU_UI_DIR=\""$(xmluidir)"\"
+
+mate_window_picker_applet_LDADD = \
+ $(MATEWINDOWPICKER_DEPS_LIBS)
+
+mate_window_picker_applet_SOURCES = \
+ applet.c \
+ task-item.c \
+ task-item.h \
+ task-list.c \
+ task-list.h \
+ task-title.c \
+ task-title.h
+
+appletdir = $(datadir)/mate-panel/applets
+applet_in_files = org.mate.panel.MateWindowPicker.mate-panel-applet.in
+applet_DATA = $(applet_in_files:.mate-panel-applet.in=.mate-panel-applet)
+
+$(applet_in_files): $(applet_in_files).in Makefile
+ $(AM_V_GEN)sed \
+ -e "s|\@LOCATION\@|$(APPLET_LOCATION)|" \
+ $< > $@
+
+org.mate.panel.MateWindowPicker.mate-panel-applet: org.mate.panel.MateWindowPicker.mate-panel-applet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
+
+APPLET_LOCATION=$(libexecdir)/mate-window-picker-applet
+
+servicedir = $(datadir)/dbus-1/services
+service_in_files = org.mate.panel.applet.MateWindowPickerFactory.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+org.mate.panel.applet.MateWindowPickerFactory.service: $(service_in_files)
+ $(AM_V_GEN)sed \
+ -e "s|\@LOCATION\@|$(APPLET_LOCATION)|" \
+ $< > $@
+
+schemasdir = @MATECONF_SCHEMA_FILE_DIR@
+schemas_in_files = mate-window-picker-applet.schemas.in
+schemas_DATA = $(schemas_in_files:.schemas.in=.schemas)
+@INTLTOOL_SCHEMAS_RULE@
+
+xmluidir = $(datadir)/mate-panel/ui
+xmlui_DATA = mate-window-picker-applet-menu.xml
+
+EXTRA_DIST = \
+ org.mate.panel.MateWindowPicker.panel-applet.in.in \
+ $(service_in_files) \
+ $(ui_DATA) \
+ $(schemas_in_files)
+
+CLEANFILES = $(applet_DATA) $(applet_DATA).in $(service_DATA) $(schemas_DATA)
+
+clean:
+ rm -f $(desktop_DATA) $(desktop_DATA).in $(server_DATA) $(server_DATA).in
diff --git a/mate-window-picker-applet/applet.c b/mate-window-picker-applet/applet.c
new file mode 100644
index 0000000..c2b33a6
--- /dev/null
+++ b/mate-window-picker-applet/applet.c
@@ -0,0 +1,351 @@
+/*
+ * 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]>
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <libmatewnck/libmatewnck.h>
+
+#include <mate-panel-applet.h>
+#include <mate-panel-applet-mateconf.h>
+#include <mateconf/mateconf-client.h>
+
+#include "task-list.h"
+#include "task-title.h"
+
+#define SHOW_WIN_KEY "show_all_windows"
+
+typedef struct
+{
+ GtkWidget *tasks;
+ GtkWidget *applet;
+ GtkWidget *title;
+
+} WinPickerApp;
+
+static WinPickerApp *mainapp;
+
+static void cw_panel_background_changed (MatePanelApplet *applet,
+ MatePanelAppletBackgroundType type,
+ GdkColor *colour,
+ GdkPixmap *pixmap,
+ gpointer user_data);
+static void display_about_dialog (GtkAction *action,
+ WinPickerApp *applet);
+
+static void display_prefs_dialog (GtkAction *action,
+ WinPickerApp *applet);
+
+static const GtkActionEntry window_picker_menu_actions [] = {
+ { "MenuPrefs", GTK_STOCK_PREFERENCES, N_("_Preferences"),
+ NULL, NULL,
+ G_CALLBACK (display_prefs_dialog) },
+ { "ShowDesktopAbout", GTK_STOCK_ABOUT, N_("_About"),
+ NULL, NULL,
+ G_CALLBACK (display_about_dialog) }
+};
+
+static const gchar *close_window_authors [] = {
+ "Neil J. Patel <[email protected]>",
+ "Stefano Karapetsas <[email protected]>",
+ NULL
+};
+
+static void
+on_show_all_windows_changed (MateConfClient *client,
+ guint conn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ WinPickerApp *app;
+ gboolean show_windows = TRUE;
+
+ app = (WinPickerApp*)data;
+
+ show_windows = mate_panel_applet_mateconf_get_bool (MATE_PANEL_APPLET (app->applet),
+ SHOW_WIN_KEY, NULL);
+
+ g_object_set (app->tasks, "show_all_windows", show_windows, NULL);
+}
+
+static inline void
+force_no_focus_padding (GtkWidget *widget)
+{
+ static gboolean first_time = TRUE;
+
+ if (first_time)
+ {
+ gtk_rc_parse_string ("\n"
+ " style \"na-tray-style\"\n"
+ " {\n"
+ " GtkWidget::focus-line-width=0\n"
+ " GtkWidget::focus-padding=0\n"
+ " }\n"
+ "\n"
+ " widget \"*.na-tray\" style \"na-tray-style\"\n"
+ "\n");
+ first_time = FALSE;
+ }
+
+ gtk_widget_set_name (widget, "na-tray");
+}
+
+static gboolean
+cw_applet_fill (MatePanelApplet *applet,
+ const gchar *iid,
+ gpointer data)
+{
+ MatewnckScreen *screen;
+ WinPickerApp *app;
+ GtkWidget *eb, *tasks, *title;
+ GError *error = NULL;
+ gchar *key;
+ gchar *ui_path;
+ GtkActionGroup *action_group;
+
+ if (strcmp (iid, "MateWindowPicker") != 0)
+ return FALSE;
+
+ bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ matewnck_set_client_type (MATEWNCK_CLIENT_TYPE_PAGER);
+
+ app = g_slice_new0 (WinPickerApp);
+ mainapp = app;
+ screen = matewnck_screen_get_default ();
+
+ /* mateconf prefs */
+ mate_panel_applet_add_preferences (applet,
+ "/schemas/apps/mate-window-picker-applet/prefs",
+ &error);
+ if (error)
+ {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ key = mate_panel_applet_mateconf_get_full_key (applet, SHOW_WIN_KEY);
+ mateconf_client_notify_add (mateconf_client_get_default (), key,
+ on_show_all_windows_changed, app,
+ NULL, NULL);
+ g_free (key);
+
+ app->applet = GTK_WIDGET (applet);
+ force_no_focus_padding (GTK_WIDGET (applet));
+ gtk_container_set_border_width (GTK_CONTAINER (applet), 0);
+
+ eb = gtk_hbox_new (FALSE, 6);
+ gtk_container_add (GTK_CONTAINER (applet), eb);
+ gtk_container_set_border_width (GTK_CONTAINER (eb), 0);
+
+ tasks = app->tasks = task_list_get_default ();
+ gtk_box_pack_start (GTK_BOX (eb), tasks, FALSE, FALSE, 0);
+
+ title = app->title = task_title_new ();
+ gtk_box_pack_start (GTK_BOX (eb), title, TRUE, TRUE, 0);
+
+ gtk_widget_show_all (GTK_WIDGET (applet));
+
+ on_show_all_windows_changed (NULL, 0, NULL, app);
+
+ /* Signals */
+ g_signal_connect (applet, "change-background",
+ G_CALLBACK (cw_panel_background_changed), NULL);
+
+
+ action_group = gtk_action_group_new ("MateWindowPicker Applet Actions");
+ gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
+ gtk_action_group_add_actions (action_group,
+ window_picker_menu_actions,
+ G_N_ELEMENTS (window_picker_menu_actions),
+ app);
+ ui_path = g_build_filename (MATEWINDOWPICKER_MENU_UI_DIR, "mate-window-picker-menu.xml", NULL);
+ mate_panel_applet_setup_menu_from_file (MATE_PANEL_APPLET (app->applet),
+ ui_path, action_group);
+ g_free (ui_path);
+ g_object_unref (action_group);
+
+ mate_panel_applet_set_flags (MATE_PANEL_APPLET (applet),
+ MATE_PANEL_APPLET_EXPAND_MAJOR
+ | MATE_PANEL_APPLET_EXPAND_MINOR
+ | MATE_PANEL_APPLET_HAS_HANDLE);
+
+ return TRUE;
+}
+
+MATE_PANEL_APPLET_OUT_PROCESS_FACTORY ("MateWindowPickerFactory",
+ PANEL_TYPE_APPLET,
+ "MateWindowPicker",
+ cw_applet_fill,
+ NULL);
+
+static void
+cw_panel_background_changed (MatePanelApplet *applet,
+ MatePanelAppletBackgroundType type,
+ GdkColor *colour,
+ GdkPixmap *pixmap,
+ gpointer user_data)
+{
+ GtkRcStyle *rc_style;
+ GtkStyle *style;
+
+ /* reset style */
+ gtk_widget_set_style (GTK_WIDGET (applet), NULL);
+ rc_style = gtk_rc_style_new ();
+ gtk_widget_modify_style (GTK_WIDGET (applet), rc_style);
+ gtk_rc_style_unref (rc_style);
+
+ gtk_widget_set_style (mainapp->title, NULL);
+ rc_style = gtk_rc_style_new ();
+ gtk_widget_modify_style (mainapp->title, rc_style);
+ gtk_rc_style_unref (rc_style);
+
+ switch (type)
+ {
+ case PANEL_NO_BACKGROUND:
+ break;
+ case PANEL_COLOR_BACKGROUND:
+ gtk_widget_modify_bg (GTK_WIDGET (applet), GTK_STATE_NORMAL, colour);
+ gtk_widget_modify_bg (mainapp->title, GTK_STATE_NORMAL, colour);
+ break;
+
+ case PANEL_PIXMAP_BACKGROUND:
+ style = gtk_style_copy (GTK_WIDGET (applet)->style);
+ if (style->bg_pixmap[GTK_STATE_NORMAL])
+ g_object_unref (style->bg_pixmap[GTK_STATE_NORMAL]);
+ style->bg_pixmap[GTK_STATE_NORMAL] = g_object_ref (pixmap);
+ gtk_widget_set_style (GTK_WIDGET (applet), style);
+ g_object_unref (style);
+
+ /*style = gtk_style_copy (mainapp->title->style);
+ if (style->bg_pixmap[GTK_STATE_NORMAL])
+ g_object_unref (style->bg_pixmap[GTK_STATE_NORMAL]);
+ style->bg_pixmap[GTK_STATE_NORMAL] = g_object_ref (pixmap);
+ gtk_widget_set_style (mainapp->title, style);
+ g_object_unref (style);*/
+
+ break;
+ }
+}
+
+static void
+display_about_dialog (GtkAction *action,
+ WinPickerApp *applet)
+{
+ GtkWidget *panel_about_dialog;
+
+ panel_about_dialog = gtk_about_dialog_new ();
+
+ g_object_set (panel_about_dialog,
+ "name", _("Window Picker"),
+ "comments", _("Window Picker"),
+ "version", PACKAGE_VERSION,
+ "authors", close_window_authors,
+ "logo-icon-name", "system-preferences-windows",
+ "copyright", "Copyright \xc2\xa9 2008 Canonical Ltd",
+ NULL);
+
+ gtk_widget_show (panel_about_dialog);
+
+ g_signal_connect (panel_about_dialog, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+
+
+ gtk_window_present (GTK_WINDOW (panel_about_dialog));
+}
+
+static void
+on_checkbox_toggled (GtkToggleButton *check, gpointer null)
+{
+ gboolean is_active;
+
+ is_active = gtk_toggle_button_get_active (check);
+
+ mate_panel_applet_mateconf_set_bool (MATE_PANEL_APPLET (mainapp->applet),
+ SHOW_WIN_KEY, is_active, NULL);
+}
+
+static void
+display_prefs_dialog (GtkAction *action,
+ WinPickerApp *applet)
+{
+ GtkWidget *window, *box, *vbox, *nb, *hbox, *label, *check, *button;
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (window), _("Preferences"));
+ gtk_window_set_type_hint (GTK_WINDOW (window),
+ GDK_WINDOW_TYPE_HINT_DIALOG);
+ gtk_container_set_border_width (GTK_CONTAINER (window), 12);
+
+ box = gtk_vbox_new (FALSE, 8);
+ gtk_container_add (GTK_CONTAINER (window), box);
+
+ nb = gtk_notebook_new ();
+ g_object_set (nb, "show-tabs", FALSE, "show-border", TRUE, NULL);
+ gtk_box_pack_start (GTK_BOX (box), nb, TRUE, TRUE, 0);
+
+ vbox = gtk_vbox_new (FALSE, 8);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
+ gtk_notebook_append_page (GTK_NOTEBOOK (nb), vbox, NULL);
+
+ check = gtk_check_button_new_with_label (_("Show windows from all workspaces"));
+ gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, TRUE, 0);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check),
+ mate_panel_applet_mateconf_get_bool (
+ MATE_PANEL_APPLET (mainapp->applet),
+ SHOW_WIN_KEY, NULL));
+ g_signal_connect (check, "toggled",
+ G_CALLBACK (on_checkbox_toggled), NULL);
+
+ check = gtk_label_new (" ");
+ gtk_box_pack_start (GTK_BOX (vbox), check, TRUE, TRUE, 0);
+
+ gtk_widget_set_size_request (nb, -1, 100);
+
+ hbox = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (box), hbox, TRUE, TRUE, 0);
+
+ label = gtk_label_new (" ");
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+
+ button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+ gtk_widget_show_all (window);
+
+ g_signal_connect (window, "delete-event",
+ G_CALLBACK (gtk_widget_destroy), window);
+
+ g_signal_connect (window, "destroy",
+ G_CALLBACK (gtk_widget_destroy), window);
+ g_signal_connect_swapped (button, "clicked",
+ G_CALLBACK (gtk_widget_destroy), window);
+
+ gtk_window_present (GTK_WINDOW (window));
+}
diff --git a/mate-window-picker-applet/mate-window-picker-applet-menu.xml b/mate-window-picker-applet/mate-window-picker-applet-menu.xml
new file mode 100644
index 0000000..7649999
--- /dev/null
+++ b/mate-window-picker-applet/mate-window-picker-applet-menu.xml
@@ -0,0 +1,2 @@
+<menuitem name="PreferencesItem" action="MenuPrefs" />
+<menuitem name="About Item" action="MenuAbout" />
diff --git a/mate-window-picker-applet/mate-window-picker-applet.schemas.in b/mate-window-picker-applet/mate-window-picker-applet.schemas.in
new file mode 100644
index 0000000..ccceb1c
--- /dev/null
+++ b/mate-window-picker-applet/mate-window-picker-applet.schemas.in
@@ -0,0 +1,13 @@
+<mateconfschemafile>
+ <schemalist>
+ <schema>
+ <key>/schemas/apps/mate-window-picker-applet/prefs/show_all_windows</key>
+ <owner>mate-window-picker-applet</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Show windows from all workspaces.</short>
+ </locale>
+ </schema>
+ </schemalist>
+</mateconfschemafile>
diff --git a/mate-window-picker-applet/org.mate.panel.MateWindowPicker.mate-panel-applet.in.in b/mate-window-picker-applet/org.mate.panel.MateWindowPicker.mate-panel-applet.in.in
new file mode 100644
index 0000000..ffc4b98
--- /dev/null
+++ b/mate-window-picker-applet/org.mate.panel.MateWindowPicker.mate-panel-applet.in.in
@@ -0,0 +1,11 @@
+[Applet Factory]
+Id=MateWindowPickerFactory
+Location=@LOCATION@
+_Name=Window Picker Applet Factory
+_Description=Window Picker
+
+[MateWindowPicker]
+_Name=Window Picker
+_Description=Window Picker
+Icon=preferences-system-windows
+BonoboId=OAFIID:MATE_WindowPicker
diff --git a/mate-window-picker-applet/org.mate.panel.applet.MateWindowPickerFactory.service.in b/mate-window-picker-applet/org.mate.panel.applet.MateWindowPickerFactory.service.in
new file mode 100644
index 0000000..f301b25
--- /dev/null
+++ b/mate-window-picker-applet/org.mate.panel.applet.MateWindowPickerFactory.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.mate.panel.applet.MateWindowPickerFactory
+Exec=@LOCATION@
diff --git a/mate-window-picker-applet/task-item.c b/mate-window-picker-applet/task-item.c
new file mode 100644
index 0000000..3e0dd97
--- /dev/null
+++ b/mate-window-picker-applet/task-item.c
@@ -0,0 +1,779 @@
+/*
+ * 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 Jason Smith <[email protected]>
+ *
+ */
+
+#include "task-item.h"
+#include "task-list.h"
+
+#include <math.h>
+#include <glib/gi18n.h>
+#include <cairo/cairo.h>
+
+G_DEFINE_TYPE (TaskItem, task_item, GTK_TYPE_EVENT_BOX);
+
+#define TASK_ITEM_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\
+ TASK_TYPE_ITEM, \
+ TaskItemPrivate))
+
+#define DEFAULT_TASK_ITEM_HEIGHT 24;
+#define DEFAULT_TASK_ITEM_WIDTH 28
+
+struct _TaskItemPrivate
+{
+ MatewnckWindow *window;
+ MatewnckScreen *screen;
+ GdkPixbuf *pixbuf;
+ GdkRectangle area;
+
+ GTimeVal urgent_time;
+ guint timer;
+ gboolean mouse_over;
+};
+
+enum {
+ TASK_ITEM_CLOSED_SIGNAL,
+ LAST_SIGNAL
+};
+
+/* D&D stuff */
+static const GtkTargetEntry drop_types[] =
+{
+ { "STRING", 0, 0 },
+ { "text/plain", 0, 0},
+ { "text/uri-list", 0, 0}
+};
+static const gint n_drop_types = G_N_ELEMENTS(drop_types);
+
+static guint task_item_signals[LAST_SIGNAL] = { 0 };
+
+static void
+update_hints (TaskItem *item)
+{
+ GtkWidget *parent;
+ GtkWidget *widget;
+ MatewnckWindow *window;
+ gint x, y, x1, y1;
+
+ widget = GTK_WIDGET (item);
+ window = item->priv->window;
+ /* Skip problems */
+ if (!MATEWNCK_IS_WINDOW (window)) return;
+ if (!GTK_IS_WIDGET (widget)) return;
+
+ /* Skip invisible windows */
+ if (!GTK_WIDGET_VISIBLE (widget)) return;
+
+ x = y = 0;
+
+ /* Recursively compute the button's coordinates */
+ for (parent = widget; parent; parent = parent->parent)
+ {
+ if (parent->parent)
+ {
+ x += parent->allocation.x;
+ y += parent->allocation.y;
+ }
+ else
+ {
+ x1 = y1 = 0;
+ if (GDK_IS_WINDOW (parent->window))
+ gdk_window_get_origin (parent->window, &x1, &y1);
+ x += x1; y += y1;
+ break;
+ }
+ }
+
+ /* Set the minimize hint for the window */
+ matewnck_window_set_icon_geometry (window, x, y,
+ widget->allocation.width,
+ widget->allocation.height);
+}
+
+static gboolean
+on_task_item_button_released (GtkWidget *widget,
+ GdkEventButton *event,
+ TaskItem *item)
+{
+ MatewnckWindow *window;
+ MatewnckScreen *screen;
+ MatewnckWorkspace *workspace;
+ TaskItemPrivate *priv;
+
+ g_return_val_if_fail (TASK_IS_ITEM (item), TRUE);
+
+ priv = item->priv;
+ window = priv->window;
+
+ g_return_val_if_fail (MATEWNCK_IS_WINDOW (window), TRUE);
+
+ screen = priv->screen;
+ workspace = matewnck_window_get_workspace (window);
+
+ if (event->button == 1)
+ {
+
+ if (MATEWNCK_IS_WORKSPACE (workspace) && workspace != matewnck_screen_get_active_workspace (screen))
+ {
+ matewnck_workspace_activate (workspace, GDK_CURRENT_TIME);
+ }
+ if (matewnck_window_is_active (window))
+ {
+ matewnck_window_minimize (window);
+ }
+ else
+ {
+ matewnck_window_activate (window, GDK_CURRENT_TIME);
+ }
+ }
+ return TRUE;
+}
+
+static void
+task_item_set_visibility (TaskItem *item)
+{
+ MatewnckScreen *screen;
+ MatewnckWindow *window;
+ MatewnckWorkspace *workspace;
+
+ g_return_if_fail (TASK_IS_ITEM (item));
+
+ TaskItemPrivate *priv = item->priv;
+
+ if (!MATEWNCK_IS_WINDOW (priv->window))
+ {
+ gtk_widget_hide (GTK_WIDGET (item));
+ return;
+ }
+
+ window = priv->window;
+
+ screen = priv->screen;
+ workspace = matewnck_screen_get_active_workspace (screen);
+
+ gboolean show_all = task_list_get_show_all_windows (TASK_LIST (task_list_get_default ()));
+ gboolean show_window = FALSE;
+
+ if (!matewnck_window_is_skip_tasklist (window))
+ {
+ if (matewnck_workspace_is_virtual (workspace))
+ {
+ show_window = matewnck_window_is_in_viewport (window, workspace);
+ }
+ else
+ {
+ show_window = matewnck_window_is_on_workspace (window, workspace);
+ }
+ show_window = show_window || show_all;
+ }
+
+ if (show_window)
+ {
+ gtk_widget_show (GTK_WIDGET (item));
+ }
+ else
+ {
+ gtk_widget_hide (GTK_WIDGET (item));
+ }
+}
+
+static void
+task_item_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ /* Candidate for terrible hack of the year award */
+ requisition->width = DEFAULT_TASK_ITEM_WIDTH;
+ requisition->height = DEFAULT_TASK_ITEM_HEIGHT;
+}
+
+static GdkPixbuf *
+task_item_sized_pixbuf_for_window (TaskItem *item,
+ MatewnckWindow *window,
+ gint size)
+{
+ GdkPixbuf *pbuf = NULL;
+
+ g_return_val_if_fail (MATEWNCK_IS_WINDOW (window), NULL);
+
+ if (matewnck_window_has_icon_name (window))
+ {
+ const gchar *icon_name = matewnck_window_get_icon_name (window);
+ GtkIconTheme *icon_theme = gtk_icon_theme_get_default ();
+
+ if (gtk_icon_theme_has_icon (icon_theme, icon_name))
+ {
+ GdkPixbuf *internal = gtk_icon_theme_load_icon (icon_theme,
+ icon_name,
+ size,
+ GTK_ICON_LOOKUP_FORCE_SIZE,
+ NULL);
+ pbuf = gdk_pixbuf_copy (internal);
+ g_object_unref (internal);
+ }
+ }
+
+ if (!pbuf)
+ {
+ pbuf = gdk_pixbuf_copy (matewnck_window_get_icon (item->priv->window));
+ }
+
+ gint width = gdk_pixbuf_get_width (pbuf);
+ gint height = gdk_pixbuf_get_height (pbuf);
+
+ if (MAX (width, height) != size)
+ {
+ gdouble scale = (gdouble) size / (gdouble) MAX (width, height);
+
+ GdkPixbuf *tmp = pbuf;
+ pbuf = gdk_pixbuf_scale_simple (tmp, (gint) (width * scale), (gint) (height * scale), GDK_INTERP_HYPER);
+
+ g_object_unref (tmp);
+ }
+
+ return pbuf;
+}
+static gboolean
+task_item_expose_event (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ cairo_t *cr;
+ TaskItem *item;
+ GdkRectangle area;
+ TaskItemPrivate *priv;
+ GdkPixbuf *desat;
+ GdkPixbuf *pbuf;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (TASK_IS_ITEM (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ item = TASK_ITEM (widget);
+ priv = item->priv;
+
+ g_return_val_if_fail (MATEWNCK_IS_WINDOW (priv->window), FALSE);
+
+ area = priv->area;
+ cr = gdk_cairo_create (event->window);
+
+ pbuf = priv->pixbuf;
+ desat = NULL;
+
+ gint size = MIN (area.height, area.width);
+ gboolean active = matewnck_window_is_active (priv->window);
+ gboolean attention = matewnck_window_or_transient_needs_attention (priv->window);
+
+ if (GDK_IS_PIXBUF (pbuf) &&
+ gdk_pixbuf_get_width (pbuf) != size &&
+ gdk_pixbuf_get_height (pbuf) != size)
+ {
+ g_object_unref (pbuf);
+ pbuf = NULL;
+ }
+
+ if (active)
+ {
+ cairo_rectangle (cr, area.x + .5, area.y - 4, area.width - 1, area.height + 8);
+ cairo_set_source_rgba (cr, .8, .8, .8, .2);
+ cairo_fill_preserve (cr);
+
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, .8, .8, .8, .4);
+ cairo_stroke (cr);
+ }
+
+ if (!pbuf)
+ {
+ pbuf = priv->pixbuf = task_item_sized_pixbuf_for_window (item, priv->window, size);
+ }
+
+ if (active || priv->mouse_over || attention)
+ {
+ gdk_cairo_set_source_pixbuf (cr,
+ pbuf,
+ (area.x + (area.width - gdk_pixbuf_get_width (pbuf)) / 2),
+ (area.y + (area.height - gdk_pixbuf_get_height (pbuf)) / 2));
+ }
+ else
+ {
+ desat = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+ TRUE,
+ gdk_pixbuf_get_bits_per_sample (pbuf),
+ gdk_pixbuf_get_width (pbuf),
+ gdk_pixbuf_get_height (pbuf));
+
+ if (desat)
+ {
+ gdk_pixbuf_saturate_and_pixelate (pbuf,
+ desat,
+ 0,
+ FALSE);
+ }
+ else /* just paint the colored version as a fallback */
+ {
+ desat = pbuf;
+ }
+ gdk_cairo_set_source_pixbuf (cr,
+ desat,
+ (area.x + (area.width - gdk_pixbuf_get_width (desat)) / 2),
+ (area.y + (area.height - gdk_pixbuf_get_height (desat)) / 2));
+ }
+ if (!priv->mouse_over && attention) /* urgent */
+ {
+ GTimeVal current_time;
+ g_get_current_time (&current_time);
+
+ gdouble ms = (current_time.tv_sec - priv->urgent_time.tv_sec) * 1000 +
+ (current_time.tv_usec - priv->urgent_time.tv_usec) / 1000;
+
+ gdouble alpha = .66 + (cos (3.15 * ms / 600) / 3);
+ cairo_paint_with_alpha (cr, alpha);
+ }
+ else if (priv->mouse_over || active) /* focused */
+ {
+ cairo_paint (cr);
+ }
+ else /* not focused */
+ {
+ cairo_paint_with_alpha (cr, .65);
+ }
+
+ if (GDK_IS_PIXBUF (desat))
+ g_object_unref (desat);
+
+ cairo_destroy (cr);
+
+ return FALSE;
+}
+
+static void
+on_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation,
+ TaskItem *item)
+{
+ TaskItemPrivate *priv;
+
+ if (allocation->width != allocation->height + 6)
+ gtk_widget_set_size_request (widget, allocation->height + 6, -1);
+
+ g_return_if_fail (TASK_IS_ITEM (item));
+
+ priv = item->priv;
+ priv->area.x = allocation->x;
+ priv->area.y = allocation->y;
+ priv->area.width = allocation->width;
+ priv->area.height = allocation->height;
+
+ update_hints (item);
+}
+
+static gboolean
+on_button_pressed (GtkWidget *button,
+ GdkEventButton *event,
+ TaskItem *item)
+{
+ MatewnckWindow *window;
+ g_return_val_if_fail (TASK_IS_ITEM (item), FALSE);
+ window = item->priv->window;
+ g_return_val_if_fail (MATEWNCK_IS_WINDOW (window), FALSE);
+
+ if (event->button == 3)
+ {
+ GtkWidget *menu = matewnck_action_menu_new (window);
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
+ event->button, event->time);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+on_query_tooltip (GtkWidget *widget,
+ gint x, gint y,
+ gboolean keyboard_mode,
+ GtkTooltip *tooltip,
+ TaskItem *item)
+{
+ MatewnckWindow *window = item->priv->window;
+ g_return_val_if_fail (MATEWNCK_IS_WINDOW (window), FALSE);
+
+ gtk_tooltip_set_text (tooltip, matewnck_window_get_name(window));
+ gtk_tooltip_set_icon (tooltip, matewnck_window_get_icon (window));
+
+ return TRUE;
+}
+
+static gboolean
+on_enter_notify (GtkWidget *widget,
+ GdkEventCrossing *event,
+ TaskItem *item)
+{
+ g_return_val_if_fail (TASK_IS_ITEM (item), FALSE);
+
+ item->priv->mouse_over = TRUE;
+ gtk_widget_queue_draw (widget);
+
+ return FALSE;
+}
+
+static gboolean
+on_leave_notify (GtkWidget *widget,
+ GdkEventCrossing *event,
+ TaskItem *item)
+{
+ g_return_val_if_fail (TASK_IS_ITEM (item), FALSE);
+
+ item->priv->mouse_over = FALSE;
+ gtk_widget_queue_draw (widget);
+
+ return FALSE;
+}
+
+static gboolean
+on_blink (TaskItem *item)
+{
+ g_return_val_if_fail (TASK_IS_ITEM (item), FALSE);
+
+ gtk_widget_queue_draw (GTK_WIDGET (item));
+
+ if (matewnck_window_or_transient_needs_attention (item->priv->window))
+ {
+ return TRUE;
+ }
+ else
+ {
+ item->priv->timer = 0;
+ return FALSE;
+ }
+}
+
+static void
+on_window_state_changed (MatewnckWindow *window,
+ MatewnckWindowState changed_mask,
+ MatewnckWindowState new_state,
+ TaskItem *item)
+{
+ g_return_if_fail (MATEWNCK_IS_WINDOW (window));
+ g_return_if_fail (TASK_IS_ITEM (item));
+
+ TaskItemPrivate *priv = item->priv;
+
+ if (new_state & MATEWNCK_WINDOW_STATE_URGENT && !priv->timer)
+ {
+ priv->timer = g_timeout_add (30, (GSourceFunc)on_blink, item);
+ g_get_current_time (&priv->urgent_time);
+ }
+
+ task_item_set_visibility (item);
+}
+
+static void
+on_window_workspace_changed (MatewnckWindow *window, TaskItem *item)
+{
+ g_return_if_fail (TASK_IS_ITEM (item));
+
+ task_item_set_visibility (item);
+}
+
+static void on_window_icon_changed (MatewnckWindow *window, TaskItem *item)
+{
+ TaskItemPrivate *priv;
+
+ g_return_if_fail (TASK_IS_ITEM (item));
+
+ priv = item->priv;
+
+ if (GDK_IS_PIXBUF (priv->pixbuf))
+ {
+ g_object_unref (priv->pixbuf);
+ priv->pixbuf = NULL;
+ }
+
+ gtk_widget_queue_draw (GTK_WIDGET (item));
+}
+
+static void
+on_screen_active_window_changed (MatewnckScreen *screen,
+ MatewnckWindow *old_window,
+ TaskItem *item)
+{
+ MatewnckWindow *window;
+ TaskItemPrivate *priv;
+
+ g_return_if_fail (TASK_IS_ITEM (item));
+
+ priv = item->priv;
+ window = priv->window;
+
+ g_return_if_fail (MATEWNCK_IS_WINDOW (window));
+
+ if ((MATEWNCK_IS_WINDOW (old_window) && window == old_window) ||
+ window == matewnck_screen_get_active_window (screen))
+ {
+ /* queue a draw to reflect that we are [no longer] the active window */
+ gtk_widget_queue_draw (GTK_WIDGET (item));
+ }
+}
+
+static void
+on_screen_active_workspace_changed (MatewnckScreen *screen,
+ MatewnckWorkspace *old_workspace,
+ TaskItem *item)
+{
+ g_return_if_fail (TASK_IS_ITEM (item));
+
+ task_item_set_visibility (item);
+}
+
+static void
+on_screen_active_viewport_changed (MatewnckScreen *screen,
+ TaskItem *item)
+{
+ g_return_if_fail (TASK_IS_ITEM (item));
+
+ task_item_set_visibility (item);
+}
+
+static void
+on_screen_window_closed (MatewnckScreen *screen,
+ MatewnckWindow *window,
+ TaskItem *item)
+{
+ TaskItemPrivate *priv;
+
+ g_return_if_fail (TASK_IS_ITEM (item));
+ priv = item->priv;
+ g_return_if_fail (MATEWNCK_IS_WINDOW (priv->window));
+
+ if (priv->window == window)
+ {
+ g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (on_screen_window_closed), item);
+ g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (on_screen_active_window_changed), item);
+ g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (on_screen_active_workspace_changed), item);
+ g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (on_screen_window_closed), item);
+ g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_window_workspace_changed), item);
+ g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_window_state_changed), item);
+
+ g_signal_emit (G_OBJECT (item), task_item_signals[TASK_ITEM_CLOSED_SIGNAL], 0);
+ }
+}
+
+static gboolean
+activate_window (GtkWidget *widget)
+{
+ gint active;
+ TaskItemPrivate *priv;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+ g_return_val_if_fail (TASK_IS_ITEM (widget), FALSE);
+
+ priv = TASK_ITEM (widget)->priv;
+
+ g_return_val_if_fail (MATEWNCK_IS_WINDOW (priv->window), FALSE);
+
+ active = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "drag-true"));
+
+ if (active)
+ {
+ MatewnckWindow *window;
+
+ window = priv->window;
+ if (MATEWNCK_IS_WINDOW (window))
+ matewnck_window_activate (window, time (NULL));
+ }
+
+ g_object_set_data (G_OBJECT (widget), "drag-true", GINT_TO_POINTER (0));
+
+ return FALSE;
+}
+
+static void
+on_drag_leave (GtkWidget *item,
+ GdkDragContext *context,
+ guint time)
+{
+ g_object_set_data (G_OBJECT (item), "drag-true", GINT_TO_POINTER (0));
+}
+
+static gboolean
+on_drag_motion (GtkWidget *item,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint t)
+{
+ gint active;
+
+ active = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "drag-true"));
+
+ if (!active)
+ {
+ g_object_set_data (G_OBJECT (item), "drag-true", GINT_TO_POINTER (1));
+
+ g_timeout_add (1000, (GSourceFunc)activate_window, item);
+ }
+
+ return FALSE;
+}
+
+static void
+task_item_setup_atk (TaskItem *item)
+{
+ TaskItemPrivate *priv;
+ GtkWidget *widget;
+ AtkObject *atk;
+ MatewnckWindow *window;
+
+ g_return_if_fail (TASK_IS_ITEM (item));
+
+ widget = GTK_WIDGET (item);
+ priv = item->priv;
+ window = priv->window;
+
+ g_return_if_fail (MATEWNCK_IS_WINDOW (window));
+
+ atk = gtk_widget_get_accessible (widget);
+ atk_object_set_name (atk, _("Window Task Button"));
+ atk_object_set_description (atk, matewnck_window_get_name (window));
+ atk_object_set_role (atk, ATK_ROLE_PUSH_BUTTON);
+}
+
+static void
+task_item_finalize (GObject *object)
+{
+ TaskItemPrivate *priv;
+ priv = TASK_ITEM_GET_PRIVATE (object);
+
+ /* remove timer */
+ if (priv->timer)
+ {
+ g_source_remove (priv->timer);
+ }
+
+ if (GDK_IS_PIXBUF (priv->pixbuf))
+ {
+ g_object_unref (priv->pixbuf);
+ }
+
+ G_OBJECT_CLASS (task_item_parent_class)->finalize (object);
+}
+
+static void
+task_item_class_init (TaskItemClass *klass)
+{
+ GObjectClass *obj_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ obj_class->finalize = task_item_finalize;
+ widget_class->expose_event = task_item_expose_event;
+ widget_class->size_request = task_item_size_request;
+
+ g_type_class_add_private (obj_class, sizeof (TaskItemPrivate));
+
+ task_item_signals [TASK_ITEM_CLOSED_SIGNAL] =
+ g_signal_new ("task-item-closed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (TaskItemClass, itemclosed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+}
+
+static void
+task_item_init (TaskItem *item)
+{
+ TaskItemPrivate *priv;
+ priv = item->priv = TASK_ITEM_GET_PRIVATE (item);
+
+ priv->timer = 0;
+}
+
+GtkWidget *
+task_item_new (MatewnckWindow *window)
+{
+ GtkWidget *item = NULL;
+ TaskItem *task;
+ TaskItemPrivate *priv;
+ MatewnckScreen *screen;
+
+ g_return_val_if_fail (MATEWNCK_IS_WINDOW (window), item);
+
+ item = g_object_new (TASK_TYPE_ITEM,
+ "has-tooltip", TRUE,
+ "visible-window", FALSE,
+ "above-child", TRUE,
+ NULL);
+
+ gtk_widget_add_events (item, GDK_ALL_EVENTS_MASK);
+ gtk_container_set_border_width (GTK_CONTAINER (item), 0);
+
+ task = TASK_ITEM (item);
+ priv = task->priv;
+ priv->window = window;
+
+ screen = matewnck_window_get_screen (window);
+ priv->screen = screen;
+
+ gtk_drag_dest_set (item,
+ GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+ drop_types, n_drop_types,
+ GDK_ACTION_COPY);
+ gtk_drag_dest_add_uri_targets (item);
+ gtk_drag_dest_add_text_targets (item);
+ g_signal_connect (item, "drag-motion",
+ G_CALLBACK (on_drag_motion), NULL);
+ g_signal_connect (item, "drag-leave",
+ G_CALLBACK (on_drag_leave), NULL);
+
+ g_signal_connect (screen, "viewports-changed",
+ G_CALLBACK (on_screen_active_viewport_changed), item);
+ g_signal_connect (screen, "active-window-changed",
+ G_CALLBACK (on_screen_active_window_changed), item);
+ g_signal_connect (screen, "active-workspace-changed",
+ G_CALLBACK (on_screen_active_workspace_changed), item);
+ g_signal_connect (screen, "window-closed",
+ G_CALLBACK (on_screen_window_closed), item);
+
+ g_signal_connect (window, "workspace-changed",
+ G_CALLBACK (on_window_workspace_changed), item);
+ g_signal_connect (window, "state-changed",
+ G_CALLBACK (on_window_state_changed), item);
+ g_signal_connect (window, "icon-changed",
+ G_CALLBACK (on_window_icon_changed), item);
+
+ g_signal_connect (item, "button-release-event",
+ G_CALLBACK (on_task_item_button_released), item);
+ g_signal_connect (item, "button-press-event",
+ G_CALLBACK (on_button_pressed), item);
+ g_signal_connect (item, "size-allocate",
+ G_CALLBACK (on_size_allocate), item);
+ g_signal_connect (item, "query-tooltip",
+ G_CALLBACK (on_query_tooltip), item);
+ g_signal_connect (item, "enter-notify-event",
+ G_CALLBACK (on_enter_notify), item);
+ g_signal_connect (item, "leave-notify-event",
+ G_CALLBACK (on_leave_notify), item);
+ g_signal_connect (item, "drag-motion",
+ G_CALLBACK (on_drag_motion), item);
+ g_signal_connect (item, "drag-leave",
+ G_CALLBACK (on_drag_leave), item);
+
+ task_item_set_visibility (task);
+ task_item_setup_atk (task);
+
+ return item;
+}
diff --git a/mate-window-picker-applet/task-item.h b/mate-window-picker-applet/task-item.h
new file mode 100644
index 0000000..bf6ce38
--- /dev/null
+++ b/mate-window-picker-applet/task-item.h
@@ -0,0 +1,72 @@
+/*
+ * 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]>
+ * Jason Smith <[email protected]>
+ *
+ */
+
+#ifndef _TASK_ITEM_H_
+#define _TASK_ITEM_H_
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <libmatewnck/libmatewnck.h>
+
+#define TASK_TYPE_ITEM (task_item_get_type ())
+
+#define TASK_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
+ TASK_TYPE_ITEM, TaskItem))
+
+#define TASK_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\
+ TASK_TYPE_ITEM, TaskItemClass))
+
+#define TASK_IS_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
+ TASK_TYPE_ITEM))
+
+#define TASK_IS_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\
+ TASK_TYPE_ITEM))
+
+#define TASK_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
+ TASK_TYPE_ITEM, TaskItemClass))
+
+typedef struct _TaskItem TaskItem;
+typedef struct _TaskItemClass TaskItemClass;
+typedef struct _TaskItemPrivate TaskItemPrivate;
+
+struct _TaskItem
+{
+ GtkEventBox parent;
+
+ TaskItemPrivate *priv;
+};
+
+struct _TaskItemClass
+{
+ GtkEventBoxClass parent_class;
+
+ void (* itemclosed) (TaskItem *item);
+};
+
+GType task_item_get_type (void) G_GNUC_CONST;
+
+GtkWidget * task_item_new (MatewnckWindow *window);
+
+GtkWidget * task_item_get_default (void);
+
+gboolean task_item_get_desktop_visible (TaskItem *item);
+
+#endif /* _TASK_ITEM_H_ */
+
diff --git a/mate-window-picker-applet/task-list.c b/mate-window-picker-applet/task-list.c
new file mode 100644
index 0000000..43c0d5d
--- /dev/null
+++ b/mate-window-picker-applet/task-list.c
@@ -0,0 +1,246 @@
+/*
+ * 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-list.h"
+#include "task-item.h"
+
+#include <libmatewnck/libmatewnck.h>
+
+G_DEFINE_TYPE (TaskList, task_list, GTK_TYPE_HBOX);
+
+#define TASK_LIST_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\
+ TASK_TYPE_LIST, \
+ TaskListPrivate))
+
+struct _TaskListPrivate
+{
+ MatewnckScreen *screen;
+ GHashTable *win_table;
+ guint timer;
+ guint counter;
+
+ gboolean show_all_windows;
+};
+
+enum
+{
+ PROP_0,
+
+ PROP_SHOW_ALL_WINDOWS
+};
+
+static void
+task_list_set_show_all_windows (TaskList *list, gboolean show_all_windows)
+{
+ TaskListPrivate *priv = list->priv;
+
+ priv->show_all_windows = show_all_windows;
+
+ g_debug ("Show all windows: %s", show_all_windows ? "true" : "false");
+}
+
+static void
+on_task_item_closed (TaskItem *item,
+ TaskList *list)
+{
+ gtk_container_remove (GTK_CONTAINER (list),
+ GTK_WIDGET (item));
+ gtk_widget_destroy (GTK_WIDGET (item));
+}
+
+static void
+on_window_opened (MatewnckScreen *screen,
+ MatewnckWindow *window,
+ TaskList *list)
+{
+ TaskListPrivate *priv;
+ MatewnckWindowType type;
+
+ g_return_if_fail (TASK_IS_LIST (list));
+ priv = list->priv;
+
+ type = matewnck_window_get_window_type (window);
+
+ if (type == MATEWNCK_WINDOW_DESKTOP
+ || type == MATEWNCK_WINDOW_DOCK
+ || type == MATEWNCK_WINDOW_SPLASHSCREEN
+ || type == MATEWNCK_WINDOW_MENU)
+ return;
+
+ GtkWidget *item = task_item_new (window);
+
+ if (item)
+ {
+ gtk_box_pack_start (GTK_BOX (list), item, FALSE, FALSE, 0);
+ g_signal_connect (TASK_ITEM (item), "task-item-closed",
+ G_CALLBACK (on_task_item_closed), list);
+ }
+}
+
+/* GObject stuff */
+static void
+task_list_finalize (GObject *object)
+{
+ TaskListPrivate *priv;
+
+ priv = TASK_LIST_GET_PRIVATE (object);
+
+ /* Remove the blink timer */
+ if (priv->timer) g_source_remove (priv->timer);
+
+ G_OBJECT_CLASS (task_list_parent_class)->finalize (object);
+}
+
+static void
+task_list_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TaskList *list = TASK_LIST (object);
+ TaskListPrivate *priv;
+
+ g_return_if_fail (TASK_IS_LIST (list));
+ priv = list->priv;
+
+ switch (prop_id)
+ {
+ case PROP_SHOW_ALL_WINDOWS:
+ g_value_set_boolean (value, priv->show_all_windows);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+task_list_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TaskList *list = TASK_LIST (object);
+ TaskListPrivate *priv;
+
+ g_return_if_fail (TASK_IS_LIST (list));
+ priv = list->priv;
+
+ switch (prop_id)
+ {
+ case PROP_SHOW_ALL_WINDOWS:
+ task_list_set_show_all_windows (list, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+task_list_class_init (TaskListClass *klass)
+{
+ GObjectClass *obj_class = G_OBJECT_CLASS (klass);
+
+ obj_class->finalize = task_list_finalize;
+ obj_class->set_property = task_list_set_property;
+ obj_class->get_property = task_list_get_property;
+
+ g_object_class_install_property (obj_class,
+ PROP_SHOW_ALL_WINDOWS,
+ g_param_spec_boolean ("show_all_windows",
+ "Show All Windows",
+ "Show windows from all workspaces",
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_type_class_add_private (obj_class, sizeof (TaskListPrivate));
+}
+
+static void
+task_list_init (TaskList *list)
+{
+ TaskListPrivate *priv;
+
+ priv = list->priv = TASK_LIST_GET_PRIVATE (list);
+
+ priv->screen = matewnck_screen_get_default ();
+
+ priv->win_table = g_hash_table_new (NULL, NULL);
+
+ /* No blink timer */
+ priv->timer = 0;
+
+ gtk_container_set_border_width (GTK_CONTAINER (list), 0);
+
+ g_signal_connect (priv->screen, "window-opened",
+ G_CALLBACK (on_window_opened), list);
+}
+
+GtkWidget *
+task_list_new (void)
+
+{
+ GtkWidget *list = NULL;
+
+ list = g_object_new (TASK_TYPE_LIST,
+ "homogeneous", FALSE,
+ "spacing", 0,
+ NULL);
+
+ return list;
+}
+
+GtkWidget *
+task_list_get_default (void)
+{
+ static GtkWidget *list = NULL;
+
+ if (!list)
+ list = task_list_new ();
+
+ return list;
+}
+
+gboolean
+task_list_get_desktop_visible (TaskList *list)
+{
+ GList *windows, *w;
+ gboolean all_minimised = TRUE;
+
+ g_return_val_if_fail (TASK_IS_LIST (list), TRUE);
+
+ windows = matewnck_screen_get_windows (list->priv->screen);
+ for (w = windows; w; w = w->next)
+ {
+ MatewnckWindow *window;
+
+ window = w->data;
+
+ if (MATEWNCK_IS_WINDOW (window) && !matewnck_window_is_minimized (window))
+ all_minimised = FALSE;
+ }
+
+ return all_minimised;
+}
+
+gboolean
+task_list_get_show_all_windows (TaskList *list)
+{
+ return list->priv->show_all_windows;
+}
+
diff --git a/mate-window-picker-applet/task-list.h b/mate-window-picker-applet/task-list.h
new file mode 100644
index 0000000..87698ba
--- /dev/null
+++ b/mate-window-picker-applet/task-list.h
@@ -0,0 +1,70 @@
+/*
+ * 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]>
+ *
+ */
+
+#ifndef _TASK_LIST_H_
+#define _TASK_LIST_H_
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#define TASK_TYPE_LIST (task_list_get_type ())
+
+#define TASK_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
+ TASK_TYPE_LIST, TaskList))
+
+#define TASK_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\
+ TASK_TYPE_LIST, TaskListClass))
+
+#define TASK_IS_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
+ TASK_TYPE_LIST))
+
+#define TASK_IS_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\
+ TASK_TYPE_LIST))
+
+#define TASK_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
+ TASK_TYPE_LIST, TaskListClass))
+
+typedef struct _TaskList TaskList;
+typedef struct _TaskListClass TaskListClass;
+typedef struct _TaskListPrivate TaskListPrivate;
+
+struct _TaskList
+{
+ GtkHBox parent;
+
+ TaskListPrivate *priv;
+};
+
+struct _TaskListClass
+{
+ GtkHBoxClass parent_class;
+};
+
+GType task_list_get_type (void) G_GNUC_CONST;
+
+GtkWidget * task_list_new (void);
+
+GtkWidget * task_list_get_default (void);
+
+gboolean task_list_get_desktop_visible (TaskList *list);
+
+gboolean task_list_get_show_all_windows (TaskList *list);
+
+#endif /* _TASK_LIST_H_ */
+
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;
+}
diff --git a/mate-window-picker-applet/task-title.h b/mate-window-picker-applet/task-title.h
new file mode 100644
index 0000000..0a1d7ec
--- /dev/null
+++ b/mate-window-picker-applet/task-title.h
@@ -0,0 +1,66 @@
+/*
+ * 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]>
+ *
+ */
+
+#ifndef _TASK_TITLE_H_
+#define _TASK_TITLE_H_
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#define TASK_TYPE_TITLE (task_title_get_type ())
+
+#define TASK_TITLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
+ TASK_TYPE_TITLE, TaskTitle))
+
+#define TASK_TITLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\
+ TASK_TYPE_TITLE, TaskTitleClass))
+
+#define TASK_IS_TITLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
+ TASK_TYPE_TITLE))
+
+#define TASK_IS_TITLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\
+ TASK_TYPE_TITLE))
+
+#define TASK_TITLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
+ TASK_TYPE_TITLE, TaskTitleClass))
+
+typedef struct _TaskTitle TaskTitle;
+typedef struct _TaskTitleClass TaskTitleClass;
+typedef struct _TaskTitlePrivate TaskTitlePrivate;
+
+struct _TaskTitle
+{
+ GtkEventBox parent;
+
+ TaskTitlePrivate *priv;
+};
+
+struct _TaskTitleClass
+{
+ GtkEventBoxClass parent_class;
+};
+
+GType task_title_get_type (void) G_GNUC_CONST;
+
+GtkWidget * task_title_new (void);
+
+
+#endif /* _TASK_TITLE_H_ */
+