diff --git a/core/input/keyboard_device.h b/core/input/keyboard_device.h index 1ee1935dc..dc2f10fab 100644 --- a/core/input/keyboard_device.h +++ b/core/input/keyboard_device.h @@ -109,10 +109,10 @@ protected: if (port >= 0 && port < (int)std::size(kb_shift)) kb_shift[port] = _modifier_keys; - if (keycode != 0 && keycode < 0xE0) + if (keycode != 0) { - gui_keyboard_key(keycode, pressed, _modifier_keys); - if (port >= 0 && port < (int)std::size(kb_key)) + gui_keyboard_key(keycode, pressed); + if (keycode < 0xE0 && port >= 0 && port < (int)std::size(kb_key)) { if (pressed) { diff --git a/core/rend/gles/imgui_impl_opengl3.cpp b/core/rend/gles/imgui_impl_opengl3.cpp index 5a87a7271..b5fb092e5 100644 --- a/core/rend/gles/imgui_impl_opengl3.cpp +++ b/core/rend/gles/imgui_impl_opengl3.cpp @@ -145,7 +145,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill glcache.Enable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); - glcache.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glcache.Disable(GL_CULL_FACE); glcache.Disable(GL_DEPTH_TEST); glcache.Enable(GL_SCISSOR_TEST); @@ -187,6 +187,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) } #endif glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); glEnableVertexAttribArray(g_AttribLocationPosition); glEnableVertexAttribArray(g_AttribLocationUV); glEnableVertexAttribArray(g_AttribLocationColor); @@ -199,12 +200,8 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; - const ImDrawIdx* idx_buffer_offset = 0; - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW); for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) @@ -228,12 +225,14 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) // Bind texture, Draw glcache.BindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); + glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))); } } - idx_buffer_offset += pcmd->ElemCount; } } + // Make sure the state cache is coherent + glcache.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); #ifndef GLES2 if (vao_handle != 0) glDeleteVertexArrays(1, &vao_handle); diff --git a/core/rend/gui.cpp b/core/rend/gui.cpp index 2f539d7ba..34675daa0 100644 --- a/core/rend/gui.cpp +++ b/core/rend/gui.cpp @@ -152,8 +152,14 @@ static ImGuiKey keycodeToImGuiKey(u8 keycode) case 0x1B: return ImGuiKey_X; case 0x1C: return ImGuiKey_Y; case 0x1D: return ImGuiKey_Z; + case 0xE0: + case 0xE4: + return ImGuiMod_Ctrl; + case 0xE1: + case 0xE5: + return ImGuiMod_Shift; + default: return ImGuiKey_None; } - return ImGuiKey_None; } void gui_initFonts() @@ -295,19 +301,19 @@ void gui_keyboard_inputUTF8(const std::string& s) io.AddInputCharactersUTF8(s.c_str()); } -void gui_keyboard_key(u8 keyCode, bool pressed, u8 modifiers) +void gui_keyboard_key(u8 keyCode, bool pressed) { if (!inited) return; - ImGuiIO& io = ImGui::GetIO(); ImGuiKey key = keycodeToImGuiKey(keyCode); + if (key == ImGuiKey_None) + return; if (!pressed && ImGui::IsKeyDown(key)) { keysUpNextFrame[keyCode] = true; return; } - io.KeyCtrl = (modifiers & (0x01 | 0x10)) != 0; - io.KeyShift = (modifiers & (0x02 | 0x20)) != 0; + ImGuiIO& io = ImGui::GetIO(); io.AddKeyEvent(key, pressed); } @@ -351,9 +357,9 @@ static void gui_newFrame() ImGuiIO& io = ImGui::GetIO(); if (mouseX < 0 || mouseX >= settings.display.width || mouseY < 0 || mouseY >= settings.display.height) - io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); else - io.MousePos = ImVec2(mouseX, mouseY); + io.AddMousePosEvent(mouseX, mouseY); static bool delayTouch; #if defined(__ANDROID__) || defined(TARGET_IPHONE) // Delay touch by one frame to allow widgets to be hovered before click @@ -365,14 +371,14 @@ static void gui_newFrame() #endif if (io.WantCaptureMouse) { - io.MouseWheel = -mouseWheel / 16; + io.AddMouseWheelEvent(0, -mouseWheel / 16); mouseWheel = 0; } if (!delayTouch) - io.MouseDown[ImGuiMouseButton_Left] = (mouseButtons & (1 << 0)) != 0; - io.MouseDown[ImGuiMouseButton_Right] = (mouseButtons & (1 << 1)) != 0; - io.MouseDown[ImGuiMouseButton_Middle] = (mouseButtons & (1 << 2)) != 0; - io.MouseDown[3] = (mouseButtons & (1 << 3)) != 0; + io.AddMouseButtonEvent(ImGuiMouseButton_Left, (mouseButtons & (1 << 0)) != 0); + io.AddMouseButtonEvent(ImGuiMouseButton_Right, (mouseButtons & (1 << 1)) != 0); + io.AddMouseButtonEvent(ImGuiMouseButton_Middle, (mouseButtons & (1 << 2)) != 0); + io.AddMouseButtonEvent(3, (mouseButtons & (1 << 3)) != 0); io.AddKeyEvent(ImGuiKey_GamepadFaceLeft, ((kcode[0] & DC_BTN_X) == 0)); io.AddKeyEvent(ImGuiKey_GamepadFaceRight, ((kcode[0] & DC_BTN_B) == 0)); @@ -2496,7 +2502,7 @@ static void gui_display_content() scanner.fetch_game_list(); // Only if Filter and Settings aren't focused... ImGui::SetNextWindowFocus(); - ImGui::BeginChild(ImGui::GetID("library"), ImVec2(0, 0), true, ImGuiWindowFlags_DragScrolling); + ImGui::BeginChild(ImGui::GetID("library"), ImVec2(0, 0), true, ImGuiWindowFlags_DragScrolling | ImGuiWindowFlags_NavFlattened); { const int itemsPerLine = std::max(ImGui::GetContentRegionMax().x / (150 * settings.display.uiScale + ImGui::GetStyle().ItemSpacing.x), 1); const float responsiveBoxSize = ImGui::GetContentRegionMax().x / itemsPerLine - ImGui::GetStyle().FramePadding.x * 2; diff --git a/core/rend/gui.h b/core/rend/gui.h index 2da21f567..6fbb503e6 100644 --- a/core/rend/gui.h +++ b/core/rend/gui.h @@ -35,7 +35,7 @@ void gui_refresh_files(); void gui_cheats(); void gui_keyboard_input(u16 wc); void gui_keyboard_inputUTF8(const std::string& s); -void gui_keyboard_key(u8 keyCode, bool pressed, u8 modifiers); +void gui_keyboard_key(u8 keyCode, bool pressed); bool gui_keyboard_captured(); bool gui_mouse_captured(); void gui_set_mouse_position(int x, int y); diff --git a/core/rend/gui_util.cpp b/core/rend/gui_util.cpp index ba88f8eb8..3b26cc794 100644 --- a/core/rend/gui_util.cpp +++ b/core/rend/gui_util.cpp @@ -359,8 +359,16 @@ void scrollWhenDraggingOnVoid(ImGuiMouseButton mouse_button) bool held = false; ImGuiButtonFlags button_flags = (mouse_button == ImGuiMouseButton_Left) ? ImGuiButtonFlags_MouseButtonLeft : (mouse_button == ImGuiMouseButton_Right) ? ImGuiButtonFlags_MouseButtonRight : ImGuiButtonFlags_MouseButtonMiddle; - if (g.HoveredId == 0) // If nothing hovered so far in the frame (not same as IsAnyItemHovered()!) - ImGui::ButtonBehavior(window->Rect(), window->GetID("##scrolldraggingoverlay"), &hovered, &held, button_flags); + // If nothing hovered so far in the frame (not same as IsAnyItemHovered()!) or item is disabled + if (g.HoveredId == 0 || g.HoveredIdDisabled) + { + bool hoveredAllowOverlap = g.HoveredIdAllowOverlap; + g.HoveredIdAllowOverlap = true; + ImGuiID overlayId = window->GetID("##scrolldraggingoverlay"); + ImGui::ButtonBehavior(window->Rect(), overlayId, &hovered, &held, button_flags); + ImGui::KeepAliveID(overlayId); + g.HoveredIdAllowOverlap = hoveredAllowOverlap; + } const ImVec2& delta = ImGui::GetIO().MouseDelta; if (held && delta != ImVec2()) { @@ -654,14 +662,14 @@ bool OptionCheckbox(const char *name, config::Option& optio template bool OptionCheckbox(const char *name, config::Option& option, const char *help); template bool OptionCheckbox(const char *name, config::Option& option, const char *help); -bool OptionSlider(const char *name, config::Option& option, int min, int max, const char *help) +bool OptionSlider(const char *name, config::Option& option, int min, int max, const char *help, const char *format) { bool valueChanged; { DisabledScope scope(option.isReadOnly()); int v = option; - valueChanged = ImGui::SliderInt(name, &v, min, max); + valueChanged = ImGui::SliderInt(name, &v, min, max, format); if (valueChanged) option.set(v); } diff --git a/core/rend/gui_util.h b/core/rend/gui_util.h index c86327383..7a99ad80c 100644 --- a/core/rend/gui_util.h +++ b/core/rend/gui_util.h @@ -44,7 +44,7 @@ IMGUI_API const ImWchar* GetGlyphRangesChineseTraditionalOfficial();// Defaul void ShowHelpMarker(const char* desc); template bool OptionCheckbox(const char *name, config::Option& option, const char *help = nullptr); -bool OptionSlider(const char *name, config::Option& option, int min, int max, const char *help = nullptr); +bool OptionSlider(const char *name, config::Option& option, int min, int max, const char *help = nullptr, const char *format = nullptr); template bool OptionRadioButton(const char *name, config::Option& option, T value, const char *help = nullptr); void OptionComboBox(const char *name, config::Option& option, const char *values[], int count, diff --git a/shell/apple/emulator-ios/emulator/FlycastViewController.mm b/shell/apple/emulator-ios/emulator/FlycastViewController.mm index 5839df831..07cd93a42 100644 --- a/shell/apple/emulator-ios/emulator/FlycastViewController.mm +++ b/shell/apple/emulator-ios/emulator/FlycastViewController.mm @@ -652,8 +652,8 @@ bool checkTryDebug() changeText = nil; if (textField.markedTextRange == nil) { // it wants to replace text with nothing, ie a delete - gui_keyboard_key(0x2A, true, 0); // backspace - gui_keyboard_key(0x2A, false, 0); + gui_keyboard_key(0x2A, true); // backspace + gui_keyboard_key(0x2A, false); } if (textField.text.length < 16) { textField.text = obligateForBackspace; @@ -667,8 +667,8 @@ bool checkTryDebug() // Terminates the editing session - (BOOL)textFieldShouldReturn:(UITextField*)_textField { - gui_keyboard_key(0x28, true, 0); // Return - gui_keyboard_key(0x28, false, 0); + gui_keyboard_key(0x28, true); // Return + gui_keyboard_key(0x28, false); return YES; }