From dee034771c8f3b519c8011faf78d277d6af76933 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Mon, 14 Sep 2015 03:06:18 +0300 Subject: Add manual and by-pointer window placement This adds a window placement preference: the existing behavior is now called "automatic" and is the default. Two new modes are being introduced: "pointer", which means that windows are placed according to the mouse pointer position; and "manual" which means that the user must manually place the new window with the mouse or keyboard. This is a straight port from muffin, commit 3257671. --- src/core/place.c | 52 ++++++++++++++++++++++++++++++++++++++++++ src/core/prefs.c | 16 +++++++++++++ src/core/window-private.h | 3 +++ src/core/window.c | 8 +++++++ src/include/common.h | 10 ++++++++ src/include/prefs.h | 5 +++- src/org.mate.marco.gschema.xml | 10 ++++++++ 7 files changed, 103 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/place.c b/src/core/place.c index 99cedd14..bcfafe42 100644 --- a/src/core/place.c +++ b/src/core/place.c @@ -87,6 +87,47 @@ northwestcmp (gconstpointer a, gconstpointer b) return 0; } +static gboolean +place_by_pointer(MetaWindow *window, + MetaFrameGeometry *fgeom, + MetaPlacementMode placement_mode, + int *new_x, + int *new_y) +{ + int window_width, window_height; + Window root_return, child_return; + int root_x_return, root_y_return; + int win_x_return, win_y_return; + unsigned int mask_return; + + XQueryPointer (window->display->xdisplay, + window->screen->xroot, + &root_return, + &child_return, + &root_x_return, + &root_y_return, + &win_x_return, + &win_y_return, + &mask_return); + + window_width = window->frame ? window->frame->rect.width : window->rect.width; + window_height = window->frame ? window->frame->rect.height : window->rect.height; + + if (fgeom) { + *new_x = root_x_return + fgeom->left_width - window_width / 2; + *new_y = root_y_return + fgeom->top_height - window_height / 2; + } + else { + *new_x = root_x_return - window_width / 2; + *new_y = root_y_return - window_height / 2; + } + + if (placement_mode == META_PLACEMENT_MODE_MANUAL) + window->move_after_placement = TRUE; + + return TRUE; +} + static void find_next_cascade (MetaWindow *window, MetaFrameGeometry *fgeom, @@ -663,6 +704,7 @@ meta_window_place (MetaWindow *window, { GList *windows; const MetaXineramaScreenInfo *xi; + MetaPlacementMode placement_mode; /* frame member variables should NEVER be used in here, only * MetaFrameGeometry. But remember fgeom == NULL @@ -853,6 +895,16 @@ meta_window_place (MetaWindow *window, x = xi->rect.x; y = xi->rect.y; + /* Placement based on pointer position */ + placement_mode = meta_prefs_get_placement_mode(); + + if (placement_mode == META_PLACEMENT_MODE_POINTER || + placement_mode == META_PLACEMENT_MODE_MANUAL) + { + if (place_by_pointer (window, fgeom, placement_mode, &x, &y)) + goto done_check_denied_focus; + } + if (find_first_fit (window, fgeom, windows, xi->number, x, y, &x, &y)) diff --git a/src/core/prefs.c b/src/core/prefs.c index 8fa28b83..2f3e9392 100644 --- a/src/core/prefs.c +++ b/src/core/prefs.c @@ -168,6 +168,8 @@ static void init_window_bindings (void); static void init_commands (void); static void init_workspace_names (void); +static MetaPlacementMode placement_mode = META_PLACEMENT_MODE_AUTOMATIC; + typedef struct { MetaPrefsChangedFunc func; @@ -317,6 +319,11 @@ static MetaEnumPreference preferences_enum[] = META_PREF_ACTION_RIGHT_CLICK_TITLEBAR, (gint *) &action_right_click_titlebar, }, + { "placement-mode", + KEY_GENERAL_SCHEMA, + META_PREF_PLACEMENT_MODE, + (gint *) &placement_mode, + }, { NULL, NULL, 0, NULL }, }; @@ -1556,6 +1563,9 @@ meta_preference_to_string (MetaPreference pref) case META_PREF_SIDE_BY_SIDE_TILING: return "SIDE_BY_SIDE_TILING"; + + case META_PREF_PLACEMENT_MODE: + return "PLACEMENT_MODE"; } return "(unknown)"; @@ -2241,6 +2251,12 @@ meta_prefs_get_force_fullscreen (void) return force_fullscreen; } +MetaPlacementMode +meta_prefs_get_placement_mode (void) +{ + return placement_mode; +} + void meta_prefs_set_force_compositing_manager (gboolean whether) { diff --git a/src/core/window-private.h b/src/core/window-private.h index 20e619cb..0b3cf594 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -139,6 +139,9 @@ struct _MetaWindow guint maximize_vertically_after_placement : 1; guint minimize_after_placement : 1; + /* Whether to move after placement */ + guint move_after_placement : 1; + /* The current or requested tile mode. If maximized_vertically is true, * this is the current mode. If not, it is the mode which will be * requested after the window grab is released */ diff --git a/src/core/window.c b/src/core/window.c index 60616e4d..30ebfa85 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -461,6 +461,7 @@ meta_window_new_with_attrs (MetaDisplay *display, window->maximize_horizontally_after_placement = FALSE; window->maximize_vertically_after_placement = FALSE; window->minimize_after_placement = FALSE; + window->move_after_placement = FALSE; window->fullscreen = FALSE; window->fullscreen_after_placement = FALSE; window->fullscreen_monitors[0] = -1; @@ -2346,6 +2347,13 @@ meta_window_show (MetaWindow *window) if (takes_focus_on_map) { meta_window_focus (window, timestamp); + + if (window->move_after_placement) + { + meta_window_begin_grab_op(window, META_GRAB_OP_KEYBOARD_MOVING, + FALSE, timestamp); + window->move_after_placement = FALSE; + } } else { diff --git a/src/include/common.h b/src/include/common.h index 69755e24..74137967 100644 --- a/src/include/common.h +++ b/src/include/common.h @@ -312,4 +312,14 @@ struct _MetaButtonLayout (ycoord) >= (rect).y && \ (ycoord) < ((rect).y + (rect).height)) +/* + * Placement mode + */ +typedef enum +{ + META_PLACEMENT_MODE_AUTOMATIC, + META_PLACEMENT_MODE_POINTER, + META_PLACEMENT_MODE_MANUAL +} MetaPlacementMode; + #endif diff --git a/src/include/prefs.h b/src/include/prefs.h index d804207c..a2fbbf55 100644 --- a/src/include/prefs.h +++ b/src/include/prefs.h @@ -64,7 +64,8 @@ typedef enum META_PREF_RESIZE_WITH_RIGHT_BUTTON, META_PREF_CENTER_NEW_WINDOWS, META_PREF_SIDE_BY_SIDE_TILING, - META_PREF_FORCE_FULLSCREEN + META_PREF_FORCE_FULLSCREEN, + META_PREF_PLACEMENT_MODE } MetaPreference; typedef void (* MetaPrefsChangedFunc) (MetaPreference pref, @@ -112,6 +113,8 @@ MetaActionTitlebar meta_prefs_get_action_double_click_titlebar (void); MetaActionTitlebar meta_prefs_get_action_middle_click_titlebar (void); MetaActionTitlebar meta_prefs_get_action_right_click_titlebar (void); +MetaPlacementMode meta_prefs_get_placement_mode (void); + void meta_prefs_set_num_workspaces (int n_workspaces); const char* meta_prefs_get_workspace_name (int i); diff --git a/src/org.mate.marco.gschema.xml b/src/org.mate.marco.gschema.xml index 4108355c..6bd57811 100644 --- a/src/org.mate.marco.gschema.xml +++ b/src/org.mate.marco.gschema.xml @@ -30,6 +30,11 @@ + + + + + @@ -171,6 +176,11 @@ Whether to enable side-by-side tiling If enabled, dropping windows on screen edges maximizes them vertically and resizes them horizontally to cover half of the available area. Drag-dropping to the top maximizes the window. + + 'automatic' + Window placement mode + The window placement mode indicates how new windows are positioned. "automatic" means the system chooses a location automatically based on the space available on the desktop, or by a simple cascade if there is no space; "pointer" means that new windows are placed according to the mouse pointer position; "manual" means that the user must manually place the new window with the mouse or keyboard. + -- cgit v1.2.1