wl_monitor.c (7384B)
1 //======================================================================== 2 // GLFW 3.3 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 // It is fine to use C99 in this file because it will not be built with VS 27 //======================================================================== 28 29 #include "internal.h" 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <errno.h> 35 #include <math.h> 36 37 38 static void outputHandleGeometry(void* data, 39 struct wl_output* output, 40 int32_t x, 41 int32_t y, 42 int32_t physicalWidth, 43 int32_t physicalHeight, 44 int32_t subpixel, 45 const char* make, 46 const char* model, 47 int32_t transform) 48 { 49 struct _GLFWmonitor *monitor = data; 50 char name[1024]; 51 52 monitor->wl.x = x; 53 monitor->wl.y = y; 54 monitor->widthMM = physicalWidth; 55 monitor->heightMM = physicalHeight; 56 57 snprintf(name, sizeof(name), "%s %s", make, model); 58 monitor->name = _glfw_strdup(name); 59 } 60 61 static void outputHandleMode(void* data, 62 struct wl_output* output, 63 uint32_t flags, 64 int32_t width, 65 int32_t height, 66 int32_t refresh) 67 { 68 struct _GLFWmonitor *monitor = data; 69 GLFWvidmode mode; 70 71 mode.width = width; 72 mode.height = height; 73 mode.redBits = 8; 74 mode.greenBits = 8; 75 mode.blueBits = 8; 76 mode.refreshRate = (int) round(refresh / 1000.0); 77 78 monitor->modeCount++; 79 monitor->modes = 80 realloc(monitor->modes, monitor->modeCount * sizeof(GLFWvidmode)); 81 monitor->modes[monitor->modeCount - 1] = mode; 82 83 if (flags & WL_OUTPUT_MODE_CURRENT) 84 monitor->wl.currentMode = monitor->modeCount - 1; 85 } 86 87 static void outputHandleDone(void* data, struct wl_output* output) 88 { 89 struct _GLFWmonitor *monitor = data; 90 91 if (monitor->widthMM <= 0 || monitor->heightMM <= 0) 92 { 93 // If Wayland does not provide a physical size, assume the default 96 DPI 94 const GLFWvidmode* mode = &monitor->modes[monitor->wl.currentMode]; 95 monitor->widthMM = (int) (mode->width * 25.4f / 96.f); 96 monitor->heightMM = (int) (mode->height * 25.4f / 96.f); 97 } 98 99 _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST); 100 } 101 102 static void outputHandleScale(void* data, 103 struct wl_output* output, 104 int32_t factor) 105 { 106 struct _GLFWmonitor *monitor = data; 107 108 monitor->wl.scale = factor; 109 } 110 111 static const struct wl_output_listener outputListener = { 112 outputHandleGeometry, 113 outputHandleMode, 114 outputHandleDone, 115 outputHandleScale, 116 }; 117 118 119 ////////////////////////////////////////////////////////////////////////// 120 ////// GLFW internal API ////// 121 ////////////////////////////////////////////////////////////////////////// 122 123 void _glfwAddOutputWayland(uint32_t name, uint32_t version) 124 { 125 _GLFWmonitor *monitor; 126 struct wl_output *output; 127 128 if (version < 2) 129 { 130 _glfwInputError(GLFW_PLATFORM_ERROR, 131 "Wayland: Unsupported output interface version"); 132 return; 133 } 134 135 // The actual name of this output will be set in the geometry handler. 136 monitor = _glfwAllocMonitor(NULL, 0, 0); 137 138 output = wl_registry_bind(_glfw.wl.registry, 139 name, 140 &wl_output_interface, 141 2); 142 if (!output) 143 { 144 _glfwFreeMonitor(monitor); 145 return; 146 } 147 148 monitor->wl.scale = 1; 149 monitor->wl.output = output; 150 monitor->wl.name = name; 151 152 wl_output_add_listener(output, &outputListener, monitor); 153 } 154 155 156 ////////////////////////////////////////////////////////////////////////// 157 ////// GLFW platform API ////// 158 ////////////////////////////////////////////////////////////////////////// 159 160 void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor) 161 { 162 if (monitor->wl.output) 163 wl_output_destroy(monitor->wl.output); 164 } 165 166 void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) 167 { 168 if (xpos) 169 *xpos = monitor->wl.x; 170 if (ypos) 171 *ypos = monitor->wl.y; 172 } 173 174 void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, 175 float* xscale, float* yscale) 176 { 177 if (xscale) 178 *xscale = (float) monitor->wl.scale; 179 if (yscale) 180 *yscale = (float) monitor->wl.scale; 181 } 182 183 void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, 184 int* xpos, int* ypos, 185 int* width, int* height) 186 { 187 if (xpos) 188 *xpos = monitor->wl.x; 189 if (ypos) 190 *ypos = monitor->wl.y; 191 if (width) 192 *width = monitor->modes[monitor->wl.currentMode].width; 193 if (height) 194 *height = monitor->modes[monitor->wl.currentMode].height; 195 } 196 197 GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) 198 { 199 *found = monitor->modeCount; 200 return monitor->modes; 201 } 202 203 void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) 204 { 205 *mode = monitor->modes[monitor->wl.currentMode]; 206 } 207 208 GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) 209 { 210 _glfwInputError(GLFW_PLATFORM_ERROR, 211 "Wayland: Gamma ramp access is not available"); 212 return GLFW_FALSE; 213 } 214 215 void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, 216 const GLFWgammaramp* ramp) 217 { 218 _glfwInputError(GLFW_PLATFORM_ERROR, 219 "Wayland: Gamma ramp access is not available"); 220 } 221 222 223 ////////////////////////////////////////////////////////////////////////// 224 ////// GLFW native API ////// 225 ////////////////////////////////////////////////////////////////////////// 226 227 GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle) 228 { 229 _GLFWmonitor* monitor = (_GLFWmonitor*) handle; 230 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 231 return monitor->wl.output; 232 } 233