Turn screen on on right-click
The right-click is almost useless on Android, so use it to turn the screen on. Add a new control event type (command) to request the server to turn the screen on.
This commit is contained in:
parent
228545cefd
commit
a139509f11
9 changed files with 107 additions and 1 deletions
|
@ -52,6 +52,9 @@ int control_event_serialize(const struct control_event *event, unsigned char *bu
|
||||||
write32(&buf[9], (Uint32) event->scroll_event.hscroll);
|
write32(&buf[9], (Uint32) event->scroll_event.hscroll);
|
||||||
write32(&buf[13], (Uint32) event->scroll_event.vscroll);
|
write32(&buf[13], (Uint32) event->scroll_event.vscroll);
|
||||||
return 17;
|
return 17;
|
||||||
|
case CONTROL_EVENT_TYPE_COMMAND:
|
||||||
|
buf[1] = event->command_event.action;
|
||||||
|
return 2;
|
||||||
default:
|
default:
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Unknown event type: %u", (unsigned) event->type);
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Unknown event type: %u", (unsigned) event->type);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -17,8 +17,11 @@ enum control_event_type {
|
||||||
CONTROL_EVENT_TYPE_TEXT,
|
CONTROL_EVENT_TYPE_TEXT,
|
||||||
CONTROL_EVENT_TYPE_MOUSE,
|
CONTROL_EVENT_TYPE_MOUSE,
|
||||||
CONTROL_EVENT_TYPE_SCROLL,
|
CONTROL_EVENT_TYPE_SCROLL,
|
||||||
|
CONTROL_EVENT_TYPE_COMMAND,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define CONTROL_EVENT_COMMAND_SCREEN_ON 0
|
||||||
|
|
||||||
struct control_event {
|
struct control_event {
|
||||||
enum control_event_type type;
|
enum control_event_type type;
|
||||||
union {
|
union {
|
||||||
|
@ -40,6 +43,9 @@ struct control_event {
|
||||||
Sint32 hscroll;
|
Sint32 hscroll;
|
||||||
Sint32 vscroll;
|
Sint32 vscroll;
|
||||||
} scroll_event;
|
} scroll_event;
|
||||||
|
struct {
|
||||||
|
int action;
|
||||||
|
} command_event;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -293,6 +293,18 @@ static void send_keycode(enum android_keycode keycode, const char *name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void turn_screen_on(void) {
|
||||||
|
struct control_event control_event = {
|
||||||
|
.type = CONTROL_EVENT_TYPE_COMMAND,
|
||||||
|
.command_event = {
|
||||||
|
.action = CONTROL_EVENT_COMMAND_SCREEN_ON,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (!controller_push_event(&controller, &control_event)) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Cannot turn screen on");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static SDL_bool handle_new_frame(void) {
|
static SDL_bool handle_new_frame(void) {
|
||||||
mutex_lock(frames.mutex);
|
mutex_lock(frames.mutex);
|
||||||
AVFrame *frame = frames.rendering_frame;
|
AVFrame *frame = frames.rendering_frame;
|
||||||
|
@ -432,6 +444,10 @@ static void handle_mouse_motion(const SDL_MouseMotionEvent *event, struct size s
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_mouse_button(const SDL_MouseButtonEvent *event, struct size screen_size) {
|
static void handle_mouse_button(const SDL_MouseButtonEvent *event, struct size screen_size) {
|
||||||
|
if (event->button == SDL_BUTTON_RIGHT) {
|
||||||
|
turn_screen_on();
|
||||||
|
return;
|
||||||
|
};
|
||||||
struct control_event control_event;
|
struct control_event control_event;
|
||||||
if (mouse_button_from_sdl_to_android(event, screen_size, &control_event)) {
|
if (mouse_button_from_sdl_to_android(event, screen_size, &control_event)) {
|
||||||
if (!controller_push_event(&controller, &control_event)) {
|
if (!controller_push_event(&controller, &control_event)) {
|
||||||
|
|
|
@ -9,11 +9,14 @@ public class ControlEvent {
|
||||||
public static final int TYPE_TEXT = 1;
|
public static final int TYPE_TEXT = 1;
|
||||||
public static final int TYPE_MOUSE = 2;
|
public static final int TYPE_MOUSE = 2;
|
||||||
public static final int TYPE_SCROLL = 3;
|
public static final int TYPE_SCROLL = 3;
|
||||||
|
public static final int TYPE_COMMAND = 4;
|
||||||
|
|
||||||
|
public static final int COMMAND_SCREEN_ON = 0;
|
||||||
|
|
||||||
private int type;
|
private int type;
|
||||||
private String text;
|
private String text;
|
||||||
private int metaState; // KeyEvent.META_*
|
private int metaState; // KeyEvent.META_*
|
||||||
private int action; // KeyEvent.ACTION_* or MotionEvent.ACTION_*
|
private int action; // KeyEvent.ACTION_* or MotionEvent.ACTION_* or COMMAND_*
|
||||||
private int keycode; // KeyEvent.KEYCODE_*
|
private int keycode; // KeyEvent.KEYCODE_*
|
||||||
private int buttons; // MotionEvent.BUTTON_*
|
private int buttons; // MotionEvent.BUTTON_*
|
||||||
private Position position;
|
private Position position;
|
||||||
|
@ -57,6 +60,13 @@ public class ControlEvent {
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ControlEvent createCommandControlEvent(int action) {
|
||||||
|
ControlEvent event = new ControlEvent();
|
||||||
|
event.type = TYPE_COMMAND;
|
||||||
|
event.action = action;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
public int getType() {
|
public int getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ public class ControlEventReader {
|
||||||
private static final int KEYCODE_PAYLOAD_LENGTH = 9;
|
private static final int KEYCODE_PAYLOAD_LENGTH = 9;
|
||||||
private static final int MOUSE_PAYLOAD_LENGTH = 13;
|
private static final int MOUSE_PAYLOAD_LENGTH = 13;
|
||||||
private static final int SCROLL_PAYLOAD_LENGTH = 16;
|
private static final int SCROLL_PAYLOAD_LENGTH = 16;
|
||||||
|
private static final int COMMAND_PAYLOAD_LENGTH = 1;
|
||||||
|
|
||||||
private final byte[] rawBuffer = new byte[128];
|
private final byte[] rawBuffer = new byte[128];
|
||||||
private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer);
|
private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer);
|
||||||
|
@ -86,6 +87,13 @@ public class ControlEventReader {
|
||||||
int vScroll = buffer.getInt();
|
int vScroll = buffer.getInt();
|
||||||
return ControlEvent.createScrollControlEvent(position, hScroll, vScroll);
|
return ControlEvent.createScrollControlEvent(position, hScroll, vScroll);
|
||||||
}
|
}
|
||||||
|
case ControlEvent.TYPE_COMMAND: {
|
||||||
|
if (buffer.remaining() < COMMAND_PAYLOAD_LENGTH) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int action = toUnsigned(buffer.get());
|
||||||
|
return ControlEvent.createCommandControlEvent(action);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
Ln.w("Unknown event type: " + type);
|
Ln.w("Unknown event type: " + type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import android.os.RemoteException;
|
||||||
import android.view.IRotationWatcher;
|
import android.view.IRotationWatcher;
|
||||||
|
|
||||||
import com.genymobile.scrcpy.wrappers.InputManager;
|
import com.genymobile.scrcpy.wrappers.InputManager;
|
||||||
|
import com.genymobile.scrcpy.wrappers.PowerManager;
|
||||||
import com.genymobile.scrcpy.wrappers.ServiceManager;
|
import com.genymobile.scrcpy.wrappers.ServiceManager;
|
||||||
|
|
||||||
public final class Device {
|
public final class Device {
|
||||||
|
@ -93,6 +94,10 @@ public final class Device {
|
||||||
return serviceManager.getInputManager();
|
return serviceManager.getInputManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PowerManager getPowerManager() {
|
||||||
|
return serviceManager.getPowerManager();
|
||||||
|
}
|
||||||
|
|
||||||
public void registerRotationWatcher(IRotationWatcher rotationWatcher) {
|
public void registerRotationWatcher(IRotationWatcher rotationWatcher) {
|
||||||
serviceManager.getWindowManager().registerRotationWatcher(rotationWatcher);
|
serviceManager.getWindowManager().registerRotationWatcher(rotationWatcher);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
import com.genymobile.scrcpy.wrappers.InputManager;
|
import com.genymobile.scrcpy.wrappers.InputManager;
|
||||||
|
import com.genymobile.scrcpy.wrappers.PowerManager;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -16,6 +17,7 @@ public class EventController {
|
||||||
|
|
||||||
private final Device device;
|
private final Device device;
|
||||||
private final InputManager inputManager;
|
private final InputManager inputManager;
|
||||||
|
private final PowerManager powerManager;
|
||||||
private final DesktopConnection connection;
|
private final DesktopConnection connection;
|
||||||
|
|
||||||
private final KeyCharacterMap charMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
|
private final KeyCharacterMap charMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
|
||||||
|
@ -28,6 +30,7 @@ public class EventController {
|
||||||
this.device = device;
|
this.device = device;
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
inputManager = device.getInputManager();
|
inputManager = device.getInputManager();
|
||||||
|
powerManager = device.getPowerManager();
|
||||||
initPointer();
|
initPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +82,10 @@ public class EventController {
|
||||||
break;
|
break;
|
||||||
case ControlEvent.TYPE_SCROLL:
|
case ControlEvent.TYPE_SCROLL:
|
||||||
injectScroll(controlEvent.getPosition(), controlEvent.getHScroll(), controlEvent.getVScroll());
|
injectScroll(controlEvent.getPosition(), controlEvent.getHScroll(), controlEvent.getVScroll());
|
||||||
|
break;
|
||||||
|
case ControlEvent.TYPE_COMMAND:
|
||||||
|
executeCommand(controlEvent.getAction());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -137,7 +144,24 @@ public class EventController {
|
||||||
return injectEvent(event);
|
return injectEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean injectKeycode(int keyCode) {
|
||||||
|
return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0)
|
||||||
|
&& injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean injectEvent(InputEvent event) {
|
private boolean injectEvent(InputEvent event) {
|
||||||
return inputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
|
return inputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean turnScreenOn() {
|
||||||
|
return powerManager.isScreenOn() || injectKeycode(KeyEvent.KEYCODE_POWER);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean executeCommand(int action) {
|
||||||
|
switch (action) {
|
||||||
|
case ControlEvent.COMMAND_SCREEN_ON:
|
||||||
|
return turnScreenOn();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.genymobile.scrcpy.wrappers;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.IInterface;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
public class PowerManager {
|
||||||
|
private final IInterface manager;
|
||||||
|
private final Method isScreenOnMethod;
|
||||||
|
|
||||||
|
public PowerManager(IInterface manager) {
|
||||||
|
this.manager = manager;
|
||||||
|
try {
|
||||||
|
String methodName = Build.VERSION.SDK_INT >= 20 ? "isInteractive" : "isScreenOn";
|
||||||
|
isScreenOnMethod = manager.getClass().getMethod(methodName);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isScreenOn() {
|
||||||
|
try {
|
||||||
|
return (Boolean) isScreenOnMethod.invoke(manager);
|
||||||
|
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,4 +37,8 @@ public class ServiceManager {
|
||||||
public InputManager getInputManager() {
|
public InputManager getInputManager() {
|
||||||
return new InputManager(getService("input", "android.hardware.input.IInputManager"));
|
return new InputManager(getService("input", "android.hardware.input.IInputManager"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PowerManager getPowerManager() {
|
||||||
|
return new PowerManager(getService("power", "android.os.IPowerManager"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue