Commit 5be337ce authored by Alberts Muktupāvels's avatar Alberts Muktupāvels

add option to set window placement mode

Adapted from patch by Chad Glendenin available at:
http://chad.glendenin.com/metacity/patch.html
parent 053602ee
......@@ -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
......
......@@ -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;
}
......@@ -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.
*
......
<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>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment