diff options
-rw-r--r-- | src/display.c | 78 | ||||
-rw-r--r-- | src/display.h | 11 | ||||
-rw-r--r-- | src/frame.c | 46 | ||||
-rw-r--r-- | src/frame.h | 5 | ||||
-rw-r--r-- | src/menu.c | 114 | ||||
-rw-r--r-- | src/screen.c | 52 | ||||
-rw-r--r-- | src/screen.h | 2 | ||||
-rw-r--r-- | src/theme.c | 8 | ||||
-rw-r--r-- | src/theme.h | 3 | ||||
-rw-r--r-- | src/uislave/menu.c | 114 | ||||
-rw-r--r-- | src/uislave/messages.h | 4 | ||||
-rw-r--r-- | src/window.c | 451 | ||||
-rw-r--r-- | src/window.h | 27 | ||||
-rw-r--r-- | src/workspace.c | 52 | ||||
-rw-r--r-- | src/workspace.h | 3 |
15 files changed, 752 insertions, 218 deletions
diff --git a/src/display.c b/src/display.c index 196224b3..2cf29e05 100644 --- a/src/display.c +++ b/src/display.c @@ -28,6 +28,8 @@ #include "errors.h" #include "keybindings.h" #include "workspace.h" +#include <X11/Xatom.h> +#include <string.h> static GSList *all_displays = NULL; static void meta_spew_event (MetaDisplay *display, @@ -61,6 +63,19 @@ unsigned_long_hash (gconstpointer v) #endif } +static int +set_string_hint (MetaDisplay *display, + Window xwindow, + Atom atom, + const char *val) +{ + meta_error_trap_push (display); + XChangeProperty (display->xdisplay, + xwindow, atom, + XA_STRING, + 8, PropModeReplace, (guchar*) val, strlen (val) + 1); + return meta_error_trap_pop (display); +} gboolean meta_display_open (const char *name) @@ -90,7 +105,18 @@ meta_display_open (const char *name) "WM_CHANGE_STATE", "SM_CLIENT_ID", "WM_CLIENT_LEADER", - "WM_WINDOW_ROLE" + "WM_WINDOW_ROLE", + "_NET_CURRENT_DESKTOP", + "_NET_SUPPORTING_WM_CHECK", + "_NET_WM_SUPPORTED", + "_NET_WM_WINDOW_TYPE", + "_NET_WM_WINDOW_TYPE_DESKTOP", + "_NET_WM_WINDOW_TYPE_DOCK", + "_NET_WM_WINDOW_TYPE_TOOLBAR", + "_NET_WM_WINDOW_TYPE_MENU", + "_NET_WM_WINDOW_TYPE_DIALOG", + "_NET_WM_WINDOW_TYPE_NORMAL", + "_NET_WM_STATE_MODAL" }; Atom atoms[G_N_ELEMENTS(atom_names)]; @@ -144,6 +170,17 @@ meta_display_open (const char *name) display->atom_sm_client_id = atoms[14]; display->atom_wm_client_leader = atoms[15]; display->atom_wm_window_role = atoms[16]; + display->atom_net_current_desktop = atoms[17]; + display->atom_net_supporting_wm_check = atoms[18]; + display->atom_net_wm_supported = atoms[19]; + display->atom_net_wm_window_type = atoms[20]; + display->atom_net_wm_window_type_desktop = atoms[21]; + display->atom_net_wm_window_type_dock = atoms[22]; + display->atom_net_wm_window_type_toolbar = atoms[23]; + display->atom_net_wm_window_type_menu = atoms[24]; + display->atom_net_wm_window_type_dialog = atoms[25]; + display->atom_net_wm_window_type_normal = atoms[26]; + display->atom_net_wm_state_modal = atoms[27]; screens = NULL; i = 0; @@ -190,6 +227,11 @@ meta_display_open (const char *name) XCreateSimpleWindow (display->xdisplay, ((MetaScreen*)display->screens->data)->xroot, -100, -100, 1, 1, 0, 0, 0); + + set_string_hint (display, + display->leader_window, + display->atom_net_supporting_wm_check, + "Metacity"); /* Now manage all existing windows */ tmp = display->screens; @@ -560,7 +602,39 @@ event_queue_callback (MetaEventQueue *queue, break; case ClientMessage: if (window) - meta_window_client_message (window, event); + { + meta_window_client_message (window, event); + } + else + { + MetaScreen *screen; + + screen = meta_display_screen_for_root (display, + event->xclient.window); + + if (screen && + event->xclient.message_type == + display->atom_net_current_desktop) + { + int space; + MetaWorkspace *workspace; + + space = event->xclient.data.l[0]; + + meta_verbose ("Request to change current workspace to %d\n", + space); + + workspace = + meta_display_get_workspace_by_screen_index (display, + screen, + space); + + if (workspace) + meta_workspace_activate (workspace); + else + meta_verbose ("Don't know about workspace %d\n", space); + } + } break; case MappingNotify: break; diff --git a/src/display.h b/src/display.h index e1704cec..553360d9 100644 --- a/src/display.h +++ b/src/display.h @@ -62,6 +62,17 @@ struct _MetaDisplay Atom atom_sm_client_id; Atom atom_wm_client_leader; Atom atom_wm_window_role; + Atom atom_net_current_desktop; + Atom atom_net_supporting_wm_check; + Atom atom_net_wm_supported; + Atom atom_net_wm_window_type; + Atom atom_net_wm_window_type_desktop; + Atom atom_net_wm_window_type_dock; + Atom atom_net_wm_window_type_toolbar; + Atom atom_net_wm_window_type_menu; + Atom atom_net_wm_window_type_dialog; + Atom atom_net_wm_window_type_normal; + Atom atom_net_wm_state_modal; /* This is the actual window from focus events, * not the one we last set diff --git a/src/frame.c b/src/frame.c index 9ec4734d..4e9d0bb3 100644 --- a/src/frame.c +++ b/src/frame.c @@ -52,14 +52,19 @@ meta_frame_init_info (MetaFrame *frame, { info->flags = META_FRAME_ALLOWS_MENU | META_FRAME_ALLOWS_DELETE | - META_FRAME_ALLOWS_ICONIFY | META_FRAME_ALLOWS_MAXIMIZE | META_FRAME_ALLOWS_RESIZE; + if (frame->window->type == META_WINDOW_NORMAL) + info->flags |= (META_FRAME_ALLOWS_ICONIFY | META_FRAME_ALLOWS_MAXIMIZE); + if (frame->window->has_focus) info->flags |= META_FRAME_HAS_FOCUS; if (frame->window->shaded) info->flags |= META_FRAME_SHADED; + + if (frame->window->on_all_workspaces) + info->flags |= META_FRAME_STUCK; info->drawable = None; info->xoffset = 0; @@ -257,6 +262,8 @@ meta_window_ensure_frame (MetaWindow *window) frame->right_width = 0; frame->bg_pixel = 0; + frame->mapped = FALSE; + attrs.event_mask = EVENT_MASK; frame->xwindow = XCreateWindow (window->display->xdisplay, @@ -355,19 +362,37 @@ meta_window_destroy_frame (MetaWindow *window) } void -meta_frame_sync_to_window (MetaFrame *frame) +meta_frame_sync_to_window (MetaFrame *frame, + gboolean need_move, + gboolean need_resize) { meta_verbose ("Syncing frame geometry %d,%d %dx%d pixel %ld\n", frame->rect.x, frame->rect.y, frame->rect.width, frame->rect.height, frame->bg_pixel); + + /* set bg to none to avoid flicker */ set_background_none (frame); - XMoveResizeWindow (frame->window->display->xdisplay, - frame->xwindow, - frame->rect.x, - frame->rect.y, - frame->rect.width, - frame->rect.height); + + if (need_move && need_resize) + XMoveResizeWindow (frame->window->display->xdisplay, + frame->xwindow, + frame->rect.x, + frame->rect.y, + frame->rect.width, + frame->rect.height); + else if (need_move) + XMoveWindow (frame->window->display->xdisplay, + frame->xwindow, + frame->rect.x, + frame->rect.y); + else if (need_resize) + XResizeWindow (frame->window->display->xdisplay, + frame->xwindow, + frame->rect.width, + frame->rect.height); + + /* also syncs bg_pixel */ set_background_color (frame); meta_frame_queue_draw (frame); } @@ -703,6 +728,11 @@ get_menu_items (MetaFrame *frame, else *ops |= META_MESSAGE_MENU_SHADE; + if (frame->window->on_all_workspaces) + *ops |= META_MESSAGE_MENU_UNSTICK; + else + *ops |= META_MESSAGE_MENU_STICK; + *ops |= (META_MESSAGE_MENU_DELETE | META_MESSAGE_MENU_WORKSPACES | META_MESSAGE_MENU_MINIMIZE); if (!(info->flags & META_FRAME_CONTROL_ICONIFY)) diff --git a/src/frame.h b/src/frame.h index 1e3e52b0..4947142e 100644 --- a/src/frame.h +++ b/src/frame.h @@ -62,6 +62,7 @@ struct _MetaFrame guint tooltip_timeout; guint theme_acquired : 1; + guint mapped : 1; }; void meta_window_ensure_frame (MetaWindow *window); @@ -84,7 +85,9 @@ void meta_frame_adjust_for_gravity (int win_gravity, int y, int *win_root_x, int *win_root_y); -void meta_frame_sync_to_window (MetaFrame *frame); +void meta_frame_sync_to_window (MetaFrame *frame, + gboolean need_move, + gboolean need_resize); #endif @@ -54,7 +54,10 @@ static MenuItem menuitems[] = { { META_MESSAGE_MENU_MAXIMIZE, NULL, N_("Ma_ximize") }, { META_MESSAGE_MENU_UNMAXIMIZE, NULL, N_("_Unmaximize") }, { META_MESSAGE_MENU_SHADE, NULL, N_("_Shade") }, - { META_MESSAGE_MENU_UNSHADE, NULL, N_("U_nshade") } + { META_MESSAGE_MENU_UNSHADE, NULL, N_("U_nshade") }, + { 0, NULL, NULL }, /* separator */ + { META_MESSAGE_MENU_STICK, NULL, N_("Put on _All Workspaces") }, + { META_MESSAGE_MENU_UNSTICK, NULL, N_("Only on _This Workspace") } }; static void @@ -105,6 +108,32 @@ get_num_desktops (void) return result; } +static gint +get_active_desktop (void) +{ + Atom type; + gint format; + gulong nitems; + gulong bytes_after; + gulong *num; + int result; + + XGetWindowProperty (gdk_display, gdk_root_window, + gdk_atom_intern ("_NET_CURRENT_DESKTOP", 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) { @@ -130,7 +159,7 @@ get_current_desktop (GdkWindow *window) if (type != XA_CARDINAL) { meta_ui_warning ("_NET_WM_DESKTOP has wrong type %s\n", gdk_atom_name (type)); - return -1; + return 0xFFFFFFFF; /* sticky */ } result = *num; @@ -172,40 +201,47 @@ meta_window_menu_show (gulong xwindow, i = 0; while (i < G_N_ELEMENTS (menuitems)) { - if (ops & menuitems[i].op) + if (ops & menuitems[i].op || menuitems[i].op == 0) { GtkWidget *mi; MenuData *md; - - if (menuitems[i].stock_id) + + if (menuitems[i].op == 0) { - GtkWidget *image; - - 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), - image); - gtk_widget_show (image); + mi = gtk_separator_menu_item_new (); } else { - mi = gtk_menu_item_new_with_mnemonic (menuitems[i].label); + if (menuitems[i].stock_id) + { + GtkWidget *image; + + 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), + image); + gtk_widget_show (image); + } + else + { + mi = gtk_menu_item_new_with_mnemonic (menuitems[i].label); + } + + if (insensitive & menuitems[i].op) + gtk_widget_set_sensitive (mi, FALSE); + + md = g_new (MenuData, 1); + + md->window = window; + md->op = menuitems[i].op; + + gtk_signal_connect (GTK_OBJECT (mi), + "activate", + GTK_SIGNAL_FUNC (activate_cb), + md); } - - if (insensitive & menuitems[i].op) - gtk_widget_set_sensitive (mi, FALSE); - - md = g_new (MenuData, 1); - - md->window = window; - md->op = menuitems[i].op; - gtk_signal_connect (GTK_OBJECT (mi), - "activate", - GTK_SIGNAL_FUNC (activate_cb), - md); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); @@ -222,22 +258,22 @@ meta_window_menu_show (gulong xwindow, meta_ui_warning ("Creating %d workspace menu current %d\n", n_workspaces, current_workspace); - if (n_workspaces > 0 && current_workspace >= 0) + if (n_workspaces > 0) { GtkWidget *mi; - - mi = gtk_separator_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); - gtk_widget_show (mi); i = 0; while (i < n_workspaces) { char *label; MenuData *md; - - label = g_strdup_printf (_("Move to workspace _%d\n"), - i + 1); + + if (current_workspace == 0xFFFFFFFF) + label = g_strdup_printf (_("Only on workspace _%d\n"), + i + 1); + else + label = g_strdup_printf (_("Move to workspace _%d\n"), + i + 1); mi = gtk_menu_item_new_with_mnemonic (label); @@ -429,6 +465,14 @@ activate_cb (GtkWidget *menuitem, gpointer data) wmspec_change_desktop (md->window, workspace); } break; + + case META_MESSAGE_MENU_STICK: + wmspec_change_desktop (md->window, 0xFFFFFFFF); + break; + + case META_MESSAGE_MENU_UNSTICK: + wmspec_change_desktop (md->window, get_active_desktop ()); + break; default: meta_ui_warning (G_STRLOC": Unknown window op\n"); diff --git a/src/screen.c b/src/screen.c index 75851c66..5b8f5c3e 100644 --- a/src/screen.c +++ b/src/screen.c @@ -30,6 +30,7 @@ #include "keybindings.h" #include <X11/cursorfont.h> +#include <X11/Xatom.h> #include <locale.h> #include <string.h> @@ -40,6 +41,53 @@ static char* get_screen_name (MetaDisplay *display, int number); +static int +set_wm_check_hint (MetaScreen *screen) +{ + unsigned long data[1]; + + data[0] = screen->display->leader_window; + + XChangeProperty (screen->display->xdisplay, screen->xroot, + screen->display->atom_net_supporting_wm_check, + XA_WINDOW, + 32, PropModeReplace, (guchar*) data, 1); + return Success; +} + +static int +set_supported_hint (MetaScreen *screen) +{ +#define N_SUPPORTED 17 + Atom atoms[N_SUPPORTED]; + + atoms[0] = screen->display->atom_net_wm_name; + atoms[1] = screen->display->atom_net_close_window; + atoms[2] = screen->display->atom_net_wm_state; + atoms[3] = screen->display->atom_net_wm_state_shaded; + atoms[4] = screen->display->atom_net_wm_state_maximized_vert; + atoms[5] = screen->display->atom_net_wm_state_maximized_horz; + atoms[6] = screen->display->atom_net_wm_desktop; + atoms[7] = screen->display->atom_net_number_of_desktops; + atoms[8] = screen->display->atom_net_current_desktop; + atoms[9] = screen->display->atom_net_wm_window_type; + atoms[10] = screen->display->atom_net_wm_window_type_desktop; + atoms[11] = screen->display->atom_net_wm_window_type_dock; + atoms[12] = screen->display->atom_net_wm_window_type_toolbar; + atoms[13] = screen->display->atom_net_wm_window_type_menu; + atoms[14] = screen->display->atom_net_wm_window_type_dialog; + atoms[15] = screen->display->atom_net_wm_window_type_normal; + atoms[16] = screen->display->atom_net_wm_state_modal; + + XChangeProperty (screen->display->xdisplay, screen->xroot, + screen->display->atom_net_wm_supported, + XA_ATOM, + 32, PropModeReplace, (guchar*) atoms, N_SUPPORTED); + + return Success; +#undef N_SUPPORTED +} + MetaScreen* meta_screen_new (MetaDisplay *display, int number) @@ -104,6 +152,10 @@ meta_screen_new (MetaDisplay *display, screen->showing_tooltip = FALSE; + set_supported_hint (screen); + + set_wm_check_hint (screen); + /* Screens must have at least one workspace at all times, * so create that required workspace. */ diff --git a/src/screen.h b/src/screen.h index 398ca158..89c71302 100644 --- a/src/screen.h +++ b/src/screen.h @@ -51,8 +51,6 @@ struct _MetaScreen guint showing_tooltip : 1; - /*< private >*/ - /* we only need one since we only draw to a single visual (that of * root window) */ diff --git a/src/theme.c b/src/theme.c index eb374375..11f911e3 100644 --- a/src/theme.c +++ b/src/theme.c @@ -179,10 +179,10 @@ default_release_frame (MetaFrameInfo *info, #define SPACER_SPACING 3 #define SPACER_WIDTH 2 #define SPACER_HEIGHT 10 -#define BUTTON_WIDTH 12 -#define BUTTON_HEIGHT 12 -#define BUTTON_PAD 2 -#define INNER_BUTTON_PAD 1 +#define BUTTON_WIDTH 14 +#define BUTTON_HEIGHT 14 +#define BUTTON_PAD 1 +#define INNER_BUTTON_PAD 3 static void calc_geometry (MetaFrameInfo *info, DefaultFrameData *d, diff --git a/src/theme.h b/src/theme.h index a80147a5..37c46ab8 100644 --- a/src/theme.h +++ b/src/theme.h @@ -42,7 +42,8 @@ typedef enum META_FRAME_ALLOWS_RESIZE = 1 << 4, META_FRAME_TRANSIENT = 1 << 5, META_FRAME_HAS_FOCUS = 1 << 6, - META_FRAME_SHADED = 1 << 7 + META_FRAME_SHADED = 1 << 7, + META_FRAME_STUCK = 1 << 8 } MetaFrameFlags; typedef enum diff --git a/src/uislave/menu.c b/src/uislave/menu.c index f9687a79..1cb4f973 100644 --- a/src/uislave/menu.c +++ b/src/uislave/menu.c @@ -54,7 +54,10 @@ static MenuItem menuitems[] = { { META_MESSAGE_MENU_MAXIMIZE, NULL, N_("Ma_ximize") }, { META_MESSAGE_MENU_UNMAXIMIZE, NULL, N_("_Unmaximize") }, { META_MESSAGE_MENU_SHADE, NULL, N_("_Shade") }, - { META_MESSAGE_MENU_UNSHADE, NULL, N_("U_nshade") } + { META_MESSAGE_MENU_UNSHADE, NULL, N_("U_nshade") }, + { 0, NULL, NULL }, /* separator */ + { META_MESSAGE_MENU_STICK, NULL, N_("Put on _All Workspaces") }, + { META_MESSAGE_MENU_UNSTICK, NULL, N_("Only on _This Workspace") } }; static void @@ -105,6 +108,32 @@ get_num_desktops (void) return result; } +static gint +get_active_desktop (void) +{ + Atom type; + gint format; + gulong nitems; + gulong bytes_after; + gulong *num; + int result; + + XGetWindowProperty (gdk_display, gdk_root_window, + gdk_atom_intern ("_NET_CURRENT_DESKTOP", 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) { @@ -130,7 +159,7 @@ get_current_desktop (GdkWindow *window) if (type != XA_CARDINAL) { meta_ui_warning ("_NET_WM_DESKTOP has wrong type %s\n", gdk_atom_name (type)); - return -1; + return 0xFFFFFFFF; /* sticky */ } result = *num; @@ -172,40 +201,47 @@ meta_window_menu_show (gulong xwindow, i = 0; while (i < G_N_ELEMENTS (menuitems)) { - if (ops & menuitems[i].op) + if (ops & menuitems[i].op || menuitems[i].op == 0) { GtkWidget *mi; MenuData *md; - - if (menuitems[i].stock_id) + + if (menuitems[i].op == 0) { - GtkWidget *image; - - 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), - image); - gtk_widget_show (image); + mi = gtk_separator_menu_item_new (); } else { - mi = gtk_menu_item_new_with_mnemonic (menuitems[i].label); + if (menuitems[i].stock_id) + { + GtkWidget *image; + + 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), + image); + gtk_widget_show (image); + } + else + { + mi = gtk_menu_item_new_with_mnemonic (menuitems[i].label); + } + + if (insensitive & menuitems[i].op) + gtk_widget_set_sensitive (mi, FALSE); + + md = g_new (MenuData, 1); + + md->window = window; + md->op = menuitems[i].op; + + gtk_signal_connect (GTK_OBJECT (mi), + "activate", + GTK_SIGNAL_FUNC (activate_cb), + md); } - - if (insensitive & menuitems[i].op) - gtk_widget_set_sensitive (mi, FALSE); - - md = g_new (MenuData, 1); - - md->window = window; - md->op = menuitems[i].op; - gtk_signal_connect (GTK_OBJECT (mi), - "activate", - GTK_SIGNAL_FUNC (activate_cb), - md); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); @@ -222,22 +258,22 @@ meta_window_menu_show (gulong xwindow, meta_ui_warning ("Creating %d workspace menu current %d\n", n_workspaces, current_workspace); - if (n_workspaces > 0 && current_workspace >= 0) + if (n_workspaces > 0) { GtkWidget *mi; - - mi = gtk_separator_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); - gtk_widget_show (mi); i = 0; while (i < n_workspaces) { char *label; MenuData *md; - - label = g_strdup_printf (_("Move to workspace _%d\n"), - i + 1); + + if (current_workspace == 0xFFFFFFFF) + label = g_strdup_printf (_("Only on workspace _%d\n"), + i + 1); + else + label = g_strdup_printf (_("Move to workspace _%d\n"), + i + 1); mi = gtk_menu_item_new_with_mnemonic (label); @@ -429,6 +465,14 @@ activate_cb (GtkWidget *menuitem, gpointer data) wmspec_change_desktop (md->window, workspace); } break; + + case META_MESSAGE_MENU_STICK: + wmspec_change_desktop (md->window, 0xFFFFFFFF); + break; + + case META_MESSAGE_MENU_UNSTICK: + wmspec_change_desktop (md->window, get_active_desktop ()); + break; default: meta_ui_warning (G_STRLOC": Unknown window op\n"); diff --git a/src/uislave/messages.h b/src/uislave/messages.h index 15203864..f9a21499 100644 --- a/src/uislave/messages.h +++ b/src/uislave/messages.h @@ -136,7 +136,9 @@ typedef enum META_MESSAGE_MENU_MAXIMIZE = 1 << 3, META_MESSAGE_MENU_UNSHADE = 1 << 4, META_MESSAGE_MENU_SHADE = 1 << 5, - META_MESSAGE_MENU_WORKSPACES = 1 << 6 + META_MESSAGE_MENU_UNSTICK = 1 << 6, + META_MESSAGE_MENU_STICK = 1 << 7, + META_MESSAGE_MENU_WORKSPACES = 1 << 8 } MetaMessageWindowMenuOps; struct _MetaMessageShowWindowMenu diff --git a/src/window.c b/src/window.c index 9094fc10..7abdf843 100644 --- a/src/window.c +++ b/src/window.c @@ -49,6 +49,8 @@ static int update_wm_class (MetaWindow *window); static int update_transient_for (MetaWindow *window); static void update_sm_hints (MetaWindow *window); static int update_role (MetaWindow *window); +static int update_net_wm_type (MetaWindow *window); +static void recalc_window_type (MetaWindow *window); static int set_wm_state (MetaWindow *window, int state); static void send_configure_notify (MetaWindow *window); @@ -64,8 +66,6 @@ static void meta_window_show (MetaWindow *window); static void meta_window_hide (MetaWindow *window); static void meta_window_move_resize_internal (MetaWindow *window, - gboolean move, - gboolean resize, gboolean is_configure_request, int root_x_nw, int root_y_nw, @@ -164,6 +164,7 @@ meta_window_new (MetaDisplay *display, Window xwindow) window->has_focus = FALSE; window->maximized = FALSE; + window->on_all_workspaces = FALSE; window->shaded = FALSE; window->initially_iconic = FALSE; window->minimized = FALSE; @@ -175,6 +176,8 @@ meta_window_new (MetaDisplay *display, Window xwindow) window->has_minimize_func = TRUE; window->has_maximize_func = TRUE; + window->wm_state_modal = FALSE; + window->res_class = NULL; window->res_name = NULL; window->role = NULL; @@ -183,6 +186,9 @@ meta_window_new (MetaDisplay *display, Window xwindow) window->xtransient_for = None; window->xgroup_leader = None; window->xclient_leader = None; + + window->type = META_WINDOW_NORMAL; + window->type_atom = None; meta_display_register_x_window (display, &window->xwindow, window); @@ -196,6 +202,7 @@ meta_window_new (MetaDisplay *display, Window xwindow) update_transient_for (window); update_sm_hints (window); /* must come after transient_for */ update_role (window); + update_net_wm_type (window); if (window->initially_iconic) { @@ -218,7 +225,7 @@ meta_window_new (MetaDisplay *display, Window xwindow) * passing TRUE for is_configure_request, ICCCM says * initial map is handled same as configure request */ - meta_window_move_resize_internal (window, TRUE, TRUE, TRUE, + meta_window_move_resize_internal (window, TRUE, window->size_hints.x, window->size_hints.y, window->size_hints.width, @@ -308,6 +315,12 @@ meta_window_calc_showing (MetaWindow *window) meta_verbose ("Window %s is on the active workspace %d\n", window->desc, meta_workspace_index (window->screen->active_workspace)); + + if (window->on_all_workspaces) + { + on_workspace = TRUE; + meta_verbose ("Window %s is on all workspaces\n", window->desc); + } if (window->minimized || !on_workspace) { @@ -334,16 +347,24 @@ meta_window_show (MetaWindow *window) /* Shaded means the frame is mapped but the window is not */ - if (window->frame) - XMapWindow (window->display->xdisplay, window->frame->xwindow); + if (window->frame && !window->frame->mapped) + { + meta_verbose ("Frame actually needs map\n"); + window->frame->mapped = TRUE; + XMapWindow (window->display->xdisplay, window->frame->xwindow); + } if (window->shaded) { - window->mapped = FALSE; - meta_error_trap_push (window->display); - XUnmapWindow (window->display->xdisplay, window->xwindow); - meta_error_trap_pop (window->display); - + if (window->mapped) + { + meta_verbose ("%s actually needs unmap\n", window->desc); + window->mapped = FALSE; + meta_error_trap_push (window->display); + XUnmapWindow (window->display->xdisplay, window->xwindow); + meta_error_trap_pop (window->display); + } + if (!window->iconic) { window->iconic = TRUE; @@ -352,10 +373,14 @@ meta_window_show (MetaWindow *window) } else { - window->mapped = TRUE; - meta_error_trap_push (window->display); - XMapWindow (window->display->xdisplay, window->xwindow); - meta_error_trap_pop (window->display); + if (!window->mapped) + { + meta_verbose ("%s actually needs map\n", window->desc); + window->mapped = TRUE; + meta_error_trap_push (window->display); + XMapWindow (window->display->xdisplay, window->xwindow); + meta_error_trap_pop (window->display); + } if (window->iconic) { @@ -370,11 +395,19 @@ meta_window_hide (MetaWindow *window) { meta_verbose ("Hiding window %s\n", window->desc); - if (window->frame) - XUnmapWindow (window->display->xdisplay, window->frame->xwindow); - XUnmapWindow (window->display->xdisplay, window->xwindow); + if (window->frame && window->frame->mapped) + { + meta_verbose ("Frame actually needs unmap\n"); + window->frame->mapped = FALSE; + XUnmapWindow (window->display->xdisplay, window->frame->xwindow); + } - window->mapped = FALSE; + if (window->mapped) + { + meta_verbose ("%s actually needs unmap\n", window->desc); + window->mapped = FALSE; + XUnmapWindow (window->display->xdisplay, window->xwindow); + } if (!window->iconic) { @@ -466,8 +499,6 @@ meta_window_unshade (MetaWindow *window) static void meta_window_move_resize_internal (MetaWindow *window, - gboolean move, - gboolean resize, gboolean is_configure_request, int root_x_nw, int root_y_nw, @@ -478,31 +509,24 @@ meta_window_move_resize_internal (MetaWindow *window, unsigned int mask; gboolean need_configure_notify; MetaFrameGeometry fgeom; + gboolean need_move_client = FALSE; + gboolean need_move_frame = FALSE; + gboolean need_resize_client = FALSE; + gboolean need_resize_frame = FALSE; - if (resize) - meta_verbose ("Resizing %s to %d x %d\n", window->desc, w, h); - if (move) - meta_verbose ("Moving %s to %d,%d\n", window->desc, - root_x_nw, root_y_nw); - + meta_verbose ("Move/resize %s to %d,%d %dx%d\n", + window->desc, root_x_nw, root_y_nw, w, h); + constrain_size (window, w, h, &w, &h); + meta_verbose ("Constrained resize of %s to %d x %d\n", window->desc, w, h); + + if (w != window->rect.width || + h != window->rect.height) + need_resize_client = TRUE; - /* remember that root_x_nw, root_y_nw are bogus if not moving, - * and w, h are bogus if not resizing - */ + window->rect.width = w; + window->rect.height = h; - if (resize) - { - constrain_size (window, w, h, &w, &h); - meta_verbose ("Constrained resize of %s to %d x %d\n", window->desc, w, h); - if (w == window->rect.width && - h == window->rect.height) - resize = FALSE; - - window->rect.width = w; - window->rect.height = h; - } - if (window->frame) { int new_w, new_h; @@ -519,7 +543,9 @@ meta_window_move_resize_internal (MetaWindow *window, else new_h = window->rect.height + fgeom.top_height + fgeom.bottom_height; - /* FIXME could check to avoid XResizeWindow on frame */ + if (new_w != window->frame->rect.width || + new_h != window->frame->rect.height) + need_resize_frame = TRUE; window->frame->rect.width = new_w; window->frame->rect.height = new_h; @@ -527,11 +553,8 @@ meta_window_move_resize_internal (MetaWindow *window, meta_verbose ("Calculated frame size %dx%d\n", window->frame->rect.width, window->frame->rect.height); - } - - if (move) - { - if (is_configure_request && window->frame) + + if (is_configure_request) { meta_frame_adjust_for_gravity (window->size_hints.win_gravity, window->frame->rect.width, @@ -541,50 +564,52 @@ meta_window_move_resize_internal (MetaWindow *window, root_y_nw, &root_x_nw, &root_y_nw); - + meta_verbose ("Compensated position for gravity, new pos %d,%d\n", root_x_nw, root_y_nw); } + } - constrain_position (window, - window->frame ? &fgeom : NULL, - root_x_nw, root_y_nw, - &root_x_nw, &root_y_nw); + constrain_position (window, + window->frame ? &fgeom : NULL, + root_x_nw, root_y_nw, + &root_x_nw, &root_y_nw); - meta_verbose ("Constrained position to %d,%d\n", - root_x_nw, root_y_nw); + meta_verbose ("Constrained position to %d,%d\n", + root_x_nw, root_y_nw); - if (window->frame) - { - int new_x, new_y; - - new_x = root_x_nw - fgeom.left_width; - new_y = root_y_nw - fgeom.top_height; + if (window->frame) + { + int new_x, new_y; - if (new_x == window->frame->rect.x && - new_y == window->frame->rect.y && - window->rect.x == fgeom.left_width && - window->rect.y == fgeom.top_height) - move = FALSE; - - window->frame->rect.x = new_x; - window->frame->rect.y = new_y; - - /* window->rect.x, window->rect.y are relative to frame, - * remember they are the server coords - */ - window->rect.x = fgeom.left_width; - window->rect.y = fgeom.top_height; - } - else - { - if (root_x_nw == window->rect.x && - root_y_nw == window->rect.y) - move = FALSE; + new_x = root_x_nw - fgeom.left_width; + new_y = root_y_nw - fgeom.top_height; - window->rect.x = root_x_nw; - window->rect.y = root_y_nw; - } + if (new_x != window->frame->rect.x || + new_y != window->frame->rect.y) + need_move_frame = TRUE; + + if (window->rect.x != fgeom.left_width || + window->rect.y != fgeom.top_height) + need_move_client = TRUE; + + window->frame->rect.x = new_x; + window->frame->rect.y = new_y; + + /* window->rect.x, window->rect.y are relative to frame, + * remember they are the server coords + */ + window->rect.x = fgeom.left_width; + window->rect.y = fgeom.top_height; + } + else + { + if (root_x_nw != window->rect.x || + root_y_nw != window->rect.y) + need_move_client = TRUE; + + window->rect.x = root_x_nw; + window->rect.y = root_y_nw; } /* Fill in other frame member variables */ @@ -602,8 +627,11 @@ meta_window_move_resize_internal (MetaWindow *window, * notify if we don't resize. ICCCM 4.1.5 */ need_configure_notify = - (!resize) || - (is_configure_request && !(move || resize || window->border_width != 0)); + (!need_resize_client) || + (is_configure_request && + !(need_move_client || need_move_frame || + need_resize_client || need_resize_frame || + window->border_width != 0)); /* Sync our new size/pos with X as efficiently as possible */ @@ -616,17 +644,17 @@ meta_window_move_resize_internal (MetaWindow *window, mask = 0; if (is_configure_request && window->border_width != 0) mask |= CWBorderWidth; /* must force to 0 */ - if (move) + if (need_move_client) mask |= (CWX | CWY); - if (resize) + if (need_resize_client) mask |= (CWWidth | CWHeight); if (mask != 0) { meta_verbose ("Syncing new geometry to client, border: %s pos: %s size: %s\n", mask & CWBorderWidth ? "true" : "false", - mask & CWX ? "true" : "false", - mask & CWWidth ? "true" : "false"); + need_move_client ? "true" : "false", + need_resize_client ? "true" : "false"); meta_error_trap_push (window->display); XConfigureWindow (window->display->xdisplay, @@ -638,10 +666,16 @@ meta_window_move_resize_internal (MetaWindow *window, /* Now do the frame */ if (window->frame) - meta_frame_sync_to_window (window->frame); + meta_frame_sync_to_window (window->frame, need_move_frame, need_resize_frame); if (need_configure_notify) send_configure_notify (window); + + /* Invariants leaving this function are: + * a) window->rect and frame->rect reflect the actual + * server-side size/pos of window->xwindow and frame->xwindow + * b) all constraints are obeyed by window->rect and frame->rect + */ } void @@ -649,7 +683,11 @@ meta_window_resize (MetaWindow *window, int w, int h) { - meta_window_move_resize_internal (window, FALSE, TRUE, FALSE, -1, -1, w, h); + int x, y; + + meta_window_get_position (window, &x, &y); + + meta_window_move_resize_internal (window, FALSE, x, y, w, h); } void @@ -657,8 +695,10 @@ meta_window_move (MetaWindow *window, int root_x_nw, int root_y_nw) { - meta_window_move_resize_internal (window, TRUE, FALSE, FALSE, - root_x_nw, root_y_nw, -1, -1); + meta_window_move_resize_internal (window, FALSE, + root_x_nw, root_y_nw, + window->rect.width, + window->rect.height); } void @@ -668,7 +708,7 @@ meta_window_move_resize (MetaWindow *window, int w, int h) { - meta_window_move_resize_internal (window, TRUE, TRUE, FALSE, + meta_window_move_resize_internal (window, FALSE, root_x_nw, root_y_nw, w, h); } @@ -676,7 +716,7 @@ meta_window_move_resize (MetaWindow *window, void meta_window_queue_move_resize (MetaWindow *window) { - /* FIXME actually queue */ + /* FIXME actually queue, don't do it immediately */ int x, y; meta_window_get_position (window, &x, &y); @@ -779,6 +819,75 @@ meta_window_change_workspace (MetaWindow *window, } void +meta_window_stick (MetaWindow *window) +{ + if (window->on_all_workspaces) + return; + + /* We don't change window->workspaces, because we revert + * to that original workspace list if on_all_workspaces is + * toggled back off. + */ + window->on_all_workspaces = TRUE; + + meta_window_set_current_workspace_hint (window); + + meta_window_queue_calc_showing (window); +} + +void +meta_window_unstick (MetaWindow *window) +{ + if (!window->on_all_workspaces) + return; + + /* Revert to window->workspaces */ + + window->on_all_workspaces = FALSE; + + /* We change ourselves to the active workspace, since otherwise you'd get + * a weird window-vaporization effect. Once we have UI for being + * on more than one workspace this should probably be add_workspace + * not change_workspace. + */ + if (!meta_workspace_contains_window (window->screen->active_workspace, + window)) + meta_window_change_workspace (window, window->screen->active_workspace); + + meta_window_set_current_workspace_hint (window); + + meta_window_queue_calc_showing (window); +} + +int +meta_window_set_current_workspace_hint (MetaWindow *window) +{ + /* FIXME if on more than one workspace, we claim to be "sticky", + * the WM spec doesn't say what to do here. + */ + unsigned long data[1]; + + if (window->workspaces == NULL) + return Success; /* this happens when destroying windows */ + + if (window->on_all_workspaces || + 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); +} + +void meta_window_raise (MetaWindow *window) { meta_verbose ("Raising window %s\n", window->desc); @@ -891,9 +1000,19 @@ meta_window_client_message (MetaWindow *window, space); if (workspace) - meta_window_change_workspace (window, workspace); + { + if (window->on_all_workspaces) + meta_window_unstick (window); + meta_window_change_workspace (window, workspace); + } + else if (space == 0xFFFFFFFF) + { + meta_window_stick (window); + } else - meta_verbose ("No such workspace %d for screen\n", space); + { + meta_verbose ("No such workspace %d for screen\n", space); + } return TRUE; } @@ -1026,7 +1145,7 @@ process_property_notify (MetaWindow *window, else if (event->atom == XA_WM_TRANSIENT_FOR) { update_transient_for (window); - + meta_window_queue_move_resize (window); } else if (event->atom == @@ -1041,6 +1160,11 @@ process_property_notify (MetaWindow *window, { meta_warning ("Broken client changed client leader window or SM client ID\n"); } + else if (event->atom == + window->display->atom_net_wm_window_type) + { + update_net_wm_type (window); + } return TRUE; } @@ -1109,7 +1233,7 @@ process_configure_request (MetaWindow *window, window->size_hints.width = width; window->size_hints.height = height; - meta_window_move_resize_internal (window, TRUE, TRUE, TRUE, + meta_window_move_resize_internal (window, TRUE, window->size_hints.x, window->size_hints.y, window->size_hints.width, @@ -1427,6 +1551,7 @@ update_net_wm_state (MetaWindow *window) window->shaded = FALSE; window->maximized = FALSE; + window->wm_state_modal = FALSE; meta_error_trap_push (window->display); XGetWindowProperty (window->display->xdisplay, window->xwindow, @@ -1437,10 +1562,16 @@ update_net_wm_state (MetaWindow *window) result = meta_error_trap_pop (window->display); if (result != Success) - return result; - + { + recalc_window_type (window); + return result; + } + if (type != XA_ATOM) - return -1; /* whatever */ + { + recalc_window_type (window); + return -1; /* whatever */ + } i = 0; while (i < n_atoms) @@ -1451,12 +1582,16 @@ update_net_wm_state (MetaWindow *window) window->maximized = TRUE; else if (atoms[i] == window->display->atom_net_wm_state_maximized_vert) window->maximized = TRUE; + else if (atoms[i] == window->display->atom_net_wm_state_modal) + window->wm_state_modal = TRUE; ++i; } XFree (atoms); + recalc_window_type (window); + return Success; } @@ -1746,10 +1881,122 @@ update_transient_for (MetaWindow *window) window->xtransient_for); else meta_verbose ("Window %s is not transient\n", window->desc); + + /* may now be a dialog */ + recalc_window_type (window); return meta_error_trap_pop (window->display); } +static int +update_net_wm_type (MetaWindow *window) +{ + Atom type; + gint format; + gulong n_atoms; + gulong bytes_after; + Atom *atoms; + int result; + int i; + + window->type_atom = None; + + meta_error_trap_push (window->display); + XGetWindowProperty (window->display->xdisplay, window->xwindow, + window->display->atom_net_wm_window_type, + 0, G_MAXLONG, + False, XA_ATOM, &type, &format, &n_atoms, + &bytes_after, (guchar **)&atoms); + + result = meta_error_trap_pop (window->display); + if (result != Success) + { + recalc_window_type (window); + return result; + } + + if (type != XA_ATOM) + { + recalc_window_type (window); + return -1; /* whatever */ + } + + i = 0; + while (i < n_atoms) + { + /* We break as soon as we find one we recognize, + * supposed to prefer those near the front of the list + */ + if (atoms[i] == window->display->atom_net_wm_window_type_desktop || + atoms[i] == window->display->atom_net_wm_window_type_dock || + atoms[i] == window->display->atom_net_wm_window_type_toolbar || + atoms[i] == window->display->atom_net_wm_window_type_menu || + atoms[i] == window->display->atom_net_wm_window_type_dialog || + atoms[i] == window->display->atom_net_wm_window_type_normal) + { + window->type_atom = atoms[i]; + break; + } + + ++i; + } + + XFree (atoms); + + if (meta_is_verbose ()) + { + char *str; + + meta_error_trap_push (window->display); + str = XGetAtomName (window->display->xdisplay, window->type_atom); + if (meta_error_trap_pop (window->display)) + str = NULL; + + meta_verbose ("Window %s type atom %s\n", window->desc, + str ? str : "(none)"); + + if (str) + XFree (str); + } + + recalc_window_type (window); + return Success; +} + +static void +recalc_window_type (MetaWindow *window) +{ + if (window->type_atom != None) + { + if (window->type_atom == window->display->atom_net_wm_window_type_desktop) + window->type = META_WINDOW_DESKTOP; + else if (window->type_atom == window->display->atom_net_wm_window_type_dock) + window->type = META_WINDOW_DOCK; + else if (window->type_atom == window->display->atom_net_wm_window_type_toolbar) + window->type = META_WINDOW_TOOLBAR; + else if (window->type_atom == window->display->atom_net_wm_window_type_menu) + window->type = META_WINDOW_MENU; + else if (window->type_atom == window->display->atom_net_wm_window_type_dialog) + window->type = META_WINDOW_DIALOG; + else if (window->type_atom == window->display->atom_net_wm_window_type_normal) + window->type = META_WINDOW_NORMAL; + } + else if (window->xtransient_for != None) + { + window->type = META_WINDOW_DIALOG; + } + else + { + window->type = META_WINDOW_NORMAL; + } + + if (window->type == META_WINDOW_DIALOG && + window->wm_state_modal) + window->type = META_WINDOW_MODAL_DIALOG; + + meta_verbose ("Calculated type %d for %s\n", window->type, window->desc); +} + static void constrain_size (MetaWindow *window, int width, int height, diff --git a/src/window.h b/src/window.h index 7ee06358..237b2c1f 100644 --- a/src/window.h +++ b/src/window.h @@ -26,6 +26,17 @@ #include "util.h" #include <X11/Xutil.h> +typedef enum +{ + META_WINDOW_NORMAL, + META_WINDOW_DESKTOP, + META_WINDOW_DOCK, + META_WINDOW_DIALOG, + META_WINDOW_MODAL_DIALOG, + META_WINDOW_TOOLBAR, + META_WINDOW_MENU +} MetaWindowType; + struct _MetaWindow { MetaDisplay *display; @@ -39,6 +50,9 @@ struct _MetaWindow char *desc; /* used in debug spew */ char *title; + MetaWindowType type; + Atom type_atom; + /* NOTE these four are not in UTF-8, we just treat them as random * binary data */ @@ -56,6 +70,12 @@ struct _MetaWindow /* Whether we're shaded */ guint shaded : 1; + + /* Whether we're sticky in the multi-workspace sense + * (vs. the not-scroll-with-viewport sense, we don't + * have no stupid viewports) + */ + guint on_all_workspaces : 1; /* Mapped is what we think the mapped state should be; * so if we get UnmapNotify and mapped == TRUE then @@ -88,6 +108,9 @@ struct _MetaWindow guint has_minimize_func : 1; guint has_maximize_func : 1; + /* Weird "_NET_WM_STATE_MODAL" flag */ + guint wm_state_modal : 1; + /* this flag tracks receipt of focus_in focus_out and * determines whether we draw the focus */ @@ -126,6 +149,8 @@ void meta_window_shade (MetaWindow *window); void meta_window_unshade (MetaWindow *window); void meta_window_change_workspace (MetaWindow *window, MetaWorkspace *workspace); +void meta_window_stick (MetaWindow *window); +void meta_window_unstick (MetaWindow *window); /* args to move are window pos, not frame pos */ void meta_window_move (MetaWindow *window, @@ -167,4 +192,6 @@ gboolean meta_window_property_notify (MetaWindow *window, XEvent *event); gboolean meta_window_client_message (MetaWindow *window, XEvent *event); + +int meta_window_set_current_workspace_hint (MetaWindow *window); #endif diff --git a/src/workspace.c b/src/workspace.c index 3920c77b..f7e5188c 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -25,8 +25,8 @@ 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); +static int set_active_space_hint (MetaScreen *screen); MetaWorkspace* meta_workspace_new (MetaScreen *screen) @@ -82,12 +82,12 @@ void meta_workspace_add_window (MetaWorkspace *workspace, MetaWindow *window) { - g_return_if_fail (g_list_find (workspace->windows, window) == NULL); - + g_return_if_fail (!meta_workspace_contains_window (workspace, window)); + workspace->windows = g_list_prepend (workspace->windows, window); window->workspaces = g_list_prepend (window->workspaces, workspace); - set_current_workspace_hint (window); + meta_window_set_current_workspace_hint (window); meta_window_queue_calc_showing (window); } @@ -96,16 +96,23 @@ void meta_workspace_remove_window (MetaWorkspace *workspace, MetaWindow *window) { - g_return_if_fail (g_list_find (workspace->windows, window) != NULL); + g_return_if_fail (meta_workspace_contains_window (workspace, window)); workspace->windows = g_list_remove (workspace->windows, window); window->workspaces = g_list_remove (window->workspaces, workspace); - set_current_workspace_hint (window); + meta_window_set_current_workspace_hint (window); meta_window_queue_calc_showing (window); } +gboolean +meta_workspace_contains_window (MetaWorkspace *workspace, + MetaWindow *window) +{ + return g_list_find (workspace->windows, window) != NULL; +} + void meta_workspace_queue_calc_showing (MetaWorkspace *workspace) { @@ -135,6 +142,8 @@ meta_workspace_activate (MetaWorkspace *workspace) workspace->screen->active_workspace = workspace; + set_active_space_hint (workspace->screen); + meta_workspace_queue_calc_showing (old); meta_workspace_queue_calc_showing (workspace); } @@ -184,44 +193,35 @@ meta_workspace_screen_index (MetaWorkspace *workspace) meta_bug ("Workspace does not exist to index!\n"); } - static int -set_current_workspace_hint (MetaWindow *window) +set_number_of_spaces_hint (MetaScreen *screen) { - /* 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); + data[0] = meta_screen_get_n_workspaces (screen); - meta_verbose ("Setting _NET_WM_DESKTOP of %s to %ld\n", - window->desc, data[0]); + meta_verbose ("Setting _NET_NUMBER_OF_DESKTOPS to %ld\n", data[0]); - meta_error_trap_push (window->display); - XChangeProperty (window->display->xdisplay, window->xwindow, - window->display->atom_net_wm_desktop, + 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 (window->display); + return meta_error_trap_pop (screen->display); } static int -set_number_of_spaces_hint (MetaScreen *screen) +set_active_space_hint (MetaScreen *screen) { unsigned long data[1]; - data[0] = meta_screen_get_n_workspaces (screen); + data[0] = meta_workspace_screen_index (screen->active_workspace); - meta_verbose ("Setting _NET_NUMBER_OF_DESKTOPS to %ld\n", data[0]); + meta_verbose ("Setting _NET_CURRENT_DESKTOP to %ld\n", data[0]); meta_error_trap_push (screen->display); XChangeProperty (screen->display->xdisplay, screen->xroot, - screen->display->atom_net_number_of_desktops, + screen->display->atom_net_current_desktop, 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 d7f7e36d..e949dd1f 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -39,7 +39,8 @@ void meta_workspace_add_window (MetaWorkspace *workspace, MetaWindow *window); void meta_workspace_remove_window (MetaWorkspace *workspace, MetaWindow *window); - +gboolean meta_workspace_contains_window (MetaWorkspace *workspace, + MetaWindow *window); void meta_workspace_activate (MetaWorkspace *workspace); int meta_workspace_index (MetaWorkspace *workspace); int meta_workspace_screen_index (MetaWorkspace *workspace); |