summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/constraints.c47
-rw-r--r--src/core/display.c28
-rw-r--r--src/core/frame.c2
-rw-r--r--src/core/prefs.c16
-rw-r--r--src/core/window-private.h2
-rw-r--r--src/core/window.c71
-rw-r--r--src/include/prefs.h2
-rw-r--r--src/org.mate.marco.gschema.xml5
8 files changed, 172 insertions, 1 deletions
diff --git a/src/core/constraints.c b/src/core/constraints.c
index c31c525d..c3acb128 100644
--- a/src/core/constraints.c
+++ b/src/core/constraints.c
@@ -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"},
@@ -784,6 +789,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,
ConstraintPriority priority,
diff --git a/src/core/display.c b/src/core/display.c
index 6dd13419..fd5dc545 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -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
diff --git a/src/core/frame.c b/src/core/frame.c
index 17d1bdff..2e0a0452 100644
--- a/src/core/frame.c
+++ b/src/core/frame.c
@@ -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)
diff --git a/src/core/prefs.c b/src/core/prefs.c
index e376089c..048b738a 100644
--- a/src/core/prefs.c
+++ b/src/core/prefs.c
@@ -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,
@@ -1075,6 +1082,12 @@ meta_prefs_get_focus_new_windows (void)
}
gboolean
+meta_prefs_get_attach_modal_dialogs (void)
+{
+ return attach_modal_dialogs;
+}
+
+gboolean
meta_prefs_get_raise_on_click (void)
{
/* Force raise_on_click on for click-to-focus, as requested by Havoc
@@ -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";
diff --git a/src/core/window-private.h b/src/core/window-private.h
index a6b49b4b..a6b6418c 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -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,
diff --git a/src/core/window.c b/src/core/window.c
index 8cffdde8..5ec4af09 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -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)
{
diff --git a/src/include/prefs.h b/src/include/prefs.h
index 29db2a10..34ab802e 100644
--- a/src/include/prefs.h
+++ b/src/include/prefs.h
@@ -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 */
diff --git a/src/org.mate.marco.gschema.xml b/src/org.mate.marco.gschema.xml
index 6632e6b1..adbb29e2 100644
--- a/src/org.mate.marco.gschema.xml
+++ b/src/org.mate.marco.gschema.xml
@@ -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>