diff --git a/js/ui/altTab.js b/js/ui/altTab.js index c5a0a2ad1..ec23fdabc 100644 --- a/js/ui/altTab.js +++ b/js/ui/altTab.js @@ -105,8 +105,10 @@ AltTabPopup.prototype = { global.screen_height); this.actor.show_all(); - this.actor.x = Math.floor((global.screen_width - this.actor.width) / 2); - this.actor.y = Math.floor((global.screen_height - this.actor.height) / 2); + + let primary = global.get_primary_monitor(); + this.actor.x = primary.x + Math.floor((primary.width - this.actor.width) / 2); + this.actor.y = primary.y + Math.floor((primary.height - this.actor.height) / 2); this._updateSelection(initialSelection); diff --git a/js/ui/lookingGlass.js b/js/ui/lookingGlass.js index 8bfd660b2..6c1e943db 100644 --- a/js/ui/lookingGlass.js +++ b/js/ui/lookingGlass.js @@ -249,15 +249,16 @@ function Inspector() { Inspector.prototype = { _init: function() { let width = 150; + let primary = global.get_primary_monitor(); let eventHandler = new Big.Box({ background_color: LG_BACKGROUND_COLOR, border: 1, border_color: LG_BORDER_COLOR, corner_radius: 4, - y: global.stage.height/2, + y: primary.y + Math.floor(primary.height / 2), reactive: true }); eventHandler.connect('notify::allocation', Lang.bind(this, function () { - eventHandler.x = Math.floor((global.stage.width)/2 - (eventHandler.width)/2); + eventHandler.x = primary.x + Math.floor((primary.width - eventHandler.width) / 2); })); global.stage.add_actor(eventHandler); let displayText = new Clutter.Text({ color: MATRIX_GREEN, @@ -518,11 +519,11 @@ LookingGlass.prototype = { }, _resizeTo: function(actor) { - let stage = global.stage; - let myWidth = stage.width * 0.7; - let myHeight = stage.height * 0.7; + let primary = global.get_primary_monitor(); + let myWidth = primary.width * 0.7; + let myHeight = primary.height * 0.7; let [srcX, srcY] = actor.get_transformed_position(); - this.actor.x = srcX + (stage.width-myWidth)/2; + this.actor.x = srcX + (primary.width - myWidth) / 2; this._hiddenY = srcY + actor.height - myHeight - 4; // -4 to hide the top corners this._targetY = this._hiddenY + myHeight; this.actor.y = this._hiddenY; diff --git a/js/ui/main.js b/js/ui/main.js index f48d38b44..110404432 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -121,7 +121,9 @@ function start() { } function _relayout() { - panel.actor.set_size(global.screen_width, Panel.PANEL_HEIGHT); + let primary = global.get_primary_monitor(); + panel.actor.set_position(primary.x, primary.y); + panel.actor.set_size(primary.width, Panel.PANEL_HEIGHT); overview.relayout(); } diff --git a/js/ui/overview.js b/js/ui/overview.js index f3f402dd7..4d5b37cbb 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -142,42 +142,44 @@ Overview.prototype = { }, _recalculateGridSizes: function () { - wideScreen = (global.screen_width/global.screen_height > WIDE_SCREEN_CUT_OFF_RATIO) && - (global.screen_height >= WIDE_SCREEN_MINIMUM_HEIGHT); + let primary = global.get_primary_monitor(); + wideScreen = (primary.width/primary.height > WIDE_SCREEN_CUT_OFF_RATIO) && + (primary.height >= WIDE_SCREEN_MINIMUM_HEIGHT); // We divide the screen into an imaginary grid which helps us determine the layout of // different visual components. if (wideScreen) { - displayGridColumnWidth = global.screen_width / COLUMNS_WIDE_SCREEN; - displayGridRowHeight = global.screen_height / ROWS_WIDE_SCREEN; + displayGridColumnWidth = primary.width / COLUMNS_WIDE_SCREEN; + displayGridRowHeight = primary.height / ROWS_WIDE_SCREEN; } else { - displayGridColumnWidth = global.screen_width / COLUMNS_REGULAR_SCREEN; - displayGridRowHeight = global.screen_height / ROWS_REGULAR_SCREEN; + displayGridColumnWidth = primary.width / COLUMNS_REGULAR_SCREEN; + displayGridRowHeight = primary.height / ROWS_REGULAR_SCREEN; } }, relayout: function () { - let screenHeight = global.screen_height; - let screenWidth = global.screen_width; + let primary = global.get_primary_monitor(); + + this._group.set_position(primary.x, primary.y); let contentY = Panel.PANEL_HEIGHT; - let contentHeight = screenHeight - contentY; + let contentHeight = primary.height - contentY; this._coverPane.set_position(0, contentY); - this._coverPane.set_size(screenWidth, contentHeight); + this._coverPane.set_size(primary.width, contentHeight); let workspaceColumnsUsed = wideScreen ? COLUMNS_FOR_WORKSPACES_WIDE_SCREEN : COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN; let workspaceRowsUsed = wideScreen ? ROWS_FOR_WORKSPACES_WIDE_SCREEN : ROWS_FOR_WORKSPACES_REGULAR_SCREEN; this._workspacesWidth = displayGridColumnWidth * workspaceColumnsUsed - WORKSPACE_GRID_PADDING * 2; - // We scale the vertical padding by (screenHeight / screenWidth) + // We scale the vertical padding by (primary.height / primary.width) // so that the workspace preserves its aspect ratio. this._workspacesHeight = displayGridRowHeight * workspaceRowsUsed - - WORKSPACE_GRID_PADDING * (screenHeight / screenWidth) * 2; + - WORKSPACE_GRID_PADDING * (primary.height / primary.width) * 2; this._workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING; - this._workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (screenHeight / screenWidth); + this._workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (primary.height / primary.width); this._dash.actor.set_position(0, contentY); this._dash.actor.set_size(displayGridColumnWidth, contentHeight); @@ -187,10 +189,10 @@ Overview.prototype = { // place the 'Add Workspace' button in the bottom row of the grid addRemoveButtonSize = Math.floor(displayGridRowHeight * 3/5); this._addButtonX = this._workspacesX + this._workspacesWidth - addRemoveButtonSize; - this._addButtonY = screenHeight - Math.floor(displayGridRowHeight * 4/5); + this._addButtonY = primary.height - Math.floor(displayGridRowHeight * 4/5); - this._backOver.set_position(0, contentY); - this._backOver.set_size(global.screen_width, contentHeight); + this._backOver.set_position(0, 0); + this._backOver.set_size(global.screen_width, global.screen_height); this._paneContainer.set_position(this._dash.actor.x + this._dash.actor.width + DEFAULT_PADDING, contentY); @@ -198,7 +200,7 @@ Overview.prototype = { this._paneContainer.height = contentHeight; this._transparentBackground.set_position(this._paneContainer.x, this._paneContainer.y); - this._transparentBackground.set_size(global.screen_width - this._paneContainer.x, + this._transparentBackground.set_size(primary.width - this._paneContainer.x, this._paneContainer.height); if (this._activeDisplayPane != null) diff --git a/js/ui/runDialog.js b/js/ui/runDialog.js index 4ffeb0f9f..473375bb7 100644 --- a/js/ui/runDialog.js +++ b/js/ui/runDialog.js @@ -60,24 +60,26 @@ RunDialog.prototype = { // All actors are inside _group. We create it initially // hidden then show it in show() - this._group = new Clutter.Group({ visible: false }); + this._group = new Clutter.Group({ visible: false, + x: 0, + y: 0, + width: global.screen_width, + height: global.screen_height }); global.stage.add_actor(this._group); - this._lightbox = new Lightbox.Lightbox(this._group); + let lightbox = new Lightbox.Lightbox(this._group); - let boxH = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, - x_align: Big.BoxAlignment.CENTER, - y_align: Big.BoxAlignment.CENTER, - width: global.screen_width, - height: global.screen_height }); + this._boxH = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, + x_align: Big.BoxAlignment.CENTER, + y_align: Big.BoxAlignment.CENTER }); - this._group.add_actor(boxH); - this._lightbox.highlight(boxH); + this._group.add_actor(this._boxH); + lightbox.highlight(this._boxH); let boxV = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, y_align: Big.BoxAlignment.CENTER }); - boxH.append(boxV, Big.BoxPackFlags.NONE); + this._boxH.append(boxV, Big.BoxPackFlags.NONE); let dialogBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, @@ -87,7 +89,7 @@ RunDialog.prototype = { padding: DIALOG_PADDING, width: DIALOG_WIDTH }); - boxH.append(dialogBox, Big.BoxPackFlags.NONE); + this._boxH.append(dialogBox, Big.BoxPackFlags.NONE); let label = new Clutter.Text({ color: BOX_TEXT_COLOR, font_name: '18px Sans', @@ -182,6 +184,12 @@ RunDialog.prototype = { if (!Main.pushModal(this._group)) return; + // Position the dialog on the current monitor + let monitor = global.get_focus_monitor(); + + this._boxH.set_position(monitor.x, monitor.y); + this._boxH.set_size(monitor.width, monitor.height); + this._isOpen = true; this._group.show(); diff --git a/src/shell-global.c b/src/shell-global.c index 727957046..3d05c68ec 100644 --- a/src/shell-global.c +++ b/src/shell-global.c @@ -869,3 +869,99 @@ shell_global_create_root_pixmap_actor (ShellGlobal *global) return clutter_clone_new (global->root_pixmap); } + +/** + * shell_global_get_monitors: + * @global: the #ShellGlobal + * + * Gets a list of the bounding boxes of the active screen's monitors. + * + * Return value: (transfer full) (element-type GdkRectangle): a list + * of monitor bounding boxes. + */ +GSList * +shell_global_get_monitors (ShellGlobal *global) +{ + MetaScreen *screen = shell_global_get_screen (global); + GSList *monitors = NULL; + MetaRectangle rect; + int i; + + g_assert (sizeof (MetaRectangle) == sizeof (GdkRectangle) && + G_STRUCT_OFFSET (MetaRectangle, x) == G_STRUCT_OFFSET (GdkRectangle, x) && + G_STRUCT_OFFSET (MetaRectangle, y) == G_STRUCT_OFFSET (GdkRectangle, y) && + G_STRUCT_OFFSET (MetaRectangle, width) == G_STRUCT_OFFSET (GdkRectangle, width) && + G_STRUCT_OFFSET (MetaRectangle, height) == G_STRUCT_OFFSET (GdkRectangle, height)); + + for (i = meta_screen_get_n_monitors (screen) - 1; i >= 0; i--) + { + meta_screen_get_monitor_geometry (screen, i, &rect); + monitors = g_slist_prepend (monitors, + g_boxed_copy (GDK_TYPE_RECTANGLE, &rect)); + } + return monitors; +} + +/** + * shell_global_get_primary_monitor: + * @global: the #ShellGlobal + * + * Gets the bounding box of the primary monitor (the one that the + * panel is on). + * + * Return value: the bounding box of the primary monitor + */ +GdkRectangle * +shell_global_get_primary_monitor (ShellGlobal *global) +{ + MetaScreen *screen = shell_global_get_screen (global); + MetaRectangle rect; + + g_assert (sizeof (MetaRectangle) == sizeof (GdkRectangle) && + G_STRUCT_OFFSET (MetaRectangle, x) == G_STRUCT_OFFSET (GdkRectangle, x) && + G_STRUCT_OFFSET (MetaRectangle, y) == G_STRUCT_OFFSET (GdkRectangle, y) && + G_STRUCT_OFFSET (MetaRectangle, width) == G_STRUCT_OFFSET (GdkRectangle, width) && + G_STRUCT_OFFSET (MetaRectangle, height) == G_STRUCT_OFFSET (GdkRectangle, height)); + + meta_screen_get_monitor_geometry (screen, 0, &rect); + return g_boxed_copy (GDK_TYPE_RECTANGLE, &rect); +} + +/** + * shell_global_get_focus_monitor: + * @global: the #ShellGlobal + * + * Gets the bounding box of the monitor containing the window that + * currently contains the keyboard focus. + * + * Return value: the bounding box of the focus monitor + */ +GdkRectangle * +shell_global_get_focus_monitor (ShellGlobal *global) +{ + MetaScreen *screen = shell_global_get_screen (global); + MetaDisplay *display = meta_screen_get_display (screen); + MetaWindow *focus = meta_display_get_focus_window (display); + MetaRectangle rect, wrect; + int nmonitors, i; + + if (focus) + { + meta_window_get_outer_rect (focus, &wrect); + nmonitors = meta_screen_get_n_monitors (screen); + + /* Find the monitor that the top-left corner of @focus is on. */ + for (i = 0; i < nmonitors; i++) + { + meta_screen_get_monitor_geometry (screen, i, &rect); + + if (rect.x < wrect.x && rect.y < wrect.y && + rect.x + rect.width > wrect.x && + rect.y + rect.height > wrect.y) + return g_boxed_copy (GDK_TYPE_RECTANGLE, &rect); + } + } + + meta_screen_get_monitor_geometry (screen, 0, &rect); + return g_boxed_copy (GDK_TYPE_RECTANGLE, &rect); +} diff --git a/src/shell-global.h b/src/shell-global.h index 998fef236..ca389ced1 100644 --- a/src/shell-global.h +++ b/src/shell-global.h @@ -73,6 +73,10 @@ void shell_global_format_time_relative_pretty (ShellGlobal *global, guint delta, ClutterActor *shell_global_create_root_pixmap_actor (ShellGlobal *global); +GSList *shell_global_get_monitors (ShellGlobal *global); +GdkRectangle *shell_global_get_primary_monitor (ShellGlobal *global); +GdkRectangle *shell_global_get_focus_monitor (ShellGlobal *global); + G_END_DECLS #endif /* __SHELL_GLOBAL_H__ */