From 8056e2e9eb69451029e25d0d9afb2a43ead25749 Mon Sep 17 00:00:00 2001
From: Chris <52449218+shadow578@users.noreply.github.com>
Date: Sun, 14 Aug 2022 22:19:26 +0200
Subject: [PATCH] feat: `swipe controls` override volume button behaviour
 (#114)

---
 .../patches/HDRAutoBrightnessPatch.java       |   4 +-
 .../patches/SwipeControlsPatch.java           |  42 ----
 .../SwipeControlsConfigurationProvider.kt     |  10 +-
 .../SwipeControlsHostActivity.kt              | 178 +++++++++++++++
 .../controller/SwipeZonesController.kt        |  15 +-
 .../controller/VolumeKeysController.kt        |  51 +++++
 .../gesture/NoPtSSwipeGestureController.kt    |   7 +-
 .../gesture/SwipeGestureController.kt         |  24 +-
 .../views/SwipeControlsHostLayout.kt          | 207 ------------------
 9 files changed, 263 insertions(+), 275 deletions(-)
 delete mode 100644 app/src/main/java/app/revanced/integrations/patches/SwipeControlsPatch.java
 create mode 100644 app/src/main/java/app/revanced/integrations/swipecontrols/SwipeControlsHostActivity.kt
 create mode 100644 app/src/main/java/app/revanced/integrations/swipecontrols/controller/VolumeKeysController.kt
 delete mode 100644 app/src/main/java/app/revanced/integrations/swipecontrols/views/SwipeControlsHostLayout.kt

diff --git a/app/src/main/java/app/revanced/integrations/patches/HDRAutoBrightnessPatch.java b/app/src/main/java/app/revanced/integrations/patches/HDRAutoBrightnessPatch.java
index ec74dc62..330b3cfd 100644
--- a/app/src/main/java/app/revanced/integrations/patches/HDRAutoBrightnessPatch.java
+++ b/app/src/main/java/app/revanced/integrations/patches/HDRAutoBrightnessPatch.java
@@ -3,7 +3,7 @@ package app.revanced.integrations.patches;
 import android.view.WindowManager;
 
 import app.revanced.integrations.settings.SettingsEnum;
-import app.revanced.integrations.swipecontrols.views.SwipeControlsHostLayout;
+import app.revanced.integrations.swipecontrols.SwipeControlsHostActivity;
 
 /**
  * Patch class for 'hdr-auto-brightness' patch
@@ -27,7 +27,7 @@ public class HDRAutoBrightnessPatch {
 
         // override with brightness set by swipe-controls
         // only when swipe-controls is active and has overridden the brightness
-        final SwipeControlsHostLayout swipeControlsHost = SwipeControlsPatch.CURRENT_HOST.get();
+        final SwipeControlsHostActivity swipeControlsHost = SwipeControlsHostActivity.getCurrentHost().get();
         if (swipeControlsHost != null
                 && swipeControlsHost.getScreen() != null
                 && swipeControlsHost.getConfig().getEnableBrightnessControl()
diff --git a/app/src/main/java/app/revanced/integrations/patches/SwipeControlsPatch.java b/app/src/main/java/app/revanced/integrations/patches/SwipeControlsPatch.java
deleted file mode 100644
index f543b3c5..00000000
--- a/app/src/main/java/app/revanced/integrations/patches/SwipeControlsPatch.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package app.revanced.integrations.patches;
-
-import android.app.Activity;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.lang.ref.WeakReference;
-
-import app.revanced.integrations.swipecontrols.views.SwipeControlsHostLayout;
-
-/**
- * Hook receiver class for 'swipe-controls' patch
- *
- * @usedBy app.revanced.patches.youtube.interaction.swipecontrols.patch.SwipeControlsPatch
- * @smali Lapp/revanced/integrations/patches/SwipeControlsPatch;
- */
-@SuppressWarnings("unused")
-public class SwipeControlsPatch {
-
-    /**
-     * the currently active swipe controls host.
-     * the reference may be null!
-     */
-    @NonNull
-    public static WeakReference<SwipeControlsHostLayout> CURRENT_HOST = new WeakReference<>(null);
-
-    /**
-     * Hook into the main activity lifecycle
-     * (using onStart here, but really anything up until onResume should be fine)
-     *
-     * @param thisRef reference to the WatchWhileActivity instance
-     * @smali WatchWhileActivity_onStartHookEX(Ljava / lang / Object ;)V
-     */
-    public static void WatchWhileActivity_onStartHookEX(@Nullable Object thisRef) {
-        if (thisRef == null) return;
-        if (thisRef instanceof Activity) {
-            SwipeControlsHostLayout swipeControlsHost = SwipeControlsHostLayout.attachTo((Activity) thisRef, false);
-            CURRENT_HOST = new WeakReference<>(swipeControlsHost);
-        }
-    }
-}
diff --git a/app/src/main/java/app/revanced/integrations/swipecontrols/SwipeControlsConfigurationProvider.kt b/app/src/main/java/app/revanced/integrations/swipecontrols/SwipeControlsConfigurationProvider.kt
index 453db1f3..5f9fc916 100644
--- a/app/src/main/java/app/revanced/integrations/swipecontrols/SwipeControlsConfigurationProvider.kt
+++ b/app/src/main/java/app/revanced/integrations/swipecontrols/SwipeControlsConfigurationProvider.kt
@@ -15,7 +15,7 @@ class SwipeControlsConfigurationProvider(
 ) {
 //region swipe enable
     /**
-     * should swipe controls be enabled? (global setting
+     * should swipe controls be enabled? (global setting)
      */
     val enableSwipeControls: Boolean
         get() = isFullscreenVideo && (enableVolumeControls || enableBrightnessControl)
@@ -39,6 +39,14 @@ class SwipeControlsConfigurationProvider(
         get() = PlayerType.current == PlayerType.WATCH_WHILE_FULLSCREEN
 //endregion
 
+//region keys enable
+    /**
+     * should volume key controls be overwritten? (global setting)
+     */
+    val overwriteVolumeKeyControls: Boolean
+        get() = isFullscreenVideo && enableVolumeControls
+//endregioin
+
 //region gesture adjustments
     /**
      * should press-to-swipe be enabled?
diff --git a/app/src/main/java/app/revanced/integrations/swipecontrols/SwipeControlsHostActivity.kt b/app/src/main/java/app/revanced/integrations/swipecontrols/SwipeControlsHostActivity.kt
new file mode 100644
index 00000000..3a3ec08d
--- /dev/null
+++ b/app/src/main/java/app/revanced/integrations/swipecontrols/SwipeControlsHostActivity.kt
@@ -0,0 +1,178 @@
+package app.revanced.integrations.swipecontrols
+
+import android.app.Activity
+import android.os.Bundle
+import android.view.KeyEvent
+import android.view.MotionEvent
+import android.view.ViewGroup
+import app.revanced.integrations.shared.PlayerType
+import app.revanced.integrations.swipecontrols.controller.AudioVolumeController
+import app.revanced.integrations.swipecontrols.controller.ScreenBrightnessController
+import app.revanced.integrations.swipecontrols.controller.SwipeZonesController
+import app.revanced.integrations.swipecontrols.controller.VolumeKeysController
+import app.revanced.integrations.swipecontrols.controller.gesture.NoPtSSwipeGestureController
+import app.revanced.integrations.swipecontrols.controller.gesture.SwipeGestureController
+import app.revanced.integrations.swipecontrols.misc.Rectangle
+import app.revanced.integrations.swipecontrols.views.SwipeControlsOverlayLayout
+import app.revanced.integrations.utils.LogHelper
+import java.lang.ref.WeakReference
+
+/**
+ * The main controller for volume and brightness swipe controls.
+ * note that the superclass is overwritten to the superclass of the WatchWhileActivity at patch time
+ *
+ * @smali Lapp/revanced/integrations/swipecontrols/SwipeControlsHostActivity;
+ */
+class SwipeControlsHostActivity : Activity() {
+    /**
+     * current instance of [AudioVolumeController]
+     */
+    var audio: AudioVolumeController? = null
+
+    /**
+     * current instance of [ScreenBrightnessController]
+     */
+    var screen: ScreenBrightnessController? = null
+
+    /**
+     * current instance of [SwipeControlsConfigurationProvider]
+     */
+    lateinit var config: SwipeControlsConfigurationProvider
+
+    /**
+     * current instance of [SwipeControlsOverlayLayout]
+     */
+    lateinit var overlay: SwipeControlsOverlayLayout
+
+    /**
+     * current instance of [SwipeZonesController]
+     */
+    lateinit var zones: SwipeZonesController
+
+    /**
+     * main gesture controller
+     */
+    private lateinit var gesture: SwipeGestureController
+
+    /**
+     * main volume keys controller
+     */
+    private lateinit var keys: VolumeKeysController
+
+    /**
+     * current content view with id [android.R.id.content]
+     */
+    private val contentRoot
+        get() = window.decorView.findViewById<ViewGroup>(android.R.id.content)
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        // create controllers
+        LogHelper.info(this.javaClass, "initializing swipe controls controllers")
+        config = SwipeControlsConfigurationProvider(this)
+        gesture = createGestureController()
+        keys = VolumeKeysController(this)
+        audio = createAudioController()
+        screen = createScreenController()
+
+        // create overlay
+        SwipeControlsOverlayLayout(this).let {
+            overlay = it
+            contentRoot.addView(it)
+        }
+
+        // create swipe zone controller
+        zones = SwipeZonesController(this) {
+            Rectangle(
+                contentRoot.x.toInt(),
+                contentRoot.y.toInt(),
+                contentRoot.width,
+                contentRoot.height
+            )
+        }
+
+        // listen for changes in the player type
+        PlayerType.onChange += this::onPlayerTypeChanged
+
+        // set current instance reference
+        currentHost = WeakReference(this)
+    }
+
+    override fun onStart() {
+        super.onStart()
+
+        // (re) attach overlay
+        LogHelper.info(this.javaClass, "attaching swipe controls overlay")
+        contentRoot.removeView(overlay)
+        contentRoot.addView(overlay)
+    }
+
+    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
+        return if ((ev != null) && gesture.onTouchEvent(ev)) true else {
+            super.dispatchTouchEvent(ev)
+        }
+    }
+
+    override fun dispatchKeyEvent(ev: KeyEvent?): Boolean {
+        return if((ev != null) && keys.onKeyEvent(ev)) true else {
+            super.dispatchKeyEvent(ev)
+        }
+    }
+
+    /**
+     * dispatch a touch event to downstream views
+     *
+     * @param event the event to dispatch
+     * @return was the event consumed?
+     */
+    fun dispatchDownstreamTouchEvent(event: MotionEvent) =
+        super.dispatchTouchEvent(event)
+
+    /**
+     * called when the player type changes
+     *
+     * @param type the new player type
+     */
+    private fun onPlayerTypeChanged(type: PlayerType) {
+        when (type) {
+            PlayerType.WATCH_WHILE_FULLSCREEN -> screen?.restore()
+            else -> {
+                screen?.save()
+                screen?.restoreDefaultBrightness()
+            }
+        }
+    }
+
+    /**
+     * create the audio volume controller
+     */
+    private fun createAudioController() =
+        if (config.enableVolumeControls)
+            AudioVolumeController(this) else null
+
+    /**
+     * create the screen brightness controller instance
+     */
+    private fun createScreenController() =
+        if (config.enableBrightnessControl)
+            ScreenBrightnessController(this) else null
+
+    /**
+     * create the gesture controller based on settings
+     */
+    private fun createGestureController() =
+        if (config.shouldEnablePressToSwipe)
+            SwipeGestureController(this)
+        else NoPtSSwipeGestureController(this)
+
+    companion object {
+        /**
+         * the currently active swipe controls host.
+         * the reference may be null!
+         */
+        @JvmStatic
+        var currentHost: WeakReference<SwipeControlsHostActivity> = WeakReference(null)
+            private set
+    }
+}
diff --git a/app/src/main/java/app/revanced/integrations/swipecontrols/controller/SwipeZonesController.kt b/app/src/main/java/app/revanced/integrations/swipecontrols/controller/SwipeZonesController.kt
index c0ef500f..f6436e80 100644
--- a/app/src/main/java/app/revanced/integrations/swipecontrols/controller/SwipeZonesController.kt
+++ b/app/src/main/java/app/revanced/integrations/swipecontrols/controller/SwipeZonesController.kt
@@ -1,6 +1,6 @@
 package app.revanced.integrations.swipecontrols.controller
 
-import android.content.Context
+import android.app.Activity
 import android.util.TypedValue
 import android.view.ViewGroup
 import app.revanced.integrations.swipecontrols.misc.Rectangle
@@ -35,29 +35,28 @@ import kotlin.math.min
  */
 @Suppress("PrivatePropertyName")
 class SwipeZonesController(
-    context: Context,
-    private val parentView: ViewGroup,
+    private val host: Activity,
     private val fallbackScreenRect: () -> Rectangle
 ) {
     /**
      * 20dp, in pixels
      */
-    private val _20dp = 20.applyDimension(context, TypedValue.COMPLEX_UNIT_DIP)
+    private val _20dp = 20.applyDimension(host, TypedValue.COMPLEX_UNIT_DIP)
 
     /**
      * 40dp, in pixels
      */
-    private val _40dp = 40.applyDimension(context, TypedValue.COMPLEX_UNIT_DIP)
+    private val _40dp = 40.applyDimension(host, TypedValue.COMPLEX_UNIT_DIP)
 
     /**
      * 80dp, in pixels
      */
-    private val _80dp = 80.applyDimension(context, TypedValue.COMPLEX_UNIT_DIP)
+    private val _80dp = 80.applyDimension(host, TypedValue.COMPLEX_UNIT_DIP)
 
     /**
      * id for R.id.player_view
      */
-    private val playerViewId = ReVancedUtils.getResourceIdByName(context, "id", "player_view")
+    private val playerViewId = ReVancedUtils.getResourceIdByName(host, "id", "player_view")
 
     /**
      * current bounding rectangle of the player
@@ -114,7 +113,7 @@ class SwipeZonesController(
      */
     private fun maybeAttachPlayerBoundsListener() {
         if (playerRect != null) return
-        parentView.findViewById<ViewGroup>(playerViewId)?.let {
+        host.findViewById<ViewGroup>(playerViewId)?.let {
             onPlayerViewLayout(it)
             it.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
                 onPlayerViewLayout(it)
diff --git a/app/src/main/java/app/revanced/integrations/swipecontrols/controller/VolumeKeysController.kt b/app/src/main/java/app/revanced/integrations/swipecontrols/controller/VolumeKeysController.kt
new file mode 100644
index 00000000..be910510
--- /dev/null
+++ b/app/src/main/java/app/revanced/integrations/swipecontrols/controller/VolumeKeysController.kt
@@ -0,0 +1,51 @@
+package app.revanced.integrations.swipecontrols.controller
+
+import android.view.KeyEvent
+import app.revanced.integrations.swipecontrols.SwipeControlsHostActivity
+
+/**
+ * controller for custom volume button behaviour
+ *
+ * @param controller main controller instance
+ */
+class VolumeKeysController(
+    private val controller: SwipeControlsHostActivity
+) {
+    /**
+     * key event handler
+     *
+     * @param event the key event
+     * @return consume the event?
+     */
+    fun onKeyEvent(event: KeyEvent): Boolean {
+        if(!controller.config.overwriteVolumeKeyControls) {
+            return false
+        }
+
+        return when (event.keyCode) {
+            KeyEvent.KEYCODE_VOLUME_DOWN ->
+                handleVolumeKeyEvent(event, false)
+            KeyEvent.KEYCODE_VOLUME_UP ->
+                handleVolumeKeyEvent(event, true)
+            else -> false
+        }
+    }
+
+    /**
+     * handle a volume up / down key event
+     *
+     * @param event the key event
+     * @param volumeUp was the key pressed the volume up key?
+     * @return consume the event?
+     */
+    private fun handleVolumeKeyEvent(event: KeyEvent, volumeUp: Boolean): Boolean {
+        if (event.action == KeyEvent.ACTION_DOWN) {
+            controller.audio?.apply {
+                volume += if (volumeUp) 1 else -1
+                controller.overlay.onVolumeChanged(volume, maxVolume)
+            }
+        }
+
+        return true
+    }
+}
diff --git a/app/src/main/java/app/revanced/integrations/swipecontrols/controller/gesture/NoPtSSwipeGestureController.kt b/app/src/main/java/app/revanced/integrations/swipecontrols/controller/gesture/NoPtSSwipeGestureController.kt
index 3791defc..9ba682ff 100644
--- a/app/src/main/java/app/revanced/integrations/swipecontrols/controller/gesture/NoPtSSwipeGestureController.kt
+++ b/app/src/main/java/app/revanced/integrations/swipecontrols/controller/gesture/NoPtSSwipeGestureController.kt
@@ -1,15 +1,14 @@
 package app.revanced.integrations.swipecontrols.controller.gesture
 
-import android.content.Context
 import android.view.MotionEvent
-import app.revanced.integrations.swipecontrols.views.SwipeControlsHostLayout
+import app.revanced.integrations.swipecontrols.SwipeControlsHostActivity
 
 /**
  * [SwipeGestureController], but with press-to-swipe disabled because a lot of people dislike the feature.
  * If you want to change something, try to do it in [SwipeGestureController] so that both configurations can benefit from it
  */
-class NoPtSSwipeGestureController(context: Context, controller: SwipeControlsHostLayout) :
-    SwipeGestureController(context, controller) {
+class NoPtSSwipeGestureController(controller: SwipeControlsHostActivity) :
+    SwipeGestureController(controller) {
 
     /**
      * to disable press-to-swipe, we have to become press-to-swipe
diff --git a/app/src/main/java/app/revanced/integrations/swipecontrols/controller/gesture/SwipeGestureController.kt b/app/src/main/java/app/revanced/integrations/swipecontrols/controller/gesture/SwipeGestureController.kt
index 0a7fad36..b298079b 100644
--- a/app/src/main/java/app/revanced/integrations/swipecontrols/controller/gesture/SwipeGestureController.kt
+++ b/app/src/main/java/app/revanced/integrations/swipecontrols/controller/gesture/SwipeGestureController.kt
@@ -1,14 +1,13 @@
 package app.revanced.integrations.swipecontrols.controller.gesture
 
-import android.content.Context
 import android.util.TypedValue
 import android.view.GestureDetector
 import android.view.MotionEvent
+import app.revanced.integrations.swipecontrols.SwipeControlsHostActivity
 import app.revanced.integrations.swipecontrols.misc.ScrollDistanceHelper
 import app.revanced.integrations.swipecontrols.misc.applyDimension
 import app.revanced.integrations.swipecontrols.misc.contains
 import app.revanced.integrations.swipecontrols.misc.toPoint
-import app.revanced.integrations.swipecontrols.views.SwipeControlsHostLayout
 import app.revanced.integrations.utils.LogHelper
 import kotlin.math.abs
 import kotlin.math.pow
@@ -17,21 +16,18 @@ import kotlin.math.pow
  * base gesture controller for volume and brightness swipe controls controls, with press-to-swipe enabled
  * for the controller without press-to-swipe, see [NoPtSSwipeGestureController]
  *
- * @param context the context to create in
  * @param controller reference to main controller instance
  */
 @Suppress("LeakingThis")
 open class SwipeGestureController(
-    context: Context,
-    private val controller: SwipeControlsHostLayout
+    private val controller: SwipeControlsHostActivity
 ) :
-    GestureDetector.SimpleOnGestureListener(),
-    SwipeControlsHostLayout.TouchEventListener {
+    GestureDetector.SimpleOnGestureListener() {
 
     /**
      * the main gesture detector that powers everything
      */
-    protected open val detector = GestureDetector(context, this)
+    protected open val detector = GestureDetector(controller, this)
 
     /**
      * to enable swipe controls, users must first long- press. this flags monitors that long- press
@@ -60,7 +56,7 @@ open class SwipeGestureController(
      */
     protected open val volumeScroller = ScrollDistanceHelper(
         10.applyDimension(
-            context,
+            controller,
             TypedValue.COMPLEX_UNIT_DIP
         )
     ) { _, _, direction ->
@@ -75,7 +71,7 @@ open class SwipeGestureController(
      */
     protected open val brightnessScroller = ScrollDistanceHelper(
         1.applyDimension(
-            context,
+            controller,
             TypedValue.COMPLEX_UNIT_DIP
         )
     ) { _, _, direction ->
@@ -90,7 +86,13 @@ open class SwipeGestureController(
         }
     }
 
-    override fun onTouchEvent(motionEvent: MotionEvent): Boolean {
+    /**
+     * touch event callback
+     *
+     * @param motionEvent the motion event that was received
+     * @return intercept the event? if true, child views will not receive the event
+     */
+    fun onTouchEvent(motionEvent: MotionEvent): Boolean {
         if (!controller.config.enableSwipeControls) {
             return false
         }
diff --git a/app/src/main/java/app/revanced/integrations/swipecontrols/views/SwipeControlsHostLayout.kt b/app/src/main/java/app/revanced/integrations/swipecontrols/views/SwipeControlsHostLayout.kt
deleted file mode 100644
index 9c0386ba..00000000
--- a/app/src/main/java/app/revanced/integrations/swipecontrols/views/SwipeControlsHostLayout.kt
+++ /dev/null
@@ -1,207 +0,0 @@
-package app.revanced.integrations.swipecontrols.views
-
-import android.annotation.SuppressLint
-import android.app.Activity
-import android.graphics.Color
-import android.view.MotionEvent
-import android.view.View
-import android.view.ViewGroup
-import android.widget.FrameLayout
-import app.revanced.integrations.shared.PlayerType
-import app.revanced.integrations.swipecontrols.SwipeControlsConfigurationProvider
-import app.revanced.integrations.swipecontrols.controller.AudioVolumeController
-import app.revanced.integrations.swipecontrols.controller.ScreenBrightnessController
-import app.revanced.integrations.swipecontrols.controller.SwipeZonesController
-import app.revanced.integrations.swipecontrols.controller.gesture.NoPtSSwipeGestureController
-import app.revanced.integrations.swipecontrols.controller.gesture.SwipeGestureController
-import app.revanced.integrations.swipecontrols.misc.Rectangle
-import app.revanced.integrations.swipecontrols.misc.SwipeControlsOverlay
-import app.revanced.integrations.utils.LogHelper
-
-/**
- * The main controller for volume and brightness swipe controls
- *
- * @param hostActivity the activity that should host the controller
- * @param debugTouchableZone show a overlay on all zones covered by this layout
- */
-@SuppressLint("ViewConstructor")
-class SwipeControlsHostLayout(
-    private val hostActivity: Activity,
-    private val mainContentChild: View,
-    debugTouchableZone: Boolean = false
-) : FrameLayout(hostActivity) {
-    init {
-        isFocusable = false
-        isClickable = false
-
-        if (debugTouchableZone) {
-            val zoneOverlay = View(context).apply {
-                layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
-                setBackgroundColor(Color.argb(50, 0, 255, 0))
-                z = 9999f
-            }
-            addView(zoneOverlay)
-        }
-    }
-
-    /**
-     * current instance of [AudioVolumeController]
-     */
-    val audio: AudioVolumeController?
-
-    /**
-     * current instance of [ScreenBrightnessController]
-     */
-    val screen: ScreenBrightnessController?
-
-    /**
-     * current instance of [SwipeControlsConfigurationProvider]
-     */
-    val config: SwipeControlsConfigurationProvider
-
-    /**
-     * current instance of [SwipeControlsOverlayLayout]
-     */
-    val overlay: SwipeControlsOverlay
-
-    /**
-     * current instance of [SwipeZonesController]
-     */
-    val zones: SwipeZonesController
-
-    /**
-     * main gesture controller
-     */
-    private val gesture: SwipeGestureController
-
-    init {
-        // create controllers
-        LogHelper.info(this.javaClass, "initializing swipe controls controllers")
-        config = SwipeControlsConfigurationProvider(hostActivity)
-        gesture = createGestureController()
-        audio = createAudioController()
-        screen = createScreenController()
-
-        // create overlay
-        SwipeControlsOverlayLayout(hostActivity).let {
-            overlay = it
-            addView(it)
-        }
-
-        // create swipe zone controller
-        zones = SwipeZonesController(context, this) {
-            Rectangle(x.toInt(), y.toInt(), width, height)
-        }
-
-        // listen for changes in the player type
-        PlayerType.onChange += this::onPlayerTypeChanged
-    }
-
-    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
-        return if (ev != null && gesture.onTouchEvent(ev)) true else {
-            super.dispatchTouchEvent(ev)
-        }
-    }
-
-    override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {
-        // main content is always at index 0, all other are inserted after
-        if (child == mainContentChild) {
-            super.addView(child, 0, params)
-        } else {
-            super.addView(child, childCount, params)
-        }
-    }
-
-    /**
-     * called when the player type changes
-     *
-     * @param type the new player type
-     */
-    private fun onPlayerTypeChanged(type: PlayerType) {
-        when (type) {
-            PlayerType.WATCH_WHILE_FULLSCREEN -> screen?.restore()
-            else -> {
-                screen?.save()
-                screen?.restoreDefaultBrightness()
-            }
-        }
-    }
-
-    /**
-     * dispatch a touch event to downstream views
-     *
-     * @param event the event to dispatch
-     * @return was the event consumed?
-     */
-    fun dispatchDownstreamTouchEvent(event: MotionEvent) =
-        super.dispatchTouchEvent(event)
-
-    /**
-     * create the audio volume controller
-     */
-    private fun createAudioController() =
-        if (config.enableVolumeControls)
-            AudioVolumeController(context) else null
-
-    /**
-     * create the screen brightness controller instance
-     */
-    private fun createScreenController() =
-        if (config.enableBrightnessControl)
-            ScreenBrightnessController(hostActivity) else null
-
-    /**
-     * create the gesture controller based on settings
-     */
-    private fun createGestureController() =
-        if (config.shouldEnablePressToSwipe)
-            SwipeGestureController(hostActivity, this)
-        else NoPtSSwipeGestureController(hostActivity, this)
-
-
-    interface TouchEventListener {
-        /**
-         * touch event callback
-         *
-         * @param motionEvent the motion event that was received
-         * @return intercept the event? if true, child views will not receive the event
-         */
-        fun onTouchEvent(motionEvent: MotionEvent): Boolean
-    }
-
-    companion object {
-        /**
-         * attach a [SwipeControlsHostLayout] to the activity
-         *
-         * @param debugTouchableZone show a overlay on all zones covered by this layout
-         * @return the attached instance
-         */
-        @JvmStatic
-        fun Activity.attachTo(debugTouchableZone: Boolean = false): SwipeControlsHostLayout {
-            // get targets
-            val contentView: ViewGroup = window.decorView.findViewById(android.R.id.content)!!
-            var content = contentView.getChildAt(0)
-
-            // detach previously attached swipe host first
-            if (content is SwipeControlsHostLayout) {
-                contentView.removeView(content)
-                content.removeAllViews()
-                content = content.mainContentChild
-            }
-
-            // create swipe host
-            val swipeHost = SwipeControlsHostLayout(this, content, debugTouchableZone).apply {
-                layoutParams = ViewGroup.LayoutParams(
-                    ViewGroup.LayoutParams.MATCH_PARENT,
-                    ViewGroup.LayoutParams.MATCH_PARENT
-                )
-            }
-
-            // insert the swipe host as parent to the actual content
-            contentView.removeView(content)
-            contentView.addView(swipeHost)
-            swipeHost.addView(content)
-            return swipeHost
-        }
-    }
-}