wl_monitor.c (8627B)
1 //======================================================================== 2 // GLFW 3.4 Wayland - www.glfw.org 3 //------------------------------------------------------------------------ 4 // Copyright (c) 2014 Jonas Ã…dahl <jadahl@gmail.com> 5 // 6 // This software is provided 'as-is', without any express or implied 7 // warranty. In no event will the authors be held liable for any damages 8 // arising from the use of this software. 9 // 10 // Permission is granted to anyone to use this software for any purpose, 11 // including commercial applications, and to alter it and redistribute it 12 // freely, subject to the following restrictions: 13 // 14 // 1. The origin of this software must not be misrepresented; you must not 15 // claim that you wrote the original software. If you use this software 16 // in a product, an acknowledgment in the product documentation would 17 // be appreciated but is not required. 18 // 19 // 2. Altered source versions must be plainly marked as such, and must not 20 // be misrepresented as being the original software. 21 // 22 // 3. This notice may not be removed or altered from any source 23 // distribution. 24 // 25 //======================================================================== 26 27 #include "internal.h" 28 29 #if defined(_GLFW_WAYLAND) 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <errno.h> 35 #include <math.h> 36 37 #include "wayland-client-protocol.h" 38 39 40 static void outputHandleGeometry(void* userData, 41 struct wl_output* output, 42 int32_t x, 43 int32_t y, 44 int32_t physicalWidth, 45 int32_t physicalHeight, 46 int32_t subpixel, 47 const char* make, 48 const char* model, 49 int32_t transform) 50 { 51 struct _GLFWmonitor* monitor = userData; 52 53 monitor->wl.x = x; 54 monitor->wl.y = y; 55 monitor->widthMM = physicalWidth; 56 monitor->heightMM = physicalHeight; 57 58 if (strlen(monitor->name) == 0) 59 snprintf(monitor->name, sizeof(monitor->name), "%s %s", make, model); 60 } 61 62 static void outputHandleMode(void* userData, 63 struct wl_output* output, 64 uint32_t flags, 65 int32_t width, 66 int32_t height, 67 int32_t refresh) 68 { 69 struct _GLFWmonitor* monitor = userData; 70 GLFWvidmode mode; 71 72 mode.width = width; 73 mode.height = height; 74 mode.redBits = 8; 75 mode.greenBits = 8; 76 mode.blueBits = 8; 77 mode.refreshRate = (int) round(refresh / 1000.0); 78 79 monitor->modeCount++; 80 monitor->modes = 81 _glfw_realloc(monitor->modes, monitor->modeCount * sizeof(GLFWvidmode)); 82 monitor->modes[monitor->modeCount - 1] = mode; 83 84 if (flags & WL_OUTPUT_MODE_CURRENT) 85 monitor->wl.currentMode = monitor->modeCount - 1; 86 } 87 88 static void outputHandleDone(void* userData, struct wl_output* output) 89 { 90 struct _GLFWmonitor* monitor = userData; 91 92 if (monitor->widthMM <= 0 || monitor->heightMM <= 0) 93 { 94 // If Wayland does not provide a physical size, assume the default 96 DPI 95 const GLFWvidmode* mode = &monitor->modes[monitor->wl.currentMode]; 96 monitor->widthMM = (int) (mode->width * 25.4f / 96.f); 97 monitor->heightMM = (int) (mode->height * 25.4f / 96.f); 98 } 99 100 for (int i = 0; i < _glfw.monitorCount; i++) 101 { 102 if (_glfw.monitors[i] == monitor) 103 return; 104 } 105 106 _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST); 107 } 108 109 static void outputHandleScale(void* userData, 110 struct wl_output* output, 111 int32_t factor) 112 { 113 struct _GLFWmonitor* monitor = userData; 114 115 monitor->wl.scale = factor; 116 117 for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next) 118 { 119 for (size_t i = 0; i < window->wl.outputScaleCount; i++) 120 { 121 if (window->wl.outputScales[i].output == monitor->wl.output) 122 { 123 window->wl.outputScales[i].factor = monitor->wl.scale; 124 _glfwUpdateBufferScaleFromOutputsWayland(window); 125 break; 126 } 127 } 128 } 129 } 130 131 void outputHandleName(void* userData, struct wl_output* wl_output, const char* name) 132 { 133 struct _GLFWmonitor* monitor = userData; 134 135 strncpy(monitor->name, name, sizeof(monitor->name) - 1); 136 } 137 138 void outputHandleDescription(void* userData, 139 struct wl_output* wl_output, 140 const char* description) 141 { 142 } 143 144 static const struct wl_output_listener outputListener = 145 { 146 outputHandleGeometry, 147 outputHandleMode, 148 outputHandleDone, 149 outputHandleScale, 150 outputHandleName, 151 outputHandleDescription, 152 }; 153 154 155 ////////////////////////////////////////////////////////////////////////// 156 ////// GLFW internal API ////// 157 ////////////////////////////////////////////////////////////////////////// 158 159 void _glfwAddOutputWayland(uint32_t name, uint32_t version) 160 { 161 if (version < 2) 162 { 163 _glfwInputError(GLFW_PLATFORM_ERROR, 164 "Wayland: Unsupported output interface version"); 165 return; 166 } 167 168 version = _glfw_min(version, WL_OUTPUT_NAME_SINCE_VERSION); 169 170 struct wl_output* output = wl_registry_bind(_glfw.wl.registry, 171 name, 172 &wl_output_interface, 173 version); 174 if (!output) 175 return; 176 177 // The actual name of this output will be set in the geometry handler 178 _GLFWmonitor* monitor = _glfwAllocMonitor("", 0, 0); 179 monitor->wl.scale = 1; 180 monitor->wl.output = output; 181 monitor->wl.name = name; 182 183 wl_proxy_set_tag((struct wl_proxy*) output, &_glfw.wl.tag); 184 wl_output_add_listener(output, &outputListener, monitor); 185 } 186 187 188 ////////////////////////////////////////////////////////////////////////// 189 ////// GLFW platform API ////// 190 ////////////////////////////////////////////////////////////////////////// 191 192 void _glfwFreeMonitorWayland(_GLFWmonitor* monitor) 193 { 194 if (monitor->wl.output) 195 wl_output_destroy(monitor->wl.output); 196 } 197 198 void _glfwGetMonitorPosWayland(_GLFWmonitor* monitor, int* xpos, int* ypos) 199 { 200 if (xpos) 201 *xpos = monitor->wl.x; 202 if (ypos) 203 *ypos = monitor->wl.y; 204 } 205 206 void _glfwGetMonitorContentScaleWayland(_GLFWmonitor* monitor, 207 float* xscale, float* yscale) 208 { 209 if (xscale) 210 *xscale = (float) monitor->wl.scale; 211 if (yscale) 212 *yscale = (float) monitor->wl.scale; 213 } 214 215 void _glfwGetMonitorWorkareaWayland(_GLFWmonitor* monitor, 216 int* xpos, int* ypos, 217 int* width, int* height) 218 { 219 if (xpos) 220 *xpos = monitor->wl.x; 221 if (ypos) 222 *ypos = monitor->wl.y; 223 if (width) 224 *width = monitor->modes[monitor->wl.currentMode].width; 225 if (height) 226 *height = monitor->modes[monitor->wl.currentMode].height; 227 } 228 229 GLFWvidmode* _glfwGetVideoModesWayland(_GLFWmonitor* monitor, int* found) 230 { 231 *found = monitor->modeCount; 232 return monitor->modes; 233 } 234 235 GLFWbool _glfwGetVideoModeWayland(_GLFWmonitor* monitor, GLFWvidmode* mode) 236 { 237 *mode = monitor->modes[monitor->wl.currentMode]; 238 return GLFW_TRUE; 239 } 240 241 GLFWbool _glfwGetGammaRampWayland(_GLFWmonitor* monitor, GLFWgammaramp* ramp) 242 { 243 _glfwInputError(GLFW_FEATURE_UNAVAILABLE, 244 "Wayland: Gamma ramp access is not available"); 245 return GLFW_FALSE; 246 } 247 248 void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) 249 { 250 _glfwInputError(GLFW_FEATURE_UNAVAILABLE, 251 "Wayland: Gamma ramp access is not available"); 252 } 253 254 255 ////////////////////////////////////////////////////////////////////////// 256 ////// GLFW native API ////// 257 ////////////////////////////////////////////////////////////////////////// 258 259 GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle) 260 { 261 _GLFWmonitor* monitor = (_GLFWmonitor*) handle; 262 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 263 264 if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND) 265 { 266 _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "Wayland: Platform not initialized"); 267 return NULL; 268 } 269 270 return monitor->wl.output; 271 } 272 273 #endif // _GLFW_WAYLAND 274