mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
overlay: mouse-as-touch needs to check if subscreen window is active (#842)
## Link to GitHub Issue or related Pull Request, if one exists Fixes #840 ## Description of change Currently, for subscreen games, mouse events are still delivered even when the subscreen overlay window is not visible. Change this so that the subscreen overlay must be active and under the mouse cursor for the mouse-to-touch transformation to occur. Applies to both native and wintouchemu. ## Testing Needs to test everything again.. iidx: - [ ] full screen with overlay - [ ] single window with overlay - [ ] two window Test: mouse, poke, api, real touch screen sdvx: - [ ] full screen with overlay - [ ] windowed popn - [x] full screen with overlay - [x] window with overlay - [x] dedicated window gitadora - [x] single window with overlay - [x] dedicated sub window nostalgia - [x] fullscreen - [x] windowed test: poke wintouchemu - [ ] Do all of the above again with wintouchemu
This commit is contained in:
@@ -495,6 +495,14 @@ namespace wintouchemu {
|
|||||||
if (hWnd != nullptr && USE_MOUSE) {
|
if (hWnd != nullptr && USE_MOUSE) {
|
||||||
bool button_pressed = get_async_primary_mouse();
|
bool button_pressed = get_async_primary_mouse();
|
||||||
|
|
||||||
|
// while the subscreen overlay cannot accept the mouse, treat the button as
|
||||||
|
// released; this ends any active touch and prevents new mouse touch contacts
|
||||||
|
if (overlay::OVERLAY &&
|
||||||
|
overlay::OVERLAY->has_subscreen_touch_transform() &&
|
||||||
|
!overlay::OVERLAY->accepts_subscreen_mouse_input()) {
|
||||||
|
button_pressed = false;
|
||||||
|
}
|
||||||
|
|
||||||
// if there was a touch event in the last 500 ms, don't insert new button presses
|
// if there was a touch event in the last 500 ms, don't insert new button presses
|
||||||
if (button_pressed && (now - last_touch_event) < 500) {
|
if (button_pressed && (now - last_touch_event) < 500) {
|
||||||
button_pressed = false;
|
button_pressed = false;
|
||||||
|
|||||||
@@ -908,6 +908,17 @@ bool overlay::SpiceOverlay::get_active() {
|
|||||||
return this->active;
|
return this->active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool overlay::SpiceOverlay::is_subscreen_overlay_visible() {
|
||||||
|
return this->get_active() &&
|
||||||
|
this->window_sub != nullptr &&
|
||||||
|
this->window_sub->get_active();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool overlay::SpiceOverlay::accepts_subscreen_mouse_input() {
|
||||||
|
return this->is_subscreen_overlay_visible() &&
|
||||||
|
this->window_sub->is_mouse_hovered();
|
||||||
|
}
|
||||||
|
|
||||||
bool overlay::SpiceOverlay::has_focus() {
|
bool overlay::SpiceOverlay::has_focus() {
|
||||||
return this->get_active() && ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow);
|
return this->get_active() && ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ namespace overlay {
|
|||||||
void show_main_menu();
|
void show_main_menu();
|
||||||
void set_active(bool active);
|
void set_active(bool active);
|
||||||
bool get_active();
|
bool get_active();
|
||||||
|
bool accepts_subscreen_mouse_input();
|
||||||
bool has_focus();
|
bool has_focus();
|
||||||
bool hotkeys_triggered();
|
bool hotkeys_triggered();
|
||||||
|
|
||||||
@@ -143,20 +144,20 @@ namespace overlay {
|
|||||||
return this->hWnd;
|
return this->hWnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool can_transform_touch_input() {
|
bool has_subscreen_touch_transform() {
|
||||||
return (this->subscreen_mouse_handler != nullptr);
|
return (this->subscreen_touch_transform != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool transform_touch_point(LONG *x, LONG *y) {
|
bool transform_touch_point(LONG *x, LONG *y) {
|
||||||
if (this->get_active() && this->subscreen_mouse_handler) {
|
if (this->get_active() && this->subscreen_touch_transform) {
|
||||||
return this->subscreen_mouse_handler(x, y);
|
return this->subscreen_touch_transform(x, y);
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_subscreen_mouse_handler(const std::function<bool(LONG *, LONG *)> &f) {
|
void set_subscreen_touch_transform(const std::function<bool(LONG *, LONG *)> &f) {
|
||||||
this->subscreen_mouse_handler = f;
|
this->subscreen_touch_transform = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// renderer
|
// renderer
|
||||||
@@ -203,7 +204,7 @@ namespace overlay {
|
|||||||
|
|
||||||
std::vector<std::unique_ptr<Window>> windows;
|
std::vector<std::unique_ptr<Window>> windows;
|
||||||
|
|
||||||
std::function<bool(LONG *, LONG *)> subscreen_mouse_handler = nullptr;
|
std::function<bool(LONG *, LONG *)> subscreen_touch_transform = nullptr;
|
||||||
|
|
||||||
bool active = false;
|
bool active = false;
|
||||||
bool toggle_down = false;
|
bool toggle_down = false;
|
||||||
@@ -216,6 +217,7 @@ namespace overlay {
|
|||||||
// so render() never runs without a matching NewFrame.
|
// so render() never runs without a matching NewFrame.
|
||||||
bool has_pending_frame = false;
|
bool has_pending_frame = false;
|
||||||
|
|
||||||
|
bool is_subscreen_overlay_visible();
|
||||||
void init();
|
void init();
|
||||||
void add_font(const char* font, ImFontConfig* config, const ImWchar* glyphs);
|
void add_font(const char* font, ImFontConfig* config, const ImWchar* glyphs);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ void overlay::Window::build() {
|
|||||||
|
|
||||||
// check if active
|
// check if active
|
||||||
if (!this->active) {
|
if (!this->active) {
|
||||||
|
this->mouse_hovered = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,10 +107,18 @@ void overlay::Window::build() {
|
|||||||
// top spot. suppress that so only an explicit focus request (see below)
|
// top spot. suppress that so only an explicit focus request (see below)
|
||||||
// decides what comes to the front.
|
// decides what comes to the front.
|
||||||
const std::string window_id = this->title + "###" + to_string(this);
|
const std::string window_id = this->title + "###" + to_string(this);
|
||||||
if (ImGui::Begin(
|
const bool build_contents = ImGui::Begin(
|
||||||
window_id.c_str(),
|
window_id.c_str(),
|
||||||
&this->active,
|
&this->active,
|
||||||
this->flags | ImGuiWindowFlags_NoFocusOnAppearing)) {
|
this->flags | ImGuiWindowFlags_NoFocusOnAppearing);
|
||||||
|
|
||||||
|
// keep the window hovered while its invisible input button is held during a drag
|
||||||
|
this->mouse_hovered =
|
||||||
|
ImGui::IsWindowHovered(
|
||||||
|
ImGuiHoveredFlags_RootAndChildWindows |
|
||||||
|
ImGuiHoveredFlags_AllowWhenBlockedByActiveItem);
|
||||||
|
|
||||||
|
if (build_contents) {
|
||||||
|
|
||||||
// window attributes - init_pos / init_size are only honored once
|
// window attributes - init_pos / init_size are only honored once
|
||||||
// (ImGuiCond_Once), so compute them a single time instead of every frame
|
// (ImGuiCond_Once), so compute them a single time instead of every frame
|
||||||
@@ -154,6 +163,9 @@ void overlay::Window::build() {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
// raw content does not have an ImGui window to hover
|
||||||
|
this->mouse_hovered = false;
|
||||||
|
|
||||||
// add raw content
|
// add raw content
|
||||||
this->build_content();
|
this->build_content();
|
||||||
}
|
}
|
||||||
@@ -201,3 +213,7 @@ bool overlay::Window::get_active() {
|
|||||||
// now it depends on us
|
// now it depends on us
|
||||||
return this->active;
|
return this->active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool overlay::Window::is_mouse_hovered() {
|
||||||
|
return this->mouse_hovered;
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace overlay {
|
|||||||
void toggle_active();
|
void toggle_active();
|
||||||
void set_active(bool active);
|
void set_active(bool active);
|
||||||
bool get_active();
|
bool get_active();
|
||||||
|
bool is_mouse_hovered();
|
||||||
|
|
||||||
// raise this window to the top of the z-order on its next build. only
|
// raise this window to the top of the z-order on its next build. only
|
||||||
// call in response to an explicit user action (keyboard toggle, UI
|
// call in response to an explicit user action (keyboard toggle, UI
|
||||||
@@ -37,6 +38,7 @@ namespace overlay {
|
|||||||
// set when the window transitions to visible so build() raises it to the
|
// set when the window transitions to visible so build() raises it to the
|
||||||
// top of the z-order on the next frame
|
// top of the z-order on the next frame
|
||||||
bool request_focus = false;
|
bool request_focus = false;
|
||||||
|
bool mouse_hovered = false;
|
||||||
std::vector<Window*> children;
|
std::vector<Window*> children;
|
||||||
|
|
||||||
// settings
|
// settings
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace overlay::windows {
|
|||||||
this->texture_width = 0;
|
this->texture_width = 0;
|
||||||
this->texture_height = 0;
|
this->texture_height = 0;
|
||||||
|
|
||||||
overlay->set_subscreen_mouse_handler([this](LONG *x, LONG *y) -> bool {
|
overlay->set_subscreen_touch_transform([this](LONG *x, LONG *y) -> bool {
|
||||||
// convert to normalized form (relative window coordinates 0.f-1.f)
|
// convert to normalized form (relative window coordinates 0.f-1.f)
|
||||||
ImVec2 xy;
|
ImVec2 xy;
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace nativetouch::inject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
POINT transformed = *position;
|
POINT transformed = *position;
|
||||||
return transform::screen_to_game(window, &transformed);
|
return transform::mouse_to_game(window, &transformed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// release the active injected contact and its window capture
|
// release the active injected contact and its window capture
|
||||||
@@ -108,7 +108,7 @@ namespace nativetouch::inject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
POINT transformed = position;
|
POINT transformed = position;
|
||||||
if (!transform::screen_to_game(window, &transformed)) {
|
if (!transform::mouse_to_game(window, &transformed)) {
|
||||||
end_mouse_contact(window);
|
end_mouse_contact(window);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ namespace nativetouch::transform {
|
|||||||
static bool has_active_overlay_transform() {
|
static bool has_active_overlay_transform() {
|
||||||
return overlay::OVERLAY != nullptr &&
|
return overlay::OVERLAY != nullptr &&
|
||||||
overlay::OVERLAY->get_active() &&
|
overlay::OVERLAY->get_active() &&
|
||||||
overlay::OVERLAY->can_transform_touch_input();
|
overlay::OVERLAY->has_subscreen_touch_transform();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool transform_overlay_touch_position(POINT *position) {
|
static bool transform_overlay_touch_position(POINT *position) {
|
||||||
@@ -120,6 +120,25 @@ namespace nativetouch::transform {
|
|||||||
return transform_overlay_touch_position(position);
|
return transform_overlay_touch_position(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool mouse_to_game(HWND window, POINT *position) {
|
||||||
|
|
||||||
|
// exception: iidx tdj dedicated subscreen window is allowed
|
||||||
|
if (is_tdj_dedicated_subscreen(window)) {
|
||||||
|
return screen_to_game(window, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this game has a subscreen overlay that can transform touch input
|
||||||
|
// but the window is hidden or not under the cursor, reject mouse-as-touch
|
||||||
|
// (e.g., iidx/sdvx are rejected here, but nostalgia is allowed)
|
||||||
|
if (overlay::OVERLAY != nullptr &&
|
||||||
|
overlay::OVERLAY->has_subscreen_touch_transform() &&
|
||||||
|
!overlay::OVERLAY->accepts_subscreen_mouse_input()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return screen_to_game(window, position);
|
||||||
|
}
|
||||||
|
|
||||||
// route hardware screen coordinates through dedicated or overlay mapping and report the result
|
// route hardware screen coordinates through dedicated or overlay mapping and report the result
|
||||||
Result hardware_to_game(POINT *position) {
|
Result hardware_to_game(POINT *position) {
|
||||||
const auto dedicated_subscreen = is_tdj_dedicated_subscreen(TDJ_SUBSCREEN_WINDOW);
|
const auto dedicated_subscreen = is_tdj_dedicated_subscreen(TDJ_SUBSCREEN_WINDOW);
|
||||||
|
|||||||
@@ -12,5 +12,6 @@ namespace nativetouch::transform {
|
|||||||
bool is_tdj_dedicated_subscreen(HWND window);
|
bool is_tdj_dedicated_subscreen(HWND window);
|
||||||
bool game_to_screen(HWND window, POINT *position);
|
bool game_to_screen(HWND window, POINT *position);
|
||||||
bool screen_to_game(HWND window, POINT *position);
|
bool screen_to_game(HWND window, POINT *position);
|
||||||
|
bool mouse_to_game(HWND window, POINT *position);
|
||||||
Result hardware_to_game(POINT *position);
|
Result hardware_to_game(POINT *position);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -944,7 +944,7 @@ void touch_get_points(std::vector<TouchPoint> &touch_points, bool overlay) {
|
|||||||
if (!overlay &&
|
if (!overlay &&
|
||||||
overlay::OVERLAY &&
|
overlay::OVERLAY &&
|
||||||
overlay::OVERLAY->get_active() &&
|
overlay::OVERLAY->get_active() &&
|
||||||
!overlay::OVERLAY->can_transform_touch_input() &&
|
!overlay::OVERLAY->has_subscreen_touch_transform() &&
|
||||||
ImGui::GetIO().WantCaptureMouse) {
|
ImGui::GetIO().WantCaptureMouse) {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -971,7 +971,7 @@ void touch_get_events(std::vector<TouchEvent> &touch_events, bool overlay) {
|
|||||||
if (!overlay &&
|
if (!overlay &&
|
||||||
overlay::OVERLAY &&
|
overlay::OVERLAY &&
|
||||||
overlay::OVERLAY->get_active() &&
|
overlay::OVERLAY->get_active() &&
|
||||||
!overlay::OVERLAY->can_transform_touch_input() &&
|
!overlay::OVERLAY->has_subscreen_touch_transform() &&
|
||||||
ImGui::GetIO().WantCaptureMouse) {
|
ImGui::GetIO().WantCaptureMouse) {
|
||||||
|
|
||||||
TOUCH_EVENTS.reset();
|
TOUCH_EVENTS.reset();
|
||||||
|
|||||||
Reference in New Issue
Block a user