Skip to content

Commit

Permalink
Allow gesture style to be changed from viewer
Browse files Browse the repository at this point in the history
This adds a toggle to toolbar, which allows user to change gesture style
during an active session.

This toggle is temporarily gated behind 'Viewer -> Show gesture style toggle' pref.
  • Loading branch information
gujjwal00 committed Mar 6, 2023
1 parent bc0f472 commit 4b118e8
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 57 deletions.
114 changes: 57 additions & 57 deletions app/src/main/java/com/gaurav/avnc/ui/vnc/Dispatcher.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
package com.gaurav.avnc.ui.vnc

import android.graphics.PointF
import com.gaurav.avnc.ui.vnc.Dispatcher.SwipeAction
import com.gaurav.avnc.viewmodel.VncViewModel
import com.gaurav.avnc.vnc.Messenger
import com.gaurav.avnc.vnc.PointerButton
Expand Down Expand Up @@ -61,83 +60,81 @@ class Dispatcher(private val activity: VncActivity) {
/**************************************************************************
* Action configuration
**************************************************************************/
private val gestureStyle = if (profile.gestureStyle == "auto") gesturePref.style else profile.gestureStyle

private val directMode = DirectMode()
private val relativeMode = RelativeMode()
private val defaultMode = if (gestureStyle == "touchscreen") directMode else relativeMode

private val tap1Action = selectPointAction(gesturePref.tap1)
private val tap2Action = selectPointAction(gesturePref.tap2)
private val doubleTapAction = selectPointAction(gesturePref.doubleTap)
private val longPressAction = selectPointAction(gesturePref.longPress)

private val swipe1Action = selectSwipeAction(if (gestureStyle == "touchpad") "move-pointer" else gesturePref.swipe1)
private val swipe2Action = selectSwipeAction(gesturePref.swipe2)
private val doubleTapSwipeAction = selectSwipeAction(gesturePref.doubleTapSwipe)
private val longPressSwipeAction = selectSwipeAction(gesturePref.longPressSwipe)

private val mouseBackAction = selectPointAction(viewModel.pref.input.mouseBack)

private fun selectPointAction(actionName: String): (PointF) -> Unit {
return when (actionName) {
"left-click" -> { p -> defaultMode.doClick(PointerButton.Left, p) }
"double-click" -> { p -> defaultMode.doDoubleClick(PointerButton.Left, p) }
"middle-click" -> { p -> defaultMode.doClick(PointerButton.Middle, p) }
"right-click" -> { p -> defaultMode.doClick(PointerButton.Right, p) }
"open-keyboard" -> { _ -> doOpenKeyboard() }
else -> { _ -> } //Nothing
}
}

private fun selectSwipeAction(actionName: String): SwipeAction {
return when (actionName) {
"pan" -> SwipeAction { _, _, dx, dy -> doPan(dx, dy) }
"move-pointer" -> SwipeAction { _, cp, dx, dy -> defaultMode.doMovePointer(cp, dx, dy) }
"remote-scroll" -> SwipeAction { sp, _, dx, dy -> defaultMode.doRemoteScroll(sp, dx, dy) }
"remote-drag" -> SwipeAction { _, cp, dx, dy -> defaultMode.doDrag(cp, dx, dy) }
else -> SwipeAction { _, _, _, _ -> } //Nothing
private var config = Config()

private inner class Config {
val gestureStyle = if (profile.gestureStyle == "auto") gesturePref.style else profile.gestureStyle
val defaultMode = if (gestureStyle == "touchscreen") directMode else relativeMode

val tap1Action = selectPointAction(gesturePref.tap1)
val tap2Action = selectPointAction(gesturePref.tap2)
val doubleTapAction = selectPointAction(gesturePref.doubleTap)
val longPressAction = selectPointAction(gesturePref.longPress)

val swipe1Action = selectSwipeAction(if (gestureStyle == "touchpad") "move-pointer" else gesturePref.swipe1)
val swipe2Action = selectSwipeAction(gesturePref.swipe2)
val doubleTapSwipeAction = selectSwipeAction(gesturePref.doubleTapSwipe)
val longPressSwipeAction = selectSwipeAction(gesturePref.longPressSwipe)

val mouseBackAction = selectPointAction(viewModel.pref.input.mouseBack)

private fun selectPointAction(actionName: String): (PointF) -> Unit {
return when (actionName) {
"left-click" -> { p -> defaultMode.doClick(PointerButton.Left, p) }
"double-click" -> { p -> defaultMode.doDoubleClick(PointerButton.Left, p) }
"middle-click" -> { p -> defaultMode.doClick(PointerButton.Middle, p) }
"right-click" -> { p -> defaultMode.doClick(PointerButton.Right, p) }
"open-keyboard" -> { _ -> doOpenKeyboard() }
else -> { _ -> } //Nothing
}
}
}

//Instead of using generic lambda, like point actions, we are using a functional
//interface with SAM conversion to avoid boxing/unboxing overhead for dx & dy.
private fun interface SwipeAction {
/**
* [sp] Start point of the gesture
* [cp] Current point of the gesture
* [dx] Change along x-axis since last event
* [dy] Change along y-axis since last event
* Returns a lambda which accepts four arguments:
*
* sp: Start point of the gesture
* cp: Current point of the gesture
* dx: Change along x-axis since last event
* dy: Change along y-axis since last event
*/
operator fun invoke(sp: PointF, cp: PointF, dx: Float, dy: Float)
private fun selectSwipeAction(actionName: String): (PointF, PointF, Float, Float) -> Unit {
return when (actionName) {
"pan" -> { _, _, dx, dy -> doPan(dx, dy) }
"move-pointer" -> { _, cp, dx, dy -> defaultMode.doMovePointer(cp, dx, dy) }
"remote-scroll" -> { sp, _, dx, dy -> defaultMode.doRemoteScroll(sp, dx, dy) }
"remote-drag" -> { _, cp, dx, dy -> defaultMode.doDrag(cp, dx, dy) }
else -> { _, _, _, _ -> } //Nothing
}
}
}


/**************************************************************************
* Event receivers
**************************************************************************/

fun onGestureStart() = defaultMode.onGestureStart()
fun onGestureStop(p: PointF) = defaultMode.onGestureStop(p)
fun onGestureStart() = config.defaultMode.onGestureStart()
fun onGestureStop(p: PointF) = config.defaultMode.onGestureStop(p)

fun onTap1(p: PointF) = tap1Action(p)
fun onTap2(p: PointF) = tap2Action(p)
fun onDoubleTap(p: PointF) = doubleTapAction(p)
fun onLongPress(p: PointF) = longPressAction(p)
fun onTap1(p: PointF) = config.tap1Action(p)
fun onTap2(p: PointF) = config.tap2Action(p)
fun onDoubleTap(p: PointF) = config.doubleTapAction(p)
fun onLongPress(p: PointF) = config.longPressAction(p)

fun onSwipe1(sp: PointF, cp: PointF, dx: Float, dy: Float) = swipe1Action(sp, cp, dx, dy)
fun onSwipe2(sp: PointF, cp: PointF, dx: Float, dy: Float) = swipe2Action(sp, cp, dx, dy)
fun onDoubleTapSwipe(sp: PointF, cp: PointF, dx: Float, dy: Float) = doubleTapSwipeAction(sp, cp, dx, dy)
fun onLongPressSwipe(sp: PointF, cp: PointF, dx: Float, dy: Float) = longPressSwipeAction(sp, cp, dx, dy)
fun onSwipe1(sp: PointF, cp: PointF, dx: Float, dy: Float) = config.swipe1Action(sp, cp, dx, dy)
fun onSwipe2(sp: PointF, cp: PointF, dx: Float, dy: Float) = config.swipe2Action(sp, cp, dx, dy)
fun onDoubleTapSwipe(sp: PointF, cp: PointF, dx: Float, dy: Float) = config.doubleTapSwipeAction(sp, cp, dx, dy)
fun onLongPressSwipe(sp: PointF, cp: PointF, dx: Float, dy: Float) = config.longPressSwipeAction(sp, cp, dx, dy)

fun onScale(scaleFactor: Float, fx: Float, fy: Float) = doScale(scaleFactor, fx, fy)
fun onFling(vx: Float, vy: Float) = defaultMode.doFling(vx, vy)
fun onFling(vx: Float, vy: Float) = config.defaultMode.doFling(vx, vy)

fun onMouseButtonDown(button: PointerButton, p: PointF) = directMode.doButtonDown(button, p)
fun onMouseButtonUp(button: PointerButton, p: PointF) = directMode.doButtonUp(button, p)
fun onMouseMove(p: PointF) = directMode.doMovePointer(p, 0f, 0f)
fun onMouseScroll(p: PointF, hs: Float, vs: Float) = directMode.doRemoteScrollFromMouse(p, hs, vs)
fun onMouseBack(p: PointF) = mouseBackAction(p)
fun onMouseBack(p: PointF) = config.mouseBackAction(p)

fun onStylusTap(p: PointF) = directMode.doClick(PointerButton.Left, p)
fun onStylusDoubleTap(p: PointF) = directMode.doDoubleClick(PointerButton.Left, p)
Expand All @@ -146,6 +143,9 @@ class Dispatcher(private val activity: VncActivity) {

fun onXKeySym(keySym: Int, isDown: Boolean) = messenger.sendKey(keySym, isDown)

fun onGestureStyleChanged() {
config = Config()
}

/**************************************************************************
* Available actions
Expand Down
21 changes: 21 additions & 0 deletions app/src/main/java/com/gaurav/avnc/ui/vnc/VncActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class VncActivity : AppCompatActivity() {
setupLayout()
setupDrawerLayout()
setupServerUnlock()
setupGestureStyle()

//Buttons
binding.keyboardBtn.setOnClickListener { showKeyboard(); closeDrawers() }
Expand Down Expand Up @@ -171,6 +172,25 @@ class VncActivity : AppCompatActivity() {
}
}

private fun setupGestureStyle() {
val styleButtonMap = mapOf(
"auto" to R.id.gesture_style_auto,
"touchscreen" to R.id.gesture_style_touchscreen,
"touchpad" to R.id.gesture_style_touchpad
)

binding.gestureStyleGroup.let { group ->
group.check(styleButtonMap[viewModel.profile.gestureStyle] ?: -1)
group.setOnCheckedChangeListener { _, id ->
for ((k, v) in styleButtonMap)
if (v == id) viewModel.profile.gestureStyle = k
viewModel.saveProfile()
dispatcher.onGestureStyleChanged()
closeDrawers()
}
}
}

private fun showCredentialDialog() {
CredentialFragment().show(supportFragmentManager, "CredentialDialog")
}
Expand Down Expand Up @@ -200,6 +220,7 @@ class VncActivity : AppCompatActivity() {

private fun closeDrawers() {
binding.zoomOptions.isChecked = false
binding.gestureStyleToggle.isChecked = false
binding.drawerLayout.closeDrawers()
}

Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/com/gaurav/avnc/util/AppPreferences.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class AppPreferences(context: Context) {
val zoomMax; get() = prefs.getInt("zoom_max", 500) / 100F
val zoomMin; get() = prefs.getInt("zoom_min", 50) / 100F
val perOrientationZoom; get() = prefs.getBoolean("per_orientation_zoom", true)
val toolbarShowGestureStyleToggle; get() = prefs.getBoolean("toolbar_show_gesture_style_toggle", false)
}

inner class Gesture {
Expand Down
47 changes: 47 additions & 0 deletions app/src/main/res/layout/activity_vnc.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,21 @@
android:contentDescription="@string/desc_virtual_keys_btn"
android:src="@drawable/ic_keyboard_mini" />

<ToggleButton
android:id="@+id/gesture_style_toggle"
style="@style/ImageButton"
android:background="@drawable/bg_toggle_button"
android:contentDescription="@string/pref_gesture"
android:drawableStart="@drawable/ic_gesture"
android:foreground="?selectableItemBackground"
android:gravity="center"
android:onCheckedChanged="@{(v,checked) -> checked ? zoomOptions.setChecked(false) : void}"
android:padding="12dp"
android:textOff=""
android:textOn=""
app:isVisible="@{viewModel.pref.viewer.toolbarShowGestureStyleToggle}"
tools:ignore="UnusedAttribute" />

<ToggleButton
android:id="@+id/zoom_options"
style="@style/ImageButton"
Expand All @@ -86,6 +101,7 @@
android:drawableStart="@drawable/ic_zoom_options"
android:foreground="?selectableItemBackground"
android:gravity="center"
android:onCheckedChanged="@{(v,checked) -> checked ? gestureStyleToggle.setChecked(false) : void}"
android:padding="12dp"
android:textOff=""
android:textOn=""
Expand Down Expand Up @@ -115,6 +131,37 @@
android:src="@drawable/ic_save" />

</LinearLayout>

<RadioGroup
android:id="@+id/gesture_style_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginStart="@dimen/margin_small"
android:background="@drawable/bg_round_rect"
android:paddingStart="@dimen/padding_small"
android:paddingEnd="@dimen/padding_normal"
app:isVisible="@{gestureStyleToggle.checked}">

<RadioButton
android:id="@+id/gesture_style_auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pref_gesture_style_auto" />

<RadioButton
android:id="@+id/gesture_style_touchscreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pref_gesture_style_touchscreen" />

<RadioButton
android:id="@+id/gesture_style_touchpad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pref_gesture_style_touchpad" />
</RadioGroup>

</LinearLayout>

</androidx.drawerlayout.widget.DrawerLayout>
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/res/xml/pref_viewer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,10 @@
app:key="toolbar_alignment"
app:title="@string/pref_toolbar_alignment"
app:useSimpleSummaryProvider="true" />

<SwitchPreference
app:defaultValue="false"
app:key="toolbar_show_gesture_style_toggle"
app:title="Show gesture style toggle" />
</PreferenceCategory>
</PreferenceScreen>

0 comments on commit 4b118e8

Please sign in to comment.