From 971f3f120763003f060bcbf88f872632a0edb1cd Mon Sep 17 00:00:00 2001 From: Rob Adams Date: Thu, 26 Jun 2003 03:09:38 +0000 Subject: [PATCH] Update constraints code to support the new _NET_WM_STRUT_PARTIAL EWMH 2003-06-10 Rob Adams Update constraints code to support the new _NET_WM_STRUT_PARTIAL EWMH draft specification. See #86682. Also, fix a bug involving work area invalidation on metacity startup. Fix for #108497. Finally, some minor fixes for full screen windows. * src/window.h: Add new MetaStruts structure to store strut rects for a window. Remove has_struts and do_not_cover flag, and support new MetaStruts instead of the four ints. * src/window.c (meta_window_new): change initialization to work with new struts. Also, move meta_window_update_struts call to after the workspaces are initialized to fix #108497. Remove do_not_cover and related code. (process_property_notify): add strut_partial (update_struts): change function name to meta_window_update_struts and expose in external MetaWindow API. Support partial width struts and the new strut rects. * src/workspace.h: add new GSLists containing pointers to all relevant struts for this workspace. * src/workspace.c (meta_workspace_new): initialize the list of strut rects for this workspace. (meta_workspace_free): free the strut rect lists (ensure_work_areas_validated): support new struts and new strut rect lists. Unleash the per-xinerama work areas. * src/constraints.c (get_outermost_onscreen_positions): Use the current window position along with the new per-workspace strut rects to compute the constraints that apply to a particular window. (constraint_hint_applies_func): don't do hints constraints on fullscreen windows (update_position_limits): for maximized windows use the work areas to set the position limits; for other windows rely on the struts constraints to be computed later in get_outermost_onscreen_positions (meta_window_constrain): don't apply aspect ratio hints to full screen windows * src/display.c (meta_display_open): add _NET_WM_STRUT_PARTIAL atom (meta_rectangle_equal): new helper function for MetaRectangles (event_queue_callback): #ifndef out if USE_GDK_DISPLAY not set to avoid compiler warning * src/display.h: add atom_net_wm_strut_partial, and add meta_rectangle_equal. * src/screen.c (meta_screen_rect_intersects_xinerama): change _window_intersects_ to _rect_intersects_ which is more useful now. (meta_screen_resize_func): update struts on windows with struts since struts are relative to the screen size, and this function is called when the screen size updates. * src/screen.h (meta_screen_rect_intersects_xinerama): change _window_intersects_ to _rect_intersects_ which is more useful now. * src/window-props.c (meta_display_init_window_prop_hooks): add hook for strut_partial * src/tools/metacity-window-demo.c: Support partial-width struts on the dock window tests for metacity testing purposes. --- ChangeLog | 65 +++++ src/constraints.c | 419 +++++++++++++++++++++---------- src/display.c | 34 ++- src/display.h | 3 + src/screen.c | 70 +++--- src/screen.h | 6 +- src/tools/metacity-window-demo.c | 38 ++- src/window-props.c | 7 +- src/window.c | 234 +++++++++++------ src/window.h | 24 +- src/workspace.c | 118 ++++++--- src/workspace.h | 5 +- 12 files changed, 718 insertions(+), 305 deletions(-) diff --git a/ChangeLog b/ChangeLog index 121a1635d..79c2675ac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,68 @@ +2003-06-10 Rob Adams + + Update constraints code to support the new _NET_WM_STRUT_PARTIAL + EWMH draft specification. See #86682. Also, fix a bug involving + work area invalidation on metacity startup. Fix for #108497. + Finally, some minor fixes for full screen windows. + + * src/window.h: Add new MetaStruts structure to store strut rects + for a window. Remove has_struts and do_not_cover flag, and + support new MetaStruts instead of the four ints. + + * src/window.c (meta_window_new): change initialization to work + with new struts. Also, move meta_window_update_struts call to + after the workspaces are initialized to fix #108497. Remove + do_not_cover and related code. + (process_property_notify): add strut_partial + (update_struts): change function name to meta_window_update_struts + and expose in external MetaWindow API. Support partial width + struts and the new strut rects. + + * src/workspace.h: add new GSLists containing pointers to all + relevant struts for this workspace. + + * src/workspace.c (meta_workspace_new): initialize the list of + strut rects for this workspace. + (meta_workspace_free): free the strut rect lists + (ensure_work_areas_validated): support new struts and new strut + rect lists. Unleash the per-xinerama work areas. + + * src/constraints.c (get_outermost_onscreen_positions): Use the + current window position along with the new per-workspace strut + rects to compute the constraints that apply to a particular + window. + (constraint_hint_applies_func): don't do hints constraints on + fullscreen windows + (update_position_limits): for maximized windows use the work areas + to set the position limits; for other windows rely on the struts + constraints to be computed later in + get_outermost_onscreen_positions + (meta_window_constrain): don't apply aspect ratio hints to full + screen windows + + * src/display.c (meta_display_open): add _NET_WM_STRUT_PARTIAL atom + (meta_rectangle_equal): new helper function for MetaRectangles + (event_queue_callback): #ifndef out if USE_GDK_DISPLAY not set to + avoid compiler warning + + * src/display.h: add atom_net_wm_strut_partial, and add + meta_rectangle_equal. + + * src/screen.c (meta_screen_rect_intersects_xinerama): change + _window_intersects_ to _rect_intersects_ which is more useful now. + (meta_screen_resize_func): update struts on windows with struts + since struts are relative to the screen size, and this function is + called when the screen size updates. + + * src/screen.h (meta_screen_rect_intersects_xinerama): change + _window_intersects_ to _rect_intersects_ which is more useful now. + + * src/window-props.c (meta_display_init_window_prop_hooks): add + hook for strut_partial + + * src/tools/metacity-window-demo.c: Support partial-width struts + on the dock window tests for metacity testing purposes. + 2003-06-22 Samúel Jón Gunnarsson * configure.in: Added "is" to ALL_LINGUAS diff --git a/src/constraints.c b/src/constraints.c index bc658a24f..abf0b650b 100644 --- a/src/constraints.c +++ b/src/constraints.c @@ -21,6 +21,8 @@ #include #include "constraints.h" +#include "window.h" +#include "workspace.h" #include "place.h" /* The way this code works was suggested by Owen Taylor. @@ -123,7 +125,7 @@ typedef struct * size of the menu control?). */ -#define TITLEBAR_LENGTH_ONSCREEN 36 +#define TITLEBAR_LENGTH_ONSCREEN 75 typedef gboolean (* MetaConstraintAppliesFunc) (MetaWindow *window); @@ -301,7 +303,7 @@ static const Constraint constraint_desktop = { * behavior, but not doing that for now. * * Top resize works the same as left resize. Right/bottom resize don't have a limit - * because the constraint is designed to keep the top right corner of the + * because the constraint is designed to keep the top left corner of the * window or its titlebar on the screen, and right/bottom resize will never move that * area. Center resize is almost like left/top but dx has the opposite sign * and new_width = orig_width + 2dx. @@ -347,31 +349,153 @@ static void get_outermost_onscreen_positions (MetaWindow *window, const ConstraintInfo *info, const MetaRectangle *orig, + int delta_x, + int delta_y, int *leftmost_x, int *rightmost_x, int *topmost_y, int *bottommost_y) { + GList *workspaces; + GList *tmp; + GSList *stmp; + MetaRectangle current; + + /* to handle struts, we get the list of workspaces for the window + * and traverse all the struts in each of the cached strut lists for + * the workspaces. Note that because the workarea has already been + * computed, these strut lists should already be up to date. No + * memory allocation should take place in this function for + * performance. + */ + + current = *orig; + current.x += delta_x; + current.y += delta_y; + + workspaces = meta_window_get_workspaces (window); + tmp = workspaces; + if (leftmost_x) - *leftmost_x = info->nw_x - orig->width + - MIN (TITLEBAR_LENGTH_ONSCREEN, orig->width); - + { + *leftmost_x = info->nw_x; + while (tmp) + { + stmp = ((MetaWorkspace*) tmp->data)->left_struts; + while (stmp) + { + MetaRectangle *rect = (MetaRectangle*) stmp->data; + /* the strut only matters if the title bar is + * overlapping the strut rect. + */ + if (((current.y - info->fgeom.top_height >= rect->y) && + (current.y - info->fgeom.top_height <= rect->y + rect->height)) || + ((current.y >= rect->y) && + (current.y <= rect->y + rect->height))) + { + *leftmost_x = MAX (*leftmost_x, rect->width); + } + + stmp = stmp->next; + } + + tmp = tmp->next; + } + + *leftmost_x = *leftmost_x - current.width + + MIN (TITLEBAR_LENGTH_ONSCREEN, current.width); + } + + tmp = workspaces; if (rightmost_x) - *rightmost_x = info->se_x - MIN (TITLEBAR_LENGTH_ONSCREEN, orig->width); + { + *rightmost_x = info->se_x; + while (tmp) + { + stmp = ((MetaWorkspace*) tmp->data)->right_struts; + while (stmp) + { + MetaRectangle *rect = (MetaRectangle*) stmp->data; + /* the strut only matters if the title bar is + * overlapping the strut rect. + */ + if (((current.y - info->fgeom.top_height >= rect->y) && + (current.y - info->fgeom.top_height <= rect->y + rect->height)) || + ((current.y >= rect->y) && + (current.y <= rect->y + rect->height))) + { + *rightmost_x = MIN (*rightmost_x, rect->x); + } + + stmp = stmp->next; + } + + tmp = tmp->next; + } + + *rightmost_x = *rightmost_x - + MIN (TITLEBAR_LENGTH_ONSCREEN, current.width); + } + tmp = workspaces; if (topmost_y) - *topmost_y = info->nw_y + info->fgeom.top_height; + { + *topmost_y = info->nw_y; + while (tmp) + { + stmp = ((MetaWorkspace*) tmp->data)->top_struts; + while (stmp) + { + MetaRectangle *rect = (MetaRectangle*) stmp->data; + /* here the strut matters if the titlebar is overlapping + * the window horizontally + */ + if ((current.x <= rect->x + rect->width) && + (current.x + current.width >= rect->x)) + { + *topmost_y = MAX (*topmost_y, rect->height); + } + + stmp = stmp->next; + } + + tmp = tmp->next; + } + + *topmost_y = *topmost_y + info->fgeom.top_height; + } + tmp = workspaces; if (bottommost_y) { + *bottommost_y = info->se_y; + while (tmp) + { + stmp = ((MetaWorkspace*) tmp->data)->bottom_struts; + while (stmp) + { + MetaRectangle *rect = (MetaRectangle*) stmp->data; + /* here the strut matters if the titlebar is overlapping + * the window horizontally + */ + if ((current.x <= rect->x + rect->width) && + (current.x + current.width >= rect->x)) + { + *bottommost_y = MIN (*bottommost_y, rect->y); + } + + stmp = stmp->next; + } + + tmp = tmp->next; + } + /* If no frame, keep random TITLEBAR_LENGTH_ONSCREEN pixels on the * screen. */ - if (window->frame) - *bottommost_y = info->se_y; - else - *bottommost_y = info->se_y - - MIN (TITLEBAR_LENGTH_ONSCREEN, orig->height); + if (!window->frame) + *bottommost_y = *bottommost_y - + MIN (TITLEBAR_LENGTH_ONSCREEN, current.height); } } @@ -384,7 +508,7 @@ constraint_onscreen_top_func (MetaWindow *window, int min_dy; int topmost_y; - get_outermost_onscreen_positions (window, info, orig, + get_outermost_onscreen_positions (window, info, orig, 0, *y_delta, NULL, NULL, &topmost_y, NULL); min_dy = topmost_y - orig->y; @@ -402,7 +526,7 @@ constraint_onscreen_bottom_func (MetaWindow *window, int max_dy; int bottommost_y; - get_outermost_onscreen_positions (window, info, orig, + get_outermost_onscreen_positions (window, info, orig, 0, *y_delta, NULL, NULL, NULL, &bottommost_y); max_dy = bottommost_y - orig->y; @@ -420,7 +544,7 @@ constraint_onscreen_vcenter_func (MetaWindow *window, int max_dy; int topmost_y; - get_outermost_onscreen_positions (window, info, orig, + get_outermost_onscreen_positions (window, info, orig, 0, *y_delta, NULL, NULL, &topmost_y, NULL); max_dy = orig->y - topmost_y; @@ -438,7 +562,7 @@ constraint_onscreen_left_func (MetaWindow *window, int min_dx; int leftmost_x; - get_outermost_onscreen_positions (window, info, orig, + get_outermost_onscreen_positions (window, info, orig, *x_delta, 0, &leftmost_x, NULL, NULL, NULL); min_dx = leftmost_x - orig->x; @@ -456,7 +580,7 @@ constraint_onscreen_right_func (MetaWindow *window, int max_dx; int rightmost_x; - get_outermost_onscreen_positions (window, info, orig, + get_outermost_onscreen_positions (window, info, orig, *x_delta, 0, NULL, &rightmost_x, NULL, NULL); max_dx = rightmost_x - orig->x; @@ -474,7 +598,7 @@ constraint_onscreen_hcenter_func (MetaWindow *window, int max_dx; int leftmost_x; - get_outermost_onscreen_positions (window, info, orig, + get_outermost_onscreen_positions (window, info, orig, *x_delta, 0, &leftmost_x, NULL, NULL, NULL); max_dx = orig->x - leftmost_x; @@ -494,7 +618,7 @@ constraint_onscreen_move_func (MetaWindow *window, int max_delta; int leftmost_x, rightmost_x, topmost_y, bottommost_y; - get_outermost_onscreen_positions (window, info, orig, + get_outermost_onscreen_positions (window, info, orig, *x_delta, *y_delta, &leftmost_x, &rightmost_x, &topmost_y, &bottommost_y); @@ -560,7 +684,7 @@ static const Constraint constraint_onscreen = { static gboolean constraint_hints_applies_func (MetaWindow *window) { - return TRUE; + return (!window->fullscreen); } static void @@ -787,25 +911,32 @@ constrain_move (MetaWindow *window, MetaRectangle *new) { const Constraint **cp; + int old_x, old_y; - cp = &all_constraints[0]; - while (*cp) - { - meta_topic (META_DEBUG_GEOMETRY, - "Before: %d %d (Move constraint '%s')\n", - x_delta, y_delta, (*cp)->name); - - if ((* (*cp)->applies_func) (window)) - (* (*cp)->move_func) (window, info, orig, - &x_delta, &y_delta); + do { + old_x = x_delta; + old_y = y_delta; + cp = &all_constraints[0]; - meta_topic (META_DEBUG_GEOMETRY, - "After: %d %d (Move constraint '%s')\n", - x_delta, y_delta, (*cp)->name); + while (*cp) + { + meta_topic (META_DEBUG_GEOMETRY, + "Before: %d %d (Move constraint '%s')\n", + x_delta, y_delta, (*cp)->name); + + if ((* (*cp)->applies_func) (window)) + (* (*cp)->move_func) (window, info, orig, + &x_delta, &y_delta); + + meta_topic (META_DEBUG_GEOMETRY, + "After: %d %d (Move constraint '%s')\n", + x_delta, y_delta, (*cp)->name); - ++cp; - } + ++cp; + } + + } while ((old_x != x_delta) || (old_y != y_delta)); new->x = orig->x + x_delta; new->y = orig->y + y_delta; @@ -1023,12 +1154,24 @@ update_position_limits (MetaWindow *window, int nw_x, nw_y; int se_x, se_y; - nw_x = info->work_area_screen.x; - nw_y = info->work_area_screen.y; + if (window->maximized) + { + nw_x = MIN (info->work_area_xinerama.x, info->work_area_screen.x); + nw_y = MIN (info->work_area_xinerama.y, info->work_area_screen.y); - /* find bottom-right corner of workarea */ - se_x = info->work_area_screen.x + info->work_area_screen.width; - se_y = info->work_area_screen.y + info->work_area_screen.height; + /* find bottom-right corner of workarea */ + se_x = MAX (info->work_area_xinerama.x + info->work_area_xinerama.width, + info->work_area_screen.x + info->work_area_screen.width); + se_y = MAX (info->work_area_xinerama.y + info->work_area_xinerama.height, + info->work_area_screen.y + info->work_area_screen.height); + } + else + { + nw_x = 0; + nw_y = 0; + se_x = window->screen->width; + se_y = window->screen->height; + } /* If we have a micro-screen or huge frames maybe nw/se got * swapped @@ -1078,7 +1221,7 @@ meta_window_constrain (MetaWindow *window, #define OUTER_WIDTH(rect) ((rect).width + info.fgeom.left_width + info.fgeom.right_width) #define OUTER_HEIGHT(rect) ((rect).height + info.fgeom.top_height + info.fgeom.bottom_height) - + meta_topic (META_DEBUG_GEOMETRY, "Constraining %s x_move_delta = %d y_move_delta = %d x_direction = %d y_direction = %d x_delta = %d y_delta = %d orig %d,%d %dx%d\n", window->desc, x_move_delta, y_move_delta, @@ -1252,108 +1395,108 @@ meta_window_constrain (MetaWindow *window, #if 0 /* Now we have to sort out the aspect ratio */ - { - /* - * width - * min_aspect <= -------- <= max_aspect - * height - */ - double min_aspect, max_aspect; - int width, height; + if (!window->fullscreen) + { + /* + * width + * min_aspect <= -------- <= max_aspect + * height + */ + double min_aspect, max_aspect; + int width, height; + + min_aspect = window->size_hints.min_aspect.x / (double) window->size_hints.min_aspect.y; + max_aspect = window->size_hints.max_aspect.x / (double) window->size_hints.max_aspect.y; + + width = current.width; + height = current.height; - min_aspect = window->size_hints.min_aspect.x / (double) window->size_hints.min_aspect.y; - max_aspect = window->size_hints.max_aspect.x / (double) window->size_hints.max_aspect.y; - - width = current.width; - height = current.height; - - /* Use the standard cut-and-pasted-between-every-WM code: */ - if (min_aspect * height > width) - { - int delta; - - delta = FLOOR (height - width / min_aspect, window->size_hints.height_inc); - if (height - delta >= window->size_hints.min_height) - height -= delta; - else - { - delta = FLOOR (height * min_aspect - width, window->size_hints.width_inc); - if (width + delta <= window->size_hints.max_width) - width += delta; - } - } - - if (max_aspect * height < width) - { - int delta; - - delta = FLOOR (width - height * max_aspect, window->size_hints.width_inc); - if (width - delta >= window->size_hints.min_width) - width -= delta; - else - { - delta = FLOOR (width / max_aspect - height, window->size_hints.height_inc); - if (height + delta <= window->size_hints.max_height) - height += delta; - } - } - - /* Convert into terms of the direction of resize and reapply the - * earlier constraints; this means aspect ratio becomes the - * least-important of the constraints. If we wanted aspect to be - * the most important, we could just not do this next bit. - */ - - if (current.width != width) - { - x_delta = width - current.width; /* positive delta to increase width */ - switch (x_direction) - { - case META_RESIZE_LEFT_OR_TOP: - constrain_resize_left (window, &info, ¤t, - - x_delta, new); - break; - case META_RESIZE_CENTER: - constrain_resize_hcenter (window, &info, ¤t, + /* Use the standard cut-and-pasted-between-every-WM code: */ + if (min_aspect * height > width) + { + int delta; + + delta = FLOOR (height - width / min_aspect, window->size_hints.height_inc); + if (height - delta >= window->size_hints.min_height) + height -= delta; + else + { + delta = FLOOR (height * min_aspect - width, window->size_hints.width_inc); + if (width + delta <= window->size_hints.max_width) + width += delta; + } + } + + if (max_aspect * height < width) + { + int delta; + + delta = FLOOR (width - height * max_aspect, window->size_hints.width_inc); + if (width - delta >= window->size_hints.min_width) + width -= delta; + else + { + delta = FLOOR (width / max_aspect - height, window->size_hints.height_inc); + if (height + delta <= window->size_hints.max_height) + height += delta; + } + } + + /* Convert into terms of the direction of resize and reapply the + * earlier constraints; this means aspect ratio becomes the + * least-important of the constraints. If we wanted aspect to be + * the most important, we could just not do this next bit. + */ + + if (current.width != width) + { + x_delta = width - current.width; /* positive delta to increase width */ + switch (x_direction) + { + case META_RESIZE_LEFT_OR_TOP: + constrain_resize_left (window, &info, ¤t, + - x_delta, new); + break; + case META_RESIZE_CENTER: + constrain_resize_hcenter (window, &info, ¤t, + x_delta, new); + break; + case META_RESIZE_RIGHT_OR_BOTTOM: + constrain_resize_right (window, &info, ¤t, x_delta, new); - break; - case META_RESIZE_RIGHT_OR_BOTTOM: - constrain_resize_right (window, &info, ¤t, - x_delta, new); - break; - } - } + break; + } + } + + if (current.height != height) + { + y_delta = height - current.height; /* positive to increase height */ + + switch (y_direction) + { + case META_RESIZE_LEFT_OR_TOP: + constrain_resize_top (window, &info, ¤t, + - y_delta, new); + break; + case META_RESIZE_CENTER: + constrain_resize_vcenter (window, &info, ¤t, + y_delta, new); + break; + case META_RESIZE_RIGHT_OR_BOTTOM: + constrain_resize_bottom (window, &info, ¤t, + y_delta, new); + break; + } + } + + current = *new; - if (current.height != height) - { - y_delta = height - current.height; /* positive to increase height */ + g_print ("3 x_delta = %d y_delta = %d pos = %d,%d size = %dx%d\n", + x_delta, y_delta, + current.x, current.y, current.width, current.height); + } - switch (y_direction) - { - case META_RESIZE_LEFT_OR_TOP: - constrain_resize_top (window, &info, ¤t, - - y_delta, new); - break; - case META_RESIZE_CENTER: - constrain_resize_vcenter (window, &info, ¤t, - y_delta, new); - break; - case META_RESIZE_RIGHT_OR_BOTTOM: - constrain_resize_bottom (window, &info, ¤t, - y_delta, new); - break; - } - } - - current = *new; - } - - - g_print ("3 x_delta = %d y_delta = %d pos = %d,%d size = %dx%d\n", - x_delta, y_delta, - current.x, current.y, current.width, current.height); #endif - meta_topic (META_DEBUG_GEOMETRY, "Constrained %s new %d,%d %dx%d old %d,%d %dx%d\n", window->desc, diff --git a/src/display.c b/src/display.c index 6be44d4ae..2856dbc76 100644 --- a/src/display.c +++ b/src/display.c @@ -77,6 +77,11 @@ static GSList *all_displays = NULL; static void meta_spew_event (MetaDisplay *display, XEvent *event); +#ifndef USE_GDK_DISPLAY +static void event_queue_callback (XEvent *event, + gpointer data); +#endif + static gboolean event_callback (XEvent *event, gpointer data); static Window event_get_modified_window (MetaDisplay *display, @@ -263,7 +268,8 @@ meta_display_open (const char *name) "_GNOME_PANEL_ACTION", "_GNOME_PANEL_ACTION_MAIN_MENU", "_GNOME_PANEL_ACTION_RUN_DIALOG", - "_METACITY_SENTINEL" + "_METACITY_SENTINEL", + "_NET_WM_STRUT_PARTIAL" }; Atom atoms[G_N_ELEMENTS(atom_names)]; @@ -406,6 +412,7 @@ meta_display_open (const char *name) display->atom_gnome_panel_action_main_menu = atoms[77]; display->atom_gnome_panel_action_run_dialog = atoms[78]; display->atom_metacity_sentinel = atoms[79]; + display->atom_net_wm_strut_partial = atoms[80]; display->prop_hooks = NULL; meta_display_init_window_prop_hooks (display); @@ -875,6 +882,15 @@ meta_display_is_double_click (MetaDisplay *display) static gboolean dump_events = TRUE; +#ifndef USE_GDK_DISPLAY +static void +event_queue_callback (XEvent *event, + gpointer data) +{ + event_callback (event, data); +} +#endif + static gboolean grab_op_is_mouse (MetaGrabOp op) { @@ -1252,6 +1268,7 @@ event_callback (XEvent *event, if (window->frame) { window->frame->need_reapply_frame_shape = TRUE; + meta_warning("from event callback\n"); meta_window_queue_move_resize (window); } } @@ -3202,6 +3219,7 @@ meta_display_queue_retheme_all_windows (MetaDisplay *display) { MetaWindow *window = tmp->data; + meta_warning("from retheme\n"); meta_window_queue_move_resize (window); if (window->frame) { @@ -3324,8 +3342,8 @@ meta_display_ping_window (MetaDisplay *display, "Sending ping with timestamp %lu to window %s\n", timestamp, window->desc); meta_window_send_icccm_message (window, - display->atom_net_wm_ping, - timestamp); + display->atom_net_wm_ping, + timestamp); } /* process the pong from our ping */ @@ -3676,6 +3694,16 @@ meta_rectangle_intersect (MetaRectangle *src1, return return_val; } +gboolean +meta_rectangle_equal (const MetaRectangle *src1, + const MetaRectangle *src2) +{ + return ((src1->x == src2->x) && + (src1->y == src2->y) && + (src1->width == src2->width) && + (src1->height == src2->height)); +} + static MetaScreen* find_screen_for_selection (MetaDisplay *display, Window owner, diff --git a/src/display.h b/src/display.h index 6265a914e..4c8800250 100644 --- a/src/display.h +++ b/src/display.h @@ -168,6 +168,7 @@ struct _MetaDisplay Atom atom_gnome_panel_action_main_menu; Atom atom_gnome_panel_action_run_dialog; Atom atom_metacity_sentinel; + Atom atom_net_wm_strut_partial; /* This is the actual window from focus events, * not the one we last set @@ -433,6 +434,8 @@ gboolean meta_grab_op_is_resizing (MetaGrabOp op); gboolean meta_rectangle_intersect (MetaRectangle *src1, MetaRectangle *src2, MetaRectangle *dest); +gboolean meta_rectangle_equal (const MetaRectangle *src1, + const MetaRectangle *src2); void meta_display_devirtualize_modifiers (MetaDisplay *display, MetaVirtualModifier modifiers, diff --git a/src/screen.c b/src/screen.c index 1ba0da7e1..15f60f07b 100644 --- a/src/screen.c +++ b/src/screen.c @@ -81,8 +81,7 @@ set_wm_check_hint (MetaScreen *screen) static int set_supported_hint (MetaScreen *screen) { -#define N_SUPPORTED 45 -#define N_WIN_SUPPORTED 1 +#define N_SUPPORTED 49 Atom atoms[N_SUPPORTED]; atoms[0] = screen->display->atom_net_wm_name; @@ -106,30 +105,34 @@ set_supported_hint (MetaScreen *screen) atoms[18] = screen->display->atom_net_client_list_stacking; atoms[19] = screen->display->atom_net_wm_state_skip_taskbar; atoms[20] = screen->display->atom_net_wm_state_skip_pager; - atoms[21] = screen->display->atom_net_wm_icon; - atoms[22] = screen->display->atom_net_wm_moveresize; - atoms[23] = screen->display->atom_net_wm_state_hidden; - atoms[24] = screen->display->atom_net_wm_window_type_utility; - atoms[25] = screen->display->atom_net_wm_window_type_splash; - atoms[26] = screen->display->atom_net_wm_state_fullscreen; - atoms[27] = screen->display->atom_net_wm_ping; - atoms[28] = screen->display->atom_net_active_window; - atoms[29] = screen->display->atom_net_workarea; - atoms[30] = screen->display->atom_net_showing_desktop; - atoms[31] = screen->display->atom_net_desktop_layout; - atoms[32] = screen->display->atom_net_desktop_names; - atoms[33] = screen->display->atom_net_wm_allowed_actions; - atoms[34] = screen->display->atom_net_wm_action_move; - atoms[35] = screen->display->atom_net_wm_action_resize; - atoms[36] = screen->display->atom_net_wm_action_shade; - atoms[37] = screen->display->atom_net_wm_action_stick; - atoms[38] = screen->display->atom_net_wm_action_maximize_horz; - atoms[39] = screen->display->atom_net_wm_action_maximize_vert; - atoms[40] = screen->display->atom_net_wm_action_change_desktop; - atoms[41] = screen->display->atom_net_wm_action_close; - atoms[42] = screen->display->atom_net_wm_state_above; - atoms[43] = screen->display->atom_net_wm_state_below; - atoms[44] = screen->display->atom_net_startup_id; + atoms[21] = screen->display->atom_net_wm_icon_name; + atoms[22] = screen->display->atom_net_wm_icon; + atoms[23] = screen->display->atom_net_wm_icon_geometry; + atoms[24] = screen->display->atom_net_wm_moveresize; + atoms[25] = screen->display->atom_net_active_window; + atoms[26] = screen->display->atom_net_wm_strut; + atoms[27] = screen->display->atom_net_wm_state_hidden; + atoms[28] = screen->display->atom_net_wm_window_type_utility; + atoms[29] = screen->display->atom_net_wm_window_type_splash; + atoms[30] = screen->display->atom_net_wm_state_fullscreen; + atoms[31] = screen->display->atom_net_wm_ping; + atoms[32] = screen->display->atom_net_wm_pid; + atoms[33] = screen->display->atom_net_workarea; + atoms[34] = screen->display->atom_net_showing_desktop; + atoms[35] = screen->display->atom_net_desktop_layout; + atoms[36] = screen->display->atom_net_desktop_names; + atoms[37] = screen->display->atom_net_wm_allowed_actions; + atoms[38] = screen->display->atom_net_wm_action_move; + atoms[39] = screen->display->atom_net_wm_action_resize; + atoms[40] = screen->display->atom_net_wm_action_shade; + atoms[41] = screen->display->atom_net_wm_action_stick; + atoms[42] = screen->display->atom_net_wm_action_maximize_horz; + atoms[43] = screen->display->atom_net_wm_action_maximize_vert; + atoms[44] = screen->display->atom_net_wm_action_change_desktop; + atoms[45] = screen->display->atom_net_wm_action_close; + atoms[46] = screen->display->atom_net_wm_state_above; + atoms[47] = screen->display->atom_net_wm_state_below; + atoms[48] = screen->display->atom_net_startup_id; XChangeProperty (screen->display->xdisplay, screen->xroot, screen->display->atom_net_supported, @@ -1461,21 +1464,18 @@ meta_screen_get_natural_xinerama_list (MetaScreen *screen, } gboolean -meta_screen_window_intersects_xinerama (MetaScreen *screen, - MetaWindow *window, - int which_xinerama) +meta_screen_rect_intersects_xinerama (MetaScreen *screen, + MetaRectangle *rect, + int which_xinerama) { - MetaRectangle window_rect; MetaRectangle dest, screen_rect; - meta_window_get_outer_rect (window, &window_rect); - screen_rect.x = screen->xinerama_infos[which_xinerama].x_origin; screen_rect.y = screen->xinerama_infos[which_xinerama].y_origin; screen_rect.width = screen->xinerama_infos[which_xinerama].width; screen_rect.height = screen->xinerama_infos[which_xinerama].height; - if (meta_rectangle_intersect (&screen_rect, &window_rect, &dest)) + if (meta_rectangle_intersect (&screen_rect, rect, &dest)) return TRUE; return FALSE; @@ -2105,6 +2105,10 @@ meta_screen_resize_func (MetaScreen *screen, MetaWindow *window, void *user_data) { + if (window->struts) + { + meta_window_update_struts (window); + } meta_window_queue_move_resize (window); } diff --git a/src/screen.h b/src/screen.h index 30d24538e..677f7faa9 100644 --- a/src/screen.h +++ b/src/screen.h @@ -148,9 +148,9 @@ const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_rect (MetaScreen const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_window (MetaScreen *screen, MetaWindow *window); -gboolean meta_screen_window_intersects_xinerama (MetaScreen *screen, - MetaWindow *window, - int which_xinerama); +gboolean meta_screen_rect_intersects_xinerama (MetaScreen *screen, + MetaRectangle *window, + int which_xinerama); const MetaXineramaScreenInfo* meta_screen_get_xinerama_neighbor (MetaScreen *screen, int which_xinerama, diff --git a/src/tools/metacity-window-demo.c b/src/tools/metacity-window-demo.c index 215ab6d00..718f1f0a6 100644 --- a/src/tools/metacity-window-demo.c +++ b/src/tools/metacity-window-demo.c @@ -33,19 +33,27 @@ set_gdk_window_struts (GdkWindow *window, int top, int bottom) { - long vals[4]; + long vals[12]; vals[0] = left; vals[1] = right; vals[2] = top; vals[3] = bottom; - + vals[4] = 000; + vals[5] = 400; + vals[6] = 200; + vals[7] = 600; + vals[8] = 76; + vals[9] = 676; + vals[10] = 200; + vals[11] = 800; + XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XWINDOW (window), XInternAtom (GDK_WINDOW_XDISPLAY (window), - "_NET_WM_STRUT", False), + "_NET_WM_STRUT_PARTIAL", False), XA_CARDINAL, 32, PropModeReplace, - (guchar *)vals, 4); + (guchar *)vals, 12); } static void @@ -441,6 +449,7 @@ border_only_cb (gpointer callback_data, gtk_widget_show_all (window); } +#if 0 static void changing_icon_cb (gpointer callback_data, guint callback_action, @@ -462,6 +471,7 @@ changing_icon_cb (gpointer callback_data, gtk_widget_show_all (window); } +#endif static gboolean focus_in_event_cb (GtkWidget *window, @@ -473,6 +483,8 @@ focus_in_event_cb (GtkWidget *window, widget = GTK_WIDGET (data); gtk_label_set_text (GTK_LABEL (widget), "Has focus"); + + return TRUE; } @@ -486,6 +498,8 @@ focus_out_event_cb (GtkWidget *window, widget = GTK_WIDGET (data); gtk_label_set_text (GTK_LABEL (widget), "Not focused"); + + return TRUE; } static GtkWidget* @@ -583,26 +597,26 @@ make_dock (int type) switch (type) { case DOCK_LEFT: - gtk_widget_set_size_request (window, DOCK_SIZE, gdk_screen_height ()); - gtk_window_move (GTK_WINDOW (window), 0, 0); + gtk_widget_set_size_request (window, DOCK_SIZE, 400); + gtk_window_move (GTK_WINDOW (window), 0, 000); set_gtk_window_struts (window, DOCK_SIZE, 0, 0, 0); gtk_window_set_title (GTK_WINDOW (window), "LeftDock"); break; case DOCK_RIGHT: - gtk_widget_set_size_request (window, DOCK_SIZE, gdk_screen_height ()); - gtk_window_move (GTK_WINDOW (window), gdk_screen_width () - DOCK_SIZE, 0); + gtk_widget_set_size_request (window, DOCK_SIZE, 400); + gtk_window_move (GTK_WINDOW (window), gdk_screen_width () - DOCK_SIZE, 200); set_gtk_window_struts (window, 0, DOCK_SIZE, 0, 0); gtk_window_set_title (GTK_WINDOW (window), "RightDock"); break; case DOCK_TOP: - gtk_widget_set_size_request (window, gdk_screen_width (), DOCK_SIZE); - gtk_window_move (GTK_WINDOW (window), 0, 0); + gtk_widget_set_size_request (window, 600, DOCK_SIZE); + gtk_window_move (GTK_WINDOW (window), 76, 0); set_gtk_window_struts (window, 0, 0, DOCK_SIZE, 0); gtk_window_set_title (GTK_WINDOW (window), "TopDock"); break; case DOCK_BOTTOM: - gtk_widget_set_size_request (window, gdk_screen_width (), DOCK_SIZE); - gtk_window_move (GTK_WINDOW (window), 0, gdk_screen_height () - DOCK_SIZE); + gtk_widget_set_size_request (window, 600, DOCK_SIZE); + gtk_window_move (GTK_WINDOW (window), 200, gdk_screen_height () - DOCK_SIZE); set_gtk_window_struts (window, 0, 0, 0, DOCK_SIZE); gtk_window_set_title (GTK_WINDOW (window), "BottomDock"); break; diff --git a/src/window-props.c b/src/window-props.c index a8e7589a4..3dae259a6 100644 --- a/src/window-props.c +++ b/src/window-props.c @@ -814,7 +814,7 @@ reload_wm_hints (MetaWindow *window, -#define N_HOOKS 22 +#define N_HOOKS 23 void meta_display_init_window_prop_hooks (MetaDisplay *display) @@ -914,6 +914,11 @@ meta_display_init_window_prop_hooks (MetaDisplay *display) hooks[i].reload_func = NULL; ++i; + hooks[i].property = display->atom_net_wm_strut_partial; + hooks[i].init_func = NULL; + hooks[i].reload_func = NULL; + ++i; + hooks[i].property = display->atom_net_startup_id; hooks[i].init_func = init_net_startup_id; hooks[i].reload_func = reload_net_startup_id; diff --git a/src/window.c b/src/window.c index 035fad0ad..fe5db8f29 100644 --- a/src/window.c +++ b/src/window.c @@ -64,7 +64,6 @@ static void update_transient_for (MetaWindow *window); static void update_sm_hints (MetaWindow *window); static void update_role (MetaWindow *window); static void update_net_wm_type (MetaWindow *window); -static void update_struts (MetaWindow *window); static void recalc_window_type (MetaWindow *window); static void recalc_window_features (MetaWindow *window); static void invalidate_work_areas (MetaWindow *window); @@ -77,8 +76,6 @@ static gboolean process_property_notify (MetaWindow *window, static void meta_window_show (MetaWindow *window); static void meta_window_hide (MetaWindow *window); -static GList* meta_window_get_workspaces (MetaWindow *window); - static void meta_window_save_rect (MetaWindow *window); static void meta_window_move_resize_internal (MetaWindow *window, @@ -479,11 +476,7 @@ meta_window_new (MetaDisplay *display, window->type = META_WINDOW_NORMAL; window->type_atom = None; - window->has_struts = FALSE; - window->left_strut = 0; - window->right_strut = 0; - window->top_strut = 0; - window->bottom_strut = 0; + window->struts = NULL; window->using_net_wm_name = FALSE; window->using_net_wm_icon_name = FALSE; @@ -516,8 +509,6 @@ meta_window_new (MetaDisplay *display, g_assert (N_INITIAL_PROPS == i); meta_window_reload_properties (window, initial_props, N_INITIAL_PROPS); - - update_struts (window); update_net_wm_state (window); @@ -651,6 +642,8 @@ meta_window_new (MetaDisplay *display, /* for the various on_all_workspaces = TRUE possible above */ meta_window_set_current_workspace_hint (window); + + meta_window_update_struts (window); /* Put our state back where it should be, * passing TRUE for is_configure_request, ICCCM says @@ -907,8 +900,11 @@ meta_window_free (MetaWindow *window) window->desc); } - if (window->has_struts) + if (window->struts) { + g_free (window->struts); + window->struts = NULL; + meta_topic (META_DEBUG_WORKAREA, "Unmanaging window %s which has struts, so invalidating work areas\n", window->desc); @@ -1679,7 +1675,7 @@ meta_window_show (MetaWindow *window) { set_net_wm_state (window); - if (window->has_struts) + if (window->struts) { meta_topic (META_DEBUG_WORKAREA, "Mapped window %s with struts, so invalidating work areas\n", @@ -1732,7 +1728,7 @@ meta_window_hide (MetaWindow *window) { set_net_wm_state (window); - if (window->has_struts) + if (window->struts) { meta_topic (META_DEBUG_WORKAREA, "Unmapped window %s with struts, so invalidating work areas\n", @@ -2307,7 +2303,7 @@ meta_window_move_resize_internal (MetaWindow *window, meta_y_direction_from_gravity (resize_gravity), y_delta, &new_rect); - + w = new_rect.width; h = new_rect.height; root_x_nw = new_rect.x; @@ -4118,10 +4114,11 @@ process_property_notify (MetaWindow *window, event->atom); meta_window_queue_update_icon (window); } - else if (event->atom == window->display->atom_net_wm_strut) + else if ((event->atom == window->display->atom_net_wm_strut) || + (event->atom == window->display->atom_net_wm_strut_partial)) { meta_verbose ("Property notify on %s for _NET_WM_STRUT\n", window->desc); - update_struts (window); + meta_window_update_struts (window); } else if (event->atom == window->display->atom_net_startup_id) { @@ -4788,7 +4785,7 @@ meta_window_queue_update_icon (MetaWindow *window) update_icon_pending = g_slist_prepend (update_icon_pending, window); } -static GList* +GList* meta_window_get_workspaces (MetaWindow *window) { if (window->on_all_workspaces) @@ -4811,68 +4808,102 @@ invalidate_work_areas (MetaWindow *window) } } -static void -update_struts (MetaWindow *window) +void +meta_window_update_struts (MetaWindow *window) { gulong *struts = NULL; int nitems; gboolean old_has_struts; - int old_left; - int old_right; - int old_top; - int old_bottom; + gboolean new_has_struts; + + MetaRectangle old_left; + MetaRectangle old_right; + MetaRectangle old_top; + MetaRectangle old_bottom; + + MetaRectangle new_left; + MetaRectangle new_right; + MetaRectangle new_top; + MetaRectangle new_bottom; meta_verbose ("Updating struts for %s\n", window->desc); - old_has_struts = window->has_struts; - old_left = window->left_strut; - old_right = window->right_strut; - old_top = window->top_strut; - old_bottom = window->bottom_strut; - - window->has_struts = FALSE; - window->left_strut = 0; - window->right_strut = 0; - window->top_strut = 0; - window->bottom_strut = 0; + if (window->struts) + { + old_has_struts = TRUE; + old_left = window->struts->left; + old_right = window->struts->right; + old_top = window->struts->top; + old_bottom = window->struts->bottom; + } + else + { + old_has_struts = FALSE; + } + + new_has_struts = FALSE; + new_left.width = 0; + new_left.x = 0; + new_left.y = 0; + new_left.height = window->screen->height; + + new_right.width = 0; + new_right.x = window->screen->width; + new_right.y = 0; + new_right.height = window->screen->height; + + new_top.height = 0; + new_top.y = 0; + new_top.x = 0; + new_top.width = window->screen->width; + + new_bottom.height = 0; + new_bottom.y = window->screen->height; + new_bottom.x = 0; + new_bottom.width = window->screen->width; if (meta_prop_get_cardinal_list (window->display, window->xwindow, - window->display->atom_net_wm_strut, + window->display->atom_net_wm_strut_partial, &struts, &nitems)) { - if (nitems != 4) + if (nitems != 12) { - meta_verbose ("_NET_WM_STRUT on %s has %d values instead of 4\n", + meta_verbose ("_NET_WM_STRUT_PARTIAL on %s has %d values instead of 12\n", window->desc, nitems); - meta_XFree (struts); } - - window->has_struts = TRUE; - window->left_strut = struts[0]; - window->right_strut = struts[1]; - window->top_strut = struts[2]; - window->bottom_strut = struts[3]; - - meta_verbose ("_NET_WM_STRUT struts %d %d %d %d for window %s\n", - window->left_strut, window->right_strut, - window->top_strut, window->bottom_strut, - window->desc); - - if (window->left_strut < 0) - window->left_strut = 0; - if (window->right_strut < 0) - window->right_strut = 0; - if (window->top_strut < 0) - window->top_strut = 0; - if (window->bottom_strut < 0) - window->bottom_strut = 0; - - meta_verbose ("Using _NET_WM_STRUT struts %d %d %d %d for window %s\n", - window->left_strut, window->right_strut, - window->top_strut, window->bottom_strut, - window->desc); - + else + { + new_has_struts = TRUE; + new_left.width = MIN ((int)struts[0], + window->screen->width/2 - 75); + new_right.width = MIN ((int)struts[1], + window->screen->width/2 - 75); + new_top.height = MIN ((int)struts[2], + window->screen->height/2 - 75); + new_bottom.height = MIN ((int)struts[3], + window->screen->height/2 - 75); + new_right.x = window->screen->width - + new_right.width; + new_bottom.y = window->screen->height - + new_bottom.height; + new_left.y = struts[4]; + new_left.height = struts[5] - new_left.y; + new_right.y = struts[6]; + new_right.height = struts[7] - new_right.y; + new_top.x = struts[8]; + new_top.width = struts[9] - new_top.x; + new_bottom.x = struts[10]; + new_bottom.width = struts[11] - new_bottom.x; + + meta_verbose ("_NET_WM_STRUT_PARTIAL struts %d %d %d %d for window %s\n", + new_left.width, + new_right.width, + new_top.height, + new_bottom.height, + window->desc); + + } meta_XFree (struts); } else @@ -4881,12 +4912,75 @@ update_struts (MetaWindow *window) window->desc); } - if (old_has_struts != window->has_struts || - old_left != window->left_strut || - old_right != window->right_strut || - old_top != window->top_strut || - old_bottom != window->bottom_strut) - { + if (!new_has_struts) + { + if (meta_prop_get_cardinal_list (window->display, + window->xwindow, + window->display->atom_net_wm_strut, + &struts, &nitems)) + { + if (nitems != 4) + { + meta_verbose ("_NET_WM_STRUT on %s has %d values instead of 4\n", + window->desc, nitems); + } + else + { + new_has_struts = TRUE; + new_left.width = MIN ((int)struts[0], + window->screen->width/2 - 75); + new_right.width = MIN ((int)struts[1], + window->screen->width/2 - 75); + new_top.height = MIN ((int)struts[2], + window->screen->height/2 - 75); + new_bottom.height = MIN ((int)struts[3], + window->screen->height/2 - 75); + new_left.x = 0; + new_right.x = window->screen->width - + new_right.width; + new_top.y = 0; + new_bottom.y = window->screen->height - + new_bottom.height; + + meta_verbose ("_NET_WM_STRUT struts %d %d %d %d for window %s\n", + new_left.width, + new_right.width, + new_top.height, + new_bottom.height, + window->desc); + + } + meta_XFree (struts); + } + else + { + meta_verbose ("No _NET_WM_STRUT property for %s\n", + window->desc); + } + } + + if (old_has_struts != new_has_struts || + (new_has_struts && old_has_struts && + (!meta_rectangle_equal(&old_left, &new_left) || + !meta_rectangle_equal(&old_right, &new_right) || + !meta_rectangle_equal(&old_top, &new_top) || + !meta_rectangle_equal(&old_bottom, &new_bottom)))) + { + if (new_has_struts) + { + if (!window->struts) + window->struts = g_new (MetaStruts, 1); + + window->struts->left = new_left; + window->struts->right = new_right; + window->struts->top = new_top; + window->struts->bottom = new_bottom; + } + else + { + g_free (window->struts); + window->struts = NULL; + } meta_topic (META_DEBUG_WORKAREA, "Invalidating work areas of window %s due to struts update\n", window->desc); diff --git a/src/window.h b/src/window.h index 47617779a..bedef1dce 100644 --- a/src/window.h +++ b/src/window.h @@ -32,6 +32,7 @@ #include typedef struct _MetaGroup MetaGroup; +typedef struct _MetaStruts MetaStruts; typedef gboolean (*MetaWindowForeachFunc) (MetaWindow *window, void *data); @@ -49,6 +50,15 @@ typedef enum META_WINDOW_SPLASHSCREEN } MetaWindowType; +struct _MetaStruts +{ + /* struts */ + MetaRectangle left; + MetaRectangle right; + MetaRectangle top; + MetaRectangle bottom; +}; + struct _MetaWindow { MetaDisplay *display; @@ -211,8 +221,8 @@ struct _MetaWindow */ guint calc_placement : 1; - /* Has nonzero struts */ - guint has_struts : 1; + /* Note: can be NULL */ + MetaStruts *struts; /* Transient parent is a root window */ guint transient_parent_is_root_window : 1; @@ -271,12 +281,6 @@ struct _MetaWindow /* x/y/w/h here get filled with ConfigureRequest values */ XSizeHints size_hints; - /* struts */ - int left_strut; - int right_strut; - int top_strut; - int bottom_strut; - /* Managed by stack.c */ MetaStackLayer layer; int stack_position; /* see comment in stack.h */ @@ -355,6 +359,8 @@ void meta_window_fill_vertical (MetaWindow *window); */ void meta_window_queue_move_resize (MetaWindow *window); +void meta_window_update_struts (MetaWindow *window); + /* this gets root coords */ void meta_window_get_position (MetaWindow *window, int *x, @@ -424,6 +430,8 @@ void meta_window_set_gravity (MetaWindow *window, void meta_window_handle_mouse_grab_op_event (MetaWindow *window, XEvent *event); +GList* meta_window_get_workspaces (MetaWindow *window); + gboolean meta_window_visible_on_workspace (MetaWindow *window, MetaWorkspace *workspace); diff --git a/src/workspace.c b/src/workspace.c index 56cbaa624..d84539e25 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -48,6 +48,11 @@ meta_workspace_new (MetaScreen *screen) workspace->all_work_areas.y = 0; workspace->all_work_areas.width = 0; workspace->all_work_areas.height = 0; + + workspace->left_struts = NULL; + workspace->right_struts = NULL; + workspace->top_struts = NULL; + workspace->bottom_struts = NULL; return workspace; } @@ -86,6 +91,12 @@ meta_workspace_free (MetaWorkspace *workspace) g_list_remove (workspace->screen->workspaces, workspace); g_free (workspace->work_areas); + + g_slist_free (workspace->left_struts); + g_slist_free (workspace->right_struts); + g_slist_free (workspace->top_struts); + g_slist_free (workspace->bottom_struts); + g_free (workspace); /* don't bother to reset names, pagers can just ignore @@ -105,7 +116,7 @@ meta_workspace_add_window (MetaWorkspace *workspace, meta_window_set_current_workspace_hint (window); meta_window_queue_calc_showing (window); - if (window->has_struts) + if (window->struts) { meta_topic (META_DEBUG_WORKAREA, "Invalidating work area of workspace %d since we're adding window %s to it\n", @@ -132,7 +143,7 @@ meta_workspace_remove_window (MetaWorkspace *workspace, meta_window_queue_calc_showing (window); - if (window->has_struts) + if (window->struts) { meta_topic (META_DEBUG_WORKAREA, "Invalidating work area of workspace %d since we're removing window %s from it\n", @@ -375,6 +386,15 @@ ensure_work_areas_validated (MetaWorkspace *workspace) if (!workspace->work_areas_invalid) return; + g_slist_free (workspace->left_struts); + workspace->left_struts = NULL; + g_slist_free (workspace->right_struts); + workspace->right_struts = NULL; + g_slist_free (workspace->top_struts); + workspace->top_struts = NULL; + g_slist_free (workspace->bottom_struts); + workspace->bottom_struts = NULL; + windows = meta_workspace_list_windows (workspace); g_free (workspace->work_areas); @@ -394,33 +414,76 @@ ensure_work_areas_validated (MetaWorkspace *workspace) { MetaWindow *w = tmp->data; - if (w->has_struts && - (meta_screen_window_intersects_xinerama (w->screen, w, i))) + if (w->struts) { meta_topic (META_DEBUG_WORKAREA, "Merging win %s with %d %d %d %d " "with %d %d %d %d\n", w->desc, - w->left_strut, w->right_strut, - w->top_strut, w->bottom_strut, + w->struts->left.width, w->struts->right.width, + w->struts->top.height, w->struts->bottom.height, left_strut, right_strut, top_strut, bottom_strut); - left_strut = MAX (left_strut, - w->left_strut - - workspace->screen->xinerama_infos[i].x_origin); - all_left_strut = MAX (all_left_strut, w->left_strut); + if ((i == 0) && (w->struts->left.width > 0)) + { + workspace->left_struts = g_slist_prepend (workspace->left_struts, + &w->struts->left); + } - right_strut = MAX (right_strut, w->right_strut); - all_right_strut = MAX (all_right_strut, w->right_strut); + if (meta_screen_rect_intersects_xinerama (w->screen, + &w->struts->left, + i)) + { + left_strut = MAX (left_strut, + w->struts->left.width - + workspace->screen->xinerama_infos[i].x_origin); + all_left_strut = MAX (all_left_strut, w->struts->left.width); + } - top_strut = MAX (top_strut, - w->top_strut - - workspace->screen->xinerama_infos[i].y_origin); - all_top_strut = MAX (all_top_strut, w->top_strut); + if ((i == 0) && (w->struts->right.width > 0)) + { + workspace->right_struts = g_slist_prepend (workspace->right_struts, + &w->struts->right); + } - bottom_strut = MAX (bottom_strut, w->bottom_strut); - all_bottom_strut = MAX (all_bottom_strut, w->bottom_strut); + if (meta_screen_rect_intersects_xinerama (w->screen, + &w->struts->right, + i)) + { + right_strut = MAX (right_strut, w->struts->right.width); + all_right_strut = MAX (all_right_strut, w->struts->right.width); + } + + if ((i == 0) && (w->struts->top.height > 0)) + { + workspace->top_struts = g_slist_prepend (workspace->top_struts, + &w->struts->top); + } + + if (meta_screen_rect_intersects_xinerama (w->screen, + &w->struts->top, + i)) + { + top_strut = MAX (top_strut, + w->struts->top.height - + workspace->screen->xinerama_infos[i].y_origin); + all_top_strut = MAX (all_top_strut, w->struts->top.height); + } + + if ((i == 0) && (w->struts->bottom.height > 0)) + { + workspace->bottom_struts = g_slist_prepend (workspace->bottom_struts, + &w->struts->bottom); + } + + if (meta_screen_rect_intersects_xinerama (w->screen, + &w->struts->bottom, + i)) + { + bottom_strut = MAX (bottom_strut, w->struts->bottom.height); + all_bottom_strut = MAX (all_bottom_strut, w->struts->bottom.height); + } } tmp = tmp->next; @@ -451,10 +514,6 @@ ensure_work_areas_validated (MetaWorkspace *workspace) bottom_strut = top_strut; } - /* FIXME even if we take struts to apply only to xineramas - * that the strut-specifying window overlaps, is it right - * to make the struts *relative to* the xinerama? - */ workspace->work_areas[i].x = left_strut + workspace->screen->xinerama_infos[i].x_origin; workspace->work_areas[i].y = top_strut + @@ -467,7 +526,7 @@ ensure_work_areas_validated (MetaWorkspace *workspace) top_strut - bottom_strut; meta_topic (META_DEBUG_WORKAREA, - "Computed [unused] work area for workspace %d " + "Computed work area for workspace %d " "xinerama %d: %d,%d %d x %d\n", meta_workspace_index (workspace), i, @@ -507,19 +566,6 @@ ensure_work_areas_validated (MetaWorkspace *workspace) workspace->screen->width - all_left_strut - all_right_strut; workspace->all_work_areas.height = workspace->screen->height - all_top_strut - all_bottom_strut; - - /* FIXME Here we disable all the per-xinerama work done earlier, - * because we don't have a spec for how it should work yet. - * If we do rely on which windows overlap what, work areas - * will need to be invalidated when we change a strut-setting - * window's size/position in move_resize_internal - */ - i = 0; - while (i < workspace->screen->n_xinerama_infos) - { - workspace->work_areas[i] = workspace->all_work_areas; - ++i; - } workspace->work_areas_invalid = FALSE; diff --git a/src/workspace.h b/src/workspace.h index c6edc758d..b89f5673d 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -42,8 +42,11 @@ struct _MetaWorkspace GList *windows; MetaRectangle all_work_areas; - MetaRectangle *work_areas; + GSList *left_struts; + GSList *right_struts; + GSList *top_struts; + GSList *bottom_struts; guint work_areas_invalid : 1; };