2014-03-13 22:51:10 +00:00
|
|
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*
|
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
import Clutter from 'gi://Clutter';
|
|
|
|
import Meta from 'gi://Meta';
|
|
|
|
import St from 'gi://St';
|
2014-03-13 22:51:10 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
import * as BoxPointer from './boxpointer.js';
|
|
|
|
import * as Main from './main.js';
|
|
|
|
import * as PopupMenu from './popupMenu.js';
|
|
|
|
import * as Screenshot from './screenshot.js';
|
2014-03-13 22:51:10 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
export class WindowMenu extends PopupMenu.PopupMenu {
|
2017-10-31 01:19:44 +00:00
|
|
|
constructor(window, sourceActor) {
|
|
|
|
super(sourceActor, 0, St.Side.TOP);
|
2014-03-13 22:51:10 +00:00
|
|
|
|
|
|
|
this.actor.add_style_class_name('window-menu');
|
|
|
|
|
|
|
|
Main.layoutManager.uiGroup.add_actor(this.actor);
|
|
|
|
this.actor.hide();
|
|
|
|
|
|
|
|
this._buildMenu(window);
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-03-13 22:51:10 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_buildMenu(window) {
|
2014-03-13 22:51:10 +00:00
|
|
|
let type = window.get_window_type();
|
|
|
|
|
|
|
|
let item;
|
|
|
|
|
2021-08-27 16:17:46 +00:00
|
|
|
// Translators: entry in the window right click menu.
|
|
|
|
item = this.addAction(_('Take Screenshot'), async () => {
|
|
|
|
try {
|
|
|
|
const actor = window.get_compositor_private();
|
|
|
|
const content = actor.paint_to_content(null);
|
|
|
|
const texture = content.get_texture();
|
|
|
|
|
|
|
|
await Screenshot.captureScreenshot(texture, null, 1, null);
|
|
|
|
} catch (e) {
|
|
|
|
logError(e, 'Error capturing screenshot');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-05-06 15:38:23 +00:00
|
|
|
item = this.addAction(_('Hide'), () => {
|
2014-03-13 22:51:10 +00:00
|
|
|
window.minimize();
|
2017-10-31 00:38:18 +00:00
|
|
|
});
|
2014-03-13 22:51:10 +00:00
|
|
|
if (!window.can_minimize())
|
|
|
|
item.setSensitive(false);
|
|
|
|
|
|
|
|
if (window.get_maximized()) {
|
2021-05-06 15:38:23 +00:00
|
|
|
item = this.addAction(_('Restore'), () => {
|
2014-03-13 22:51:10 +00:00
|
|
|
window.unmaximize(Meta.MaximizeFlags.BOTH);
|
2017-10-31 00:38:18 +00:00
|
|
|
});
|
2014-03-13 22:51:10 +00:00
|
|
|
} else {
|
2023-08-06 22:34:20 +00:00
|
|
|
item = this.addAction(_('Maximize'), () => {
|
2014-03-13 22:51:10 +00:00
|
|
|
window.maximize(Meta.MaximizeFlags.BOTH);
|
2017-10-31 00:38:18 +00:00
|
|
|
});
|
2014-03-13 22:51:10 +00:00
|
|
|
}
|
|
|
|
if (!window.can_maximize())
|
|
|
|
item.setSensitive(false);
|
|
|
|
|
2023-06-08 04:53:07 +00:00
|
|
|
item = this.addAction(_('Move'), event => {
|
2022-10-21 18:21:13 +00:00
|
|
|
const device = event.get_device();
|
|
|
|
const seat = device.get_seat();
|
|
|
|
const deviceType = device.get_device_type();
|
|
|
|
const pointer =
|
|
|
|
deviceType === Clutter.InputDeviceType.POINTER_DEVICE ||
|
|
|
|
deviceType === Clutter.InputDeviceType.TABLET_DEVICE ||
|
|
|
|
deviceType === Clutter.InputDeviceType.PEN_DEVICE ||
|
|
|
|
deviceType === Clutter.InputDeviceType.ERASER_DEVICE
|
|
|
|
? device : seat.get_pointer();
|
|
|
|
|
|
|
|
window.begin_grab_op(
|
|
|
|
Meta.GrabOp.KEYBOARD_MOVING,
|
|
|
|
pointer, null,
|
|
|
|
event.get_time());
|
2017-10-31 00:38:18 +00:00
|
|
|
});
|
2014-03-13 22:51:10 +00:00
|
|
|
if (!window.allows_move())
|
|
|
|
item.setSensitive(false);
|
|
|
|
|
2023-06-08 04:53:07 +00:00
|
|
|
item = this.addAction(_('Resize'), event => {
|
2022-10-21 18:21:13 +00:00
|
|
|
const device = event.get_device();
|
|
|
|
const seat = device.get_seat();
|
|
|
|
const deviceType = device.get_device_type();
|
|
|
|
const pointer =
|
|
|
|
deviceType === Clutter.InputDeviceType.POINTER_DEVICE ||
|
|
|
|
deviceType === Clutter.InputDeviceType.TABLET_DEVICE ||
|
|
|
|
deviceType === Clutter.InputDeviceType.PEN_DEVICE ||
|
|
|
|
deviceType === Clutter.InputDeviceType.ERASER_DEVICE
|
|
|
|
? device : seat.get_pointer();
|
|
|
|
|
|
|
|
window.begin_grab_op(
|
|
|
|
Meta.GrabOp.KEYBOARD_RESIZING_UNKNOWN,
|
|
|
|
pointer, null,
|
|
|
|
event.get_time());
|
2017-10-31 00:38:18 +00:00
|
|
|
});
|
2014-03-13 22:51:10 +00:00
|
|
|
if (!window.allows_resize())
|
|
|
|
item.setSensitive(false);
|
|
|
|
|
2023-08-07 00:51:19 +00:00
|
|
|
if (!window.titlebar_is_onscreen() && type !== Meta.WindowType.DOCK && type !== Meta.WindowType.DESKTOP) {
|
2023-08-06 22:34:20 +00:00
|
|
|
this.addAction(_('Move Titlebar Onscreen'), () => {
|
2014-03-13 22:51:10 +00:00
|
|
|
window.shove_titlebar_onscreen();
|
2017-10-31 00:38:18 +00:00
|
|
|
});
|
2014-03-13 22:51:10 +00:00
|
|
|
}
|
|
|
|
|
2023-08-06 22:34:20 +00:00
|
|
|
item = this.addAction(_('Always on Top'), () => {
|
2014-03-13 22:51:10 +00:00
|
|
|
if (window.is_above())
|
|
|
|
window.unmake_above();
|
|
|
|
else
|
|
|
|
window.make_above();
|
2017-10-31 00:38:18 +00:00
|
|
|
});
|
2014-03-13 22:51:10 +00:00
|
|
|
if (window.is_above())
|
2015-07-30 13:54:16 +00:00
|
|
|
item.setOrnament(PopupMenu.Ornament.CHECK);
|
2023-08-07 00:51:19 +00:00
|
|
|
if (window.get_maximized() === Meta.MaximizeFlags.BOTH ||
|
|
|
|
type === Meta.WindowType.DOCK ||
|
|
|
|
type === Meta.WindowType.DESKTOP ||
|
|
|
|
type === Meta.WindowType.SPLASHSCREEN)
|
2014-03-13 22:51:10 +00:00
|
|
|
item.setSensitive(false);
|
|
|
|
|
2014-05-23 16:38:23 +00:00
|
|
|
if (Main.sessionMode.hasWorkspaces &&
|
|
|
|
(!Meta.prefs_get_workspaces_only_on_primary() ||
|
|
|
|
window.is_on_primary_monitor())) {
|
2014-03-13 22:51:10 +00:00
|
|
|
let isSticky = window.is_on_all_workspaces();
|
|
|
|
|
2023-08-06 22:34:20 +00:00
|
|
|
item = this.addAction(_('Always on Visible Workspace'), () => {
|
2014-03-13 22:51:10 +00:00
|
|
|
if (isSticky)
|
|
|
|
window.unstick();
|
|
|
|
else
|
|
|
|
window.stick();
|
2017-10-31 00:38:18 +00:00
|
|
|
});
|
2014-03-13 22:51:10 +00:00
|
|
|
if (isSticky)
|
2015-07-30 13:54:16 +00:00
|
|
|
item.setOrnament(PopupMenu.Ornament.CHECK);
|
2014-03-13 22:51:10 +00:00
|
|
|
if (window.is_always_on_all_workspaces())
|
|
|
|
item.setSensitive(false);
|
|
|
|
|
|
|
|
if (!isSticky) {
|
|
|
|
let workspace = window.get_workspace();
|
2023-08-07 00:51:19 +00:00
|
|
|
if (workspace !== workspace.get_neighbor(Meta.MotionDirection.LEFT)) {
|
2023-08-06 22:34:20 +00:00
|
|
|
this.addAction(_('Move to Workspace Left'), () => {
|
2017-10-31 00:38:18 +00:00
|
|
|
let dir = Meta.MotionDirection.LEFT;
|
|
|
|
window.change_workspace(workspace.get_neighbor(dir));
|
|
|
|
});
|
2015-06-22 21:10:50 +00:00
|
|
|
}
|
2023-08-07 00:51:19 +00:00
|
|
|
if (workspace !== workspace.get_neighbor(Meta.MotionDirection.RIGHT)) {
|
2023-08-06 22:34:20 +00:00
|
|
|
this.addAction(_('Move to Workspace Right'), () => {
|
2017-10-31 00:38:18 +00:00
|
|
|
let dir = Meta.MotionDirection.RIGHT;
|
|
|
|
window.change_workspace(workspace.get_neighbor(dir));
|
|
|
|
});
|
2015-06-22 21:10:50 +00:00
|
|
|
}
|
2023-08-07 00:51:19 +00:00
|
|
|
if (workspace !== workspace.get_neighbor(Meta.MotionDirection.UP)) {
|
2023-08-06 22:34:20 +00:00
|
|
|
this.addAction(_('Move to Workspace Up'), () => {
|
2017-10-31 00:38:18 +00:00
|
|
|
let dir = Meta.MotionDirection.UP;
|
|
|
|
window.change_workspace(workspace.get_neighbor(dir));
|
|
|
|
});
|
2014-03-13 22:51:10 +00:00
|
|
|
}
|
2023-08-07 00:51:19 +00:00
|
|
|
if (workspace !== workspace.get_neighbor(Meta.MotionDirection.DOWN)) {
|
2023-08-06 22:34:20 +00:00
|
|
|
this.addAction(_('Move to Workspace Down'), () => {
|
2017-10-31 00:38:18 +00:00
|
|
|
let dir = Meta.MotionDirection.DOWN;
|
|
|
|
window.change_workspace(workspace.get_neighbor(dir));
|
|
|
|
});
|
2014-03-13 22:51:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-03 07:55:38 +00:00
|
|
|
let display = global.display;
|
|
|
|
let nMonitors = display.get_n_monitors();
|
2017-10-11 10:42:04 +00:00
|
|
|
let monitorIndex = window.get_monitor();
|
|
|
|
if (nMonitors > 1 && monitorIndex >= 0) {
|
2017-10-31 00:38:18 +00:00
|
|
|
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
|
|
|
2018-09-11 10:55:55 +00:00
|
|
|
let dir = Meta.DisplayDirection.UP;
|
2017-10-31 00:38:18 +00:00
|
|
|
let upMonitorIndex =
|
2018-01-03 07:55:38 +00:00
|
|
|
display.get_monitor_neighbor_index(monitorIndex, dir);
|
2023-08-07 00:51:19 +00:00
|
|
|
if (upMonitorIndex !== -1) {
|
2023-08-06 22:34:20 +00:00
|
|
|
this.addAction(_('Move to Monitor Up'), () => {
|
2017-10-31 00:38:18 +00:00
|
|
|
window.move_to_monitor(upMonitorIndex);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-09-11 10:55:55 +00:00
|
|
|
dir = Meta.DisplayDirection.DOWN;
|
2017-10-31 00:38:18 +00:00
|
|
|
let downMonitorIndex =
|
2018-01-03 07:55:38 +00:00
|
|
|
display.get_monitor_neighbor_index(monitorIndex, dir);
|
2023-08-07 00:51:19 +00:00
|
|
|
if (downMonitorIndex !== -1) {
|
2023-08-06 22:34:20 +00:00
|
|
|
this.addAction(_('Move to Monitor Down'), () => {
|
2017-10-31 00:38:18 +00:00
|
|
|
window.move_to_monitor(downMonitorIndex);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-09-11 10:55:55 +00:00
|
|
|
dir = Meta.DisplayDirection.LEFT;
|
2017-10-31 00:38:18 +00:00
|
|
|
let leftMonitorIndex =
|
2018-01-03 07:55:38 +00:00
|
|
|
display.get_monitor_neighbor_index(monitorIndex, dir);
|
2023-08-07 00:51:19 +00:00
|
|
|
if (leftMonitorIndex !== -1) {
|
2023-08-06 22:34:20 +00:00
|
|
|
this.addAction(_('Move to Monitor Left'), () => {
|
2017-10-31 00:38:18 +00:00
|
|
|
window.move_to_monitor(leftMonitorIndex);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-09-11 10:55:55 +00:00
|
|
|
dir = Meta.DisplayDirection.RIGHT;
|
2017-10-31 00:38:18 +00:00
|
|
|
let rightMonitorIndex =
|
2018-01-03 07:55:38 +00:00
|
|
|
display.get_monitor_neighbor_index(monitorIndex, dir);
|
2023-08-07 00:51:19 +00:00
|
|
|
if (rightMonitorIndex !== -1) {
|
2023-08-06 22:34:20 +00:00
|
|
|
this.addAction(_('Move to Monitor Right'), () => {
|
2017-10-31 00:38:18 +00:00
|
|
|
window.move_to_monitor(rightMonitorIndex);
|
|
|
|
});
|
|
|
|
}
|
2015-03-24 03:19:46 +00:00
|
|
|
}
|
|
|
|
|
2014-03-13 22:51:10 +00:00
|
|
|
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
|
|
|
2023-08-06 22:34:20 +00:00
|
|
|
item = this.addAction(_('Close'), event => {
|
2014-05-21 17:53:50 +00:00
|
|
|
window.delete(event.get_time());
|
2017-10-31 00:38:18 +00:00
|
|
|
});
|
2014-03-13 22:51:10 +00:00
|
|
|
if (!window.can_close())
|
|
|
|
item.setSensitive(false);
|
|
|
|
}
|
2023-07-10 09:53:00 +00:00
|
|
|
}
|
2014-05-24 01:32:44 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
export class WindowMenuManager {
|
2017-10-31 01:19:44 +00:00
|
|
|
constructor() {
|
2019-04-09 23:23:59 +00:00
|
|
|
this._manager = new PopupMenu.PopupMenuManager(Main.layoutManager.dummyCursor);
|
2014-05-31 03:19:20 +00:00
|
|
|
|
2023-08-06 22:40:20 +00:00
|
|
|
this._sourceActor = new St.Widget({reactive: true, visible: false});
|
2017-10-31 00:38:18 +00:00
|
|
|
this._sourceActor.connect('button-press-event', () => {
|
|
|
|
this._manager.activeMenu.toggle();
|
|
|
|
});
|
2014-05-31 03:19:20 +00:00
|
|
|
Main.uiGroup.add_actor(this._sourceActor);
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-03-13 22:51:10 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
showWindowMenuForWindow(window, type, rect) {
|
2017-06-03 22:37:36 +00:00
|
|
|
if (!Main.sessionMode.hasWmMenus)
|
|
|
|
return;
|
|
|
|
|
2023-08-07 00:51:19 +00:00
|
|
|
if (type !== Meta.WindowMenuType.WM)
|
2018-10-04 15:14:00 +00:00
|
|
|
throw new Error('Unsupported window menu type');
|
|
|
|
let menu = new WindowMenu(window, this._sourceActor);
|
2014-05-24 01:32:44 +00:00
|
|
|
|
2014-03-13 22:51:10 +00:00
|
|
|
this._manager.addMenu(menu);
|
|
|
|
|
2017-10-31 00:38:18 +00:00
|
|
|
menu.connect('activate', () => {
|
2014-05-27 15:32:34 +00:00
|
|
|
window.check_alive(global.get_current_time());
|
|
|
|
});
|
2017-10-31 00:38:18 +00:00
|
|
|
let destroyId = window.connect('unmanaged', () => {
|
|
|
|
menu.close();
|
|
|
|
});
|
2014-05-27 15:32:34 +00:00
|
|
|
|
2015-10-19 17:06:28 +00:00
|
|
|
this._sourceActor.set_size(Math.max(1, rect.width), Math.max(1, rect.height));
|
2014-05-31 03:19:20 +00:00
|
|
|
this._sourceActor.set_position(rect.x, rect.y);
|
|
|
|
this._sourceActor.show();
|
|
|
|
|
2019-09-12 16:01:46 +00:00
|
|
|
menu.open(BoxPointer.PopupAnimation.FADE);
|
2018-11-27 12:58:25 +00:00
|
|
|
menu.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
|
2017-10-31 00:38:18 +00:00
|
|
|
menu.connect('open-state-changed', (menu_, isOpen) => {
|
2014-05-31 03:19:20 +00:00
|
|
|
if (isOpen)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._sourceActor.hide();
|
|
|
|
menu.destroy();
|
2015-05-21 16:14:51 +00:00
|
|
|
window.disconnect(destroyId);
|
2017-10-31 00:38:18 +00:00
|
|
|
});
|
2014-05-24 01:32:44 +00:00
|
|
|
}
|
2023-07-10 09:53:00 +00:00
|
|
|
}
|