Commit bbf76b6b authored by Maxim Ermilov's avatar Maxim Ermilov Committed by Alberts Muktupāvels

Optionally attach modal dialogs

Add a preference /apps/mutter/general/attach_modal_dialogs. When
true, instead of having independent titlebars, modal dialogs appear
attached to the titlebar of the parent window and are moved
together with the parent window.

https://bugzilla.gnome.org/show_bug.cgi?id=612726

NOTE: Patch copied from mutter and adapted for metacity.
parent 542cc51d
......@@ -140,6 +140,10 @@ typedef struct
GList *usable_xinerama_region;
} ConstraintInfo;
static gboolean constrain_modal_dialog (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
gboolean check_only);
static gboolean constrain_maximization (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
......@@ -213,6 +217,7 @@ typedef struct {
} Constraint;
static const Constraint all_constraints[] = {
{constrain_modal_dialog, "constrain_modal_dialog"},
{constrain_maximization, "constrain_maximization"},
{constrain_tiling, "constrain_tiling"},
{constrain_fullscreen, "constrain_fullscreen"},
......@@ -732,6 +737,48 @@ get_size_limits (const MetaWindow *window,
}
}
static gboolean
constrain_modal_dialog (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
gboolean check_only)
{
int x, y;
MetaWindow *parent = meta_window_get_transient_for (window);
gboolean constraint_already_satisfied;
if (!meta_prefs_get_attach_modal_dialogs ())
return TRUE;
if (window->type != META_WINDOW_MODAL_DIALOG || !parent || parent == window)
return TRUE;
x = parent->rect.x + (parent->rect.width / 2 - info->current.width / 2);
y = 0;
if (parent->frame)
{
MetaFrameGeometry fgeom;
x += parent->frame->rect.x;
y += parent->frame->rect.y;
meta_frame_calc_geometry (parent->frame, &fgeom);
y += fgeom.top_height;
y += info->fgeom->top_height;
}
else
y = parent->rect.y + info->fgeom->top_height;
constraint_already_satisfied = (x == info->current.x) && (y == info->current.y);
if (check_only || constraint_already_satisfied)
return constraint_already_satisfied;
info->current.y = y;
info->current.x = x;
return TRUE;
}
static gboolean
constrain_maximization (MetaWindow *window,
ConstraintInfo *info,
......
......@@ -4951,6 +4951,34 @@ prefs_changed_callback (MetaPreference pref,
else
disable_compositor (display);
}
else if (pref == META_PREF_ATTACH_MODAL_DIALOGS)
{
MetaDisplay *display = data;
GSList *windows;
GSList *tmp;
windows = meta_display_list_windows (display);
for (tmp = windows; tmp != NULL; tmp = tmp->next)
{
MetaWindow *w = tmp->data;
MetaWindow *parent = meta_window_get_transient_for (w);
meta_window_recalc_features (w);
if (w->type == META_WINDOW_MODAL_DIALOG && parent && parent != w)
{
int x, y;
/* Forcing a call to move_resize() does two things: first, it handles
* resizing the dialog frame window to the correct size when we remove
* or add the decorations. Second, it will take care of positioning the
* dialog as "attached" to the parent when we turn the preference on
* via the constrain_modal_dialog() constraint.
**/
meta_window_get_position (w, &x, &y);
meta_window_move (w, FALSE, x, y);
}
}
}
}
void
......
......@@ -265,7 +265,7 @@ meta_frame_get_flags (MetaFrame *frame)
if (META_WINDOW_ALLOWS_VERTICAL_RESIZE (frame->window))
flags |= META_FRAME_ALLOWS_VERTICAL_RESIZE;
if (frame->window->has_focus)
if (meta_window_appears_focused (frame->window))
flags |= META_FRAME_HAS_FOCUS;
if (frame->window->shaded)
......
......@@ -70,6 +70,7 @@ static MetaVirtualModifier mouse_button_mods = Mod1Mask;
static GDesktopFocusMode focus_mode = G_DESKTOP_FOCUS_MODE_CLICK;
static GDesktopFocusNewWindows focus_new_windows = G_DESKTOP_FOCUS_NEW_WINDOWS_SMART;
static gboolean raise_on_click = TRUE;
static gboolean attach_modal_dialogs = FALSE;
static char* current_theme = NULL;
static int num_workspaces = 4;
static GDesktopTitlebarAction action_double_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE;
......@@ -258,6 +259,14 @@ static MetaEnumPreference preferences_enum[] =
static MetaBoolPreference preferences_bool[] =
{
{
{ "attach-modal-dialogs",
SCHEMA_METACITY,
META_PREF_ATTACH_MODAL_DIALOGS
},
&attach_modal_dialogs,
TRUE,
},
{
{ "raise-on-click",
SCHEMA_GENERAL,
......@@ -914,6 +923,12 @@ meta_prefs_get_focus_new_windows (void)
return focus_new_windows;
}
gboolean
meta_prefs_get_attach_modal_dialogs (void)
{
return attach_modal_dialogs;
}
gboolean
meta_prefs_get_raise_on_click (void)
{
......@@ -1353,6 +1368,9 @@ meta_preference_to_string (MetaPreference pref)
case META_PREF_FOCUS_NEW_WINDOWS:
return "FOCUS_NEW_WINDOWS";
case META_PREF_ATTACH_MODAL_DIALOGS:
return "ATTACH_MODAL_DIALOGS";
case META_PREF_RAISE_ON_CLICK:
return "RAISE_ON_CLICK";
......
......@@ -452,6 +452,8 @@ void meta_window_update_fullscreen_monitors (MetaWindow *window,
unsigned long left,
unsigned long right);
gboolean meta_window_appears_focused (MetaWindow *window);
/* args to move are window pos, not frame pos */
void meta_window_move (MetaWindow *window,
gboolean user_op,
......
......@@ -3305,6 +3305,19 @@ send_sync_request (MetaWindow *window)
}
#endif
static gboolean
move_attached_dialog (MetaWindow *window,
void *data)
{
MetaWindow *parent = meta_window_get_transient_for (window);
if (window->type == META_WINDOW_MODAL_DIALOG && parent && parent != window)
/* It ignores x,y for such a dialog */
meta_window_move (window, FALSE, 0, 0);
return FALSE;
}
static void
meta_window_move_resize_internal (MetaWindow *window,
MetaMoveResizeFlags flags,
......@@ -3759,6 +3772,9 @@ meta_window_move_resize_internal (MetaWindow *window,
* server-side size/pos of window->xwindow and frame->xwindow
* b) all constraints are obeyed by window->rect and frame->rect
*/
if (meta_prefs_get_attach_modal_dialogs ())
meta_window_foreach_transient (window, move_attached_dialog, NULL);
}
void
......@@ -5389,6 +5405,23 @@ meta_window_client_message (MetaWindow *window,
return FALSE;
}
static void
check_ancestor_focus_appearance (MetaWindow *window)
{
MetaWindow *parent = meta_window_get_transient_for (window);
if (!meta_prefs_get_attach_modal_dialogs ())
return;
if (window->type != META_WINDOW_MODAL_DIALOG || !parent || parent == window)
return;
if (parent->frame)
meta_frame_queue_draw (parent->frame);
check_ancestor_focus_appearance (parent);
}
gboolean
meta_window_notify_focus (MetaWindow *window,
XEvent *event)
......@@ -5525,6 +5558,9 @@ meta_window_notify_focus (MetaWindow *window,
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
!meta_prefs_get_raise_on_click())
meta_display_ungrab_focus_window_button (window->display, window);
/* parent window become active. */
check_ancestor_focus_appearance (window);
}
}
else if (event->type == FocusOut ||
......@@ -5551,6 +5587,10 @@ meta_window_notify_focus (MetaWindow *window,
window->display->focus_window = NULL;
window->has_focus = FALSE;
/* parent window become active. */
check_ancestor_focus_appearance (window);
if (window->frame)
meta_frame_queue_draw (window->frame);
......@@ -6350,6 +6390,16 @@ recalc_window_features (MetaWindow *window)
if (window->type == META_WINDOW_TOOLBAR)
window->decorated = FALSE;
if (window->type == META_WINDOW_MODAL_DIALOG && meta_prefs_get_attach_modal_dialogs ())
{
MetaWindow *parent = meta_window_get_transient_for (window);
if (parent)
{
window->has_resize_func = FALSE;
window->border_only = TRUE;
}
}
if (window->type == META_WINDOW_DESKTOP ||
window->type == META_WINDOW_DOCK)
window->always_sticky = TRUE;
......@@ -8431,6 +8481,28 @@ meta_window_get_frame (MetaWindow *window)
return window->frame;
}
static gboolean
transient_has_focus (MetaWindow *window,
void *data)
{
if (window->type == META_WINDOW_MODAL_DIALOG && meta_window_appears_focused (window))
*((gboolean *)data) = TRUE;
return FALSE;
}
gboolean
meta_window_appears_focused (MetaWindow *window)
{
if (!window->has_focus && meta_prefs_get_attach_modal_dialogs ())
{
gboolean focus = FALSE;
meta_window_foreach_transient (window, transient_has_focus, &focus);
return focus;
}
return window->has_focus;
}
gboolean
meta_window_has_focus (MetaWindow *window)
{
......
......@@ -34,6 +34,7 @@ typedef enum
META_PREF_MOUSE_BUTTON_MODS,
META_PREF_FOCUS_MODE,
META_PREF_FOCUS_NEW_WINDOWS,
META_PREF_ATTACH_MODAL_DIALOGS,
META_PREF_RAISE_ON_CLICK,
META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR,
META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR,
......@@ -88,6 +89,7 @@ guint meta_prefs_get_mouse_button_resize (void);
guint meta_prefs_get_mouse_button_menu (void);
GDesktopFocusMode meta_prefs_get_focus_mode (void);
GDesktopFocusNewWindows meta_prefs_get_focus_new_windows (void);
gboolean meta_prefs_get_attach_modal_dialogs (void);
gboolean meta_prefs_get_raise_on_click (void);
const char* meta_prefs_get_theme (void);
/* returns NULL if GTK default should be used */
......
......@@ -10,6 +10,15 @@
<schema id="org.gnome.metacity" path="/org/gnome/metacity/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="attach-modal-dialogs" type="b">
<default>false</default>
<_summary>Attach modal dialogs</_summary>
<_description>
When true, instead of having independent titlebars, modal dialogs
appear attached to the titlebar of the parent window and are moved
together with the parent window.
</_description>
</key>
<key name="compositing-manager" type="b">
<default>true</default>
<_summary>Compositing Manager</_summary>
......
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