From ba47b33ed600266b1194b774c9edbd7e6a0097ef Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Tue, 20 Apr 2021 20:59:58 +0200 Subject: [PATCH 1/7] Reverse boolean logic for readability Refs #2260 --- .../com/genymobile/scrcpy/wrappers/ActivityManager.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/ActivityManager.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/ActivityManager.java index 71967c500c..93ed452875 100644 --- a/server/src/main/java/com/genymobile/scrcpy/wrappers/ActivityManager.java +++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/ActivityManager.java @@ -14,7 +14,7 @@ public class ActivityManager { private final IInterface manager; private Method getContentProviderExternalMethod; - private boolean getContentProviderExternalMethodLegacy; + private boolean getContentProviderExternalMethodNewVersion = true; private Method removeContentProviderExternalMethod; public ActivityManager(IInterface manager) { @@ -29,7 +29,7 @@ private Method getGetContentProviderExternalMethod() throws NoSuchMethodExceptio } catch (NoSuchMethodException e) { // old version getContentProviderExternalMethod = manager.getClass().getMethod("getContentProviderExternal", String.class, int.class, IBinder.class); - getContentProviderExternalMethodLegacy = true; + getContentProviderExternalMethodNewVersion = false; } } return getContentProviderExternalMethod; @@ -46,7 +46,7 @@ private ContentProvider getContentProviderExternal(String name, IBinder token) { try { Method method = getGetContentProviderExternalMethod(); Object[] args; - if (!getContentProviderExternalMethodLegacy) { + if (getContentProviderExternalMethodNewVersion) { // new version args = new Object[]{name, ServiceManager.USER_ID, token, null}; } else { From 3eb46adf1956504f13ee3ccbe1d2cf1aee0d53c4 Mon Sep 17 00:00:00 2001 From: brunoais Date: Sat, 17 Apr 2021 13:26:54 +0100 Subject: [PATCH 2/7] Rename control message type to COLLAPSE_PANELS The collapsing action collapses any panels. By the way, the Android method is named collapsePanels(). PR #2260 Signed-off-by: Romain Vimont --- app/src/control_msg.c | 2 +- app/src/control_msg.h | 2 +- app/src/input_manager.c | 6 +++--- app/tests/test_control_msg_serialize.c | 8 ++++---- .../main/java/com/genymobile/scrcpy/ControlMessage.java | 2 +- .../java/com/genymobile/scrcpy/ControlMessageReader.java | 2 +- .../src/main/java/com/genymobile/scrcpy/Controller.java | 2 +- .../com/genymobile/scrcpy/ControlMessageReaderTest.java | 6 +++--- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/src/control_msg.c b/app/src/control_msg.c index 69e750140a..7d18fb6a4f 100644 --- a/app/src/control_msg.c +++ b/app/src/control_msg.c @@ -81,7 +81,7 @@ control_msg_serialize(const struct control_msg *msg, unsigned char *buf) { buf[1] = msg->set_screen_power_mode.mode; return 2; case CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL: - case CONTROL_MSG_TYPE_COLLAPSE_NOTIFICATION_PANEL: + case CONTROL_MSG_TYPE_COLLAPSE_PANELS: case CONTROL_MSG_TYPE_GET_CLIPBOARD: case CONTROL_MSG_TYPE_ROTATE_DEVICE: // no additional data diff --git a/app/src/control_msg.h b/app/src/control_msg.h index 8d9ab7d42d..1e9481d9e7 100644 --- a/app/src/control_msg.h +++ b/app/src/control_msg.h @@ -27,7 +27,7 @@ enum control_msg_type { CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT, CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON, CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL, - CONTROL_MSG_TYPE_COLLAPSE_NOTIFICATION_PANEL, + CONTROL_MSG_TYPE_COLLAPSE_PANELS, CONTROL_MSG_TYPE_GET_CLIPBOARD, CONTROL_MSG_TYPE_SET_CLIPBOARD, CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE, diff --git a/app/src/input_manager.c b/app/src/input_manager.c index b8a8c84602..574e02d41f 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -179,9 +179,9 @@ expand_notification_panel(struct controller *controller) { } static void -collapse_notification_panel(struct controller *controller) { +collapse_panels(struct controller *controller) { struct control_msg msg; - msg.type = CONTROL_MSG_TYPE_COLLAPSE_NOTIFICATION_PANEL; + msg.type = CONTROL_MSG_TYPE_COLLAPSE_PANELS; if (!controller_push_msg(controller, &msg)) { LOGW("Could not request 'collapse notification panel'"); @@ -498,7 +498,7 @@ input_manager_process_key(struct input_manager *im, case SDLK_n: if (control && !repeat && down) { if (shift) { - collapse_notification_panel(controller); + collapse_panels(controller); } else { expand_notification_panel(controller); } diff --git a/app/tests/test_control_msg_serialize.c b/app/tests/test_control_msg_serialize.c index 4771ce1fe5..d7b899299b 100644 --- a/app/tests/test_control_msg_serialize.c +++ b/app/tests/test_control_msg_serialize.c @@ -177,9 +177,9 @@ static void test_serialize_expand_notification_panel(void) { assert(!memcmp(buf, expected, sizeof(expected))); } -static void test_serialize_collapse_notification_panel(void) { +static void test_serialize_collapse_panels(void) { struct control_msg msg = { - .type = CONTROL_MSG_TYPE_COLLAPSE_NOTIFICATION_PANEL, + .type = CONTROL_MSG_TYPE_COLLAPSE_PANELS, }; unsigned char buf[CONTROL_MSG_MAX_SIZE]; @@ -187,7 +187,7 @@ static void test_serialize_collapse_notification_panel(void) { assert(size == 1); const unsigned char expected[] = { - CONTROL_MSG_TYPE_COLLAPSE_NOTIFICATION_PANEL, + CONTROL_MSG_TYPE_COLLAPSE_PANELS, }; assert(!memcmp(buf, expected, sizeof(expected))); } @@ -274,7 +274,7 @@ int main(int argc, char *argv[]) { test_serialize_inject_scroll_event(); test_serialize_back_or_screen_on(); test_serialize_expand_notification_panel(); - test_serialize_collapse_notification_panel(); + test_serialize_collapse_panels(); test_serialize_get_clipboard(); test_serialize_set_clipboard(); test_serialize_set_screen_power_mode(); diff --git a/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java b/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java index 44cb1b599f..34ce1941b1 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java +++ b/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java @@ -11,7 +11,7 @@ public final class ControlMessage { public static final int TYPE_INJECT_SCROLL_EVENT = 3; public static final int TYPE_BACK_OR_SCREEN_ON = 4; public static final int TYPE_EXPAND_NOTIFICATION_PANEL = 5; - public static final int TYPE_COLLAPSE_NOTIFICATION_PANEL = 6; + public static final int TYPE_COLLAPSE_PANELS = 6; public static final int TYPE_GET_CLIPBOARD = 7; public static final int TYPE_SET_CLIPBOARD = 8; public static final int TYPE_SET_SCREEN_POWER_MODE = 9; diff --git a/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java b/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java index 7ebecf76ac..97f027ffb9 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java +++ b/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java @@ -77,7 +77,7 @@ public ControlMessage next() { msg = parseSetScreenPowerMode(); break; case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL: - case ControlMessage.TYPE_COLLAPSE_NOTIFICATION_PANEL: + case ControlMessage.TYPE_COLLAPSE_PANELS: case ControlMessage.TYPE_GET_CLIPBOARD: case ControlMessage.TYPE_ROTATE_DEVICE: msg = ControlMessage.createEmpty(type); diff --git a/server/src/main/java/com/genymobile/scrcpy/Controller.java b/server/src/main/java/com/genymobile/scrcpy/Controller.java index 6af5ddf649..15c0584a3f 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Controller.java +++ b/server/src/main/java/com/genymobile/scrcpy/Controller.java @@ -107,7 +107,7 @@ private void handleEvent() throws IOException { case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL: Device.expandNotificationPanel(); break; - case ControlMessage.TYPE_COLLAPSE_NOTIFICATION_PANEL: + case ControlMessage.TYPE_COLLAPSE_PANELS: Device.collapsePanels(); break; case ControlMessage.TYPE_GET_CLIPBOARD: diff --git a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java index 6167ddebf0..97429026b0 100644 --- a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java +++ b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java @@ -182,19 +182,19 @@ public void testParseExpandNotificationPanelEvent() throws IOException { } @Test - public void testParseCollapseNotificationPanelEvent() throws IOException { + public void testParseCollapsePanelsEvent() throws IOException { ControlMessageReader reader = new ControlMessageReader(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos); - dos.writeByte(ControlMessage.TYPE_COLLAPSE_NOTIFICATION_PANEL); + dos.writeByte(ControlMessage.TYPE_COLLAPSE_PANELS); byte[] packet = bos.toByteArray(); reader.readFrom(new ByteArrayInputStream(packet)); ControlMessage event = reader.next(); - Assert.assertEquals(ControlMessage.TYPE_COLLAPSE_NOTIFICATION_PANEL, event.getType()); + Assert.assertEquals(ControlMessage.TYPE_COLLAPSE_PANELS, event.getType()); } @Test From a7044177870ef9f5e13700f350305f19e06c76a4 Mon Sep 17 00:00:00 2001 From: brunoais Date: Sat, 17 Apr 2021 13:15:31 +0100 Subject: [PATCH 3/7] Count repeated identical key events This will allow shortcuts such as MOD+n+n to open the settings panel. PR #2260 Signed-off-by: Romain Vimont --- app/src/input_manager.c | 19 +++++++++++++++++-- app/src/input_manager.h | 7 +++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/app/src/input_manager.c b/app/src/input_manager.c index 574e02d41f..b600628552 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -72,6 +72,10 @@ input_manager_init(struct input_manager *im, im->sdl_shortcut_mods.count = shortcut_mods->count; im->vfinger_down = false; + + im->last_keycode = SDLK_UNKNOWN; + im->last_mod = 0; + im->key_repeat = 0; } static void @@ -384,16 +388,27 @@ input_manager_process_key(struct input_manager *im, // control: indicates the state of the command-line option --no-control bool control = im->control; - bool smod = is_shortcut_mod(im, event->keysym.mod); - struct controller *controller = im->controller; SDL_Keycode keycode = event->keysym.sym; + uint16_t mod = event->keysym.mod; bool down = event->type == SDL_KEYDOWN; bool ctrl = event->keysym.mod & KMOD_CTRL; bool shift = event->keysym.mod & KMOD_SHIFT; bool repeat = event->repeat; + bool smod = is_shortcut_mod(im, mod); + + if (down && !repeat) { + if (keycode == im->last_keycode && mod == im->last_mod) { + ++im->key_repeat; + } else { + im->key_repeat = 0; + im->last_keycode = keycode; + im->last_mod = mod; + } + } + // The shortcut modifier is pressed if (smod) { int action = down ? ACTION_DOWN : ACTION_UP; diff --git a/app/src/input_manager.h b/app/src/input_manager.h index 160977b387..5c7e2b913f 100644 --- a/app/src/input_manager.h +++ b/app/src/input_manager.h @@ -33,6 +33,13 @@ struct input_manager { } sdl_shortcut_mods; bool vfinger_down; + + // Tracks the number of identical consecutive shortcut key down events. + // Not to be confused with event->repeat, which counts the number of + // system-generated repeated key presses. + unsigned key_repeat; + SDL_Keycode last_keycode; + uint16_t last_mod; }; void From e081b5a59a57e7b82d85769a5ea5602dfdb46afe Mon Sep 17 00:00:00 2001 From: brunoais Date: Sat, 17 Apr 2021 13:32:18 +0100 Subject: [PATCH 4/7] Add control message to expand settings panel PR #2260 Signed-off-by: Romain Vimont --- app/src/control_msg.c | 1 + app/src/control_msg.h | 1 + app/src/input_manager.c | 10 ++++++ app/tests/test_control_msg_serialize.c | 16 ++++++++++ .../com/genymobile/scrcpy/ControlMessage.java | 11 ++++--- .../scrcpy/ControlMessageReader.java | 1 + .../com/genymobile/scrcpy/Controller.java | 3 ++ .../java/com/genymobile/scrcpy/Device.java | 4 +++ .../scrcpy/wrappers/StatusBarManager.java | 31 +++++++++++++++++++ .../scrcpy/ControlMessageReaderTest.java | 16 ++++++++++ 10 files changed, 89 insertions(+), 5 deletions(-) diff --git a/app/src/control_msg.c b/app/src/control_msg.c index 7d18fb6a4f..8908c5462a 100644 --- a/app/src/control_msg.c +++ b/app/src/control_msg.c @@ -81,6 +81,7 @@ control_msg_serialize(const struct control_msg *msg, unsigned char *buf) { buf[1] = msg->set_screen_power_mode.mode; return 2; case CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL: + case CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL: case CONTROL_MSG_TYPE_COLLAPSE_PANELS: case CONTROL_MSG_TYPE_GET_CLIPBOARD: case CONTROL_MSG_TYPE_ROTATE_DEVICE: diff --git a/app/src/control_msg.h b/app/src/control_msg.h index 1e9481d9e7..c1099c794f 100644 --- a/app/src/control_msg.h +++ b/app/src/control_msg.h @@ -27,6 +27,7 @@ enum control_msg_type { CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT, CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON, CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL, + CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL, CONTROL_MSG_TYPE_COLLAPSE_PANELS, CONTROL_MSG_TYPE_GET_CLIPBOARD, CONTROL_MSG_TYPE_SET_CLIPBOARD, diff --git a/app/src/input_manager.c b/app/src/input_manager.c index b600628552..0d3175e641 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -182,6 +182,16 @@ expand_notification_panel(struct controller *controller) { } } +static void +expand_settings_panel(struct controller *controller) { + struct control_msg msg; + msg.type = CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL; + + if (!controller_push_msg(controller, &msg)) { + LOGW("Could not request 'expand settings panel'"); + } +} + static void collapse_panels(struct controller *controller) { struct control_msg msg; diff --git a/app/tests/test_control_msg_serialize.c b/app/tests/test_control_msg_serialize.c index d7b899299b..ef9247ca23 100644 --- a/app/tests/test_control_msg_serialize.c +++ b/app/tests/test_control_msg_serialize.c @@ -177,6 +177,21 @@ static void test_serialize_expand_notification_panel(void) { assert(!memcmp(buf, expected, sizeof(expected))); } +static void test_serialize_expand_settings_panel(void) { + struct control_msg msg = { + .type = CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL, + }; + + unsigned char buf[CONTROL_MSG_MAX_SIZE]; + size_t size = control_msg_serialize(&msg, buf); + assert(size == 1); + + const unsigned char expected[] = { + CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL, + }; + assert(!memcmp(buf, expected, sizeof(expected))); +} + static void test_serialize_collapse_panels(void) { struct control_msg msg = { .type = CONTROL_MSG_TYPE_COLLAPSE_PANELS, @@ -274,6 +289,7 @@ int main(int argc, char *argv[]) { test_serialize_inject_scroll_event(); test_serialize_back_or_screen_on(); test_serialize_expand_notification_panel(); + test_serialize_expand_settings_panel(); test_serialize_collapse_panels(); test_serialize_get_clipboard(); test_serialize_set_clipboard(); diff --git a/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java b/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java index 34ce1941b1..f8edd53c11 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java +++ b/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java @@ -11,11 +11,12 @@ public final class ControlMessage { public static final int TYPE_INJECT_SCROLL_EVENT = 3; public static final int TYPE_BACK_OR_SCREEN_ON = 4; public static final int TYPE_EXPAND_NOTIFICATION_PANEL = 5; - public static final int TYPE_COLLAPSE_PANELS = 6; - public static final int TYPE_GET_CLIPBOARD = 7; - public static final int TYPE_SET_CLIPBOARD = 8; - public static final int TYPE_SET_SCREEN_POWER_MODE = 9; - public static final int TYPE_ROTATE_DEVICE = 10; + public static final int TYPE_EXPAND_SETTINGS_PANEL = 6; + public static final int TYPE_COLLAPSE_PANELS = 7; + public static final int TYPE_GET_CLIPBOARD = 8; + public static final int TYPE_SET_CLIPBOARD = 9; + public static final int TYPE_SET_SCREEN_POWER_MODE = 10; + public static final int TYPE_ROTATE_DEVICE = 11; private int type; private String text; diff --git a/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java b/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java index 97f027ffb9..e4ab840201 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java +++ b/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java @@ -77,6 +77,7 @@ public ControlMessage next() { msg = parseSetScreenPowerMode(); break; case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL: + case ControlMessage.TYPE_EXPAND_SETTINGS_PANEL: case ControlMessage.TYPE_COLLAPSE_PANELS: case ControlMessage.TYPE_GET_CLIPBOARD: case ControlMessage.TYPE_ROTATE_DEVICE: diff --git a/server/src/main/java/com/genymobile/scrcpy/Controller.java b/server/src/main/java/com/genymobile/scrcpy/Controller.java index 15c0584a3f..3760bbd4b6 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Controller.java +++ b/server/src/main/java/com/genymobile/scrcpy/Controller.java @@ -107,6 +107,9 @@ private void handleEvent() throws IOException { case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL: Device.expandNotificationPanel(); break; + case ControlMessage.TYPE_EXPAND_SETTINGS_PANEL: + Device.expandSettingsPanel(); + break; case ControlMessage.TYPE_COLLAPSE_PANELS: Device.collapsePanels(); break; diff --git a/server/src/main/java/com/genymobile/scrcpy/Device.java b/server/src/main/java/com/genymobile/scrcpy/Device.java index 624c9fa0d3..a63976fd20 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Device.java +++ b/server/src/main/java/com/genymobile/scrcpy/Device.java @@ -227,6 +227,10 @@ public static void expandNotificationPanel() { SERVICE_MANAGER.getStatusBarManager().expandNotificationsPanel(); } + public static void expandSettingsPanel() { + SERVICE_MANAGER.getStatusBarManager().expandSettingsPanel(); + } + public static void collapsePanels() { SERVICE_MANAGER.getStatusBarManager().collapsePanels(); } diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/StatusBarManager.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/StatusBarManager.java index 6f8941bdf0..5b1e5f5ed8 100644 --- a/server/src/main/java/com/genymobile/scrcpy/wrappers/StatusBarManager.java +++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/StatusBarManager.java @@ -11,6 +11,8 @@ public class StatusBarManager { private final IInterface manager; private Method expandNotificationsPanelMethod; + private Method expandSettingsPanelMethod; + private boolean expandSettingsPanelMethodNewVersion = true; private Method collapsePanelsMethod; public StatusBarManager(IInterface manager) { @@ -24,6 +26,20 @@ private Method getExpandNotificationsPanelMethod() throws NoSuchMethodException return expandNotificationsPanelMethod; } + private Method getExpandSettingsPanel() throws NoSuchMethodException { + if (expandSettingsPanelMethod == null) { + try { + // Since Android 7: https://android.googlesource.com/platform/frameworks/base.git/+/a9927325eda025504d59bb6594fee8e240d95b01%5E%21/ + expandSettingsPanelMethod = manager.getClass().getMethod("expandSettingsPanel", String.class); + } catch (NoSuchMethodException e) { + // old version + expandSettingsPanelMethod = manager.getClass().getMethod("expandSettingsPanel"); + expandSettingsPanelMethodNewVersion = false; + } + } + return expandSettingsPanelMethod; + } + private Method getCollapsePanelsMethod() throws NoSuchMethodException { if (collapsePanelsMethod == null) { collapsePanelsMethod = manager.getClass().getMethod("collapsePanels"); @@ -40,6 +56,21 @@ public void expandNotificationsPanel() { } } + public void expandSettingsPanel() { + try { + Method method = getExpandSettingsPanel(); + if (expandSettingsPanelMethodNewVersion) { + // new version + method.invoke(manager, (Object) null); + } else { + // old version + method.invoke(manager); + } + } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { + Ln.e("Could not invoke method", e); + } + } + public void collapsePanels() { try { Method method = getCollapsePanelsMethod(); diff --git a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java index 97429026b0..da56848676 100644 --- a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java +++ b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java @@ -181,6 +181,22 @@ public void testParseExpandNotificationPanelEvent() throws IOException { Assert.assertEquals(ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL, event.getType()); } + @Test + public void testParseExpandSettingsPanelEvent() throws IOException { + ControlMessageReader reader = new ControlMessageReader(); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(bos); + dos.writeByte(ControlMessage.TYPE_EXPAND_SETTINGS_PANEL); + + byte[] packet = bos.toByteArray(); + + reader.readFrom(new ByteArrayInputStream(packet)); + ControlMessage event = reader.next(); + + Assert.assertEquals(ControlMessage.TYPE_EXPAND_SETTINGS_PANEL, event.getType()); + } + @Test public void testParseCollapsePanelsEvent() throws IOException { ControlMessageReader reader = new ControlMessageReader(); From 70f7e07c1ef47a0ceb9b51f1fdc69967f443e6cc Mon Sep 17 00:00:00 2001 From: brunoais Date: Tue, 20 Apr 2021 18:31:39 +0200 Subject: [PATCH 5/7] Add keyboard shortcut to expand settings panel PR #2260 Signed-off-by: Romain Vimont --- app/src/input_manager.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/input_manager.c b/app/src/input_manager.c index 0d3175e641..d5b0c50500 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -524,8 +524,10 @@ input_manager_process_key(struct input_manager *im, if (control && !repeat && down) { if (shift) { collapse_panels(controller); - } else { + } else if (im->key_repeat == 0) { expand_notification_panel(controller); + } else { + expand_settings_panel(controller); } } return; From aafedb01c03ea87fba1bf93c0b4602812a79c78e Mon Sep 17 00:00:00 2001 From: brunoais Date: Sat, 17 Apr 2021 13:56:53 +0100 Subject: [PATCH 6/7] Add mouse shortcut to expand settings panel Double-click on extra mouse button to open the settings panel (a single-click opens the notification panel). This is consistent with the keyboard shortcut MOD+n+n. PR #2264 Signed-off-by: Romain Vimont --- app/src/input_manager.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/input_manager.c b/app/src/input_manager.c index d5b0c50500..9408661688 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -693,7 +693,11 @@ input_manager_process_mouse_button(struct input_manager *im, return; } if (control && event->button == SDL_BUTTON_X2 && down) { - expand_notification_panel(im->controller); + if (event->clicks < 2) { + expand_notification_panel(im->controller); + } else { + expand_settings_panel(im->controller); + } return; } if (control && event->button == SDL_BUTTON_RIGHT) { From 01f424e46abebd9994a1e5e1e7538bff2c73bef4 Mon Sep 17 00:00:00 2001 From: brunoais Date: Thu, 22 Apr 2021 21:57:31 +0100 Subject: [PATCH 7/7] Document 4th+5th + 2xn shortcuts --- README.md | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 6a987a73a3..97259ceb0a 100644 --- a/README.md +++ b/README.md @@ -698,10 +698,10 @@ _[Super] is typically the Windows or Cmd key._ | Rotate display left | MOD+ _(left)_ | Rotate display right | MOD+ _(right)_ | Resize window to 1:1 (pixel-perfect) | MOD+g - | Resize window to remove black borders | MOD+w \| _Double-click¹_ + | Resize window to remove black borders | MOD+w \| _Left-Double-click¹_ | Click on `HOME` | MOD+h \| _Middle-click_ | Click on `BACK` | MOD+b \| _Right-click²_ - | Click on `APP_SWITCH` | MOD+s + | Click on `APP_SWITCH` | MOD+s \| _4th-click³_ | Click on `MENU` (unlock screen) | MOD+m | Click on `VOLUME_UP` | MOD+ _(up)_ | Click on `VOLUME_DOWN` | MOD+ _(down)_ @@ -710,18 +710,27 @@ _[Super] is typically the Windows or Cmd key._ | Turn device screen off (keep mirroring) | MOD+o | Turn device screen on | MOD+Shift+o | Rotate device screen | MOD+r - | Expand notification panel | MOD+n - | Collapse notification panel | MOD+Shift+n - | Copy to clipboard³ | MOD+c - | Cut to clipboard³ | MOD+x - | Synchronize clipboards and paste³ | MOD+v + | Expand notification panel | MOD+n \| _5th-click³_ + | Expand settings panel | MOD+n+n \| _5th-double-click³_ + | Collapse panels | MOD+Shift+n + | Copy to clipboard⁴ | MOD+c + | Cut to clipboard⁴ | MOD+x + | Synchronize clipboards and paste⁴ | MOD+v | Inject computer clipboard text | MOD+Shift+v | Enable/disable FPS counter (on stdout) | MOD+i | Pinch-to-zoom | Ctrl+_click-and-move_ _¹Double-click on black borders to remove them._ _²Right-click turns the screen on if it was off, presses BACK otherwise._ -_³Only on Android >= 7._ +_³4th/5th mouse button, if your mouse has it_ +_⁴Only on Android >= 7._ + +Shortcuts with repeated keys are executted by releasing and pressing the key a second time. +For example, to execute "Expand settings panel": + +1. Press and keep pressing MOD. +2. Then double-press n. +3. Finally, release MOD. All Ctrl+_key_ shortcuts are forwarded to the device, so they are handled by the active application.