use the layout information to figure out up/down neighbors

2002-05-15  Havoc Pennington  <hp@pobox.com>

	* src/workspace.c (meta_workspace_get_neighbor): use the layout
	information to figure out up/down neighbors

	* src/display.c (event_callback): catch propertynotify on
	_NET_DESKTOP_LAYOUT

	* src/screen.c (meta_screen_update_workspace_layout): keep track
	of the layout of workspaces as set by the pager
This commit is contained in:
Havoc Pennington 2002-05-16 04:03:36 +00:00 committed by Havoc Pennington
parent 2c73ab41ed
commit 5f65ca07d7
6 changed files with 223 additions and 22 deletions

View File

@ -1,3 +1,14 @@
2002-05-15 Havoc Pennington <hp@pobox.com>
* src/workspace.c (meta_workspace_get_neighbor): use the layout
information to figure out up/down neighbors
* src/display.c (event_callback): catch propertynotify on
_NET_DESKTOP_LAYOUT
* src/screen.c (meta_screen_update_workspace_layout): keep track
of the layout of workspaces as set by the pager
2002-05-15 James M. Cape <jcape@ignore-your.tv>
* src/themes/Esco/metacity-theme-1.xml: Minor tweak to minimize

View File

@ -206,7 +206,8 @@ meta_display_open (const char *name)
"_NET_WM_PID",
"WM_CLIENT_MACHINE",
"_NET_WM_WORKAREA",
"_NET_SHOW_DESKTOP"
"_NET_SHOW_DESKTOP",
"_NET_DESKTOP_LAYOUT"
};
Atom atoms[G_N_ELEMENTS(atom_names)];
@ -315,6 +316,7 @@ meta_display_open (const char *name)
display->atom_wm_client_machine = atoms[55];
display->atom_net_wm_workarea = atoms[56];
display->atom_net_show_desktop = atoms[57];
display->atom_net_desktop_layout = atoms[58];
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
* created in screen_new
@ -1241,6 +1243,20 @@ event_callback (XEvent *event,
case PropertyNotify:
if (window && !frame_was_receiver)
meta_window_property_notify (window, event);
else
{
MetaScreen *screen;
screen = meta_display_screen_for_root (display,
event->xproperty.window);
if (screen)
{
if (event->xproperty.atom ==
display->atom_net_desktop_layout)
meta_screen_update_workspace_layout (screen);
}
}
break;
case SelectionClear:
break;

View File

@ -130,6 +130,7 @@ struct _MetaDisplay
Atom atom_net_wm_state_fullscreen;
Atom atom_net_wm_workarea;
Atom atom_net_show_desktop;
Atom atom_net_desktop_layout;
/* This is the actual window from focus events,
* not the one we last set

View File

@ -29,6 +29,7 @@
#include "workspace.h"
#include "keybindings.h"
#include "stack.h"
#include "xprops.h"
#ifdef HAVE_XINERAMA
#include <X11/extensions/Xinerama.h>
@ -82,7 +83,7 @@ set_wm_check_hint (MetaScreen *screen)
static int
set_supported_hint (MetaScreen *screen)
{
#define N_SUPPORTED 31
#define N_SUPPORTED 32
#define N_WIN_SUPPORTED 1
Atom atoms[N_SUPPORTED];
@ -117,6 +118,7 @@ set_supported_hint (MetaScreen *screen)
atoms[28] = screen->display->atom_net_active_window;
atoms[29] = screen->display->atom_net_wm_workarea;
atoms[30] = screen->display->atom_net_show_desktop;
atoms[31] = screen->display->atom_net_desktop_layout;
XChangeProperty (screen->display->xdisplay, screen->xroot,
screen->display->atom_net_supported,
@ -227,6 +229,10 @@ meta_screen_new (MetaDisplay *display,
screen->work_area_idle = 0;
screen->rows_of_workspaces = 1;
screen->columns_of_workspaces = -1;
screen->vertical_workspaces = FALSE;
screen->xinerama_infos = NULL;
screen->n_xinerama_infos = 0;
@ -321,6 +327,8 @@ meta_screen_new (MetaDisplay *display,
set_wm_check_hint (screen);
meta_screen_update_workspace_layout (screen);
/* Screens must have at least one workspace at all times,
* so create that required workspace.
*/
@ -799,3 +807,72 @@ meta_screen_get_current_xinerama (MetaScreen *screen)
return &screen->xinerama_infos[0];
}
#define _NET_WM_ORIENTATION_HORZ 0
#define _NET_WM_ORIENTATION_VERT 1
void
meta_screen_update_workspace_layout (MetaScreen *screen)
{
gulong *list;
int n_items;
list = NULL;
n_items = 0;
if (meta_prop_get_cardinal_list (screen->display,
screen->xroot,
screen->display->atom_net_desktop_layout,
&list, &n_items))
{
if (n_items == 3)
{
int cols, rows;
switch (list[0])
{
case _NET_WM_ORIENTATION_HORZ:
screen->vertical_workspaces = FALSE;
break;
case _NET_WM_ORIENTATION_VERT:
screen->vertical_workspaces = TRUE;
break;
default:
meta_warning ("Someone set a weird orientation in _NET_DESKTOP_LAYOUT\n");
break;
}
rows = list[1];
cols = list[2];
if (rows <= 0 && cols <= 0)
{
meta_warning ("Columns = %d rows = %d in _NET_DESKTOP_LAYOUT makes no sense\n", rows, cols);
}
else
{
if (rows > 0)
screen->rows_of_workspaces = rows;
else
screen->rows_of_workspaces = -1;
if (cols > 0)
screen->columns_of_workspaces = cols;
else
screen->columns_of_workspaces = -1;
}
}
else
{
meta_warning ("Someone set _NET_DESKTOP_LAYOUT to %d integers instead of 3\n",
n_items);
}
meta_XFree (list);
}
meta_verbose ("Workspace layout rows = %d cols = %d orientation = %d\n",
screen->rows_of_workspaces,
screen->columns_of_workspaces,
screen->vertical_workspaces);
}

View File

@ -65,6 +65,10 @@ struct _MetaScreen
guint work_area_idle;
int rows_of_workspaces;
int columns_of_workspaces;
guint vertical_workspaces : 1;
guint keys_grabbed : 1;
};
@ -92,6 +96,8 @@ void meta_screen_focus_top_window (MetaScreen *scree
const MetaXineramaScreenInfo* meta_screen_get_current_xinerama (MetaScreen *screen);
void meta_screen_update_workspace_layout (MetaScreen *screen);
#endif

View File

@ -516,16 +516,90 @@ MetaWorkspace*
meta_workspace_get_neighbor (MetaWorkspace *workspace,
MetaMotionDirection direction)
{
/* FIXME this isn't using any sane layout, just assuming
* the spaces are in a big row
*/
int i, num_workspaces;
int i, num_workspaces, grid_area;
int rows, cols;
i = meta_workspace_index (workspace);
num_workspaces = meta_screen_get_n_workspaces (workspace->screen);
/* Wrap from the last workspace to the first one, and vice-versa */
num_workspaces = g_list_length (workspace->screen->display->workspaces);
/*
* 3 rows, 4 columns, horizontal layout:
* +--+--+--+--+
* | 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|
* +--+--+--+--+
*
*/
rows = workspace->screen->rows_of_workspaces;
cols = workspace->screen->columns_of_workspaces;
if (rows <= 0 && cols <= 0)
cols = num_workspaces;
if (rows <= 0)
rows = num_workspaces / cols + ((num_workspaces % cols) > 0 ? 1 : 0);
if (cols <= 0)
cols = num_workspaces / rows + ((num_workspaces % rows) > 0 ? 1 : 0);
/* paranoia */
if (rows < 1)
rows = 1;
if (cols < 1)
cols = 1;
grid_area = rows * cols;
meta_verbose ("Getting neighbor rows = %d cols = %d vert = %d "
"current = %d num_spaces = %d neighbor = %d\n",
rows, cols, workspace->screen->vertical_workspaces,
i, num_workspaces, direction);
if (workspace->screen->vertical_workspaces)
{
switch (direction)
{
case META_MOTION_LEFT:
if (i < rows)
{
i = grid_area - (i % rows) - 1;
while (i >= num_workspaces)
i -= rows;
}
else
i -= rows;
break;
case META_MOTION_RIGHT:
if ((i + rows) >= num_workspaces)
i = i + rows - num_workspaces;
else
i += rows;
break;
case META_MOTION_UP:
--i;
if (i == -1)
i = num_workspaces - 1;
break;
case META_MOTION_DOWN:
++i;
if (i == num_workspaces)
i = 0;
break;
}
}
else
{
switch (direction)
{
case META_MOTION_LEFT:
@ -539,9 +613,25 @@ meta_workspace_get_neighbor (MetaWorkspace *workspace,
i = 0;
break;
case META_MOTION_UP:
case META_MOTION_DOWN:
return NULL;
if (i < cols)
{
i = grid_area - (i % cols) - 1;
while (i >= num_workspaces)
i -= cols;
}
else
i -= cols;
break;
case META_MOTION_DOWN:
if ((i + cols) >= num_workspaces)
i = i + cols - num_workspaces;
else
i += cols;
break;
}
}
meta_verbose ("Neighbor space is %d\n", i);
return meta_display_get_workspace_by_index (workspace->screen->display,
i);