Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a41bcd4f10 | ||
|
|
1a13f29b0c | ||
|
|
b6a6de9bb5 | ||
|
|
5b7631898c | ||
|
|
f8bae05036 | ||
|
|
60c75e5fcf | ||
|
|
c6d2063f4d | ||
|
|
52f373fb70 | ||
|
|
283a1ec5c2 | ||
|
|
c516f05927 | ||
|
|
e836a9e5e0 | ||
|
|
d1674c5f75 | ||
|
|
9fa283877c | ||
|
|
f1a154207f | ||
|
|
5b07dfded9 | ||
|
|
9f9dbd579b | ||
|
|
c9477dd94d | ||
|
|
5a30ebe403 | ||
|
|
a5f347ba10 | ||
|
|
dab326c17e | ||
|
|
bdf6af3ee3 | ||
|
|
1532c15325 | ||
|
|
cbd1b7d983 | ||
|
|
4b9c53ff2e | ||
|
|
6eb3a62e2b | ||
|
|
0469fc6aa9 | ||
|
|
1f6f22010e | ||
|
|
ae1b17d29c | ||
|
|
3fa750ce17 | ||
|
|
56e2a570e3 | ||
|
|
167f0be6b4 | ||
|
|
80eb29bd51 | ||
|
|
f2b261c573 | ||
|
|
6c49ca825c | ||
|
|
6a25971366 | ||
|
|
dc3523a344 | ||
|
|
2ef6dba0a5 | ||
|
|
92db87f7cb | ||
|
|
82d2011061 | ||
|
|
545b811562 | ||
|
|
d99d0a06bd | ||
|
|
6105eecff2 | ||
|
|
d1254d9b57 | ||
|
|
2db4589dea | ||
|
|
dfeb99fc0a |
19
NEWS
19
NEWS
@@ -1,3 +1,22 @@
|
||||
3.33.4
|
||||
======
|
||||
* Make GNOME Classic more classic:
|
||||
- Disable GNOME 3 overview [Florian; !69]
|
||||
- Add window picker button to window list [Florian; !73, !80]
|
||||
- Style improvements and fixes [Jakub; #169, !82]
|
||||
- Support horizontal workspace layout in window list [Florian; !70]
|
||||
- Add draggable previews to window list workspace switcher [Florian; !74]
|
||||
- Arrange workspaces horizontally [Florian; !72]
|
||||
* workspace-indicator: Support horizontal workspace layout [Florian; !71]
|
||||
* workspace-indicator: Add draggable previews [Florian; !77]
|
||||
* Misc. bug fixes and cleanups [Florian; !75, !76, !79, !78, #168, !84]
|
||||
|
||||
Contributors:
|
||||
Florian Müllner, Jakub Steiner, Jor Teron
|
||||
|
||||
Translators:
|
||||
Jor Teron [mjw]
|
||||
|
||||
3.33.3
|
||||
======
|
||||
* Misc. bug fixes [Florian, Marco; !67, !68]
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
{
|
||||
"parentMode": "user",
|
||||
"stylesheetName": "gnome-classic.css",
|
||||
"hasOverview": false,
|
||||
"enabledExtensions": [@CLASSIC_EXTENSIONS@],
|
||||
"panel": { "left": ["activities", "appMenu"],
|
||||
"panel": { "left": ["appMenu"],
|
||||
"center": [],
|
||||
"right": ["a11y", "keyboard", "dateMenu", "aggregateMenu"]
|
||||
}
|
||||
|
||||
@@ -32,18 +32,20 @@ $variant: 'light';
|
||||
font-weight: normal;
|
||||
color: $fg_color;
|
||||
text-shadow: none;
|
||||
&:active, &:overview, &:focus, &:checked {
|
||||
// Trick due to St limitations. It needs a background to draw
|
||||
// a box-shadow
|
||||
background-color: $selected_bg_color !important;
|
||||
color: $selected_fg_color !important;
|
||||
box-shadow: none;
|
||||
& > .system-status-icon { icon-shadow: none; }
|
||||
}
|
||||
&:hover {
|
||||
color: lighten($fg_color,10%);
|
||||
text-shadow: none;
|
||||
& .system-status-icon { icon-shadow: none; }
|
||||
}
|
||||
&:active, &:overview, &:focus, &:checked {
|
||||
// Trick due to St limitations. It needs a background to draw
|
||||
// a box-shadow
|
||||
background-color: $selected_bg_color;
|
||||
color: $selected_fg_color;
|
||||
box-shadow: none;
|
||||
& > .system-status-icon { icon-shadow: none; }
|
||||
}
|
||||
|
||||
.app-menu-icon { width: 0; height: 0; margin: 0; } // shell's display:none; :D
|
||||
|
||||
.system-status-icon {
|
||||
@@ -91,15 +93,3 @@ $variant: 'light';
|
||||
background-image: url("calendar-today.svg");
|
||||
}
|
||||
|
||||
.message-list-clear-button.button {
|
||||
color: $fg_color
|
||||
}
|
||||
|
||||
.notification-banner {
|
||||
background-color: $bg_color !important;
|
||||
color: $fg_color;
|
||||
.notification-button {
|
||||
background-color: darken($bg_color,5%);
|
||||
&:hover, &focus { background-color: darken($bg_color,2%); }
|
||||
}
|
||||
}
|
||||
|
||||
Submodule data/gnome-shell-sass updated: c5df33dda7...478d47a177
@@ -4,17 +4,17 @@
|
||||
const {
|
||||
Atk, Clutter, Gio, GLib, GMenu, GObject, Gtk, Meta, Shell, St
|
||||
} = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const DND = imports.ui.dnd;
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
|
||||
const appSys = Shell.AppSystem.get_default();
|
||||
|
||||
const APPLICATION_ICON_SIZE = 32;
|
||||
@@ -25,21 +25,6 @@ const NAVIGATION_REGION_OVERSHOOT = 50;
|
||||
Gio._promisify(Gio._LocalFilePrototype, 'query_info_async', 'query_info_finish');
|
||||
Gio._promisify(Gio._LocalFilePrototype, 'set_attributes_async', 'set_attributes_finish');
|
||||
|
||||
var ActivitiesMenuItem = GObject.registerClass(
|
||||
class ActivitiesMenuItem extends PopupMenu.PopupBaseMenuItem {
|
||||
_init(button) {
|
||||
super._init();
|
||||
this._button = button;
|
||||
this.add_child(new St.Label({ text: _('Activities Overview') }));
|
||||
}
|
||||
|
||||
activate(event) {
|
||||
this._button.menu.toggle();
|
||||
Main.overview.toggle();
|
||||
super.activate(event);
|
||||
}
|
||||
});
|
||||
|
||||
var ApplicationMenuItem = GObject.registerClass(
|
||||
class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem {
|
||||
_init(button, app) {
|
||||
@@ -82,6 +67,8 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem {
|
||||
this._button.selectCategory(null);
|
||||
this._button.menu.toggle();
|
||||
super.activate(event);
|
||||
|
||||
Main.overview.hide();
|
||||
}
|
||||
|
||||
setActive(active, params) {
|
||||
@@ -103,7 +90,9 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem {
|
||||
}
|
||||
|
||||
_updateIcon() {
|
||||
this._iconBin.set_child(this.getDragActor());
|
||||
let icon = this.getDragActor();
|
||||
icon.style_class = 'icon-dropshadow';
|
||||
this._iconBin.set_child(icon);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -233,28 +222,9 @@ class ApplicationsMenu extends PopupMenu.PopupMenu {
|
||||
return false;
|
||||
}
|
||||
|
||||
open(animate) {
|
||||
this._button.hotCorner.setBarrierSize(0);
|
||||
if (this._button.hotCorner.actor) // fallback corner
|
||||
this._button.hotCorner.actor.hide();
|
||||
super.open(animate);
|
||||
}
|
||||
|
||||
close(animate) {
|
||||
let size = Main.layoutManager.panelBox.height;
|
||||
this._button.hotCorner.setBarrierSize(size);
|
||||
if (this._button.hotCorner.actor) // fallback corner
|
||||
this._button.hotCorner.actor.show();
|
||||
super.close(animate);
|
||||
}
|
||||
|
||||
toggle() {
|
||||
if (this.isOpen) {
|
||||
if (this.isOpen)
|
||||
this._button.selectCategory(null);
|
||||
} else {
|
||||
if (Main.overview.visible)
|
||||
Main.overview.hide();
|
||||
}
|
||||
super.toggle();
|
||||
}
|
||||
}
|
||||
@@ -406,8 +376,6 @@ class ApplicationsButton extends PanelMenu.Button {
|
||||
this.name = 'panelApplications';
|
||||
this.label_actor = this._label;
|
||||
|
||||
this.connect('captured-event', this._onCapturedEvent.bind(this));
|
||||
|
||||
this._showingId = Main.overview.connect('showing', () => {
|
||||
this.add_accessible_state (Atk.StateType.CHECKED);
|
||||
});
|
||||
@@ -449,10 +417,6 @@ class ApplicationsButton extends PanelMenu.Button {
|
||||
}
|
||||
}
|
||||
|
||||
get hotCorner() {
|
||||
return Main.layoutManager.hotCorners[Main.layoutManager.primaryIndex];
|
||||
}
|
||||
|
||||
_createVertSeparator() {
|
||||
let separator = new St.DrawingArea({
|
||||
style_class: 'calendar-vertical-separator',
|
||||
@@ -463,6 +427,8 @@ class ApplicationsButton extends PanelMenu.Button {
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
super._onDestroy();
|
||||
|
||||
Main.overview.disconnect(this._showingId);
|
||||
Main.overview.disconnect(this._hidingId);
|
||||
appSys.disconnect(this._installedChangedId);
|
||||
@@ -478,14 +444,6 @@ class ApplicationsButton extends PanelMenu.Button {
|
||||
this._desktopTarget.destroy();
|
||||
}
|
||||
|
||||
_onCapturedEvent(actor, event) {
|
||||
if (event.type() == Clutter.EventType.BUTTON_PRESS) {
|
||||
if (!Main.overview.shouldToggleByCornerOrButton())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
_onMenuKeyPress(actor, event) {
|
||||
let symbol = event.get_key_symbol();
|
||||
if (symbol == Clutter.KEY_Left || symbol == Clutter.KEY_Right) {
|
||||
@@ -628,14 +586,6 @@ class ApplicationsButton extends PanelMenu.Button {
|
||||
y_align: St.Align.START
|
||||
});
|
||||
|
||||
let activities = new ActivitiesMenuItem(this);
|
||||
this.leftBox.add(activities, {
|
||||
expand: false,
|
||||
x_fill: true,
|
||||
y_fill: false,
|
||||
y_align: St.Align.START
|
||||
});
|
||||
|
||||
this.applicationsBox = new St.BoxLayout({ vertical: true });
|
||||
this.applicationsScrollBox.add_actor(this.applicationsBox);
|
||||
this.categoriesBox = new St.BoxLayout({ vertical: true });
|
||||
@@ -747,19 +697,16 @@ class ApplicationsButton extends PanelMenu.Button {
|
||||
});
|
||||
|
||||
let appsMenuButton;
|
||||
let activitiesButton;
|
||||
|
||||
function enable() {
|
||||
activitiesButton = Main.panel.statusArea['activities'];
|
||||
activitiesButton.container.hide();
|
||||
appsMenuButton = new ApplicationsButton();
|
||||
Main.panel.addToStatusArea('apps-menu', appsMenuButton, 1, 'left');
|
||||
let index = Main.sessionMode.panel.left.indexOf('activities') + 1;
|
||||
Main.panel.addToStatusArea('apps-menu', appsMenuButton, index, 'left');
|
||||
}
|
||||
|
||||
function disable() {
|
||||
Main.panel.menuManager.removeMenu(appsMenuButton.menu);
|
||||
appsMenuButton.destroy();
|
||||
activitiesButton.container.show();
|
||||
}
|
||||
|
||||
function init() {
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
class WindowMover {
|
||||
constructor() {
|
||||
|
||||
@@ -5,13 +5,12 @@ const { Gio, GObject, Shell, St } = imports.gi;
|
||||
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const ShellMountOperation = imports.ui.shellMountOperation;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
|
||||
var MountMenuItem = GObject.registerClass(
|
||||
class MountMenuItem extends PopupMenu.PopupBaseMenuItem {
|
||||
_init(mount) {
|
||||
@@ -153,7 +152,7 @@ class DriveMenu extends PanelMenu.Button {
|
||||
}
|
||||
|
||||
_updateMenuVisibility() {
|
||||
if (this._mounts.filter(i => i.actor.visible).length > 0)
|
||||
if (this._mounts.filter(i => i.visible).length > 0)
|
||||
this.show();
|
||||
else
|
||||
this.hide();
|
||||
|
||||
38
extensions/horizontal-workspaces/extension.js
Normal file
38
extensions/horizontal-workspaces/extension.js
Normal file
@@ -0,0 +1,38 @@
|
||||
/* exported init */
|
||||
const { Meta } = imports.gi;
|
||||
|
||||
const { ThumbnailsBox } = imports.ui.workspaceThumbnail;
|
||||
|
||||
class Extension {
|
||||
constructor() {
|
||||
this._origUpdateSwitcherVisibility =
|
||||
ThumbnailsBox.prototype._updateSwitcherVisibility;
|
||||
}
|
||||
|
||||
enable() {
|
||||
global.workspace_manager.override_workspace_layout(
|
||||
Meta.DisplayCorner.TOPLEFT,
|
||||
false,
|
||||
1,
|
||||
-1);
|
||||
|
||||
ThumbnailsBox.prototype._updateSwitcherVisibility = function() {
|
||||
this.hide();
|
||||
};
|
||||
}
|
||||
|
||||
disable() {
|
||||
global.workspace_manager.override_workspace_layout(
|
||||
Meta.DisplayCorner.TOPLEFT,
|
||||
false,
|
||||
-1,
|
||||
1);
|
||||
|
||||
ThumbnailsBox.prototype._updateSwitcherVisibility =
|
||||
this._origUpdateSwitcherVisibility;
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
return new Extension();
|
||||
}
|
||||
5
extensions/horizontal-workspaces/meson.build
Normal file
5
extensions/horizontal-workspaces/meson.build
Normal file
@@ -0,0 +1,5 @@
|
||||
extension_data += configure_file(
|
||||
input: metadata_name + '.in',
|
||||
output: metadata_name,
|
||||
configuration: metadata_conf
|
||||
)
|
||||
10
extensions/horizontal-workspaces/metadata.json.in
Normal file
10
extensions/horizontal-workspaces/metadata.json.in
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extension-id": "@extension_id@",
|
||||
"uuid": "@uuid@",
|
||||
"settings-schema": "@gschemaname@",
|
||||
"gettext-domain": "@gettext_domain@",
|
||||
"name": "Horizontal workspaces",
|
||||
"description": "Use a horizontal workspace layout",
|
||||
"shell-version": [ "@shell_current@" ],
|
||||
"url": "@url@"
|
||||
}
|
||||
1
extensions/horizontal-workspaces/stylesheet.css
Normal file
1
extensions/horizontal-workspaces/stylesheet.css
Normal file
@@ -0,0 +1 @@
|
||||
/* This extensions requires no special styling */
|
||||
@@ -1,8 +1,7 @@
|
||||
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
|
||||
/* exported enable disable */
|
||||
const Workspace = imports.ui.workspace;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Workspace = imports.ui.workspace;
|
||||
|
||||
// testing settings for natural window placement strategy:
|
||||
const WINDOW_PLACEMENT_NATURAL_ACCURACY = 20; // accuracy of window translate moves (KDE-default: 20)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
const { Clutter, GObject, St } = imports.gi;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
@@ -11,7 +12,6 @@ const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
||||
const _ = Gettext.gettext;
|
||||
const N_ = x => x;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Me = ExtensionUtils.getCurrentExtension();
|
||||
const PlaceDisplay = Me.imports.placeDisplay;
|
||||
|
||||
@@ -136,9 +136,9 @@ let _indicator;
|
||||
function enable() {
|
||||
_indicator = new PlacesMenu;
|
||||
|
||||
let pos = 1;
|
||||
let pos = Main.sessionMode.panel.left.indexOf('appMenu');
|
||||
if ('apps-menu' in Main.panel.statusArea)
|
||||
pos = 2;
|
||||
pos++;
|
||||
Main.panel.addToStatusArea('places-menu', _indicator, pos, 'left');
|
||||
}
|
||||
|
||||
|
||||
@@ -21,11 +21,10 @@
|
||||
|
||||
const { Meta, Shell, St } = imports.gi;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
|
||||
const MESSAGE_FADE_TIME = 2;
|
||||
|
||||
let text;
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
/* exported init */
|
||||
|
||||
const { Gio, GLib } = imports.gi;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const SETTINGS_KEY = 'name';
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
|
||||
class ThemeManager {
|
||||
constructor() {
|
||||
this._settings = ExtensionUtils.getSettings();
|
||||
|
||||
@@ -4,36 +4,39 @@
|
||||
border-top-width: 1px;
|
||||
border-bottom-width: 0px;
|
||||
height: 2.25em ;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.bottom-panel .window-button > StWidget,
|
||||
.bottom-panel .window-picker-toggle > StWidget {
|
||||
color: #2e3436;
|
||||
background-color: #eee;
|
||||
border-radius: 3px;
|
||||
padding: 3px 6px 1px;
|
||||
box-shadow: none;
|
||||
text-shadow: none;
|
||||
border: 1px solid rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.bottom-panel .window-button > StWidget {
|
||||
background-gradient-drection: vertical;
|
||||
background-color: #fff;
|
||||
background-gradient-start: #fff;
|
||||
background-gradient-end: #eee;
|
||||
color: #000;
|
||||
-st-natural-width: 18.7em;
|
||||
max-width: 18.75em;
|
||||
color: #2e3436;
|
||||
background-color: #eee;
|
||||
border-radius: 2px;
|
||||
padding: 3px 6px 1px;
|
||||
box-shadow: inset -1px -1px 1px rgba(0,0,0,0.5);
|
||||
text-shadow: 0 0 transparent;
|
||||
}
|
||||
|
||||
.bottom-panel .window-button:hover > StWidget {
|
||||
.bottom-panel .window-button:hover > StWidget,
|
||||
.bottom-panel .window-picker-toggle:hover > StWidget {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.bottom-panel .window-button:active > StWidget,
|
||||
.bottom-panel .window-button:focus > StWidget {
|
||||
box-shadow: inset 1px 1px 2px rgba(0,0,0,0.5);
|
||||
box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.bottom-panel .window-button.focused > StWidget {
|
||||
background-color: #ddd;
|
||||
box-shadow: inset 1px 1px 1px rgba(0,0,0,0.5);
|
||||
.bottom-panel .window-button.focused > StWidget,
|
||||
.bottom-panel .window-picker-toggle:checked > StWidget {
|
||||
background-color: #ccc;
|
||||
box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.bottom-panel .window-button.focused:hover > StWidget {
|
||||
@@ -42,5 +45,24 @@
|
||||
|
||||
.bottom-panel .window-button.minimized > StWidget {
|
||||
color: #888;
|
||||
box-shadow: inset -1px -1px 1px rgba(0,0,0,0.5);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* workspace switcher */
|
||||
.window-list-workspace-indicator .workspace {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.window-list-workspace-indicator .workspace.active {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.window-list-window-preview {
|
||||
background-color: #ededed;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.window-list-window-preview.active {
|
||||
background-color: #f6f5f4;
|
||||
border: 2px solid #888;
|
||||
}
|
||||
|
||||
@@ -2,12 +2,15 @@
|
||||
const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell, St } = imports.gi;
|
||||
|
||||
const DND = imports.ui.dnd;
|
||||
const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Main = imports.ui.main;
|
||||
const Overview = imports.ui.overview;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const Me = ExtensionUtils.getCurrentExtension();
|
||||
const { WindowPicker, WindowPickerToggle } = Me.imports.windowPicker;
|
||||
const { WorkspaceIndicator } = Me.imports.workspaceIndicator;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
||||
const _ = Gettext.gettext;
|
||||
@@ -130,19 +133,22 @@ class WindowContextMenu extends PopupMenu.PopupMenu {
|
||||
}
|
||||
}
|
||||
|
||||
class WindowTitle {
|
||||
constructor(metaWindow) {
|
||||
const WindowTitle = GObject.registerClass({
|
||||
GTypeName: 'WindowListWindowTitle'
|
||||
}, class WindowTitle extends St.BoxLayout {
|
||||
_init(metaWindow) {
|
||||
this._metaWindow = metaWindow;
|
||||
this.actor = new St.BoxLayout({
|
||||
|
||||
super._init({
|
||||
style_class: 'window-button-box',
|
||||
x_expand: true,
|
||||
y_expand: true
|
||||
});
|
||||
|
||||
this._icon = new St.Bin({ style_class: 'window-button-icon' });
|
||||
this.actor.add(this._icon);
|
||||
this.add(this._icon);
|
||||
this.label_actor = new St.Label({ y_align: Clutter.ActorAlign.CENTER });
|
||||
this.actor.add(this.label_actor);
|
||||
this.add(this.label_actor);
|
||||
|
||||
this._textureCache = St.TextureCache.get_default();
|
||||
this._iconThemeChangedId = this._textureCache.connect(
|
||||
@@ -153,7 +159,7 @@ class WindowTitle {
|
||||
'notify::gtk-application-id', this._updateIcon.bind(this));
|
||||
this._updateIcon();
|
||||
|
||||
this.actor.connect('destroy', this._onDestroy.bind(this));
|
||||
this.connect('destroy', this._onDestroy.bind(this));
|
||||
|
||||
this._notifyTitleId = this._metaWindow.connect(
|
||||
'notify::title', this._updateTitle.bind(this));
|
||||
@@ -195,33 +201,32 @@ class WindowTitle {
|
||||
this._metaWindow.disconnect(this._notifyWmClass);
|
||||
this._metaWindow.disconnect(this._notifyAppId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
class BaseButton {
|
||||
constructor(perMonitor, monitorIndex) {
|
||||
if (this.constructor === BaseButton)
|
||||
throw new TypeError('Cannot instantiate abstract class BaseButton');
|
||||
|
||||
const BaseButton = GObject.registerClass({
|
||||
GTypeName: 'WindowListBaseButton',
|
||||
GTypeFlags: GObject.TypeFlags.ABSTRACT
|
||||
}, class BaseButton extends St.Button {
|
||||
_init(perMonitor, monitorIndex) {
|
||||
this._perMonitor = perMonitor;
|
||||
this._monitorIndex = monitorIndex;
|
||||
|
||||
this.actor = new St.Button({
|
||||
super._init({
|
||||
style_class: 'window-button',
|
||||
x_fill: true,
|
||||
y_fill: true,
|
||||
can_focus: true,
|
||||
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE
|
||||
});
|
||||
this.actor._delegate = this;
|
||||
|
||||
this.actor.connect('allocation-changed',
|
||||
this.connect('allocation-changed',
|
||||
this._updateIconGeometry.bind(this));
|
||||
this.actor.connect('clicked', this._onClicked.bind(this));
|
||||
this.actor.connect('destroy', this._onDestroy.bind(this));
|
||||
this.actor.connect('popup-menu', this._onPopupMenu.bind(this));
|
||||
this.connect('clicked', this._onClicked.bind(this));
|
||||
this.connect('destroy', this._onDestroy.bind(this));
|
||||
this.connect('popup-menu', this._onPopupMenu.bind(this));
|
||||
|
||||
this._contextMenuManager = new PopupMenu.PopupMenuManager(this.actor);
|
||||
this._contextMenuManager = new PopupMenu.PopupMenuManager(this);
|
||||
|
||||
this._switchWorkspaceId = global.window_manager.connect(
|
||||
'switch-workspace', this._updateVisibility.bind(this));
|
||||
@@ -237,18 +242,19 @@ class BaseButton {
|
||||
}
|
||||
|
||||
get active() {
|
||||
return this.actor.has_style_class_name('focused');
|
||||
return this.has_style_class_name('focused');
|
||||
}
|
||||
|
||||
activate() {
|
||||
if (this.active)
|
||||
return;
|
||||
|
||||
this._onClicked(this.actor, 1);
|
||||
this._onClicked(this, 1);
|
||||
}
|
||||
|
||||
_onClicked(_actor, _button) {
|
||||
throw new Error('Not implemented');
|
||||
throw new GObject.NotImplementedError(
|
||||
`_onClicked in ${this.constructor.name}`);
|
||||
}
|
||||
|
||||
_canOpenPopupMenu() {
|
||||
@@ -262,18 +268,20 @@ class BaseButton {
|
||||
}
|
||||
|
||||
_isFocused() {
|
||||
throw new Error('Not implemented');
|
||||
throw new GObject.NotImplementedError(
|
||||
`_isFocused in ${this.constructor.name}`);
|
||||
}
|
||||
|
||||
_updateStyle() {
|
||||
if (this._isFocused())
|
||||
this.actor.add_style_class_name('focused');
|
||||
this.add_style_class_name('focused');
|
||||
else
|
||||
this.actor.remove_style_class_name('focused');
|
||||
this.remove_style_class_name('focused');
|
||||
}
|
||||
|
||||
_windowEnteredOrLeftMonitor(_metaDisplay, _monitorIndex, _metaWindow) {
|
||||
throw new Error('Not implemented');
|
||||
throw new GObject.NotImplementedError(
|
||||
`_windowEnteredOrLeftMonitor in ${this.constructor.name}`);
|
||||
}
|
||||
|
||||
_isWindowVisible(window) {
|
||||
@@ -285,20 +293,22 @@ class BaseButton {
|
||||
}
|
||||
|
||||
_updateVisibility() {
|
||||
throw new Error('Not implemented');
|
||||
throw new GObject.NotImplementedError(
|
||||
`_updateVisibility in ${this.constructor.name}`);
|
||||
}
|
||||
|
||||
_getIconGeometry() {
|
||||
let rect = new Meta.Rectangle();
|
||||
|
||||
[rect.x, rect.y] = this.actor.get_transformed_position();
|
||||
[rect.width, rect.height] = this.actor.get_transformed_size();
|
||||
[rect.x, rect.y] = this.get_transformed_position();
|
||||
[rect.width, rect.height] = this.get_transformed_size();
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
_updateIconGeometry() {
|
||||
throw new Error('Not implemented');
|
||||
throw new GObject.NotImplementedError(
|
||||
`_updateIconGeometry in ${this.constructor.name}`);
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
@@ -312,21 +322,23 @@ class BaseButton {
|
||||
global.display.disconnect(this._windowLeftMonitorId);
|
||||
this._windowLeftMonitorId = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
class WindowButton extends BaseButton {
|
||||
constructor(metaWindow, perMonitor, monitorIndex) {
|
||||
super(perMonitor, monitorIndex);
|
||||
const WindowButton = GObject.registerClass({
|
||||
GTypeName: 'WindowListWindowButton'
|
||||
}, class WindowButton extends BaseButton {
|
||||
_init(metaWindow, perMonitor, monitorIndex) {
|
||||
super._init(perMonitor, monitorIndex);
|
||||
|
||||
this.metaWindow = metaWindow;
|
||||
this._updateVisibility();
|
||||
|
||||
this._windowTitle = new WindowTitle(this.metaWindow);
|
||||
this.actor.set_child(this._windowTitle.actor);
|
||||
this.actor.label_actor = this._windowTitle.label_actor;
|
||||
this.set_child(this._windowTitle);
|
||||
this.label_actor = this._windowTitle.label_actor;
|
||||
|
||||
this._contextMenu = new WindowContextMenu(this.actor, this.metaWindow);
|
||||
this._contextMenu = new WindowContextMenu(this, this.metaWindow);
|
||||
this._contextMenu.connect('open-state-changed', _onMenuStateChanged);
|
||||
this._contextMenu.actor.hide();
|
||||
this._contextMenuManager.addMenu(this._contextMenu);
|
||||
@@ -360,9 +372,9 @@ class WindowButton extends BaseButton {
|
||||
super._updateStyle();
|
||||
|
||||
if (this.metaWindow.minimized)
|
||||
this.actor.add_style_class_name('minimized');
|
||||
this.add_style_class_name('minimized');
|
||||
else
|
||||
this.actor.remove_style_class_name('minimized');
|
||||
this.remove_style_class_name('minimized');
|
||||
}
|
||||
|
||||
_windowEnteredOrLeftMonitor(metaDisplay, monitorIndex, metaWindow) {
|
||||
@@ -371,7 +383,7 @@ class WindowButton extends BaseButton {
|
||||
}
|
||||
|
||||
_updateVisibility() {
|
||||
this.actor.visible = this._isWindowVisible(this.metaWindow);
|
||||
this.visible = this._isWindowVisible(this.metaWindow);
|
||||
}
|
||||
|
||||
_updateIconGeometry() {
|
||||
@@ -384,14 +396,14 @@ class WindowButton extends BaseButton {
|
||||
global.display.disconnect(this._notifyFocusId);
|
||||
this._contextMenu.destroy();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
class AppContextMenu extends PopupMenu.PopupMenu {
|
||||
constructor(source, appButton) {
|
||||
constructor(source) {
|
||||
super(source, 0.5, St.Side.BOTTOM);
|
||||
|
||||
this._appButton = appButton;
|
||||
this._appButton = source;
|
||||
|
||||
this._minimizeItem = new PopupMenu.PopupMenuItem(_('Minimize all'));
|
||||
this._minimizeItem.connect('activate', () => {
|
||||
@@ -432,12 +444,12 @@ class AppContextMenu extends PopupMenu.PopupMenu {
|
||||
|
||||
open(animate) {
|
||||
let windows = this._appButton.getWindowList();
|
||||
this._minimizeItem.actor.visible = windows.some(w => !w.minimized);
|
||||
this._unminimizeItem.actor.visible = windows.some(w => w.minimized);
|
||||
this._maximizeItem.actor.visible = windows.some(w => {
|
||||
this._minimizeItem.visible = windows.some(w => !w.minimized);
|
||||
this._unminimizeItem.visible = windows.some(w => w.minimized);
|
||||
this._maximizeItem.visible = windows.some(w => {
|
||||
return w.get_maximized() != Meta.MaximizeFlags.BOTH;
|
||||
});
|
||||
this._unmaximizeItem.actor.visible = windows.some(w => {
|
||||
this._unmaximizeItem.visible = windows.some(w => {
|
||||
return w.get_maximized() == Meta.MaximizeFlags.BOTH;
|
||||
});
|
||||
|
||||
@@ -445,15 +457,17 @@ class AppContextMenu extends PopupMenu.PopupMenu {
|
||||
}
|
||||
}
|
||||
|
||||
class AppButton extends BaseButton {
|
||||
constructor(app, perMonitor, monitorIndex) {
|
||||
super(perMonitor, monitorIndex);
|
||||
const AppButton = GObject.registerClass({
|
||||
GTypeName: 'WindowListAppButton',
|
||||
}, class AppButton extends BaseButton {
|
||||
_init(app, perMonitor, monitorIndex) {
|
||||
super._init(perMonitor, monitorIndex);
|
||||
|
||||
this.app = app;
|
||||
this._updateVisibility();
|
||||
|
||||
let stack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
|
||||
this.actor.set_child(stack);
|
||||
this.set_child(stack);
|
||||
|
||||
this._singleWindowTitle = new St.Bin({
|
||||
x_expand: true,
|
||||
@@ -481,15 +495,15 @@ class AppButton extends BaseButton {
|
||||
this._multiWindowTitle.add(label);
|
||||
this._multiWindowTitle.label_actor = label;
|
||||
|
||||
this._menuManager = new PopupMenu.PopupMenuManager(this.actor);
|
||||
this._menu = new PopupMenu.PopupMenu(this.actor, 0.5, St.Side.BOTTOM);
|
||||
this._menuManager = new PopupMenu.PopupMenuManager(this);
|
||||
this._menu = new PopupMenu.PopupMenu(this, 0.5, St.Side.BOTTOM);
|
||||
this._menu.connect('open-state-changed', _onMenuStateChanged);
|
||||
this._menu.actor.hide();
|
||||
this._menu.connect('activate', this._onMenuActivate.bind(this));
|
||||
this._menuManager.addMenu(this._menu);
|
||||
Main.uiGroup.add_actor(this._menu.actor);
|
||||
|
||||
this._appContextMenu = new AppContextMenu(this.actor, this);
|
||||
this._appContextMenu = new AppContextMenu(this);
|
||||
this._appContextMenu.connect('open-state-changed', _onMenuStateChanged);
|
||||
this._appContextMenu.actor.hide();
|
||||
Main.uiGroup.add_actor(this._appContextMenu.actor);
|
||||
@@ -522,9 +536,9 @@ class AppButton extends BaseButton {
|
||||
if (!this._perMonitor) {
|
||||
// fast path: use ShellApp API to avoid iterating over all windows.
|
||||
let workspace = global.workspace_manager.get_active_workspace();
|
||||
this.actor.visible = this.app.is_on_workspace(workspace);
|
||||
this.visible = this.app.is_on_workspace(workspace);
|
||||
} else {
|
||||
this.actor.visible = this.getWindowList().length >= 1;
|
||||
this.visible = this.getWindowList().length >= 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,8 +566,8 @@ class AppButton extends BaseButton {
|
||||
if (!this._windowTitle) {
|
||||
this.metaWindow = windows[0];
|
||||
this._windowTitle = new WindowTitle(this.metaWindow);
|
||||
this._singleWindowTitle.child = this._windowTitle.actor;
|
||||
this._windowContextMenu = new WindowContextMenu(this.actor, this.metaWindow);
|
||||
this._singleWindowTitle.child = this._windowTitle;
|
||||
this._windowContextMenu = new WindowContextMenu(this, this.metaWindow);
|
||||
this._windowContextMenu.connect(
|
||||
'open-state-changed', _onMenuStateChanged);
|
||||
Main.uiGroup.add_actor(this._windowContextMenu.actor);
|
||||
@@ -562,7 +576,7 @@ class AppButton extends BaseButton {
|
||||
}
|
||||
this._contextMenuManager.removeMenu(this._appContextMenu);
|
||||
this._contextMenu = this._windowContextMenu;
|
||||
this.actor.label_actor = this._windowTitle.label_actor;
|
||||
this.label_actor = this._windowTitle.label_actor;
|
||||
} else {
|
||||
if (this._windowTitle) {
|
||||
this.metaWindow = null;
|
||||
@@ -573,7 +587,7 @@ class AppButton extends BaseButton {
|
||||
}
|
||||
this._contextMenu = this._appContextMenu;
|
||||
this._contextMenuManager.addMenu(this._appContextMenu);
|
||||
this.actor.label_actor = this._multiWindowTitle.label_actor;
|
||||
this.label_actor = this._multiWindowTitle.label_actor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -602,7 +616,7 @@ class AppButton extends BaseButton {
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
let windowTitle = new WindowTitle(windows[i]);
|
||||
let item = new PopupMenu.PopupBaseMenuItem();
|
||||
item.actor.add_actor(windowTitle.actor);
|
||||
item.add_actor(windowTitle);
|
||||
item._window = windows[i];
|
||||
this._menu.addMenuItem(item);
|
||||
}
|
||||
@@ -630,151 +644,33 @@ class AppButton extends BaseButton {
|
||||
this.app.disconnect(this._windowsChangedId);
|
||||
this._menu.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let WorkspaceIndicator = GObject.registerClass(
|
||||
class WorkspaceIndicator extends PanelMenu.Button {
|
||||
_init() {
|
||||
super._init(0.0, _('Workspace Indicator'), true);
|
||||
this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM));
|
||||
this.add_style_class_name('window-list-workspace-indicator');
|
||||
this.menu.actor.remove_style_class_name('panel-menu');
|
||||
|
||||
let container = new St.Widget({
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true,
|
||||
y_expand: true
|
||||
});
|
||||
this.add_actor(container);
|
||||
|
||||
let workspaceManager = global.workspace_manager;
|
||||
|
||||
this._currentWorkspace = workspaceManager.get_active_workspace().index();
|
||||
this.statusLabel = new St.Label({
|
||||
text: this._getStatusText(),
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.CENTER
|
||||
});
|
||||
container.add_actor(this.statusLabel);
|
||||
|
||||
this.workspacesItems = [];
|
||||
|
||||
this._workspaceManagerSignals = [
|
||||
workspaceManager.connect('notify::n-workspaces',
|
||||
this._updateMenu.bind(this)),
|
||||
workspaceManager.connect_after('workspace-switched',
|
||||
this._updateIndicator.bind(this))
|
||||
];
|
||||
|
||||
this.connect('scroll-event', this._onScrollEvent.bind(this));
|
||||
this._updateMenu();
|
||||
|
||||
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' });
|
||||
this._settingsChangedId = this._settings.connect(
|
||||
'changed::workspace-names', this._updateMenu.bind(this));
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
for (let i = 0; i < this._workspaceManagerSignals.length; i++)
|
||||
global.workspace_manager.disconnect(this._workspaceManagerSignals[i]);
|
||||
|
||||
if (this._settingsChangedId) {
|
||||
this._settings.disconnect(this._settingsChangedId);
|
||||
this._settingsChangedId = 0;
|
||||
}
|
||||
|
||||
super._onDestroy();
|
||||
}
|
||||
|
||||
_updateIndicator() {
|
||||
this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE);
|
||||
this._currentWorkspace = global.workspace_manager.get_active_workspace().index();
|
||||
this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT);
|
||||
|
||||
this.statusLabel.set_text(this._getStatusText());
|
||||
}
|
||||
|
||||
_getStatusText() {
|
||||
let workspaceManager = global.workspace_manager;
|
||||
let current = workspaceManager.get_active_workspace().index();
|
||||
let total = workspaceManager.n_workspaces;
|
||||
|
||||
return '%d / %d'.format(current + 1, total);
|
||||
}
|
||||
|
||||
_updateMenu() {
|
||||
let workspaceManager = global.workspace_manager;
|
||||
|
||||
this.menu.removeAll();
|
||||
this.workspacesItems = [];
|
||||
this._currentWorkspace = workspaceManager.get_active_workspace().index();
|
||||
|
||||
for (let i = 0; i < workspaceManager.n_workspaces; i++) {
|
||||
let name = Meta.prefs_get_workspace_name(i);
|
||||
let item = new PopupMenu.PopupMenuItem(name);
|
||||
item.workspaceId = i;
|
||||
|
||||
item.connect('activate', (item, _event) => {
|
||||
this._activate(item.workspaceId);
|
||||
});
|
||||
|
||||
if (i == this._currentWorkspace)
|
||||
item.setOrnament(PopupMenu.Ornament.DOT);
|
||||
|
||||
this.menu.addMenuItem(item);
|
||||
this.workspacesItems[i] = item;
|
||||
}
|
||||
|
||||
this.statusLabel.set_text(this._getStatusText());
|
||||
}
|
||||
|
||||
_activate(index) {
|
||||
let workspaceManager = global.workspace_manager;
|
||||
|
||||
if (index >= 0 && index < workspaceManager.n_workspaces) {
|
||||
let metaWorkspace = workspaceManager.get_workspace_by_index(index);
|
||||
metaWorkspace.activate(global.get_current_time());
|
||||
}
|
||||
}
|
||||
|
||||
_onScrollEvent(actor, event) {
|
||||
let direction = event.get_scroll_direction();
|
||||
let diff = 0;
|
||||
if (direction == Clutter.ScrollDirection.DOWN) {
|
||||
diff = 1;
|
||||
} else if (direction == Clutter.ScrollDirection.UP) {
|
||||
diff = -1;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
let newIndex = this._currentWorkspace + diff;
|
||||
this._activate(newIndex);
|
||||
}
|
||||
|
||||
_allocate(actor, box, flags) {
|
||||
if (actor.get_n_children() > 0)
|
||||
actor.get_first_child().allocate(box, flags);
|
||||
}
|
||||
});
|
||||
|
||||
class WindowList {
|
||||
constructor(perMonitor, monitor) {
|
||||
|
||||
const WindowList = GObject.registerClass({
|
||||
GTypeName: 'WindowListWindowList',
|
||||
}, class WindowList extends St.Widget {
|
||||
_init(perMonitor, monitor) {
|
||||
this._perMonitor = perMonitor;
|
||||
this._monitor = monitor;
|
||||
|
||||
this.actor = new St.Widget({
|
||||
super._init({
|
||||
name: 'panel',
|
||||
style_class: 'bottom-panel solid',
|
||||
reactive: true,
|
||||
track_hover: true,
|
||||
layout_manager: new Clutter.BinLayout()
|
||||
});
|
||||
this.actor.connect('destroy', this._onDestroy.bind(this));
|
||||
this.connect('destroy', this._onDestroy.bind(this));
|
||||
|
||||
let box = new St.BoxLayout({ x_expand: true, y_expand: true });
|
||||
this.actor.add_actor(box);
|
||||
this.add_actor(box);
|
||||
|
||||
let toggle = new WindowPickerToggle();
|
||||
box.add_actor(toggle);
|
||||
|
||||
toggle.connect('notify::checked',
|
||||
this._updateWindowListVisibility.bind(this));
|
||||
|
||||
let layout = new Clutter.BoxLayout({ homogeneous: true });
|
||||
this._windowList = new St.Widget({
|
||||
@@ -809,18 +705,18 @@ class WindowList {
|
||||
this._updateWorkspaceIndicatorVisibility.bind(this));
|
||||
this._updateWorkspaceIndicatorVisibility();
|
||||
|
||||
this._menuManager = new PopupMenu.PopupMenuManager(this.actor);
|
||||
this._menuManager = new PopupMenu.PopupMenuManager(this);
|
||||
this._menuManager.addMenu(this._workspaceIndicator.menu);
|
||||
|
||||
Main.layoutManager.addChrome(this.actor, {
|
||||
Main.layoutManager.addChrome(this, {
|
||||
affectsStruts: true,
|
||||
trackFullscreen: true
|
||||
});
|
||||
Main.uiGroup.set_child_above_sibling(this.actor, Main.layoutManager.panelBox);
|
||||
Main.ctrlAltTabManager.addGroup(this.actor, _('Window List'), 'start-here-symbolic');
|
||||
Main.uiGroup.set_child_above_sibling(this, Main.layoutManager.panelBox);
|
||||
Main.ctrlAltTabManager.addGroup(this, _('Window List'), 'start-here-symbolic');
|
||||
|
||||
this.actor.width = this._monitor.width;
|
||||
this.actor.connect('notify::height', this._updatePosition.bind(this));
|
||||
this.width = this._monitor.width;
|
||||
this.connect('notify::height', this._updatePosition.bind(this));
|
||||
this._updatePosition();
|
||||
|
||||
this._appSystem = Shell.AppSystem.get_default();
|
||||
@@ -835,10 +731,10 @@ class WindowList {
|
||||
keyboardBox.visible = state;
|
||||
if (state) {
|
||||
Main.uiGroup.set_child_above_sibling(
|
||||
this.actor, keyboardBox);
|
||||
this, keyboardBox);
|
||||
} else {
|
||||
Main.uiGroup.set_child_above_sibling(
|
||||
this.actor, Main.layoutManager.panelBox);
|
||||
this, Main.layoutManager.panelBox);
|
||||
}
|
||||
this._updateKeyboardAnchor();
|
||||
});
|
||||
@@ -854,12 +750,12 @@ class WindowList {
|
||||
'switch-workspace', this._checkGrouping.bind(this));
|
||||
|
||||
this._overviewShowingId = Main.overview.connect('showing', () => {
|
||||
this.actor.hide();
|
||||
this.hide();
|
||||
this._updateKeyboardAnchor();
|
||||
});
|
||||
|
||||
this._overviewHidingId = Main.overview.connect('hiding', () => {
|
||||
this.actor.visible = !Main.layoutManager.primaryMonitor.inFullscreen;
|
||||
this.visible = !Main.layoutManager.primaryMonitor.inFullscreen;
|
||||
this._updateKeyboardAnchor();
|
||||
});
|
||||
|
||||
@@ -897,17 +793,16 @@ class WindowList {
|
||||
return;
|
||||
|
||||
let children = this._windowList.get_children()
|
||||
.filter(c => c.visible)
|
||||
.map(a => a._delegate);
|
||||
.filter(c => c.visible);
|
||||
let active = children.findIndex(c => c.active);
|
||||
let newActive = Math.max(0, Math.min(active + diff, children.length - 1));
|
||||
children[newActive].activate();
|
||||
}
|
||||
|
||||
_updatePosition() {
|
||||
this.actor.set_position(
|
||||
this.set_position(
|
||||
this._monitor.x,
|
||||
this._monitor.y + this._monitor.height - this.actor.height);
|
||||
this._monitor.y + this._monitor.height - this.height);
|
||||
}
|
||||
|
||||
_updateWorkspaceIndicatorVisibility() {
|
||||
@@ -920,6 +815,19 @@ class WindowList {
|
||||
this._workspaceIndicator.visible = hasWorkspaces && workspacesOnMonitor;
|
||||
}
|
||||
|
||||
_updateWindowListVisibility() {
|
||||
let visible = !Main.windowPicker.visible;
|
||||
|
||||
Tweener.addTween(this._windowList, {
|
||||
opacity: visible ? 255 : 0,
|
||||
transition: 'ease-out-quad',
|
||||
time: Overview.ANIMATION_TIME
|
||||
});
|
||||
|
||||
this._windowList.reactive = visible;
|
||||
this._windowList.get_children().forEach(c => c.reactive = visible);
|
||||
}
|
||||
|
||||
_getPreferredUngroupedWindowListWidth() {
|
||||
if (this._windowList.get_n_children() == 0)
|
||||
return this._windowList.get_preferred_width(-1)[1];
|
||||
@@ -941,7 +849,7 @@ class WindowList {
|
||||
|
||||
_getMaxWindowListWidth() {
|
||||
let indicatorsBox = this._workspaceIndicator.get_parent();
|
||||
return this.actor.width - indicatorsBox.get_preferred_width(-1)[1];
|
||||
return this.width - indicatorsBox.get_preferred_width(-1)[1];
|
||||
}
|
||||
|
||||
_groupingModeChanged() {
|
||||
@@ -993,7 +901,7 @@ class WindowList {
|
||||
if (!Main.keyboard.actor)
|
||||
return;
|
||||
|
||||
let translationY = Main.overview.visible ? 0 : this.actor.height;
|
||||
let translationY = Main.overview.visible ? 0 : this.height;
|
||||
Main.keyboard.actor.translation_y = -translationY;
|
||||
}
|
||||
|
||||
@@ -1009,7 +917,7 @@ class WindowList {
|
||||
|
||||
_addApp(app) {
|
||||
let button = new AppButton(app, this._perMonitor, this._monitor.index);
|
||||
this._windowList.layout_manager.pack(button.actor,
|
||||
this._windowList.layout_manager.pack(button,
|
||||
true, true, true,
|
||||
Clutter.BoxAlignment.START,
|
||||
Clutter.BoxAlignment.START);
|
||||
@@ -1017,7 +925,7 @@ class WindowList {
|
||||
|
||||
_removeApp(app) {
|
||||
let children = this._windowList.get_children();
|
||||
let child = children.find(c => c._delegate.app == app);
|
||||
let child = children.find(c => c.app == app);
|
||||
if (child)
|
||||
child.destroy();
|
||||
}
|
||||
@@ -1033,11 +941,11 @@ class WindowList {
|
||||
return;
|
||||
|
||||
let children = this._windowList.get_children();
|
||||
if (children.find(c => c._delegate.metaWindow == win))
|
||||
if (children.find(c => c.metaWindow == win))
|
||||
return;
|
||||
|
||||
let button = new WindowButton(win, this._perMonitor, this._monitor.index);
|
||||
this._windowList.layout_manager.pack(button.actor,
|
||||
this._windowList.layout_manager.pack(button,
|
||||
true, true, true,
|
||||
Clutter.BoxAlignment.START,
|
||||
Clutter.BoxAlignment.START);
|
||||
@@ -1054,7 +962,7 @@ class WindowList {
|
||||
return; // not actually removed, just moved to another workspace
|
||||
|
||||
let children = this._windowList.get_children();
|
||||
let child = children.find(c => c._delegate.metaWindow == win);
|
||||
let child = children.find(c => c.metaWindow == win);
|
||||
if (child)
|
||||
child.destroy();
|
||||
}
|
||||
@@ -1103,15 +1011,12 @@ class WindowList {
|
||||
|
||||
_onDragMotion(dragEvent) {
|
||||
if (Main.overview.visible ||
|
||||
!this.actor.contains(dragEvent.targetActor)) {
|
||||
!this.contains(dragEvent.targetActor)) {
|
||||
this._removeActivateTimeout();
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
}
|
||||
|
||||
let hoveredWindow = null;
|
||||
if (dragEvent.targetActor._delegate)
|
||||
hoveredWindow = dragEvent.targetActor._delegate.metaWindow;
|
||||
|
||||
let hoveredWindow = dragEvent.targetActor.metaWindow;
|
||||
if (!hoveredWindow ||
|
||||
this._dndWindow == hoveredWindow)
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
@@ -1136,7 +1041,7 @@ class WindowList {
|
||||
let [x, y] = global.get_pointer();
|
||||
let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y);
|
||||
|
||||
if (this._dndWindow && this.actor.contains(pickedActor))
|
||||
if (this._dndWindow && this.contains(pickedActor))
|
||||
this._dndWindow.activate(global.get_current_time());
|
||||
this._dndWindow = null;
|
||||
this._dndTimeoutId = 0;
|
||||
@@ -1150,7 +1055,7 @@ class WindowList {
|
||||
|
||||
this._workspaceIndicator.destroy();
|
||||
|
||||
Main.ctrlAltTabManager.removeGroup(this.actor);
|
||||
Main.ctrlAltTabManager.removeGroup(this);
|
||||
|
||||
this._appSystem.disconnect(this._appStateChangedId);
|
||||
this._appStateChangedId = 0;
|
||||
@@ -1182,12 +1087,12 @@ class WindowList {
|
||||
for (let i = 0; i < windows.length; i++)
|
||||
windows[i].metaWindow.set_icon_geometry(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
class Extension {
|
||||
constructor() {
|
||||
this._windowLists = null;
|
||||
this._injections = {};
|
||||
this._hideOverviewOrig = Main.overview.hide;
|
||||
}
|
||||
|
||||
enable() {
|
||||
@@ -1200,11 +1105,18 @@ class Extension {
|
||||
this._monitorsChangedId = Main.layoutManager.connect(
|
||||
'monitors-changed', this._buildWindowLists.bind(this));
|
||||
|
||||
Main.windowPicker = new WindowPicker();
|
||||
|
||||
Main.overview.hide = () => {
|
||||
Main.windowPicker.close();
|
||||
this._hideOverviewOrig.call(Main.overview);
|
||||
};
|
||||
|
||||
this._buildWindowLists();
|
||||
}
|
||||
|
||||
_buildWindowLists() {
|
||||
this._windowLists.forEach(list => list.actor.destroy());
|
||||
this._windowLists.forEach(list => list.destroy());
|
||||
this._windowLists = [];
|
||||
|
||||
let showOnAllMonitors = this._settings.get_boolean('show-on-all-monitors');
|
||||
@@ -1226,14 +1138,19 @@ class Extension {
|
||||
this._monitorsChangedId = 0;
|
||||
|
||||
this._windowLists.forEach(windowList => {
|
||||
windowList.actor.hide();
|
||||
windowList.actor.destroy();
|
||||
windowList.hide();
|
||||
windowList.destroy();
|
||||
});
|
||||
this._windowLists = null;
|
||||
|
||||
Main.windowPicker.destroy();
|
||||
delete Main.windowPicker;
|
||||
|
||||
Main.overview.hide = this._hideOverviewOrig;
|
||||
}
|
||||
|
||||
someWindowListContains(actor) {
|
||||
return this._windowLists.some(list => list.actor.contains(actor));
|
||||
return this._windowLists.some(list => list.contains(actor));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ extension_data += configure_file(
|
||||
configuration: metadata_conf
|
||||
)
|
||||
|
||||
extension_sources += files('prefs.js')
|
||||
extension_sources += files('prefs.js', 'windowPicker.js', 'workspaceIndicator.js')
|
||||
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')
|
||||
|
||||
if classic_mode_enabled
|
||||
|
||||
@@ -26,9 +26,8 @@
|
||||
spacing: 4px;
|
||||
}
|
||||
|
||||
.window-button > StWidget {
|
||||
-st-natural-width: 18.75em;
|
||||
max-width: 18.75em;
|
||||
.window-button > StWidget,
|
||||
.window-picker-toggle > StWidget {
|
||||
color: #bbb;
|
||||
background-color: black;
|
||||
border-radius: 4px;
|
||||
@@ -37,7 +36,21 @@
|
||||
text-shadow: 1px 1px 4px rgba(0,0,0,0.8);
|
||||
}
|
||||
|
||||
.window-button:hover > StWidget {
|
||||
.window-picker-toggle {
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.window-picker-toggle > StWidet {
|
||||
border: 1px solid rgba(255,255,255,0.3);
|
||||
}
|
||||
|
||||
.window-button > StWidget {
|
||||
-st-natural-width: 18.75em;
|
||||
max-width: 18.75em;
|
||||
}
|
||||
|
||||
.window-button:hover > StWidget,
|
||||
.window-picker-toggle:hover > StWidget {
|
||||
color: white;
|
||||
background-color: #1f1f1f;
|
||||
}
|
||||
@@ -47,12 +60,14 @@
|
||||
box-shadow: inset 2px 2px 4px rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
.window-button.focused > StWidget {
|
||||
.window-button.focused > StWidget,
|
||||
.window-picker-toggle:checked > StWidget {
|
||||
color: white;
|
||||
box-shadow: inset 1px 1px 4px rgba(255,255,255,0.7);
|
||||
}
|
||||
|
||||
.window-button.focused:active > StWidget {
|
||||
.window-button.focused:active > StWidget,
|
||||
.window-picker-toggle:checked:active > StWidget {
|
||||
box-shadow: inset 2px 2px 4px rgba(255,255,255,0.7);
|
||||
}
|
||||
|
||||
@@ -70,13 +85,50 @@
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.window-list-workspace-indicator {
|
||||
.window-list-workspace-indicator .status-label-bin {
|
||||
background-color: rgba(200, 200, 200, .3);
|
||||
border: 1px solid #cccccc;
|
||||
padding: 0 3px;
|
||||
margin: 3px 0;
|
||||
}
|
||||
|
||||
.window-list-workspace-indicator .workspaces-box {
|
||||
spacing: 3px;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.window-list-workspace-indicator > StWidget {
|
||||
background-color: rgba(200, 200, 200, .3);
|
||||
.window-list-workspace-indicator .workspace {
|
||||
border: 1px solid #cccccc;
|
||||
width: 52px;
|
||||
}
|
||||
|
||||
.window-list-workspace-indicator .workspace:first-child:last-child:ltr,
|
||||
.window-list-workspace-indicator .workspace:first-child:last-child:rtl {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.window-list-workspace-indicator .workspace:first-child:ltr,
|
||||
.window-list-workspace-indicator .workspace:last-child:rtl {
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
.window-list-workspace-indicator .workspace:first-child:rtl,
|
||||
.window-list-workspace-indicator .workspace:last-child:ltr {
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
.window-list-workspace-indicator .workspace.active {
|
||||
background-color: rgba(200, 200, 200, .3);
|
||||
}
|
||||
|
||||
.window-list-window-preview {
|
||||
background-color: #252525;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.window-list-window-preview.active {
|
||||
background-color: #353535;
|
||||
border: 2px solid #ccc;
|
||||
}
|
||||
|
||||
.notification {
|
||||
|
||||
278
extensions/window-list/windowPicker.js
Normal file
278
extensions/window-list/windowPicker.js
Normal file
@@ -0,0 +1,278 @@
|
||||
/* exported WindowPicker, WindowPickerToggle */
|
||||
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
|
||||
|
||||
const Layout = imports.ui.layout;
|
||||
const Main = imports.ui.main;
|
||||
const Overview = imports.ui.overview;
|
||||
const { WorkspacesDisplay } = imports.ui.workspacesView;
|
||||
|
||||
let MyWorkspacesDisplay = class extends WorkspacesDisplay {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.actor.add_constraint(
|
||||
new Layout.MonitorConstraint({
|
||||
primary: true,
|
||||
work_area: true
|
||||
}));
|
||||
|
||||
this.actor.connect('destroy', this._onDestroy.bind(this));
|
||||
|
||||
this._workareasChangedId = global.display.connect('workareas-changed',
|
||||
this._onWorkAreasChanged.bind(this));
|
||||
this._onWorkAreasChanged();
|
||||
}
|
||||
|
||||
show(...args) {
|
||||
if (this._scrollEventId == 0)
|
||||
this._scrollEventId = Main.windowPicker.connect('scroll-event',
|
||||
this._onScrollEvent.bind(this));
|
||||
|
||||
super.show(...args);
|
||||
}
|
||||
|
||||
hide(...args) {
|
||||
if (this._scrollEventId > 0)
|
||||
Main.windowPicker.disconnect(this._scrollEventId);
|
||||
this._scrollEventId = 0;
|
||||
|
||||
super.hide(...args);
|
||||
}
|
||||
|
||||
_onWorkAreasChanged() {
|
||||
let { primaryIndex } = Main.layoutManager;
|
||||
let workarea = Main.layoutManager.getWorkAreaForMonitor(primaryIndex);
|
||||
this.setWorkspacesFullGeometry(workarea);
|
||||
}
|
||||
|
||||
_updateWorkspacesViews() {
|
||||
super._updateWorkspacesViews();
|
||||
|
||||
this._workspacesViews.forEach(v => {
|
||||
Main.layoutManager.overviewGroup.remove_actor(v.actor);
|
||||
Main.windowPicker.add_actor(v.actor);
|
||||
});
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
if (this._workareasChangedId)
|
||||
global.display.disconnect(this._workareasChangedId);
|
||||
this._workareasChangedId = 0;
|
||||
}
|
||||
};
|
||||
|
||||
var WindowPicker = GObject.registerClass({
|
||||
GTypeName: 'WindowListWindowPicker',
|
||||
Signals: {
|
||||
'open-state-changed': { param_types: [GObject.TYPE_BOOLEAN] },
|
||||
'scroll-event': { param_types: [Clutter.Event.$gtype] }
|
||||
}
|
||||
}, class extends Clutter.Actor {
|
||||
_init() {
|
||||
this._visible = false;
|
||||
this._modal = false;
|
||||
|
||||
this._overlayKeyId = 0;
|
||||
this._stageKeyPressId = 0;
|
||||
|
||||
super._init();
|
||||
|
||||
this.connect('destroy', this._onDestroy.bind(this));
|
||||
|
||||
global.bind_property('screen-width',
|
||||
this, 'width',
|
||||
GObject.BindingFlags.SYNC_CREATE);
|
||||
global.bind_property('screen-height',
|
||||
this, 'height',
|
||||
GObject.BindingFlags.SYNC_CREATE);
|
||||
|
||||
this._backgroundGroup = new Meta.BackgroundGroup({ reactive: true });
|
||||
this.add_child(this._backgroundGroup);
|
||||
|
||||
this._backgroundGroup.connect('scroll-event', (a, ev) => {
|
||||
this.emit('scroll-event', ev);
|
||||
});
|
||||
|
||||
// Trick WorkspacesDisplay constructor into adding actions here
|
||||
let addActionOrig = Main.overview.addAction;
|
||||
Main.overview.addAction = a => this._backgroundGroup.add_action(a);
|
||||
|
||||
this._workspacesDisplay = new MyWorkspacesDisplay();
|
||||
this.add_child(this._workspacesDisplay.actor);
|
||||
|
||||
Main.overview.addAction = addActionOrig;
|
||||
|
||||
this._bgManagers = [];
|
||||
|
||||
this._monitorsChangedId = Main.layoutManager.connect('monitors-changed',
|
||||
this._updateBackgrounds.bind(this));
|
||||
this._updateBackgrounds();
|
||||
|
||||
Main.uiGroup.insert_child_below(this, global.window_group);
|
||||
|
||||
if (!Main.sessionMode.hasOverview) {
|
||||
this._overlayKeyId = global.display.connect('overlay-key', () => {
|
||||
if (!this._visible)
|
||||
this.open();
|
||||
else
|
||||
this.close();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
get visible() {
|
||||
return this._visible;
|
||||
}
|
||||
|
||||
open() {
|
||||
if (this._visible)
|
||||
return;
|
||||
|
||||
this._visible = true;
|
||||
|
||||
if (!this._syncGrab())
|
||||
return;
|
||||
|
||||
this._fakeOverviewVisible(true);
|
||||
this._shadeBackgrounds();
|
||||
this._fakeOverviewAnimation();
|
||||
this._workspacesDisplay.show(false);
|
||||
|
||||
this._stageKeyPressId = global.stage.connect('key-press-event',
|
||||
(a, event) => {
|
||||
let sym = event.get_key_symbol();
|
||||
if (sym == Clutter.KEY_Escape) {
|
||||
this.close();
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
});
|
||||
|
||||
this.emit('open-state-changed', this._visible);
|
||||
}
|
||||
|
||||
close() {
|
||||
if (!this._visible)
|
||||
return;
|
||||
|
||||
this._visible = false;
|
||||
|
||||
if (!this._syncGrab())
|
||||
return;
|
||||
|
||||
this._workspacesDisplay.animateFromOverview(false);
|
||||
this._unshadeBackgrounds();
|
||||
this._fakeOverviewAnimation(() => {
|
||||
this._workspacesDisplay.hide();
|
||||
this._fakeOverviewVisible(false);
|
||||
});
|
||||
|
||||
global.stage.disconnect(this._stageKeyPressId);
|
||||
this._stageKeyPressId = 0;
|
||||
|
||||
this.emit('open-state-changed', this._visible);
|
||||
}
|
||||
|
||||
_fakeOverviewAnimation(onComplete) {
|
||||
Main.overview.animationInProgress = true;
|
||||
GLib.timeout_add(
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
Overview.ANIMATION_TIME * 1000,
|
||||
() => {
|
||||
Main.overview.animationInProgress = false;
|
||||
if (onComplete)
|
||||
onComplete();
|
||||
});
|
||||
}
|
||||
|
||||
_fakeOverviewVisible(visible) {
|
||||
// Fake overview state for WorkspacesDisplay
|
||||
Main.overview.visible = visible;
|
||||
|
||||
// Hide real windows
|
||||
Main.layoutManager._inOverview = visible;
|
||||
Main.layoutManager._updateVisibility();
|
||||
}
|
||||
|
||||
_syncGrab() {
|
||||
if (this._visible) {
|
||||
if (this._modal)
|
||||
return true;
|
||||
|
||||
this._modal = Main.pushModal(this, {
|
||||
actionMode: Shell.ActionMode.OVERVIEW
|
||||
});
|
||||
|
||||
if (!this._modal) {
|
||||
this.hide();
|
||||
return false;
|
||||
}
|
||||
} else if (this._modal) {
|
||||
Main.popModal(this);
|
||||
this._modal = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
if (this._monitorsChangedId)
|
||||
Main.layoutManager.disconnect(this._monitorsChangedId);
|
||||
this._monitorsChangedId = 0;
|
||||
|
||||
if (this._overlayKeyId)
|
||||
global.display.disconnect(this._overlayKeyId);
|
||||
this._overlayKeyId = 0;
|
||||
|
||||
if (this._stageKeyPressId)
|
||||
global.stage.disconnect(this._stageKeyPressId);
|
||||
this._stageKeyPressId = 0;
|
||||
}
|
||||
|
||||
_updateBackgrounds() {
|
||||
Main.overview._updateBackgrounds.call(this);
|
||||
}
|
||||
|
||||
_shadeBackgrounds() {
|
||||
Main.overview._shadeBackgrounds.call(this);
|
||||
}
|
||||
|
||||
_unshadeBackgrounds() {
|
||||
Main.overview._unshadeBackgrounds.call(this);
|
||||
}
|
||||
});
|
||||
|
||||
var WindowPickerToggle = GObject.registerClass(
|
||||
class WindowPickerToggle extends St.Button {
|
||||
_init() {
|
||||
let iconBin = new St.Widget({
|
||||
layout_manager: new Clutter.BinLayout()
|
||||
});
|
||||
iconBin.add_child(new St.Icon({
|
||||
icon_name: 'focus-windows-symbolic',
|
||||
icon_size: 16,
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.CENTER
|
||||
}));
|
||||
super._init({
|
||||
style_class: 'window-picker-toggle',
|
||||
child: iconBin,
|
||||
visible: !Main.sessionMode.hasOverview,
|
||||
x_fill: true,
|
||||
y_fill: true,
|
||||
toggle_mode: true
|
||||
});
|
||||
|
||||
this.connect('notify::checked', () => {
|
||||
if (this.checked)
|
||||
Main.windowPicker.open();
|
||||
else
|
||||
Main.windowPicker.close();
|
||||
});
|
||||
|
||||
Main.windowPicker.connect('open-state-changed', () => {
|
||||
this.checked = Main.windowPicker.visible;
|
||||
});
|
||||
}
|
||||
});
|
||||
402
extensions/window-list/workspaceIndicator.js
Normal file
402
extensions/window-list/workspaceIndicator.js
Normal file
@@ -0,0 +1,402 @@
|
||||
/* exported WorkspaceIndicator */
|
||||
const { Clutter, Gio, GObject, Meta, St } = imports.gi;
|
||||
|
||||
const DND = imports.ui.dnd;
|
||||
const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
let WindowPreview = GObject.registerClass({
|
||||
GTypeName: 'WindowListWindowPreview'
|
||||
}, class WindowPreview extends St.Button {
|
||||
_init(window) {
|
||||
super._init({
|
||||
style_class: 'window-list-window-preview'
|
||||
});
|
||||
|
||||
this._delegate = this;
|
||||
DND.makeDraggable(this, { restoreOnSuccess: true });
|
||||
|
||||
this._window = window;
|
||||
|
||||
this.connect('destroy', this._onDestroy.bind(this));
|
||||
|
||||
this._sizeChangedId = this._window.connect('size-changed',
|
||||
this._relayout.bind(this));
|
||||
this._positionChangedId = this._window.connect('position-changed',
|
||||
this._relayout.bind(this));
|
||||
this._minimizedChangedId = this._window.connect('notify::minimized',
|
||||
this._relayout.bind(this));
|
||||
this._monitorEnteredId = global.display.connect('window-entered-monitor',
|
||||
this._relayout.bind(this));
|
||||
this._monitorLeftId = global.display.connect('window-left-monitor',
|
||||
this._relayout.bind(this));
|
||||
|
||||
// Do initial layout when we get a parent
|
||||
let id = this.connect('parent-set', () => {
|
||||
this.disconnect(id);
|
||||
if (!this.get_parent())
|
||||
return;
|
||||
this._laterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
|
||||
this._laterId = 0;
|
||||
this._relayout();
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
this._focusChangedId = global.display.connect('notify::focus-window',
|
||||
this._onFocusChanged.bind(this));
|
||||
this._onFocusChanged();
|
||||
}
|
||||
|
||||
// needed for DND
|
||||
get realWindow() {
|
||||
return this._window.get_compositor_private();
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this._window.disconnect(this._sizeChangedId);
|
||||
this._window.disconnect(this._positionChangedId);
|
||||
this._window.disconnect(this._minimizedChangedId);
|
||||
global.display.disconnect(this._monitorEnteredId);
|
||||
global.display.disconnect(this._monitorLeftId);
|
||||
global.display.disconnect(this._focusChangedId);
|
||||
if (this._laterId)
|
||||
Meta.later_remove(this._laterId);
|
||||
}
|
||||
|
||||
_onFocusChanged() {
|
||||
if (global.display.focus_window == this._window)
|
||||
this.add_style_class_name('active');
|
||||
else
|
||||
this.remove_style_class_name('active');
|
||||
}
|
||||
|
||||
_relayout() {
|
||||
let monitor = Main.layoutManager.findIndexForActor(this);
|
||||
this.visible = monitor == this._window.get_monitor() &&
|
||||
this._window.showing_on_its_workspace();
|
||||
|
||||
if (!this.visible)
|
||||
return;
|
||||
|
||||
let workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
|
||||
let hscale = this.get_parent().allocation.get_width() / workArea.width;
|
||||
let vscale = this.get_parent().allocation.get_height() / workArea.height;
|
||||
|
||||
let frameRect = this._window.get_frame_rect();
|
||||
this.set_size(
|
||||
Math.round(Math.min(frameRect.width, workArea.width) * hscale),
|
||||
Math.round(Math.min(frameRect.height, workArea.height) * vscale));
|
||||
this.set_position(
|
||||
Math.round(frameRect.x * hscale),
|
||||
Math.round(frameRect.y * vscale));
|
||||
}
|
||||
});
|
||||
|
||||
let WorkspaceThumbnail = GObject.registerClass({
|
||||
GTypeName: 'WindowListWorkspaceThumbnail'
|
||||
}, class WorkspaceThumbnail extends St.Button {
|
||||
_init(index) {
|
||||
super._init({
|
||||
style_class: 'workspace',
|
||||
child: new Clutter.Actor({
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
clip_to_allocation: true
|
||||
}),
|
||||
x_fill: true,
|
||||
y_fill: true
|
||||
});
|
||||
|
||||
this.connect('destroy', this._onDestroy.bind(this));
|
||||
|
||||
this._index = index;
|
||||
this._delegate = this; // needed for DND
|
||||
|
||||
this._windowPreviews = new Map();
|
||||
|
||||
let workspaceManager = global.workspace_manager;
|
||||
this._workspace = workspaceManager.get_workspace_by_index(index);
|
||||
|
||||
this._windowAddedId = this._workspace.connect('window-added',
|
||||
(ws, window) => {
|
||||
this._addWindow(window);
|
||||
});
|
||||
this._windowRemovedId = this._workspace.connect('window-removed',
|
||||
(ws, window) => {
|
||||
this._removeWindow(window);
|
||||
});
|
||||
this._restackedId = global.display.connect('restacked',
|
||||
this._onRestacked.bind(this));
|
||||
|
||||
this._workspace.list_windows().forEach(w => this._addWindow(w));
|
||||
this._onRestacked();
|
||||
}
|
||||
|
||||
acceptDrop(source) {
|
||||
if (!source.realWindow)
|
||||
return false;
|
||||
|
||||
let window = source.realWindow.get_meta_window();
|
||||
this._moveWindow(window);
|
||||
return true;
|
||||
}
|
||||
|
||||
handleDragOver(source) {
|
||||
if (source.realWindow)
|
||||
return DND.DragMotionResult.MOVE_DROP;
|
||||
else
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
}
|
||||
|
||||
_addWindow(window) {
|
||||
if (this._windowPreviews.has(window))
|
||||
return;
|
||||
|
||||
let preview = new WindowPreview(window);
|
||||
preview.connect('clicked', (a, btn) => this.emit('clicked', btn));
|
||||
this._windowPreviews.set(window, preview);
|
||||
this.child.add_child(preview);
|
||||
}
|
||||
|
||||
_removeWindow(window) {
|
||||
let preview = this._windowPreviews.get(window);
|
||||
if (!preview)
|
||||
return;
|
||||
|
||||
this._windowPreviews.delete(window);
|
||||
preview.destroy();
|
||||
}
|
||||
|
||||
_onRestacked() {
|
||||
let lastPreview = null;
|
||||
let windows = global.get_window_actors().map(a => a.meta_window);
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
let preview = this._windowPreviews.get(windows[i]);
|
||||
if (!preview)
|
||||
continue;
|
||||
|
||||
this.child.set_child_above_sibling(preview, lastPreview);
|
||||
lastPreview = preview;
|
||||
}
|
||||
}
|
||||
|
||||
_moveWindow(window) {
|
||||
let monitorIndex = Main.layoutManager.findIndexForActor(this);
|
||||
if (monitorIndex != window.get_monitor())
|
||||
window.move_to_monitor(monitorIndex);
|
||||
window.change_workspace_by_index(this._index, false);
|
||||
}
|
||||
|
||||
on_clicked() {
|
||||
let ws = global.workspace_manager.get_workspace_by_index(this._index);
|
||||
if (ws)
|
||||
ws.activate(global.get_current_time());
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this._workspace.disconnect(this._windowAddedId);
|
||||
this._workspace.disconnect(this._windowRemovedId);
|
||||
global.display.disconnect(this._restackedId);
|
||||
}
|
||||
});
|
||||
|
||||
var WorkspaceIndicator = GObject.registerClass({
|
||||
GTypeName: 'WindowListWorkspaceIndicator'
|
||||
}, class WorkspaceIndicator extends PanelMenu.Button {
|
||||
_init() {
|
||||
super._init(0.0, _('Workspace Indicator'), true);
|
||||
this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM));
|
||||
this.add_style_class_name('window-list-workspace-indicator');
|
||||
this.menu.actor.remove_style_class_name('panel-menu');
|
||||
|
||||
let container = new St.Widget({
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true,
|
||||
y_expand: true
|
||||
});
|
||||
this.add_actor(container);
|
||||
|
||||
let workspaceManager = global.workspace_manager;
|
||||
|
||||
this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
||||
this._statusLabel = new St.Label({ text: this._getStatusText() });
|
||||
|
||||
this._statusBin = new St.Bin({
|
||||
style_class: 'status-label-bin',
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
child: this._statusLabel
|
||||
});
|
||||
container.add_actor(this._statusBin);
|
||||
|
||||
this._thumbnailsBox = new St.BoxLayout({
|
||||
style_class: 'workspaces-box',
|
||||
y_expand: true,
|
||||
reactive: true
|
||||
});
|
||||
this._thumbnailsBox.connect('scroll-event',
|
||||
this._onScrollEvent.bind(this));
|
||||
container.add_actor(this._thumbnailsBox);
|
||||
|
||||
this._workspacesItems = [];
|
||||
|
||||
this._workspaceManagerSignals = [
|
||||
workspaceManager.connect('notify::n-workspaces',
|
||||
this._nWorkspacesChanged.bind(this)),
|
||||
workspaceManager.connect_after('workspace-switched',
|
||||
this._onWorkspaceSwitched.bind(this)),
|
||||
workspaceManager.connect('notify::layout-rows',
|
||||
this._onWorkspaceOrientationChanged.bind(this))
|
||||
];
|
||||
|
||||
this.connect('scroll-event', this._onScrollEvent.bind(this));
|
||||
this._updateMenu();
|
||||
this._updateThumbnails();
|
||||
this._onWorkspaceOrientationChanged();
|
||||
|
||||
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' });
|
||||
this._settingsChangedId = this._settings.connect(
|
||||
'changed::workspace-names', this._updateMenuLabels.bind(this));
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
for (let i = 0; i < this._workspaceManagerSignals.length; i++)
|
||||
global.workspace_manager.disconnect(this._workspaceManagerSignals[i]);
|
||||
|
||||
if (this._settingsChangedId) {
|
||||
this._settings.disconnect(this._settingsChangedId);
|
||||
this._settingsChangedId = 0;
|
||||
}
|
||||
|
||||
super._onDestroy();
|
||||
}
|
||||
|
||||
_onWorkspaceOrientationChanged() {
|
||||
let vertical = global.workspace_manager.layout_rows == -1;
|
||||
this.reactive = vertical;
|
||||
|
||||
this._statusBin.visible = vertical;
|
||||
this._thumbnailsBox.visible = !vertical;
|
||||
}
|
||||
|
||||
_onWorkspaceSwitched() {
|
||||
let workspaceManager = global.workspace_manager;
|
||||
this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
||||
|
||||
this._updateMenuOrnament();
|
||||
this._updateActiveThumbnail();
|
||||
|
||||
this._statusLabel.set_text(this._getStatusText());
|
||||
}
|
||||
|
||||
_nWorkspacesChanged() {
|
||||
this._updateMenu();
|
||||
this._updateThumbnails();
|
||||
}
|
||||
|
||||
_updateMenuOrnament() {
|
||||
for (let i = 0; i < this._workspacesItems.length; i++) {
|
||||
this._workspacesItems[i].setOrnament(i == this._currentWorkspace
|
||||
? PopupMenu.Ornament.DOT
|
||||
: PopupMenu.Ornament.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
_updateActiveThumbnail() {
|
||||
let thumbs = this._thumbnailsBox.get_children();
|
||||
for (let i = 0; i < thumbs.length; i++) {
|
||||
if (i == this._currentWorkspace)
|
||||
thumbs[i].add_style_class_name('active');
|
||||
else
|
||||
thumbs[i].remove_style_class_name('active');
|
||||
}
|
||||
}
|
||||
|
||||
_getStatusText() {
|
||||
let workspaceManager = global.workspace_manager;
|
||||
let current = workspaceManager.get_active_workspace_index();
|
||||
let total = workspaceManager.n_workspaces;
|
||||
|
||||
return '%d / %d'.format(current + 1, total);
|
||||
}
|
||||
|
||||
_updateMenuLabels() {
|
||||
for (let i = 0; i < this._workspacesItems.length; i++) {
|
||||
let item = this._workspacesItems[i];
|
||||
let name = Meta.prefs_get_workspace_name(i);
|
||||
item.label.text = name;
|
||||
}
|
||||
}
|
||||
|
||||
_updateMenu() {
|
||||
let workspaceManager = global.workspace_manager;
|
||||
|
||||
this.menu.removeAll();
|
||||
this._workspacesItems = [];
|
||||
this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
||||
|
||||
for (let i = 0; i < workspaceManager.n_workspaces; i++) {
|
||||
let name = Meta.prefs_get_workspace_name(i);
|
||||
let item = new PopupMenu.PopupMenuItem(name);
|
||||
item.workspaceId = i;
|
||||
|
||||
item.connect('activate', (item, _event) => {
|
||||
this._activate(item.workspaceId);
|
||||
});
|
||||
|
||||
if (i == this._currentWorkspace)
|
||||
item.setOrnament(PopupMenu.Ornament.DOT);
|
||||
|
||||
this.menu.addMenuItem(item);
|
||||
this._workspacesItems[i] = item;
|
||||
}
|
||||
|
||||
this._statusLabel.set_text(this._getStatusText());
|
||||
}
|
||||
|
||||
_updateThumbnails() {
|
||||
let workspaceManager = global.workspace_manager;
|
||||
|
||||
this._thumbnailsBox.destroy_all_children();
|
||||
|
||||
for (let i = 0; i < workspaceManager.n_workspaces; i++) {
|
||||
let thumb = new WorkspaceThumbnail(i);
|
||||
this._thumbnailsBox.add_actor(thumb);
|
||||
}
|
||||
this._updateActiveThumbnail();
|
||||
}
|
||||
|
||||
_activate(index) {
|
||||
let workspaceManager = global.workspace_manager;
|
||||
|
||||
if (index >= 0 && index < workspaceManager.n_workspaces) {
|
||||
let metaWorkspace = workspaceManager.get_workspace_by_index(index);
|
||||
metaWorkspace.activate(global.get_current_time());
|
||||
}
|
||||
}
|
||||
|
||||
_onScrollEvent(actor, event) {
|
||||
let direction = event.get_scroll_direction();
|
||||
let diff = 0;
|
||||
if (direction == Clutter.ScrollDirection.DOWN) {
|
||||
diff = 1;
|
||||
} else if (direction == Clutter.ScrollDirection.UP) {
|
||||
diff = -1;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
let newIndex = this._currentWorkspace + diff;
|
||||
this._activate(newIndex);
|
||||
}
|
||||
|
||||
_allocate(actor, box, flags) {
|
||||
if (actor.get_n_children() > 0)
|
||||
actor.get_first_child().allocate(box, flags);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2,57 +2,268 @@
|
||||
/* exported init enable disable */
|
||||
|
||||
const { Clutter, Gio, GObject, Meta, St } = imports.gi;
|
||||
|
||||
const DND = imports.ui.dnd;
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
|
||||
const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
|
||||
const WORKSPACE_KEY = 'workspace-names';
|
||||
|
||||
let WindowPreview = GObject.registerClass({
|
||||
GTypeName: 'WorkspaceIndicatorWindowPreview'
|
||||
}, class WindowPreview extends St.Button {
|
||||
_init(window) {
|
||||
super._init({
|
||||
style_class: 'workspace-indicator-window-preview'
|
||||
});
|
||||
|
||||
this._delegate = this;
|
||||
DND.makeDraggable(this, { restoreOnSuccess: true });
|
||||
|
||||
this._window = window;
|
||||
|
||||
this.connect('destroy', this._onDestroy.bind(this));
|
||||
|
||||
this._sizeChangedId = this._window.connect('size-changed',
|
||||
this._relayout.bind(this));
|
||||
this._positionChangedId = this._window.connect('position-changed',
|
||||
this._relayout.bind(this));
|
||||
this._minimizedChangedId = this._window.connect('notify::minimized',
|
||||
this._relayout.bind(this));
|
||||
this._monitorEnteredId = global.display.connect('window-entered-monitor',
|
||||
this._relayout.bind(this));
|
||||
this._monitorLeftId = global.display.connect('window-left-monitor',
|
||||
this._relayout.bind(this));
|
||||
|
||||
// Do initial layout when we get a parent
|
||||
let id = this.connect('parent-set', () => {
|
||||
this.disconnect(id);
|
||||
if (!this.get_parent())
|
||||
return;
|
||||
this._laterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
|
||||
this._laterId = 0;
|
||||
this._relayout();
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
this._focusChangedId = global.display.connect('notify::focus-window',
|
||||
this._onFocusChanged.bind(this));
|
||||
this._onFocusChanged();
|
||||
}
|
||||
|
||||
// needed for DND
|
||||
get realWindow() {
|
||||
return this._window.get_compositor_private();
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this._window.disconnect(this._sizeChangedId);
|
||||
this._window.disconnect(this._positionChangedId);
|
||||
this._window.disconnect(this._minimizedChangedId);
|
||||
global.display.disconnect(this._monitorEnteredId);
|
||||
global.display.disconnect(this._monitorLeftId);
|
||||
global.display.disconnect(this._focusChangedId);
|
||||
if (this._laterId)
|
||||
Meta.later_remove(this._laterId);
|
||||
}
|
||||
|
||||
_onFocusChanged() {
|
||||
if (global.display.focus_window == this._window)
|
||||
this.add_style_class_name('active');
|
||||
else
|
||||
this.remove_style_class_name('active');
|
||||
}
|
||||
|
||||
_relayout() {
|
||||
let monitor = Main.layoutManager.findIndexForActor(this);
|
||||
this.visible = monitor == this._window.get_monitor() &&
|
||||
this._window.showing_on_its_workspace();
|
||||
|
||||
if (!this.visible)
|
||||
return;
|
||||
|
||||
let workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
|
||||
let hscale = this.get_parent().allocation.get_width() / workArea.width;
|
||||
let vscale = this.get_parent().allocation.get_height() / workArea.height;
|
||||
|
||||
let frameRect = this._window.get_frame_rect();
|
||||
this.set_size(
|
||||
Math.round(Math.min(frameRect.width, workArea.width) * hscale),
|
||||
Math.round(Math.min(frameRect.height, workArea.height) * vscale));
|
||||
this.set_position(
|
||||
Math.round(frameRect.x * hscale),
|
||||
Math.round(frameRect.y * vscale));
|
||||
}
|
||||
});
|
||||
|
||||
let WorkspaceThumbnail = GObject.registerClass({
|
||||
GTypeName: 'WorkspaceIndicatorWorkspaceThumbnail'
|
||||
}, class WorkspaceThumbnail extends St.Button {
|
||||
_init(index) {
|
||||
super._init({
|
||||
style_class: 'workspace',
|
||||
child: new Clutter.Actor({
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
clip_to_allocation: true
|
||||
}),
|
||||
x_fill: true,
|
||||
y_fill: true
|
||||
});
|
||||
|
||||
this.connect('destroy', this._onDestroy.bind(this));
|
||||
|
||||
this._index = index;
|
||||
this._delegate = this; // needed for DND
|
||||
|
||||
this._windowPreviews = new Map();
|
||||
|
||||
let workspaceManager = global.workspace_manager;
|
||||
this._workspace = workspaceManager.get_workspace_by_index(index);
|
||||
|
||||
this._windowAddedId = this._workspace.connect('window-added',
|
||||
(ws, window) => {
|
||||
this._addWindow(window);
|
||||
});
|
||||
this._windowRemovedId = this._workspace.connect('window-removed',
|
||||
(ws, window) => {
|
||||
this._removeWindow(window);
|
||||
});
|
||||
this._restackedId = global.display.connect('restacked',
|
||||
this._onRestacked.bind(this));
|
||||
|
||||
this._workspace.list_windows().forEach(w => this._addWindow(w));
|
||||
this._onRestacked();
|
||||
}
|
||||
|
||||
acceptDrop(source) {
|
||||
if (!source.realWindow)
|
||||
return false;
|
||||
|
||||
let window = source.realWindow.get_meta_window();
|
||||
this._moveWindow(window);
|
||||
return true;
|
||||
}
|
||||
|
||||
handleDragOver(source) {
|
||||
if (source.realWindow)
|
||||
return DND.DragMotionResult.MOVE_DROP;
|
||||
else
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
}
|
||||
|
||||
_addWindow(window) {
|
||||
if (this._windowPreviews.has(window))
|
||||
return;
|
||||
|
||||
let preview = new WindowPreview(window);
|
||||
preview.connect('clicked', (a, btn) => this.emit('clicked', btn));
|
||||
this._windowPreviews.set(window, preview);
|
||||
this.child.add_child(preview);
|
||||
}
|
||||
|
||||
_removeWindow(window) {
|
||||
let preview = this._windowPreviews.get(window);
|
||||
if (!preview)
|
||||
return;
|
||||
|
||||
this._windowPreviews.delete(window);
|
||||
preview.destroy();
|
||||
}
|
||||
|
||||
_onRestacked() {
|
||||
let lastPreview = null;
|
||||
let windows = global.get_window_actors().map(a => a.meta_window);
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
let preview = this._windowPreviews.get(windows[i]);
|
||||
if (!preview)
|
||||
continue;
|
||||
|
||||
this.child.set_child_above_sibling(preview, lastPreview);
|
||||
lastPreview = preview;
|
||||
}
|
||||
}
|
||||
|
||||
_moveWindow(window) {
|
||||
let monitorIndex = Main.layoutManager.findIndexForActor(this);
|
||||
if (monitorIndex != window.get_monitor())
|
||||
window.move_to_monitor(monitorIndex);
|
||||
window.change_workspace_by_index(this._index, false);
|
||||
}
|
||||
|
||||
on_clicked() {
|
||||
let ws = global.workspace_manager.get_workspace_by_index(this._index);
|
||||
if (ws)
|
||||
ws.activate(global.get_current_time());
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this._workspace.disconnect(this._windowAddedId);
|
||||
this._workspace.disconnect(this._windowRemovedId);
|
||||
global.display.disconnect(this._restackedId);
|
||||
}
|
||||
});
|
||||
|
||||
let WorkspaceIndicator = GObject.registerClass(
|
||||
class WorkspaceIndicator extends PanelMenu.Button {
|
||||
_init() {
|
||||
super._init(0.0, _('Workspace Indicator'));
|
||||
|
||||
let container = new St.Widget({
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true,
|
||||
y_expand: true
|
||||
});
|
||||
this.add_actor(container);
|
||||
|
||||
let workspaceManager = global.workspace_manager;
|
||||
|
||||
this._currentWorkspace = workspaceManager.get_active_workspace().index();
|
||||
this.statusLabel = new St.Label({
|
||||
this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
||||
this._statusLabel = new St.Label({
|
||||
style_class: 'panel-workspace-indicator',
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
text: this._labelText()
|
||||
});
|
||||
|
||||
this.add_actor(this.statusLabel);
|
||||
container.add_actor(this._statusLabel);
|
||||
|
||||
this.workspacesItems = [];
|
||||
this._thumbnailsBox = new St.BoxLayout({
|
||||
style_class: 'panel-workspace-indicator-box',
|
||||
y_expand: true,
|
||||
reactive: true
|
||||
});
|
||||
|
||||
container.add_actor(this._thumbnailsBox);
|
||||
|
||||
this._workspacesItems = [];
|
||||
this._workspaceSection = new PopupMenu.PopupMenuSection();
|
||||
this.menu.addMenuItem(this._workspaceSection);
|
||||
|
||||
this._workspaceManagerSignals = [
|
||||
workspaceManager.connect_after('workspace-added',
|
||||
this._createWorkspacesSection.bind(this)),
|
||||
workspaceManager.connect_after('workspace-removed',
|
||||
this._createWorkspacesSection.bind(this)),
|
||||
workspaceManager.connect_after('notify::n-workspaces',
|
||||
this._nWorkspacesChanged.bind(this)),
|
||||
workspaceManager.connect_after('workspace-switched',
|
||||
this._updateIndicator.bind(this))
|
||||
this._onWorkspaceSwitched.bind(this)),
|
||||
workspaceManager.connect('notify::layout-rows',
|
||||
this._onWorkspaceOrientationChanged.bind(this))
|
||||
];
|
||||
|
||||
this.connect('scroll-event', this._onScrollEvent.bind(this));
|
||||
this._thumbnailsBox.connect('scroll-event', this._onScrollEvent.bind(this));
|
||||
this._createWorkspacesSection();
|
||||
|
||||
//styling
|
||||
this.statusLabel.add_style_class_name('panel-workspace-indicator');
|
||||
this._updateThumbnails();
|
||||
this._onWorkspaceOrientationChanged();
|
||||
|
||||
this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA });
|
||||
this._settingsChangedId = this._settings.connect(
|
||||
`changed::${WORKSPACE_KEY}`,
|
||||
this._createWorkspacesSection.bind(this));
|
||||
this._updateMenuLabels.bind(this));
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
@@ -64,15 +275,55 @@ class WorkspaceIndicator extends PanelMenu.Button {
|
||||
this._settingsChangedId = 0;
|
||||
}
|
||||
|
||||
Main.panel.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
|
||||
|
||||
super._onDestroy();
|
||||
}
|
||||
|
||||
_updateIndicator() {
|
||||
this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE);
|
||||
this._currentWorkspace = global.workspace_manager.get_active_workspace().index();
|
||||
this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT);
|
||||
_onWorkspaceOrientationChanged() {
|
||||
let vertical = global.workspace_manager.layout_rows == -1;
|
||||
this.reactive = vertical;
|
||||
|
||||
this.statusLabel.set_text(this._labelText());
|
||||
this._statusLabel.visible = vertical;
|
||||
this._thumbnailsBox.visible = !vertical;
|
||||
|
||||
// Disable offscreen-redirect when showing the workspace switcher
|
||||
// so that clip-to-allocation works
|
||||
Main.panel.set_offscreen_redirect(vertical
|
||||
? Clutter.OffscreenRedirect.ALWAYS
|
||||
: Clutter.OffscreenRedirect.AUTOMATIC_FOR_OPACITY);
|
||||
}
|
||||
|
||||
_onWorkspaceSwitched() {
|
||||
this._currentWorkspace = global.workspace_manager.get_active_workspace_index();
|
||||
|
||||
this._updateMenuOrnament();
|
||||
this._updateActiveThumbnail();
|
||||
|
||||
this._statusLabel.set_text(this._labelText());
|
||||
}
|
||||
|
||||
_nWorkspacesChanged() {
|
||||
this._createWorkspacesSection();
|
||||
this._updateThumbnails();
|
||||
}
|
||||
|
||||
_updateMenuOrnament() {
|
||||
for (let i = 0; i < this._workspacesItems.length; i++) {
|
||||
this._workspacesItems[i].setOrnament(i == this._currentWorkspace
|
||||
? PopupMenu.Ornament.DOT
|
||||
: PopupMenu.Ornament.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
_updateActiveThumbnail() {
|
||||
let thumbs = this._thumbnailsBox.get_children();
|
||||
for (let i = 0; i < thumbs.length; i++) {
|
||||
if (i == this._currentWorkspace)
|
||||
thumbs[i].add_style_class_name('active');
|
||||
else
|
||||
thumbs[i].remove_style_class_name('active');
|
||||
}
|
||||
}
|
||||
|
||||
_labelText(workspaceIndex) {
|
||||
@@ -83,34 +334,51 @@ class WorkspaceIndicator extends PanelMenu.Button {
|
||||
return Meta.prefs_get_workspace_name(workspaceIndex);
|
||||
}
|
||||
|
||||
_updateMenuLabels() {
|
||||
for (let i = 0; i < this._workspacesItems.length; i++)
|
||||
this._workspacesItems[i].label.text = this._labelText(i);
|
||||
}
|
||||
|
||||
_createWorkspacesSection() {
|
||||
let workspaceManager = global.workspace_manager;
|
||||
|
||||
this._workspaceSection.removeAll();
|
||||
this.workspacesItems = [];
|
||||
this._currentWorkspace = workspaceManager.get_active_workspace().index();
|
||||
this._workspacesItems = [];
|
||||
this._currentWorkspace = workspaceManager.get_active_workspace_index();
|
||||
|
||||
let i = 0;
|
||||
for (; i < workspaceManager.n_workspaces; i++) {
|
||||
this.workspacesItems[i] = new PopupMenu.PopupMenuItem(this._labelText(i));
|
||||
this._workspaceSection.addMenuItem(this.workspacesItems[i]);
|
||||
this.workspacesItems[i].workspaceId = i;
|
||||
this.workspacesItems[i].label_actor = this.statusLabel;
|
||||
this.workspacesItems[i].connect('activate', (actor, _event) => {
|
||||
this._workspacesItems[i] = new PopupMenu.PopupMenuItem(this._labelText(i));
|
||||
this._workspaceSection.addMenuItem(this._workspacesItems[i]);
|
||||
this._workspacesItems[i].workspaceId = i;
|
||||
this._workspacesItems[i].label_actor = this._statusLabel;
|
||||
this._workspacesItems[i].connect('activate', (actor, _event) => {
|
||||
this._activate(actor.workspaceId);
|
||||
});
|
||||
|
||||
if (i == this._currentWorkspace)
|
||||
this.workspacesItems[i].setOrnament(PopupMenu.Ornament.DOT);
|
||||
this._workspacesItems[i].setOrnament(PopupMenu.Ornament.DOT);
|
||||
}
|
||||
|
||||
this.statusLabel.set_text(this._labelText());
|
||||
this._statusLabel.set_text(this._labelText());
|
||||
}
|
||||
|
||||
_updateThumbnails() {
|
||||
let workspaceManager = global.workspace_manager;
|
||||
|
||||
this._thumbnailsBox.destroy_all_children();
|
||||
|
||||
for (let i = 0; i < workspaceManager.n_workspaces; i++) {
|
||||
let thumb = new WorkspaceThumbnail(i);
|
||||
this._thumbnailsBox.add_actor(thumb);
|
||||
}
|
||||
this._updateActiveThumbnail();
|
||||
}
|
||||
|
||||
_activate(index) {
|
||||
let workspaceManager = global.workspace_manager;
|
||||
|
||||
if (index >= 0 && index < workspaceManager.n_workspaces) {
|
||||
if (index >= 0 && index < workspaceManager.n_workspaces) {
|
||||
let metaWorkspace = workspaceManager.get_workspace_by_index(index);
|
||||
metaWorkspace.activate(global.get_current_time());
|
||||
}
|
||||
@@ -127,7 +395,7 @@ class WorkspaceIndicator extends PanelMenu.Button {
|
||||
return;
|
||||
}
|
||||
|
||||
let newIndex = global.workspace_manager.get_active_workspace().index() + diff;
|
||||
let newIndex = global.workspace_manager.get_active_workspace_index() + diff;
|
||||
this._activate(newIndex);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,5 +1,40 @@
|
||||
.panel-workspace-indicator {
|
||||
padding: 0 8px;
|
||||
background-color: rgba(200, 200, 200, .5);
|
||||
}
|
||||
|
||||
.panel-workspace-indicator-box {
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
.panel-workspace-indicator-box .workspace {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.panel-workspace-indicator,
|
||||
.panel-workspace-indicator-box .workspace {
|
||||
border: 1px solid #cccccc;
|
||||
}
|
||||
|
||||
.panel-workspace-indicator,
|
||||
.panel-workspace-indicator-box .workspace.active {
|
||||
background-color: rgba(200, 200, 200, .5);
|
||||
}
|
||||
|
||||
.panel-workspace-indicator-box .workspace {
|
||||
background-color: rgba(200, 200, 200, .3);
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
.panel-workspace-indicator-box .workspace:first-child {
|
||||
border-left-width: 1px;
|
||||
}
|
||||
|
||||
.workspace-indicator-window-preview {
|
||||
background-color: #252525;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.workspace-indicator-window-preview.active {
|
||||
background-color: #353535;
|
||||
border: 2px solid #ccc;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"error",
|
||||
{
|
||||
"properties": "never",
|
||||
"allow": ["^vfunc_"]
|
||||
"allow": ["^vfunc_", "^on_"]
|
||||
}
|
||||
],
|
||||
"no-unused-vars": [
|
||||
@@ -21,10 +21,6 @@
|
||||
"prefer-arrow-callback": "error"
|
||||
},
|
||||
"globals": {
|
||||
"global": false,
|
||||
"_": false,
|
||||
"C_": false,
|
||||
"N_": false,
|
||||
"ngettext": false
|
||||
"global": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
project('gnome-shell-extensions',
|
||||
version: '3.33.3',
|
||||
version: '3.33.4',
|
||||
meson_version: '>= 0.44.0',
|
||||
license: 'GPL2+'
|
||||
)
|
||||
@@ -33,6 +33,7 @@ uuid_suffix = '@gnome-shell-extensions.gcampax.github.com'
|
||||
|
||||
classic_extensions = [
|
||||
'apps-menu',
|
||||
'horizontal-workspaces',
|
||||
'places-menu',
|
||||
'launch-new-instance',
|
||||
'window-list'
|
||||
|
||||
@@ -38,6 +38,7 @@ kn
|
||||
ko
|
||||
lt
|
||||
lv
|
||||
mjw
|
||||
ml
|
||||
mr
|
||||
ms
|
||||
|
||||
@@ -15,6 +15,7 @@ extensions/user-theme/org.gnome.shell.extensions.user-theme.gschema.xml
|
||||
extensions/window-list/extension.js
|
||||
extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml
|
||||
extensions/window-list/prefs.js
|
||||
extensions/window-list/workspaceIndicator.js
|
||||
extensions/windowsNavigator/extension.js
|
||||
extensions/workspace-indicator/extension.js
|
||||
extensions/workspace-indicator/prefs.js
|
||||
|
||||
249
po/mjw.po
Normal file
249
po/mjw.po
Normal file
@@ -0,0 +1,249 @@
|
||||
# Karbi (India) translation for gnome-shell-extensions.
|
||||
# Copyright (C) 2019 gnome-shell-extensions's Free Software Foundation, Inc.
|
||||
# This file is distributed under the same license as the gnome-shell-extensions package.
|
||||
# Jor Teron <jor.teron@gmail.com>, 2019.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell-extensions master\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/"
|
||||
"issues\n"
|
||||
"POT-Creation-Date: 2019-07-14 04:31+0000\n"
|
||||
"PO-Revision-Date: 2019-07-16 08:19+0530\n"
|
||||
"Last-Translator: Jor Teron <jor.teron@gmail.com>\n"
|
||||
"Language-Team: Karbi <mjw@li.org>\n"
|
||||
"Language: mjw\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: gedit 3.28.1\n"
|
||||
|
||||
#: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3
|
||||
msgid "GNOME Classic"
|
||||
msgstr "GNOME Classic"
|
||||
|
||||
#: data/gnome-classic.desktop.in:4
|
||||
msgid "This session logs you into GNOME Classic"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/apps-menu/extension.js:111
|
||||
msgid "Favorites"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/apps-menu/extension.js:366
|
||||
msgid "Applications"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/auto-move-windows/org.gnome.shell.extensions.auto-move-windows.gschema.xml:6
|
||||
msgid "Application and workspace list"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/auto-move-windows/org.gnome.shell.extensions.auto-move-windows.gschema.xml:7
|
||||
msgid ""
|
||||
"A list of strings, each containing an application id (desktop file name), "
|
||||
"followed by a colon and the workspace number"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/auto-move-windows/prefs.js:60
|
||||
msgid "Application"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/auto-move-windows/prefs.js:71
|
||||
#: extensions/auto-move-windows/prefs.js:134
|
||||
msgid "Workspace"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/auto-move-windows/prefs.js:89
|
||||
msgid "Add Rule"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/auto-move-windows/prefs.js:111
|
||||
msgid "Create new matching rule"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/auto-move-windows/prefs.js:117
|
||||
msgid "Add"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: %s is the filesystem name
|
||||
#: extensions/drive-menu/extension.js:102
|
||||
#: extensions/places-menu/placeDisplay.js:232
|
||||
#, javascript-format
|
||||
msgid "Ejecting drive “%s” failed:"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/drive-menu/extension.js:118
|
||||
msgid "Removable devices"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/drive-menu/extension.js:145
|
||||
msgid "Open Files"
|
||||
msgstr "Files kangpu"
|
||||
|
||||
#: extensions/native-window-placement/org.gnome.shell.extensions.native-window-placement.gschema.xml:5
|
||||
msgid "Use more screen for windows"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/native-window-placement/org.gnome.shell.extensions.native-window-placement.gschema.xml:6
|
||||
msgid ""
|
||||
"Try to use more screen for placing window thumbnails by adapting to screen "
|
||||
"aspect ratio, and consolidating them further to reduce the bounding box. "
|
||||
"This setting applies only with the natural placement strategy."
|
||||
msgstr ""
|
||||
|
||||
#: extensions/native-window-placement/org.gnome.shell.extensions.native-window-placement.gschema.xml:11
|
||||
msgid "Place window captions on top"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/native-window-placement/org.gnome.shell.extensions.native-window-placement.gschema.xml:12
|
||||
msgid ""
|
||||
"If true, place window captions on top the respective thumbnail, overriding "
|
||||
"shell default of placing it at the bottom. Changing this setting requires "
|
||||
"restarting the shell to have any effect."
|
||||
msgstr ""
|
||||
|
||||
#: extensions/places-menu/extension.js:80
|
||||
#: extensions/places-menu/extension.js:84
|
||||
msgid "Places"
|
||||
msgstr "Places"
|
||||
|
||||
#: extensions/places-menu/placeDisplay.js:46
|
||||
#, javascript-format
|
||||
msgid "Failed to launch “%s”"
|
||||
msgstr "“%s” ingpu un-eh"
|
||||
|
||||
#: extensions/places-menu/placeDisplay.js:61
|
||||
#, javascript-format
|
||||
msgid "Failed to mount volume for “%s”"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/places-menu/placeDisplay.js:148
|
||||
#: extensions/places-menu/placeDisplay.js:171
|
||||
msgid "Computer"
|
||||
msgstr "Computer"
|
||||
|
||||
#: extensions/places-menu/placeDisplay.js:358
|
||||
msgid "Home"
|
||||
msgstr "Home"
|
||||
|
||||
#: extensions/places-menu/placeDisplay.js:403
|
||||
msgid "Browse Network"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/screenshot-window-sizer/org.gnome.shell.extensions.screenshot-window-sizer.gschema.xml:7
|
||||
msgid "Cycle Screenshot Sizes"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/screenshot-window-sizer/org.gnome.shell.extensions.screenshot-window-sizer.gschema.xml:11
|
||||
msgid "Cycle Screenshot Sizes Backward"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/user-theme/org.gnome.shell.extensions.user-theme.gschema.xml:5
|
||||
msgid "Theme name"
|
||||
msgstr "Theme amen"
|
||||
|
||||
#: extensions/user-theme/org.gnome.shell.extensions.user-theme.gschema.xml:6
|
||||
msgid "The name of the theme, to be loaded from ~/.themes/name/gnome-shell"
|
||||
msgstr "Theme amem, kewan ji pen ~/.themes/name/gnome-shell"
|
||||
|
||||
#: extensions/window-list/extension.js:99
|
||||
msgid "Close"
|
||||
msgstr "Kanghap"
|
||||
|
||||
#: extensions/window-list/extension.js:119
|
||||
msgid "Unminimize"
|
||||
msgstr "Pabi-thuthe"
|
||||
|
||||
#: extensions/window-list/extension.js:119
|
||||
msgid "Minimize"
|
||||
msgstr "Pabi"
|
||||
|
||||
#: extensions/window-list/extension.js:126
|
||||
msgid "Unmaximize"
|
||||
msgstr "Pathe-thuthe"
|
||||
|
||||
#: extensions/window-list/extension.js:126
|
||||
msgid "Maximize"
|
||||
msgstr "Pathe"
|
||||
|
||||
#: extensions/window-list/extension.js:399
|
||||
msgid "Minimize all"
|
||||
msgstr "Kado-kawe pabi"
|
||||
|
||||
#: extensions/window-list/extension.js:405
|
||||
msgid "Unminimize all"
|
||||
msgstr "Kado-kawe pabi-thuthe"
|
||||
|
||||
#: extensions/window-list/extension.js:411
|
||||
msgid "Maximize all"
|
||||
msgstr "Kathe-kawe pathe"
|
||||
|
||||
#: extensions/window-list/extension.js:419
|
||||
msgid "Unmaximize all"
|
||||
msgstr "Kado-kawe pathe-thuthe"
|
||||
|
||||
#: extensions/window-list/extension.js:427
|
||||
msgid "Close all"
|
||||
msgstr "Kado-kawe kanghap"
|
||||
|
||||
#: extensions/window-list/extension.js:642
|
||||
#: extensions/workspace-indicator/extension.js:20
|
||||
msgid "Workspace Indicator"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/window-list/extension.js:829
|
||||
msgid "Window List"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:12
|
||||
msgid "When to group windows"
|
||||
msgstr "Mentu hutsi windows muluk nangji"
|
||||
|
||||
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:13
|
||||
msgid ""
|
||||
"Decides when to group windows from the same application on the window list. "
|
||||
"Possible values are “never”, “auto” and “always”."
|
||||
msgstr ""
|
||||
|
||||
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:20
|
||||
msgid "Show the window list on all monitors"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:21
|
||||
msgid ""
|
||||
"Whether to show the window list on all connected monitors or only on the "
|
||||
"primary one."
|
||||
msgstr ""
|
||||
|
||||
#: extensions/window-list/prefs.js:25
|
||||
msgid "Window Grouping"
|
||||
msgstr "Window muluk"
|
||||
|
||||
#: extensions/window-list/prefs.js:47
|
||||
msgid "Never group windows"
|
||||
msgstr "Windows muluk ri"
|
||||
|
||||
#: extensions/window-list/prefs.js:48
|
||||
msgid "Group windows when space is limited"
|
||||
msgstr "Adim bihek te windows muluk noi"
|
||||
|
||||
#: extensions/window-list/prefs.js:49
|
||||
msgid "Always group windows"
|
||||
msgstr "Windows muluk vek nangji"
|
||||
|
||||
#: extensions/window-list/prefs.js:75
|
||||
msgid "Show on all monitors"
|
||||
msgstr ""
|
||||
|
||||
#: extensions/workspace-indicator/prefs.js:131
|
||||
msgid "Workspace Names"
|
||||
msgstr "Workspace amen hai"
|
||||
|
||||
#: extensions/workspace-indicator/prefs.js:151
|
||||
msgid "Name"
|
||||
msgstr "Amen"
|
||||
|
||||
#: extensions/workspace-indicator/prefs.js:191
|
||||
#, javascript-format
|
||||
msgid "Workspace %d"
|
||||
msgstr "Workspace amen %d"
|
||||
Reference in New Issue
Block a user