762903618d
Instead of requiring the user to open the prefs dialog to change workspace names, make the menu items themselves editable. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/405>
696 lines
21 KiB
JavaScript
696 lines
21 KiB
JavaScript
// SPDX-FileCopyrightText: 2011 Erick Pérez Castellanos <erick.red@gmail.com>
|
|
// SPDX-FileCopyrightText: 2011 Giovanni Campagna <gcampagna@src.gnome.org>
|
|
// SPDX-FileCopyrightText: 2017 Florian Müllner <fmuellner@gnome.org>
|
|
//
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
import Clutter from 'gi://Clutter';
|
|
import Gio from 'gi://Gio';
|
|
import GObject from 'gi://GObject';
|
|
import Meta from 'gi://Meta';
|
|
import Shell from 'gi://Shell';
|
|
import St from 'gi://St';
|
|
|
|
import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js';
|
|
|
|
import * as DND from 'resource:///org/gnome/shell/ui/dnd.js';
|
|
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
|
|
import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js';
|
|
import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js';
|
|
|
|
const TOOLTIP_OFFSET = 6;
|
|
const TOOLTIP_ANIMATION_TIME = 150;
|
|
|
|
const SCROLL_TIME = 100;
|
|
|
|
let baseStyleClassName = '';
|
|
|
|
class WindowPreview extends St.Button {
|
|
static {
|
|
GObject.registerClass(this);
|
|
}
|
|
|
|
constructor(window) {
|
|
super({
|
|
style_class: `${baseStyleClassName}-window-preview`,
|
|
});
|
|
|
|
this._delegate = this;
|
|
DND.makeDraggable(this, {restoreOnSuccess: true});
|
|
|
|
this._window = window;
|
|
|
|
this._window.connectObject(
|
|
'size-changed', () => this._checkRelayout(),
|
|
'position-changed', () => this._checkRelayout(),
|
|
'notify::minimized', this._updateVisible.bind(this),
|
|
'notify::skip-taskbar', this._updateVisible.bind(this),
|
|
this);
|
|
this._updateVisible();
|
|
|
|
global.display.connectObject('notify::focus-window',
|
|
this._onFocusChanged.bind(this), this);
|
|
this._onFocusChanged();
|
|
}
|
|
|
|
// needed for DND
|
|
get metaWindow() {
|
|
return this._window;
|
|
}
|
|
|
|
_onFocusChanged() {
|
|
if (global.display.focus_window === this._window)
|
|
this.add_style_class_name('active');
|
|
else
|
|
this.remove_style_class_name('active');
|
|
}
|
|
|
|
_checkRelayout() {
|
|
const monitor = Main.layoutManager.findIndexForActor(this);
|
|
const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
|
|
if (this._window.get_frame_rect().overlap(workArea))
|
|
this.queue_relayout();
|
|
}
|
|
|
|
_updateVisible() {
|
|
this.visible = !this._window.skip_taskbar &&
|
|
this._window.showing_on_its_workspace();
|
|
}
|
|
}
|
|
|
|
class WorkspaceLayout extends Clutter.LayoutManager {
|
|
static {
|
|
GObject.registerClass(this);
|
|
}
|
|
|
|
vfunc_get_preferred_width() {
|
|
return [0, 0];
|
|
}
|
|
|
|
vfunc_get_preferred_height() {
|
|
return [0, 0];
|
|
}
|
|
|
|
vfunc_allocate(container, box) {
|
|
const monitor = Main.layoutManager.findIndexForActor(container);
|
|
const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
|
|
const hscale = box.get_width() / workArea.width;
|
|
const vscale = box.get_height() / workArea.height;
|
|
|
|
for (const child of container) {
|
|
const childBox = new Clutter.ActorBox();
|
|
const frameRect = child.metaWindow.get_frame_rect();
|
|
childBox.set_size(
|
|
Math.round(Math.min(frameRect.width, workArea.width) * hscale),
|
|
Math.round(Math.min(frameRect.height, workArea.height) * vscale));
|
|
childBox.set_origin(
|
|
Math.round((frameRect.x - workArea.x) * hscale),
|
|
Math.round((frameRect.y - workArea.y) * vscale));
|
|
child.allocate(childBox);
|
|
}
|
|
}
|
|
}
|
|
|
|
class WorkspaceThumbnail extends St.Button {
|
|
static [GObject.properties] = {
|
|
'active': GObject.ParamSpec.boolean(
|
|
'active', null, null,
|
|
GObject.ParamFlags.READWRITE,
|
|
false),
|
|
};
|
|
|
|
static {
|
|
GObject.registerClass(this);
|
|
}
|
|
|
|
constructor(index) {
|
|
super();
|
|
|
|
const box = new St.BoxLayout({
|
|
style_class: 'workspace-box',
|
|
y_expand: true,
|
|
orientation: Clutter.Orientation.VERTICAL,
|
|
});
|
|
this.set_child(box);
|
|
|
|
this._preview = new St.Bin({
|
|
style_class: 'workspace',
|
|
child: new Clutter.Actor({
|
|
layout_manager: new WorkspaceLayout(),
|
|
clip_to_allocation: true,
|
|
x_expand: true,
|
|
y_expand: true,
|
|
}),
|
|
y_expand: true,
|
|
});
|
|
box.add_child(this._preview);
|
|
|
|
this._tooltip = new St.Label({
|
|
style_class: 'dash-label',
|
|
visible: false,
|
|
});
|
|
Main.uiGroup.add_child(this._tooltip);
|
|
|
|
this.connect('destroy', this._onDestroy.bind(this));
|
|
this.connect('notify::hover', this._syncTooltip.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._workspace.bind_property('active',
|
|
this, 'active',
|
|
GObject.BindingFlags.SYNC_CREATE);
|
|
|
|
this._workspace.connectObject(
|
|
'window-added', (ws, window) => this._addWindow(window),
|
|
'window-removed', (ws, window) => this._removeWindow(window),
|
|
this);
|
|
|
|
global.display.connectObject('restacked',
|
|
this._onRestacked.bind(this), this);
|
|
|
|
this._workspace.list_windows().forEach(w => this._addWindow(w));
|
|
this._onRestacked();
|
|
}
|
|
|
|
get active() {
|
|
return this._preview.has_style_class_name('active');
|
|
}
|
|
|
|
set active(active) {
|
|
if (active)
|
|
this._preview.add_style_class_name('active');
|
|
else
|
|
this._preview.remove_style_class_name('active');
|
|
this.notify('active');
|
|
}
|
|
|
|
acceptDrop(source) {
|
|
if (!source.metaWindow)
|
|
return false;
|
|
|
|
this._moveWindow(source.metaWindow);
|
|
return true;
|
|
}
|
|
|
|
handleDragOver(source) {
|
|
if (source.metaWindow)
|
|
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._preview.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._preview.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());
|
|
}
|
|
|
|
_syncTooltip() {
|
|
if (this.hover) {
|
|
this._tooltip.set({
|
|
text: Meta.prefs_get_workspace_name(this._index),
|
|
visible: true,
|
|
opacity: 0,
|
|
});
|
|
|
|
const [stageX, stageY] = this.get_transformed_position();
|
|
const [thumbWidth, thumbHeight] = this.allocation.get_size();
|
|
const [tipWidth, tipHeight] = this._tooltip.get_size();
|
|
const xOffset = Math.floor((thumbWidth - tipWidth) / 2);
|
|
const monitor = Main.layoutManager.findMonitorForActor(this);
|
|
const x = Math.clamp(
|
|
stageX + xOffset,
|
|
monitor.x,
|
|
monitor.x + monitor.width - tipWidth);
|
|
const y = stageY - monitor.y > thumbHeight + TOOLTIP_OFFSET
|
|
? stageY - tipHeight - TOOLTIP_OFFSET // show above
|
|
: stageY + thumbHeight + TOOLTIP_OFFSET; // show below
|
|
this._tooltip.set_position(x, y);
|
|
}
|
|
|
|
this._tooltip.ease({
|
|
opacity: this.hover ? 255 : 0,
|
|
duration: TOOLTIP_ANIMATION_TIME,
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
|
onComplete: () => (this._tooltip.visible = this.hover),
|
|
});
|
|
}
|
|
|
|
_onDestroy() {
|
|
this._tooltip.destroy();
|
|
}
|
|
}
|
|
|
|
class WorkspacePreviews extends Clutter.Actor {
|
|
static {
|
|
GObject.registerClass(this);
|
|
}
|
|
|
|
constructor(params) {
|
|
super({
|
|
...params,
|
|
layout_manager: new Clutter.BinLayout(),
|
|
reactive: true,
|
|
y_expand: true,
|
|
});
|
|
|
|
this.connect('scroll-event',
|
|
(a, event) => Main.wm.handleWorkspaceScroll(event));
|
|
|
|
const {workspaceManager} = global;
|
|
|
|
workspaceManager.connectObject(
|
|
'notify::n-workspaces', () => this._updateThumbnails(), GObject.ConnectFlags.AFTER,
|
|
'workspace-switched', () => this._updateScrollPosition(),
|
|
this);
|
|
|
|
this.connect('notify::mapped', () => {
|
|
if (this.mapped)
|
|
this._updateScrollPosition();
|
|
});
|
|
|
|
this._thumbnailsBox = new St.BoxLayout({
|
|
style_class: 'workspaces-box',
|
|
y_expand: true,
|
|
});
|
|
|
|
this._scrollView = new St.ScrollView({
|
|
style_class: 'workspaces-view hfade',
|
|
enable_mouse_scrolling: false,
|
|
hscrollbar_policy: St.PolicyType.EXTERNAL,
|
|
vscrollbar_policy: St.PolicyType.NEVER,
|
|
y_expand: true,
|
|
child: this._thumbnailsBox,
|
|
});
|
|
|
|
this.add_child(this._scrollView);
|
|
|
|
this._updateThumbnails();
|
|
}
|
|
|
|
_updateThumbnails() {
|
|
const {nWorkspaces} = global.workspace_manager;
|
|
|
|
this._thumbnailsBox.destroy_all_children();
|
|
|
|
for (let i = 0; i < nWorkspaces; i++)
|
|
this._thumbnailsBox.add_child(new WorkspaceThumbnail(i));
|
|
|
|
if (this.mapped)
|
|
this._updateScrollPosition();
|
|
}
|
|
|
|
_updateScrollPosition() {
|
|
const adjustment = this._scrollView.hadjustment;
|
|
const {upper, pageSize} = adjustment;
|
|
let {value} = adjustment;
|
|
|
|
const activeWorkspace =
|
|
[...this._thumbnailsBox].find(a => a.active);
|
|
|
|
if (!activeWorkspace)
|
|
return;
|
|
|
|
let offset = 0;
|
|
const hfade = this._scrollView.get_effect('fade');
|
|
if (hfade)
|
|
offset = hfade.fade_margins.left;
|
|
|
|
let {x1, x2} = activeWorkspace.get_allocation_box();
|
|
let parent = activeWorkspace.get_parent();
|
|
while (parent !== this._scrollView) {
|
|
if (!parent)
|
|
throw new Error('actor not in scroll view');
|
|
|
|
const box = parent.get_allocation_box();
|
|
x1 += box.x1;
|
|
x2 += box.x1;
|
|
parent = parent.get_parent();
|
|
}
|
|
|
|
if (x1 < value + offset)
|
|
value = Math.max(0, x1 - offset);
|
|
else if (x2 > value + pageSize - offset)
|
|
value = Math.min(upper, x2 + offset - pageSize);
|
|
else
|
|
return;
|
|
|
|
adjustment.ease(value, {
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
|
duration: SCROLL_TIME,
|
|
});
|
|
}
|
|
}
|
|
|
|
class EditableMenuItem extends PopupMenu.PopupBaseMenuItem {
|
|
static [GObject.signals] = {
|
|
'edited': {},
|
|
};
|
|
|
|
static {
|
|
GObject.registerClass(this);
|
|
}
|
|
|
|
constructor() {
|
|
super({
|
|
style_class: 'editable-menu-item',
|
|
});
|
|
this.get_accessible()?.set_description(
|
|
_('Press %s to edit').format('e'));
|
|
|
|
const stack = new Shell.Stack({
|
|
x_expand: true,
|
|
x_align: Clutter.ActorAlign.START,
|
|
});
|
|
this.add_child(stack);
|
|
|
|
this.label = new St.Label({
|
|
y_align: Clutter.ActorAlign.CENTER,
|
|
});
|
|
stack.add_child(this.label);
|
|
this.label_actor = this.label;
|
|
|
|
this._entry = new St.Entry({
|
|
opacity: 0,
|
|
reactive: false,
|
|
});
|
|
stack.add_child(this._entry);
|
|
|
|
this.label.bind_property('text',
|
|
this._entry, 'text',
|
|
GObject.BindingFlags.DEFAULT);
|
|
|
|
this._entry.clutter_text.connect('activate',
|
|
() => this._stopEditing());
|
|
|
|
this._editButton = new St.Button({
|
|
style_class: 'icon-button flat',
|
|
icon_name: 'document-edit-symbolic',
|
|
button_mask: St.ButtonMask.ONE,
|
|
toggle_mode: true,
|
|
x_align: Clutter.ActorAlign.END,
|
|
y_align: Clutter.ActorAlign.CENTER,
|
|
});
|
|
this.add_child(this._editButton);
|
|
|
|
this._editButton.connect('notify::checked', () => {
|
|
if (this._editButton.checked) {
|
|
this._editButton.icon_name = 'ornament-check-symbolic';
|
|
this._startEditing();
|
|
} else {
|
|
this._editButton.icon_name = 'document-edit-symbolic';
|
|
this._stopEditing();
|
|
}
|
|
});
|
|
this.connect('key-release-event', (o, event) => {
|
|
if (event.get_key_symbol() === Clutter.KEY_e)
|
|
this._editButton.checked = true;
|
|
});
|
|
|
|
global.stage.connectObject('notify::key-focus', () => {
|
|
const {keyFocus} = global.stage;
|
|
if (!keyFocus || !this.contains(keyFocus))
|
|
this._stopEditing();
|
|
}, this);
|
|
}
|
|
|
|
_switchActor(from, to) {
|
|
to.reactive = true;
|
|
to.ease({
|
|
opacity: 255,
|
|
duration: 300,
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
|
});
|
|
|
|
from.ease({
|
|
opacity: 0,
|
|
duration: 300,
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
|
onComplete: () => {
|
|
from.reactive = false;
|
|
},
|
|
});
|
|
}
|
|
|
|
_startEditing() {
|
|
this._switchActor(this.label, this._entry);
|
|
|
|
this._entry.clutter_text.set_selection(0, -1);
|
|
this._entry.clutter_text.grab_key_focus();
|
|
}
|
|
|
|
_stopEditing() {
|
|
if (this.label.text !== this._entry.text) {
|
|
this.label.text = this._entry.text;
|
|
this.emit('edited');
|
|
}
|
|
|
|
if (this._editButton.checked)
|
|
this._editButton.checked = false;
|
|
|
|
this._switchActor(this._entry, this.label);
|
|
this.navigate_focus(this, St.DirectionType.TAB_FORWARD, false);
|
|
}
|
|
}
|
|
|
|
class WorkspacesMenu extends PopupMenu.PopupMenu {
|
|
constructor(sourceActor) {
|
|
super(sourceActor, 0.5, St.Side.TOP);
|
|
|
|
this.actor.add_style_class_name(`${baseStyleClassName}-menu`);
|
|
|
|
this._workspacesSection = new PopupMenu.PopupMenuSection();
|
|
this.addMenuItem(this._workspacesSection);
|
|
|
|
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
|
|
this.addAction(_('Settings'), () => {
|
|
const extension = Extension.lookupByURL(import.meta.url);
|
|
extension.openPreferences();
|
|
});
|
|
|
|
this._desktopSettings =
|
|
new Gio.Settings({schema_id: 'org.gnome.desktop.wm.preferences'});
|
|
this._desktopSettings.connectObject('changed::workspace-names', () => {
|
|
this._updateWorkspaceLabels();
|
|
this.emit('active-name-changed');
|
|
}, this);
|
|
|
|
const {workspaceManager} = global;
|
|
workspaceManager.connectObject(
|
|
'notify::n-workspaces', () => this._updateWorkspaceItems(),
|
|
'workspace-switched', () => this._updateActiveIndicator(),
|
|
this.actor);
|
|
this._updateWorkspaceItems();
|
|
}
|
|
|
|
get activeName() {
|
|
const {workspaceManager} = global;
|
|
const active = workspaceManager.get_active_workspace_index();
|
|
return Meta.prefs_get_workspace_name(active);
|
|
}
|
|
|
|
_updateWorkspaceItems() {
|
|
const {workspaceManager} = global;
|
|
const {nWorkspaces} = workspaceManager;
|
|
|
|
const section = this._workspacesSection.actor;
|
|
while (section.get_n_children() < nWorkspaces) {
|
|
const item = new EditableMenuItem();
|
|
item.connect('activate', (o, event) => {
|
|
const index = [...section].indexOf(item);
|
|
const workspace = workspaceManager.get_workspace_by_index(index);
|
|
workspace?.activate(event.get_time());
|
|
});
|
|
item.connect('edited', () => {
|
|
const nLabels = section.get_n_children();
|
|
const oldNames = this._desktopSettings.get_strv('workspace-names');
|
|
const newNames = [...section].map(c => c.label.text);
|
|
this._desktopSettings.set_strv('workspace-names',
|
|
[...newNames, ...oldNames.slice(nLabels)]);
|
|
});
|
|
this._workspacesSection.addMenuItem(item);
|
|
}
|
|
|
|
[...section].splice(nWorkspaces).forEach(item => item.destroy());
|
|
|
|
this._updateWorkspaceLabels();
|
|
this._updateActiveIndicator();
|
|
}
|
|
|
|
_updateWorkspaceLabels() {
|
|
const items = [...this._workspacesSection.actor];
|
|
items.forEach(
|
|
(item, i) => (item.label.text = Meta.prefs_get_workspace_name(i)));
|
|
}
|
|
|
|
_updateActiveIndicator() {
|
|
const {workspaceManager} = global;
|
|
const active = workspaceManager.get_active_workspace_index();
|
|
|
|
const items = [...this._workspacesSection.actor];
|
|
items.forEach((item, i) => {
|
|
item.setOrnament(i === active
|
|
? PopupMenu.Ornament.CHECK
|
|
: PopupMenu.Ornament.NONE);
|
|
});
|
|
this.emit('active-name-changed');
|
|
}
|
|
}
|
|
|
|
export class WorkspaceIndicator extends PanelMenu.Button {
|
|
static {
|
|
GObject.registerClass(this);
|
|
}
|
|
|
|
constructor(params = {}) {
|
|
super(0.5, _('Workspace Indicator'), true);
|
|
|
|
const {
|
|
baseStyleClass = 'workspace-indicator',
|
|
settings,
|
|
} = params;
|
|
|
|
this._settings = settings;
|
|
|
|
baseStyleClassName = baseStyleClass;
|
|
this.add_style_class_name(baseStyleClassName);
|
|
|
|
this.setMenu(new WorkspacesMenu(this));
|
|
|
|
let container = new St.Widget({
|
|
layout_manager: new Clutter.BinLayout(),
|
|
x_expand: true,
|
|
y_expand: true,
|
|
});
|
|
this.add_child(container);
|
|
|
|
this._statusBox = new St.BoxLayout();
|
|
container.add_child(this._statusBox);
|
|
|
|
this._statusLabel = new St.Label({
|
|
style_class: 'status-label',
|
|
x_expand: true,
|
|
y_align: Clutter.ActorAlign.CENTER,
|
|
text: this.menu.activeName,
|
|
});
|
|
this._statusBox.add_child(this._statusLabel);
|
|
this._statusBox.add_child(new St.Icon({
|
|
icon_name: 'pan-down-symbolic',
|
|
style_class: 'system-status-icon',
|
|
}));
|
|
|
|
this.menu.connect('active-name-changed',
|
|
() => this._statusLabel.set_text(this.menu.activeName));
|
|
|
|
this._thumbnails = new WorkspacePreviews();
|
|
container.add_child(this._thumbnails);
|
|
|
|
this._thumbnails.connect('button-press-event', (a, event) => {
|
|
if (event.get_button() !== Clutter.BUTTON_SECONDARY)
|
|
return Clutter.EVENT_PROPAGATE;
|
|
|
|
this.menu.toggle();
|
|
return Clutter.EVENT_STOP;
|
|
});
|
|
|
|
this.connect('scroll-event',
|
|
(a, event) => Main.wm.handleWorkspaceScroll(event));
|
|
|
|
this._inTopBar = false;
|
|
this.connect('notify::realized', () => {
|
|
if (!this.realized)
|
|
return;
|
|
|
|
this._inTopBar = Main.panel.contains(this);
|
|
this._updateTopBarRedirect();
|
|
});
|
|
|
|
this._settings.connect('changed::embed-previews',
|
|
() => this._updateThumbnailVisibility());
|
|
this._updateThumbnailVisibility();
|
|
}
|
|
|
|
_onDestroy() {
|
|
if (this._inTopBar)
|
|
Main.panel.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
|
|
this._inTopBar = false;
|
|
|
|
super._onDestroy();
|
|
}
|
|
|
|
_updateThumbnailVisibility() {
|
|
const usePreviews = this._settings.get_boolean('embed-previews');
|
|
this.reactive = !usePreviews;
|
|
|
|
this._thumbnails.visible = usePreviews;
|
|
this._statusBox.visible = !usePreviews;
|
|
|
|
if (usePreviews) {
|
|
this.add_style_class_name('previews');
|
|
this.remove_style_class_name('name-label');
|
|
} else {
|
|
this.remove_style_class_name('previews');
|
|
this.add_style_class_name('name-label');
|
|
}
|
|
|
|
this._updateTopBarRedirect();
|
|
}
|
|
|
|
_updateTopBarRedirect() {
|
|
if (!this._inTopBar)
|
|
return;
|
|
|
|
// Disable offscreen-redirect when showing the workspace switcher
|
|
// so that clip-to-allocation works
|
|
Main.panel.set_offscreen_redirect(this._thumbnails.visible
|
|
? Clutter.OffscreenRedirect.ALWAYS
|
|
: Clutter.OffscreenRedirect.AUTOMATIC_FOR_OPACITY);
|
|
}
|
|
}
|