From f392ea0a1207c509cc1b89627c8de978586b4d50 Mon Sep 17 00:00:00 2001 From: User8395 Date: Thu, 4 Sep 2025 00:34:07 +0000 Subject: [PATCH] Plugins/MousePadPlugin: Consolidate Bigscreen remote and mousepad into one plugin for TV targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When connected to a TV (running Plasma Bigscreen), Remote Input will show a TV remote and a button on the top to switch to mouse and keyboard. When connected to any other device, Remote Input will show the mouse and keyboard only. **Removals:** - [x] Remove BigscreenPlugin **Additions:** - [x] Add "Use mouse and keyboard" **Changes:** - [x] Plugin has both remote and mouse/keyboard if device is TV, just mouse/keyboard otherwise **Code changes:** - [x] Move all TV functions to MousePlugin ![Screencast_20250519_174042](/uploads/606b32ddc584025fea5fa49b006f3a79/Screencast_20250519_174042.mp4) --- AndroidManifest.xml | 2 +- res/drawable/tv_remote_24px.xml | 10 ++ res/layout/activity_bigscreen.xml | 2 +- res/menu/menu_bigscreen.xml | 10 ++ res/values/strings.xml | 4 +- .../BigscreenPlugin/BigscreenPlugin.java | 146 ------------------ .../BigscreenActivity.java | 36 ++++- .../MousePadPlugin/MousePadPlugin.java | 68 +++++++- 8 files changed, 119 insertions(+), 159 deletions(-) create mode 100644 res/drawable/tv_remote_24px.xml create mode 100644 res/menu/menu_bigscreen.xml delete mode 100644 src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenPlugin.java rename src/org/kde/kdeconnect/Plugins/{BigscreenPlugin => MousePadPlugin}/BigscreenActivity.java (80%) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 5eb9981c..18a0bdd9 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -268,7 +268,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted + + diff --git a/res/layout/activity_bigscreen.xml b/res/layout/activity_bigscreen.xml index e2edc725..8e2b098f 100644 --- a/res/layout/activity_bigscreen.xml +++ b/res/layout/activity_bigscreen.xml @@ -12,7 +12,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted android:layout_width="match_parent" android:layout_height="match_parent" xmlns:tools="http://schemas.android.com/tools" - tools:context="org.kde.kdeconnect.Plugins.BigscreenPlugin.BigscreenActivity"> + tools:context="org.kde.kdeconnect.Plugins.MousePadPlugin.BigscreenActivity"> diff --git a/res/menu/menu_bigscreen.xml b/res/menu/menu_bigscreen.xml new file mode 100644 index 00000000..00952098 --- /dev/null +++ b/res/menu/menu_bigscreen.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 8add4548..24b0f4d3 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -30,7 +30,8 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted Share the clipboard content Clipboard Sent Remote input - Use your phone or tablet as a touchpad and keyboard + Use your phone or tablet as a touchpad and keyboard + Use your phone or tablet as a TV remote Presentation remote Use your device to change slides in a presentation Receive remote keypresses @@ -226,6 +227,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted Send Right Click Send Middle Click Show Keyboard + Show Mouse and Keyboard Device not paired Caution: There are multiple devices with the same name. Request pairing diff --git a/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenPlugin.java b/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenPlugin.java deleted file mode 100644 index 0016d305..00000000 --- a/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenPlugin.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2014 Ahmed I. Khalil - * SPDX-FileCopyrightText: 2020 Sylvia van Os - * - * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL -*/ - -package org.kde.kdeconnect.Plugins.BigscreenPlugin; - - -import static org.kde.kdeconnect.Plugins.MousePadPlugin.KeyListenerView.SpecialKeysMap; - -import android.Manifest; -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.view.KeyEvent; - -import androidx.annotation.DrawableRes; -import androidx.annotation.NonNull; - -import org.kde.kdeconnect.DeviceType; -import org.kde.kdeconnect.NetworkPacket; -import org.kde.kdeconnect.Plugins.Plugin; -import org.kde.kdeconnect.Plugins.PluginFactory; -import org.kde.kdeconnect_tp.R; - -@PluginFactory.LoadablePlugin -public class BigscreenPlugin extends Plugin { - - private final static String PACKET_TYPE_MOUSEPAD_REQUEST = "kdeconnect.mousepad.request"; - private final static String PACKET_TYPE_BIGSCREEN_STT = "kdeconnect.bigscreen.stt"; - - @Override - public boolean isCompatible() { - return getDevice().getDeviceType().equals(DeviceType.TV) && super.isCompatible(); - } - - @Override - protected int getOptionalPermissionExplanation() { - return R.string.bigscreen_optional_permission_explanation; - } - - @Override - public @NonNull String getDisplayName() { - return context.getString(R.string.pref_plugin_bigscreen); - } - - @Override - public @NonNull String getDescription() { - return context.getString(R.string.pref_plugin_bigscreen_desc); - } - - @Override - public @DrawableRes int getIcon() { - return R.drawable.ic_presenter_24dp; - } - - @Override - public boolean isEnabledByDefault() { - return true; - } - - @Override - public boolean hasSettings() { - return false; - } - - @Override - public boolean displayAsButton(Context context) { - return true; - } - - @Override - public void startMainActivity(Activity parentActivity) { - Intent intent = new Intent(parentActivity, BigscreenActivity.class); - intent.putExtra("deviceId", getDevice().getDeviceId()); - parentActivity.startActivity(intent); - } - - @Override - public @NonNull String[] getSupportedPacketTypes() { return new String[]{PACKET_TYPE_BIGSCREEN_STT}; } - - @Override - public @NonNull String[] getOutgoingPacketTypes() { - return new String[]{PACKET_TYPE_MOUSEPAD_REQUEST, PACKET_TYPE_BIGSCREEN_STT}; - } - - @Override - public @NonNull String getActionName() { - return context.getString(R.string.pref_plugin_bigscreen); - } - - public @NonNull String[] getOptionalPermissions() { - return new String[]{Manifest.permission.RECORD_AUDIO}; - } - - public Boolean hasMicPermission() { - return isPermissionGranted(Manifest.permission.RECORD_AUDIO); - } - - - public void sendLeft() { - NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST); - np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_LEFT)); - getDevice().sendPacket(np); - } - - public void sendRight() { - NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST); - np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_RIGHT)); - getDevice().sendPacket(np); - } - - public void sendUp() { - NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST); - np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_UP)); - getDevice().sendPacket(np); - } - - public void sendDown() { - NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST); - np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_DOWN)); - getDevice().sendPacket(np); - } - - public void sendSelect() { - NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST); - np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_ENTER)); - getDevice().sendPacket(np); - } - - public void sendHome() { - NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST); - np.set("alt", true); - np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_F4)); - getDevice().sendPacket(np); - } - - public void sendSTT(String content) { - NetworkPacket np = new NetworkPacket(PACKET_TYPE_BIGSCREEN_STT); - np.set("type", "stt"); - np.set("content", content); - getDevice().sendPacket(np); - } -} diff --git a/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenActivity.java b/src/org/kde/kdeconnect/Plugins/MousePadPlugin/BigscreenActivity.java similarity index 80% rename from src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenActivity.java rename to src/org/kde/kdeconnect/Plugins/MousePadPlugin/BigscreenActivity.java index 3ce20443..635025af 100644 --- a/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenActivity.java +++ b/src/org/kde/kdeconnect/Plugins/MousePadPlugin/BigscreenActivity.java @@ -3,9 +3,9 @@ * SPDX-FileCopyrightText: 2020 Sylvia van Os * * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL -*/ + */ -package org.kde.kdeconnect.Plugins.BigscreenPlugin; +package org.kde.kdeconnect.Plugins.MousePadPlugin; import android.Manifest; import android.app.Activity; @@ -13,6 +13,9 @@ import android.content.Intent; import android.os.Bundle; import android.speech.RecognizerIntent; import android.speech.SpeechRecognizer; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import androidx.annotation.NonNull; @@ -33,9 +36,9 @@ import kotlin.LazyKt; public class BigscreenActivity extends BaseActivity { private static final int REQUEST_SPEECH = 100; - + private final Lazy lazyBinding = LazyKt.lazy(() -> ActivityBigscreenBinding.inflate(getLayoutInflater())); - + @NonNull @Override protected ActivityBigscreenBinding getBinding() { @@ -57,7 +60,7 @@ public class BigscreenActivity extends BaseActivity { getBinding().micButton.setVisibility(View.INVISIBLE); } - BigscreenPlugin plugin = KdeConnect.getInstance().getDevicePlugin(deviceId, BigscreenPlugin.class); + MousePadPlugin plugin = KdeConnect.getInstance().getDevicePlugin(deviceId, MousePadPlugin.class); if (plugin == null) { finish(); return; @@ -90,6 +93,27 @@ public class BigscreenActivity extends BaseActivity { startActivityForResult(intent, REQUEST_SPEECH); } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.menu_bigscreen, menu); + + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + if (id == R.id.menu_use_mouse_and_keyboard) { + Intent intent = new Intent(this, MousePadActivity.class); + intent.putExtra("deviceId", getIntent().getStringExtra("deviceId")); + startActivity(intent); + return true; + } else { + return super.onOptionsItemSelected(item); + } + } + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); @@ -99,7 +123,7 @@ public class BigscreenActivity extends BaseActivity { .getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); if (result.get(0) != null) { final String deviceId = getIntent().getStringExtra("deviceId"); - BigscreenPlugin plugin = KdeConnect.getInstance().getDevicePlugin(deviceId, BigscreenPlugin.class); + MousePadPlugin plugin = KdeConnect.getInstance().getDevicePlugin(deviceId, MousePadPlugin.class); if (plugin == null) { finish(); return; diff --git a/src/org/kde/kdeconnect/Plugins/MousePadPlugin/MousePadPlugin.java b/src/org/kde/kdeconnect/Plugins/MousePadPlugin/MousePadPlugin.java index dbb9038e..5eea8b8e 100644 --- a/src/org/kde/kdeconnect/Plugins/MousePadPlugin/MousePadPlugin.java +++ b/src/org/kde/kdeconnect/Plugins/MousePadPlugin/MousePadPlugin.java @@ -6,13 +6,18 @@ package org.kde.kdeconnect.Plugins.MousePadPlugin; +import static org.kde.kdeconnect.Plugins.MousePadPlugin.KeyListenerView.SpecialKeysMap; + +import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.view.KeyEvent; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; +import org.kde.kdeconnect.DeviceType; import org.kde.kdeconnect.NetworkPacket; import org.kde.kdeconnect.Plugins.Plugin; import org.kde.kdeconnect.Plugins.PluginFactory; @@ -25,6 +30,7 @@ public class MousePadPlugin extends Plugin { //public final static String PACKET_TYPE_MOUSEPAD = "kdeconnect.mousepad"; public final static String PACKET_TYPE_MOUSEPAD_REQUEST = "kdeconnect.mousepad.request"; private final static String PACKET_TYPE_MOUSEPAD_KEYBOARDSTATE = "kdeconnect.mousepad.keyboardstate"; + private final static String PACKET_TYPE_BIGSCREEN_STT = "kdeconnect.bigscreen.stt"; private boolean keyboardEnabled = true; @@ -43,7 +49,7 @@ public class MousePadPlugin extends Plugin { @Override public @NonNull String getDescription() { - return context.getString(R.string.pref_plugin_mousepad_desc); + return context.getString(R.string.pref_plugin_mousepad_desc_nontv); } @Override @@ -68,9 +74,15 @@ public class MousePadPlugin extends Plugin { @Override public void startMainActivity(Activity parentActivity) { - Intent intent = new Intent(parentActivity, MousePadActivity.class); - intent.putExtra("deviceId", getDevice().getDeviceId()); - parentActivity.startActivity(intent); + if (getDevice().getDeviceType() == DeviceType.TV) { + Intent intent = new Intent(parentActivity, BigscreenActivity.class); + intent.putExtra("deviceId", getDevice().getDeviceId()); + parentActivity.startActivity(intent); + } else { + Intent intent = new Intent(parentActivity, MousePadActivity.class); + intent.putExtra("deviceId", getDevice().getDeviceId()); + parentActivity.startActivity(intent); + } } @Override @@ -95,6 +107,10 @@ public class MousePadPlugin extends Plugin { getDevice().sendPacket(np); } + public Boolean hasMicPermission() { + return isPermissionGranted(Manifest.permission.RECORD_AUDIO); + } + public void sendLeftClick() { NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST); np.set("singleclick", true); @@ -139,6 +155,50 @@ public class MousePadPlugin extends Plugin { getDevice().sendPacket(np); } + public void sendLeft() { + NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST); + np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_LEFT)); + getDevice().sendPacket(np); + } + + public void sendRight() { + NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST); + np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_RIGHT)); + getDevice().sendPacket(np); + } + + public void sendUp() { + NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST); + np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_UP)); + getDevice().sendPacket(np); + } + + public void sendDown() { + NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST); + np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_DOWN)); + getDevice().sendPacket(np); + } + + public void sendSelect() { + NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST); + np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_ENTER)); + getDevice().sendPacket(np); + } + + public void sendHome() { + NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST); + np.set("alt", true); + np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_F4)); + getDevice().sendPacket(np); + } + + public void sendSTT(String content) { + NetworkPacket np = new NetworkPacket(PACKET_TYPE_BIGSCREEN_STT); + np.set("type", "stt"); + np.set("content", content); + getDevice().sendPacket(np); + } + public void sendKeyboardPacket(NetworkPacket np) { getDevice().sendPacket(np); }