diff options
Diffstat (limited to 'applets/wncklet/workspace-switcher.c')
-rw-r--r-- | applets/wncklet/workspace-switcher.c | 932 |
1 files changed, 932 insertions, 0 deletions
diff --git a/applets/wncklet/workspace-switcher.c b/applets/wncklet/workspace-switcher.c new file mode 100644 index 00000000..cd241bea --- /dev/null +++ b/applets/wncklet/workspace-switcher.c @@ -0,0 +1,932 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/* + * libwnck based pager applet. + * (C) 2001 Alexander Larsson + * (C) 2001 Red Hat, Inc + * + * Authors: Alexander Larsson + * + */ + +#define WNCK_I_KNOW_THIS_IS_UNSTABLE 1 + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + +#include <string.h> + +#include <mate-panel-applet.h> +#include <mate-panel-applet-mateconf.h> + +#include <stdlib.h> + +#include <glib/gi18n.h> +#include <gtk/gtk.h> +#include <libwnck/libwnck.h> +#include <mateconf/mateconf-client.h> + +#include "workspace-switcher.h" + +#include "wncklet.h" + +/* even 16 is pretty darn dubious. */ +#define MAX_REASONABLE_ROWS 16 +#define DEFAULT_ROWS 1 + +#define NEVER_SENSITIVE "never_sensitive" +#define NUM_WORKSPACES "/apps/marco/general/num_workspaces" +#define WORKSPACE_NAME "/apps/marco/workspace_names/name_1" + +#define WORKSPACE_SWITCHER_ICON "mate-panel-workspace-switcher" + +typedef enum { + PAGER_WM_MARCO, + PAGER_WM_COMPIZ, + PAGER_WM_UNKNOWN +} PagerWM; + +typedef struct { + GtkWidget* applet; + + GtkWidget* pager; + + WnckScreen* screen; + PagerWM wm; + + /* Properties: */ + GtkWidget* properties_dialog; + GtkWidget* workspaces_frame; + GtkWidget* workspace_names_label; + GtkWidget* workspace_names_scroll; + GtkWidget* display_workspaces_toggle; + GtkWidget* all_workspaces_radio; + GtkWidget* current_only_radio; + GtkWidget* num_rows_spin; /* for vertical layout this is cols */ + GtkWidget* label_row_col; + GtkWidget* num_workspaces_spin; + GtkWidget* workspaces_tree; + GtkListStore* workspaces_store; + + GtkOrientation orientation; + int n_rows; /* for vertical layout this is cols */ + WnckPagerDisplayMode display_mode; + gboolean display_all; + + /* mateconf listeners id */ + guint listeners[3]; +} PagerData; + +static void display_properties_dialog(GtkAction* action, PagerData* pager); +static void display_help_dialog(GtkAction* action, PagerData* pager); +static void display_about_dialog(GtkAction* action, PagerData* pager); + +static void pager_update(PagerData* pager) +{ + wnck_pager_set_orientation(WNCK_PAGER(pager->pager), pager->orientation); + wnck_pager_set_n_rows(WNCK_PAGER(pager->pager), pager->n_rows); + wnck_pager_set_show_all(WNCK_PAGER(pager->pager), pager->display_all); + + if (pager->wm == PAGER_WM_MARCO) + wnck_pager_set_display_mode(WNCK_PAGER(pager->pager), pager->display_mode); + else + wnck_pager_set_display_mode(WNCK_PAGER(pager->pager), WNCK_PAGER_DISPLAY_CONTENT); +} + +static void update_properties_for_wm(PagerData* pager) +{ + switch (pager->wm) + { + case PAGER_WM_MARCO: + if (pager->workspaces_frame) + gtk_widget_show(pager->workspaces_frame); + if (pager->workspace_names_label) + gtk_widget_show(pager->workspace_names_label); + if (pager->workspace_names_scroll) + gtk_widget_show(pager->workspace_names_scroll); + if (pager->display_workspaces_toggle) + gtk_widget_show(pager->display_workspaces_toggle); + break; + case PAGER_WM_COMPIZ: + if (pager->workspaces_frame) + gtk_widget_show(pager->workspaces_frame); + if (pager->workspace_names_label) + gtk_widget_hide(pager->workspace_names_label); + if (pager->workspace_names_scroll) + gtk_widget_hide(pager->workspace_names_scroll); + if (pager->display_workspaces_toggle) + gtk_widget_hide(pager->display_workspaces_toggle); + break; + case PAGER_WM_UNKNOWN: + if (pager->workspaces_frame) + gtk_widget_hide(pager->workspaces_frame); + break; + default: + g_assert_not_reached(); + } + + if (pager->properties_dialog) + gtk_window_reshow_with_initial_size(GTK_WINDOW(pager->properties_dialog)); +} + +static void window_manager_changed(WnckScreen* screen, PagerData* pager) +{ + const char *wm_name; + + wm_name = wnck_screen_get_window_manager_name(screen); + + if (!wm_name) + pager->wm = PAGER_WM_UNKNOWN; + else if (strcmp(wm_name, "Marco") == 0) + pager->wm = PAGER_WM_MARCO; + else if (strcmp(wm_name, "Compiz") == 0) + pager->wm = PAGER_WM_COMPIZ; + else + pager->wm = PAGER_WM_UNKNOWN; + + update_properties_for_wm(pager); + pager_update(pager); +} + +static void applet_realized(MatePanelApplet* applet, PagerData* pager) +{ + pager->screen = wncklet_get_screen(GTK_WIDGET(applet)); + + window_manager_changed(pager->screen, pager); + wncklet_connect_while_alive(pager->screen, "window_manager_changed", G_CALLBACK(window_manager_changed), pager, pager->applet); +} + +static void applet_unrealized(MatePanelApplet* applet, PagerData* pager) +{ + pager->screen = NULL; + pager->wm = PAGER_WM_UNKNOWN; +} + +static void applet_change_orient(MatePanelApplet* applet, MatePanelAppletOrient orient, PagerData* pager) +{ + GtkOrientation new_orient; + + switch (orient) + { + case MATE_PANEL_APPLET_ORIENT_LEFT: + case MATE_PANEL_APPLET_ORIENT_RIGHT: + new_orient = GTK_ORIENTATION_VERTICAL; + break; + case MATE_PANEL_APPLET_ORIENT_UP: + case MATE_PANEL_APPLET_ORIENT_DOWN: + default: + new_orient = GTK_ORIENTATION_HORIZONTAL; + break; + } + + if (new_orient == pager->orientation) + return; + + pager->orientation = new_orient; + pager_update(pager); + + if (pager->label_row_col) + gtk_label_set_text(GTK_LABEL(pager->label_row_col), pager->orientation == GTK_ORIENTATION_HORIZONTAL ? _("rows") : _("columns")); +} + +static void applet_change_background(MatePanelApplet* applet, MatePanelAppletBackgroundType type, GdkColor* color, GdkPixmap* pixmap, PagerData* pager) +{ + switch (type) + { + case PANEL_NO_BACKGROUND: + wnck_pager_set_shadow_type(WNCK_PAGER(pager->pager), GTK_SHADOW_IN); + break; + case PANEL_COLOR_BACKGROUND: + wnck_pager_set_shadow_type(WNCK_PAGER(pager->pager), GTK_SHADOW_NONE); + break; + case PANEL_PIXMAP_BACKGROUND: + wnck_pager_set_shadow_type(WNCK_PAGER(pager->pager), GTK_SHADOW_NONE); + break; + } +} + +static gboolean applet_scroll(MatePanelApplet* applet, GdkEventScroll* event, PagerData* pager) +{ + GdkScrollDirection absolute_direction; + int index; + int n_workspaces; + int n_columns; + int in_last_row; + + if (event->type != GDK_SCROLL) + return FALSE; + + index = wnck_workspace_get_number(wnck_screen_get_active_workspace(pager->screen)); + n_workspaces = wnck_screen_get_workspace_count(pager->screen); + n_columns = n_workspaces / pager->n_rows; + + if (n_workspaces % pager->n_rows != 0) + n_columns++; + + in_last_row = n_workspaces % n_columns; + + absolute_direction = event->direction; + + if (gtk_widget_get_direction(GTK_WIDGET(applet)) == GTK_TEXT_DIR_RTL) + { + switch (event->direction) + { + case GDK_SCROLL_DOWN: + case GDK_SCROLL_UP: + break; + case GDK_SCROLL_RIGHT: + absolute_direction = GDK_SCROLL_LEFT; + break; + case GDK_SCROLL_LEFT: + absolute_direction = GDK_SCROLL_RIGHT; + break; + } + } + + switch (absolute_direction) + { + case GDK_SCROLL_DOWN: + if (index + n_columns < n_workspaces) + { + index += n_columns; + } + else if ((index < n_workspaces - 1 && index + in_last_row != n_workspaces - 1) || (index == n_workspaces - 1 && in_last_row != 0)) + { + index = (index % n_columns) + 1; + } + break; + + case GDK_SCROLL_RIGHT: + if (index < n_workspaces - 1) + index++; + break; + + case GDK_SCROLL_UP: + if (index - n_columns >= 0) + { + index -= n_columns; + } + else if (index > 0) + { + index = ((pager->n_rows - 1) * n_columns) + (index % n_columns) - 1; + } + + if (index >= n_workspaces) + index -= n_columns; + break; + + case GDK_SCROLL_LEFT: + if (index > 0) + index--; + break; + default: + g_assert_not_reached(); + break; + } + + wnck_workspace_activate(wnck_screen_get_workspace(pager->screen, index), event->time); + + return TRUE; +} + +static void destroy_pager(GtkWidget* widget, PagerData* pager) +{ + MateConfClient* client = mateconf_client_get_default(); + + mateconf_client_notify_remove(client, pager->listeners[0]); + mateconf_client_notify_remove(client, pager->listeners[1]); + mateconf_client_notify_remove(client, pager->listeners[2]); + + g_object_unref(G_OBJECT(client)); + + pager->listeners[0] = 0; + pager->listeners[1] = 0; + pager->listeners[2] = 0; + + if (pager->properties_dialog) + gtk_widget_destroy(pager->properties_dialog); + + g_free(pager); +} + +static const GtkActionEntry pager_menu_actions[] = { + { + "PagerPreferences", + GTK_STOCK_PROPERTIES, + N_("_Preferences"), + NULL, + NULL, + G_CALLBACK(display_properties_dialog) + }, + { + "PagerHelp", + GTK_STOCK_HELP, + N_("_Help"), + NULL, + NULL, + G_CALLBACK(display_help_dialog) + }, + { + "PagerAbout", + GTK_STOCK_ABOUT, + N_("_About"), + NULL, + NULL, + G_CALLBACK(display_about_dialog) + } +}; + +static void num_rows_changed(MateConfClient* client, guint cnxn_id, MateConfEntry* entry, PagerData* pager) +{ + int n_rows = DEFAULT_ROWS; + + if (entry->value != NULL && entry->value->type == MATECONF_VALUE_INT) + { + n_rows = mateconf_value_get_int(entry->value); + } + + n_rows = CLAMP(n_rows, 1, MAX_REASONABLE_ROWS); + + pager->n_rows = n_rows; + pager_update(pager); + + if (pager->num_rows_spin && gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(pager->num_rows_spin)) != n_rows) + gtk_spin_button_set_value(GTK_SPIN_BUTTON(pager->num_rows_spin), pager->n_rows); +} + +static void display_workspace_names_changed(MateConfClient* client, guint cnxn_id, MateConfEntry* entry, PagerData* pager) +{ + gboolean value = FALSE; /* Default value */ + + if (entry->value != NULL && entry->value->type == MATECONF_VALUE_BOOL) + { + value = mateconf_value_get_bool(entry->value); + } + + if (value) + { + pager->display_mode = WNCK_PAGER_DISPLAY_NAME; + } + else + { + pager->display_mode = WNCK_PAGER_DISPLAY_CONTENT; + } + + pager_update(pager); + + if (pager->display_workspaces_toggle && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pager->display_workspaces_toggle)) != value) + { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pager->display_workspaces_toggle), value); + } +} + + +static void all_workspaces_changed(MateConfClient* client, guint cnxn_id, MateConfEntry* entry, PagerData* pager) +{ + gboolean value = TRUE; /* Default value */ + + if (entry->value != NULL && entry->value->type == MATECONF_VALUE_BOOL) + { + value = mateconf_value_get_bool(entry->value); + } + + pager->display_all = value; + pager_update(pager); + + if (pager->all_workspaces_radio) + { + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pager->all_workspaces_radio)) != value) + { + if (value) + { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pager->all_workspaces_radio), TRUE); + } + else + { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pager->current_only_radio), TRUE); + } + } + + if (!g_object_get_data(G_OBJECT(pager->num_rows_spin), NEVER_SENSITIVE)) + gtk_widget_set_sensitive(pager->num_rows_spin, value); + } +} + +static void setup_mateconf(PagerData* pager) +{ + MateConfClient* client; + char* key; + + client = mateconf_client_get_default(); + + key = mate_panel_applet_mateconf_get_full_key(MATE_PANEL_APPLET(pager->applet), "num_rows"); + pager->listeners[0] = mateconf_client_notify_add(client, key, (MateConfClientNotifyFunc) num_rows_changed, pager, NULL, NULL); + + g_free(key); + + + key = mate_panel_applet_mateconf_get_full_key(MATE_PANEL_APPLET(pager->applet), "display_workspace_names"); + pager->listeners[1] = mateconf_client_notify_add(client, key, (MateConfClientNotifyFunc) display_workspace_names_changed, pager, NULL, NULL); + + g_free(key); + + key = mate_panel_applet_mateconf_get_full_key(MATE_PANEL_APPLET(pager->applet), "display_all_workspaces"); + pager->listeners[2] = mateconf_client_notify_add(client, key, (MateConfClientNotifyFunc) all_workspaces_changed, pager, NULL, NULL); + + g_free(key); + + g_object_unref(G_OBJECT(client)); +} + +gboolean workspace_switcher_applet_fill(MatePanelApplet* applet) +{ + PagerData* pager; + GtkActionGroup* action_group; + gchar* ui_path; + GError* error; + gboolean display_names; + + mate_panel_applet_add_preferences(applet, "/schemas/apps/workspace_switcher_applet/prefs", NULL); + + pager = g_new0(PagerData, 1); + + pager->applet = GTK_WIDGET(applet); + + mate_panel_applet_set_flags(MATE_PANEL_APPLET(pager->applet), MATE_PANEL_APPLET_EXPAND_MINOR); + + setup_mateconf(pager); + + error = NULL; + pager->n_rows = mate_panel_applet_mateconf_get_int(applet, "num_rows", &error); + + if (error) + { + g_printerr(_("Error loading num_rows value for Workspace Switcher: %s\n"), error->message); + g_error_free(error); + /* leave current value */ + } + + pager->n_rows = CLAMP(pager->n_rows, 1, MAX_REASONABLE_ROWS); + + error = NULL; + display_names = mate_panel_applet_mateconf_get_bool(applet, "display_workspace_names", &error); + + if (error) + { + g_printerr(_("Error loading display_workspace_names value for Workspace Switcher: %s\n"), error->message); + g_error_free(error); + /* leave current value */ + } + + if (display_names) + { + pager->display_mode = WNCK_PAGER_DISPLAY_NAME; + } + else + { + pager->display_mode = WNCK_PAGER_DISPLAY_CONTENT; + } + + error = NULL; + pager->display_all = mate_panel_applet_mateconf_get_bool(applet, "display_all_workspaces", &error); + + if (error) + { + g_printerr(_("Error loading display_all_workspaces value for Workspace Switcher: %s\n"), error->message); + g_error_free(error); + /* leave current value */ + } + + switch (mate_panel_applet_get_orient(applet)) + { + case MATE_PANEL_APPLET_ORIENT_LEFT: + case MATE_PANEL_APPLET_ORIENT_RIGHT: + pager->orientation = GTK_ORIENTATION_VERTICAL; + break; + case MATE_PANEL_APPLET_ORIENT_UP: + case MATE_PANEL_APPLET_ORIENT_DOWN: + default: + pager->orientation = GTK_ORIENTATION_HORIZONTAL; + break; + } + + pager->pager = wnck_pager_new(NULL); + pager->screen = NULL; + pager->wm = PAGER_WM_UNKNOWN; + wnck_pager_set_shadow_type(WNCK_PAGER(pager->pager), GTK_SHADOW_IN); + + g_signal_connect(G_OBJECT(pager->pager), "destroy", G_CALLBACK(destroy_pager), pager); + + gtk_container_add(GTK_CONTAINER(pager->applet), pager->pager); + gtk_widget_show(pager->pager); + + g_signal_connect(G_OBJECT(pager->applet), "realize", G_CALLBACK(applet_realized), pager); + g_signal_connect(G_OBJECT(pager->applet), "unrealize", G_CALLBACK(applet_unrealized), pager); + g_signal_connect(G_OBJECT(pager->applet), "change_orient", G_CALLBACK(applet_change_orient), pager); + g_signal_connect(G_OBJECT(pager->applet), "scroll-event", G_CALLBACK(applet_scroll), pager); + g_signal_connect(G_OBJECT(pager->applet), "change_background", G_CALLBACK(applet_change_background), pager); + + gtk_widget_show(pager->applet); + + mate_panel_applet_set_background_widget(MATE_PANEL_APPLET(pager->applet), GTK_WIDGET(pager->applet)); + + action_group = gtk_action_group_new("WorkspaceSwitcher Applet Actions"); + gtk_action_group_set_translation_domain(action_group, GETTEXT_PACKAGE); + gtk_action_group_add_actions(action_group, pager_menu_actions, G_N_ELEMENTS(pager_menu_actions), pager); + ui_path = g_build_filename(WNCK_MENU_UI_DIR, "workspace-switcher-menu.xml", NULL); + mate_panel_applet_setup_menu_from_file(MATE_PANEL_APPLET(pager->applet), ui_path, action_group); + g_free(ui_path); + + if (mate_panel_applet_get_locked_down(MATE_PANEL_APPLET(pager->applet))) + { + GtkAction *action; + + action = gtk_action_group_get_action(action_group, "PagerPreferences"); + gtk_action_set_visible(action, FALSE); + } + + g_object_unref(action_group); + + return TRUE; +} + + +static void display_help_dialog(GtkAction* action, PagerData* pager) +{ + wncklet_display_help(pager->applet, "user-guide", "overview-workspaces", WORKSPACE_SWITCHER_ICON); +} + +static void display_about_dialog(GtkAction* action, PagerData* pager) +{ + static const gchar* authors[] = { + "Alexander Larsson <[email protected]>", + NULL + }; + + const char* documenters[] = { + "John Fleck <[email protected]>", + "Sun MATE Documentation Team <[email protected]>", + NULL + }; + + char copyright[] = \ + "Copyright \xc2\xa9 2001-2002 Red Hat, Inc."; + + gtk_show_about_dialog(GTK_WINDOW(pager->applet), + "program-name", _("Workspace Switcher"), + "authors", authors, + "comments", _("The Workspace Switcher shows you a small version of your workspaces that lets you manage your windows."), + "copyright", copyright, + "documenters", documenters, + "icon-name", WORKSPACE_SWITCHER_ICON, + "logo-icon-name", WORKSPACE_SWITCHER_ICON, + "translator-credits", _("translator-credits"), + "version", VERSION, + "website", "http://matsusoft.com.ar/projects/mate/", + NULL); +} + + +static void display_workspace_names_toggled(GtkToggleButton*button, PagerData* pager) +{ + mate_panel_applet_mateconf_set_bool(MATE_PANEL_APPLET(pager->applet), "display_workspace_names", gtk_toggle_button_get_active(button), NULL); +} + +static void all_workspaces_toggled(GtkToggleButton* button, PagerData* pager) +{ + mate_panel_applet_mateconf_set_bool(MATE_PANEL_APPLET(pager->applet), "display_all_workspaces", gtk_toggle_button_get_active(button), NULL); +} + +static void num_rows_value_changed(GtkSpinButton* button, PagerData* pager) +{ + mate_panel_applet_mateconf_set_int(MATE_PANEL_APPLET(pager->applet), "num_rows", gtk_spin_button_get_value_as_int(button), NULL); +} + +static void update_workspaces_model(PagerData* pager) +{ + int nr_ws, i; + WnckWorkspace* workspace; + GtkTreeIter iter; + + nr_ws = wnck_screen_get_workspace_count(pager->screen); + + if (pager->properties_dialog) + { + if (nr_ws != gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(pager->num_workspaces_spin))) + gtk_spin_button_set_value(GTK_SPIN_BUTTON(pager->num_workspaces_spin), nr_ws); + + gtk_list_store_clear(pager->workspaces_store); + + for (i = 0; i < nr_ws; i++) + { + workspace = wnck_screen_get_workspace(pager->screen, i); + gtk_list_store_append(pager->workspaces_store, &iter); + gtk_list_store_set(pager->workspaces_store, &iter, 0, wnck_workspace_get_name(workspace), -1); + } + } +} + +static void workspace_renamed(WnckWorkspace* space, PagerData* pager) +{ + int i; + GtkTreeIter iter; + + i = wnck_workspace_get_number(space); + + if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(pager->workspaces_store), &iter, NULL, i)) + gtk_list_store_set(pager->workspaces_store, &iter, 0, wnck_workspace_get_name(space), -1); +} + +static void workspace_created(WnckScreen* screen, WnckWorkspace* space, PagerData* pager) +{ + g_return_if_fail(WNCK_IS_SCREEN(screen)); + + update_workspaces_model(pager); + + wncklet_connect_while_alive(space, "name_changed", G_CALLBACK(workspace_renamed), pager, pager->properties_dialog); +} + +static void workspace_destroyed(WnckScreen* screen, WnckWorkspace* space, PagerData* pager) +{ + g_return_if_fail(WNCK_IS_SCREEN(screen)); + update_workspaces_model(pager); +} + +static void num_workspaces_value_changed(GtkSpinButton* button, PagerData* pager) +{ + /* Slow down a bit after the first change, since it's moving really to + * fast. See bug #336731 for background. + * FIXME: remove this if bug 410520 gets fixed. */ + button->timer_step = 0.2; + + wnck_screen_change_workspace_count(pager->screen, gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(pager->num_workspaces_spin))); +} + +static gboolean workspaces_tree_focused_out(GtkTreeView* treeview, GdkEventFocus* event, PagerData* pager) +{ + GtkTreeSelection* selection; + + selection = gtk_tree_view_get_selection(treeview); + gtk_tree_selection_unselect_all(selection); + return TRUE; +} + +static void workspace_name_edited(GtkCellRendererText* cell_renderer_text, const gchar* path, const gchar* new_text, PagerData* pager) +{ + const gint* indices; + WnckWorkspace* workspace; + GtkTreePath* p; + + p = gtk_tree_path_new_from_string(path); + indices = gtk_tree_path_get_indices(p); + workspace = wnck_screen_get_workspace(pager->screen, indices[0]); + + if (workspace != NULL) + { + gchar* temp_name = g_strdup(new_text); + + wnck_workspace_change_name(workspace, g_strstrip(temp_name)); + + g_free(temp_name); + } + else + { + g_warning("Edited name of workspace %d which no longer exists", indices[0]); + } + + gtk_tree_path_free(p); +} + +static void properties_dialog_destroyed(GtkWidget* widget, PagerData* pager) +{ + pager->properties_dialog = NULL; + pager->workspaces_frame = NULL; + pager->workspace_names_label = NULL; + pager->workspace_names_scroll = NULL; + pager->display_workspaces_toggle = NULL; + pager->all_workspaces_radio = NULL; + pager->current_only_radio = NULL; + pager->num_rows_spin = NULL; + pager->label_row_col = NULL; + pager->num_workspaces_spin = NULL; + pager->workspaces_tree = NULL; + pager->workspaces_store = NULL; +} + +static gboolean delete_event(GtkWidget* widget, gpointer data) +{ + gtk_widget_destroy(widget); + return TRUE; +} + +static void response_cb(GtkWidget* widget, int id, PagerData* pager) +{ + if (id == GTK_RESPONSE_HELP) + wncklet_display_help(widget, "user-guide", "overview-workspaces", WORKSPACE_SWITCHER_ICON); + else + gtk_widget_destroy(widget); +} + +static void close_dialog(GtkWidget* button, gpointer data) +{ + PagerData* pager = data; + GtkTreeViewColumn* col; + + /* This is a hack. The "editable" signal for GtkCellRenderer is emitted + only on button press or focus cycle. Hence when the user changes the + name and closes the preferences dialog without a button-press he would + lose the name changes. So, we call the gtk_cell_editable_editing_done + to stop the editing. Thanks to Paolo for a better crack than the one I had. + */ + + col = gtk_tree_view_get_column(GTK_TREE_VIEW(pager->workspaces_tree), 0); + + if (col->editable_widget != NULL && GTK_IS_CELL_EDITABLE(col->editable_widget)) + gtk_cell_editable_editing_done(col->editable_widget); + + gtk_widget_destroy(pager->properties_dialog); +} + +#define WID(s) GTK_WIDGET(gtk_builder_get_object(builder, s)) + +static void +setup_sensitivity(PagerData* pager, GtkBuilder* builder, const char* wid1, const char* wid2, const char* wid3, const char* key) +{ + MatePanelApplet* applet = MATE_PANEL_APPLET(pager->applet); + MateConfClient* client = mateconf_client_get_default(); + char* fullkey; + GtkWidget* w; + + if (key[0] == '/') + fullkey = g_strdup(key); + else + fullkey = mate_panel_applet_mateconf_get_full_key(applet, key); + + if (mateconf_client_key_is_writable(client, fullkey, NULL)) + { + g_object_unref(G_OBJECT(client)); + g_free(fullkey); + return; + } + + g_object_unref(G_OBJECT(client)); + g_free(fullkey); + + w = WID(wid1); + g_assert(w != NULL); + g_object_set_data(G_OBJECT(w), NEVER_SENSITIVE, GINT_TO_POINTER(1)); + gtk_widget_set_sensitive(w, FALSE); + + if (wid2 != NULL) + { + w = WID(wid2); + g_assert(w != NULL); + g_object_set_data(G_OBJECT(w), NEVER_SENSITIVE, GINT_TO_POINTER(1)); + gtk_widget_set_sensitive(w, FALSE); + } + + if (wid3 != NULL) + { + w = WID(wid3); + g_assert(w != NULL); + g_object_set_data(G_OBJECT(w), NEVER_SENSITIVE, GINT_TO_POINTER(1)); + gtk_widget_set_sensitive(w, FALSE); + } +} + +static void setup_dialog(GtkBuilder* builder, PagerData* pager) +{ + gboolean value; + GtkTreeViewColumn* column; + GtkCellRenderer* cell; + int nr_ws, i; + + pager->workspaces_frame = WID("workspaces_frame"); + pager->workspace_names_label = WID("workspace_names_label"); + pager->workspace_names_scroll = WID("workspace_names_scroll"); + + pager->display_workspaces_toggle = WID("workspace_name_toggle"); + setup_sensitivity(pager, builder, "workspace_name_toggle", NULL, NULL, "display_workspace_names" /* key */); + + pager->all_workspaces_radio = WID("all_workspaces_radio"); + pager->current_only_radio = WID("current_only_radio"); + setup_sensitivity(pager, builder, "all_workspaces_radio", "current_only_radio", "label_row_col", "display_all_workspaces" /* key */); + + pager->num_rows_spin = WID("num_rows_spin"); + pager->label_row_col = WID("label_row_col"); + setup_sensitivity(pager, builder, "num_rows_spin", NULL, NULL, "num_rows" /* key */); + + pager->num_workspaces_spin = WID("num_workspaces_spin"); + setup_sensitivity(pager, builder, "num_workspaces_spin", NULL, NULL, NUM_WORKSPACES /* key */); + + pager->workspaces_tree = WID("workspaces_tree_view"); + setup_sensitivity(pager, builder, "workspaces_tree_view", NULL, NULL, WORKSPACE_NAME /* key */); + + /* Display workspace names: */ + + g_signal_connect(G_OBJECT(pager->display_workspaces_toggle), "toggled", (GCallback) display_workspace_names_toggled, pager); + + if (pager->display_mode == WNCK_PAGER_DISPLAY_NAME) + { + value = TRUE; + } + else + { + value = FALSE; + } + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pager->display_workspaces_toggle), value); + + /* Display all workspaces: */ + g_signal_connect(G_OBJECT(pager->all_workspaces_radio), "toggled", (GCallback) all_workspaces_toggled, pager); + + if (pager->display_all) + { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pager->all_workspaces_radio), TRUE); + + if (!g_object_get_data(G_OBJECT(pager->num_rows_spin), NEVER_SENSITIVE)) + { + gtk_widget_set_sensitive(pager->num_rows_spin, TRUE); + } + } + else + { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pager->current_only_radio), TRUE); + gtk_widget_set_sensitive(pager->num_rows_spin, FALSE); + } + + /* Num rows: */ + g_signal_connect(G_OBJECT(pager->num_rows_spin), "value_changed", (GCallback) num_rows_value_changed, pager); + + gtk_spin_button_set_value(GTK_SPIN_BUTTON(pager->num_rows_spin), pager->n_rows); + gtk_label_set_text(GTK_LABEL(pager->label_row_col), pager->orientation == GTK_ORIENTATION_HORIZONTAL ? _("rows") : _("columns")); + + g_signal_connect(pager->properties_dialog, "destroy", G_CALLBACK(properties_dialog_destroyed), pager); + g_signal_connect(pager->properties_dialog, "delete_event", G_CALLBACK(delete_event), pager); + g_signal_connect(pager->properties_dialog, "response", G_CALLBACK(response_cb), pager); + + g_signal_connect(WID("done_button"), "clicked", (GCallback) close_dialog, pager); + + gtk_spin_button_set_value(GTK_SPIN_BUTTON(pager->num_workspaces_spin), wnck_screen_get_workspace_count(pager->screen)); + g_signal_connect(G_OBJECT(pager->num_workspaces_spin), "value_changed", (GCallback) num_workspaces_value_changed, pager); + + wncklet_connect_while_alive(pager->screen, "workspace_created", G_CALLBACK(workspace_created), pager, pager->properties_dialog); + + wncklet_connect_while_alive(pager->screen, "workspace_destroyed", G_CALLBACK(workspace_destroyed), pager, pager->properties_dialog); + + g_signal_connect(G_OBJECT(pager->workspaces_tree), "focus_out_event", (GCallback) workspaces_tree_focused_out, pager); + + pager->workspaces_store = gtk_list_store_new(1, G_TYPE_STRING, NULL); + update_workspaces_model(pager); + gtk_tree_view_set_model(GTK_TREE_VIEW(pager->workspaces_tree), GTK_TREE_MODEL(pager->workspaces_store)); + + g_object_unref(pager->workspaces_store); + + cell = g_object_new(GTK_TYPE_CELL_RENDERER_TEXT, "editable", TRUE, NULL); + column = gtk_tree_view_column_new_with_attributes("workspace", cell, "text", 0, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(pager->workspaces_tree), column); + g_signal_connect(cell, "edited", (GCallback) workspace_name_edited, pager); + + nr_ws = wnck_screen_get_workspace_count(pager->screen); + + for (i = 0; i < nr_ws; i++) + { + wncklet_connect_while_alive(G_OBJECT(wnck_screen_get_workspace(pager->screen, i)), "name_changed", G_CALLBACK(workspace_renamed), pager, pager->properties_dialog); + } + + update_properties_for_wm(pager); +} + +static void display_properties_dialog(GtkAction* action, PagerData* pager) +{ + if (pager->properties_dialog == NULL) + { + GtkBuilder* builder; + GError* error; + + builder = gtk_builder_new(); + gtk_builder_set_translation_domain(builder, GETTEXT_PACKAGE); + + error = NULL; + gtk_builder_add_from_file(builder, PAGER_BUILDERDIR "/workspace-switcher.ui", &error); + + if (error) + { + g_warning("Error loading preferences: %s", error->message); + g_error_free(error); + return; + } + + pager->properties_dialog = WID("pager_properties_dialog"); + + g_object_add_weak_pointer(G_OBJECT(pager->properties_dialog), (gpointer*) &pager->properties_dialog); + + setup_dialog(builder, pager); + + g_object_unref(builder); + } + + gtk_window_set_icon_name(GTK_WINDOW(pager->properties_dialog), WORKSPACE_SWITCHER_ICON); + gtk_window_set_screen(GTK_WINDOW(pager->properties_dialog), gtk_widget_get_screen(pager->applet)); + gtk_window_present(GTK_WINDOW(pager->properties_dialog)); +} |