[metacity] add option to set window placement mode
- From: Alberts MuktupÄvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [metacity] add option to set window placement mode
- Date: Fri, 6 Jun 2014 14:19:47 +0000 (UTC)
commit 5be337ce674fe6cd955bc5c2077e86ad6c642601
Author: Alberts MuktupÄvels <alberts muktupavels gmail com>
Date: Wed Jan 8 16:33:23 2014 +0200
add option to set window placement mode
Adapted from patch by Chad Glendenin available at:
http://chad.glendenin.com/metacity/patch.html
src/core/place.c | 98 ++++++++++++++++++++++++++++++++-
src/core/prefs.c | 24 ++++++--
src/include/prefs.h | 14 ++++-
src/org.gnome.metacity.gschema.xml.in | 23 ++++++++
4 files changed, 150 insertions(+), 9 deletions(-)
---
diff --git a/src/core/place.c b/src/core/place.c
index 4c20a3f..f9dc67f 100644
--- a/src/core/place.c
+++ b/src/core/place.c
@@ -639,6 +639,98 @@ find_first_fit (MetaWindow *window,
return retval;
}
+static gboolean
+find_preferred_position (MetaWindow *window,
+ MetaFrameGeometry *fgeom,
+ /* visible windows on relevant workspaces */
+ GList *windows,
+ int xinerama,
+ int x,
+ int y,
+ int *new_x,
+ int *new_y)
+{
+ MetaRectangle rect;
+ MetaRectangle work_area;
+ MetaPlacementMode placement_mode_pref = meta_prefs_get_placement_mode ();
+
+ /* If first_fit placement is the preference, just pass all the
+ * options through to the original find_first_fit function.
+ * Otherwise, process the user preference here.
+ */
+ if (placement_mode_pref == META_PLACEMENT_MODE_SMART)
+ {
+ return find_first_fit (window, fgeom, windows,
+ xinerama,
+ x, y, new_x, new_y);
+ }
+ else if (placement_mode_pref == META_PLACEMENT_MODE_CASCADE)
+ {
+ /* This is an abuse of find_next_cascade(), because it was not
+ * intended for this use, and because it is not designed to
+ * deal with placement on multiple Xineramas.
+ */
+ find_next_cascade (window, fgeom, windows, x, y, new_x, new_y);
+ return TRUE;
+ }
+
+ rect.width = window->rect.width;
+ rect.height = window->rect.height;
+
+ if (fgeom)
+ {
+ rect.width += fgeom->left_width + fgeom->right_width;
+ rect.height += fgeom->top_height + fgeom->bottom_height;
+ }
+
+ meta_window_get_work_area_for_xinerama (window, xinerama, &work_area);
+
+ /* Cannot use rect_fits_in_work_area here because that function
+ * also checks the x & y position of rect, but those are not set
+ * yet in this case.
+ */
+ if ((rect.width <= work_area.width) && (rect.height <= work_area.height))
+ {
+ switch (placement_mode_pref)
+ {
+ case META_PLACEMENT_MODE_CENTER:
+ /* This is a plain centering, different from center_tile */
+ *new_x = work_area.x + ((work_area.width - rect.width) / 2);
+ *new_y = work_area.y + ((work_area.height - rect.height) / 2);
+ break;
+
+ case META_PLACEMENT_MODE_ORIGIN:
+ *new_x = work_area.x;
+ *new_y = work_area.y;
+ break;
+
+ case META_PLACEMENT_MODE_RANDOM:
+ *new_x = (int) ((float) (work_area.width - rect.width) *
+ ((float) rand() / (float) RAND_MAX));
+ *new_y = (int) ((float) (work_area.height - rect.height) *
+ ((float) rand() / (float) RAND_MAX));
+ *new_x += work_area.x;
+ *new_y += work_area.y;
+ break;
+
+ default:
+ meta_warning ("Unknown window-placement option chosen.\n");
+ return FALSE;
+ break;
+ }
+
+ if (fgeom)
+ {
+ *new_x += fgeom->left_width;
+ *new_y += fgeom->top_height;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
void
meta_window_place (MetaWindow *window,
MetaFrameGeometry *fgeom,
@@ -839,9 +931,9 @@ meta_window_place (MetaWindow *window,
x = xi->rect.x;
y = xi->rect.y;
- if (find_first_fit (window, fgeom, windows,
- xi->number,
- x, y, &x, &y))
+ if (find_preferred_position (window, fgeom, windows,
+ xi->number,
+ x, y, &x, &y))
goto done_check_denied_focus;
/* Maximize windows if they are too big for their work area (bit of
diff --git a/src/core/prefs.c b/src/core/prefs.c
index 7d2ce93..3e93140 100644
--- a/src/core/prefs.c
+++ b/src/core/prefs.c
@@ -42,6 +42,7 @@
#define KEY_NUM_WORKSPACES "num-workspaces"
#define KEY_WORKSPACE_NAMES "workspace-names"
#define KEY_COMPOSITOR "compositing-manager"
+#define KEY_PLACEMENT_MODE "placement-mode"
/* Keys from "foreign" schemas */
#define KEY_GNOME_ACCESSIBILITY "toolkit-accessibility"
@@ -92,6 +93,8 @@ static gboolean force_fullscreen = TRUE;
static GDesktopVisualBellType visual_bell_type = G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH;
static MetaButtonLayout button_layout;
+static MetaPlacementMode placement_mode = META_PLACEMENT_MODE_SMART;
+
/* NULL-terminated array */
static char **workspace_names = NULL;
@@ -242,6 +245,13 @@ static MetaEnumPreference preferences_enum[] =
},
&action_right_click_titlebar,
},
+ {
+ { "placement-mode",
+ SCHEMA_METACITY,
+ META_PREF_PLACEMENT_MODE,
+ },
+ &placement_mode,
+ },
{ { NULL, 0, 0 }, NULL },
};
@@ -626,7 +636,6 @@ handle_preference_update_int (GSettings *settings,
}
}
-
/****************************************************************************/
/* Listeners. */
/****************************************************************************/
@@ -740,7 +749,6 @@ queue_changed (MetaPreference pref)
changed_idle_handler, NULL, NULL);
}
-
/****************************************************************************/
/* Initialisation. */
/****************************************************************************/
@@ -791,7 +799,6 @@ meta_prefs_init (void)
init_workspace_names ();
}
-
/****************************************************************************/
/* Updates. */
/****************************************************************************/
@@ -925,7 +932,6 @@ meta_prefs_get_cursor_size (void)
return cursor_size;
}
-
/****************************************************************************/
/* Handlers for string preferences. */
/****************************************************************************/
@@ -1412,6 +1418,9 @@ meta_preference_to_string (MetaPreference pref)
case META_PREF_FORCE_FULLSCREEN:
return "FORCE_FULLSCREEN";
+
+ case META_PREF_PLACEMENT_MODE:
+ return "PLACEMENT_MODE";
}
return "(unknown)";
@@ -1822,6 +1831,12 @@ meta_prefs_get_force_fullscreen (void)
return force_fullscreen;
}
+MetaPlacementMode
+meta_prefs_get_placement_mode (void)
+{
+ return placement_mode;
+}
+
void
meta_prefs_set_compositing_manager (gboolean whether)
{
@@ -1833,4 +1848,3 @@ meta_prefs_set_force_fullscreen (gboolean whether)
{
force_fullscreen = whether;
}
-
diff --git a/src/include/prefs.h b/src/include/prefs.h
index 16fdc8d..c251aba 100644
--- a/src/include/prefs.h
+++ b/src/include/prefs.h
@@ -58,9 +58,19 @@ typedef enum
META_PREF_CURSOR_SIZE,
META_PREF_COMPOSITING_MANAGER,
META_PREF_RESIZE_WITH_RIGHT_BUTTON,
- META_PREF_FORCE_FULLSCREEN
+ META_PREF_FORCE_FULLSCREEN,
+ META_PREF_PLACEMENT_MODE
} MetaPreference;
+typedef enum
+{
+ META_PLACEMENT_MODE_SMART,
+ META_PLACEMENT_MODE_CASCADE,
+ META_PLACEMENT_MODE_CENTER,
+ META_PLACEMENT_MODE_ORIGIN,
+ META_PLACEMENT_MODE_RANDOM
+} MetaPlacementMode;
+
typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
gpointer data);
@@ -114,6 +124,8 @@ int meta_prefs_get_cursor_size (void);
gboolean meta_prefs_get_compositing_manager (void);
gboolean meta_prefs_get_force_fullscreen (void);
+MetaPlacementMode meta_prefs_get_placement_mode (void);
+
/**
* Sets whether the compositor is turned on.
*
diff --git a/src/org.gnome.metacity.gschema.xml.in b/src/org.gnome.metacity.gschema.xml.in
index d6cda89..d1fd336 100644
--- a/src/org.gnome.metacity.gschema.xml.in
+++ b/src/org.gnome.metacity.gschema.xml.in
@@ -1,5 +1,13 @@
<schemalist>
+ <enum id="org.gnome.metacity.MetaPlacementMode">
+ <value nick="smart" value="0" />
+ <value nick="cascade" value="1" />
+ <value nick="center" value="2" />
+ <value nick="origin" value="3" />
+ <value nick="random" value="4" />
+ </enum>
+
<schema id="org.gnome.metacity" path="/org/gnome/metacity/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="compositing-manager" type="b">
@@ -22,6 +30,21 @@
However, the wireframe feature is disabled when accessibility is on.
</_description>
</key>
+ <key name="placement-mode" enum="org.gnome.metacity.MetaPlacementMode">
+ <default>'smart'</default>
+ <_summary>Window placement behavior</_summary>
+ <_description>
+ Metacity's default window-placement behavior is smart (first-fit),
+ similar to behaviors in some other window managers. It will try to tile
+ windows so that they do not overlap. Set this option to "smart" for this
+ behavior.
+
+ This option can be set to "center" to place new windows in the centers
+ of their workspaces, "origin" for the upper-left corners of the
+ workspaces, or "random" to place new windows at random locations within
+ their workspaces.
+ </_description>
+ </key>
</schema>
</schemalist>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]