summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-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
6 files changed, 165 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)
{