Skip to content

Commit

Permalink
wip: add game back menu
Browse files Browse the repository at this point in the history
Add back menu to send sepcial keys. E.g. close fullscreen while using yuzu.
  • Loading branch information
Karim Mreisi committed Jan 15, 2023
1 parent b8904bb commit b6097d3
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 1 deletion.
19 changes: 18 additions & 1 deletion app/src/main/java/com/limelight/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PictureInPictureParams;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
Expand All @@ -63,7 +65,10 @@
import android.view.Display;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.SubMenu;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.View;
Expand All @@ -72,12 +77,15 @@
import android.view.View.OnTouchListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.view.inputmethod.InputMethodManager;
import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;

import java.io.ByteArrayInputStream;
import java.io.PipedOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.cert.CertificateException;
Expand Down Expand Up @@ -2264,7 +2272,16 @@ public void onUsbPermissionPromptCompleted() {
public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
switch (keyEvent.getAction()) {
case KeyEvent.ACTION_DOWN:
return handleKeyDown(keyEvent);
boolean handled = handleKeyDown(keyEvent);
if (handled)
return true;

// Intercept back key event before android handles it
// Always handle the request, the user has to select "Disconnect" within the back menu to actually disconnect
if (keyCode == keyEvent.KEYCODE_BACK) {
new GameBackMenu(this, conn);
return true;
}
case KeyEvent.ACTION_UP:
return handleKeyUp(keyEvent);
default:
Expand Down
98 changes: 98 additions & 0 deletions app/src/main/java/com/limelight/GameBackMenu.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.limelight;

import android.app.AlertDialog;
import android.widget.ArrayAdapter;

import com.limelight.nvstream.NvConnection;
import com.limelight.nvstream.input.KeyboardPacket;

public class GameBackMenu {

private final Game game;
private final NvConnection conn;

public GameBackMenu(Game game, NvConnection conn) {
this.game = game;
this.conn = conn;

showMenuDialog("Back Menu", new MenuDialogOption[]{
new MenuDialogOption("Send special key(s)", () -> showSpecialKeysMenu()),
new MenuDialogOption("Disconnect", () -> game.onBackPressed()),
new MenuDialogOption("Cancel", null),
});
}

private void sendKeySequence(byte modifier, short[] keys) {

for (short key : keys)
conn.sendKeyboardInput(key, KeyboardPacket.KEY_DOWN, (byte) (modifier | KeyboardPacket.KEY_DOWN));

for (int pos = keys.length - 1; pos >= 0; pos--)
conn.sendKeyboardInput(keys[pos], KeyboardPacket.KEY_UP, (byte) (modifier | KeyboardPacket.KEY_UP));
}

private void showMenuDialog(String title, MenuDialogOption[] options) {
AlertDialog.Builder builder = new AlertDialog.Builder(game);
builder.setTitle(title);

final ArrayAdapter<String> actions =
new ArrayAdapter<String>(game, android.R.layout.simple_list_item_1);

for (MenuDialogOption option : options) {
actions.add(option.label);
}

builder.setAdapter(actions, (dialog, which) -> {
String label = actions.getItem(which);
for (MenuDialogOption option : options) {
if (!label.equals(option.label)) {
continue;
}

if (option.runnable != null) {
option.runnable.run();
}
break;
}
});

builder.show();
}

private void showSpecialKeysMenu() {
showMenuDialog(ACTIONS.SEND_SPECIAL_KEYS, new MenuDialogOption[]{
new MenuDialogOption("Send ESC", () -> sendKeySequence(
(byte) 0, new short[]{0x18})),
new MenuDialogOption("Send F11", () -> sendKeySequence(
(byte) 0, new short[]{0x7a})),
new MenuDialogOption("Send WIN (Open Start Menu)", () -> sendKeySequence(
(byte) 0, new short[]{0x5B})),
new MenuDialogOption("Send WIN + D (Switch to Desktop)", () -> sendKeySequence(
(byte) 0, new short[]{0x5B, 0x44})),
new MenuDialogOption("Send WIN + G (Open Xbox Game Bar)", () -> sendKeySequence(
(byte) 0, new short[]{0x5B, 0x47})),
/*
TODO: Currently not working
new MenuDialogOption("Send SHIFT + TAB (Open Steam Overlay)", () -> sendKeySequence(
(byte) 0, new short[]{0xA0, 0x09})),
*/
new MenuDialogOption("Cancel", null),
});
}

private interface ACTIONS {
String CONTINUE = "Continue";
String SEND_SPECIAL_KEYS = "Send special key(s)";
String DISCONNECT = "Disconnect";
}

private class MenuDialogOption {
private final String label;
private final Runnable runnable;

MenuDialogOption(String label, Runnable runnable) {
this.label = label;
this.runnable = runnable;
}
}
}

0 comments on commit b6097d3

Please sign in to comment.