在Debian上遇到GLFW的回调glfwSetDropCallback问题

时间:2017-03-14 23:36:21

标签: c++ opengl glfw

我目前正在创建一个轻量级程序来查看和操作类似于程序Blender或3DS max的3D对象。

我正在使用C ++,GLFW和OpenGL。虽然我打算让它成为跨平台,但我目前只在使用XFCE桌面环境运行Debian 9.0(延伸)的计算机上工作。

目前回调glfwSetDropCallback似乎永远不会被调用,无论我尝试什么。我设置了断点并断言但没有。我尝试过的所有其他回调都运行得很好。我从我的项目中包含了我的GLFW cpp。如果需要其他东西,请随意询问。

另外作为最后一点,我只是使用GLFW,因为其他一切似乎都太重了我的需求。同样使用X11直接看起来像很多工作没有太大的收获,特别是因为我需要针对每个目标操作系统的不同解决方案。最后,我只想将项目拖放到我的程序窗口,然后让我的代码对路径做一些事情。

#include "GLFWindow.h"

#include <cassert>
#include <iostream>

// Variables for callback.
static bool keys[1024];
static std::vector<std::string> dragAndDrop;
static Camera* _camera;
static GLdouble* _lastX;
static GLdouble* _lastY;

GLFWindow::GLFWindow()
:m_window(nullptr), m_lastX(0.0), m_lastY(0.0)
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, GLFW_VERSION_MAJOR);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, GLFW_VERSION_MINOR);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE); // For OSX
    glfwWindowHint(GLFW_FOCUSED, GL_TRUE);

    std::cout << glfwGetVersionString() << std::endl;

    m_window = glfwCreateWindow(1920, 1080, "Model Viewer", /*glfwGetPrimaryMonitor()*/nullptr, nullptr);
    if(m_window == nullptr)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        assert(m_window != nullptr);
    }

    glfwMakeContextCurrent(m_window);
    glfwSetWindowPos(m_window, 1920 - 1920/2, 1080 - 1080/2);

    glfwSetKeyCallback(m_window, 
    [](GLFWwindow* window, int key, int, int action, int)
    {
        if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
            glfwSetWindowShouldClose(window, GL_TRUE);

        if(action == GLFW_PRESS)
            keys[key] = true;
        else if(action == GLFW_RELEASE)
            keys[key] = false;
    });

    glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);

    glfwSetCursorEnterCallback(m_window,
    [](GLFWwindow* window, int entered)
    {
        if(entered)
        {
            double xPos, yPos;
            glfwGetCursorPos(window, &xPos, &yPos);

            *_lastX = xPos;
            *_lastY = yPos;
        }
    });

    glfwSetDropCallback(m_window,
    [](GLFWwindow*, int count, const char** paths)
    {
        std::cout << "Drag and Drop count - " << count << std::endl;
        for(unsigned int i = 0; i < count; ++i)
        {
            std::cout << std::string(paths[i]) << std::endl;
            dragAndDrop.push_back(std::string(paths[i]));
        }
    });
}

GLFWindow::~GLFWindow()
{
    glfwTerminate();
}

GLint GLFWindow::GetWidth()
{
    GLint width = 0;
    glfwGetFramebufferSize(m_window, &width, nullptr);
    return width;
}

GLint GLFWindow::GetHeight()
{
    GLint height = 0;
    glfwGetFramebufferSize(m_window, nullptr, &height);
    return height;
}

std::string GLFWindow::GetDragAndDrop()
{
    if(dragAndDrop.empty())
        return "END";

    std::string item = dragAndDrop[dragAndDrop.size()-1];
    dragAndDrop.pop_back();

    if(item.find(".obj") == std::string::npos && item.find(".fbx") == std::string::npos
    && item.find(".OBJ") == std::string::npos && item.find(".FBX") == std::string::npos)
        return "INVALID";

    return item;
}

bool GLFWindow::ShouldClose()
{
    return glfwWindowShouldClose(m_window);
}

void GLFWindow::AddCamera(Camera* camera)
{
    m_camera = camera;

    _camera = m_camera;
    _lastX = &m_lastX;
    _lastY = &m_lastY;

    glfwSetScrollCallback(m_window,
    [](GLFWwindow*, double, double yoffset)
    {
        _camera->ProcessMouseScroll(yoffset);
    });

    glfwSetCursorPosCallback(m_window,
    [](GLFWwindow*, double xPos, double yPos)
    {
        GLfloat xOffset = xPos - *_lastX;
        GLfloat yOffset = *_lastY - yPos;

        *_lastX = xPos;
        *_lastY = yPos;
        _camera->ProcessMouseMovement(xOffset, yOffset);
    });
}

void GLFWindow::PollEvents(const GLfloat deltaTime)
{
    glfwPollEvents();

    if(keys[GLFW_KEY_W])
        m_camera->ProcessKeyboard(0, deltaTime);
    if(keys[GLFW_KEY_S])
        m_camera->ProcessKeyboard(1, deltaTime);
    if(keys[GLFW_KEY_A])
        m_camera->ProcessKeyboard(2, deltaTime);
    if(keys[GLFW_KEY_D])
        m_camera->ProcessKeyboard(3, deltaTime);
    if(keys[GLFW_KEY_Q])
        m_camera->ProcessKeyboard(4, deltaTime);
    if(keys[GLFW_KEY_E])
        m_camera->ProcessKeyboard(5, deltaTime);
}

GLfloat GLFWindow::GetElapsedTime()
{
    return glfwGetTime();
}

void GLFWindow::SwapBuffers()
{
    glfwSwapBuffers(m_window);
}

谢谢你的时间, 布兰登

编辑:

我添加了一些X11代码来测试一些东西。

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>

Display *display =XOpenDisplay((char *)0);
if(XInternAtom(display, "XdndAware", False))
    std::cout << "Supported" << std::endl;

此代码始终返回Supported。我现在相信它是GLFW的一个错误。

最终编辑: 这是GLFW的一个错误。 错误是由于Thunar提供text / uri-list,而GLFW假定支持UTF8_STRING。修复传入。 如果其他人有这个问题,这里是修复。 https://github.com/glfw/glfw/commit/6a65341e14bc7745c52fe86fe53be08dbd682dd9

1 个答案:

答案 0 :(得分:1)

修改: This was indeed a bug and has been resolved.

首先确保您使用最新的稳定GLFW版本(今天是3.2.1)。

最明显的原因可能是您从未致电GLFWindow::PollEvents(),因此永远不会致电glfwPollEvents()。但是,我怀疑这是原因,因为你从未提及任何其他输入问题。

要验证它是否真的是永远不会被调用的回调,请尝试这个最小的例子:

glfwInit();

// You might need some of the window hints

GLFWwindow *window = glfwCreateWindow(600, 400, "Test glfwSetDropCallback", NULL, NULL);

glfwSetDropCallback(window, [](GLFWwindow*, int count, const char **paths)
{
    std::cout << "Drag and Drop count - " << count << std::endl;

    for (unsigned int i = 0; i < count; ++i)
        std::cout << "- " << paths[i] << std::endl;
});

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

glfwDestroyWindow(window);

glfwTerminate();

我刚在Windows上测试了上面的代码,但它确实有效。因此,如果该代码不起作用。然后它可能是特定于X11的错误,应该在GLFW's issue tracker上通知。

如果它仍然无效。然后在认为它是一个错误之前,你应该测试你的显示器是否支持文件丢弃。所以虽然这是X11具体的。您只是用它来验证支持。

请注意,如果不支持删除文件,GLFW不会抱怨。

自从我触及X11以来已经很久了。但是,如果我没记错的话,检查对删除文件的支持将是这样的:

Display *display = ...
if (XInternAtom(display, "XdndAware", False))
    std::cout << "Supported" << std::endl;
相关问题