From 1d16d3e2ac1e3d3fb4f71cd2ce1dd697f583b6e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Sat, 13 Feb 2021 17:19:03 +0100 Subject: [PATCH] Add OSD headerbar and transition to floating mode --- css/styles.css | 10 +++++- src/app.js | 21 +++++++----- src/controls.js | 2 -- src/headerbar.js | 15 ++++---- src/headerbarBase.js | 5 +++ src/player.js | 11 +++--- src/revealers.js | 82 +++++++++++++++++++++++++++++++++++++++----- src/widget.js | 20 ++++++++--- 8 files changed, 128 insertions(+), 38 deletions(-) diff --git a/css/styles.css b/css/styles.css index 7f0af224..3d3acc6d 100644 --- a/css/styles.css +++ b/css/styles.css @@ -18,6 +18,12 @@ radio { .gtk402 .osd trough highlight { border-color: inherit; } +.osd headerbar { + background: transparent; +} +.osd headerbar button { + border: transparent; +} .adwrounded.csd { border-radius: 8px; } @@ -72,6 +78,9 @@ radio { font-size: 23px; text-shadow: none; } +.reavealertop { + background: transparent; +} .tvmode .reavealertop { min-height: 88px; box-shadow: inset 0px 200px 10px -132px rgba(0,0,0,0.4); @@ -79,7 +88,6 @@ radio { font-size: 28px; font-weight: 500; text-shadow: none; - background: transparent; } .tvtime { margin-top: -2px; diff --git a/src/app.js b/src/app.js index b3357061..fc2871ab 100644 --- a/src/app.js +++ b/src/app.js @@ -1,6 +1,5 @@ -const { Gio, GObject } = imports.gi; +const { Gio, GObject, Gtk } = imports.gi; const { AppBase } = imports.src.appBase; -const { HeaderBar } = imports.src.headerbar; const { Widget } = imports.src.widget; const Debug = imports.src.debug; @@ -23,14 +22,20 @@ class ClapperApp extends AppBase { super.vfunc_startup(); - this.active_window.isClapperApp = true; - this.active_window.add_css_class('nobackground'); + const window = this.active_window; - const clapperWidget = new Widget(); - this.active_window.set_child(clapperWidget); + window.isClapperApp = true; + window.add_css_class('nobackground'); - const headerBar = new HeaderBar(this.active_window); - this.active_window.set_titlebar(headerBar); + const clapperWidget = new Widget(window); + window.set_child(clapperWidget); + + const dummyHeaderbar = new Gtk.HeaderBar({ + can_focus: false, + focusable: false, + visible: false, + }); + window.set_titlebar(dummyHeaderbar); } vfunc_open(files, hint) diff --git a/src/controls.js b/src/controls.js index 9bdfb82a..cb576469 100644 --- a/src/controls.js +++ b/src/controls.js @@ -28,8 +28,6 @@ class ClapperControls extends Gtk.Box this.currentPosition = 0; this.currentDuration = 0; this.isPositionDragging = false; - - this.isMobileMonitor = false; this.isMobile = false; this.showHours = false; diff --git a/src/headerbar.js b/src/headerbar.js index 32651366..5faf5206 100644 --- a/src/headerbar.js +++ b/src/headerbar.js @@ -1,4 +1,4 @@ -const { GObject } = imports.gi; +const { GObject, Gtk } = imports.gi; const { HeaderBarBase } = imports.src.headerbarBase; var HeaderBar = GObject.registerClass( @@ -8,21 +8,18 @@ class ClapperHeaderBar extends HeaderBarBase { super._init(window); - const clapperWidget = window.get_child(); - clapperWidget.controls.unfloatButton.bind_property('visible', this, 'visible', - GObject.BindingFlags.INVERT_BOOLEAN - ); + this.title_widget.visible = false; } _onFloatButtonClicked() { - const clapperWidget = this.get_prev_sibling(); - clapperWidget.setFloatingMode(true); + const clapperWidget = this.root.child; + + clapperWidget.controlsRevealer.toggleReveal(); } _onFullscreenButtonClicked() { - const window = this.get_parent(); - window.fullscreen(); + this.root.fullscreen(); } }); diff --git a/src/headerbarBase.js b/src/headerbarBase.js index dacdfe8c..e72bf34d 100644 --- a/src/headerbarBase.js +++ b/src/headerbarBase.js @@ -20,26 +20,31 @@ class ClapperHeaderBarBase extends Gtk.HeaderBar const mainMenuButton = new Gtk.MenuButton({ icon_name: 'open-menu-symbolic', + valign: Gtk.Align.CENTER, }); const mainMenuModel = uiBuilder.get_object('mainMenu'); const mainMenuPopover = new HeaderBarPopover(mainMenuModel); mainMenuButton.set_popover(mainMenuPopover); + mainMenuButton.add_css_class('circular'); this.pack_start(mainMenuButton); const buttonsBox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, + valign: Gtk.Align.CENTER, }); buttonsBox.add_css_class('linked'); const floatButton = new Gtk.Button({ icon_name: 'preferences-desktop-remote-desktop-symbolic', }); + floatButton.add_css_class('circular'); floatButton.connect('clicked', this._onFloatButtonClicked.bind(this)); buttonsBox.append(floatButton); const fullscreenButton = new Gtk.Button({ icon_name: 'view-fullscreen-symbolic', }); + fullscreenButton.add_css_class('circular'); fullscreenButton.connect('clicked', this._onFullscreenButtonClicked.bind(this)); buttonsBox.append(fullscreenButton); diff --git a/src/player.js b/src/player.js index 7f8086dd..2a7aeb98 100644 --- a/src/player.js +++ b/src/player.js @@ -685,11 +685,6 @@ class ClapperPlayer extends PlayerBase if(!this._updateTimeTimeout) this._setUpdateTimeInterval(); - if(!clapperWidget.revealerTop.get_reveal_child()) { - /* Do not grab controls key focus on mouse movement */ - clapperWidget.revealerBottom.set_can_focus(false); - clapperWidget.revealControls(true); - } this._setHideControlsTimeout(); } else { @@ -698,6 +693,12 @@ class ClapperPlayer extends PlayerBase if(this._updateTimeTimeout) this._clearTimeout('updateTime'); } + + if(!clapperWidget.revealerTop.get_reveal_child()) { + /* Do not grab controls key focus on mouse movement */ + clapperWidget.revealerBottom.set_can_focus(false); + clapperWidget.revealControls(true); + } } this.posX = posX; diff --git a/src/revealers.js b/src/revealers.js index 3d6454e8..861e8cda 100644 --- a/src/revealers.js +++ b/src/revealers.js @@ -1,4 +1,5 @@ const { GLib, GObject, Gtk, Pango } = imports.gi; +const { HeaderBar } = imports.src.headerbar; const Debug = imports.src.debug; const REVEAL_TIME = 800; @@ -89,7 +90,7 @@ class ClapperCustomRevealer extends Gtk.Revealer var RevealerTop = GObject.registerClass( class ClapperRevealerTop extends CustomRevealer { - _init() + _init(window) { super._init({ transition_duration: REVEAL_TIME, @@ -103,12 +104,6 @@ class ClapperRevealerTop extends CustomRevealer ? '%I:%M %p' : '%H:%M'; - this.revealerGrid = new Gtk.Grid({ - column_spacing: 8 - }); - this.revealerGrid.add_css_class('osd'); - this.revealerGrid.add_css_class('reavealertop'); - this.mediaTitle = new Gtk.Label({ ellipsize: Pango.EllipsizeMode.END, vexpand: true, @@ -131,11 +126,25 @@ class ClapperRevealerTop extends CustomRevealer this.endTime = new Gtk.Label(timeLabelOpts); this.endTime.add_css_class('tvendtime'); + const revealerBox = new Gtk.Box({ + orientation: Gtk.Orientation.VERTICAL, + }); + revealerBox.add_css_class('osd'); + revealerBox.add_css_class('reavealertop'); + + this.headerBar = new HeaderBar(window); + revealerBox.append(this.headerBar); + + this.revealerGrid = new Gtk.Grid({ + column_spacing: 8, + visible: false, + }); this.revealerGrid.attach(this.mediaTitle, 0, 0, 1, 1); this.revealerGrid.attach(this.currentTime, 1, 0, 1, 1); this.revealerGrid.attach(this.endTime, 1, 0, 1, 1); + revealerBox.append(this.revealerGrid); - this.set_child(this.revealerGrid); + this.set_child(revealerBox); } setMediaTitle(title) @@ -229,6 +238,63 @@ class ClapperRevealerBottom extends CustomRevealer } }); +var ControlsRevealer = GObject.registerClass( +class ClapperControlsRevealer extends Gtk.Revealer +{ + _init() + { + super._init({ + transition_duration: 600, + transition_type: Gtk.RevealerTransitionType.SLIDE_DOWN, + reveal_child: true, + }); + + this.connect('notify::child-revealed', this._onControlsRevealed.bind(this)); + } + + toggleReveal() + { + /* Prevent interrupting transition */ + if(this.reveal_child !== this.child_revealed) + return; + + const { widget } = this.root.child.player; + + if(!this.child_revealed) + this.visible = true; + else + this.add_tick_callback(this._onUnrevealTick.bind(this, widget)); + + widget.height_request = widget.get_height(); + this.reveal_child ^= true; + } + + _onControlsRevealed() + { + if(this.child_revealed) { + const clapperWidget = this.root.child; + const [width, height] = this.root.get_default_size(); + + clapperWidget.player.widget.height_request = -1; + this.root.set_default_size(width, height); + } + } + + _onUnrevealTick(playerWidget) + { + const [width, height] = this.root.get_default_size(); + + if(!this.child_revealed) { + playerWidget.height_request = -1; + this.visible = false; + } + + this.root.set_default_size(width, playerWidget.get_height()); + + return this.child_revealed; + } +}); + var ButtonsRevealer = GObject.registerClass( class ClapperButtonsRevealer extends Gtk.Revealer { diff --git a/src/widget.js b/src/widget.js index 5fb02e07..0898f799 100644 --- a/src/widget.js +++ b/src/widget.js @@ -12,7 +12,7 @@ const { settings } = Misc; var Widget = GObject.registerClass( class ClapperWidget extends Gtk.Grid { - _init() + _init(window) { super._init(); @@ -27,11 +27,12 @@ class ClapperWidget extends Gtk.Grid this.fullscreenMode = false; this.floatingMode = false; this.isSeekable = false; + this.isMobileMonitor = false; this.needsTracksUpdate = true; this.overlay = new Gtk.Overlay(); - this.revealerTop = new Revealers.RevealerTop(); + this.revealerTop = new Revealers.RevealerTop(window); this.revealerBottom = new Revealers.RevealerBottom(); this.controls = new Controls(); @@ -41,8 +42,11 @@ class ClapperWidget extends Gtk.Grid this.controlsBox.add_css_class('controlsbox'); this.controlsBox.append(this.controls); + this.controlsRevealer = new Revealers.ControlsRevealer(); + this.controlsRevealer.set_child(this.controlsBox); + this.attach(this.overlay, 0, 0, 1, 1); - this.attach(this.controlsBox, 0, 1, 1, 1); + this.attach(this.controlsRevealer, 0, 1, 1, 1); this.mapSignal = this.connect('map', this._onMap.bind(this)); @@ -112,7 +116,9 @@ class ClapperWidget extends Gtk.Grid const root = this.get_root(); const action = (isFullscreen) ? 'add' : 'remove'; root[action + '_css_class']('gpufriendlyfs'); - root[action + '_css_class']('tvmode'); + + if(!this.isMobileMonitor) + root[action + '_css_class']('tvmode'); if(!this.floatingMode) this._changeControlsPlacement(isFullscreen); @@ -125,6 +131,10 @@ class ClapperWidget extends Gtk.Grid this.controls.setFullscreenMode(isFullscreen); this.showControls(isFullscreen); + + this.revealerTop.headerBar.visible = !isFullscreen; + this.revealerTop.revealerGrid.visible = (isFullscreen && !this.isMobileMonitor); + this.player.widget.grab_focus(); if(this.player.playOnFullscreen && isFullscreen) { @@ -617,7 +627,7 @@ class ClapperWidget extends Gtk.Grid const monitorWidth = Math.max(geometry.width, geometry.height); if(monitorWidth < 1280) { - this.controls.isMobileMonitor = true; + this.isMobileMonitor = true; debug('mobile monitor detected'); }