redo using new calc_workspace_layout to fix #98302

2003-01-05  Havoc Pennington  <hp@pobox.com>

	* 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
This commit is contained in:
Havoc Pennington 2003-01-05 18:36:01 +00:00 committed by Havoc Pennington
parent 1d22cb8518
commit 90748385c2
7 changed files with 384 additions and 227 deletions

View File

@ -1,3 +1,14 @@
2003-01-05 Havoc Pennington <hp@pobox.com>
* 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 <pauli.virtanen@hut.fi>
* configure.in (ALL_LINGUAS): Added "fi" (Finnish).

View File

@ -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

View File

@ -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,

View File

@ -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);

View File

@ -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,

View File

@ -286,7 +286,7 @@ topic_name (MetaDebugTopic topic)
return "SHAPES";
}
return "Window manager";
return "WM";
}
static int sync_count = 0;

View File

@ -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);
}