mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-30 07:42:23 +02:00
305 lines
8.0 KiB
JavaScript
305 lines
8.0 KiB
JavaScript
const { GObject, Gtk } = imports.gi;
|
|
const Debug = imports.src.debug;
|
|
const Misc = imports.src.misc;
|
|
|
|
const { debug } = Debug;
|
|
|
|
var HeaderBarBase = GObject.registerClass(
|
|
class ClapperHeaderBarBase extends Gtk.Box
|
|
{
|
|
_init()
|
|
{
|
|
super._init({
|
|
can_focus: false,
|
|
orientation: Gtk.Orientation.HORIZONTAL,
|
|
spacing: 6,
|
|
margin_top: 6,
|
|
margin_start: 6,
|
|
margin_end: 6,
|
|
});
|
|
this.add_css_class('osdheaderbar');
|
|
|
|
this.isMaximized = false;
|
|
this.isMenuOnLeft = true;
|
|
this.hasPipIcons = false;
|
|
|
|
const clapperPath = Misc.getClapperPath();
|
|
const uiBuilder = Gtk.Builder.new_from_file(
|
|
`${clapperPath}/ui/clapper.ui`
|
|
);
|
|
|
|
this.menuWidget = new Gtk.Box({
|
|
orientation: Gtk.Orientation.HORIZONTAL,
|
|
valign: Gtk.Align.CENTER,
|
|
spacing: 6,
|
|
});
|
|
|
|
this.menuButton = new Gtk.MenuButton({
|
|
icon_name: 'open-menu-symbolic',
|
|
valign: Gtk.Align.CENTER,
|
|
can_focus: false,
|
|
});
|
|
const menuToggleButton = this.menuButton.get_first_child();
|
|
menuToggleButton.add_css_class('osd');
|
|
const mainMenuModel = uiBuilder.get_object('mainMenu');
|
|
const mainMenuPopover = new HeaderBarPopover(mainMenuModel);
|
|
this.menuButton.set_popover(mainMenuPopover);
|
|
this.menuButton.add_css_class('circular');
|
|
this.menuWidget.append(this.menuButton);
|
|
|
|
this.extraButtonsBox = new Gtk.Box({
|
|
orientation: Gtk.Orientation.HORIZONTAL,
|
|
valign: Gtk.Align.CENTER,
|
|
});
|
|
this.extraButtonsBox.add_css_class('linked');
|
|
|
|
const floatButton = new Gtk.Button({
|
|
icon_name: 'go-bottom-symbolic',
|
|
can_focus: false,
|
|
});
|
|
floatButton.add_css_class('osd');
|
|
floatButton.add_css_class('circular');
|
|
floatButton.add_css_class('linkedleft');
|
|
floatButton.connect('clicked',
|
|
this._onFloatButtonClicked.bind(this)
|
|
);
|
|
this.extraButtonsBox.append(floatButton);
|
|
|
|
const separator = new Gtk.Separator({
|
|
orientation: Gtk.Orientation.VERTICAL,
|
|
});
|
|
separator.add_css_class('linkseparator');
|
|
this.extraButtonsBox.append(separator);
|
|
|
|
const fullscreenButton = new Gtk.Button({
|
|
icon_name: 'view-fullscreen-symbolic',
|
|
can_focus: false,
|
|
});
|
|
fullscreenButton.add_css_class('osd');
|
|
fullscreenButton.add_css_class('circular');
|
|
fullscreenButton.add_css_class('linkedright');
|
|
fullscreenButton.connect('clicked',
|
|
this._onFullscreenButtonClicked.bind(this)
|
|
);
|
|
this.extraButtonsBox.append(fullscreenButton);
|
|
this.menuWidget.append(this.extraButtonsBox);
|
|
|
|
this.spacerWidget = new Gtk.Box({
|
|
hexpand: true,
|
|
});
|
|
|
|
this.minimizeWidget = this._getWindowButton('minimize');
|
|
this.maximizeWidget = this._getWindowButton('maximize');
|
|
this.closeWidget = this._getWindowButton('close');
|
|
|
|
const gtkSettings = Gtk.Settings.get_default();
|
|
this._onLayoutUpdate(gtkSettings);
|
|
|
|
gtkSettings.connect(
|
|
'notify::gtk-decoration-layout',
|
|
this._onLayoutUpdate.bind(this)
|
|
);
|
|
}
|
|
|
|
setMenuOnLeft(isOnLeft)
|
|
{
|
|
if(this.isMenuOnLeft === isOnLeft)
|
|
return;
|
|
|
|
if(isOnLeft) {
|
|
this.menuWidget.reorder_child_after(
|
|
this.extraButtonsBox, this.menuButton
|
|
);
|
|
}
|
|
else {
|
|
this.menuWidget.reorder_child_after(
|
|
this.menuButton, this.extraButtonsBox
|
|
);
|
|
}
|
|
|
|
this.isMenuOnLeft = isOnLeft;
|
|
}
|
|
|
|
setMaximized(isMaximized)
|
|
{
|
|
if(this.isMaximized === isMaximized)
|
|
return;
|
|
|
|
this.maximizeWidget.icon_name = (isMaximized)
|
|
? 'window-restore-symbolic'
|
|
: 'window-maximize-symbolic';
|
|
|
|
this.isMaximized = isMaximized;
|
|
}
|
|
|
|
_onLayoutUpdate(gtkSettings)
|
|
{
|
|
const gtkLayout = gtkSettings.gtk_decoration_layout;
|
|
|
|
this._replaceButtons(gtkLayout);
|
|
}
|
|
|
|
_replaceButtons(gtkLayout)
|
|
{
|
|
const modLayout = gtkLayout.replace(':', ',spacer,');
|
|
const layoutArr = modLayout.split(',');
|
|
|
|
let lastWidget = null;
|
|
|
|
let showMinimize = false;
|
|
let showMaximize = false;
|
|
let showClose = false;
|
|
|
|
let menuAdded = false;
|
|
let spacerAdded = false;
|
|
|
|
debug(`headerbar layout: ${modLayout}`);
|
|
|
|
for(let name of layoutArr) {
|
|
/* Menu might be named "appmenu" */
|
|
if(!menuAdded && (!name || name === 'appmenu' || name === 'icon'))
|
|
name = 'menu';
|
|
|
|
const widget = this[`${name}Widget`];
|
|
if(!widget) continue;
|
|
|
|
if(!widget.parent)
|
|
this.append(widget);
|
|
else
|
|
this.reorder_child_after(widget, lastWidget);
|
|
|
|
switch(name) {
|
|
case 'spacer':
|
|
spacerAdded = true;
|
|
break;
|
|
case 'minimize':
|
|
showMinimize = true;
|
|
break;
|
|
case 'maximize':
|
|
showMaximize = true;
|
|
break;
|
|
case 'close':
|
|
showClose = true;
|
|
break;
|
|
case 'menu':
|
|
this.setMenuOnLeft(!spacerAdded);
|
|
menuAdded = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
lastWidget = widget;
|
|
}
|
|
|
|
this.minimizeWidget.visible = showMinimize;
|
|
this.maximizeWidget.visible = showMaximize;
|
|
this.closeWidget.visible = showClose;
|
|
}
|
|
|
|
_getWindowButton(name)
|
|
{
|
|
const button = new Gtk.Button({
|
|
icon_name: `window-${name}-symbolic`,
|
|
valign: Gtk.Align.CENTER,
|
|
can_focus: false,
|
|
});
|
|
button.add_css_class('osd');
|
|
button.add_css_class('circular');
|
|
|
|
if(name === 'maximize')
|
|
name = 'toggle-maximized';
|
|
|
|
button.connect('clicked',
|
|
this._onWindowButtonActivate.bind(this, name)
|
|
);
|
|
|
|
return button;
|
|
}
|
|
|
|
_updateFloatIcon(isFloating)
|
|
{
|
|
const floatButton = this.extraButtonsBox.get_first_child();
|
|
if(!floatButton) return;
|
|
|
|
const iconName = (!this.hasPipIcons)
|
|
? 'go-bottom-symbolic'
|
|
: (isFloating)
|
|
? 'pip-out-symbolic'
|
|
: 'pip-in-symbolic';
|
|
|
|
if(floatButton.icon_name !== iconName)
|
|
floatButton.icon_name = iconName;
|
|
}
|
|
|
|
_onWindowButtonActivate(action)
|
|
{
|
|
}
|
|
|
|
_onFloatButtonClicked(button)
|
|
{
|
|
}
|
|
|
|
_onFullscreenButtonClicked(button)
|
|
{
|
|
}
|
|
|
|
_onIconThemeChanged(iconTheme)
|
|
{
|
|
/* Those icons are relatively new,
|
|
* so check if theme has them */
|
|
this.hasPipIcons = (
|
|
iconTheme.has_icon('pip-in-symbolic')
|
|
&& iconTheme.has_icon('pip-out-symbolic')
|
|
);
|
|
|
|
const { controlsRevealer } = this.root.child;
|
|
|
|
this._updateFloatIcon(!controlsRevealer.reveal_child);
|
|
}
|
|
});
|
|
|
|
var HeaderBarPopover = GObject.registerClass(
|
|
class ClapperHeaderBarPopover extends Gtk.PopoverMenu
|
|
{
|
|
_init(model)
|
|
{
|
|
super._init({
|
|
menu_model: model,
|
|
});
|
|
|
|
this.connect('map', this._onMap.bind(this));
|
|
this.connect('closed', this._onClosed.bind(this));
|
|
}
|
|
|
|
_onMap()
|
|
{
|
|
const { child } = this.root;
|
|
|
|
if(
|
|
!child
|
|
|| !child.player
|
|
|| !child.player.widget
|
|
)
|
|
return;
|
|
|
|
child.revealControls();
|
|
child.isPopoverOpen = true;
|
|
}
|
|
|
|
_onClosed()
|
|
{
|
|
const { child } = this.root;
|
|
|
|
if(
|
|
!child
|
|
|| !child.player
|
|
|| !child.player.widget
|
|
)
|
|
return;
|
|
|
|
child.revealControls();
|
|
child.isPopoverOpen = false;
|
|
}
|
|
});
|