mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
7ccd938f9b
## 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
220 lines
6.5 KiB
C++
220 lines
6.5 KiB
C++
#include "window.h"
|
|
#include "cfg/configurator.h"
|
|
#include "util/logging.h"
|
|
#include "games/io.h"
|
|
#include "misc/eamuse.h"
|
|
#include "external/imgui/imgui_internal.h"
|
|
|
|
|
|
overlay::Window::Window(SpiceOverlay *overlay) : overlay(overlay) {
|
|
}
|
|
|
|
overlay::Window::~Window() {
|
|
|
|
// kill children
|
|
for (auto &child : this->children) {
|
|
delete child;
|
|
}
|
|
}
|
|
|
|
void overlay::Window::update() {
|
|
|
|
// check if toggle is enabled
|
|
if (this->toggle_button != ~0u) {
|
|
|
|
// get state
|
|
auto overlay_buttons = games::get_buttons_overlay(eamuse_get_game());
|
|
bool toggle_button_new = overlay_buttons
|
|
&& this->overlay->hotkeys_triggered()
|
|
&& GameAPI::Buttons::getState(RI_MGR, overlay_buttons->at(this->toggle_button));
|
|
if (toggle_button_new && !this->toggle_button_state) {
|
|
|
|
// if the overlay is hidden just reactivate it
|
|
if (!this->overlay->get_active()) {
|
|
|
|
// but don't let the main menu occlude it if it was previously visible
|
|
if (this->overlay->window_main_menu) {
|
|
this->overlay->window_main_menu->set_active(false);
|
|
}
|
|
|
|
this->active = true;
|
|
this->overlay->set_active(true);
|
|
} else {
|
|
this->toggle_active();
|
|
}
|
|
|
|
// raise to the top, but only because the user pressed the hotkey and
|
|
// the window is now visible
|
|
if (this->active) {
|
|
this->bring_to_front();
|
|
}
|
|
}
|
|
this->toggle_button_state = toggle_button_new;
|
|
}
|
|
|
|
// update children
|
|
auto it = this->children.begin();
|
|
while (it != this->children.end()) {
|
|
(*it)->update();
|
|
if ((*it)->active) {
|
|
it++;
|
|
} else {
|
|
delete (*it);
|
|
this->children.erase(it);
|
|
}
|
|
}
|
|
}
|
|
|
|
void overlay::Window::build() {
|
|
|
|
// check if active
|
|
if (!this->active) {
|
|
this->mouse_hovered = false;
|
|
return;
|
|
}
|
|
|
|
if (this->draws_window) {
|
|
|
|
// automatic max window size
|
|
if (!cfg::CONFIGURATOR_STANDALONE && (size_max.x < 0 || size_max.y < 0)) {
|
|
auto &display_size = ImGui::GetIO().DisplaySize;
|
|
ImVec2 size_max_auto(display_size.x - 100, display_size.y - 100);
|
|
ImGui::SetNextWindowSizeConstraints(size_min, size_max_auto, resize_callback);
|
|
} else {
|
|
ImGui::SetNextWindowSizeConstraints(size_min, size_max, resize_callback);
|
|
}
|
|
|
|
// background alpha
|
|
if (this->bg_alpha != 1.f) {
|
|
ImGui::SetNextWindowBgAlpha(this->bg_alpha);
|
|
}
|
|
|
|
if (this->remove_window_padding) {
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
|
}
|
|
|
|
const bool custom_window_padding =
|
|
!this->remove_window_padding && this->window_padding.x >= 0.f;
|
|
if (custom_window_padding) {
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, this->window_padding);
|
|
}
|
|
|
|
// create window
|
|
// NoFocusOnAppearing: when the overlay is re-shown every window reappears at
|
|
// once and ImGui would auto-focus whichever is submitted last, stealing the
|
|
// top spot. suppress that so only an explicit focus request (see below)
|
|
// decides what comes to the front.
|
|
const std::string window_id = this->title + "###" + to_string(this);
|
|
const bool build_contents = ImGui::Begin(
|
|
window_id.c_str(),
|
|
&this->active,
|
|
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
|
|
// (ImGuiCond_Once), so compute them a single time instead of every frame
|
|
if (!this->initial_window_calculated) {
|
|
this->initial_window_calculated = true;
|
|
this->calculate_initial_window();
|
|
}
|
|
ImGui::SetWindowPos(this->init_pos, ImGuiCond_Once);
|
|
ImGui::SetWindowSize(this->init_size, ImGuiCond_Once);
|
|
|
|
// add content
|
|
this->build_content();
|
|
|
|
// build children
|
|
for (auto &child : this->children) {
|
|
child->build();
|
|
}
|
|
}
|
|
// end window
|
|
ImGui::End();
|
|
|
|
// apply an explicit focus request now that the window exists. FocusWindow
|
|
// with UnlessBelowModal raises it to the front, but keeps it right below
|
|
// any blocking popup/modal instead of jumping in front of it (this also
|
|
// re-orders brand-new windows that ImGui places on top by default).
|
|
if (this->request_focus) {
|
|
this->request_focus = false;
|
|
if (ImGuiWindow *w = ImGui::FindWindowByName(window_id.c_str())) {
|
|
ImGui::FocusWindow(w, ImGuiFocusRequestFlags_UnlessBelowModal);
|
|
}
|
|
}
|
|
|
|
if (this->remove_window_padding) {
|
|
ImGui::PopStyleVar();
|
|
ImGui::PopStyleVar();
|
|
ImGui::PopStyleVar();
|
|
}
|
|
|
|
if (custom_window_padding) {
|
|
ImGui::PopStyleVar();
|
|
}
|
|
|
|
} else {
|
|
|
|
// raw content does not have an ImGui window to hover
|
|
this->mouse_hovered = false;
|
|
|
|
// add raw content
|
|
this->build_content();
|
|
}
|
|
}
|
|
|
|
void overlay::Window::toggle_active() {
|
|
|
|
// flip bool
|
|
this->active = !this->active;
|
|
|
|
// update children
|
|
for (auto &child : this->children) {
|
|
child->toggle_active();
|
|
}
|
|
}
|
|
|
|
void overlay::Window::set_active(bool active) {
|
|
|
|
// toggle if different
|
|
if (this->get_active() != active) {
|
|
|
|
// flip bool
|
|
this->active = !this->active;
|
|
|
|
// update children
|
|
for (auto &child : this->children) {
|
|
child->set_active(this->active);
|
|
}
|
|
}
|
|
}
|
|
|
|
void overlay::Window::bring_to_front() {
|
|
this->request_focus = true;
|
|
}
|
|
|
|
bool overlay::Window::get_active() {
|
|
|
|
// check for active children
|
|
for (auto &child : this->children) {
|
|
if (child->get_active()) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// now it depends on us
|
|
return this->active;
|
|
}
|
|
|
|
bool overlay::Window::is_mouse_hovered() {
|
|
return this->mouse_hovered;
|
|
}
|