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() { cleanup(); }
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);
174 void resize(uint width, uint height)
176 glfwSetWindowSize(mWindow, width, height);
181 DerivedRenderApp::WM::init(derived());
182 while (!glfwWindowShouldClose(mWindow)) {
184 DerivedRenderApp::WM::paint(derived());
185#ifdef VCLIB_RENDER_BACKEND_OPENGL2
186 glfwSwapBuffers(mWindow);
215#if defined(__linux__)
216#ifdef VCLIB_RENDER_WITH_WAYLAND
217 nwh = (
void*) (uintptr_t) glfwGetWaylandWindow(mWindow);
219 nwh = (
void*) (uintptr_t) glfwGetX11Window(mWindow);
222 nwh = glfwGetWin32Window(mWindow);
223#elif defined(__APPLE__)
224 nwh = glfwGetCocoaWindow(mWindow);
230 void* displayId()
const
234#ifdef VCLIB_RENDER_WITH_WAYLAND
235 ndt = (
void*) (uintptr_t) glfwGetWaylandDisplay();
237 ndt = (
void*) (uintptr_t) glfwGetX11Display();
244 void* windowPtr() {
return reinterpret_cast<void*
>(mWindow); }
247 virtual void glfwFramebufferSizeCallback(GLFWwindow*,
int width,
int height)
249 DerivedRenderApp::WM::resize(derived(), width, height);
252 virtual void glfwContentScaleCallback(
261 glfwGetFramebufferSize(mWindow, &width, &height);
262 DerivedRenderApp::WM::resize(derived(), width, height);
265 virtual void glfwKeyCallback(
272#if defined GLFW_EXPOSE_NATIVE_X11
275 mods = fixKeyboardMods(key, action, mods);
279 DerivedRenderApp::WM::setModifiers(
280 derived(), glfw::fromGLFW((glfw::KeyboardModifiers) mods));
282 vcl::Key::Enum k = glfw::fromGLFW((glfw::Key) key);
284 if (action == GLFW_PRESS || action == GLFW_REPEAT) {
285 DerivedRenderApp::WM::keyPress(derived(), k);
287 else if (action == GLFW_RELEASE) {
288 DerivedRenderApp::WM::keyRelease(derived(), k);
292 virtual void glfwMouseButtonCallback(
298 vcl::MouseButton::Enum btn = glfw::fromGLFW((glfw::MouseButton) button);
300 DerivedRenderApp::WM::setModifiers(
301 derived(), glfw::fromGLFW((glfw::KeyboardModifiers) mods));
305 glfwGetCursorPos(win, &pos.x(), &pos.y());
308 pos.x() *= dpiScale().
x();
309 pos.y() *= dpiScale().
y();
312 if (action == GLFW_PRESS) {
314 const double timeSeconds = glfwGetTime();
316 if (timeSeconds - mLastPressedTime < DOUBLE_CLICK_TIME_SECS &&
317 button == mLastPressedButton &&
318 (mLastPressedPos - pos).norm() < DOUBLE_CLICK_DIST_PIXELS) {
319 mLastPressedTime = 0.0;
320 mLastPressedButton = NO_BUTTON;
321 DerivedRenderApp::WM::mouseDoubleClick(
322 derived(), btn, pos.x(), pos.y());
325 mLastPressedTime = timeSeconds;
326 mLastPressedButton = button;
327 mLastPressedPos = pos;
328 DerivedRenderApp::WM::mousePress(
329 derived(), btn, pos.x(), pos.y());
332 else if (action == GLFW_RELEASE) {
333 DerivedRenderApp::WM::mouseRelease(
334 derived(), btn, pos.x(), pos.y());
338 virtual void glfwCursorPosCallback(GLFWwindow*,
double xpos,
double ypos)
342 xpos *= dpiScale().
x();
343 ypos *= dpiScale().
y();
345 DerivedRenderApp::WM::mouseMove(derived(), xpos, ypos);
348 virtual void glfwScrollCallback(GLFWwindow*,
double xoffset,
double yoffset)
354 const double TO_PIXEL_FACTOR = 10;
355 DerivedRenderApp::WM::mouseScroll(
357 xoffset * TO_PIXEL_FACTOR,
358 yoffset * TO_PIXEL_FACTOR);
366 glfwDestroyWindow(mWindow);
374 glfwSetFramebufferSizeCallback(
375 mWindow, [](GLFWwindow* window,
int width,
int height) {
376 auto* self =
static_cast<WindowManager*
>(
377 glfwGetWindowUserPointer(window));
378 self->glfwFramebufferSizeCallback(window, width, height);
382 glfwSetWindowContentScaleCallback(
383 mWindow, [](GLFWwindow* window,
float xscale,
float yscale) {
384 auto* self =
static_cast<WindowManager*
>(
385 glfwGetWindowUserPointer(window));
386 self->glfwContentScaleCallback(window, xscale, yscale);
392 [](GLFWwindow* window,
397 auto* self =
static_cast<WindowManager*
>(
398 glfwGetWindowUserPointer(window));
399 self->glfwKeyCallback(window, key, scancode, action, mods);
403 glfwSetCursorPosCallback(
404 mWindow, [](GLFWwindow* window,
double xpos,
double ypos) {
405 auto* self =
static_cast<WindowManager*
>(
406 glfwGetWindowUserPointer(window));
407 self->glfwCursorPosCallback(window, xpos, ypos);
411 glfwSetMouseButtonCallback(
412 mWindow, [](GLFWwindow* window,
int button,
int action,
int mods) {
413 auto* self =
static_cast<WindowManager*
>(
414 glfwGetWindowUserPointer(window));
415 self->glfwMouseButtonCallback(window, button, action, mods);
419 glfwSetScrollCallback(
420 mWindow, [](GLFWwindow* window,
double xoffset,
double yoffset) {
421 auto* self =
static_cast<WindowManager*
>(
422 glfwGetWindowUserPointer(window));
423 self->glfwScrollCallback(window, xoffset, yoffset);
427 auto* derived() {
return static_cast<DerivedRenderApp*
>(
this); }
429 const auto* derived()
const
431 return static_cast<const DerivedRenderApp*
>(
this);
434 static int fixKeyboardMods(
int key,
int action,
int mods)
437 case GLFW_KEY_LEFT_SHIFT:
438 case GLFW_KEY_RIGHT_SHIFT:
439 return (action == GLFW_PRESS) ? mods | GLFW_MOD_SHIFT :
440 mods & (~GLFW_MOD_SHIFT);
441 case GLFW_KEY_LEFT_CONTROL:
442 case GLFW_KEY_RIGHT_CONTROL:
443 return (action == GLFW_PRESS) ? mods | GLFW_MOD_CONTROL :
444 mods & (~GLFW_MOD_CONTROL);
445 case GLFW_KEY_LEFT_ALT:
446 case GLFW_KEY_RIGHT_ALT:
447 return (action == GLFW_PRESS) ? mods | GLFW_MOD_ALT :
448 mods & (~GLFW_MOD_ALT);
449 case GLFW_KEY_LEFT_SUPER:
450 case GLFW_KEY_RIGHT_SUPER:
451 return (action == GLFW_PRESS) ? mods | GLFW_MOD_SUPER :
452 mods & (~GLFW_MOD_SUPER);