2 * Copyright © 2012 Intel Corporation
3 * Copyright © 2008 Kristian Høgsberg
4 * Copyright © 2012-2013 Collabora, Ltd.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30 #include "piglit-util-gl.h"
31 #include "piglit_wl_framework.h"
33 #include <wayland-client.h>
34 #include <waffle_wayland.h>
35 #include <xkbcommon/xkbcommon.h>
38 struct piglit_wl_framework
{
39 struct piglit_winsys_framework winsys_fw
;
41 struct wl_display
*dpy
;
42 struct wl_registry
*registry
;
45 struct wl_keyboard
*keyboard
;
48 struct xkb_context
*context
;
49 struct xkb_keymap
*keymap
;
50 struct xkb_state
*state
;
54 /* Most of the code here taken from window.c in Weston source code. */
55 static void keymap(void *data
,
56 struct wl_keyboard
*wl_keyboard
,
61 struct piglit_wl_framework
*wl_fw
=
62 (struct piglit_wl_framework
*) data
;
63 struct xkb_keymap
*keymap
;
64 struct xkb_state
*state
;
68 if (!data
|| format
!= WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1
) {
73 map_str
= mmap(NULL
, size
, PROT_READ
, MAP_SHARED
, fd
, 0);
74 if (map_str
== MAP_FAILED
) {
79 /* Set up XKB keymap */
80 keymap
= xkb_keymap_new_from_string(wl_fw
->xkb
.context
,
82 XKB_KEYMAP_FORMAT_TEXT_V1
,
85 munmap(map_str
, size
);
89 fprintf(stderr
, "failed to compile keymap\n");
93 /* Set up XKB state */
94 state
= xkb_state_new(keymap
);
96 fprintf(stderr
, "failed to create XKB state\n");
97 xkb_keymap_unref(keymap
);
101 /* Look up the preferred locale, falling back to "C" as default */
102 if (!(locale
= getenv("LC_ALL")))
103 if (!(locale
= getenv("LC_CTYPE")))
104 if (!(locale
= getenv("LANG")))
107 xkb_keymap_unref(wl_fw
->xkb
.keymap
);
108 xkb_state_unref(wl_fw
->xkb
.state
);
109 wl_fw
->xkb
.keymap
= keymap
;
110 wl_fw
->xkb
.state
= state
;
113 static void enter(void *data
,
114 struct wl_keyboard
*wl_keyboard
,
116 struct wl_surface
*surface
,
117 struct wl_array
*keys
)
121 static void leave(void *data
,
122 struct wl_keyboard
*wl_keyboard
,
124 struct wl_surface
*surface
)
128 static void key(void *data
,
129 struct wl_keyboard
*wl_keyboard
,
135 struct piglit_wl_framework
*wl_fw
=
136 (struct piglit_wl_framework
*) data
;
137 struct piglit_winsys_framework
*winsys_fw
= &wl_fw
->winsys_fw
;
138 const struct piglit_gl_test_config
*test_config
=
139 winsys_fw
->wfl_fw
.gl_fw
.test_config
;
141 const xkb_keysym_t
*syms
;
144 uint32_t code
= key
+ 8;
147 if (!wl_fw
->xkb
.state
)
150 num_syms
= xkb_state_key_get_syms(wl_fw
->xkb
.state
, code
, &syms
);
151 sym
= XKB_KEY_NoSymbol
;
155 winsys_fw
->need_redisplay
= true;
157 if (state
!= WL_KEYBOARD_KEY_STATE_PRESSED
)
160 if (winsys_fw
->user_keyboard_func
)
161 winsys_fw
->user_keyboard_func(sym
, 0, 0);
163 if (winsys_fw
->need_redisplay
) {
164 enum piglit_result result
= PIGLIT_PASS
;
165 if (test_config
->display
)
166 result
= test_config
->display();
167 if (piglit_automatic
)
168 piglit_report_result(result
);
169 winsys_fw
->need_redisplay
= false;
173 static void modifiers(void *data
,
174 struct wl_keyboard
*wl_keyboard
,
176 uint32_t mods_depressed
,
177 uint32_t mods_latched
,
178 uint32_t mods_locked
,
183 static const struct wl_keyboard_listener keyboard_listener
= {
192 process_events(struct wl_display
*dpy
)
195 if (wl_display_dispatch(dpy
) == -1)
200 static void global(void *data
,
201 struct wl_registry
*wl_registry
,
203 const char *interface
,
206 struct piglit_wl_framework
*wl_fw
=
207 (struct piglit_wl_framework
*) data
;
209 if (strcmp(interface
, "wl_seat") != 0)
212 wl_fw
->seat
= wl_registry_bind(wl_registry
, name
, &wl_seat_interface
, 1);
213 wl_fw
->keyboard
= wl_seat_get_keyboard(wl_fw
->seat
);
216 wl_keyboard_add_listener(wl_fw
->keyboard
, &keyboard_listener
, data
);
219 static void global_remove(void *data
,
220 struct wl_registry
*wl_registry
,
225 static const struct wl_registry_listener registry_listener
= {
231 enter_event_loop(struct piglit_winsys_framework
*winsys_fw
)
233 struct piglit_wl_framework
*wl_fw
=
234 (struct piglit_wl_framework
*) winsys_fw
;
235 const struct piglit_gl_test_config
*test_config
=
236 winsys_fw
->wfl_fw
.gl_fw
.test_config
;
237 enum piglit_result result
= PIGLIT_PASS
;
239 /* The Wayland window fails to appear on the first call to
240 * swapBuffers (which occured in display_cb above). This is
241 * likely due to swapBuffers being called before receiving an
242 * expose event. Until piglit has proper Wayland support,
243 * redraw as a workaround.
245 if (test_config
->display
)
246 result
= test_config
->display();
248 /* Do not proceed to event loop in case of piglit_automatic. */
249 if (piglit_automatic
)
250 piglit_report_result(result
);
252 process_events(wl_fw
->dpy
);
256 show_window(struct piglit_winsys_framework
*winsys_fw
)
258 waffle_window_show(winsys_fw
->wfl_fw
.window
);
262 destroy(struct piglit_gl_framework
*gl_fw
)
264 struct piglit_wl_framework
*wl_fw
=
265 (struct piglit_wl_framework
*) gl_fw
;
270 xkb_keymap_unref(wl_fw
->xkb
.keymap
);
271 xkb_state_unref(wl_fw
->xkb
.state
);
272 xkb_context_unref(wl_fw
->xkb
.context
);
274 wl_registry_destroy(wl_fw
->registry
);
276 piglit_winsys_framework_teardown(&wl_fw
->winsys_fw
);
280 struct piglit_gl_framework
*
281 piglit_wl_framework_create(const struct piglit_gl_test_config
*test_config
)
283 struct piglit_wl_framework
*wl_fw
= NULL
;
284 struct piglit_winsys_framework
*winsys_fw
= NULL
;
285 struct piglit_gl_framework
*gl_fw
= NULL
;
288 wl_fw
= calloc(1, sizeof(*wl_fw
));
289 winsys_fw
= &wl_fw
->winsys_fw
;
290 gl_fw
= &wl_fw
->winsys_fw
.wfl_fw
.gl_fw
;
292 ok
= piglit_winsys_framework_init(&wl_fw
->winsys_fw
,
293 test_config
, WAFFLE_PLATFORM_WAYLAND
);
297 wl_fw
->xkb
.context
= xkb_context_new(0);
298 wl_fw
->xkb
.keymap
= NULL
;
299 wl_fw
->xkb
.state
= NULL
;
301 if (!wl_fw
->xkb
.context
)
304 union waffle_native_window
*n_window
=
305 waffle_window_get_native(winsys_fw
->wfl_fw
.window
);
307 wl_fw
->dpy
= n_window
->wayland
->display
.wl_display
;
308 wl_fw
->registry
= wl_display_get_registry(wl_fw
->dpy
);
310 wl_registry_add_listener(wl_fw
->registry
, ®istry_listener
, wl_fw
);
312 winsys_fw
->show_window
= show_window
;
313 winsys_fw
->enter_event_loop
= enter_event_loop
;
314 gl_fw
->destroy
= destroy
;