Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f840f70052 | ||
|
|
ef99394ffb | ||
|
|
778eebc421 | ||
|
|
97d1cbca19 | ||
|
|
a0cae3d130 | ||
|
|
01893ca048 | ||
|
|
c86a67823c |
4
NEWS
4
NEWS
@@ -1,6 +1,6 @@
|
||||
3.26.2
|
||||
3.27.1
|
||||
======
|
||||
* updated translations: (ca@valencia)
|
||||
* updated translations (ca@valencia)
|
||||
|
||||
3.26.1
|
||||
======
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
AC_PREREQ(2.63)
|
||||
AC_INIT([gnome-shell-extensions],[3.26.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&component=extensions])
|
||||
AC_INIT([gnome-shell-extensions],[3.27.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&component=extensions])
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_AUX_DIR([config])
|
||||
|
||||
@@ -36,7 +36,7 @@ const ActivitiesMenuItem = new Lang.Class({
|
||||
Extends: PopupMenu.PopupBaseMenuItem,
|
||||
|
||||
_init: function(button) {
|
||||
this.parent();
|
||||
this.parent();
|
||||
this._button = button;
|
||||
this.actor.add_child(new St.Label({ text: _("Activities Overview") }));
|
||||
},
|
||||
@@ -44,7 +44,7 @@ const ActivitiesMenuItem = new Lang.Class({
|
||||
activate: function(event) {
|
||||
this._button.menu.toggle();
|
||||
Main.overview.toggle();
|
||||
this.parent(event);
|
||||
this.parent(event);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -53,8 +53,8 @@ const ApplicationMenuItem = new Lang.Class({
|
||||
Extends: PopupMenu.PopupBaseMenuItem,
|
||||
|
||||
_init: function(button, app) {
|
||||
this.parent();
|
||||
this._app = app;
|
||||
this.parent();
|
||||
this._app = app;
|
||||
this._button = button;
|
||||
|
||||
this._iconBin = new St.Bin();
|
||||
@@ -93,10 +93,10 @@ const ApplicationMenuItem = new Lang.Class({
|
||||
},
|
||||
|
||||
activate: function(event) {
|
||||
this._app.open_new_window(-1);
|
||||
this._app.open_new_window(-1);
|
||||
this._button.selectCategory(null, null);
|
||||
this._button.menu.toggle();
|
||||
this.parent(event);
|
||||
this.parent(event);
|
||||
},
|
||||
|
||||
setActive: function(active, params) {
|
||||
@@ -127,8 +127,8 @@ const CategoryMenuItem = new Lang.Class({
|
||||
Extends: PopupMenu.PopupBaseMenuItem,
|
||||
|
||||
_init: function(button, category) {
|
||||
this.parent();
|
||||
this._category = category;
|
||||
this.parent();
|
||||
this._category = category;
|
||||
this._button = button;
|
||||
|
||||
this._oldX = -1;
|
||||
@@ -147,7 +147,7 @@ const CategoryMenuItem = new Lang.Class({
|
||||
activate: function(event) {
|
||||
this._button.selectCategory(this._category, this);
|
||||
this._button.scrollToCatButton(this);
|
||||
this.parent(event);
|
||||
this.parent(event);
|
||||
},
|
||||
|
||||
_isNavigatingSubmenu: function([x, y]) {
|
||||
@@ -249,7 +249,7 @@ const ApplicationsMenu = new Lang.Class({
|
||||
},
|
||||
|
||||
isEmpty: function() {
|
||||
return false;
|
||||
return false;
|
||||
},
|
||||
|
||||
open: function(animate) {
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
|
||||
// Start apps on custom workspaces
|
||||
|
||||
const GdkPixbuf = imports.gi.GdkPixbuf;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const GMenu = imports.gi.GMenu;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
@@ -1,24 +1,7 @@
|
||||
// -*- 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 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 WindowPositionFlags = Workspace.WindowPositionFlags;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Me = ExtensionUtils.getCurrentExtension();
|
||||
@@ -31,25 +14,6 @@ const WINDOW_PLACEMENT_NATURAL_ACCURACY = 20; // accuracy
|
||||
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 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({
|
||||
Name: 'NativeWindowPlacement.Rect',
|
||||
|
||||
@@ -110,40 +74,31 @@ const Rect = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
let winInjections, workspaceInjections, connectedSignals;
|
||||
const NaturalLayoutStrategy = new Lang.Class({
|
||||
Name: 'NaturalLayoutStrategy',
|
||||
Extends: Workspace.LayoutStrategy,
|
||||
|
||||
function resetState() {
|
||||
winInjections = { };
|
||||
workspaceInjections = { };
|
||||
connectedSignals = [ ];
|
||||
}
|
||||
_init: function(settings) {
|
||||
this._settings = settings;
|
||||
},
|
||||
|
||||
function enable() {
|
||||
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 });
|
||||
computeLayout: function(windows, layout) {
|
||||
layout.windows = windows;
|
||||
},
|
||||
|
||||
/**
|
||||
* _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.
|
||||
* This function is almost a 1:1 copy of the function
|
||||
* PresentWindowsEffect::calculateWindowTransformationsNatural() from KDE, see:
|
||||
* https://projects.kde.org/projects/kde/kdebase/kde-workspace/repository/revisions/master/entry/kwin/effects/presentwindows/presentwindows.cpp
|
||||
*/
|
||||
Workspace.Workspace.prototype._calculateWindowTransformationsNatural = function(clones, area) {
|
||||
computeWindowSlots: function(layout, area) {
|
||||
// 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.
|
||||
|
||||
let area_rect = new Rect(area.x, area.y, area.width, area.height);
|
||||
let bounds = area_rect.copy();
|
||||
let clones = layout.windows;
|
||||
|
||||
let direction = 0;
|
||||
let directions = [];
|
||||
@@ -201,7 +156,7 @@ function enable() {
|
||||
rects[j].translate(diff[0], diff[1]);
|
||||
|
||||
|
||||
if (useMoreScreen) {
|
||||
if (this._settings.get_boolean('use-more-screen')) {
|
||||
// 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
|
||||
// equal sections, if the window center is in any of the corner sections pull the
|
||||
@@ -291,157 +246,39 @@ function enable() {
|
||||
|
||||
return slots;
|
||||
}
|
||||
workspaceInjections['_calculateWindowTransformationsNatural'] = undefined;
|
||||
});
|
||||
|
||||
/**
|
||||
* _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;
|
||||
}
|
||||
let winInjections, workspaceInjections;
|
||||
|
||||
let initialPositioning = flags & WindowPositionFlags.INITIAL;
|
||||
let animate = flags & WindowPositionFlags.ANIMATE;
|
||||
function resetState() {
|
||||
winInjections = { };
|
||||
workspaceInjections = { };
|
||||
}
|
||||
|
||||
let layout = this._currentLayout;
|
||||
let strategy = layout.strategy;
|
||||
function enable() {
|
||||
resetState();
|
||||
|
||||
let [, , padding] = this._getSpacingAndPadding();
|
||||
let area = Workspace.padArea(this._actualGeometry, padding);
|
||||
|
||||
/// EDIT replace this version by our own:
|
||||
//let slots = strategy.computeWindowSlots(layout, area);
|
||||
|
||||
|
||||
/// EDIT copied from _realRecalculateWindowPositions:
|
||||
let clones = this._windows.slice();
|
||||
if (clones.length == 0)
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
let settings = Convenience.getSettings();
|
||||
|
||||
workspaceInjections['_getBestLayout'] = Workspace.Workspace.prototype._getBestLayout;
|
||||
Workspace.Workspace.prototype._getBestLayout = function(windows) {
|
||||
let strategy = new NaturalLayoutStrategy(settings);
|
||||
let layout = { strategy };
|
||||
strategy.computeLayout(windows, layout);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
/// position window titles on top of windows in overlay ////
|
||||
if (windowCaptionsOnTop) {
|
||||
winInjections['relayout'] = Workspace.WindowOverlay.prototype.relayout;
|
||||
Workspace.WindowOverlay.prototype.relayout = function(animate) {
|
||||
if (settings.get_boolean('window-captions-on-top')) {
|
||||
let [, , , cloneHeight] = this._windowClone.slot;
|
||||
this.title.translation_y = -cloneHeight;
|
||||
}
|
||||
|
||||
/// 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));
|
||||
}
|
||||
};
|
||||
}
|
||||
winInjections['relayout'].call(this, animate);
|
||||
};
|
||||
}
|
||||
|
||||
function removeInjection(object, injection, name) {
|
||||
@@ -459,9 +296,6 @@ function disable() {
|
||||
for (i in winInjections)
|
||||
removeInjection(Workspace.WindowOverlay.prototype, winInjections, i);
|
||||
|
||||
for each (i in connectedSignals)
|
||||
i.obj.disconnect(i.id);
|
||||
|
||||
global.stage.queue_relayout();
|
||||
resetState();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user