From 90748385c219e123b1a3e058a70f877db07b3e01 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 5 Jan 2003 18:36:01 +0000 Subject: [PATCH] redo using new calc_workspace_layout to fix #98302 2003-01-05 Havoc Pennington * src/workspace.c (meta_workspace_get_neighbor): redo using new calc_workspace_layout to fix #98302 * src/util.c (topic_name): shorten default prefix * src/screen.c (meta_screen_calc_workspace_layout): enhance this to handle all the funky layouts and calculate more information than before --- ChangeLog | 11 ++ src/screen.c | 390 ++++++++++++++++++++++++++++++++++++++---------- src/screen.h | 21 ++- src/tabpopup.c | 11 +- src/tabpopup.h | 1 + src/util.c | 2 +- src/workspace.c | 175 ++++------------------ 7 files changed, 384 insertions(+), 227 deletions(-) diff --git a/ChangeLog b/ChangeLog index f33e87c25..21df0d1c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2003-01-05 Havoc Pennington + + * src/workspace.c (meta_workspace_get_neighbor): redo using new + calc_workspace_layout to fix #98302 + + * src/util.c (topic_name): shorten default prefix + + * src/screen.c (meta_screen_calc_workspace_layout): enhance this + to handle all the funky layouts and calculate more information + than before + 2003-01-05 Pauli Virtanen * configure.in (ALL_LINGUAS): Added "fi" (Finnish). diff --git a/src/screen.c b/src/screen.c index ef0627036..1912d898d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1068,7 +1068,8 @@ meta_screen_ensure_tab_popup (MetaScreen *screen, entries[i].key = (MetaTabEntryKey) window->xwindow; entries[i].title = window->title; entries[i].icon = window->icon; - + entries[i].blank = FALSE; + if (!window->minimized || !meta_window_get_icon_geometry (window, &r)) meta_window_get_outer_rect (window, &r); @@ -1124,79 +1125,66 @@ void meta_screen_ensure_workspace_popup (MetaScreen *screen) { MetaTabEntry *entries; - int len, rows, cols; + int len; int i; - + MetaWorkspaceLayout layout; + int n_workspaces; + int current_workspace; + if (screen->tab_popup) return; - len = meta_screen_get_n_workspaces (screen); + current_workspace = meta_workspace_index (screen->active_workspace); + n_workspaces = meta_screen_get_n_workspaces (screen); + meta_screen_calc_workspace_layout (screen, n_workspaces, + current_workspace, &layout); + + len = layout.grid_area; + entries = g_new (MetaTabEntry, len + 1); entries[len].key = NULL; entries[len].title = NULL; entries[len].icon = NULL; - - meta_screen_calc_workspace_layout (screen, len, &rows, &cols); - /* FIXME: handle screen->starting_corner - */ - if (screen->vertical_workspaces) + i = 0; + while (i < len) { - int j, k, iter; - - for (i = 0, iter = 0; i < rows; ++i) - { - for (j = 0; j < cols; ++j) - { - MetaWorkspace *workspace; - - k = i + (j * rows); - if (k >= len) - break; - - workspace = meta_screen_get_workspace_by_index (screen, k); - g_assert (workspace); - - entries[iter].key = (MetaTabEntryKey) workspace; - entries[iter].title = meta_workspace_get_name (workspace); - entries[iter].icon = NULL; - - g_assert (entries[iter].title != NULL); - - iter++; - } - } - - g_assert (iter == len); - } - else - { - for (i = 0; i < len; ++i) + if (layout.grid[i] >= 0) { MetaWorkspace *workspace; - - workspace = meta_screen_get_workspace_by_index (screen, i); - - g_assert (workspace); - + + workspace = meta_screen_get_workspace_by_index (screen, + layout.grid[i]); + entries[i].key = (MetaTabEntryKey) workspace; entries[i].title = meta_workspace_get_name (workspace); entries[i].icon = NULL; - + entries[i].blank = FALSE; + g_assert (entries[i].title != NULL); } + else + { + entries[i].key = NULL; + entries[i].title = NULL; + entries[i].icon = NULL; + entries[i].blank = TRUE; + } + + ++i; } screen->tab_popup = meta_ui_tab_popup_new (entries, screen->number, len, - cols, + layout.cols, FALSE); g_free (entries); + meta_screen_free_workspace_layout (&layout); - /* don't show tab popup, since proper window isn't selected yet */ + /* don't show tab popup, since proper space isn't selected yet */ } /* Focus top window on active workspace */ @@ -1594,36 +1582,39 @@ meta_screen_queue_workarea_recalc (MetaScreen *screen) } } -void -meta_screen_calc_workspace_layout (MetaScreen *screen, - int num_workspaces, - int *r, - int *c) -{ - int cols, rows; - /* - * 3 rows, 4 columns, horizontal layout - * and starting from top left: - * +--+--+--+--+ - * | 1| 2| 3| 4| - * +--+--+--+--+ - * | 5| 6| 7| 8| - * +--+--+--+--+ - * | 9|10|11|12| - * +--+--+--+--+ - * - * vertical layout: - * +--+--+--+--+ - * | 1| 4| 7|10| - * +--+--+--+--+ - * | 2| 5| 8|11| - * +--+--+--+--+ - * | 3| 6| 9|12| - * +--+--+--+--+ - * - */ - +#ifdef WITH_VERBOSE_MODE +static char * +meta_screen_corner_to_string (MetaScreenCorner corner) +{ + switch (corner) + { + case META_SCREEN_TOPLEFT: + return "TopLeft"; + case META_SCREEN_TOPRIGHT: + return "TopRight"; + case META_SCREEN_BOTTOMLEFT: + return "BottomLeft"; + case META_SCREEN_BOTTOMRIGHT: + return "BottomRight"; + } + + return "Unknown"; +} +#endif /* WITH_VERBOSE_MODE */ + +void +meta_screen_calc_workspace_layout (MetaScreen *screen, + int num_workspaces, + int current_space, + MetaWorkspaceLayout *layout) +{ + int rows, cols; + int grid_area; + int *grid; + int i, r, c; + int current_row, current_col; + rows = screen->rows_of_workspaces; cols = screen->columns_of_workspaces; if (rows <= 0 && cols <= 0) @@ -1640,8 +1631,251 @@ meta_screen_calc_workspace_layout (MetaScreen *screen, if (cols < 1) cols = 1; - *r = rows; - *c = cols; + g_assert (rows != 0 && cols != 0); + + grid_area = rows * cols; + + meta_verbose ("Getting layout rows = %d cols = %d current = %d " + "num_spaces = %d vertical = %s corner = %s\n", + rows, cols, current_space, num_workspaces, + screen->vertical_workspaces ? "(true)" : "(false)", + meta_screen_corner_to_string (screen->starting_corner)); + + /* ok, we want to setup the distances in the workspace array to go + * in each direction. Remember, there are many ways that a workspace + * array can be setup. + * see http://www.freedesktop.org/standards/wm-spec/1.2/html/x109.html + * and look at the _NET_DESKTOP_LAYOUT section for details. + * For instance: + */ + /* starting_corner = META_SCREEN_TOPLEFT + * vertical_workspaces = 0 vertical_workspaces=1 + * 1234 1357 + * 5678 2468 + * + * starting_corner = META_SCREEN_TOPRIGHT + * vertical_workspaces = 0 vertical_workspaces=1 + * 4321 7531 + * 8765 8642 + * + * starting_corner = META_SCREEN_BOTTOMLEFT + * vertical_workspaces = 0 vertical_workspaces=1 + * 5678 2468 + * 1234 1357 + * + * starting_corner = META_SCREEN_BOTTOMRIGHT + * vertical_workspaces = 0 vertical_workspaces=1 + * 8765 8642 + * 4321 7531 + * + */ + /* keep in mind that we could have a ragged layout, e.g. the "8" + * in the above grids could be missing + */ + + + grid = g_new (int, grid_area); + + current_row = -1; + current_col = -1; + i = 0; + + switch (screen->starting_corner) + { + case META_SCREEN_TOPLEFT: + if (screen->vertical_workspaces) + { + r = 0; + while (r < rows) + { + c = 0; + while (c < cols) + { + grid[r*cols+c] = i; + ++i; + ++c; + } + ++r; + } + } + else + { + c = 0; + while (c < cols) + { + r = 0; + while (r < rows) + { + grid[r*cols+c] = i; + ++i; + ++r; + } + ++c; + } + } + break; + case META_SCREEN_TOPRIGHT: + if (screen->vertical_workspaces) + { + r = 0; + while (r < rows) + { + c = cols - 1; + while (c >= 0) + { + grid[r*cols+c] = i; + ++i; + --c; + } + ++r; + } + } + else + { + c = cols - 1; + while (c >= 0) + { + r = 0; + while (r < rows) + { + grid[r*cols+c] = i; + ++i; + ++r; + } + --c; + } + } + break; + case META_SCREEN_BOTTOMLEFT: + if (screen->vertical_workspaces) + { + r = rows - 1; + while (r >= 0) + { + c = 0; + while (c < cols) + { + grid[r*cols+c] = i; + ++i; + ++c; + } + --r; + } + } + else + { + c = 0; + while (c < cols) + { + r = rows - 1; + while (r >= 0) + { + grid[r*cols+c] = i; + ++i; + --r; + } + ++c; + } + } + break; + case META_SCREEN_BOTTOMRIGHT: + if (screen->vertical_workspaces) + { + r = rows - 1; + while (r >= 0) + { + c = cols - 1; + while (c >= 0) + { + grid[r*cols+c] = i; + ++i; + --c; + } + --r; + } + } + else + { + c = cols - 1; + while (c >= 0) + { + r = rows - 1; + while (r >= 0) + { + grid[r*cols+c] = i; + ++i; + --r; + } + --c; + } + } + break; + } + + if (i != grid_area) + meta_bug ("did not fill in the whole workspace grid in %s (%d filled)\n", + G_GNUC_FUNCTION, i); + + current_row = 0; + current_col = 0; + r = 0; + while (r < rows) + { + c = 0; + while (c < cols) + { + if (grid[r*cols+c] == current_space) + { + current_row = r; + current_col = c; + } + else if (grid[r*cols+c] >= num_workspaces) + { + /* flag nonexistent spaces with -1 */ + grid[r*cols+c] = -1; + } + ++c; + } + ++r; + } + + layout->rows = rows; + layout->cols = cols; + layout->grid = grid; + layout->grid_area = grid_area; + layout->current_row = current_row; + layout->current_col = current_col; + +#ifdef WITH_VERBOSE_MODE + if (meta_is_verbose ()) + { + r = 0; + while (r < layout->rows) + { + meta_verbose (""); + meta_push_no_msg_prefix (); + c = 0; + while (c < layout->cols) + { + if (r == layout->current_row && + c == layout->current_col) + meta_verbose ("*%2d ", layout->grid[r*layout->cols+c]); + else + meta_verbose ("%3d ", layout->grid[r*layout->cols+c]); + ++c; + } + meta_verbose ("\n"); + meta_pop_no_msg_prefix (); + ++r; + } + } +#endif /* WITH_VERBOSE_MODE */ +} + +void +meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout) +{ + g_free (layout->grid); } static void diff --git a/src/screen.h b/src/screen.h index 351f6b92a..5ab5ec38e 100644 --- a/src/screen.h +++ b/src/screen.h @@ -138,10 +138,23 @@ void meta_screen_queue_workarea_recalc (MetaScreen *scree Window meta_create_offscreen_window (Display *xdisplay, Window parent); -void meta_screen_calc_workspace_layout (MetaScreen *screen, - int num_workspaces, - int *r, - int *c); +typedef struct MetaWorkspaceLayout MetaWorkspaceLayout; + +struct MetaWorkspaceLayout +{ + int rows; + int cols; + int *grid; + int grid_area; + int current_row; + int current_col; +}; + +void meta_screen_calc_workspace_layout (MetaScreen *screen, + int num_workspaces, + int current_space, + MetaWorkspaceLayout *layout); +void meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout); void meta_screen_resize (MetaScreen *screen, int width, diff --git a/src/tabpopup.c b/src/tabpopup.c index 5dfcf1ccb..58e2a2ab9 100644 --- a/src/tabpopup.c +++ b/src/tabpopup.c @@ -44,6 +44,7 @@ struct _TabEntry GtkWidget *widget; GdkRectangle rect; GdkRectangle inner_rect; + guint blank : 1; }; struct _MetaTabPopup @@ -160,6 +161,7 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries, te->title = g_strdup (entries[i].title); te->widget = NULL; te->icon = entries[i].icon; + te->blank = entries[i].blank; if (te->icon) g_object_ref (G_OBJECT (te->icon)); @@ -227,8 +229,13 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries, TabEntry *te; te = tmp->data; - - if (outline) + + if (te->blank) + { + /* just stick a widget here to avoid special cases */ + image = gtk_alignment_new (0.0, 0.0, 0.0, 0.0); + } + else if (outline) { image = selectable_image_new (te->icon); diff --git a/src/tabpopup.h b/src/tabpopup.h index 67a0c748a..82f28f559 100644 --- a/src/tabpopup.h +++ b/src/tabpopup.h @@ -39,6 +39,7 @@ struct _MetaTabEntry GdkPixbuf *icon; int x, y, width, height; int inner_x, inner_y, inner_width, inner_height; + guint blank : 1; }; MetaTabPopup* meta_ui_tab_popup_new (const MetaTabEntry *entries, diff --git a/src/util.c b/src/util.c index 6e43f5fe9..e10441931 100644 --- a/src/util.c +++ b/src/util.c @@ -286,7 +286,7 @@ topic_name (MetaDebugTopic topic) return "SHAPES"; } - return "Window manager"; + return "WM"; } static int sync_count = 0; diff --git a/src/workspace.c b/src/workspace.c index d49fd3988..40e445da1 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -435,168 +435,59 @@ meta_motion_direction_to_string (MetaMotionDirection direction) } #endif /* WITH_VERBOSE_MODE */ -#ifdef WITH_VERBOSE_MODE -static char * -meta_screen_corner_to_string (MetaScreenCorner corner) -{ - switch (corner) - { - case META_SCREEN_TOPLEFT: - return "TopLeft"; - case META_SCREEN_TOPRIGHT: - return "TopRight"; - case META_SCREEN_BOTTOMLEFT: - return "BottomLeft"; - case META_SCREEN_BOTTOMRIGHT: - return "BottomRight"; - } - - return "Unknown"; -} -#endif /* WITH_VERBOSE_MODE */ - MetaWorkspace* meta_workspace_get_neighbor (MetaWorkspace *workspace, MetaMotionDirection direction) { - int i, num_workspaces, grid_area; - int rows, cols; - int new_workspace_idx; - int up_diff, down_diff, left_diff, right_diff; - int current_row, current_col; - - i = meta_workspace_index (workspace); + MetaWorkspaceLayout layout; + int i, current_space, num_workspaces; + + current_space = meta_workspace_index (workspace); num_workspaces = meta_screen_get_n_workspaces (workspace->screen); - meta_screen_calc_workspace_layout (workspace->screen, num_workspaces, - &rows, &cols); + current_space, &layout); - g_assert (rows != 0 && cols != 0); - - grid_area = rows * cols; - - meta_verbose ("Getting neighbor rows = %d cols = %d current = %d " - "num_spaces = %d vertical = %s direction = %s corner = %s\n", - rows, cols, i, num_workspaces, - workspace->screen->vertical_workspaces ? "(true)" : "(false)", - meta_motion_direction_to_string (direction), - meta_screen_corner_to_string (workspace->screen->starting_corner)); + meta_verbose ("Getting neighbor of %d in direction %s\n", + current_space, meta_motion_direction_to_string (direction)); - /* ok, we want to setup the distances in the workspace array to go - * in each direction. Remember, there are many ways that a workspace - * array can be setup. - * see http://www.freedesktop.org/standards/wm-spec/1.2/html/x109.html - * and look at the _NET_DESKTOP_LAYOUT section for details. - * For instance: - */ - /* starting_corner = META_SCREEN_TOPLEFT - * vertical_workspaces = 0 vertical_workspaces=1 - * 1234 1357 - * 5678 2468 - * - * starting_corner = META_SCREEN_TOPRIGHT - * vertical_workspaces = 0 vertical_workspaces=1 - * 4321 7531 - * 8765 8642 - * - * starting_corner = META_SCREEN_BOTTOMLEFT - * vertical_workspaces = 0 vertical_workspaces=1 - * 5678 2468 - * 1234 1357 - * - * starting_corner = META_SCREEN_BOTTOMRIGHT - * vertical_workspaces = 0 vertical_workspaces=1 - * 8765 8642 - * 4321 7531 - * - */ - - if (workspace->screen->vertical_workspaces) - { - up_diff = -1; - down_diff = 1; - left_diff = -1 * rows; - right_diff = rows; - current_col = ((i - 1) / rows) + 1; - current_row = ((i - 1) % rows) + 1; - } - else - { - up_diff = -1 * cols; - down_diff = cols; - left_diff = -1; - right_diff = 1; - current_col = (i % cols) + 1; - current_row = ((i - 1) / cols) + 1; - } - - switch (workspace->screen->starting_corner) - { - default: - case META_SCREEN_TOPLEFT: - /* this was the default case setup in the if() above */ - break; - case META_SCREEN_TOPRIGHT: - /* ok, we need to inverse the left/right values */ - left_diff = -1 * left_diff; - right_diff = -1 * right_diff; - /* also, current column needs to be mirrored */ - current_col = rows - ((current_col-1)%rows) ; - break; - case META_SCREEN_BOTTOMLEFT: - /* ok, we need to inverse the up/down values */ - up_diff = -1 * up_diff; - down_diff = -1 * up_diff; - /* also, current row needs to be mirrored */ - current_row = cols - ((current_row-1)%cols); - break; - case META_SCREEN_BOTTOMRIGHT: - /* in this case, we need to inverse everything */ - up_diff = -1 * up_diff; - down_diff = -1 * up_diff; - left_diff = -1 * left_diff; - right_diff = -1 * right_diff; - /* also, current column and row need to be reversed */ - current_col = rows - ((current_col-1)%rows); - current_row = cols - ((current_row-1)%cols); - break; - } - - meta_verbose ("Workspace deltas: up = %d down = %d left = %d right = %d. " - "Current col = %d row = %d\n", up_diff, down_diff, left_diff, - right_diff, current_col, current_row); - - /* calculate what we think the next spot should be */ - new_workspace_idx = i; - switch (direction) { case META_MOTION_LEFT: - if (current_col >= 1) - new_workspace_idx = i + left_diff; + layout.current_col -= 1; break; case META_MOTION_RIGHT: - if (current_col <= cols) - new_workspace_idx = i + right_diff; + layout.current_col += 1; break; case META_MOTION_UP: - if (current_row >= 1) - new_workspace_idx = i + up_diff; + layout.current_row -= 1; break; case META_MOTION_DOWN: - if (current_row <= rows) - new_workspace_idx = i + down_diff; - break; - default: - new_workspace_idx = 0; + layout.current_row += 1; break; } - /* and now make sure we don't over/under flow */ - if ((new_workspace_idx >= 0) && (new_workspace_idx < num_workspaces)) - i = new_workspace_idx; - - meta_verbose ("Neighbor workspace is %d\n", i); + if (layout.current_col < 0) + layout.current_col = 0; + if (layout.current_col >= layout.cols) + layout.current_col = layout.cols - 1; + if (layout.current_row < 0) + layout.current_row = 0; + if (layout.current_row >= layout.rows) + layout.current_row = layout.rows - 1; + + i = layout.grid[layout.current_row * layout.cols + layout.current_col]; + + if (i < 0) + i = current_space; + + if (i >= num_workspaces) + meta_bug ("calc_workspace_layout left an invalid (too-high) workspace number %d in the grid\n", + i); + + meta_verbose ("Neighbor workspace is %d at row %d col %d\n", + i, layout.current_row, layout.current_col); + + meta_screen_free_workspace_layout (&layout); return meta_screen_get_workspace_by_index (workspace->screen, i); }