//======================================================================== // GLFW 3.4 Wayland - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014 Jonas Ã…dahl // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages // arising from the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; you must not // claim that you wrote the original software. If you use this software // in a product, an acknowledgment in the product documentation would // be appreciated but is not required. // // 2. Altered source versions must be plainly marked as such, and must not // be misrepresented as being the original software. // // 3. This notice may not be removed or altered from any source // distribution. // //======================================================================== // It is fine to use C99 in this file because it will not be built with VS //======================================================================== #include "internal.h" #if defined(_GLFW_WAYLAND) #include #include #include #include #include #include "wayland-client-protocol.h" static void outputHandleGeometry(void* userData, struct wl_output* output, int32_t x, int32_t y, int32_t physicalWidth, int32_t physicalHeight, int32_t subpixel, const char* make, const char* model, int32_t transform) { struct _GLFWmonitor* monitor = userData; monitor->wl.x = x; monitor->wl.y = y; monitor->widthMM = physicalWidth; monitor->heightMM = physicalHeight; if (strlen(monitor->name) == 0) snprintf(monitor->name, sizeof(monitor->name), "%s %s", make, model); } static void outputHandleMode(void* userData, struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { struct _GLFWmonitor* monitor = userData; GLFWvidmode mode; mode.width = width; mode.height = height; mode.redBits = 8; mode.greenBits = 8; mode.blueBits = 8; mode.refreshRate = (int) round(refresh / 1000.0); monitor->modeCount++; monitor->modes = _glfw_realloc(monitor->modes, monitor->modeCount * sizeof(GLFWvidmode)); monitor->modes[monitor->modeCount - 1] = mode; if (flags & WL_OUTPUT_MODE_CURRENT) monitor->wl.currentMode = monitor->modeCount - 1; } static void outputHandleDone(void* userData, struct wl_output* output) { struct _GLFWmonitor* monitor = userData; if (monitor->widthMM <= 0 || monitor->heightMM <= 0) { // If Wayland does not provide a physical size, assume the default 96 DPI const GLFWvidmode* mode = &monitor->modes[monitor->wl.currentMode]; monitor->widthMM = (int) (mode->width * 25.4f / 96.f); monitor->heightMM = (int) (mode->height * 25.4f / 96.f); } for (int i = 0; i < _glfw.monitorCount; i++) { if (_glfw.monitors[i] == monitor) return; } _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST); } static void outputHandleScale(void* userData, struct wl_output* output, int32_t factor) { struct _GLFWmonitor* monitor = userData; monitor->wl.contentScale = factor; for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next) { for (int i = 0; i < window->wl.scaleCount; i++) { if (window->wl.scales[i].output == monitor->wl.output) { window->wl.scales[i].factor = monitor->wl.contentScale; _glfwUpdateContentScaleWayland(window); break; } } } } #ifdef WL_OUTPUT_NAME_SINCE_VERSION void outputHandleName(void* userData, struct wl_output* wl_output, const char* name) { struct _GLFWmonitor* monitor = userData; strncpy(monitor->name, name, sizeof(monitor->name) - 1); } void outputHandleDescription(void* userData, struct wl_output* wl_output, const char* description) { } #endif // WL_OUTPUT_NAME_SINCE_VERSION static const struct wl_output_listener outputListener = { outputHandleGeometry, outputHandleMode, outputHandleDone, outputHandleScale, #ifdef WL_OUTPUT_NAME_SINCE_VERSION outputHandleName, outputHandleDescription, #endif }; ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// void _glfwAddOutputWayland(uint32_t name, uint32_t version) { if (version < 2) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Unsupported output interface version"); return; } #ifdef WL_OUTPUT_NAME_SINCE_VERSION version = _glfw_min(version, WL_OUTPUT_NAME_SINCE_VERSION); #else version = 2; #endif struct wl_output* output = wl_registry_bind(_glfw.wl.registry, name, &wl_output_interface, version); if (!output) return; // The actual name of this output will be set in the geometry handler _GLFWmonitor* monitor = _glfwAllocMonitor("", 0, 0); monitor->wl.contentScale = 1; monitor->wl.output = output; monitor->wl.name = name; wl_proxy_set_tag((struct wl_proxy*) output, &_glfw.wl.tag); wl_output_add_listener(output, &outputListener, monitor); } ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// void _glfwFreeMonitorWayland(_GLFWmonitor* monitor) { if (monitor->wl.output) wl_output_destroy(monitor->wl.output); } void _glfwGetMonitorPosWayland(_GLFWmonitor* monitor, int* xpos, int* ypos) { if (xpos) *xpos = monitor->wl.x; if (ypos) *ypos = monitor->wl.y; } void _glfwGetMonitorContentScaleWayland(_GLFWmonitor* monitor, float* xscale, float* yscale) { if (xscale) *xscale = (float) monitor->wl.contentScale; if (yscale) *yscale = (float) monitor->wl.contentScale; } void _glfwGetMonitorWorkareaWayland(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height) { if (xpos) *xpos = monitor->wl.x; if (ypos) *ypos = monitor->wl.y; if (width) *width = monitor->modes[monitor->wl.currentMode].width; if (height) *height = monitor->modes[monitor->wl.currentMode].height; } GLFWvidmode* _glfwGetVideoModesWayland(_GLFWmonitor* monitor, int* found) { *found = monitor->modeCount; return monitor->modes; } void _glfwGetVideoModeWayland(_GLFWmonitor* monitor, GLFWvidmode* mode) { *mode = monitor->modes[monitor->wl.currentMode]; } GLFWbool _glfwGetGammaRampWayland(_GLFWmonitor* monitor, GLFWgammaramp* ramp) { _glfwInputError(GLFW_FEATURE_UNAVAILABLE, "Wayland: Gamma ramp access is not available"); return GLFW_FALSE; } void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) { _glfwInputError(GLFW_FEATURE_UNAVAILABLE, "Wayland: Gamma ramp access is not available"); } ////////////////////////////////////////////////////////////////////////// ////// GLFW native API ////// ////////////////////////////////////////////////////////////////////////// GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); return monitor->wl.output; } #endif // _GLFW_WAYLAND