2017-06-08 14:49:20 +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 GObject from 'gi://GObject';
|
|
|
|
import Meta from 'gi://Meta';
|
|
|
|
import St from 'gi://St';
|
2017-06-08 14:49:20 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
import * as SwitcherPopup from './switcherPopup.js';
|
2017-06-08 14:49:20 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
const APP_ICON_SIZE = 96;
|
2017-06-08 14:49:20 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
export const SwitchMonitorPopup = GObject.registerClass(
|
2017-10-31 01:23:39 +00:00
|
|
|
class SwitchMonitorPopup extends SwitcherPopup.SwitcherPopup {
|
2017-10-31 00:03:21 +00:00
|
|
|
_init() {
|
2021-12-02 21:04:01 +00:00
|
|
|
let items = [];
|
|
|
|
|
|
|
|
items.push({
|
|
|
|
icon: 'view-mirror-symbolic',
|
|
|
|
/* Translators: this is for display mirroring i.e. cloning.
|
|
|
|
* Try to keep it under around 15 characters.
|
|
|
|
*/
|
|
|
|
label: _('Mirror'),
|
2022-03-19 15:53:59 +00:00
|
|
|
configType: Meta.MonitorSwitchConfigType.ALL_MIRROR,
|
2021-12-02 21:04:01 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
items.push({
|
|
|
|
icon: 'video-joined-displays-symbolic',
|
|
|
|
/* Translators: this is for the desktop spanning displays.
|
|
|
|
* Try to keep it under around 15 characters.
|
|
|
|
*/
|
|
|
|
label: _('Join Displays'),
|
2022-03-19 15:53:59 +00:00
|
|
|
configType: Meta.MonitorSwitchConfigType.ALL_LINEAR,
|
2021-12-02 21:04:01 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
if (global.backend.get_monitor_manager().has_builtin_panel) {
|
|
|
|
items.push({
|
|
|
|
icon: 'video-single-display-symbolic',
|
|
|
|
/* Translators: this is for using only an external display.
|
|
|
|
* Try to keep it under around 15 characters.
|
|
|
|
*/
|
|
|
|
label: _('External Only'),
|
2022-03-19 15:53:59 +00:00
|
|
|
configType: Meta.MonitorSwitchConfigType.EXTERNAL,
|
2021-12-02 21:04:01 +00:00
|
|
|
});
|
|
|
|
items.push({
|
|
|
|
icon: 'computer-symbolic',
|
|
|
|
/* Translators: this is for using only the laptop display.
|
|
|
|
* Try to keep it under around 15 characters.
|
|
|
|
*/
|
|
|
|
label: _('Built-in Only'),
|
2022-03-19 15:53:59 +00:00
|
|
|
configType: Meta.MonitorSwitchConfigType.BUILTIN,
|
2021-12-02 21:04:01 +00:00
|
|
|
});
|
|
|
|
}
|
2017-06-08 14:49:20 +00:00
|
|
|
|
2017-10-31 01:23:39 +00:00
|
|
|
super._init(items);
|
2017-06-08 14:49:20 +00:00
|
|
|
|
|
|
|
this._switcherList = new SwitchMonitorSwitcher(items);
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2017-06-08 14:49:20 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
show(backward, binding, mask) {
|
2022-09-07 18:24:44 +00:00
|
|
|
if (!global.backend.get_monitor_manager().can_switch_config())
|
2017-06-08 14:49:20 +00:00
|
|
|
return false;
|
|
|
|
|
2017-10-31 01:23:39 +00:00
|
|
|
return super.show(backward, binding, mask);
|
|
|
|
}
|
2017-06-08 14:49:20 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_initialSelection() {
|
2022-09-07 18:24:44 +00:00
|
|
|
let currentConfig = global.backend.get_monitor_manager().get_switch_config();
|
2022-08-29 08:45:05 +00:00
|
|
|
let selectConfig = (currentConfig + 1) % this._items.length;
|
switchMonitor: switch to next config upon initial keypress
In GNOME-3.24, pressing Super+P or a similar function key would cause
a switch to the next available monitor configuration.
However, in GNOME-3.26, this was reimplemented in mutter and gnome-shell
and the behaviour is now different: pressing Super+P and releasing will
cause no change in montor configuration[1]. In this new design you have
to press Super+P and keep holding Super in order to keep the switcher
open, then press P again (or use the arrow keys or mouse) to
select the next one in the list.
This is incompatible with many Asus products such as Asus X530UN, where
pressing the presentation mode media key (Fn+F8) actually generates
the following keypress events from the keyboard controller:
Fn pressed: nothing
F8 pressed: nothing
F8 released: Super press, p press, p release, Super release (quick burst)
Fn released: nothing
With this firmware behaviour it's not possible to hold the keys and have
the dialog come up so that you can select another new mode.
To solve this, when the switcher is opened, select the next available
display config by default, which is more similar to the pre-GNOME-3.26
behaviour. Now pressing Fn+F8 on this laptop will result in the display
mode switch taking place.
[1]: The mentioned desired behaviour will at least happen after
https://gitlab.gnome.org/GNOME/mutter/issues/281 has been fixed
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/208
2018-07-31 00:17:44 +00:00
|
|
|
this._select(selectConfig);
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2017-06-08 14:49:20 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_keyPressHandler(keysym, action) {
|
2017-06-08 14:49:20 +00:00
|
|
|
if (action == Meta.KeyBindingAction.SWITCH_MONITOR)
|
|
|
|
this._select(this._next());
|
2019-11-05 19:37:28 +00:00
|
|
|
else if (keysym == Clutter.KEY_Left)
|
2017-06-08 14:49:20 +00:00
|
|
|
this._select(this._previous());
|
2019-11-05 19:37:28 +00:00
|
|
|
else if (keysym == Clutter.KEY_Right)
|
2017-06-08 14:49:20 +00:00
|
|
|
this._select(this._next());
|
|
|
|
else
|
|
|
|
return Clutter.EVENT_PROPAGATE;
|
|
|
|
|
|
|
|
return Clutter.EVENT_STOP;
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2017-06-08 14:49:20 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_finish() {
|
2017-10-31 01:23:39 +00:00
|
|
|
super._finish();
|
2017-06-08 14:49:20 +00:00
|
|
|
|
2021-12-02 21:04:01 +00:00
|
|
|
const monitorManager = global.backend.get_monitor_manager();
|
|
|
|
const item = this._items[this._selectedIndex];
|
|
|
|
|
2022-03-19 15:53:59 +00:00
|
|
|
monitorManager.switch_config(item.configType);
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2017-06-08 14:49:20 +00:00
|
|
|
});
|
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
const SwitchMonitorSwitcher = GObject.registerClass(
|
2017-10-31 01:23:39 +00:00
|
|
|
class SwitchMonitorSwitcher extends SwitcherPopup.SwitcherList {
|
2017-10-31 00:03:21 +00:00
|
|
|
_init(items) {
|
2017-10-31 01:23:39 +00:00
|
|
|
super._init(true);
|
2017-06-08 14:49:20 +00:00
|
|
|
|
|
|
|
for (let i = 0; i < items.length; i++)
|
|
|
|
this._addIcon(items[i]);
|
2017-10-31 01:23:39 +00:00
|
|
|
}
|
2017-06-08 14:49:20 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_addIcon(item) {
|
2020-03-29 21:51:13 +00:00
|
|
|
const box = new St.BoxLayout({
|
|
|
|
style_class: 'alt-tab-app',
|
|
|
|
vertical: true,
|
|
|
|
});
|
2017-06-08 14:49:20 +00:00
|
|
|
|
2020-03-29 21:51:13 +00:00
|
|
|
const icon = new St.Icon({
|
|
|
|
icon_name: item.icon,
|
|
|
|
icon_size: APP_ICON_SIZE,
|
|
|
|
});
|
2019-10-21 18:44:00 +00:00
|
|
|
box.add_child(icon);
|
2017-06-08 14:49:20 +00:00
|
|
|
|
2020-01-02 07:25:14 +00:00
|
|
|
let text = new St.Label({
|
|
|
|
text: item.label,
|
|
|
|
x_align: Clutter.ActorAlign.CENTER,
|
|
|
|
});
|
2019-10-21 18:44:00 +00:00
|
|
|
box.add_child(text);
|
2017-06-08 14:49:20 +00:00
|
|
|
|
|
|
|
this.addItem(box, text);
|
|
|
|
}
|
|
|
|
});
|