diff --git a/ChangeLog b/ChangeLog index 5685337c5..356cf16ca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,12 @@ -2006-10-16 Elijah Newren +2006-11-05 Justin Mason + + * src/keybindings.c: implement handle_move_to_{side|corner}_* to + allow the user to flip a window to the side or corner of the + screen. Fixes #317884. + * src/prefs.h: keybindings for the above. + * src/metacity.schemas.in: keybindings for the above. + +2006-11-05 Elijah Newren * src/frames.c: improved rounding of rounded corners. Fixes #360542, mostly. diff --git a/src/keybindings.c b/src/keybindings.c index 22547a0c1..8b32eecbb 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -191,6 +191,46 @@ static void handle_maximize_horiz (MetaDisplay *display, MetaWindow *window, XEvent *event, MetaKeyBinding *binding); +static void handle_move_to_side_n (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding); +static void handle_move_to_side_w (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding); +static void handle_move_to_side_s (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding); +static void handle_move_to_side_e (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding); +static void handle_move_to_corner_nw (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding); +static void handle_move_to_corner_ne (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding); +static void handle_move_to_corner_sw (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding); +static void handle_move_to_corner_se (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding); static void handle_run_terminal (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, @@ -432,6 +472,14 @@ static const MetaKeyHandler window_handlers[] = { { META_KEYBINDING_LOWER, handle_lower, NULL}, { META_KEYBINDING_MAXIMIZE_VERTICALLY, handle_maximize_vert, NULL }, { META_KEYBINDING_MAXIMIZE_HORIZONTALLY, handle_maximize_horiz, NULL }, + { META_KEYBINDING_MOVE_TO_SIDE_N, handle_move_to_side_n, NULL }, + { META_KEYBINDING_MOVE_TO_SIDE_S, handle_move_to_side_s, NULL }, + { META_KEYBINDING_MOVE_TO_SIDE_E, handle_move_to_side_e, NULL }, + { META_KEYBINDING_MOVE_TO_SIDE_W, handle_move_to_side_w, NULL }, + { META_KEYBINDING_MOVE_TO_CORNER_NW, handle_move_to_corner_nw, NULL }, + { META_KEYBINDING_MOVE_TO_CORNER_NE, handle_move_to_corner_ne, NULL }, + { META_KEYBINDING_MOVE_TO_CORNER_SW, handle_move_to_corner_sw, NULL }, + { META_KEYBINDING_MOVE_TO_CORNER_SE, handle_move_to_corner_se, NULL }, { NULL, NULL, NULL } }; @@ -2817,6 +2865,162 @@ handle_maximize_horiz (MetaDisplay *display, } } +/* Move a window to a corner; to_bottom/to_right are FALSE for the + * top or left edge, or TRUE for the bottom/right edge. xchange/ychange + * are FALSE if that dimension is not to be changed, TRUE otherwise. + * Together they describe which of the four corners, or four sides, + * is desired. + */ +static void +handle_move_to_corner_backend (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + gboolean xchange, + gboolean ychange, + gboolean to_right, + gboolean to_bottom) +{ + MetaRectangle work_area; + MetaRectangle outer; + int orig_x, orig_y; + int new_x, new_y; + int frame_width, frame_height; + + meta_window_get_work_area_all_xineramas (window, &work_area); + meta_window_get_outer_rect (window, &outer); + meta_window_get_position (window, &orig_x, &orig_y); + + frame_width = (window->frame ? window->frame->child_x : 0); + frame_height = (window->frame ? window->frame->child_y : 0); + + if (xchange) { + new_x = work_area.x + (to_right ? + (work_area.width + frame_width) - outer.width : + 0); + } else { + new_x = orig_x; + } + + if (ychange) { + new_y = work_area.y + (to_bottom ? + (work_area.height + frame_height) - outer.height : + 0); + } else { + new_y = orig_y; + } + + meta_window_move_resize (window, + FALSE, + new_x, + new_y, + window->rect.width, + window->rect.height); +} + +static void +handle_move_to_corner_nw (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding) +{ + if (window) + { + handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, FALSE, FALSE); + } +} + +static void +handle_move_to_corner_ne (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding) +{ + if (window) + { + handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, TRUE, FALSE); + } +} + +static void +handle_move_to_corner_sw (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding) +{ + if (window) + { + handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, FALSE, TRUE); + } +} + +static void +handle_move_to_corner_se (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding) +{ + if (window) + { + handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, TRUE, TRUE); + } +} + +static void +handle_move_to_side_n (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding) +{ + if (window) + { + handle_move_to_corner_backend (display, screen, window, FALSE, TRUE, FALSE, FALSE); + } +} + +static void +handle_move_to_side_s (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding) +{ + if (window) + { + handle_move_to_corner_backend (display, screen, window, FALSE, TRUE, FALSE, TRUE); + } +} + +static void +handle_move_to_side_e (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding) +{ + if (window) + { + handle_move_to_corner_backend (display, screen, window, TRUE, FALSE, TRUE, FALSE); + } +} + +static void +handle_move_to_side_w (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + XEvent *event, + MetaKeyBinding *binding) +{ + if (window) + { + handle_move_to_corner_backend (display, screen, window, TRUE, FALSE, FALSE, FALSE); + } +} + static gboolean process_workspace_switch_grab (MetaDisplay *display, MetaScreen *screen, diff --git a/src/metacity.schemas.in b/src/metacity.schemas.in index b16b3d31c..5557d0dea 100644 --- a/src/metacity.schemas.in +++ b/src/metacity.schemas.in @@ -1084,6 +1084,198 @@ you set + + /schemas/apps/metacity/window_keybindings/move_to_corner_nw + /apps/metacity/window_keybindings/move_to_corner_nw + metacity + string + + + Move window to north-west corner + + This keybinding moves a window into the north-west (top left) + corner of the screen. + + 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. + + + + + + /schemas/apps/metacity/window_keybindings/move_to_corner_ne + /apps/metacity/window_keybindings/move_to_corner_ne + metacity + string + + + Move window to north-east corner + + This keybinding moves a window into the north-east (top right) + corner of the screen. + + 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. + + + + + + /schemas/apps/metacity/window_keybindings/move_to_corner_sw + /apps/metacity/window_keybindings/move_to_corner_sw + metacity + string + + + Move window to south-west corner + + This keybinding moves a window into the south-west (bottom left) + corner of the screen. + + 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. + + + + + + /schemas/apps/metacity/window_keybindings/move_to_corner_se + /apps/metacity/window_keybindings/move_to_corner_se + metacity + string + + + Move window to south-east corner + + This keybinding moves a window into the south-east (bottom right) + corner of the screen. + + 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. + + + + + + /schemas/apps/metacity/window_keybindings/move_to_side_n + /apps/metacity/window_keybindings/move_to_side_n + metacity + string + + + Move window to north side of screen + + This keybinding moves a window against the north (top) + side of the screen. + + 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. + + + + + + /schemas/apps/metacity/window_keybindings/move_to_side_s + /apps/metacity/window_keybindings/move_to_side_s + metacity + string + + + Move window to south side of screen + + This keybinding moves a window into the south (bottom) + side of the screen. + + 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. + + + + + + /schemas/apps/metacity/window_keybindings/move_to_side_e + /apps/metacity/window_keybindings/move_to_side_e + metacity + string + + + Move window to east side of screen + + This keybinding moves a window into the east (right) + side of the screen. + + 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. + + + + + + /schemas/apps/metacity/window_keybindings/move_to_side_w + /apps/metacity/window_keybindings/move_to_side_w + metacity + string + + + Move window to west side of screen + + This keybinding moves a window into the west (left) + side of the screen. + + 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. + + + + diff --git a/src/prefs.c b/src/prefs.c index 3690a7984..3313bd384 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -1940,6 +1940,14 @@ static MetaKeyPref window_bindings[] = { { META_KEYBINDING_LOWER, NULL, FALSE }, { META_KEYBINDING_MAXIMIZE_VERTICALLY, NULL, FALSE }, { META_KEYBINDING_MAXIMIZE_HORIZONTALLY, NULL, FALSE }, + { META_KEYBINDING_MOVE_TO_CORNER_NW, NULL, FALSE }, + { META_KEYBINDING_MOVE_TO_CORNER_NE, NULL, FALSE }, + { META_KEYBINDING_MOVE_TO_CORNER_SW, NULL, FALSE }, + { META_KEYBINDING_MOVE_TO_CORNER_SE, NULL, FALSE }, + { META_KEYBINDING_MOVE_TO_SIDE_N, NULL, FALSE }, + { META_KEYBINDING_MOVE_TO_SIDE_S, NULL, FALSE }, + { META_KEYBINDING_MOVE_TO_SIDE_E, NULL, FALSE }, + { META_KEYBINDING_MOVE_TO_SIDE_W, NULL, FALSE }, { NULL, NULL, FALSE } }; diff --git a/src/prefs.h b/src/prefs.h index f1e81a8c5..df1b947cc 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -207,6 +207,14 @@ gboolean meta_prefs_get_compositing_manager (void); #define META_KEYBINDING_LOWER "lower" #define META_KEYBINDING_MAXIMIZE_VERTICALLY "maximize_vertically" #define META_KEYBINDING_MAXIMIZE_HORIZONTALLY "maximize_horizontally" +#define META_KEYBINDING_MOVE_TO_CORNER_NW "move_to_corner_nw" +#define META_KEYBINDING_MOVE_TO_CORNER_NE "move_to_corner_ne" +#define META_KEYBINDING_MOVE_TO_CORNER_SW "move_to_corner_sw" +#define META_KEYBINDING_MOVE_TO_CORNER_SE "move_to_corner_se" +#define META_KEYBINDING_MOVE_TO_SIDE_N "move_to_side_n" +#define META_KEYBINDING_MOVE_TO_SIDE_S "move_to_side_s" +#define META_KEYBINDING_MOVE_TO_SIDE_E "move_to_side_e" +#define META_KEYBINDING_MOVE_TO_SIDE_W "move_to_side_w" typedef enum _MetaKeyBindingAction {