From af0e082c43d4d80b218fdbbeb53b06bb836fdeee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Wed, 12 May 2021 15:31:09 +0200 Subject: [PATCH] Readapt to changed monitor on the fly Check and apply/remove TV mode UI on the fly when switching monitors. This allows for e.g. having a mobile device connected to external big screen, drag Clapper window from one screen to another and UI should automatically adapt between mobile and TV modes without interrupting playback. This also helps in situations where monitor size is not initially known on window map #74. --- css/styles.css | 46 +++++++++++++++--------------- src/widget.js | 77 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 81 insertions(+), 42 deletions(-) diff --git a/css/styles.css b/css/styles.css index cf26d143..86666971 100644 --- a/css/styles.css +++ b/css/styles.css @@ -70,7 +70,7 @@ radio { min-height: 180px; } -.tvmode popover box { +.fullscreen.tvmode popover box { text-shadow: none; font-size: 21px; font-weight: 500; @@ -87,17 +87,17 @@ radio { margin-left: 1px; margin-right: 1px; } -.tvmode .playercontrols button { +.fullscreen.tvmode .playercontrols button { min-width: 32px; min-height: 32px; margin: 5px; margin-left: 3px; margin-right: 3px; } -.tvmode button image { +.fullscreen.tvmode button image { -gtk-icon-shadow: none; } -.tvmode radio { +.fullscreen.tvmode radio { margin-left: 0px; margin-right: 4px; border: 2px solid; @@ -105,13 +105,13 @@ radio { min-height: 17px; } -.tvmode .playercontrols button image { +.fullscreen.tvmode .playercontrols button image { -gtk-icon-size: 24px; } .adwicons .playbackicon { -gtk-icon-size: 20px; } -.adwicons.tvmode .playbackicon { +.adwicons.fullscreen.tvmode .playbackicon { -gtk-icon-size: 28px; } .labelbuttonlabel { @@ -122,21 +122,21 @@ radio { font-variant-numeric: tabular-nums; font-weight: 600; } -.tvmode .labelbuttonlabel { +.fullscreen.tvmode .labelbuttonlabel { font-size: 22px; text-shadow: none; } /* Top Revealer */ -.tvmode .revealertopgrid { +.fullscreen.tvmode .revealertopgrid { font-family: 'Cantarell', sans-serif; } -.tvmode .tvtitle { +.fullscreen.tvmode .tvtitle { font-size: 28px; font-weight: 500; text-shadow: none; } -.tvtime { +.fullscreen.tvmode .tvtime { margin-top: -2px; margin-bottom: -2px; min-height: 4px; @@ -144,7 +144,7 @@ radio { font-weight: 700; font-variant-numeric: tabular-nums; } -.tvendtime { +.fullscreen.tvmode .tvendtime { margin-top: -4px; margin-bottom: 2px; min-height: 6px; @@ -171,7 +171,7 @@ radio { .osd .positionscale trough highlight { min-height: 6px; } -.tvmode .positionscale trough slider { +.fullscreen.tvmode .positionscale trough slider { color: transparent; background: transparent; border-color: transparent; @@ -183,11 +183,11 @@ radio { .positionscale.fine-tune mark indicator { min-height: 6px; } -.tvmode .positionscale mark indicator { +.fullscreen.tvmode .positionscale mark indicator { min-height: 7px; min-width: 2px; } -.tvmode .positionscale.fine-tune mark indicator { +.fullscreen.tvmode .positionscale.fine-tune mark indicator { min-height: 7px; min-width: 2px; } @@ -199,17 +199,17 @@ radio { margin-top: 4px; margin-bottom: -6px; } -.tvmode .positionscale marks.top { +.fullscreen.tvmode .positionscale marks.top { margin-bottom: 2px; } -.tvmode .positionscale marks.bottom { +.fullscreen.tvmode .positionscale marks.bottom { margin-top: 2px; } -.tvmode .positionscale trough highlight { +.fullscreen.tvmode .positionscale trough highlight { border-radius: 3px; min-height: 20px; } -.tvmode .positionscale.fine-tune trough highlight { +.fullscreen.tvmode .positionscale.fine-tune trough highlight { border-radius: 3px; min-height: 20px; } @@ -221,7 +221,7 @@ radio { margin-right: -6px; min-height: 180px; } -.tvmode .volumescale { +.fullscreen.tvmode .volumescale { margin: 2px; margin-left: -6px; margin-right: -4px; @@ -232,7 +232,7 @@ radio { margin-top: -4px; margin-bottom: -6px; } -.tvmode .volumescale trough highlight { +.fullscreen.tvmode .volumescale trough highlight { min-width: 6px; } .overamp trough highlight { @@ -246,10 +246,10 @@ radio { .elapsedpopoverbox box separator { background: @insensitive_fg_color; } -.tvmode .elapsedpopoverbox { +.fullscreen.tvmode .elapsedpopoverbox { min-width: 360px; } -.tvmode .speedscale trough highlight { +.fullscreen.tvmode .speedscale trough highlight { min-height: 6px; } @@ -272,7 +272,7 @@ radio { .chapterlabel { min-width: 32px; } -.tvmode .chapterlabel { +.fullscreen.tvmode .chapterlabel { min-width: 40px; text-shadow: none; font-size: 22px; diff --git a/src/widget.js b/src/widget.js index 0065b047..9f328c03 100644 --- a/src/widget.js +++ b/src/widget.js @@ -38,6 +38,7 @@ class ClapperWidget extends Gtk.Grid this._hideControlsTimeout = null; this._updateTimeTimeout = null; + this.surfaceMapSignal = null; this.needsCursorRestore = false; @@ -145,9 +146,6 @@ class ClapperWidget extends Gtk.Grid const action = (isFullscreen) ? 'add' : 'remove'; root[action + '_css_class']('gpufriendlyfs'); - if(!this.isMobileMonitor) - root[action + '_css_class']('tvmode'); - if(!isFullscreen) this._clearTimeout('updateTime'); @@ -538,30 +536,70 @@ class ClapperWidget extends Gtk.Grid _onWindowMap(window) { const surface = window.get_surface(); - const monitor = window.display.get_monitor_at_surface(surface); - const geometry = monitor.geometry; - const size = JSON.parse(settings.get_string('window-size')); - debug(`monitor application-pixels: ${geometry.width}x${geometry.height}`); - - if(geometry.width >= size[0] && geometry.height >= size[1]) { - window.set_default_size(size[0], size[1]); - debug(`restored window size: ${size[0]}x${size[1]}`); - } - - const monitorWidth = Math.max(geometry.width, geometry.height); - - if(monitorWidth < 1280) { - this.isMobileMonitor = true; - debug('mobile monitor detected'); - } + if(!surface.mapped) + this.surfaceMapSignal = surface.connect( + 'notify::mapped', this._onSurfaceMapNotify.bind(this) + ); + else + this._onSurfaceMapNotify(surface); surface.connect('notify::state', this._onStateNotify.bind(this)); + surface.connect('enter-monitor', this._onEnterMonitor.bind(this)); surface.connect('layout', this._onLayoutUpdate.bind(this)); this.player._onWindowMap(window); } + _onSurfaceMapNotify(surface) + { + if(!surface.mapped) + return; + + if(this.surfaceMapSignal) { + surface.disconnect(this.surfaceMapSignal); + this.surfaceMapSignal = null; + } + + const monitor = surface.display.get_monitor_at_surface(surface); + const size = JSON.parse(settings.get_string('window-size')); + const hasMonitor = Boolean(monitor && monitor.geometry); + + /* Let GTK handle window restore if no monitor, otherwise + check if its size is greater then saved window size */ + if( + !hasMonitor + || (monitor.geometry.width >= size[0] + && monitor.geometry.height >= size[1]) + ) { + if(!hasMonitor) + debug('restoring window size without monitor geometry'); + + this.root.set_default_size(size[0], size[1]); + debug(`restored window size: ${size[0]}x${size[1]}`); + } + } + + _onEnterMonitor(surface, monitor) + { + debug('entered new monitor'); + + const { geometry } = monitor; + debug(`monitor application-pixels: ${geometry.width}x${geometry.height}`); + + const monitorWidth = Math.max(geometry.width, geometry.height); + this.isMobileMonitor = (monitorWidth < 1280); + debug(`mobile monitor detected: ${this.isMobileMonitor}`); + + const hasTVCss = this.root.has_css_class('tvmode'); + if(hasTVCss === this.isMobileMonitor) { + const action = (this.isMobileMonitor) ? 'remove' : 'add'; + this.root[action + '_css_class']('tvmode'); + } + /* Update top revealer display mode */ + this.revealerTop.setFullscreenMode(this.isFullscreenMode, this.isMobileMonitor); + } + _clearTimeout(name) { if(!this[`_${name}Timeout`]) @@ -611,6 +649,7 @@ class ClapperWidget extends Gtk.Grid && !this.isMobileMonitor && !this._updateTimeTimeout ) { + debug('setting update time interval'); this._setUpdateTimeInterval(); } }