1 //========================================================================
2 // GLFW 3.2 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 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33
34
35 struct _GLFWvidmodeWayland
36 {
37 GLFWvidmode base;
38 uint32_t flags;
39 };
40
geometry(void * data,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)41 static void geometry(void* data,
42 struct wl_output* output,
43 int32_t x,
44 int32_t y,
45 int32_t physicalWidth,
46 int32_t physicalHeight,
47 int32_t subpixel,
48 const char* make,
49 const char* model,
50 int32_t transform)
51 {
52 struct _GLFWmonitor *monitor = data;
53
54 monitor->wl.x = x;
55 monitor->wl.y = y;
56 monitor->widthMM = physicalWidth;
57 monitor->heightMM = physicalHeight;
58 }
59
mode(void * data,struct wl_output * output,uint32_t flags,int32_t width,int32_t height,int32_t refresh)60 static void mode(void* data,
61 struct wl_output* output,
62 uint32_t flags,
63 int32_t width,
64 int32_t height,
65 int32_t refresh)
66 {
67 struct _GLFWmonitor *monitor = data;
68 _GLFWvidmodeWayland mode = { { 0 }, };
69
70 mode.base.width = width;
71 mode.base.height = height;
72 mode.base.refreshRate = refresh / 1000;
73 mode.flags = flags;
74
75 if (monitor->wl.modesCount + 1 >= monitor->wl.modesSize)
76 {
77 int size = monitor->wl.modesSize * 2;
78 _GLFWvidmodeWayland* modes =
79 realloc(monitor->wl.modes,
80 size * sizeof(_GLFWvidmodeWayland));
81 monitor->wl.modes = modes;
82 monitor->wl.modesSize = size;
83 }
84
85 monitor->wl.modes[monitor->wl.modesCount++] = mode;
86 }
87
done(void * data,struct wl_output * output)88 static void done(void* data,
89 struct wl_output* output)
90 {
91 struct _GLFWmonitor *monitor = data;
92
93 monitor->wl.done = GLFW_TRUE;
94 }
95
scale(void * data,struct wl_output * output,int32_t factor)96 static void scale(void* data,
97 struct wl_output* output,
98 int32_t factor)
99 {
100 struct _GLFWmonitor *monitor = data;
101
102 monitor->wl.scale = factor;
103 }
104
105 static const struct wl_output_listener output_listener = {
106 geometry,
107 mode,
108 done,
109 scale,
110 };
111
112
113 //////////////////////////////////////////////////////////////////////////
114 ////// GLFW internal API //////
115 //////////////////////////////////////////////////////////////////////////
116
_glfwAddOutputWayland(uint32_t name,uint32_t version)117 void _glfwAddOutputWayland(uint32_t name, uint32_t version)
118 {
119 _GLFWmonitor *monitor;
120 struct wl_output *output;
121 char name_str[80];
122
123 memset(name_str, 0, sizeof(name_str));
124 snprintf(name_str, 79, "wl_output@%u", name);
125
126 if (version < 2)
127 {
128 _glfwInputError(GLFW_PLATFORM_ERROR,
129 "Wayland: Unsupported output interface version");
130 return;
131 }
132
133 monitor = _glfwAllocMonitor(name_str, 0, 0);
134
135 output = wl_registry_bind(_glfw.wl.registry,
136 name,
137 &wl_output_interface,
138 2);
139 if (!output)
140 {
141 _glfwFreeMonitor(monitor);
142 return;
143 }
144
145 monitor->wl.modes = calloc(4, sizeof(_GLFWvidmodeWayland));
146 monitor->wl.modesSize = 4;
147
148 monitor->wl.scale = 1;
149
150 monitor->wl.output = output;
151 wl_output_add_listener(output, &output_listener, monitor);
152
153 if (_glfw.wl.monitorsCount + 1 >= _glfw.wl.monitorsSize)
154 {
155 _GLFWmonitor** monitors = _glfw.wl.monitors;
156 int size = _glfw.wl.monitorsSize * 2;
157
158 monitors = realloc(monitors, size * sizeof(_GLFWmonitor*));
159
160 _glfw.wl.monitors = monitors;
161 _glfw.wl.monitorsSize = size;
162 }
163
164 _glfw.wl.monitors[_glfw.wl.monitorsCount++] = monitor;
165 }
166
167
168 //////////////////////////////////////////////////////////////////////////
169 ////// GLFW platform API //////
170 //////////////////////////////////////////////////////////////////////////
171
_glfwPlatformGetMonitors(int * count)172 _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
173 {
174 _GLFWmonitor** monitors;
175 _GLFWmonitor* monitor;
176 int i, monitorsCount = _glfw.wl.monitorsCount;
177
178 if (_glfw.wl.monitorsCount == 0)
179 goto err;
180
181 monitors = calloc(monitorsCount, sizeof(_GLFWmonitor*));
182
183 for (i = 0; i < monitorsCount; i++)
184 {
185 _GLFWmonitor* origMonitor = _glfw.wl.monitors[i];
186 monitor = calloc(1, sizeof(_GLFWmonitor));
187
188 monitor->modes =
189 _glfwPlatformGetVideoModes(origMonitor,
190 &origMonitor->wl.modesCount);
191 *monitor = *_glfw.wl.monitors[i];
192 monitors[i] = monitor;
193 }
194
195 *count = monitorsCount;
196 return monitors;
197
198 err:
199 *count = 0;
200 return NULL;
201 }
202
_glfwPlatformIsSameMonitor(_GLFWmonitor * first,_GLFWmonitor * second)203 GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
204 {
205 return first->wl.output == second->wl.output;
206 }
207
_glfwPlatformGetMonitorPos(_GLFWmonitor * monitor,int * xpos,int * ypos)208 void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
209 {
210 if (xpos)
211 *xpos = monitor->wl.x;
212 if (ypos)
213 *ypos = monitor->wl.y;
214 }
215
_glfwPlatformGetVideoModes(_GLFWmonitor * monitor,int * found)216 GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
217 {
218 GLFWvidmode *modes;
219 int i, modesCount = monitor->wl.modesCount;
220
221 modes = calloc(modesCount, sizeof(GLFWvidmode));
222
223 for (i = 0; i < modesCount; i++)
224 modes[i] = monitor->wl.modes[i].base;
225
226 *found = modesCount;
227 return modes;
228 }
229
_glfwPlatformGetVideoMode(_GLFWmonitor * monitor,GLFWvidmode * mode)230 void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
231 {
232 int i;
233
234 for (i = 0; i < monitor->wl.modesCount; i++)
235 {
236 if (monitor->wl.modes[i].flags & WL_OUTPUT_MODE_CURRENT)
237 {
238 *mode = monitor->wl.modes[i].base;
239 return;
240 }
241 }
242 }
243
_glfwPlatformGetGammaRamp(_GLFWmonitor * monitor,GLFWgammaramp * ramp)244 void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
245 {
246 // TODO
247 _glfwInputError(GLFW_PLATFORM_ERROR,
248 "Wayland: Gamma ramp getting not supported yet");
249 }
250
_glfwPlatformSetGammaRamp(_GLFWmonitor * monitor,const GLFWgammaramp * ramp)251 void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
252 {
253 // TODO
254 _glfwInputError(GLFW_PLATFORM_ERROR,
255 "Wayland: Gamma ramp setting not supported yet");
256 }
257
258
259 //////////////////////////////////////////////////////////////////////////
260 ////// GLFW native API //////
261 //////////////////////////////////////////////////////////////////////////
262
glfwGetWaylandMonitor(GLFWmonitor * handle)263 GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle)
264 {
265 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
266 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
267 return monitor->wl.output;
268 }
269
270