Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 057e5bb0c1 | |||
| 07fc66765d | |||
| daa7b9b6ab |
@@ -1,6 +1,6 @@
|
|||||||
3.27.1
|
3.26.2
|
||||||
======
|
======
|
||||||
* updated translations (ca@valencia)
|
* updated translations: (ca@valencia)
|
||||||
|
|
||||||
3.26.1
|
3.26.1
|
||||||
======
|
======
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
AC_PREREQ(2.63)
|
AC_PREREQ(2.63)
|
||||||
AC_INIT([gnome-shell-extensions],[3.27.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&component=extensions])
|
AC_INIT([gnome-shell-extensions],[3.26.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&component=extensions])
|
||||||
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AC_CONFIG_AUX_DIR([config])
|
AC_CONFIG_AUX_DIR([config])
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const ActivitiesMenuItem = new Lang.Class({
|
|||||||
Extends: PopupMenu.PopupBaseMenuItem,
|
Extends: PopupMenu.PopupBaseMenuItem,
|
||||||
|
|
||||||
_init: function(button) {
|
_init: function(button) {
|
||||||
this.parent();
|
this.parent();
|
||||||
this._button = button;
|
this._button = button;
|
||||||
this.actor.add_child(new St.Label({ text: _("Activities Overview") }));
|
this.actor.add_child(new St.Label({ text: _("Activities Overview") }));
|
||||||
},
|
},
|
||||||
@@ -44,7 +44,7 @@ const ActivitiesMenuItem = new Lang.Class({
|
|||||||
activate: function(event) {
|
activate: function(event) {
|
||||||
this._button.menu.toggle();
|
this._button.menu.toggle();
|
||||||
Main.overview.toggle();
|
Main.overview.toggle();
|
||||||
this.parent(event);
|
this.parent(event);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -53,8 +53,8 @@ const ApplicationMenuItem = new Lang.Class({
|
|||||||
Extends: PopupMenu.PopupBaseMenuItem,
|
Extends: PopupMenu.PopupBaseMenuItem,
|
||||||
|
|
||||||
_init: function(button, app) {
|
_init: function(button, app) {
|
||||||
this.parent();
|
this.parent();
|
||||||
this._app = app;
|
this._app = app;
|
||||||
this._button = button;
|
this._button = button;
|
||||||
|
|
||||||
this._iconBin = new St.Bin();
|
this._iconBin = new St.Bin();
|
||||||
@@ -93,10 +93,10 @@ const ApplicationMenuItem = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
activate: function(event) {
|
activate: function(event) {
|
||||||
this._app.open_new_window(-1);
|
this._app.open_new_window(-1);
|
||||||
this._button.selectCategory(null, null);
|
this._button.selectCategory(null, null);
|
||||||
this._button.menu.toggle();
|
this._button.menu.toggle();
|
||||||
this.parent(event);
|
this.parent(event);
|
||||||
},
|
},
|
||||||
|
|
||||||
setActive: function(active, params) {
|
setActive: function(active, params) {
|
||||||
@@ -127,8 +127,8 @@ const CategoryMenuItem = new Lang.Class({
|
|||||||
Extends: PopupMenu.PopupBaseMenuItem,
|
Extends: PopupMenu.PopupBaseMenuItem,
|
||||||
|
|
||||||
_init: function(button, category) {
|
_init: function(button, category) {
|
||||||
this.parent();
|
this.parent();
|
||||||
this._category = category;
|
this._category = category;
|
||||||
this._button = button;
|
this._button = button;
|
||||||
|
|
||||||
this._oldX = -1;
|
this._oldX = -1;
|
||||||
@@ -147,7 +147,7 @@ const CategoryMenuItem = new Lang.Class({
|
|||||||
activate: function(event) {
|
activate: function(event) {
|
||||||
this._button.selectCategory(this._category, this);
|
this._button.selectCategory(this._category, this);
|
||||||
this._button.scrollToCatButton(this);
|
this._button.scrollToCatButton(this);
|
||||||
this.parent(event);
|
this.parent(event);
|
||||||
},
|
},
|
||||||
|
|
||||||
_isNavigatingSubmenu: function([x, y]) {
|
_isNavigatingSubmenu: function([x, y]) {
|
||||||
@@ -249,7 +249,7 @@ const ApplicationsMenu = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
isEmpty: function() {
|
isEmpty: function() {
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
open: function(animate) {
|
open: function(animate) {
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
|
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
|
||||||
// Start apps on custom workspaces
|
// Start apps on custom workspaces
|
||||||
|
|
||||||
const GdkPixbuf = imports.gi.GdkPixbuf;
|
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
const GObject = imports.gi.GObject;
|
||||||
const GMenu = imports.gi.GMenu;
|
|
||||||
const Gtk = imports.gi.Gtk;
|
const Gtk = imports.gi.Gtk;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Mainloop = imports.mainloop;
|
|
||||||
|
|
||||||
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
||||||
const _ = Gettext.gettext;
|
const _ = Gettext.gettext;
|
||||||
|
|||||||
@@ -1,7 +1,24 @@
|
|||||||
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
|
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
|
||||||
|
// import just everything from workspace.js:
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Gio = imports.gi.Gio;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
const Meta = imports.gi.Meta;
|
||||||
|
const Pango = imports.gi.Pango;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const St = imports.gi.St;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
|
||||||
|
const DND = imports.ui.dnd;
|
||||||
|
const Lightbox = imports.ui.lightbox;
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const Overview = imports.ui.overview;
|
||||||
|
const Panel = imports.ui.panel;
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
const Workspace = imports.ui.workspace;
|
const Workspace = imports.ui.workspace;
|
||||||
|
const WindowPositionFlags = Workspace.WindowPositionFlags;
|
||||||
|
|
||||||
const ExtensionUtils = imports.misc.extensionUtils;
|
const ExtensionUtils = imports.misc.extensionUtils;
|
||||||
const Me = ExtensionUtils.getCurrentExtension();
|
const Me = ExtensionUtils.getCurrentExtension();
|
||||||
@@ -14,6 +31,25 @@ const WINDOW_PLACEMENT_NATURAL_ACCURACY = 20; // accuracy
|
|||||||
const WINDOW_PLACEMENT_NATURAL_GAPS = 5; // half of the minimum gap between windows
|
const WINDOW_PLACEMENT_NATURAL_GAPS = 5; // half of the minimum gap between windows
|
||||||
const WINDOW_PLACEMENT_NATURAL_MAX_TRANSLATIONS = 5000; // safety limit for preventing endless loop if something is wrong in the algorithm
|
const WINDOW_PLACEMENT_NATURAL_MAX_TRANSLATIONS = 5000; // safety limit for preventing endless loop if something is wrong in the algorithm
|
||||||
|
|
||||||
|
const PLACE_WINDOW_CAPTIONS_ON_TOP = true; // place window titles in overview on top of windows with overlap parameter
|
||||||
|
|
||||||
|
const WORKSPACE_BORDER_GAP = 10; // minimum gap between the workspace area and the workspace selector
|
||||||
|
const WINDOW_AREA_TOP_GAP = 20; // minimum gap between the workspace area and the top border. This keeps window captions and close buttons visible. 13px (26/2) should currently be enough.
|
||||||
|
|
||||||
|
const BUTTON_LAYOUT_SCHEMA = 'org.gnome.desktop.wm.preferences';
|
||||||
|
const BUTTON_LAYOUT_KEY = 'button-layout';
|
||||||
|
|
||||||
|
function injectToFunction(parent, name, func) {
|
||||||
|
let origin = parent[name];
|
||||||
|
parent[name] = function() {
|
||||||
|
let ret;
|
||||||
|
ret = origin.apply(this, arguments);
|
||||||
|
if (ret === undefined)
|
||||||
|
ret = func.apply(this, arguments);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const Rect = new Lang.Class({
|
const Rect = new Lang.Class({
|
||||||
Name: 'NativeWindowPlacement.Rect',
|
Name: 'NativeWindowPlacement.Rect',
|
||||||
|
|
||||||
@@ -74,31 +110,40 @@ const Rect = new Lang.Class({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const NaturalLayoutStrategy = new Lang.Class({
|
let winInjections, workspaceInjections, connectedSignals;
|
||||||
Name: 'NaturalLayoutStrategy',
|
|
||||||
Extends: Workspace.LayoutStrategy,
|
|
||||||
|
|
||||||
_init: function(settings) {
|
function resetState() {
|
||||||
this._settings = settings;
|
winInjections = { };
|
||||||
},
|
workspaceInjections = { };
|
||||||
|
connectedSignals = [ ];
|
||||||
|
}
|
||||||
|
|
||||||
computeLayout: function(windows, layout) {
|
function enable() {
|
||||||
layout.windows = windows;
|
resetState();
|
||||||
},
|
|
||||||
|
let settings = Convenience.getSettings();
|
||||||
|
let useMoreScreen = settings.get_boolean('use-more-screen');
|
||||||
|
let windowCaptionsOnTop = settings.get_boolean('window-captions-on-top');
|
||||||
|
let signalId = settings.connect('changed::use-more-screen', function() {
|
||||||
|
useMoreScreen = settings.get_boolean('use-more-screen');
|
||||||
|
});
|
||||||
|
connectedSignals.push({ obj: settings, id: signalId });
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* _calculateWindowTransformationsNatural:
|
||||||
|
* @clones: Array of #MetaWindow
|
||||||
|
*
|
||||||
* Returns clones with matching target coordinates and scales to arrange windows in a natural way that no overlap exists and relative window size is preserved.
|
* Returns clones with matching target coordinates and scales to arrange windows in a natural way that no overlap exists and relative window size is preserved.
|
||||||
* This function is almost a 1:1 copy of the function
|
* This function is almost a 1:1 copy of the function
|
||||||
* PresentWindowsEffect::calculateWindowTransformationsNatural() from KDE, see:
|
* PresentWindowsEffect::calculateWindowTransformationsNatural() from KDE, see:
|
||||||
* https://projects.kde.org/projects/kde/kdebase/kde-workspace/repository/revisions/master/entry/kwin/effects/presentwindows/presentwindows.cpp
|
* https://projects.kde.org/projects/kde/kdebase/kde-workspace/repository/revisions/master/entry/kwin/effects/presentwindows/presentwindows.cpp
|
||||||
*/
|
*/
|
||||||
computeWindowSlots: function(layout, area) {
|
Workspace.Workspace.prototype._calculateWindowTransformationsNatural = function(clones, area) {
|
||||||
// As we are using pseudo-random movement (See "slot") we need to make sure the list
|
// As we are using pseudo-random movement (See "slot") we need to make sure the list
|
||||||
// is always sorted the same way no matter which window is currently active.
|
// is always sorted the same way no matter which window is currently active.
|
||||||
|
|
||||||
let area_rect = new Rect(area.x, area.y, area.width, area.height);
|
let area_rect = new Rect(area.x, area.y, area.width, area.height);
|
||||||
let bounds = area_rect.copy();
|
let bounds = area_rect.copy();
|
||||||
let clones = layout.windows;
|
|
||||||
|
|
||||||
let direction = 0;
|
let direction = 0;
|
||||||
let directions = [];
|
let directions = [];
|
||||||
@@ -156,7 +201,7 @@ const NaturalLayoutStrategy = new Lang.Class({
|
|||||||
rects[j].translate(diff[0], diff[1]);
|
rects[j].translate(diff[0], diff[1]);
|
||||||
|
|
||||||
|
|
||||||
if (this._settings.get_boolean('use-more-screen')) {
|
if (useMoreScreen) {
|
||||||
// Try to keep the bounding rect the same aspect as the screen so that more
|
// Try to keep the bounding rect the same aspect as the screen so that more
|
||||||
// screen real estate is utilised. We do this by splitting the screen into nine
|
// screen real estate is utilised. We do this by splitting the screen into nine
|
||||||
// equal sections, if the window center is in any of the corner sections pull the
|
// equal sections, if the window center is in any of the corner sections pull the
|
||||||
@@ -246,39 +291,157 @@ const NaturalLayoutStrategy = new Lang.Class({
|
|||||||
|
|
||||||
return slots;
|
return slots;
|
||||||
}
|
}
|
||||||
});
|
workspaceInjections['_calculateWindowTransformationsNatural'] = undefined;
|
||||||
|
|
||||||
let winInjections, workspaceInjections;
|
/**
|
||||||
|
* _updateWindowPositions:
|
||||||
|
* @flags:
|
||||||
|
* INITIAL - this is the initial positioning of the windows.
|
||||||
|
* ANIMATE - Indicates that we need animate changing position.
|
||||||
|
*/
|
||||||
|
workspaceInjections['_updateWindowPositions'] = Workspace.Workspace.prototype._updateWindowPositions;
|
||||||
|
Workspace.Workspace.prototype._updateWindowPositions = function(flags) {
|
||||||
|
if (this._currentLayout == null) {
|
||||||
|
this._recalculateWindowPositions(flags);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
function resetState() {
|
let initialPositioning = flags & WindowPositionFlags.INITIAL;
|
||||||
winInjections = { };
|
let animate = flags & WindowPositionFlags.ANIMATE;
|
||||||
workspaceInjections = { };
|
|
||||||
}
|
|
||||||
|
|
||||||
function enable() {
|
let layout = this._currentLayout;
|
||||||
resetState();
|
let strategy = layout.strategy;
|
||||||
|
|
||||||
let settings = Convenience.getSettings();
|
let [, , padding] = this._getSpacingAndPadding();
|
||||||
|
let area = Workspace.padArea(this._actualGeometry, padding);
|
||||||
|
|
||||||
workspaceInjections['_getBestLayout'] = Workspace.Workspace.prototype._getBestLayout;
|
/// EDIT replace this version by our own:
|
||||||
Workspace.Workspace.prototype._getBestLayout = function(windows) {
|
//let slots = strategy.computeWindowSlots(layout, area);
|
||||||
let strategy = new NaturalLayoutStrategy(settings);
|
|
||||||
let layout = { strategy };
|
|
||||||
strategy.computeLayout(windows, layout);
|
|
||||||
|
|
||||||
return layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// position window titles on top of windows in overlay ////
|
/// EDIT copied from _realRecalculateWindowPositions:
|
||||||
winInjections['relayout'] = Workspace.WindowOverlay.prototype.relayout;
|
let clones = this._windows.slice();
|
||||||
Workspace.WindowOverlay.prototype.relayout = function(animate) {
|
if (clones.length == 0)
|
||||||
if (settings.get_boolean('window-captions-on-top')) {
|
return;
|
||||||
let [, , , cloneHeight] = this._windowClone.slot;
|
|
||||||
this.title.translation_y = -cloneHeight;
|
clones.sort(function(a, b) {
|
||||||
|
return a.metaWindow.get_stable_sequence() - b.metaWindow.get_stable_sequence();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this._reservedSlot)
|
||||||
|
clones.push(this._reservedSlot);
|
||||||
|
|
||||||
|
/// EDIT our own window placement function:
|
||||||
|
let slots = this._calculateWindowTransformationsNatural(clones, area);
|
||||||
|
|
||||||
|
|
||||||
|
let currentWorkspace = global.screen.get_active_workspace();
|
||||||
|
let isOnCurrentWorkspace = this.metaWorkspace == null || this.metaWorkspace == currentWorkspace;
|
||||||
|
|
||||||
|
for (let i = 0; i < slots.length; i++) {
|
||||||
|
let slot = slots[i];
|
||||||
|
let [x, y, scale, clone] = slot;
|
||||||
|
let metaWindow = clone.metaWindow;
|
||||||
|
let overlay = clone.overlay;
|
||||||
|
clone.slotId = i;
|
||||||
|
|
||||||
|
// Positioning a window currently being dragged must be avoided;
|
||||||
|
// we'll just leave a blank spot in the layout for it.
|
||||||
|
if (clone.inDrag)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
let cloneWidth = clone.actor.width * scale;
|
||||||
|
let cloneHeight = clone.actor.height * scale;
|
||||||
|
clone.slot = [x, y, cloneWidth, cloneHeight];
|
||||||
|
|
||||||
|
if (overlay && (initialPositioning || !clone.positioned))
|
||||||
|
overlay.hide();
|
||||||
|
|
||||||
|
if (!clone.positioned) {
|
||||||
|
// This window appeared after the overview was already up
|
||||||
|
// Grow the clone from the center of the slot
|
||||||
|
clone.actor.x = x + cloneWidth / 2;
|
||||||
|
clone.actor.y = y + cloneHeight / 2;
|
||||||
|
clone.actor.scale_x = 0;
|
||||||
|
clone.actor.scale_y = 0;
|
||||||
|
clone.positioned = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animate && isOnCurrentWorkspace) {
|
||||||
|
if (!metaWindow.showing_on_its_workspace()) {
|
||||||
|
/* Hidden windows should fade in and grow
|
||||||
|
* therefore we need to resize them now so they
|
||||||
|
* can be scaled up later */
|
||||||
|
if (initialPositioning) {
|
||||||
|
clone.actor.opacity = 0;
|
||||||
|
clone.actor.scale_x = 0;
|
||||||
|
clone.actor.scale_y = 0;
|
||||||
|
clone.actor.x = x;
|
||||||
|
clone.actor.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tweener.addTween(clone.actor,
|
||||||
|
{ opacity: 255,
|
||||||
|
time: Overview.ANIMATION_TIME,
|
||||||
|
transition: 'easeInQuad'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this._animateClone(clone, overlay, x, y, scale, initialPositioning);
|
||||||
|
} else {
|
||||||
|
// cancel any active tweens (otherwise they might override our changes)
|
||||||
|
Tweener.removeTweens(clone.actor);
|
||||||
|
clone.actor.set_position(x, y);
|
||||||
|
clone.actor.set_scale(scale, scale);
|
||||||
|
clone.overlay.relayout(false);
|
||||||
|
this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
winInjections['relayout'].call(this, animate);
|
|
||||||
};
|
|
||||||
|
/// position window titles on top of windows in overlay ////
|
||||||
|
if (windowCaptionsOnTop) {
|
||||||
|
|
||||||
|
/// This is almost a direct copy of the original relayout function. Differences are marked.
|
||||||
|
winInjections['relayout'] = Workspace.WindowOverlay.prototype.relayout;
|
||||||
|
Workspace.WindowOverlay.prototype.relayout = function(animate) {
|
||||||
|
winInjections['relayout'].call(this, animate);
|
||||||
|
let title = this.title;
|
||||||
|
let border = this.border;
|
||||||
|
|
||||||
|
this._parentActor.set_child_above_sibling(title, border);
|
||||||
|
|
||||||
|
Tweener.removeTweens(title);
|
||||||
|
|
||||||
|
let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot;
|
||||||
|
|
||||||
|
// Clutter.Actor.get_preferred_width() will return the fixed width if one
|
||||||
|
// is set, so we need to reset the width by calling set_width(-1), to forward
|
||||||
|
// the call down to StLabel.
|
||||||
|
// We also need to save and restore the current width, otherwise the animation
|
||||||
|
// starts from the wrong point.
|
||||||
|
let prevTitleWidth = title.width;
|
||||||
|
title.set_width(-1);
|
||||||
|
let [titleMinWidth, titleNatWidth] = title.get_preferred_width(-1);
|
||||||
|
let titleWidth = Math.max(titleMinWidth, Math.min(titleNatWidth, cloneWidth));
|
||||||
|
title.width = prevTitleWidth;
|
||||||
|
|
||||||
|
let titleX = cloneX + (cloneWidth - titleWidth) / 2;
|
||||||
|
|
||||||
|
/// this is the actual difference to original gnome-shell:
|
||||||
|
//let titleY = cloneY + cloneHeight - (title.height - this.borderSize) / 2;
|
||||||
|
let titleY = cloneY - (title.height - this.borderSize) / 2;
|
||||||
|
|
||||||
|
if (animate)
|
||||||
|
this._animateOverlayActor(title, Math.floor(titleX), Math.floor(titleY), titleWidth);
|
||||||
|
else {
|
||||||
|
title.width = titleWidth;
|
||||||
|
title.set_position(Math.floor(titleX), Math.floor(titleY));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeInjection(object, injection, name) {
|
function removeInjection(object, injection, name) {
|
||||||
@@ -296,6 +459,9 @@ function disable() {
|
|||||||
for (i in winInjections)
|
for (i in winInjections)
|
||||||
removeInjection(Workspace.WindowOverlay.prototype, winInjections, i);
|
removeInjection(Workspace.WindowOverlay.prototype, winInjections, i);
|
||||||
|
|
||||||
|
for each (i in connectedSignals)
|
||||||
|
i.obj.disconnect(i.id);
|
||||||
|
|
||||||
global.stage.queue_relayout();
|
global.stage.queue_relayout();
|
||||||
resetState();
|
resetState();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user