10 #include <GLFW/glfw3.h>
13 #include <unordered_map>
27 namespace visualization {
31 static constexpr
int FALLBACK_MONITOR_WIDTH = 1024;
32 static constexpr
int FALLBACK_MONITOR_HEIGHT = 768;
36 static constexpr
double DOUBLE_CLICK_TIME = 0.300;
40 double g_last_button_down_time = 0.0;
43 int MouseButtonFromGLFW(
int button) {
45 case GLFW_MOUSE_BUTTON_LEFT:
47 case GLFW_MOUSE_BUTTON_RIGHT:
49 case GLFW_MOUSE_BUTTON_MIDDLE:
51 case GLFW_MOUSE_BUTTON_4:
53 case GLFW_MOUSE_BUTTON_5:
60 int KeymodsFromGLFW(
int glfw_mods) {
62 if (glfw_mods & GLFW_MOD_SHIFT) {
65 if (glfw_mods & GLFW_MOD_CONTROL) {
72 if (glfw_mods & GLFW_MOD_ALT) {
79 if (glfw_mods & GLFW_MOD_SUPER) {
89 float CallGLFWGetWindowContentScale(GLFWwindow* w) {
91 glfwGetWindowContentScale(w, &xscale, &yscale);
105 MacTransformIntoApp();
107 glfwInitHint(GLFW_COCOA_MENUBAR, GLFW_FALSE);
110 glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE);
118 glfwWaitEventsTimeout(timeout_secs);
120 if (glfwGetError(&err) != GLFW_NO_ERROR) {
121 std::cerr <<
"[error] GLFW error: " << err <<
std::endl;
126 int screen_width = FALLBACK_MONITOR_WIDTH;
127 int screen_height = FALLBACK_MONITOR_HEIGHT;
128 auto* monitor = glfwGetWindowMonitor((GLFWwindow*)w);
130 monitor = glfwGetPrimaryMonitor();
133 const GLFWvidmode* mode = glfwGetVideoMode(monitor);
135 screen_width = mode->width;
136 screen_height = mode->height;
145 return Size(screen_width, screen_height);
153 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
154 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
155 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
156 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
161 glfwWindowHint(GLFW_ALPHA_BITS, 0);
162 glfwWindowHint(GLFW_STENCIL_BITS, 0);
165 glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
168 glfwWindowHint(GLFW_VISIBLE, visible ? GLFW_TRUE : GLFW_FALSE);
169 glfwWindowHint(GLFW_FLOATING,
170 ((flags &
FLAG_TOPMOST) != 0 ? GLFW_TRUE : GLFW_FALSE));
174 glfwSetWindowUserPointer(glfw_window,
o3d_window);
175 glfwSetWindowSizeCallback(glfw_window, ResizeCallback);
176 glfwSetWindowPosCallback(glfw_window, WindowMovedCallback);
177 glfwSetWindowRefreshCallback(glfw_window, DrawCallback);
178 glfwSetCursorPosCallback(glfw_window, MouseMoveCallback);
179 glfwSetMouseButtonCallback(glfw_window, MouseButtonCallback);
180 glfwSetScrollCallback(glfw_window, MouseScrollCallback);
181 glfwSetKeyCallback(glfw_window, KeyCallback);
182 glfwSetCharCallback(glfw_window, CharCallback);
183 glfwSetDropCallback(glfw_window, DragDropCallback);
184 glfwSetWindowCloseCallback(glfw_window, CloseCallback);
190 glfwDestroyWindow((GLFWwindow*)w);
198 return glfwGetWindowAttrib((GLFWwindow*)w, GLFW_VISIBLE);
203 glfwShowWindow((GLFWwindow*)w);
205 glfwHideWindow((GLFWwindow*)w);
210 glfwFocusWindow((GLFWwindow*)w);
214 return glfwGetWindowAttrib((GLFWwindow*)w, GLFW_FOCUSED);
219 glfwGetWindowPos((GLFWwindow*)w, &x, &y);
224 glfwSetWindowPos((GLFWwindow*)w, x, y);
229 glfwGetWindowSize((GLFWwindow*)w, &
width, &
height);
239 glfwGetFramebufferSize((GLFWwindow*)w, (
int*)&
width, (
int*)&
height);
244 std::cout <<
"[o3d] TODO: implement GLFWWindowSystem::SetWindowSizePixels()"
257 return CallGLFWGetWindowContentScale((GLFWwindow*)w);
266 return CallGLFWGetWindowContentScale((GLFWwindow*)w);
270 glfwSetWindowTitle((GLFWwindow*)w, title);
275 glfwGetCursorPos((GLFWwindow*)w, &mx, &my);
281 GLFWwindow* gw = (GLFWwindow*)w;
283 if (glfwGetMouseButton(gw, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) {
286 if (glfwGetMouseButton(gw, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS) {
289 if (glfwGetMouseButton(gw, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS) {
296 glfwSetWindowShouldClose((GLFWwindow*)w, 0);
300 void GLFWWindowSystem::DrawCallback(GLFWwindow* window) {
301 Window* w =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
305 void GLFWWindowSystem::ResizeCallback(GLFWwindow* window,
308 Window* w =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
312 void GLFWWindowSystem::WindowMovedCallback(GLFWwindow* window,
318 Window* w =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
323 void GLFWWindowSystem::RescaleCallback(GLFWwindow* window,
326 Window* w =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
330 void GLFWWindowSystem::MouseMoveCallback(GLFWwindow* window,
333 Window* w =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
335 for (
int b = GLFW_MOUSE_BUTTON_1; b < GLFW_MOUSE_BUTTON_5; ++b) {
336 if (glfwGetMouseButton(window, b) == GLFW_PRESS) {
337 buttons |= MouseButtonFromGLFW(b);
353 void GLFWWindowSystem::MouseButtonCallback(GLFWwindow* window,
357 Window* w =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
362 glfwGetCursorPos(window, &mx, &my);
370 type, ix, iy, KeymodsFromGLFW(mods),
374 if (g_last_button_down == me.button.button) {
375 double dt = now - g_last_button_down_time;
376 if (dt > 0.0 && dt < DOUBLE_CLICK_TIME) {
377 me.button.count += 1;
381 g_last_button_down = me.button.button;
382 g_last_button_down_time = now;
387 void GLFWWindowSystem::MouseScrollCallback(GLFWwindow* window,
390 Window* w =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
393 glfwGetCursorPos(window, &mx, &my);
403 bool isTrackpad =
true;
405 bool isTrackpad =
false;
419 void GLFWWindowSystem::KeyCallback(
420 GLFWwindow* window,
int key,
int scancode,
int action,
int mods) {
421 static std::unordered_map<int, uint32_t> g_GLFW2Key = {
446 Window* w =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
448 auto type = (action == GLFW_RELEASE ? KeyEvent::Type::UP
449 : KeyEvent::Type::DOWN);
452 if (key >=
'A' && key <=
'Z') {
455 auto it = g_GLFW2Key.find(key);
456 if (it != g_GLFW2Key.end()) {
460 KeyEvent e = {
type, k, (action == GLFW_REPEAT)};
465 void GLFWWindowSystem::CharCallback(GLFWwindow* window,
466 unsigned int utf32char) {
473 if (utf32char <= 0x7f) {
476 }
else if (utf32char <= 0x7ff) {
477 utf8[0] = 0xc0 | (utf32char >> 6);
478 utf8[1] = 0x80 | (utf32char & 0x3f);
480 }
else if (utf32char <= 0xffff) {
481 utf8[0] = 0xe0 | (utf32char >> 12);
482 utf8[1] = 0x80 | ((utf32char >> 6) & 0x3f);
483 utf8[2] = 0x80 | (utf32char & 0x3f);
485 }
else if (utf32char <= 0x10ffff) {
486 utf8[0] = 0xf0 | (utf32char >> 18);
487 utf8[1] = 0x80 | ((utf32char >> 12) & 0x3f);
488 utf8[2] = 0x80 | ((utf32char >> 6) & 0x3f);
489 utf8[3] = 0x80 | (utf32char & 0x3f);
497 Window* w =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
498 w->OnTextInput(TextInputEvent{utf8});
501 void GLFWWindowSystem::DragDropCallback(GLFWwindow* window,
503 const char* paths[]) {
504 Window* w =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
505 for (
int i = 0; i <
count; ++i) {
506 w->OnDragDropped(paths[i]);
510 void GLFWWindowSystem::CloseCallback(GLFWwindow* window) {
511 Window* w =
static_cast<Window*
>(glfwGetWindowUserPointer(window));
static Application & GetInstance()
WindowSystem & GetWindowSystem() const
void DestroyWindow(OSWindow w) override
Size GetScreenSize(OSWindow w) override
void Initialize() override
float GetWindowScaleFactor(OSWindow w) const override
float GetUIScaleFactor(OSWindow w) const override
MenuBase * CreateOSMenu() override
Point GetWindowPos(OSWindow w) const override
void PostRedrawEvent(OSWindow w) override
void RaiseWindowToTop(OSWindow w) override
OSWindow CreateOSWindow(Window *o3d_window, int width, int height, const char *title, int flags) override
bool IsActiveWindow(OSWindow w) const override
rendering::FilamentRenderer * CreateRenderer(OSWindow w) override
Point GetMousePosInWindow(OSWindow w) const override
void SetWindowPos(OSWindow w, int x, int y) override
Size GetWindowSizePixels(OSWindow w) const override
void WaitEventsTimeout(double timeout_secs) override
void ResizeRenderer(OSWindow w, rendering::FilamentRenderer *renderer) override
void SetWindowSizePixels(OSWindow w, const Size &size) override
void SetWindowSize(OSWindow w, int width, int height) override
bool GetWindowIsVisible(OSWindow w) const override
void Uninitialize() override
void ShowWindow(OSWindow w, bool show) override
void CancelUserClose(OSWindow w) override
void SetWindowTitle(OSWindow w, const char *title) override
void * GetNativeDrawable(OSWindow w) override
Size GetWindowSize(OSWindow w) const override
int GetMouseButtons(OSWindow w) const override
static constexpr int FLAG_TOPMOST
static constexpr int FLAG_HIDDEN
virtual float GetWindowScaleFactor(OSWindow w) const =0
static filament::Engine & GetInstance()
static FilamentResourceManager & GetResourceManager()
void UpdateSwapChain() override
QTextStream & endl(QTextStream &stream)
MiniVec< float, N > ceil(const MiniVec< float, N > &a)
void PostNativeExposeEvent(GLFWwindow *glfw_window)
void * GetNativeDrawable(GLFWwindow *glfw_window)
Generic file read and write utility for python interface.
static MouseEvent MakeWheelEvent(const Type type, const int x, const int y, const int modifiers, const float dx, const float dy, const bool isTrackpad)
static MouseEvent MakeButtonEvent(const Type type, const int x, const int y, const int modifiers, const MouseButton button, const int count)