Reputation: 21
I am currently creating a lightweight program to view and manipulate 3D objects similar to the program Blender or 3DS max.
I am using C++, GLFW, and OpenGL. While I plan to have it be cross platform, I am currently only working on a computer running Debian 9.0 (stretch) with the XFCE desktop environment.
Currently the callback glfwSetDropCallback never seems to get called, no mater what I try. I have set break points and asserts but nothing. All other callbacks that I have tried work just fine. I have included my GLFW cpp from my project. If something else is needed feel free to ask.
Also as a last note I am just using GLFW because everything else seems too heavy for my needs. Also using X11 directly appears like a lot of work for not much gain, especially since I would need a different solution for each OS I target. In the end I just want to be able to drag and drop items onto my programs window and then have my code do something with the path(s).
#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);
}
Thanks you for your time, Brandon
Edit:
I added some X11 code in to test some things.
#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;
This code always returns Supported. I now believe it is a bug with GLFW.
Final Edit: This was a bug with GLFW. Bug is due to Thunar providing text/uri-list while GLFW assumed UTF8_STRING was supported. Fix incoming. If anyone else has this issue here is the fix. https://github.com/glfw/glfw/commit/6a65341e14bc7745c52fe86fe53be08dbd682dd9
Upvotes: 1
Views: 1021
Reputation: 26245
Edit: This was indeed a bug and has been resolved.
First of all make sure that you're using the newest stable GLFW version (today that is 3.2.1).
The most obvious reason could be that you never call GLFWindow::PollEvents()
thus in turn never call glfwPollEvents()
. However I'm doubting this is the cause, as you never mention any other input problems.
To verify if it really is the callback never getting called, try this minimal example:
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();
I just tested the above code on Windows and it worked. So if that code doesn't work. Then it might be a X11 specific bug and should be notified on GLFW's issue tracker.
If it still doesn't work. Then before deeming it a bug, you should test if your display even supports file dropping. So while this is X11 specific. You'd only be using it to verify support.
Note that GLFW doesn't complain if dropping files isn't supported.
It's a long time since I've touched X11. But if I recall correctly, checking support for dropping files would be something like this:
Display *display = ...
if (XInternAtom(display, "XdndAware", False))
std::cout << "Supported" << std::endl;
Upvotes: 1