From 0498d55314582293a72c7edf8b33b8f362340456 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 29 May 2002 03:11:24 +0000 Subject: [PATCH] Patch from Erwann Chenede for raise_or_lower keybinding 2002-05-28 Havoc Pennington Patch from Erwann Chenede for raise_or_lower keybinding * src/display.c, src/common.h: POINT_IN_RECT moved to a common location, removed from here (meta_rectangle_intersect): move here and make it public * src/prefs.c: add raise_or_lower keybinding * src/stack.c (meta_stack_get_below, meta_stack_get_above): add an arg to only get windows within the same layer * src/keybindings.c (handle_raise_or_lower): add handling for a "raise window if obscured, else lower" keybinding --- ChangeLog | 16 +++++++++++ src/common.h | 6 +++++ src/display.c | 43 +++++++++++++++++++++++++----- src/display.h | 4 +++ src/frames.c | 6 ----- src/keybindings.c | 59 ++++++++++++++++++++++++++++++++++++++--- src/metacity.schemas.in | 28 ++++++++++++++++++- src/prefs.c | 1 + src/prefs.h | 1 + src/screen.c | 37 -------------------------- src/stack.c | 10 +++++-- src/stack.h | 7 +++-- 12 files changed, 161 insertions(+), 57 deletions(-) diff --git a/ChangeLog b/ChangeLog index d64a95f95..bf3082598 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2002-05-28 Havoc Pennington + + Patch from Erwann Chenede for raise_or_lower keybinding + + * src/display.c, src/common.h: POINT_IN_RECT moved to a common + location, removed from here + (meta_rectangle_intersect): move here and make it public + + * src/prefs.c: add raise_or_lower keybinding + + * src/stack.c (meta_stack_get_below, meta_stack_get_above): add an + arg to only get windows within the same layer + + * src/keybindings.c (handle_raise_or_lower): add handling for a + "raise window if obscured, else lower" keybinding + 2002-05-28 Havoc Pennington * src/window.c (meta_window_configure_request): handle CWStackMode diff --git a/src/common.h b/src/common.h index 82985d0d4..4450d7129 100644 --- a/src/common.h +++ b/src/common.h @@ -151,6 +151,12 @@ typedef enum #define META_PRIORITY_PREFS_NOTIFY (G_PRIORITY_DEFAULT_IDLE + 10) #define META_PRIORITY_WORK_AREA_HINT (G_PRIORITY_DEFAULT_IDLE + 15) +#define POINT_IN_RECT(xcoord, ycoord, rect) \ + ((xcoord) >= (rect).x && \ + (xcoord) < ((rect).x + (rect).width) && \ + (ycoord) >= (rect).y && \ + (ycoord) < ((rect).y + (rect).height)) + #endif diff --git a/src/display.c b/src/display.c index a2750a93c..15f0d4189 100644 --- a/src/display.c +++ b/src/display.c @@ -810,12 +810,6 @@ reset_ignores (MetaDisplay *display) display->ungrab_should_not_cause_focus_window = None; } -#define POINT_IN_RECT(xcoord, ycoord, rect) \ - ((xcoord) >= (rect).x && \ - (xcoord) < ((rect).x + (rect).width) && \ - (ycoord) >= (rect).y && \ - (ycoord) < ((rect).y + (rect).height)) - static gboolean window_raise_with_delay_callback (void *data) { @@ -2926,3 +2920,40 @@ meta_resize_gravity_from_grab_op (MetaGrabOp op) return gravity; } +gboolean +meta_rectangle_intersect (MetaRectangle *src1, + MetaRectangle *src2, + MetaRectangle *dest) +{ + int dest_x, dest_y; + int dest_w, dest_h; + int return_val; + + g_return_val_if_fail (src1 != NULL, FALSE); + g_return_val_if_fail (src2 != NULL, FALSE); + g_return_val_if_fail (dest != NULL, FALSE); + + return_val = FALSE; + + dest_x = MAX (src1->x, src2->x); + dest_y = MAX (src1->y, src2->y); + dest_w = MIN (src1->x + src1->width, src2->x + src2->width) - dest_x; + dest_h = MIN (src1->y + src1->height, src2->y + src2->height) - dest_y; + + if (dest_w > 0 && dest_h > 0) + { + dest->x = dest_x; + dest->y = dest_y; + dest->width = dest_w; + dest->height = dest_h; + return_val = TRUE; + } + else + { + dest->width = 0; + dest->height = 0; + } + + return return_val; +} + diff --git a/src/display.h b/src/display.h index 7b6ac68a0..d4214ff31 100644 --- a/src/display.h +++ b/src/display.h @@ -318,4 +318,8 @@ MetaWindow* meta_display_get_tab_next (MetaDisplay *display, int meta_resize_gravity_from_grab_op (MetaGrabOp op); +gboolean meta_rectangle_intersect (MetaRectangle *src1, + MetaRectangle *src2, + MetaRectangle *dest); + #endif diff --git a/src/frames.c b/src/frames.c index d699d81f4..07c5be8d9 100644 --- a/src/frames.c +++ b/src/frames.c @@ -1596,12 +1596,6 @@ control_rect (MetaFrameControl control, return rect; } -#define POINT_IN_RECT(xcoord, ycoord, rect) \ - ((xcoord) >= (rect).x && \ - (xcoord) < ((rect).x + (rect).width) && \ - (ycoord) >= (rect).y && \ - (ycoord) < ((rect).y + (rect).height)) - #define RESIZE_EXTENDS 15 static MetaFrameControl get_control (MetaFrames *frames, diff --git a/src/keybindings.c b/src/keybindings.c index 238a942dd..482ad8830 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -94,7 +94,10 @@ static void handle_move_to_workspace (MetaDisplay *display, MetaWindow *window, XEvent *event, MetaKeyBinding *binding); - +static void handle_raise_or_lower (MetaDisplay *display, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding); /* debug */ static void handle_spew_mark (MetaDisplay *display, @@ -217,6 +220,7 @@ static const MetaKeyHandler window_handlers[] = { GINT_TO_POINTER (META_MOTION_UP) }, { META_KEYBINDING_MOVE_WORKSPACE_DOWN, handle_move_to_workspace, GINT_TO_POINTER (META_MOTION_DOWN) }, + { META_KEYBINDING_RAISE_OR_LOWER, handle_raise_or_lower, NULL}, { NULL, NULL, NULL } }; @@ -1696,6 +1700,57 @@ handle_move_to_workspace (MetaDisplay *display, } } +static void +handle_raise_or_lower (MetaDisplay *display, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding) +{ + /* Get window at pointer */ + + MetaScreen *screen; + + screen = meta_display_screen_for_root (display, event->xbutton.root); + if (screen == NULL) + return; + + if (window) + { + MetaWindow *above = NULL; + + /* Check if top */ + if (meta_stack_get_top (window->screen->stack) == window) + { + meta_window_lower (window); + return; + } + + /* else check if windows in same layer are intersecting it */ + + above = meta_stack_get_above (window->screen->stack, window, TRUE); + + while (above) + { + MetaRectangle tmp, win_rect, above_rect; + + meta_window_get_outer_rect (window, &win_rect); + meta_window_get_outer_rect (above, &above_rect); + + /* Check if obscured */ + if (meta_rectangle_intersect (&win_rect, &above_rect, &tmp)) + { + meta_window_raise (window); + return; + } + + above = meta_stack_get_above (window->screen->stack, above, TRUE); + } + + /* window is not obscured */ + meta_window_lower (window); + } +} + static void handle_spew_mark (MetaDisplay *display, MetaWindow *window, @@ -1720,5 +1775,3 @@ meta_set_keybindings_disabled (gboolean setting) "Ignoring keybindings disable message, not in debug mode\n"); } } - - diff --git a/src/metacity.schemas.in b/src/metacity.schemas.in index 37505da05..f8e203fd6 100644 --- a/src/metacity.schemas.in +++ b/src/metacity.schemas.in @@ -690,6 +690,33 @@ you set + + + /schemas/apps/metacity/window_keybindings/raise_or_lower + /apps/metacity/window_keybindings/raise_or_lower + metacity + string + + + Raise window if obscured, lowers it otherwise + + This keybinding changes whether a window is above or below + other windows. If the window is covered by another window, it raises + the window above other windows. If the window is already fully visible, + it lowers the window below other windows. + + The format looks like "<Control>a" or + "<Shift><Alt>F1. + + The parser is fairly liberal and allows lower or upper case, + and also abbreviations such as "<Ctl>" and + "<Ctrl>". If you set the option to the special string + "disabled", then there will be no keybinding for this + action. + + + + @@ -1179,7 +1206,6 @@ you set - diff --git a/src/prefs.c b/src/prefs.c index 80dc7e8cb..010bf4d5f 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -850,6 +850,7 @@ static MetaKeyPref window_bindings[] = { { META_KEYBINDING_MOVE_WORKSPACE_RIGHT, 0, 0 }, { META_KEYBINDING_MOVE_WORKSPACE_UP, 0, 0 }, { META_KEYBINDING_MOVE_WORKSPACE_DOWN, 0, 0 }, + { META_KEYBINDING_RAISE_OR_LOWER, 0, 0 }, { NULL, 0, 0 } }; diff --git a/src/prefs.h b/src/prefs.h index 975d4b404..5531c1bf0 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -111,6 +111,7 @@ void meta_prefs_set_num_workspaces (int n_workspaces); #define META_KEYBINDING_MOVE_WORKSPACE_RIGHT "move_to_workspace_right" #define META_KEYBINDING_MOVE_WORKSPACE_UP "move_to_workspace_up" #define META_KEYBINDING_MOVE_WORKSPACE_DOWN "move_to_workspace_down" +#define META_KEYBINDING_RAISE_OR_LOWER "raise_or_lower" typedef struct { diff --git a/src/screen.c b/src/screen.c index 22a070eb5..60ad783a9 100644 --- a/src/screen.c +++ b/src/screen.c @@ -800,43 +800,6 @@ meta_screen_focus_top_window (MetaScreen *screen, } } -static gboolean -meta_rectangle_intersect (MetaRectangle *src1, - MetaRectangle *src2, - MetaRectangle *dest) -{ - int dest_x, dest_y; - int dest_w, dest_h; - int return_val; - - g_return_val_if_fail (src1 != NULL, FALSE); - g_return_val_if_fail (src2 != NULL, FALSE); - g_return_val_if_fail (dest != NULL, FALSE); - - return_val = FALSE; - - dest_x = MAX (src1->x, src2->x); - dest_y = MAX (src1->y, src2->y); - dest_w = MIN (src1->x + src1->width, src2->x + src2->width) - dest_x; - dest_h = MIN (src1->y + src1->height, src2->y + src2->height) - dest_y; - - if (dest_w > 0 && dest_h > 0) - { - dest->x = dest_x; - dest->y = dest_y; - dest->width = dest_w; - dest->height = dest_h; - return_val = TRUE; - } - else - { - dest->width = 0; - dest->height = 0; - } - - return return_val; -} - const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_window (MetaScreen *screen, MetaWindow *window) diff --git a/src/stack.c b/src/stack.c index 6222bdd47..b0926e467 100644 --- a/src/stack.c +++ b/src/stack.c @@ -938,7 +938,8 @@ meta_stack_get_bottom (MetaStack *stack) MetaWindow* meta_stack_get_above (MetaStack *stack, - MetaWindow *window) + MetaWindow *window, + gboolean only_within_layer) { GList *link; @@ -951,13 +952,16 @@ meta_stack_get_above (MetaStack *stack, if (link->prev) return link->prev->data; + else if (only_within_layer) + return NULL; else return find_next_above_layer (stack, window->layer); } MetaWindow* meta_stack_get_below (MetaStack *stack, - MetaWindow *window) + MetaWindow *window, + gboolean only_within_layer) { GList *link; @@ -970,6 +974,8 @@ meta_stack_get_below (MetaStack *stack, if (link->next) return link->next->data; + else if (only_within_layer) + return NULL; else return find_prev_below_layer (stack, window->layer); } diff --git a/src/stack.h b/src/stack.h index cc2c9d738..7a401db38 100644 --- a/src/stack.h +++ b/src/stack.h @@ -93,12 +93,15 @@ void meta_stack_thaw (MetaStack *stack); MetaWindow* meta_stack_get_top (MetaStack *stack); MetaWindow* meta_stack_get_bottom (MetaStack *stack); MetaWindow* meta_stack_get_above (MetaStack *stack, - MetaWindow *window); + MetaWindow *window, + gboolean only_within_layer); MetaWindow* meta_stack_get_below (MetaStack *stack, - MetaWindow *window); + MetaWindow *window, + gboolean only_within_layer); MetaWindow* meta_stack_get_default_focus_window (MetaStack *stack, MetaWorkspace *workspace, MetaWindow *not_this_one); + /* -1 if a < b, etc. */ int meta_stack_windows_cmp (MetaStack *stack,