Track fullscreen status per-monitor in Chrome
This is required since we can have chrome on multiple monitors (due to per-monitor hot-corners). Windows are primary associated with the monitor that their center is on. https://bugzilla.gnome.org/show_bug.cgi?id=642881
This commit is contained in:
parent
7cf311dac0
commit
885f668d53
127
js/ui/chrome.js
127
js/ui/chrome.js
@ -31,11 +31,13 @@ Chrome.prototype = {
|
|||||||
Main.uiGroup.add_actor(this.actor);
|
Main.uiGroup.add_actor(this.actor);
|
||||||
this.actor.connect('allocate', Lang.bind(this, this._allocated));
|
this.actor.connect('allocate', Lang.bind(this, this._allocated));
|
||||||
|
|
||||||
this._inFullscreen = false;
|
this._monitors = [];
|
||||||
this._inOverview = false;
|
this._inOverview = false;
|
||||||
|
|
||||||
this._trackedActors = [];
|
this._trackedActors = [];
|
||||||
|
|
||||||
|
global.gdk_screen.connect('monitors-changed',
|
||||||
|
Lang.bind(this, this._monitorsChanged));
|
||||||
global.screen.connect('restacked',
|
global.screen.connect('restacked',
|
||||||
Lang.bind(this, this._windowsRestacked));
|
Lang.bind(this, this._windowsRestacked));
|
||||||
|
|
||||||
@ -48,6 +50,8 @@ Chrome.prototype = {
|
|||||||
Main.overview.connect('hidden',
|
Main.overview.connect('hidden',
|
||||||
Lang.bind(this, this._overviewHidden));
|
Lang.bind(this, this._overviewHidden));
|
||||||
|
|
||||||
|
this._updateMonitors();
|
||||||
|
this._updateFullscreen();
|
||||||
this._queueUpdateRegions();
|
this._queueUpdateRegions();
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -187,7 +191,8 @@ Chrome.prototype = {
|
|||||||
let actorData = this._trackedActors[i];
|
let actorData = this._trackedActors[i];
|
||||||
if (this._inOverview && !actorData.visibleInOverview)
|
if (this._inOverview && !actorData.visibleInOverview)
|
||||||
this.actor.set_skip_paint(actorData.actor, true);
|
this.actor.set_skip_paint(actorData.actor, true);
|
||||||
else if (!this._inOverview && this._inFullscreen && !actorData.visibleInFullscreen)
|
else if (!this._inOverview && !actorData.visibleInFullscreen &&
|
||||||
|
this._findMonitorForActor(actorData.actor).inFullscreen)
|
||||||
this.actor.set_skip_paint(actorData.actor, true);
|
this.actor.set_skip_paint(actorData.actor, true);
|
||||||
else
|
else
|
||||||
this.actor.set_skip_paint(actorData.actor, false);
|
this.actor.set_skip_paint(actorData.actor, false);
|
||||||
@ -206,15 +211,77 @@ Chrome.prototype = {
|
|||||||
this._queueUpdateRegions();
|
this._queueUpdateRegions();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_updateMonitors: function() {
|
||||||
|
let monitors = global.get_monitors();
|
||||||
|
let primary = global.get_primary_monitor();
|
||||||
|
this._monitors = monitors;
|
||||||
|
for (let i = 0; i < monitors.length; i++) {
|
||||||
|
let monitor = monitors[i];
|
||||||
|
if (monitor.x == primary.x &&
|
||||||
|
monitor.y == primary.y &&
|
||||||
|
monitor.width == primary.width &&
|
||||||
|
monitor.height == primary.height)
|
||||||
|
this._primaryMonitor = monitor;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_findMonitorForRect: function(x, y, w, h) {
|
||||||
|
// First look at what monitor the center of the rectangle is at
|
||||||
|
let cx = x + w/2;
|
||||||
|
let cy = y + h/2;
|
||||||
|
for (let i = 0; i < this._monitors.length; i++) {
|
||||||
|
let monitor = this._monitors[i];
|
||||||
|
if (cx >= monitor.x && cx < monitor.x + monitor.width &&
|
||||||
|
cy >= monitor.y && cy < monitor.y + monitor.height)
|
||||||
|
return monitor;
|
||||||
|
}
|
||||||
|
// If the center is not on a monitor, return the first overlapping monitor
|
||||||
|
for (let i = 0; i < this._monitors.length; i++) {
|
||||||
|
let monitor = this._monitors[i];
|
||||||
|
if (x + w > monitor.x && x < monitor.x + monitor.width &&
|
||||||
|
y + h > monitor.y && y < monitor.y + monitor.height)
|
||||||
|
return monitor;
|
||||||
|
}
|
||||||
|
// otherwise on no monitor
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
_findMonitorForWindow: function(window) {
|
||||||
|
return this._findMonitorForRect(window.x, window.y, window.width, window.height);
|
||||||
|
},
|
||||||
|
|
||||||
|
// This call guarantees that we return some monitor to simplify usage of it
|
||||||
|
// In practice all tracked actors should be visible on some monitor anyway
|
||||||
|
_findMonitorForActor: function(actor) {
|
||||||
|
let [x, y] = actor.get_transformed_position();
|
||||||
|
let [w, h] = actor.get_transformed_size();
|
||||||
|
let monitor = this._findMonitorForRect(x, y, w, h);
|
||||||
|
if (monitor)
|
||||||
|
return monitor;
|
||||||
|
return this._primaryMonitor; // Not on any monitor, pretend its on the primary
|
||||||
|
},
|
||||||
|
|
||||||
|
_monitorsChanged: function() {
|
||||||
|
this._updateMonitors();
|
||||||
|
|
||||||
|
// Update everything that depends on monitor positions
|
||||||
|
this._updateFullscreen();
|
||||||
|
this._updateVisibility();
|
||||||
|
this._queueUpdateRegions();
|
||||||
|
},
|
||||||
|
|
||||||
_queueUpdateRegions: function() {
|
_queueUpdateRegions: function() {
|
||||||
if (!this._updateRegionIdle)
|
if (!this._updateRegionIdle)
|
||||||
this._updateRegionIdle = Mainloop.idle_add(Lang.bind(this, this._updateRegions),
|
this._updateRegionIdle = Mainloop.idle_add(Lang.bind(this, this._updateRegions),
|
||||||
Meta.PRIORITY_BEFORE_REDRAW);
|
Meta.PRIORITY_BEFORE_REDRAW);
|
||||||
},
|
},
|
||||||
|
|
||||||
_windowsRestacked: function() {
|
_updateFullscreen: function() {
|
||||||
let windows = Main.getWindowActorsForWorkspace(global.screen.get_active_workspace_index());
|
let windows = Main.getWindowActorsForWorkspace(global.screen.get_active_workspace_index());
|
||||||
let primary = global.get_primary_monitor();
|
|
||||||
|
// Reset all monitors to not fullscreen
|
||||||
|
for (let i = 0; i < this._monitors.length; i++)
|
||||||
|
this._monitors[i].inFullscreen = false;
|
||||||
|
|
||||||
// The chrome layer should be visible unless there is a window
|
// The chrome layer should be visible unless there is a window
|
||||||
// with layer FULLSCREEN, or a window with layer
|
// with layer FULLSCREEN, or a window with layer
|
||||||
@ -228,39 +295,43 @@ Chrome.prototype = {
|
|||||||
|
|
||||||
// @windows is sorted bottom to top.
|
// @windows is sorted bottom to top.
|
||||||
|
|
||||||
let wasInFullscreen = this._inFullscreen;
|
|
||||||
this._inFullscreen = false;
|
|
||||||
for (let i = windows.length - 1; i > -1; i--) {
|
for (let i = windows.length - 1; i > -1; i--) {
|
||||||
let layer = windows[i].get_meta_window().get_layer();
|
let window = windows[i];
|
||||||
|
let layer = window.get_meta_window().get_layer();
|
||||||
// There are 3 cases we check here for:
|
|
||||||
// 1.) Monitor sized window
|
|
||||||
// 2.) Window with a position somewhere on the primary screen having the _NET_WM_FULLSCREEN flag set
|
|
||||||
// 3.) Window that is partly off screen (tries to hide its decorations) which might have negative coords
|
|
||||||
// We check for 1.) and 2.) by checking if the upper right corner is on the primary monitor, but avoid the case
|
|
||||||
// where it overlaps with the secondary screen (like window.x + window.width == primary.x + primary.width)
|
|
||||||
// For 3.) we just ignore negative values as they don't really make sense
|
|
||||||
|
|
||||||
if (layer == Meta.StackLayer.FULLSCREEN) {
|
if (layer == Meta.StackLayer.FULLSCREEN) {
|
||||||
if (Math.max(windows[i].x, 0) >= primary.x && Math.max(windows[i].x, 0) < primary.x + primary.width &&
|
let monitor = this._findMonitorForWindow(window);
|
||||||
Math.max(windows[i].y, 0) >= primary.y && Math.max(windows[i].y, 0) < primary.y + primary.height) {
|
if (monitor)
|
||||||
this._inFullscreen = true;
|
monitor.inFullscreen = true;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (layer == Meta.StackLayer.OVERRIDE_REDIRECT) {
|
if (layer == Meta.StackLayer.OVERRIDE_REDIRECT) {
|
||||||
if (windows[i].x <= primary.x &&
|
let monitor = this._findMonitorForWindow(window);
|
||||||
windows[i].x + windows[i].width >= primary.x + primary.width &&
|
if (monitor &&
|
||||||
windows[i].y <= primary.y &&
|
window.x <= monitor.x &&
|
||||||
windows[i].y + windows[i].height >= primary.y + primary.height) {
|
window.x + window.width >= monitor.x + monitor.width &&
|
||||||
this._inFullscreen = true;
|
window.y <= monitor.y &&
|
||||||
break;
|
window.y + window.height >= monitor.y + monitor.height)
|
||||||
}
|
monitor.inFullscreen = true;
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
if (this._inFullscreen != wasInFullscreen) {
|
_windowsRestacked: function() {
|
||||||
|
let wasInFullscreen = [];
|
||||||
|
for (let i = 0; i < this._monitors.length; i++)
|
||||||
|
wasInFullscreen[i] = this._monitors[i].inFullscreen;
|
||||||
|
|
||||||
|
this._updateFullscreen();
|
||||||
|
|
||||||
|
let changed = false;
|
||||||
|
for (let i = 0; i < wasInFullscreen.length; i++) {
|
||||||
|
if (wasInFullscreen[i] != this._monitors[i].inFullscreen) {
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
this._updateVisibility();
|
this._updateVisibility();
|
||||||
this._queueUpdateRegions();
|
this._queueUpdateRegions();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user