diff --git a/src/display.c b/src/display.c index 7858951b7..df2169a96 100644 --- a/src/display.c +++ b/src/display.c @@ -84,7 +84,9 @@ meta_display_open (const char *name) "MOTIF_WM_HINTS", "_NET_WM_STATE_SHADED", "_NET_WM_STATE_MAXIMIZED_HORZ", - "_NET_WM_STATE_MAXIMIZED_VERT" + "_NET_WM_STATE_MAXIMIZED_VERT", + "_NET_WM_DESKTOP", + "_NET_NUMBER_OF_DESKTOPS" }; Atom atoms[G_N_ELEMENTS(atom_names)]; @@ -111,13 +113,29 @@ meta_display_open (const char *name) display->name = g_strdup (XDisplayName (name)); display->xdisplay = xdisplay; display->error_traps = NULL; - + display->server_grab_count = 0; display->workspaces = NULL; /* we have to go ahead and do this so error handlers work */ all_displays = g_slist_prepend (all_displays, display); meta_display_init_keys (display); + + XInternAtoms (display->xdisplay, atom_names, G_N_ELEMENTS (atom_names), + False, atoms); + display->atom_net_wm_name = atoms[0]; + display->atom_wm_protocols = atoms[1]; + display->atom_wm_take_focus = atoms[2]; + display->atom_wm_delete_window = atoms[3]; + display->atom_wm_state = atoms[4]; + display->atom_net_close_window = atoms[5]; + display->atom_net_wm_state = atoms[6]; + display->atom_motif_wm_hints = atoms[7]; + display->atom_net_wm_state_shaded = atoms[8]; + display->atom_net_wm_state_maximized_horz = atoms[9]; + display->atom_net_wm_state_maximized_vert = atoms[10]; + display->atom_net_wm_desktop = atoms[11]; + display->atom_net_number_of_desktops = atoms[12]; screens = NULL; i = 0; @@ -151,22 +169,6 @@ meta_display_open (const char *name) display); display->window_ids = g_hash_table_new (unsigned_long_hash, unsigned_long_equal); - - display->server_grab_count = 0; - - XInternAtoms (display->xdisplay, atom_names, G_N_ELEMENTS (atom_names), - False, atoms); - display->atom_net_wm_name = atoms[0]; - display->atom_wm_protocols = atoms[1]; - display->atom_wm_take_focus = atoms[2]; - display->atom_wm_delete_window = atoms[3]; - display->atom_wm_state = atoms[4]; - display->atom_net_close_window = atoms[5]; - display->atom_net_wm_state = atoms[6]; - display->atom_motif_wm_hints = atoms[7]; - display->atom_net_wm_state_shaded = atoms[8]; - display->atom_net_wm_state_maximized_horz = atoms[9]; - display->atom_net_wm_state_maximized_vert = atoms[10]; display->double_click_time = 250; display->last_button_time = 0; @@ -551,6 +553,27 @@ event_queue_callback (MetaEventQueue *queue, */ meta_window_delete (window, CurrentTime); } + else if (event->xclient.message_type == + display->atom_net_wm_desktop) + { + int space; + MetaWorkspace *workspace; + + space = event->xclient.data.l[0]; + + meta_verbose ("Request to move %s to screen workspace %d\n", + window->desc, space); + + workspace = + meta_display_get_workspace_by_screen_index (display, + window->screen, + space); + + if (workspace) + meta_window_change_workspace (window, workspace); + else + meta_verbose ("No such workspace %d for screen\n", space); + } } break; case MappingNotify: diff --git a/src/display.h b/src/display.h index 45be6ae8e..1b3ef03d7 100644 --- a/src/display.h +++ b/src/display.h @@ -50,6 +50,8 @@ struct _MetaDisplay Atom atom_net_wm_state_shaded; Atom atom_net_wm_state_maximized_horz; Atom atom_net_wm_state_maximized_vert; + Atom atom_net_wm_desktop; + Atom atom_net_number_of_desktops; /* This is the actual window from focus events, * not the one we last set @@ -106,5 +108,4 @@ MetaWorkspace* meta_display_get_workspace_by_screen_index (MetaDisplay *displa MetaScreen *screen, int index); - #endif diff --git a/src/menu.c b/src/menu.c index 81015dd60..5e77abc97 100644 --- a/src/menu.c +++ b/src/menu.c @@ -22,6 +22,7 @@ #include "menu.h" #include "main.h" #include +#include typedef struct _MenuItem MenuItem; typedef struct _MenuData MenuData; @@ -44,9 +45,10 @@ static void activate_cb (GtkWidget *menuitem, gpointer data); static GtkWidget *menu = NULL; static MenuItem menuitems[] = { - { META_MESSAGE_MENU_DELETE, GTK_STOCK_CLOSE, N_("Close") }, - { META_MESSAGE_MENU_MINIMIZE, NULL, N_("Minimize") }, - { META_MESSAGE_MENU_MAXIMIZE, NULL, N_("Maximize") } + { META_MESSAGE_MENU_DELETE, GTK_STOCK_CLOSE, N_("_Close") }, + { META_MESSAGE_MENU_MINIMIZE, NULL, N_("_Minimize") }, + { META_MESSAGE_MENU_MAXIMIZE, NULL, N_("Ma_ximize") }, + { META_MESSAGE_MENU_SHADE, NULL, N_("_Shade") } }; static void @@ -71,6 +73,67 @@ popup_position_func (GtkMenu *menu, *y = CLAMP (*y, 0, MAX (0, gdk_screen_height () - req.height)); } +static gint +get_num_desktops (void) +{ + Atom type; + gint format; + gulong nitems; + gulong bytes_after; + gulong *num; + int result; + + XGetWindowProperty (gdk_display, gdk_root_window, + gdk_atom_intern ("_NET_NUMBER_OF_DESKTOPS", FALSE), + 0, G_MAXLONG, + False, XA_CARDINAL, &type, &format, &nitems, + &bytes_after, (guchar **)&num); + + if (type != XA_CARDINAL) + return 0; + + result = *num; + + XFree (num); + + return result; +} + +static gulong +get_current_desktop (GdkWindow *window) +{ + Atom type; + gint format; + gulong nitems; + gulong bytes_after; + gulong *num; + gulong result; + int err; + + gdk_error_trap_push (); + type = None; + XGetWindowProperty (gdk_display, GDK_WINDOW_XID (window), + gdk_atom_intern ("_NET_WM_DESKTOP", FALSE), + 0, G_MAXLONG, + False, XA_CARDINAL, &type, &format, &nitems, + &bytes_after, (guchar **)&num); + err = gdk_error_trap_pop (); + if (err != Success) + meta_ui_warning ("Error %d getting _NET_WM_DESKTOP\n", err); + + if (type != XA_CARDINAL) + { + meta_ui_warning ("_NET_WM_DESKTOP has wrong type %s\n", gdk_atom_name (type)); + return -1; + } + + result = *num; + + XFree (num); + + return result; +} + void meta_window_menu_show (gulong xwindow, int root_x, int root_y, @@ -82,6 +145,8 @@ meta_window_menu_show (gulong xwindow, int i; GdkWindow *window; GdkPoint *pt; + int n_workspaces; + int current_workspace; if (menu) gtk_widget_destroy (menu); @@ -110,7 +175,7 @@ meta_window_menu_show (gulong xwindow, { GtkWidget *image; - mi = gtk_image_menu_item_new_with_label (menuitems[i].label); + mi = gtk_image_menu_item_new_with_mnemonic (menuitems[i].label); image = gtk_image_new_from_stock (menuitems[i].stock_id, GTK_ICON_SIZE_MENU); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), @@ -119,7 +184,7 @@ meta_window_menu_show (gulong xwindow, } else { - mi = gtk_menu_item_new_with_label (menuitems[i].label); + mi = gtk_menu_item_new_with_mnemonic (menuitems[i].label); } if (insensitive & menuitems[i].op) @@ -142,6 +207,60 @@ meta_window_menu_show (gulong xwindow, } ++i; } + + if (ops & META_MESSAGE_MENU_WORKSPACES) + { + n_workspaces = get_num_desktops (); + current_workspace = get_current_desktop (window); + + meta_ui_warning ("Creating %d workspace menu current %d\n", + n_workspaces, current_workspace); + + if (n_workspaces > 0 && current_workspace >= 0) + { + i = 0; + while (i < n_workspaces) + { + char *label; + GtkWidget *mi; + MenuData *md; + + label = g_strdup_printf (_("Move to workspace _%d\n"), + i + 1); + + mi = gtk_menu_item_new_with_mnemonic (label); + + g_free (label); + + if (current_workspace == i || + insensitive & META_MESSAGE_MENU_WORKSPACES) + gtk_widget_set_sensitive (mi, FALSE); + + md = g_new (MenuData, 1); + + md->window = window; + md->op = META_MESSAGE_MENU_WORKSPACES; + + g_object_set_data (G_OBJECT (mi), + "workspace", + GINT_TO_POINTER (i)); + + gtk_signal_connect (GTK_OBJECT (mi), + "activate", + GTK_SIGNAL_FUNC (activate_cb), + md); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), + mi); + + gtk_widget_show (mi); + + ++i; + } + } + } + else + meta_ui_warning ("not creating workspace menu\n"); gtk_signal_connect (GTK_OBJECT (menu), "destroy", @@ -196,6 +315,58 @@ close_window (GdkWindow *window) gdk_error_trap_pop (); } +static void +wmspec_change_state (gboolean add, + GdkWindow *window, + GdkAtom state1, + GdkAtom state2) +{ + XEvent xev; + Atom op; + + if (add) + op = gdk_atom_intern ("_NET_WM_STATE_ADD", FALSE); + else + op = gdk_atom_intern ("_NET_WM_STATE_REMOVE", FALSE); + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = gdk_display; + xev.xclient.window = GDK_WINDOW_XID (window); + xev.xclient.message_type = gdk_atom_intern ("_NET_WM_STATE", FALSE); + xev.xclient.format = 32; + xev.xclient.data.l[0] = op; + xev.xclient.data.l[1] = state1; + xev.xclient.data.l[2] = state2; + + XSendEvent (gdk_display, gdk_root_window, False, + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); +} + +static void +wmspec_change_desktop (GdkWindow *window, + gint desktop) +{ + XEvent xev; + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = gdk_display; + xev.xclient.window = GDK_WINDOW_XID (window); + xev.xclient.message_type = gdk_atom_intern ("_NET_WM_DESKTOP", FALSE); + xev.xclient.format = 32; + xev.xclient.data.l[0] = desktop; + xev.xclient.data.l[1] = 0; + xev.xclient.data.l[2] = 0; + + XSendEvent (gdk_display, gdk_root_window, False, + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); +} + static void activate_cb (GtkWidget *menuitem, gpointer data) { @@ -219,6 +390,23 @@ activate_cb (GtkWidget *menuitem, gpointer data) gdk_error_trap_pop (); break; + case META_MESSAGE_MENU_SHADE: + wmspec_change_state (TRUE, md->window, + gdk_atom_intern ("_NET_WM_STATE_SHADED", FALSE), + 0); + break; + + case META_MESSAGE_MENU_WORKSPACES: + { + int workspace; + + workspace = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem), + "workspace")); + + wmspec_change_desktop (md->window, workspace); + } + break; + default: meta_ui_warning (G_STRLOC": Unknown window op\n"); break; diff --git a/src/screen.c b/src/screen.c index 1c262cd58..75851c66c 100644 --- a/src/screen.c +++ b/src/screen.c @@ -460,3 +460,25 @@ meta_screen_hide_tip (MetaScreen *screen) screen->showing_tooltip = FALSE; } } + +int +meta_screen_get_n_workspaces (MetaScreen *screen) +{ + GList *tmp; + int i; + + i = 0; + tmp = screen->display->workspaces; + while (tmp != NULL) + { + MetaWorkspace *w = tmp->data; + + if (w->screen == screen) + ++i; + + tmp = tmp->next; + } + + return i; + +} diff --git a/src/screen.h b/src/screen.h index 50647915e..398ca158c 100644 --- a/src/screen.h +++ b/src/screen.h @@ -77,6 +77,9 @@ void meta_screen_show_tip (MetaScreen *scree const char *markup); void meta_screen_hide_tip (MetaScreen *screen); +int meta_screen_get_n_workspaces (MetaScreen *screen); + + #endif diff --git a/src/uislave/menu.c b/src/uislave/menu.c index 81015dd60..5e77abc97 100644 --- a/src/uislave/menu.c +++ b/src/uislave/menu.c @@ -22,6 +22,7 @@ #include "menu.h" #include "main.h" #include +#include typedef struct _MenuItem MenuItem; typedef struct _MenuData MenuData; @@ -44,9 +45,10 @@ static void activate_cb (GtkWidget *menuitem, gpointer data); static GtkWidget *menu = NULL; static MenuItem menuitems[] = { - { META_MESSAGE_MENU_DELETE, GTK_STOCK_CLOSE, N_("Close") }, - { META_MESSAGE_MENU_MINIMIZE, NULL, N_("Minimize") }, - { META_MESSAGE_MENU_MAXIMIZE, NULL, N_("Maximize") } + { META_MESSAGE_MENU_DELETE, GTK_STOCK_CLOSE, N_("_Close") }, + { META_MESSAGE_MENU_MINIMIZE, NULL, N_("_Minimize") }, + { META_MESSAGE_MENU_MAXIMIZE, NULL, N_("Ma_ximize") }, + { META_MESSAGE_MENU_SHADE, NULL, N_("_Shade") } }; static void @@ -71,6 +73,67 @@ popup_position_func (GtkMenu *menu, *y = CLAMP (*y, 0, MAX (0, gdk_screen_height () - req.height)); } +static gint +get_num_desktops (void) +{ + Atom type; + gint format; + gulong nitems; + gulong bytes_after; + gulong *num; + int result; + + XGetWindowProperty (gdk_display, gdk_root_window, + gdk_atom_intern ("_NET_NUMBER_OF_DESKTOPS", FALSE), + 0, G_MAXLONG, + False, XA_CARDINAL, &type, &format, &nitems, + &bytes_after, (guchar **)&num); + + if (type != XA_CARDINAL) + return 0; + + result = *num; + + XFree (num); + + return result; +} + +static gulong +get_current_desktop (GdkWindow *window) +{ + Atom type; + gint format; + gulong nitems; + gulong bytes_after; + gulong *num; + gulong result; + int err; + + gdk_error_trap_push (); + type = None; + XGetWindowProperty (gdk_display, GDK_WINDOW_XID (window), + gdk_atom_intern ("_NET_WM_DESKTOP", FALSE), + 0, G_MAXLONG, + False, XA_CARDINAL, &type, &format, &nitems, + &bytes_after, (guchar **)&num); + err = gdk_error_trap_pop (); + if (err != Success) + meta_ui_warning ("Error %d getting _NET_WM_DESKTOP\n", err); + + if (type != XA_CARDINAL) + { + meta_ui_warning ("_NET_WM_DESKTOP has wrong type %s\n", gdk_atom_name (type)); + return -1; + } + + result = *num; + + XFree (num); + + return result; +} + void meta_window_menu_show (gulong xwindow, int root_x, int root_y, @@ -82,6 +145,8 @@ meta_window_menu_show (gulong xwindow, int i; GdkWindow *window; GdkPoint *pt; + int n_workspaces; + int current_workspace; if (menu) gtk_widget_destroy (menu); @@ -110,7 +175,7 @@ meta_window_menu_show (gulong xwindow, { GtkWidget *image; - mi = gtk_image_menu_item_new_with_label (menuitems[i].label); + mi = gtk_image_menu_item_new_with_mnemonic (menuitems[i].label); image = gtk_image_new_from_stock (menuitems[i].stock_id, GTK_ICON_SIZE_MENU); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), @@ -119,7 +184,7 @@ meta_window_menu_show (gulong xwindow, } else { - mi = gtk_menu_item_new_with_label (menuitems[i].label); + mi = gtk_menu_item_new_with_mnemonic (menuitems[i].label); } if (insensitive & menuitems[i].op) @@ -142,6 +207,60 @@ meta_window_menu_show (gulong xwindow, } ++i; } + + if (ops & META_MESSAGE_MENU_WORKSPACES) + { + n_workspaces = get_num_desktops (); + current_workspace = get_current_desktop (window); + + meta_ui_warning ("Creating %d workspace menu current %d\n", + n_workspaces, current_workspace); + + if (n_workspaces > 0 && current_workspace >= 0) + { + i = 0; + while (i < n_workspaces) + { + char *label; + GtkWidget *mi; + MenuData *md; + + label = g_strdup_printf (_("Move to workspace _%d\n"), + i + 1); + + mi = gtk_menu_item_new_with_mnemonic (label); + + g_free (label); + + if (current_workspace == i || + insensitive & META_MESSAGE_MENU_WORKSPACES) + gtk_widget_set_sensitive (mi, FALSE); + + md = g_new (MenuData, 1); + + md->window = window; + md->op = META_MESSAGE_MENU_WORKSPACES; + + g_object_set_data (G_OBJECT (mi), + "workspace", + GINT_TO_POINTER (i)); + + gtk_signal_connect (GTK_OBJECT (mi), + "activate", + GTK_SIGNAL_FUNC (activate_cb), + md); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), + mi); + + gtk_widget_show (mi); + + ++i; + } + } + } + else + meta_ui_warning ("not creating workspace menu\n"); gtk_signal_connect (GTK_OBJECT (menu), "destroy", @@ -196,6 +315,58 @@ close_window (GdkWindow *window) gdk_error_trap_pop (); } +static void +wmspec_change_state (gboolean add, + GdkWindow *window, + GdkAtom state1, + GdkAtom state2) +{ + XEvent xev; + Atom op; + + if (add) + op = gdk_atom_intern ("_NET_WM_STATE_ADD", FALSE); + else + op = gdk_atom_intern ("_NET_WM_STATE_REMOVE", FALSE); + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = gdk_display; + xev.xclient.window = GDK_WINDOW_XID (window); + xev.xclient.message_type = gdk_atom_intern ("_NET_WM_STATE", FALSE); + xev.xclient.format = 32; + xev.xclient.data.l[0] = op; + xev.xclient.data.l[1] = state1; + xev.xclient.data.l[2] = state2; + + XSendEvent (gdk_display, gdk_root_window, False, + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); +} + +static void +wmspec_change_desktop (GdkWindow *window, + gint desktop) +{ + XEvent xev; + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = gdk_display; + xev.xclient.window = GDK_WINDOW_XID (window); + xev.xclient.message_type = gdk_atom_intern ("_NET_WM_DESKTOP", FALSE); + xev.xclient.format = 32; + xev.xclient.data.l[0] = desktop; + xev.xclient.data.l[1] = 0; + xev.xclient.data.l[2] = 0; + + XSendEvent (gdk_display, gdk_root_window, False, + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); +} + static void activate_cb (GtkWidget *menuitem, gpointer data) { @@ -219,6 +390,23 @@ activate_cb (GtkWidget *menuitem, gpointer data) gdk_error_trap_pop (); break; + case META_MESSAGE_MENU_SHADE: + wmspec_change_state (TRUE, md->window, + gdk_atom_intern ("_NET_WM_STATE_SHADED", FALSE), + 0); + break; + + case META_MESSAGE_MENU_WORKSPACES: + { + int workspace; + + workspace = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem), + "workspace")); + + wmspec_change_desktop (md->window, workspace); + } + break; + default: meta_ui_warning (G_STRLOC": Unknown window op\n"); break; diff --git a/src/uislave/messages.h b/src/uislave/messages.h index 4e083042c..c4fe64c06 100644 --- a/src/uislave/messages.h +++ b/src/uislave/messages.h @@ -133,7 +133,13 @@ typedef enum META_MESSAGE_MENU_DELETE = 1 << 0, META_MESSAGE_MENU_MINIMIZE = 1 << 1, META_MESSAGE_MENU_MAXIMIZE = 1 << 2, - META_MESSAGE_MENU_ALL = META_MESSAGE_MENU_DELETE | META_MESSAGE_MENU_MINIMIZE | META_MESSAGE_MENU_MAXIMIZE + META_MESSAGE_MENU_SHADE = 1 << 3, + META_MESSAGE_MENU_WORKSPACES = 1 << 4, + META_MESSAGE_MENU_ALL = META_MESSAGE_MENU_DELETE | + META_MESSAGE_MENU_MINIMIZE | + META_MESSAGE_MENU_MAXIMIZE | + META_MESSAGE_MENU_SHADE | + META_MESSAGE_MENU_WORKSPACES } MetaMessageWindowMenuOps; struct _MetaMessageShowWindowMenu diff --git a/src/window.c b/src/window.c index a06730499..f0ed4dd06 100644 --- a/src/window.c +++ b/src/window.c @@ -619,6 +619,33 @@ meta_window_focus (MetaWindow *window, } } +void +meta_window_change_workspace (MetaWindow *window, + MetaWorkspace *workspace) +{ + meta_verbose ("Changing window %s to workspace %d\n", + window->desc, meta_workspace_index (workspace)); + + /* See if we're already on this space */ + if (g_list_find (window->workspaces, workspace) != NULL) + { + meta_verbose ("Already on this workspace\n"); + return; + } + + /* Add first, to maintain invariant that we're always + * on some workspace. + */ + meta_workspace_add_window (workspace, window); + + /* Lamely rely on prepend */ + g_assert (window->workspaces->data == workspace); + + /* Remove from all other spaces */ + while (window->workspaces->next) /* while list size > 1 */ + meta_workspace_remove_window (window->workspaces->next->data, window); +} + void meta_window_raise (MetaWindow *window) { diff --git a/src/window.h b/src/window.h index bd3bf2701..36a27ad1e 100644 --- a/src/window.h +++ b/src/window.h @@ -112,7 +112,8 @@ void meta_window_maximize (MetaWindow *window); void meta_window_unmaximize (MetaWindow *window); void meta_window_shade (MetaWindow *window); void meta_window_unshade (MetaWindow *window); - +void meta_window_change_workspace (MetaWindow *window, + MetaWorkspace *workspace); /* args to move are window pos, not frame pos */ void meta_window_move (MetaWindow *window, diff --git a/src/workspace.c b/src/workspace.c index 2e1fb53d7..3920c77b9 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -20,9 +20,14 @@ */ #include "workspace.h" +#include "errors.h" +#include void meta_workspace_queue_calc_showing (MetaWorkspace *workspace); +static int set_current_workspace_hint (MetaWindow *window); +static int set_number_of_spaces_hint (MetaScreen *screen); + MetaWorkspace* meta_workspace_new (MetaScreen *screen) { @@ -42,6 +47,9 @@ meta_workspace_new (MetaScreen *screen) workspace->workarea.y = 0; workspace->workarea.width = WidthOfScreen (screen->xscreen); workspace->workarea.height = HeightOfScreen (screen->xscreen); + + /* Update hint for current number of workspaces */ + set_number_of_spaces_hint (screen); return workspace; } @@ -79,6 +87,8 @@ meta_workspace_add_window (MetaWorkspace *workspace, workspace->windows = g_list_prepend (workspace->windows, window); window->workspaces = g_list_prepend (window->workspaces, workspace); + set_current_workspace_hint (window); + meta_window_queue_calc_showing (window); } @@ -91,6 +101,8 @@ meta_workspace_remove_window (MetaWorkspace *workspace, workspace->windows = g_list_remove (workspace->windows, window); window->workspaces = g_list_remove (window->workspaces, workspace); + set_current_workspace_hint (window); + meta_window_queue_calc_showing (window); } @@ -147,3 +159,70 @@ meta_workspace_index (MetaWorkspace *workspace) meta_bug ("Workspace does not exist to index!\n"); } + +int +meta_workspace_screen_index (MetaWorkspace *workspace) +{ + GList *tmp; + int i; + + i = 0; + tmp = workspace->screen->display->workspaces; + while (tmp != NULL) + { + MetaWorkspace *w = tmp->data; + + if (tmp->data == workspace) + return i; + + if (w->screen == workspace->screen) + ++i; + + tmp = tmp->next; + } + + meta_bug ("Workspace does not exist to index!\n"); +} + + +static int +set_current_workspace_hint (MetaWindow *window) +{ + /* if on more than one workspace, we claim to be "sticky" */ + unsigned long data[1]; + + if (window->workspaces == NULL) + return Success; /* this happens when destroying windows */ + + if (g_list_length (window->workspaces) > 1) + data[0] = 0xFFFFFFFF; + else + data[0] = meta_workspace_screen_index (window->workspaces->data); + + meta_verbose ("Setting _NET_WM_DESKTOP of %s to %ld\n", + window->desc, data[0]); + + meta_error_trap_push (window->display); + XChangeProperty (window->display->xdisplay, window->xwindow, + window->display->atom_net_wm_desktop, + XA_CARDINAL, + 32, PropModeReplace, (guchar*) data, 1); + return meta_error_trap_pop (window->display); +} + +static int +set_number_of_spaces_hint (MetaScreen *screen) +{ + unsigned long data[1]; + + data[0] = meta_screen_get_n_workspaces (screen); + + meta_verbose ("Setting _NET_NUMBER_OF_DESKTOPS to %ld\n", data[0]); + + meta_error_trap_push (screen->display); + XChangeProperty (screen->display->xdisplay, screen->xroot, + screen->display->atom_net_number_of_desktops, + XA_CARDINAL, + 32, PropModeReplace, (guchar*) data, 1); + return meta_error_trap_pop (screen->display); +} diff --git a/src/workspace.h b/src/workspace.h index 5cde8a0a6..d7f7e36dc 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -42,6 +42,7 @@ void meta_workspace_remove_window (MetaWorkspace *workspace, void meta_workspace_activate (MetaWorkspace *workspace); int meta_workspace_index (MetaWorkspace *workspace); +int meta_workspace_screen_index (MetaWorkspace *workspace); #endif