Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions MotionEventMod/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
plugins {
alias(libs.plugins.buildlogic.android.application)
alias(libs.plugins.buildlogic.kotlin.android)
}

android {
val packageName = "com.programminghoch10.MotionEventMod"
namespace = packageName
namespace = "com.programminghoch10.MotionEventMod"

defaultConfig {
applicationId = packageName
minSdk = 14
targetSdk = 33
targetSdk = 37
buildConfigField("String", "SHARED_PREFERENCES_NAME", "\"MotionEventMod\"")
buildConfigField("String", "TAG", "\"${namespace!!.split(".").last()}\"")
}
buildFeatures {
buildConfig = true
}
}

dependencies {
implementation(libs.androidx.preference.ktx)
}
19 changes: 16 additions & 3 deletions MotionEventMod/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,33 @@

<application
android:icon="@android:drawable/ic_menu_edit"
android:label="MotionEventMod"
android:label="@string/app_name"
>
<activity
android:name=".SettingsActivity"
android:enableOnBackInvokedCallback="false"
android:excludeFromRecents="true"
android:exported="true"
android:label="@string/activity_settings_title"
android:theme="@style/AppTheme"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="de.robv.android.xposed.category.MODULE_SETTINGS" />
</intent-filter>
</activity>

<meta-data
android:name="xposedmodule"
android:value="true"
/>
<meta-data
android:name="xposeddescription"
android:value="Disable touch input for some seconds after the stylus was in use"
android:value="@string/description"
/>
<meta-data
android:name="xposedminversion"
android:value="82"
android:value="93"
/>
<meta-data
android:name="xposedscope"
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.programminghoch10.MotionEventMod

import android.os.Bundle
import androidx.fragment.app.FragmentActivity
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreference
import androidx.preference.TwoStatePreference
import com.programminghoch10.MotionEventMod.BuildConfig.SHARED_PREFERENCES_NAME

class SettingsActivity : FragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.settings_activity)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction().replace(R.id.settings, SettingsFragment()).commit()
}
actionBar?.setDisplayHomeAsUpEnabled(true)
}

override fun onNavigateUp(): Boolean {
if (supportFragmentManager.backStackEntryCount > 0) supportFragmentManager.popBackStack()
else finish()
return true
}

class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
preferenceManager.sharedPreferencesName = SHARED_PREFERENCES_NAME
preferenceManager.sharedPreferencesMode = MODE_WORLD_READABLE
setPreferencesFromResource(R.xml.root_preferences, rootKey)

val disableTouchTimeoutPreference = findPreference<TimeoutPreference>("disableTouchTimeout")!!
val disableTouchDuringPenPreference = findPreference<SwitchPreference>("disableTouchDuringPen")!!
val disableTouchDuringHoverPreference = findPreference<SwitchPreference>("disableTouchDuringHover")!!
val replayOngoingEventsPreference = findPreference<SwitchPreference>("replayOngoingEvents")!!

fun recalculateDependencies() {
disableTouchDuringHoverPreference.isEnabled = disableTouchDuringPenPreference.isEnabledAndChecked
disableTouchTimeoutPreference.isEnabled =
disableTouchDuringPenPreference.isEnabledAndChecked || disableTouchDuringHoverPreference.isEnabledAndChecked
replayOngoingEventsPreference.isEnabled =
disableTouchDuringPenPreference.isEnabledAndChecked || disableTouchDuringHoverPreference.isEnabledAndChecked
}
preferenceManager.sharedPreferences!!.registerOnSharedPreferenceChangeListener { _, _ -> recalculateDependencies() }
recalculateDependencies()
}
}

class TypeSelectorFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
preferenceManager.sharedPreferencesName = SHARED_PREFERENCES_NAME
preferenceManager.sharedPreferencesMode = MODE_WORLD_READABLE
preferenceScreen = preferenceManager.createPreferenceScreen(requireContext())
(toolTypeFields + sourceClassFields + actionTypeFields + buttonFields).map { it.name }.forEach {
val preference = SwitchPreference(requireContext())
preference.key = typeEnabledKey(it)
preference.title = it
preference.setDefaultValue(true)
preferenceScreen.addPreference(preference)
}
}
}
}

private val TwoStatePreference.isEnabledAndChecked get() = isEnabled && isChecked
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.programminghoch10.MotionEventMod

import android.app.AlertDialog
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.EditText
import android.widget.TextView
import androidx.preference.Preference

class TimeoutPreference(context: Context, attrs: AttributeSet) : Preference(context, attrs) {
val TAG = TimeoutPreference::class.simpleName
var defaultValue = 0f

var savedValue: Float
get() = getPersistedFloat(defaultValue)
set(value) {
persistFloat(value)
}

override fun setDefaultValue(defaultValue: Any?) {
require(defaultValue is Float)
this.defaultValue = defaultValue
super.setDefaultValue(defaultValue)
}

override fun getSummary(): CharSequence {
return String.format(super.summary.toString(), savedValue)
}

override fun onClick() {
require(sharedPreferences != null)
val inflater = LayoutInflater.from(context)
val dialogView = inflater.inflate(R.layout.timeoutpreference_dialog, null)
dialogView.findViewById<TextView>(android.R.id.title).text = title
val editText = dialogView.findViewById<EditText>(R.id.editText)
editText.setText(savedValue.toString())
AlertDialog.Builder(context).apply {
setView(dialogView)
}.setPositiveButton(android.R.string.ok) { _, _ ->
val result = editText.text.toString().toFloatOrNull() ?: 0f
if (callChangeListener(result)) savedValue = result
notifyChanged()
}.setNegativeButton(android.R.string.cancel, null).show()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.programminghoch10.MotionEventMod

import android.os.Build
import android.os.Parcel
import android.os.Parcelable
import android.view.InputDevice
import android.view.MotionEvent


val toolTypeFields = MotionEvent::class.java.declaredFields.filter { it.name.startsWith("TOOL_TYPE_") && it.type == Int::class.java }
val sourceClassFields = InputDevice::class.java.declaredFields.filter { it.name.startsWith("SOURCE_CLASS_") && it.type == Int::class.java }
.filter { it.name != "SOURCE_CLASS_MASK" }
val actionTypeFields =
MotionEvent::class.java.declaredFields.filter { it.name.startsWith("ACTION_") && it.type == Int::class.java }.filter { it.name != "ACTION_MASK" }
val buttonFields = MotionEvent::class.java.declaredFields.filter { it.name.startsWith("BUTTON_") && it.type == Int::class.java }
val buttonFieldsMap = buttonFields.associate { field -> field.name to field.getInt(null) }
fun typeEnabledKey(fieldName: String): String = "${fieldName.lowercase()}_enabled"

// thanks https://farhanpatel.dev/index.php/2020/06/14/deep-clones-with-android-parcelable/
// slightly modified for compatibility, extension functions and nullability
fun <T : Parcelable> T.deepClone(): T {
var parcel = Parcel.obtain()
parcel.writeParcelable(this, 0)
parcel.setDataPosition(0)
val clone = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
parcel.readParcelable(this::class.java.classLoader, this::class.java)
} else {
@Suppress("DEPRECATION") parcel.readParcelable(this::class.java.classLoader)
}
// it is important to recycle parcel and free up resources once done
parcel.recycle()
require(clone != null)
return clone
}
Loading
Loading