diff --git a/ChangeLog b/ChangeLog index 0bba052b3..0b4690093 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2001-12-09 Havoc Pennington + + * src/workspace.c (meta_workspace_free): update number of + workspaces hint + + * src/screen.c (update_num_workspaces): implement number of + workspaces setting + + * src/window.c (meta_window_configure_request): honor configure + requests on windows of type NORMAL, but still be mean to those of + type DIALOG + + * src/main.c (main): add more log domains to those we set a log + handler for, and only set warnings fatal in debug mode + + * src/metacity.schemas: add number of workspaces setting + 2001-12-09 Havoc Pennington * src/display.c (event_callback): in click-to-focus mode don't diff --git a/src/errors.c b/src/errors.c index 3bf480fbd..95d1a33a1 100644 --- a/src/errors.c +++ b/src/errors.c @@ -51,7 +51,7 @@ meta_error_trap_push (MetaDisplay *display) int meta_error_trap_pop (MetaDisplay *display) { - /* just use GDK trap */ + /* just use GDK trap, but we do the sync since GDK doesn't */ XSync (display->xdisplay, False); return gdk_error_trap_pop (); diff --git a/src/main.c b/src/main.c index f00d87e86..2228bb78f 100644 --- a/src/main.c +++ b/src/main.c @@ -49,7 +49,7 @@ log_handler (const gchar *log_domain, const gchar *message, gpointer user_data) { - meta_warning ("GLib log level %d: %s\n", log_level, message); + meta_warning ("Log level %d: %s\n", log_level, message); } static void @@ -184,8 +184,28 @@ main (int argc, char **argv) g_log_set_handler (NULL, G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, log_handler, NULL); - g_log_set_always_fatal (G_LOG_LEVEL_MASK); + g_log_set_handler ("Gtk", + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, + log_handler, NULL); + g_log_set_handler ("Gdk", + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, + log_handler, NULL); + g_log_set_handler ("GLib", + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, + log_handler, NULL); + g_log_set_handler ("Pango", + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, + log_handler, NULL); + g_log_set_handler ("GLib-GObject", + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, + log_handler, NULL); + g_log_set_handler ("GThread", + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, + log_handler, NULL); + if (meta_is_debugging ()) + g_log_set_always_fatal (G_LOG_LEVEL_MASK); + /* Connect to SM as late as possible - but before managing display, * or we might try to manage a window before we have the session * info diff --git a/src/metacity.schemas b/src/metacity.schemas index e8caa56e4..355a90943 100644 --- a/src/metacity.schemas +++ b/src/metacity.schemas @@ -76,6 +76,22 @@ + + /schemas/apps/metacity/general/num_workspaces + /apps/metacity/general/num_workspaces + metacity + int + 4 + + Number of workspaces + + Number of workspaces. Must be more than zero, and + has a fixed maximum (to prevent accidentally destroying + your desktop by asking for 34 million workspaces). + + + + diff --git a/src/prefs.c b/src/prefs.c index a82d69a4e..eefb0916e 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -32,6 +32,7 @@ #define KEY_USE_DESKTOP_FONT "/apps/metacity/general/titlebar_uses_desktop_font" #define KEY_TITLEBAR_FONT "/apps/metacity/general/titlebar_font" #define KEY_TITLEBAR_FONT_SIZE "/apps/metacity/general/titlebar_font_size" +#define KEY_NUM_WORKSPACES "/apps/metacity/general/num_workspaces" static GConfClient *client = NULL; static GList *listeners = NULL; @@ -41,11 +42,13 @@ static gboolean use_desktop_font = TRUE; static PangoFontDescription *titlebar_font = NULL; static int titlebar_font_size = 0; static MetaFocusMode focus_mode = META_FOCUS_MODE_CLICK; +static int num_workspaces = 4; static gboolean update_use_desktop_font (gboolean value); static gboolean update_titlebar_font (const char *value); static gboolean update_titlebar_font_size (int value); static gboolean update_focus_mode (const char *value); +static gboolean update_num_workspaces (int value); static void queue_changed (MetaPreference pref); static void change_notify (GConfClient *client, @@ -174,7 +177,7 @@ cleanup_error (GError **error) { if (*error) { - meta_warning ("%s", (*error)->message); + meta_warning ("%s\n", (*error)->message); g_error_free (*error); *error = NULL; @@ -206,6 +209,11 @@ meta_prefs_init (void) update_focus_mode (str_val); g_free (str_val); + /* If the keys aren't set in the database, we use essentially + * bogus values instead of any kind of default. This is + * just lazy. But they keys ought to be set, anyhow. + */ + bool_val = gconf_client_get_bool (client, KEY_USE_DESKTOP_FONT, &err); cleanup_error (&err); @@ -222,6 +230,11 @@ meta_prefs_init (void) update_titlebar_font (str_val); g_free (str_val); + int_val = gconf_client_get_int (client, KEY_NUM_WORKSPACES, + &err); + cleanup_error (&err); + update_num_workspaces (int_val); + gconf_client_notify_add (client, "/apps/metacity", change_notify, NULL, @@ -310,6 +323,23 @@ change_notify (GConfClient *client, if (update_use_desktop_font (b)) queue_changed (META_PREF_TITLEBAR_FONT); } + else if (strcmp (key, KEY_NUM_WORKSPACES) == 0) + { + int d; + + if (value && value->type != GCONF_VALUE_INT) + { + meta_warning (_("GConf key \"%s\" is set to an invalid type\n"), + KEY_NUM_WORKSPACES); + goto out; + } + + /* 4 is a fallback that should never be used */ + d = value ? gconf_value_get_int (value) : 4; + + if (update_num_workspaces (d)) + queue_changed (META_PREF_NUM_WORKSPACES); + } else meta_verbose ("Key %s doesn't mean anything to Metacity\n", key); @@ -419,6 +449,35 @@ meta_prefs_get_titlebar_font_size (void) return titlebar_font_size; } + +#define MAX_REASONABLE_WORKSPACES 32 + +static gboolean +update_num_workspaces (int value) +{ + int old = num_workspaces; + + if (value < 1 || value > MAX_REASONABLE_WORKSPACES) + { + meta_warning (_("%d stored in GConf key %s is not a reasonable number of workspaces, current maximum is %d\n"), + value, KEY_NUM_WORKSPACES, MAX_REASONABLE_WORKSPACES); + if (value < 1) + value = 1; + else if (value > MAX_REASONABLE_WORKSPACES) + value = MAX_REASONABLE_WORKSPACES; + } + + num_workspaces = value; + + return old != num_workspaces; +} + +int +meta_prefs_get_num_workspaces (void) +{ + return num_workspaces; +} + const char* meta_preference_to_string (MetaPreference pref) { @@ -435,6 +494,10 @@ meta_preference_to_string (MetaPreference pref) case META_PREF_TITLEBAR_FONT_SIZE: return "TITLEBAR_FONT_SIZE"; break; + + case META_PREF_NUM_WORKSPACES: + return "NUM_WORKSPACES"; + break; } return "(unknown)"; diff --git a/src/prefs.h b/src/prefs.h index 3b45a615b..2acb4102e 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -30,7 +30,8 @@ typedef enum { META_PREF_FOCUS_MODE, META_PREF_TITLEBAR_FONT, - META_PREF_TITLEBAR_FONT_SIZE + META_PREF_TITLEBAR_FONT_SIZE, + META_PREF_NUM_WORKSPACES } MetaPreference; @@ -50,6 +51,7 @@ MetaFocusMode meta_prefs_get_focus_mode (void); const PangoFontDescription* meta_prefs_get_titlebar_font (void); /* returns 0 if default should be used */ int meta_prefs_get_titlebar_font_size (void); +int meta_prefs_get_num_workspaces (void); #endif diff --git a/src/screen.c b/src/screen.c index 970751bcb..a04f39f63 100644 --- a/src/screen.c +++ b/src/screen.c @@ -25,6 +25,7 @@ #include "errors.h" #include "window.h" #include "frame.h" +#include "prefs.h" #include "workspace.h" #include "keybindings.h" #include "stack.h" @@ -36,6 +37,9 @@ static char* get_screen_name (MetaDisplay *display, int number); +static void update_num_workspaces (MetaScreen *screen); +static void prefs_changed_callback (MetaPreference pref, + gpointer data); static int set_wm_check_hint (MetaScreen *screen) @@ -231,6 +235,8 @@ meta_screen_new (MetaDisplay *display, screen->tab_popup = NULL; screen->stack = meta_stack_new (screen); + + meta_prefs_add_listener (prefs_changed_callback, screen); meta_verbose ("Added screen %d ('%s') root 0x%lx\n", screen->number, screen->screen_name, screen->xroot); @@ -240,7 +246,9 @@ meta_screen_new (MetaDisplay *display, void meta_screen_free (MetaScreen *screen) -{ +{ + meta_prefs_remove_listener (prefs_changed_callback, screen); + meta_screen_ungrab_keys (screen); meta_ui_free (screen->ui); @@ -303,6 +311,19 @@ meta_screen_for_x_screen (Screen *xscreen) return meta_display_screen_for_x_screen (display, xscreen); } +static void +prefs_changed_callback (MetaPreference pref, + gpointer data) +{ + MetaScreen *screen = data; + + if (pref == META_PREF_NUM_WORKSPACES) + { + update_num_workspaces (screen); + } +} + + static char* get_screen_name (MetaDisplay *display, int number) @@ -437,7 +458,91 @@ meta_screen_get_n_workspaces (MetaScreen *screen) } return i; +} +static void +update_num_workspaces (MetaScreen *screen) +{ + int new_num; + GList *tmp; + int i; + GList *extras; + MetaWorkspace *last_remaining; + gboolean need_change_space; + + new_num = meta_prefs_get_num_workspaces (); + + g_assert (new_num > 0); + + last_remaining = NULL; + extras = NULL; + i = 0; + tmp = screen->display->workspaces; + while (tmp != NULL) + { + MetaWorkspace *w = tmp->data; + + if (w->screen == screen) + { + ++i; + + if (i > new_num) + extras = g_list_prepend (extras, w); + else + last_remaining = w; + } + + tmp = tmp->next; + } + + g_assert (last_remaining); + + /* Get rid of the extra workspaces by moving all their windows + * to last_remaining, then activating last_remaining if + * one of the removed workspaces was active. This will be a bit + * wacky if the config tool for changing number of workspaces + * is on a removed workspace ;-) + */ + need_change_space = FALSE; + tmp = extras; + while (tmp != NULL) + { + MetaWorkspace *w = tmp->data; + + meta_workspace_relocate_windows (w, last_remaining); + + if (w == screen->active_workspace) + need_change_space = TRUE; + + tmp = tmp->next; + } + + if (need_change_space) + meta_workspace_activate (last_remaining); + + /* Should now be safe to free the workspaces */ + tmp = extras; + while (tmp != NULL) + { + MetaWorkspace *w = tmp->data; + + g_assert (w->windows == NULL); + meta_workspace_free (w); + + tmp = tmp->next; + } + + g_list_free (extras); + + /* Add missing workspaces. FIXME This will keep setting the + * number-of-workspaces root window property on each workspace + * creation, kind of a lame thing + */ + while (i < new_num) + { + meta_workspace_new (screen); + ++i; + } } void diff --git a/src/window.c b/src/window.c index b7b47cd40..fd15a993b 100644 --- a/src/window.c +++ b/src/window.c @@ -2200,12 +2200,9 @@ meta_window_configure_request (MetaWindow *window, if (((window->type == META_WINDOW_DESKTOP || window->type == META_WINDOW_DOCK || window->type == META_WINDOW_TOOLBAR || - window->type == META_WINDOW_MENU) && + window->type == META_WINDOW_MENU || + window->type == META_WINDOW_NORMAL) && (window->size_hints.flags & PPosition)) || - /* This is here exactly until some crap app annoys me - * by misusing it. ;-) Then I remove it and only honor - * USPosition at map time. - */ (window->size_hints.flags & USPosition)) { if (event->xconfigurerequest.value_mask & CWX) @@ -2224,7 +2221,8 @@ meta_window_configure_request (MetaWindow *window, if (window->type == META_WINDOW_DESKTOP || window->type == META_WINDOW_DOCK || window->type == META_WINDOW_TOOLBAR || - window->type == META_WINDOW_MENU) + window->type == META_WINDOW_MENU || + window->type == META_WINDOW_NORMAL) { if (event->xconfigurerequest.value_mask & CWWidth) width = event->xconfigurerequest.width; diff --git a/src/workspace.c b/src/workspace.c index 7bf51e9c9..20eb11ec3 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -58,24 +58,39 @@ void meta_workspace_free (MetaWorkspace *workspace) { GList *tmp; + MetaScreen *screen; + + g_return_if_fail (workspace != workspace->screen->active_workspace); + + /* Here we assume all the windows are already on another workspace + * as well, so they won't be "orphaned" + */ tmp = workspace->windows; while (tmp != NULL) { GList *next; + MetaWindow *window = tmp->data; next = tmp->next; - /* pop front of list */ - meta_workspace_remove_window (workspace, tmp->data); + + /* pop front of list we're iterating over */ + meta_workspace_remove_window (workspace, window); + g_assert (window->workspaces != NULL); tmp = next; } g_assert (workspace->windows == NULL); + + screen = workspace->screen; workspace->screen->display->workspaces = g_list_remove (workspace->screen->display->workspaces, workspace); g_free (workspace); + + /* Update hint for current number of workspaces */ + set_number_of_spaces_hint (screen); } void @@ -106,6 +121,34 @@ meta_workspace_remove_window (MetaWorkspace *workspace, meta_window_queue_calc_showing (window); } +void +meta_workspace_relocate_windows (MetaWorkspace *workspace, + MetaWorkspace *new_home) +{ + GList *tmp; + GList *copy; + + g_return_if_fail (workspace != new_home); + + /* can't modify list we're iterating over */ + copy = g_list_copy (workspace->windows); + + tmp = copy; + while (tmp != NULL) + { + MetaWindow *window = tmp->data; + + meta_workspace_add_window (new_home, window); + meta_workspace_remove_window (workspace, window); + + tmp = tmp->next; + } + + g_list_free (copy); + + g_assert (workspace->windows == NULL); +} + gboolean meta_workspace_contains_window (MetaWorkspace *workspace, MetaWindow *window) @@ -226,6 +269,3 @@ set_active_space_hint (MetaScreen *screen) 32, PropModeReplace, (guchar*) data, 1); return meta_error_trap_pop (screen->display); } - - - diff --git a/src/workspace.h b/src/workspace.h index 6620eeeda..97f12ec84 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -39,6 +39,8 @@ void meta_workspace_add_window (MetaWorkspace *workspace, MetaWindow *window); void meta_workspace_remove_window (MetaWorkspace *workspace, MetaWindow *window); +void meta_workspace_relocate_windows (MetaWorkspace *workspace, + MetaWorkspace *new_home); /* don't confuse with meta_window_visible_on_workspace() */ gboolean meta_workspace_contains_window (MetaWorkspace *workspace, MetaWindow *window);