Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GLFW: hover doesn't work correctly with overlapping viewports #7316

Open
paulocoutinhox opened this issue Feb 14, 2024 · 13 comments
Open

GLFW: hover doesn't work correctly with overlapping viewports #7316

paulocoutinhox opened this issue Feb 14, 2024 · 13 comments

Comments

@paulocoutinhox
Copy link

paulocoutinhox commented Feb 14, 2024

Version/Branch of Dear ImGui:

Branch: docking

Back-ends:

imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp

Compiler, OS:

macOS + clang

Full config/build information:

No response

Details:

Button hover don't work using viewports when one window is over other window:

When we create a window with a button (bt1) and a separate window with other controls, if the first window is over the second window, the hover over the button bt1 in window 1 don't work.

The hover and the click don't work.

See the video to see.

Screenshots/Video:

Screen.Recording.2024-02-14.at.04.57.21.mov

Minimal, Complete and Verifiable Example code:

#include "imgui.h"
#include "backends/imgui_impl_glfw.h"
#include "backends/imgui_impl_opengl3.h"
#include <GLFW/glfw3.h>
#include <iostream>
#include <vector>
#include <chrono>
#include <filesystem>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#include <opencv2/opencv.hpp>

namespace fs = std::filesystem;

struct ImageTexture {
    GLuint textureID;
    int width, height;
};

// Function to load texture from image
ImageTexture LoadTextureFromImage(const char* imagePath) {
    ImageTexture imgTexture = {0, 0, 0};
    int width, height, channels;
    unsigned char* data = stbi_load(imagePath, &width, &height, &channels, 0);
    if (data == nullptr) {
        std::cerr << "Error loading image: " << imagePath << std::endl;
        return imgTexture;
    }

    glGenTextures(1, &imgTexture.textureID);
    glBindTexture(GL_TEXTURE_2D, imgTexture.textureID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, channels == 4 ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, data);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    stbi_image_free(data);

    imgTexture.width = width;
    imgTexture.height = height;

    return imgTexture;
}

void TextAutoSizedAndCentered(const std::string& text, ImFont* font, bool useDisplaySize) {
    ImGuiIO& io = ImGui::GetIO();

    // Define padding
    float paddingX = 20.0f; // Horizontal padding
    float paddingY = 20.0f; // Vertical padding

    ImVec2 baseSize; // Initialize base size
    ImVec2 basePos; // Initialize base position

    if (useDisplaySize) {
        if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
            // When viewports are enabled, use the main viewport's size and position
            ImGuiViewport* mainViewport = ImGui::GetMainViewport();
            baseSize = mainViewport->Size;
            basePos = mainViewport->Pos;
        } else {
            // If viewports are not enabled, use the display size and position (0, 0)
            baseSize = io.DisplaySize;
            basePos = ImVec2(0, 0);
        }
    } else {
        // When not using display size, use the current window's size and position
        baseSize = ImGui::GetWindowSize();
        basePos = ImGui::GetWindowPos();
    }

    // Ensure there's a minimum size for drawing text
    baseSize.x = std::max(baseSize.x, 1.0f); // Minimum width
    baseSize.y = std::max(baseSize.y, 1.0f); // Minimum height

    // Calculates available area considering padding
    float availableWidth = baseSize.x - 2 * paddingX;
    float availableHeight = baseSize.y - 2 * paddingY;

    // Finds the required width for the text and the number of lines
    float maxLineWidth = 0.0f;
    int lineCount = 0;
    std::istringstream stream(text);
    std::string line;
    while (std::getline(stream, line)) {
        ImVec2 lineSize = font->CalcTextSizeA(font->FontSize, FLT_MAX, 0.0f, line.c_str());
        if (lineSize.x > maxLineWidth) {
            maxLineWidth = lineSize.x;
        }
        lineCount++;
    }

    // Adjusts the font size if the longest line is wider than the available space
    float scaleFactor = (maxLineWidth > availableWidth) ? (availableWidth / maxLineWidth) : 1.0f;
    float fontSize = font->FontSize * scaleFactor;

    // Ensures the text block fits vertically within the available height
    float totalTextHeight = fontSize * lineCount;
    if (totalTextHeight > availableHeight) {
        fontSize *= availableHeight / totalTextHeight;
    }

    // Prepares to draw the text
    ImDrawList* drawList = ImGui::GetForegroundDrawList();

    // Text and outline colors
    ImU32 textColor = IM_COL32(255, 255, 255, 255);
    ImU32 outlineColor = IM_COL32(0, 0, 0, 255);

    // Resets the stream to draw the text
    stream.clear();
    stream.seekg(0, std::ios::beg);

    // Calculates the starting y position to center the text block vertically
    float textPosY = basePos.y + paddingY + (availableHeight - fontSize * lineCount) / 2.0f;

    // Draws the text line by line
    while (std::getline(stream, line)) {
        ImVec2 lineSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0.0f, line.c_str());

        // Centers each line of text
        float textPosX = basePos.x + paddingX + (availableWidth - lineSize.x) / 2.0f;

        // Draws the outline
        float outlineThickness = 1.0f;
        for (int x = -outlineThickness; x <= outlineThickness; ++x) {
            for (int y = -outlineThickness; y <= outlineThickness; ++y) {
                if (x != 0 || y != 0) {
                    drawList->AddText(font, fontSize, ImVec2(textPosX + x, textPosY + y), outlineColor, line.c_str());
                }
            }
        }

        // Draws the line of text
        drawList->AddText(font, fontSize, ImVec2(textPosX, textPosY), textColor, line.c_str());

        // Moves to the next line
        textPosY += fontSize;
    }
}

void windowCloseCallback(GLFWwindow* window) {
    glfwDestroyWindow(window);
}

void windowKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
    auto altF4 = (key == GLFW_KEY_W && mods == GLFW_MOD_SUPER);
    auto commandQ = (key == GLFW_KEY_F4 && mods == GLFW_MOD_ALT && action == GLFW_PRESS);

    if (altF4 || commandQ) {
        glfwDestroyWindow(window);
    }
}

int main() {
    if (!glfwInit()) {
        std::cerr << "Error initializing GLFW." << std::endl;
        return -1;
    }

    // GLFW window creation
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

    // Main window
    GLFWwindow* window = glfwCreateWindow(1024, 768, "Image Grid with ImGui", nullptr, nullptr);
    if (window == nullptr) {
        std::cerr << "Error creating GLFW window." << std::endl;
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);
    glfwSwapInterval(1); // Enable vsync

    // Video window
    GLFWwindow* videoWindow = nullptr;

    /*
    GLFWwindow* videoWindow = glfwCreateWindow(1024, 768, "Video Player", nullptr, nullptr);
    if (videoWindow == nullptr) {
        std::cerr << "Error creating GLFW video window." << std::endl;
        glfwTerminate();
        return -1;
    }

    glfwSetWindowCloseCallback(videoWindow, windowCloseCallback);
    glfwSetKeyCallback(videoWindow, windowKeyCallback);
    */

    // ImGui initialization
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;
    ImGui::StyleColorsDark();
    io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
    io.IniFilename = nullptr;

    // Load fonts
    io.Fonts->AddFontDefault();
    ImFont* myFont = io.Fonts->AddFontFromFileTTF("fonts/Poppins-Bold.ttf", 500);

    if (!myFont) {
        std::cerr << "Error while load font." << std::endl;
    }

    // Load implementations for ImGui
    ImGui_ImplGlfw_InitForOpenGL(window, true);
    ImGui_ImplOpenGL3_Init();

    // Load images from directory
    std::vector<ImageTexture> textures;
    std::string pathToImages = "images";

    for (const auto& entry : fs::directory_iterator(pathToImages)) {
        if (entry.is_regular_file()) {
            textures.push_back(LoadTextureFromImage(entry.path().string().c_str()));
        }
    }

    // Open video file
    cv::VideoCapture video("videos/video1.mp4");
    if (!video.isOpened()) {
        std::cerr << "Error opening video." << std::endl;
        return -1;
    }

    cv::Mat frame;
    GLuint videoTexture = 0;

    int videoWidth = 0;
    int videoHeight = 0;
    int videoStartFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_NoFocusOnAppearing;

    int monitorsCount;

    double fps = video.get(cv::CAP_PROP_FPS);
    auto frameDuration = std::chrono::milliseconds(static_cast<int>(1000 / fps));
    std::chrono::steady_clock::time_point lastFrameTime = std::chrono::steady_clock::now();

    bool starting = true;

    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();

        // Get video frame
        auto currentTime = std::chrono::steady_clock::now();
        if (std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - lastFrameTime) >= frameDuration) {
            if (video.read(frame)) {
                // Convert BGR to RGBA
                cv::Mat frameRGBA;
                cv::cvtColor(frame, frameRGBA, cv::COLOR_BGR2RGBA);

                // Update video texture
                if (videoTexture == 0) {
                    glGenTextures(1, &videoTexture);
                    glBindTexture(GL_TEXTURE_2D, videoTexture);
                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                }

                glBindTexture(GL_TEXTURE_2D, videoTexture);
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, frameRGBA.cols, frameRGBA.rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, frameRGBA.data);

                if (videoWidth == 0 || videoHeight == 0) {
                    videoWidth = frame.cols;
                    videoHeight = frame.rows;
                }

                lastFrameTime = currentTime;
            } else {
                // Restart video playback when reaching the end
                video.set(cv::CAP_PROP_POS_FRAMES, 0);
            }
        }

        // Main window
        glfwMakeContextCurrent(window);
        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        // Draw center text
        //TextAutoSizedAndCentered("DEUS ENVIOU\nSEU FILHO AMADO\nPRA PERDOAR\nPRA ME SALVAR", myFont, true);

        // Render tabs
        ImGuiViewport* viewport = ImGui::GetMainViewport();

        ImGui::SetNextWindowPos(viewport->Pos);
        ImGui::SetNextWindowSize(viewport->Size);
        ImGui::SetNextWindowViewport(viewport->ID);

        ImGui::Begin("Control Panel", nullptr, ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus);

            if (starting) {
                ImVec2 winPos = ImVec2(ImGui::GetCursorPos().x + 500, ImGui::GetCursorPos().y + 50);

                ImGui::SetWindowPos(winPos);
                ImGui::SetWindowSize(ImVec2(400, 200));
            }

            if (ImGui::BeginTabBar("TabBar")) {
                if (ImGui::BeginTabItem("Configurações")) {
                    // Pasta do projeto
                    ImGui::Text("Pasta do projeto:");
                    static char pathBuf[256];
                    ImGui::InputText("Selecionar a pasta onde está o seu projeto", pathBuf, IM_ARRAYSIZE(pathBuf));
                    ImGui::SameLine();
                    if (ImGui::Button("Selecionar pasta")) {
                        // Implemente a lógica para abrir o diálogo de seleção de pasta
                    }

                    // Separador
                    ImGui::Separator();

                    // Projeto
                    ImGui::Text("Projeto");
                    if (ImGui::Button("Fechar projeto")) {
                        // Implemente a lógica para fechar o projeto
                    }
                    ImGui::SameLine();
                    if (ImGui::Button("Tela preta")) {
                        // Implemente a lógica para definir a tela como preta
                    }
                    ImGui::SameLine();
                    if (ImGui::Button("Tela padrão")) {
                        // Implemente a lógica para definir a tela como padrão
                    }

                    // Separador
                    ImGui::Separator();

                    // Texto
                    ImGui::Text("Texto");
                    static ImVec4 textColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
                    if (ImGui::ColorEdit3("Cor do texto", (float*)&textColor)) {
                        // Implemente a lógica para mudar a cor do texto
                    }
                    static ImVec4 outlineColor = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
                    ImGui::SameLine();
                    if (ImGui::ColorEdit3("Cor do contorno", (float*)&outlineColor)) {
                        // Implemente a lógica para mudar a cor do contorno
                    }

                    static int fontSize = 40;
                    ImGui::SliderInt("Tamanho da fonte", &fontSize, 10, 100);
                    static bool autoAdjust = true;
                    ImGui::Checkbox("Auto ajuste do tamanho?", &autoAdjust);

                    // Separador
                    ImGui::Separator();

                    // Video
                    ImGui::Text("Video");
                    static bool fullscreen = true;
                    ImGui::Checkbox("Ocupar toda a tela?", &fullscreen);

                    if (ImGui::Button("Aplicar")) {
                        // Implemente a lógica para aplicar as configurações de vídeo
                    }

                    ImGui::EndTabItem();
                }

                if (ImGui::BeginTabItem("Tab 2")) {
                    ImGui::Text("Tab 2");
                    ImGui::EndTabItem();
                }

                ImGui::EndTabBar();
            }

        ImGui::End();

        // Render image grid
        ImGui::Begin("Images");

        if (starting) {
            ImVec2 winPos = ImVec2(ImGui::GetCursorPos().x + 50, ImGui::GetCursorPos().y + 50);

            ImGui::SetWindowPos(winPos);
            ImGui::SetWindowSize(ImVec2(400, 200));
        }

        float windowWidth = ImGui::GetContentRegionAvail().x;
        int imagesPerRow = std::max(1, static_cast<int>(windowWidth / 100.0f));
        float imageSize = windowWidth / imagesPerRow;

        for (int i = 0; i < textures.size(); ++i) {
            float aspectRatio = static_cast<float>(textures[i].width) / textures[i].height;
            ImGui::Image((void*)(intptr_t)textures[i].textureID, ImVec2(imageSize, imageSize / aspectRatio));
            if ((i + 1) % imagesPerRow != 0) ImGui::SameLine();
        }

        ImGui::End();

        // Render video
        if (videoWindow) {
            glfwMakeContextCurrent(videoWindow);
            glfwPollEvents();
        }

        int videoFlags = videoStartFlags;
        ImVec2 videoWinPos;
        ImVec2 videoWinSize;
        GLFWmonitor** monitors = glfwGetMonitors(&monitorsCount);

        if (starting) {
            if (monitorsCount > 1 && io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
                int monitorPosX, monitorPosY, monitorWidth, monitorHeight;
                glfwGetMonitorWorkarea(monitors[1], &monitorPosX, &monitorPosY, &monitorWidth, &monitorHeight);

                videoWinPos = ImVec2(monitorPosX, monitorPosY);
                videoWinSize = ImVec2(monitorWidth, monitorHeight);

                videoFlags = videoFlags | ImGuiWindowFlags_NoDecoration;
            } else {
                videoWinPos = ImVec2(ImGui::GetCursorPos().x + 50, ImGui::GetCursorPos().y + 300);
                videoWinSize = ImVec2(400, 200);
            }
        } else {
            if (monitorsCount > 1 && io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
                int monitorPosX, monitorPosY, monitorWidth, monitorHeight;
                glfwGetMonitorWorkarea(monitors[1], &monitorPosX, &monitorPosY, &monitorWidth, &monitorHeight);

                videoWinPos = ImVec2(monitorPosX, monitorPosY);
                videoWinSize = ImVec2(monitorWidth, monitorHeight);

                videoFlags = videoFlags | ImGuiWindowFlags_NoDecoration;
            } else {
                videoWinPos = ImVec2(ImGui::GetCursorPos().x + 50, ImGui::GetCursorPos().y + 300);
                videoWinSize = ImVec2(400, 200);
            }
        }

        ImGui::Begin("Video Player", nullptr, videoFlags);
        ImGui::SetWindowPos(videoWinPos);
        ImGui::SetWindowSize(videoWinSize);

        TextAutoSizedAndCentered("DEUS ENVIOU\nSEU FILHO AMADO\nPRA PERDOAR\nPRA ME SALVAR", myFont, false);

        if (videoTexture != 0) {
            // Get total window dimensions from ImGui
            ImVec2 windowSize = ImGui::GetContentRegionAvail();

            // Calculate video aspect ratio
            float videoAspectRatio = (float)videoWidth / (float)videoHeight;

            // Calculate image size based on video and window aspect ratio
            ImVec2 imageSize;
            if (windowSize.x / windowSize.y > videoAspectRatio) {
                // Window is wider than video
                imageSize.x = windowSize.y * videoAspectRatio;
                imageSize.y = windowSize.y;
            } else {
                // Window is taller than video
                imageSize.x = windowSize.x;
                imageSize.y = windowSize.x / videoAspectRatio;
            }

            // Calculate position to center the image in the window
            ImVec2 imagePos = ImVec2(
                ImGui::GetCursorPos().x + (windowSize.x - imageSize.x) * 0.5f, // X position for centering
                ImGui::GetCursorPos().y + (windowSize.y - imageSize.y) * 0.5f  // Y position for centering
                );

            // Apply calculated position
            ImGui::SetCursorPos(imagePos);

            // Render video image with adjusted size and position
            ImGui::Image((void*)(intptr_t)videoTexture, imageSize);
        }

        ImGui::End();

        // Render ImGui
        ImGui::Render();
        int displayW, displayH;
        glfwGetFramebufferSize(window, &displayW, &displayH);
        glViewport(0, 0, displayW, displayH);
        glClearColor(0.45f, 0.55f, 0.60f, 1.00f);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

        if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
        {
            ImGui::UpdatePlatformWindows();
            ImGui::RenderPlatformWindowsDefault();
        }

        glfwSwapBuffers(window);

        starting = false;
    }

    // Cleanup
    if (videoTexture != 0) {
        glDeleteTextures(1, &videoTexture);
    }

    for (auto& texture : textures) {
        glDeleteTextures(1, &texture.textureID);
    }

    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();

    if (videoWindow) {
        glfwDestroyWindow(videoWindow);
    }

    glfwDestroyWindow(window);
    glfwTerminate();

    return 0;
}
@ocornut
Copy link
Owner

ocornut commented Feb 14, 2024

  • Does clicking back and forth in the "Images" windows then back into the main viewport fixes the issues?

  • Could you check in Demo->Configuration->BackendFlags if ImGuiBackendFlags_HasMouseHoveredViewport is enabled ?

  • What is your version of GLFW ? If it is under 3.4 and ImGuiBackendFlags_HasMouseHoveredViewport is not set, can you find a way to update to 3.4 ?

  • Can you confirm in "Demo->Tools->Metrics/Debugger->Internal State->Windowing" the state of "HoveredWindow" and `"MouseViewport: XXXXXXXX (UserHovered: XXXXXX, Last Hovered XXXXXX"). The easier being to record a video with this panel open and see how the value evolve when moving the mouse and then after clicking in both viewports back and forth.

(PS: No need to be posting 521 lines of code if the issue may be expressed in 6 lines (two Begin()/Button()/End() blocks) and pasted into an existing example app. It's easier to grasp and understand things when code is a minimal.)

@paulocoutinhox
Copy link
Author

Hi,

My version 3.3.9, when i set your backend flag, it works:

IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
ImGui::StyleColorsDark();
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport;

Thanks.

@paulocoutinhox
Copy link
Author

Sorry, with more tests i see that now it is inverse:

Screen.Recording.2024-02-14.at.08.07.08.mov

@ocornut
Copy link
Owner

ocornut commented Feb 14, 2024

Never set the backend flag manually, it needs to be set by the backend which can provide support for it.
I asked you multiple questions, precise answers would be good (I can't make sense of the video if I don't know what's the flag according to backend or if you erroneously modified this flag).

@paulocoutinhox
Copy link
Author

  • Does clicking back and forth in the "Images" windows then back into the main viewport fixes the issues?
  • Could you check in Demo->Configuration->BackendFlags if ImGuiBackendFlags_HasMouseHoveredViewport is enabled ?
  • What is your version of GLFW ? If it is under 3.4 and ImGuiBackendFlags_HasMouseHoveredViewport is not set, can you find a way to update to 3.4 ?
  • Can you confirm in "Demo->Tools->Metrics/Debugger->Internal State->Windowing" the state of "HoveredWindow" and `"MouseViewport: XXXXXXXX (UserHovered: XXXXXX, Last Hovered XXXXXX"). The easier being to record a video with this panel open and see how the value evolve when moving the mouse and then after clicking in both viewports back and forth.

(PS: No need to be posting 521 lines of code if the issue may be expressed in 6 lines (two Begin()/Button()/End() blocks) and pasted into an existing example app. It's easier to grasp and understand things when code is a minimal.)

Q1: Yes, if i do it back to work.

q1.mov

Q2: It was not set.

image

Q3: 3.3.9

brew install glfw
Running `brew update --auto-update`...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core and homebrew/cask).
==> New Casks
gitbutler

You have 9 outdated formulae installed.

==> Downloading https://ghcr.io/v2/homebrew/core/glfw/manifests/3.3.9

From: https://formulae.brew.sh/formula/glfw

After update to 3.4.0 branch the problem of hover is solved but it is inverseted now, the click on window over the button make the button click happen, i made a new video:

q3.mov

Q4: Video showing hover debug (it has 3.3.9 glfw):

q4.mov

@paulocoutinhox
Copy link
Author

More:

I installed version 3.4.0 and it come with flags ticked:

image

Also, the problem on button appear be solve using 3.4.0:

q4-2.mov

But in my code with 3.4.0 too, the image window let click go behind:

q4-3.mov

@ocornut
Copy link
Owner

ocornut commented Feb 14, 2024

Thank you for your careful answers. They are remaining issues on Mac and with GLFW.

I'm going to ask for a little more, I think we can make progress on tthis.

Q1: When the backend cannot provide ImGuiBackendFlags_HasMouseHoveredViewport feature, we use an heuristic for determining window order, which notable has this issue on startup (#7014).
Request: Could you confirm that commenting out the two lines mentioned in first of #7014 "fixes" the issue with GLFW 3.3.9 ?


Q2/Q3: With GLFW 3.3.9 we currently cannot support HasMouseHoveredViewport on Mac, but it should work with GLFW 3.4.
Howevr, in 1.87 we relaxed specs for supporting ImGuiBackendFlags_HasMouseHoveredViewport, and I think we missed an opportunity to make GLFW backend support the simplified mode.

Request: Can you try with GLFW 3.3.9 in imgui_impl_glfw,cpp to change:

#if GLFW_HAS_MOUSE_PASSTHROUGH || (GLFW_HAS_WINDOW_HOVERED && defined(_WIN32))
    io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can call io.AddMouseViewportEvent() with correct data (optional)
#endif

to

#if GLFW_HAS_MOUSE_PASSTHROUGH || GLFW_HAS_WINDOW_HOVERED
    io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can call io.AddMouseViewportEvent() with correct data (optional)
#endif

And

#if GLFW_HAS_MOUSE_PASSTHROUGH || (GLFW_HAS_WINDOW_HOVERED && defined(_WIN32))
        const bool window_no_input = (viewport->Flags & ImGuiViewportFlags_NoInputs) != 0;

to

#if GLFW_HAS_MOUSE_PASSTHROUGH || GLFW_HAS_WINDOW_HOVERED
        const bool window_no_input = (viewport->Flags & ImGuiViewportFlags_NoInputs) != 0;

With this change ImGuiBackendFlags_HasMouseHoveredViewport will become enabled but I wonder if the hovering will be correct with 3.3.9 on Mac with this change (I cannot test on a Mac right now).

(note that the requested changed from Q1 and Q2/Q3 are for two different code path, one is for fixing the logic without ImGuiBackendFlags_HasMouseHoveredViewport, the other is to making it possible to have ImGuiBackendFlags_HasMouseHoveredViewport with GLFW 3.3.9 instead of GLFW 3.4)

--

There is a remaining issue which you show in in q4.mov and q4-3.mov but I don't understand why it doesn't happen in q4-2.mov. I don't understand why this happen. Could you make that same video with GLFW 3.4 with the Metrics section open?

@paulocoutinhox
Copy link
Author

Q1 - I change to 3.3.9 and the problem of hover still happen commenting that lines or not.

q1-1.mov

@paulocoutinhox
Copy link
Author

Q2: With the fixes, it works with 3.3.9 and all the problems appear be solved.

q2-1.mov

@ocornut ocornut changed the title Button hover don't work using viewports when one window is over other window Button hover don't work correctly with overlapping viewports Feb 14, 2024
@paulocoutinhox
Copy link
Author

You need that i make a PR for this?

@ocornut
Copy link
Owner

ocornut commented Feb 15, 2024

No, I will investigate this further soon. There are two issues to fix but I cannot repro the 3.4.0 one with correct pass through, maybe its a mac only issue.

@ocornut ocornut changed the title Button hover don't work correctly with overlapping viewports GLFW: hover doesn't work correctly with overlapping viewports Feb 15, 2024
ocornut added a commit that referenced this issue Feb 15, 2024
@paulocoutinhox
Copy link
Author

If wanna help, im here.

@ocornut
Copy link
Owner

ocornut commented Feb 15, 2024

I'm getting access to Mac as I think they are variety of issues which are tricky to discuss. I pushed a first fix now for GLFW 3.3.x version, please check it out. But there's an additional issue with initial boot-time state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants