69 static constexpr double DOUBLE_CLICK_TIME_SECS = 0.25;
70 static constexpr double DOUBLE_CLICK_DIST_PIXELS = 4.0;
72 double mLastPressedTime = 0.0;
73 int mLastPressedButton = NO_BUTTON;
74 Point2d mLastPressedPos = {0, 0};
102 const std::string& windowTitle,
109 "The DerivedRenderApp must satisfy the RenderAppConcept.");
113 std::cerr <<
"Failed to initialize GLFW" << std::endl;
117#if defined(VCLIB_RENDER_BACKEND_BGFX)
120#if defined(__APPLE__)
123#elif defined(VCLIB_RENDER_BACKEND_OPENGL2)
132 width, height, windowTitle.c_str(),
nullptr,
nullptr);
134 std::cerr <<
"Failed to create GLFW window" << std::endl;
139#ifdef VCLIB_RENDER_BACKEND_OPENGL2
140 glfwMakeContextCurrent(mWindow);
144 glfwGetWindowContentScale(mWindow, &mScaleX, &mScaleY);
146 glfwSetWindowUserPointer(mWindow,
this);
150 virtual ~WindowManager() =
default;
152 const std::string& windowTitle()
const {
return mTitle; }
154 void setWindowTitle(
const std::string& title)
157 glfwSetWindowTitle(mWindow, mTitle.c_str());
163 glfwGetWindowSize(mWindow, &width, &height);
170 glfwGetWindowSize(mWindow, &width, &height);
176 DerivedRenderApp::WM::init(derived());
177 while (!glfwWindowShouldClose(mWindow)) {
179 DerivedRenderApp::WM::paint(derived());
180#ifdef VCLIB_RENDER_BACKEND_OPENGL2
181 glfwSwapBuffers(mWindow);
208#if defined(__linux__)
209#ifdef VCLIB_RENDER_WITH_WAYLAND
210 nwh = (
void*) (uintptr_t) glfwGetWaylandWindow(mWindow);
212 nwh = (
void*) (uintptr_t) glfwGetX11Window(mWindow);
215 nwh = glfwGetWin32Window(mWindow);
216#elif defined(__APPLE__)
217 nwh = glfwGetCocoaWindow(mWindow);
223 void* displayId()
const
227#ifdef VCLIB_RENDER_WITH_WAYLAND
228 ndt = (
void*) (uintptr_t) glfwGetWaylandDisplay();
230 ndt = (
void*) (uintptr_t) glfwGetX11Display();
237 void* windowPtr() {
return reinterpret_cast<void*
>(mWindow); }
240 virtual void glfwFramebufferSizeCallback(GLFWwindow*,
int width,
int height)
242 DerivedRenderApp::WM::resize(derived(), width, height);
245 virtual void glfwContentScaleCallback(
254 glfwGetFramebufferSize(mWindow, &width, &height);
255 DerivedRenderApp::WM::resize(derived(), width, height);
258 virtual void glfwKeyCallback(
265#if defined GLFW_EXPOSE_NATIVE_X11
268 mods = fixKeyboardMods(key, action, mods);
272 DerivedRenderApp::WM::setModifiers(
273 derived(), glfw::fromGLFW((glfw::KeyboardModifiers) mods));
275 vcl::Key::Enum k = glfw::fromGLFW((glfw::Key) key);
277 if (action == GLFW_PRESS || action == GLFW_REPEAT) {
278 DerivedRenderApp::WM::keyPress(derived(), k);
280 else if (action == GLFW_RELEASE) {
281 DerivedRenderApp::WM::keyRelease(derived(), k);
285 virtual void glfwMouseButtonCallback(
291 vcl::MouseButton::Enum btn = glfw::fromGLFW((glfw::MouseButton) button);
293 DerivedRenderApp::WM::setModifiers(
294 derived(), glfw::fromGLFW((glfw::KeyboardModifiers) mods));
298 glfwGetCursorPos(win, &pos.x(), &pos.y());
301 pos.x() *= dpiScale().
x();
302 pos.y() *= dpiScale().
y();
305 if (action == GLFW_PRESS) {
307 const double timeSeconds = glfwGetTime();
309 if (timeSeconds - mLastPressedTime < DOUBLE_CLICK_TIME_SECS &&
310 button == mLastPressedButton &&
311 (mLastPressedPos - pos).norm() < DOUBLE_CLICK_DIST_PIXELS) {
312 mLastPressedTime = 0.0;
313 mLastPressedButton = NO_BUTTON;
314 DerivedRenderApp::WM::mouseDoubleClick(
315 derived(), btn, pos.x(), pos.y());
318 mLastPressedTime = timeSeconds;
319 mLastPressedButton = button;
320 mLastPressedPos = pos;
321 DerivedRenderApp::WM::mousePress(
322 derived(), btn, pos.x(), pos.y());
325 else if (action == GLFW_RELEASE) {
326 DerivedRenderApp::WM::mouseRelease(
327 derived(), btn, pos.x(), pos.y());
331 virtual void glfwCursorPosCallback(GLFWwindow*,
double xpos,
double ypos)
335 xpos *= dpiScale().
x();
336 ypos *= dpiScale().
y();
338 DerivedRenderApp::WM::mouseMove(derived(), xpos, ypos);
341 virtual void glfwScrollCallback(GLFWwindow*,
double xoffset,
double yoffset)
347 const double TO_PIXEL_FACTOR = 10;
348 DerivedRenderApp::WM::mouseScroll(
350 xoffset * TO_PIXEL_FACTOR,
351 yoffset * TO_PIXEL_FACTOR);
359 glfwSetFramebufferSizeCallback(
360 mWindow, [](GLFWwindow* window,
int width,
int height) {
361 auto* self =
static_cast<WindowManager*
>(
362 glfwGetWindowUserPointer(window));
363 self->glfwFramebufferSizeCallback(window, width, height);
367 glfwSetWindowContentScaleCallback(
368 mWindow, [](GLFWwindow* window,
float xscale,
float yscale) {
369 auto* self =
static_cast<WindowManager*
>(
370 glfwGetWindowUserPointer(window));
371 self->glfwContentScaleCallback(window, xscale, yscale);
377 [](GLFWwindow* window,
382 auto* self =
static_cast<WindowManager*
>(
383 glfwGetWindowUserPointer(window));
384 self->glfwKeyCallback(window, key, scancode, action, mods);
388 glfwSetCursorPosCallback(
389 mWindow, [](GLFWwindow* window,
double xpos,
double ypos) {
390 auto* self =
static_cast<WindowManager*
>(
391 glfwGetWindowUserPointer(window));
392 self->glfwCursorPosCallback(window, xpos, ypos);
396 glfwSetMouseButtonCallback(
397 mWindow, [](GLFWwindow* window,
int button,
int action,
int mods) {
398 auto* self =
static_cast<WindowManager*
>(
399 glfwGetWindowUserPointer(window));
400 self->glfwMouseButtonCallback(window, button, action, mods);
404 glfwSetScrollCallback(
405 mWindow, [](GLFWwindow* window,
double xoffset,
double yoffset) {
406 auto* self =
static_cast<WindowManager*
>(
407 glfwGetWindowUserPointer(window));
408 self->glfwScrollCallback(window, xoffset, yoffset);
412 auto* derived() {
return static_cast<DerivedRenderApp*
>(
this); }
414 const auto* derived()
const
416 return static_cast<const DerivedRenderApp*
>(
this);
419 static int fixKeyboardMods(
int key,
int action,
int mods)
422 case GLFW_KEY_LEFT_SHIFT:
423 case GLFW_KEY_RIGHT_SHIFT:
424 return (action == GLFW_PRESS) ? mods | GLFW_MOD_SHIFT :
425 mods & (~GLFW_MOD_SHIFT);
426 case GLFW_KEY_LEFT_CONTROL:
427 case GLFW_KEY_RIGHT_CONTROL:
428 return (action == GLFW_PRESS) ? mods | GLFW_MOD_CONTROL :
429 mods & (~GLFW_MOD_CONTROL);
430 case GLFW_KEY_LEFT_ALT:
431 case GLFW_KEY_RIGHT_ALT:
432 return (action == GLFW_PRESS) ? mods | GLFW_MOD_ALT :
433 mods & (~GLFW_MOD_ALT);
434 case GLFW_KEY_LEFT_SUPER:
435 case GLFW_KEY_RIGHT_SUPER:
436 return (action == GLFW_PRESS) ? mods | GLFW_MOD_SUPER :
437 mods & (~GLFW_MOD_SUPER);