Skip to content
Permalink
Browse files

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.
  • Loading branch information...
Zaspire authored and vkareh committed Sep 27, 2014
1 parent 4f47c5b commit 37fecf49392eb10ada1f4bf481d6ad6be56891dd
Showing with 172 additions and 1 deletion.
  1. +47 −0 src/core/constraints.c
  2. +28 −0 src/core/display.c
  3. +1 −1 src/core/frame.c
  4. +16 −0 src/core/prefs.c
  5. +2 −0 src/core/window-private.h
  6. +71 −0 src/core/window.c
  7. +2 −0 src/include/prefs.h
  8. +5 −0 src/org.mate.marco.gschema.xml
@@ -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,
@@ -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"},
@@ -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,
@@ -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
@@ -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)
@@ -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;
@@ -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,
@@ -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)
{
@@ -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";

@@ -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,
@@ -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,
@@ -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
@@ -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)
@@ -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 ||
@@ -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,
@@ -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;
@@ -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)
{
@@ -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,
@@ -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 */
@@ -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>

0 comments on commit 37fecf4

Please sign in to comment.
You can’t perform that action at this time.