From 5f65ca07d73352836f89ab96cf0410fd36b59a65 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Thu, 16 May 2002 04:03:36 +0000 Subject: [PATCH] use the layout information to figure out up/down neighbors 2002-05-15 Havoc Pennington * 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 --- ChangeLog | 11 ++++ src/display.c | 18 ++++++- src/display.h | 1 + src/screen.c | 79 ++++++++++++++++++++++++++++- src/screen.h | 6 +++ src/workspace.c | 130 ++++++++++++++++++++++++++++++++++++++++-------- 6 files changed, 223 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index f90a4a15d..c8d0af01c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2002-05-15 Havoc Pennington + + * 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 * src/themes/Esco/metacity-theme-1.xml: Minor tweak to minimize diff --git a/src/display.c b/src/display.c index 81ced59b4..a2f18e378 100644 --- a/src/display.c +++ b/src/display.c @@ -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; diff --git a/src/display.h b/src/display.h index 92b2a0259..54a1fe130 100644 --- a/src/display.h +++ b/src/display.h @@ -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 diff --git a/src/screen.c b/src/screen.c index c765eda4c..7505ab29a 100644 --- a/src/screen.c +++ b/src/screen.c @@ -29,6 +29,7 @@ #include "workspace.h" #include "keybindings.h" #include "stack.h" +#include "xprops.h" #ifdef HAVE_XINERAMA #include @@ -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, @@ -226,6 +228,10 @@ meta_screen_new (MetaDisplay *display, screen->default_depth = DefaultDepthOfScreen (screen->xscreen); 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; @@ -320,6 +326,8 @@ meta_screen_new (MetaDisplay *display, set_supported_hint (screen); 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); +} diff --git a/src/screen.h b/src/screen.h index bc85d873f..ca84cf896 100644 --- a/src/screen.h +++ b/src/screen.h @@ -64,6 +64,10 @@ struct _MetaScreen int n_xinerama_infos; 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 diff --git a/src/workspace.c b/src/workspace.c index ca43b0e8c..be441ad9a 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -516,33 +516,123 @@ 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); + + /* + * 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; - /* Wrap from the last workspace to the first one, and vice-versa */ - num_workspaces = g_list_length (workspace->screen->display->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); - switch (direction) + /* 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) { - case META_MOTION_LEFT: - --i; - if (i == -1) - i = num_workspaces - 1; - break; - case META_MOTION_RIGHT: - ++i; - if (i == num_workspaces) - i = 0; - break; - case META_MOTION_UP: - case META_MOTION_DOWN: - return NULL; + 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: + --i; + if (i == -1) + i = num_workspaces - 1; + break; + case META_MOTION_RIGHT: + ++i; + if (i == num_workspaces) + i = 0; + break; + case META_MOTION_UP: + 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); }