当前位置: 首页 > 知识库问答 >
问题:

Debian上的GLFW回调glfwSetDropCallback有问题

司马耘豪
2023-03-14

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

我正在使用C、GLFW和OpenGL。虽然我计划让它跨平台,但我目前只在一台运行Debian9.0(stretch)和XFCE桌面环境的计算机上工作。

目前回调glfwSetDropCallback似乎从来没有被调用,无论我尝试什么。我已经设定了断点和断言,但什么都没有。我尝试过的所有其他回调都很好。我已经包括我的GLFW cpp从我的项目。如果需要其他东西,请随时询问。

最后一点,我只是在使用GLFW,因为其他的东西对我来说都太重了。另外,直接使用X11似乎需要做很多工作,但收获不大,特别是因为我需要为每个OS I目标提供不同的解决方案。最后,我只希望能够将项目拖放到我的程序窗口中,然后让我的代码对路径做一些处理。

#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;

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

最终编辑:这是GLFW的一个bug。错误是由于Thunar提供文本/uri列表,而GLFW假定支持UTF8_字符串。修复传入的。如果其他人有这个问题,这里是修复。https://github.com/glfw/glfw/commit/6a65341e14bc7745c52fe86fe53be08dbd682dd9

共有1个答案

滕无尘
2023-03-14

编辑:这确实是一个bug,已经解决了。

首先,确保您使用的是最新的稳定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特定的bug,应该在GLFW的问题跟踪程序上得到通知。

如果它仍然不起作用。然后,在认为它是一个bug之前,您应该测试您的显示器是否支持文件删除。因此,尽管这是X11特有的。你只能用它来验证支持。

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

我已经很久没碰过X11了。但是如果我没记错的话,检查对删除文件的支持是这样的:

Display *display = ...
if (XInternAtom(display, "XdndAware", False))
    std::cout << "Supported" << std::endl;
 类似资料:
  • 一般来说,我对GLFW和OpenGL比较陌生,我正在开发一个小型模型渲染器。我目前正在处理输入,我面临着GLFW如何处理输入的问题,让我解释一下:每个教程都告诉我使用glfwGetKey和“if-forest”来查看是否按下了这样或那样的键。我遇到的问题是,如果我映射了很多关键点,它可能会变得很慢,而且很难看。所以我使用函数指针表和glfwSetKeyCallback来加速这一过程并获得更清晰的代

  • 在中设置回调函数时,要使用什么? 我尝试将函数设置为类型<code>void。将其更改为<code>void __stdcall,但如何使用<code>GLFW的<code>typedef,例如<code>GLFW*fun?我认为这是正确的选择。我真的需要一个示例源代码。 顺便说一句,我将GLFW定义为 更新 我的代码是这样的: (我以三种方式做到了) 一 原型。因为在下面,所以这个给我一个编译错

  • 我目前正在使用OpenGL和GLFW开发一个跨平台的2D渲染引擎。我有一个名为GameWindow的基本窗口类,以及一个名为Game的继承GameWindow的类。游戏覆盖了基类中的一些虚拟方法,以便GameWindow可以处理帧限制等。在GameWindow的构造函数中,我使用glfwSetWindowSizeCallback指定窗口调整大小时要运行的方法。然后,此方法调用GameWindow的

  • 我正在努力理解我的代码在这个Leetcode问题上出了什么问题。 问题:给定一个字符串,确定它是否是回文,只考虑字母数字字符,忽略大小写。 现在,我通过了108/476个案例,我没有通过这个测试:“一个人,一个计划,一条运河:巴拿马”。 这是我的代码,请帮我识别问题!

  • 我不确定Twilio Authy的register\u user()的成功回调是否正在启动。在我的代码中 尽管新用户已成功添加到Authy,且响应状态为200。 我想在register\u user()的成功回调中设置authyUsrId的值,并在发送给POST请求的JSON响应中使用它。 但在回应中,我只得到了这个 <代码>{姓名:'你好'} 是否有任何方法可以调试register\u user

  • 我的应用程序应该更新,如果tmx是新的,如果旧的什么都不做,如果不存在插入文件。如果文档被插入,它工作完美,否则它不能正确更新或说E11000 dup密钥。想弄清楚我的回调是不是错了还是逻辑。(我是node.js+MongoDB的新手)MongoClient=require(“MongoDB”).MongoClient,assert=require(“assert”),url=“MongoDB:/