2024-04-14 17:09:51 +03:00
|
|
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
2024-06-10 15:24:34 +03:00
|
|
|
#include <SDL3/SDL_events.h>
|
2024-12-14 22:30:17 +00:00
|
|
|
#include <SDL3/SDL_hints.h>
|
2024-06-10 15:24:34 +03:00
|
|
|
#include <SDL3/SDL_init.h>
|
|
|
|
#include <SDL3/SDL_properties.h>
|
2024-10-19 15:57:01 +03:00
|
|
|
#include <SDL3/SDL_timer.h>
|
2024-06-10 15:24:34 +03:00
|
|
|
#include <SDL3/SDL_video.h>
|
2024-11-30 22:37:36 +02:00
|
|
|
|
2024-04-14 17:09:51 +03:00
|
|
|
#include "common/assert.h"
|
2024-06-09 12:25:00 +02:00
|
|
|
#include "common/config.h"
|
2024-04-14 17:09:51 +03:00
|
|
|
#include "core/libraries/pad/pad.h"
|
2024-09-08 16:50:32 -03:00
|
|
|
#include "imgui/renderer/imgui_core.h"
|
2024-04-14 17:09:51 +03:00
|
|
|
#include "input/controller.h"
|
|
|
|
#include "sdl_window.h"
|
2024-07-28 16:54:09 +03:00
|
|
|
#include "video_core/renderdoc.h"
|
2024-04-14 17:09:51 +03:00
|
|
|
|
2024-07-09 02:18:34 -07:00
|
|
|
#ifdef __APPLE__
|
|
|
|
#include <SDL3/SDL_metal.h>
|
|
|
|
#endif
|
|
|
|
|
2024-04-14 17:09:51 +03:00
|
|
|
namespace Frontend {
|
|
|
|
|
2024-11-30 22:37:36 +02:00
|
|
|
using namespace Libraries::Pad;
|
|
|
|
|
|
|
|
static OrbisPadButtonDataOffset SDLGamepadToOrbisButton(u8 button) {
|
|
|
|
switch (button) {
|
|
|
|
case SDL_GAMEPAD_BUTTON_DPAD_DOWN:
|
|
|
|
return OrbisPadButtonDataOffset::Down;
|
|
|
|
case SDL_GAMEPAD_BUTTON_DPAD_UP:
|
|
|
|
return OrbisPadButtonDataOffset::Up;
|
|
|
|
case SDL_GAMEPAD_BUTTON_DPAD_LEFT:
|
|
|
|
return OrbisPadButtonDataOffset::Left;
|
|
|
|
case SDL_GAMEPAD_BUTTON_DPAD_RIGHT:
|
|
|
|
return OrbisPadButtonDataOffset::Right;
|
|
|
|
case SDL_GAMEPAD_BUTTON_SOUTH:
|
|
|
|
return OrbisPadButtonDataOffset::Cross;
|
|
|
|
case SDL_GAMEPAD_BUTTON_NORTH:
|
|
|
|
return OrbisPadButtonDataOffset::Triangle;
|
|
|
|
case SDL_GAMEPAD_BUTTON_WEST:
|
|
|
|
return OrbisPadButtonDataOffset::Square;
|
|
|
|
case SDL_GAMEPAD_BUTTON_EAST:
|
|
|
|
return OrbisPadButtonDataOffset::Circle;
|
|
|
|
case SDL_GAMEPAD_BUTTON_START:
|
|
|
|
return OrbisPadButtonDataOffset::Options;
|
|
|
|
case SDL_GAMEPAD_BUTTON_TOUCHPAD:
|
|
|
|
return OrbisPadButtonDataOffset::TouchPad;
|
|
|
|
case SDL_GAMEPAD_BUTTON_BACK:
|
|
|
|
return OrbisPadButtonDataOffset::TouchPad;
|
|
|
|
case SDL_GAMEPAD_BUTTON_LEFT_SHOULDER:
|
|
|
|
return OrbisPadButtonDataOffset::L1;
|
|
|
|
case SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER:
|
|
|
|
return OrbisPadButtonDataOffset::R1;
|
|
|
|
case SDL_GAMEPAD_BUTTON_LEFT_STICK:
|
|
|
|
return OrbisPadButtonDataOffset::L3;
|
|
|
|
case SDL_GAMEPAD_BUTTON_RIGHT_STICK:
|
|
|
|
return OrbisPadButtonDataOffset::R3;
|
|
|
|
default:
|
|
|
|
return OrbisPadButtonDataOffset::None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-19 15:57:01 +03:00
|
|
|
static Uint32 SDLCALL PollController(void* userdata, SDL_TimerID timer_id, Uint32 interval) {
|
|
|
|
auto* controller = reinterpret_cast<Input::GameController*>(userdata);
|
|
|
|
return controller->Poll();
|
|
|
|
}
|
|
|
|
|
2024-07-24 00:12:53 -06:00
|
|
|
WindowSDL::WindowSDL(s32 width_, s32 height_, Input::GameController* controller_,
|
2024-08-01 00:56:10 +03:00
|
|
|
std::string_view window_title)
|
2024-07-25 01:15:44 -06:00
|
|
|
: width{width_}, height{height_}, controller{controller_} {
|
2024-12-14 22:30:17 +00:00
|
|
|
if (!SDL_SetHint(SDL_HINT_APP_NAME, "shadPS4")) {
|
|
|
|
UNREACHABLE_MSG("Failed to set SDL window hint: {}", SDL_GetError());
|
|
|
|
}
|
2024-09-29 20:47:55 -07:00
|
|
|
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
2024-04-14 17:09:51 +03:00
|
|
|
UNREACHABLE_MSG("Failed to initialize SDL video subsystem: {}", SDL_GetError());
|
|
|
|
}
|
2024-06-14 00:58:57 +03:00
|
|
|
SDL_InitSubSystem(SDL_INIT_AUDIO);
|
2024-04-14 17:09:51 +03:00
|
|
|
|
|
|
|
SDL_PropertiesID props = SDL_CreateProperties();
|
2024-08-01 01:11:58 +03:00
|
|
|
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING,
|
|
|
|
std::string(window_title).c_str());
|
2024-04-14 17:09:51 +03:00
|
|
|
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, SDL_WINDOWPOS_CENTERED);
|
|
|
|
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, SDL_WINDOWPOS_CENTERED);
|
|
|
|
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, width);
|
|
|
|
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, height);
|
|
|
|
SDL_SetNumberProperty(props, "flags", SDL_WINDOW_VULKAN);
|
2024-09-25 11:43:08 +02:00
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_RESIZABLE_BOOLEAN, true);
|
2024-04-14 17:09:51 +03:00
|
|
|
window = SDL_CreateWindowWithProperties(props);
|
|
|
|
SDL_DestroyProperties(props);
|
|
|
|
if (window == nullptr) {
|
|
|
|
UNREACHABLE_MSG("Failed to create window handle: {}", SDL_GetError());
|
|
|
|
}
|
|
|
|
|
2024-12-29 17:35:52 +07:00
|
|
|
SDL_SetWindowMinimumSize(window, 640, 360);
|
2025-01-07 14:30:05 +01:00
|
|
|
|
|
|
|
bool error = false;
|
|
|
|
const SDL_DisplayID displayIndex = SDL_GetDisplayForWindow(window);
|
|
|
|
if (displayIndex < 0) {
|
|
|
|
LOG_ERROR(Frontend, "Error getting display index: {}", SDL_GetError());
|
|
|
|
error = true;
|
|
|
|
}
|
|
|
|
const SDL_DisplayMode* displayMode;
|
|
|
|
if ((displayMode = SDL_GetCurrentDisplayMode(displayIndex)) == 0) {
|
|
|
|
LOG_ERROR(Frontend, "Error getting display mode: {}", SDL_GetError());
|
|
|
|
error = true;
|
|
|
|
}
|
|
|
|
if (!error) {
|
|
|
|
SDL_SetWindowFullscreenMode(window,
|
|
|
|
Config::getFullscreenMode() == "True" ? displayMode : NULL);
|
|
|
|
}
|
|
|
|
SDL_SetWindowFullscreen(window, Config::getIsFullscreen());
|
2024-04-14 17:09:51 +03:00
|
|
|
|
2024-08-13 11:54:08 +02:00
|
|
|
SDL_InitSubSystem(SDL_INIT_GAMEPAD);
|
|
|
|
controller->TryOpenSDLController();
|
|
|
|
|
2024-04-14 17:09:51 +03:00
|
|
|
#if defined(SDL_PLATFORM_WIN32)
|
|
|
|
window_info.type = WindowSystemType::Windows;
|
2024-08-05 19:27:03 +03:00
|
|
|
window_info.render_surface = SDL_GetPointerProperty(SDL_GetWindowProperties(window),
|
|
|
|
SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
|
2024-04-14 17:09:51 +03:00
|
|
|
#elif defined(SDL_PLATFORM_LINUX)
|
|
|
|
if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) {
|
|
|
|
window_info.type = WindowSystemType::X11;
|
2024-08-05 19:52:30 +03:00
|
|
|
window_info.display_connection = SDL_GetPointerProperty(
|
|
|
|
SDL_GetWindowProperties(window), SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL);
|
2024-04-14 17:09:51 +03:00
|
|
|
window_info.render_surface = (void*)SDL_GetNumberProperty(
|
|
|
|
SDL_GetWindowProperties(window), SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
|
|
|
|
} else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0) {
|
|
|
|
window_info.type = WindowSystemType::Wayland;
|
2024-08-05 22:36:25 +03:00
|
|
|
window_info.display_connection = SDL_GetPointerProperty(
|
2024-04-14 17:09:51 +03:00
|
|
|
SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, NULL);
|
2024-08-05 22:36:25 +03:00
|
|
|
window_info.render_surface = SDL_GetPointerProperty(
|
|
|
|
SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, NULL);
|
2024-04-14 17:09:51 +03:00
|
|
|
}
|
2024-07-09 02:18:34 -07:00
|
|
|
#elif defined(SDL_PLATFORM_MACOS)
|
|
|
|
window_info.type = WindowSystemType::Metal;
|
|
|
|
window_info.render_surface = SDL_Metal_GetLayer(SDL_Metal_CreateView(window));
|
2024-04-14 17:09:51 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
WindowSDL::~WindowSDL() = default;
|
|
|
|
|
2024-11-30 22:37:36 +02:00
|
|
|
void WindowSDL::WaitEvent() {
|
2024-04-14 17:09:51 +03:00
|
|
|
// Called on main thread
|
|
|
|
SDL_Event event;
|
|
|
|
|
2024-07-28 16:54:09 +03:00
|
|
|
if (!SDL_WaitEvent(&event)) {
|
2024-04-14 17:09:51 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-09-08 16:50:32 -03:00
|
|
|
if (ImGui::Core::ProcessEvent(&event)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-04-14 17:09:51 +03:00
|
|
|
switch (event.type) {
|
|
|
|
case SDL_EVENT_WINDOW_RESIZED:
|
|
|
|
case SDL_EVENT_WINDOW_MAXIMIZED:
|
|
|
|
case SDL_EVENT_WINDOW_RESTORED:
|
2024-11-30 22:37:36 +02:00
|
|
|
OnResize();
|
2024-04-14 17:09:51 +03:00
|
|
|
break;
|
|
|
|
case SDL_EVENT_WINDOW_MINIMIZED:
|
|
|
|
case SDL_EVENT_WINDOW_EXPOSED:
|
|
|
|
is_shown = event.type == SDL_EVENT_WINDOW_EXPOSED;
|
2024-11-30 22:37:36 +02:00
|
|
|
OnResize();
|
2024-04-14 17:09:51 +03:00
|
|
|
break;
|
|
|
|
case SDL_EVENT_KEY_DOWN:
|
|
|
|
case SDL_EVENT_KEY_UP:
|
2024-11-30 22:37:36 +02:00
|
|
|
OnKeyPress(&event);
|
2024-04-14 17:09:51 +03:00
|
|
|
break;
|
2024-08-13 11:54:08 +02:00
|
|
|
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
|
|
|
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
|
|
|
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
2024-08-28 13:48:50 +02:00
|
|
|
case SDL_EVENT_GAMEPAD_ADDED:
|
|
|
|
case SDL_EVENT_GAMEPAD_REMOVED:
|
|
|
|
case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN:
|
|
|
|
case SDL_EVENT_GAMEPAD_TOUCHPAD_UP:
|
|
|
|
case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION:
|
2024-11-30 22:37:36 +02:00
|
|
|
OnGamepadEvent(&event);
|
2024-08-13 11:54:08 +02:00
|
|
|
break;
|
2025-01-01 19:05:22 +01:00
|
|
|
// i really would have appreciated ANY KIND OF DOCUMENTATION ON THIS
|
|
|
|
// AND IT DOESN'T EVEN USE PROPER ENUMS
|
|
|
|
case SDL_EVENT_GAMEPAD_SENSOR_UPDATE:
|
|
|
|
switch ((SDL_SensorType)event.gsensor.sensor) {
|
|
|
|
case SDL_SENSOR_GYRO:
|
|
|
|
controller->Gyro(0, event.gsensor.data);
|
|
|
|
break;
|
|
|
|
case SDL_SENSOR_ACCEL:
|
|
|
|
controller->Acceleration(0, event.gsensor.data);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2024-04-14 17:09:51 +03:00
|
|
|
case SDL_EVENT_QUIT:
|
|
|
|
is_open = false;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-30 22:37:36 +02:00
|
|
|
void WindowSDL::InitTimers() {
|
2024-10-19 15:57:01 +03:00
|
|
|
SDL_AddTimer(100, &PollController, controller);
|
|
|
|
}
|
|
|
|
|
2024-12-09 17:11:11 -03:00
|
|
|
void WindowSDL::RequestKeyboard() {
|
|
|
|
if (keyboard_grab == 0) {
|
|
|
|
SDL_StartTextInput(window);
|
|
|
|
}
|
|
|
|
keyboard_grab++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void WindowSDL::ReleaseKeyboard() {
|
|
|
|
ASSERT(keyboard_grab > 0);
|
|
|
|
keyboard_grab--;
|
|
|
|
if (keyboard_grab == 0) {
|
|
|
|
SDL_StopTextInput(window);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-30 22:37:36 +02:00
|
|
|
void WindowSDL::OnResize() {
|
2024-04-14 17:09:51 +03:00
|
|
|
SDL_GetWindowSizeInPixels(window, &width, &height);
|
2024-09-08 16:50:32 -03:00
|
|
|
ImGui::Core::OnResize();
|
2024-04-14 17:09:51 +03:00
|
|
|
}
|
|
|
|
|
2024-11-30 22:37:36 +02:00
|
|
|
void WindowSDL::OnKeyPress(const SDL_Event* event) {
|
2024-09-11 12:56:27 +03:00
|
|
|
#ifdef __APPLE__
|
|
|
|
// Use keys that are more friendly for keyboards without a keypad.
|
|
|
|
// Once there are key binding options this won't be necessary.
|
|
|
|
constexpr SDL_Keycode CrossKey = SDLK_N;
|
|
|
|
constexpr SDL_Keycode CircleKey = SDLK_B;
|
|
|
|
constexpr SDL_Keycode SquareKey = SDLK_V;
|
|
|
|
constexpr SDL_Keycode TriangleKey = SDLK_C;
|
|
|
|
#else
|
|
|
|
constexpr SDL_Keycode CrossKey = SDLK_KP_2;
|
|
|
|
constexpr SDL_Keycode CircleKey = SDLK_KP_6;
|
|
|
|
constexpr SDL_Keycode SquareKey = SDLK_KP_4;
|
|
|
|
constexpr SDL_Keycode TriangleKey = SDLK_KP_8;
|
|
|
|
#endif
|
|
|
|
|
2024-11-30 22:37:36 +02:00
|
|
|
auto button = OrbisPadButtonDataOffset::None;
|
2024-06-17 13:42:39 +03:00
|
|
|
Input::Axis axis = Input::Axis::AxisMax;
|
|
|
|
int axisvalue = 0;
|
|
|
|
int ax = 0;
|
2024-10-07 23:15:30 -07:00
|
|
|
std::string backButtonBehavior = Config::getBackButtonBehavior();
|
2024-09-11 12:56:27 +03:00
|
|
|
switch (event->key.key) {
|
|
|
|
case SDLK_UP:
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::Up;
|
2024-09-11 12:56:27 +03:00
|
|
|
break;
|
|
|
|
case SDLK_DOWN:
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::Down;
|
2024-09-11 12:56:27 +03:00
|
|
|
break;
|
|
|
|
case SDLK_LEFT:
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::Left;
|
2024-09-11 12:56:27 +03:00
|
|
|
break;
|
|
|
|
case SDLK_RIGHT:
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::Right;
|
2024-09-11 12:56:27 +03:00
|
|
|
break;
|
|
|
|
case TriangleKey:
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::Triangle;
|
2024-09-11 12:56:27 +03:00
|
|
|
break;
|
|
|
|
case CircleKey:
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::Circle;
|
2024-09-11 12:56:27 +03:00
|
|
|
break;
|
|
|
|
case CrossKey:
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::Cross;
|
2024-09-11 12:56:27 +03:00
|
|
|
break;
|
|
|
|
case SquareKey:
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::Square;
|
2024-09-11 12:56:27 +03:00
|
|
|
break;
|
|
|
|
case SDLK_RETURN:
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::Options;
|
2024-09-11 12:56:27 +03:00
|
|
|
break;
|
|
|
|
case SDLK_A:
|
|
|
|
axis = Input::Axis::LeftX;
|
|
|
|
if (event->type == SDL_EVENT_KEY_DOWN) {
|
|
|
|
axisvalue += -127;
|
|
|
|
} else {
|
|
|
|
axisvalue = 0;
|
2024-06-21 14:37:49 +03:00
|
|
|
}
|
2024-09-11 12:56:27 +03:00
|
|
|
ax = Input::GetAxis(-0x80, 0x80, axisvalue);
|
|
|
|
break;
|
|
|
|
case SDLK_D:
|
|
|
|
axis = Input::Axis::LeftX;
|
|
|
|
if (event->type == SDL_EVENT_KEY_DOWN) {
|
|
|
|
axisvalue += 127;
|
|
|
|
} else {
|
|
|
|
axisvalue = 0;
|
2024-06-21 14:37:49 +03:00
|
|
|
}
|
2024-09-11 12:56:27 +03:00
|
|
|
ax = Input::GetAxis(-0x80, 0x80, axisvalue);
|
|
|
|
break;
|
|
|
|
case SDLK_W:
|
|
|
|
axis = Input::Axis::LeftY;
|
|
|
|
if (event->type == SDL_EVENT_KEY_DOWN) {
|
|
|
|
axisvalue += -127;
|
|
|
|
} else {
|
|
|
|
axisvalue = 0;
|
|
|
|
}
|
|
|
|
ax = Input::GetAxis(-0x80, 0x80, axisvalue);
|
|
|
|
break;
|
|
|
|
case SDLK_S:
|
|
|
|
axis = Input::Axis::LeftY;
|
|
|
|
if (event->type == SDL_EVENT_KEY_DOWN) {
|
|
|
|
axisvalue += 127;
|
|
|
|
} else {
|
|
|
|
axisvalue = 0;
|
|
|
|
}
|
|
|
|
ax = Input::GetAxis(-0x80, 0x80, axisvalue);
|
|
|
|
break;
|
|
|
|
case SDLK_J:
|
|
|
|
axis = Input::Axis::RightX;
|
|
|
|
if (event->type == SDL_EVENT_KEY_DOWN) {
|
|
|
|
axisvalue += -127;
|
|
|
|
} else {
|
|
|
|
axisvalue = 0;
|
|
|
|
}
|
|
|
|
ax = Input::GetAxis(-0x80, 0x80, axisvalue);
|
|
|
|
break;
|
|
|
|
case SDLK_L:
|
|
|
|
axis = Input::Axis::RightX;
|
|
|
|
if (event->type == SDL_EVENT_KEY_DOWN) {
|
|
|
|
axisvalue += 127;
|
|
|
|
} else {
|
|
|
|
axisvalue = 0;
|
|
|
|
}
|
|
|
|
ax = Input::GetAxis(-0x80, 0x80, axisvalue);
|
|
|
|
break;
|
|
|
|
case SDLK_I:
|
|
|
|
axis = Input::Axis::RightY;
|
|
|
|
if (event->type == SDL_EVENT_KEY_DOWN) {
|
|
|
|
axisvalue += -127;
|
|
|
|
} else {
|
|
|
|
axisvalue = 0;
|
|
|
|
}
|
|
|
|
ax = Input::GetAxis(-0x80, 0x80, axisvalue);
|
|
|
|
break;
|
|
|
|
case SDLK_K:
|
|
|
|
axis = Input::Axis::RightY;
|
|
|
|
if (event->type == SDL_EVENT_KEY_DOWN) {
|
|
|
|
axisvalue += 127;
|
|
|
|
} else {
|
|
|
|
axisvalue = 0;
|
|
|
|
}
|
|
|
|
ax = Input::GetAxis(-0x80, 0x80, axisvalue);
|
|
|
|
break;
|
|
|
|
case SDLK_X:
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::L3;
|
2024-09-11 12:56:27 +03:00
|
|
|
break;
|
|
|
|
case SDLK_M:
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::R3;
|
2024-09-11 12:56:27 +03:00
|
|
|
break;
|
|
|
|
case SDLK_Q:
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::L1;
|
2024-09-11 12:56:27 +03:00
|
|
|
break;
|
|
|
|
case SDLK_U:
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::R1;
|
2024-09-11 12:56:27 +03:00
|
|
|
break;
|
|
|
|
case SDLK_E:
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::L2;
|
2024-09-11 12:56:27 +03:00
|
|
|
axis = Input::Axis::TriggerLeft;
|
|
|
|
if (event->type == SDL_EVENT_KEY_DOWN) {
|
|
|
|
axisvalue += 255;
|
|
|
|
} else {
|
|
|
|
axisvalue = 0;
|
|
|
|
}
|
|
|
|
ax = Input::GetAxis(0, 0x80, axisvalue);
|
|
|
|
break;
|
|
|
|
case SDLK_O:
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::R2;
|
2024-09-11 12:56:27 +03:00
|
|
|
axis = Input::Axis::TriggerRight;
|
|
|
|
if (event->type == SDL_EVENT_KEY_DOWN) {
|
|
|
|
axisvalue += 255;
|
|
|
|
} else {
|
|
|
|
axisvalue = 0;
|
|
|
|
}
|
|
|
|
ax = Input::GetAxis(0, 0x80, axisvalue);
|
|
|
|
break;
|
|
|
|
case SDLK_SPACE:
|
2024-10-07 23:15:30 -07:00
|
|
|
if (backButtonBehavior != "none") {
|
|
|
|
float x = backButtonBehavior == "left" ? 0.25f
|
|
|
|
: (backButtonBehavior == "right" ? 0.75f : 0.5f);
|
|
|
|
// trigger a touchpad event so that the touchpad emulation for back button works
|
|
|
|
controller->SetTouchpadState(0, true, x, 0.5f);
|
2024-11-30 22:37:36 +02:00
|
|
|
button = OrbisPadButtonDataOffset::TouchPad;
|
2024-10-07 23:15:30 -07:00
|
|
|
} else {
|
2024-11-30 22:37:36 +02:00
|
|
|
button = {};
|
2024-10-07 23:15:30 -07:00
|
|
|
}
|
2024-09-11 12:56:27 +03:00
|
|
|
break;
|
|
|
|
case SDLK_F11:
|
|
|
|
if (event->type == SDL_EVENT_KEY_DOWN) {
|
|
|
|
{
|
2024-08-26 18:27:31 -04:00
|
|
|
SDL_WindowFlags flag = SDL_GetWindowFlags(window);
|
|
|
|
bool is_fullscreen = flag & SDL_WINDOW_FULLSCREEN;
|
|
|
|
SDL_SetWindowFullscreen(window, !is_fullscreen);
|
|
|
|
}
|
|
|
|
}
|
2024-09-11 12:56:27 +03:00
|
|
|
break;
|
|
|
|
case SDLK_F12:
|
|
|
|
if (event->type == SDL_EVENT_KEY_DOWN) {
|
|
|
|
// Trigger rdoc capture
|
|
|
|
VideoCore::TriggerCapture();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2024-04-14 17:09:51 +03:00
|
|
|
}
|
2024-11-30 22:37:36 +02:00
|
|
|
if (button != OrbisPadButtonDataOffset::None) {
|
2024-06-17 12:52:25 +03:00
|
|
|
controller->CheckButton(0, button, event->type == SDL_EVENT_KEY_DOWN);
|
2024-04-14 17:09:51 +03:00
|
|
|
}
|
2024-06-17 14:33:03 +03:00
|
|
|
if (axis != Input::Axis::AxisMax) {
|
2024-09-11 12:56:27 +03:00
|
|
|
controller->Axis(0, axis, ax);
|
2024-06-17 13:42:39 +03:00
|
|
|
}
|
2024-04-14 17:09:51 +03:00
|
|
|
}
|
|
|
|
|
2024-11-30 22:37:36 +02:00
|
|
|
void WindowSDL::OnGamepadEvent(const SDL_Event* event) {
|
|
|
|
auto button = OrbisPadButtonDataOffset::None;
|
2024-08-13 11:54:08 +02:00
|
|
|
Input::Axis axis = Input::Axis::AxisMax;
|
|
|
|
switch (event->type) {
|
2024-08-28 13:48:50 +02:00
|
|
|
case SDL_EVENT_GAMEPAD_ADDED:
|
|
|
|
case SDL_EVENT_GAMEPAD_REMOVED:
|
|
|
|
controller->TryOpenSDLController();
|
|
|
|
break;
|
|
|
|
case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN:
|
|
|
|
case SDL_EVENT_GAMEPAD_TOUCHPAD_UP:
|
|
|
|
case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION:
|
|
|
|
controller->SetTouchpadState(event->gtouchpad.finger,
|
|
|
|
event->type != SDL_EVENT_GAMEPAD_TOUCHPAD_UP,
|
|
|
|
event->gtouchpad.x, event->gtouchpad.y);
|
|
|
|
break;
|
2024-08-13 11:54:08 +02:00
|
|
|
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
2024-11-30 22:37:36 +02:00
|
|
|
case SDL_EVENT_GAMEPAD_BUTTON_UP: {
|
|
|
|
button = SDLGamepadToOrbisButton(event->gbutton.button);
|
|
|
|
if (button == OrbisPadButtonDataOffset::None) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (event->gbutton.button != SDL_GAMEPAD_BUTTON_BACK) {
|
|
|
|
controller->CheckButton(0, button, event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
const auto backButtonBehavior = Config::getBackButtonBehavior();
|
|
|
|
if (backButtonBehavior != "none") {
|
|
|
|
float x = backButtonBehavior == "left" ? 0.25f
|
|
|
|
: (backButtonBehavior == "right" ? 0.75f : 0.5f);
|
|
|
|
// trigger a touchpad event so that the touchpad emulation for back button works
|
|
|
|
controller->SetTouchpadState(0, true, x, 0.5f);
|
|
|
|
controller->CheckButton(0, button, event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN);
|
2024-08-13 11:54:08 +02:00
|
|
|
}
|
|
|
|
break;
|
2024-11-30 22:37:36 +02:00
|
|
|
}
|
2024-08-13 11:54:08 +02:00
|
|
|
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
|
|
|
axis = event->gaxis.axis == SDL_GAMEPAD_AXIS_LEFTX ? Input::Axis::LeftX
|
|
|
|
: event->gaxis.axis == SDL_GAMEPAD_AXIS_LEFTY ? Input::Axis::LeftY
|
|
|
|
: event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHTX ? Input::Axis::RightX
|
|
|
|
: event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHTY ? Input::Axis::RightY
|
|
|
|
: event->gaxis.axis == SDL_GAMEPAD_AXIS_LEFT_TRIGGER ? Input::Axis::TriggerLeft
|
|
|
|
: event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER ? Input::Axis::TriggerRight
|
|
|
|
: Input::Axis::AxisMax;
|
|
|
|
if (axis != Input::Axis::AxisMax) {
|
2024-08-22 19:43:45 +03:00
|
|
|
if (event->gaxis.axis == SDL_GAMEPAD_AXIS_LEFT_TRIGGER ||
|
|
|
|
event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) {
|
|
|
|
controller->Axis(0, axis, Input::GetAxis(0, 0x8000, event->gaxis.value));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
controller->Axis(0, axis, Input::GetAxis(-0x8000, 0x8000, event->gaxis.value));
|
|
|
|
}
|
2024-08-13 11:54:08 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-11 12:56:27 +03:00
|
|
|
} // namespace Frontend
|