Skip to content

Commit

Permalink
Optionally attach modal dialogs
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Zaspire authored and vkareh committed Aug 28, 2018
1 parent 4f47c5b commit 37fecf4
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 1 deletion.
47 changes: 47 additions & 0 deletions src/core/constraints.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,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,
Expand Down Expand Up @@ -222,6 +226,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"},
Expand Down Expand Up @@ -783,6 +788,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,
Expand Down
28 changes: 28 additions & 0 deletions src/core/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -5216,6 +5216,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
Expand Down
2 changes: 1 addition & 1 deletion src/core/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,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)
Expand Down
16 changes: 16 additions & 0 deletions src/core/prefs.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ static MetaVirtualModifier mouse_button_mods = Mod1Mask;
static MetaFocusMode focus_mode = META_FOCUS_MODE_CLICK;
static MetaFocusNewWindows focus_new_windows = META_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 MetaWrapStyle wrap_style = META_WRAP_NONE;
Expand Down Expand Up @@ -334,6 +335,12 @@ static MetaEnumPreference preferences_enum[] =

static MetaBoolPreference preferences_bool[] =
{
{ "attach-modal-dialogs",
KEY_GENERAL_SCHEMA,
META_PREF_ATTACH_MODAL_DIALOGS,
&attach_modal_dialogs,
TRUE,
},
{ "raise-on-click",
KEY_GENERAL_SCHEMA,
META_PREF_RAISE_ON_CLICK,
Expand Down Expand Up @@ -1074,6 +1081,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)
{
Expand Down Expand Up @@ -1536,6 +1549,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";

Expand Down
2 changes: 2 additions & 0 deletions src/core/window-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,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,
Expand Down
71 changes: 71 additions & 0 deletions src/core/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -3412,6 +3412,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,
Expand Down Expand Up @@ -3866,6 +3879,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
Expand Down Expand Up @@ -5504,6 +5520,23 @@ meta_window_appears_focused_changed (MetaWindow *window)
meta_frame_queue_draw (window->frame);
}

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)
Expand Down Expand Up @@ -5639,6 +5672,9 @@ meta_window_notify_focus (MetaWindow *window,
if (meta_prefs_get_focus_mode () == META_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 ||
Expand Down Expand Up @@ -5666,6 +5702,9 @@ meta_window_notify_focus (MetaWindow *window,
window->display->focus_window = NULL;
window->has_focus = FALSE;

/* parent window become active. */
check_ancestor_focus_appearance (window);

meta_window_appears_focused_changed (window);

meta_compositor_set_active_window (window->display->compositor,
Expand Down Expand Up @@ -6472,6 +6511,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;
Expand Down Expand Up @@ -8594,6 +8643,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)
{
Expand Down
2 changes: 2 additions & 0 deletions src/include/prefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -87,6 +88,7 @@ guint meta_prefs_get_mouse_button_resize (void);
guint meta_prefs_get_mouse_button_menu (void);
MetaFocusMode meta_prefs_get_focus_mode (void);
MetaFocusNewWindows 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 */
Expand Down
5 changes: 5 additions & 0 deletions src/org.mate.marco.gschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@
<summary>Visual Bell Type</summary>
<description>Tells Marco how to implement the visual indication that the system bell or another application 'bell' indicator has been rung. Currently there are two valid values, "fullscreen", which causes a fullscreen white-black flash, and "frame_flash" which causes the titlebar of the application which sent the bell signal to flash. If the application which sent the bell is unknown (as is usually the case for the default "system beep"), the currently focused window's titlebar is flashed.</description>
</key>
<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>
Expand Down

0 comments on commit 37fecf4

Please sign in to comment.