1414 *
1515 * Run with: ./gameframe /path/to/your/app
1616 */
17-
1817#include <assert.h>
1918#include <signal.h>
2019#include <stdbool.h>
3837#include <wlr/types/wlr_subcompositor.h>
3938#include <wlr/types/wlr_xdg_shell.h>
4039#include <wlr/util/log.h>
40+ #include <wlr/types/wlr_cursor.h>
4141
4242struct gameframe_server {
4343 struct wl_display * display ;
@@ -46,30 +46,25 @@ struct gameframe_server {
4646 struct wlr_allocator * allocator ;
4747 struct wlr_scene * scene ;
4848 struct wlr_scene_output * scene_output ;
49-
5049 struct wlr_xdg_shell * xdg_shell ;
5150 struct wlr_compositor * compositor ;
5251 struct wlr_subcompositor * subcompositor ;
53-
5452 struct wlr_output_layout * output_layout ;
5553 struct wlr_seat * seat ;
56-
54+ struct wlr_cursor * cursor ;
5755 struct wl_listener new_output ;
5856 struct wl_listener new_xdg_surface ;
5957 struct wl_listener new_input ;
6058 struct wl_listener request_set_cursor ;
6159 struct wl_listener request_set_selection ;
62-
6360 pid_t child_pid ;
6461};
65-
6662struct gameframe_output {
6763 struct wlr_output * wlr_output ;
6864 struct gameframe_server * server ;
6965 struct wl_listener frame ;
7066 struct wl_listener destroy ;
7167};
72-
7368struct gameframe_view {
7469 struct wlr_xdg_toplevel * xdg_toplevel ;
7570 struct wlr_scene_tree * scene_tree ;
@@ -82,32 +77,25 @@ struct gameframe_view {
8277 struct wl_listener request_maximize ;
8378 struct wl_listener request_fullscreen ;
8479};
85-
8680static void output_frame (struct wl_listener * listener , void * data ) {
8781 struct gameframe_output * output = wl_container_of (listener , output , frame );
8882 struct wlr_scene * scene = output -> server -> scene ;
8983 struct wlr_scene_output * scene_output = wlr_scene_get_scene_output (scene , output -> wlr_output );
90-
9184 wlr_scene_output_commit (scene_output , NULL );
92-
9385 struct timespec now ;
9486 clock_gettime (CLOCK_MONOTONIC , & now );
9587 wlr_scene_output_send_frame_done (scene_output , & now );
9688}
97-
9889static void output_destroy (struct wl_listener * listener , void * data ) {
9990 struct gameframe_output * output = wl_container_of (listener , output , destroy );
10091 wl_list_remove (& output -> frame .link );
10192 wl_list_remove (& output -> destroy .link );
10293 free (output );
10394}
104-
10595static void server_new_output (struct wl_listener * listener , void * data ) {
10696 struct gameframe_server * server = wl_container_of (listener , server , new_output );
10797 struct wlr_output * wlr_output = data ;
108-
10998 wlr_output_init_render (wlr_output , server -> allocator , server -> renderer );
110-
11199 struct wlr_output_state state ;
112100 wlr_output_state_init (& state );
113101 wlr_output_state_set_enabled (& state , true);
@@ -117,33 +105,27 @@ static void server_new_output(struct wl_listener *listener, void *data) {
117105 }
118106 wlr_output_commit_state (wlr_output , & state );
119107 wlr_output_state_finish (& state );
120-
121108 struct gameframe_output * output = calloc (1 , sizeof (* output ));
122109 output -> wlr_output = wlr_output ;
123110 output -> server = server ;
124111 output -> frame .notify = output_frame ;
125112 wl_signal_add (& wlr_output -> events .frame , & output -> frame );
126113 output -> destroy .notify = output_destroy ;
127114 wl_signal_add (& wlr_output -> events .destroy , & output -> destroy );
128-
129115 wlr_output_layout_add_auto (server -> output_layout , wlr_output );
130-
131- server -> scene_output = wlr_scene_attach_output (server -> scene , wlr_output );
116+ server -> scene_output = wlr_scene_output_create (server -> scene , wlr_output );
132117}
133-
134118static void xdg_toplevel_map (struct wl_listener * listener , void * data ) {
135119 struct gameframe_view * view = wl_container_of (listener , view , map );
136- wlr_scene_tree_set_position ( view -> scene_tree , 0 , 0 );
120+ wlr_scene_node_set_position ( & view -> scene_tree -> node , 0 , 0 );
137121 wlr_xdg_toplevel_set_size (view -> xdg_toplevel , 0 , 0 ); // Fullscreen implicitly
138122 wlr_xdg_toplevel_set_fullscreen (view -> xdg_toplevel , true);
139123}
140-
141124static void xdg_toplevel_unmap (struct wl_listener * listener , void * data ) {
142125 struct gameframe_view * view = wl_container_of (listener , view , unmap );
143126 // No-op for now
144127}
145-
146- static void xdg_toplevel_destroy (struct wl_listener * listener , void * data ) {
128+ static void view_destroy (struct wl_listener * listener , void * data ) {
147129 struct gameframe_view * view = wl_container_of (listener , view , destroy );
148130 wl_list_remove (& view -> map .link );
149131 wl_list_remove (& view -> unmap .link );
@@ -154,45 +136,36 @@ static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) {
154136 wl_list_remove (& view -> request_fullscreen .link );
155137 free (view );
156138}
157-
158139static void xdg_toplevel_request_move (struct wl_listener * listener , void * data ) {
159140 // No moving in fullscreen
160141}
161-
162142static void xdg_toplevel_request_resize (struct wl_listener * listener , void * data ) {
163143 // No resizing in fullscreen
164144}
165-
166145static void xdg_toplevel_request_maximize (struct wl_listener * listener , void * data ) {
167146 // Already maximized/fullscreen
168147}
169-
170148static void xdg_toplevel_request_fullscreen (struct wl_listener * listener , void * data ) {
171149 struct gameframe_view * view = wl_container_of (listener , view , request_fullscreen );
172- struct wlr_xdg_toplevel_set_fullscreen_event * event = data ;
173- wlr_xdg_toplevel_set_fullscreen (view -> xdg_toplevel , event -> fullscreen );
150+ struct wlr_xdg_surface * xdg_surface = data ;
151+ wlr_xdg_toplevel_set_fullscreen (view -> xdg_toplevel , xdg_surface -> toplevel -> requested . fullscreen );
174152}
175-
176153static void server_new_xdg_surface (struct wl_listener * listener , void * data ) {
177154 struct gameframe_server * server = wl_container_of (listener , server , new_xdg_surface );
178155 struct wlr_xdg_surface * xdg_surface = data ;
179-
180156 if (xdg_surface -> role != WLR_XDG_SURFACE_ROLE_TOPLEVEL ) {
181157 return ;
182158 }
183-
184159 struct gameframe_view * view = calloc (1 , sizeof (* view ));
185160 view -> server = server ;
186161 view -> xdg_toplevel = xdg_surface -> toplevel ;
187162 view -> scene_tree = wlr_scene_xdg_surface_create (& server -> scene -> tree , xdg_surface );
188-
189163 view -> map .notify = xdg_toplevel_map ;
190- wl_signal_add (& xdg_surface -> events .map , & view -> map );
164+ wl_signal_add (& xdg_surface -> surface -> events .map , & view -> map );
191165 view -> unmap .notify = xdg_toplevel_unmap ;
192- wl_signal_add (& xdg_surface -> events .unmap , & view -> unmap );
193- view -> destroy .notify = xdg_toplevel_destroy ;
166+ wl_signal_add (& xdg_surface -> surface -> events .unmap , & view -> unmap );
167+ view -> destroy .notify = view_destroy ;
194168 wl_signal_add (& xdg_surface -> events .destroy , & view -> destroy );
195-
196169 view -> request_move .notify = xdg_toplevel_request_move ;
197170 wl_signal_add (& view -> xdg_toplevel -> events .request_move , & view -> request_move );
198171 view -> request_resize .notify = xdg_toplevel_request_resize ;
@@ -202,16 +175,13 @@ static void server_new_xdg_surface(struct wl_listener *listener, void *data) {
202175 view -> request_fullscreen .notify = xdg_toplevel_request_fullscreen ;
203176 wl_signal_add (& view -> xdg_toplevel -> events .request_fullscreen , & view -> request_fullscreen );
204177}
205-
206178static void process_keyboard (struct gameframe_server * server , struct wlr_keyboard * keyboard ) {
207179 wlr_seat_set_keyboard (server -> seat , keyboard );
208180 wlr_keyboard_set_repeat_info (keyboard , 25 , 600 );
209181}
210-
211182static void server_new_input (struct wl_listener * listener , void * data ) {
212183 struct gameframe_server * server = wl_container_of (listener , server , new_input );
213184 struct wlr_input_device * device = data ;
214-
215185 switch (device -> type ) {
216186 case WLR_INPUT_DEVICE_KEYBOARD : {
217187 struct wlr_keyboard * kb = wlr_keyboard_from_input_device (device );
@@ -223,106 +193,86 @@ static void server_new_input(struct wl_listener *listener, void *data) {
223193 process_keyboard (server , kb );
224194 break ;
225195 }
226- case WLR_INPUT_DEVICE_POINTER :
227- wlr_seat_set_capabilities (server -> seat , WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_KEYBOARD );
196+ case WLR_INPUT_DEVICE_POINTER : {
197+ wlr_cursor_attach_input_device (server -> cursor , device );
228198 break ;
199+ }
229200 default :
230201 break ;
231202 }
232-
233203 uint32_t caps = WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_KEYBOARD ;
234204 wlr_seat_set_capabilities (server -> seat , caps );
235205}
236-
237206static void request_set_cursor (struct wl_listener * listener , void * data ) {
238207 struct gameframe_server * server = wl_container_of (listener , server , request_set_cursor );
239208 struct wlr_seat_pointer_request_set_cursor_event * event = data ;
240- struct wlr_seat_client * client = event -> seat_client ;
241-
242- if (client == NULL ) {
243- return ;
209+ struct wlr_seat_client * focused_client = server -> seat -> pointer_state .focused_client ;
210+ if (focused_client != NULL && focused_client == event -> seat_client ) {
211+ wlr_cursor_set_surface (server -> cursor , event -> surface , event -> hotspot_x , event -> hotspot_y );
244212 }
245-
246- wlr_seat_pointer_surface_set_cursor (server -> seat , client , event -> surface , event -> hotspot_x , event -> hotspot_y );
247213}
248-
249214static void request_set_selection (struct wl_listener * listener , void * data ) {
250215 struct gameframe_server * server = wl_container_of (listener , server , request_set_selection );
251216 struct wlr_seat_request_set_selection_event * event = data ;
252217 wlr_seat_set_selection (server -> seat , event -> source , event -> serial );
253218}
254-
255219int main (int argc , char * argv []) {
256220 wlr_log_init (WLR_DEBUG , NULL );
257-
258221 if (argc < 2 ) {
259222 fprintf (stderr , "Usage: %s <command>\n" , argv [0 ]);
260223 return 1 ;
261224 }
262-
263225 struct gameframe_server server = {0 };
264226 server .display = wl_display_create ();
265227 if (server .display == NULL ) {
266228 wlr_log (WLR_ERROR , "Cannot create wayland display" );
267229 return 1 ;
268230 }
269-
270231 server .backend = wlr_backend_autocreate (wl_display_get_event_loop (server .display ), NULL );
271232 if (server .backend == NULL ) {
272233 wlr_log (WLR_ERROR , "Cannot create backend" );
273234 return 1 ;
274235 }
275-
276236 server .renderer = wlr_renderer_autocreate (server .backend );
277237 if (server .renderer == NULL ) {
278238 wlr_log (WLR_ERROR , "Cannot create renderer" );
279239 return 1 ;
280240 }
281-
282241 wlr_renderer_init_wl_display (server .renderer , server .display );
283-
284242 server .allocator = wlr_allocator_autocreate (server .backend , server .renderer );
285243 if (server .allocator == NULL ) {
286244 wlr_log (WLR_ERROR , "Cannot create allocator" );
287245 return 1 ;
288246 }
289-
290247 server .compositor = wlr_compositor_create (server .display , 5 , server .renderer );
291248 server .subcompositor = wlr_subcompositor_create (server .display );
292249 wlr_data_device_manager_create (server .display );
293-
294- server .output_layout = wlr_output_layout_create ();
250+ server .output_layout = wlr_output_layout_create (server .display );
251+ server .cursor = wlr_cursor_create ();
252+ wlr_cursor_attach_output_layout (server .cursor , server .output_layout );
295253 server .scene = wlr_scene_create ();
296-
297254 server .new_output .notify = server_new_output ;
298255 wl_signal_add (& server .backend -> events .new_output , & server .new_output );
299-
300256 server .xdg_shell = wlr_xdg_shell_create (server .display , 3 );
301257 server .new_xdg_surface .notify = server_new_xdg_surface ;
302258 wl_signal_add (& server .xdg_shell -> events .new_surface , & server .new_xdg_surface );
303-
304259 server .seat = wlr_seat_create (server .display , "seat0" );
305260 server .request_set_cursor .notify = request_set_cursor ;
306261 wl_signal_add (& server .seat -> events .request_set_cursor , & server .request_set_cursor );
307262 server .request_set_selection .notify = request_set_selection ;
308263 wl_signal_add (& server .seat -> events .request_set_selection , & server .request_set_selection );
309-
310264 server .new_input .notify = server_new_input ;
311265 wl_signal_add (& server .backend -> events .new_input , & server .new_input );
312-
313266 const char * socket = wl_display_add_socket_auto (server .display );
314267 if (socket == NULL ) {
315268 wlr_log (WLR_ERROR , "Cannot add socket" );
316269 return 1 ;
317270 }
318-
319271 if (!wlr_backend_start (server .backend )) {
320272 wlr_log (WLR_ERROR , "Cannot start backend" );
321273 return 1 ;
322274 }
323-
324275 setenv ("WAYLAND_DISPLAY" , socket , true);
325-
326276 server .child_pid = fork ();
327277 if (server .child_pid == 0 ) {
328278 execvp (argv [1 ], argv + 1 );
@@ -332,22 +282,18 @@ int main(int argc, char *argv[]) {
332282 wlr_log (WLR_ERROR , "Cannot fork" );
333283 return 1 ;
334284 }
335-
336285 wlr_log (WLR_INFO , "Running on WAYLAND_DISPLAY=%s" , socket );
337286 wl_display_run (server .display );
338-
339287 if (server .child_pid > 0 ) {
340288 kill (server .child_pid , SIGTERM );
341289 waitpid (server .child_pid , NULL , 0 );
342290 }
343-
344291 wl_display_destroy_clients (server .display );
345292 wl_display_destroy (server .display );
346293 wlr_scene_output_destroy (server .scene_output );
347294 wlr_output_layout_destroy (server .output_layout );
348295 wlr_allocator_destroy (server .allocator );
349296 wlr_renderer_destroy (server .renderer );
350297 wlr_backend_destroy (server .backend );
351-
352298 return 0 ;
353299}
0 commit comments