2 * Copyright © 2008 Kristian Høgsberg
3 * Copyright © 2012 Intel Corporation
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting documentation, and
9 * that the name of the copyright holders not be used in advertising or
10 * publicity pertaining to distribution of the software without specific,
11 * written prior permission. The copyright holders make no representations
12 * about the suitability of this software for any purpose. It is provided "as
13 * is" without express or implied warranty.
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
34 #include <linux/input.h>
35 #include <wayland-client.h>
37 #include "fullscreen-shell-client-protocol.h"
41 struct output *output;
45 struct display *display;
46 struct window *window;
47 struct widget *widget;
48 struct _wl_fullscreen_shell *fshell;
49 enum _wl_fullscreen_shell_present_method present_method;
52 float pointer_x, pointer_y;
55 struct wl_list output_list;
56 struct fs_output *current_output;
60 fullscreen_handler(struct window *window, void *data)
62 struct fullscreen *fullscreen = data;
64 fullscreen->fullscreen ^= 1;
65 window_set_fullscreen(window, fullscreen->fullscreen);
69 draw_string(cairo_t *cr,
75 cairo_text_extents_t text_extents;
76 cairo_font_extents_t font_extents;
80 cairo_select_font_face(cr, "sans",
81 CAIRO_FONT_SLANT_NORMAL,
82 CAIRO_FONT_WEIGHT_NORMAL);
83 cairo_set_font_size(cr, 14);
85 cairo_font_extents (cr, &font_extents);
89 vsnprintf(buffer, sizeof(buffer), fmt, argp);
93 end = strchr(p, '\n');
97 cairo_show_text(cr, p);
98 cairo_text_extents (cr, p, &text_extents);
99 cairo_rel_move_to (cr, -text_extents.x_advance, font_extents.height);
114 redraw_handler(struct widget *widget, void *data)
116 struct fullscreen *fullscreen = data;
117 struct rectangle allocation;
118 cairo_surface_t *surface;
122 const char *method_name[] = { "default", "center", "zoom", "zoom_crop", "stretch"};
124 surface = window_get_surface(fullscreen->window);
125 if (surface == NULL ||
126 cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
127 fprintf(stderr, "failed to create cairo egl surface\n");
131 widget_get_allocation(fullscreen->widget, &allocation);
133 cr = widget_cairo_create(widget);
135 cairo_set_source_rgb(cr, 0, 0, 0);
138 cairo_set_source_rgb(cr, 0, 0, 1);
139 cairo_set_line_width (cr, 10);
140 cairo_rectangle(cr, 5, 5, allocation.width - 10, allocation.height - 10);
146 cairo_set_source_rgb(cr, 1, 1, 1);
148 if (fullscreen->fshell) {
150 "Surface size: %d, %d\n"
151 "Scale: %d, transform: %d\n"
153 "Output: %s, present method: %s\n"
154 "Keys: (s)cale, (t)ransform, si(z)e, (m)ethod,\n"
155 " (o)utput, modes(w)itch, (q)uit\n",
156 fullscreen->width, fullscreen->height,
157 window_get_buffer_scale (fullscreen->window),
158 window_get_buffer_transform (fullscreen->window),
159 fullscreen->pointer_x, fullscreen->pointer_y,
160 method_name[fullscreen->present_method],
161 fullscreen->current_output ? output_get_model(fullscreen->current_output->output): "null");
164 "Surface size: %d, %d\n"
165 "Scale: %d, transform: %d\n"
168 "Keys: (s)cale, (t)ransform, si(z)e, (f)ullscreen, (q)uit\n",
169 fullscreen->width, fullscreen->height,
170 window_get_buffer_scale (fullscreen->window),
171 window_get_buffer_transform (fullscreen->window),
172 fullscreen->pointer_x, fullscreen->pointer_y,
173 fullscreen->fullscreen);
178 while (y + 60 < fullscreen->height) {
179 border = (i++ % 2 == 0) ? 1 : 0.5;
182 cairo_set_line_width (cr, border);
183 while (x + 70 < fullscreen->width) {
184 if (window_has_focus(fullscreen->window) &&
185 fullscreen->pointer_x >= x && fullscreen->pointer_x < x + 50 &&
186 fullscreen->pointer_y >= y && fullscreen->pointer_y < y + 40) {
187 cairo_set_source_rgb(cr, 1, 0, 0);
193 cairo_set_source_rgb(cr, 0, 1, 0);
195 x + border/2.0, y + border/2.0,
204 if (window_has_focus(fullscreen->window) && fullscreen->draw_cursor) {
205 cairo_set_source_rgb(cr, 1, 1, 1);
206 cairo_set_line_width (cr, 8);
208 fullscreen->pointer_x - 12,
209 fullscreen->pointer_y - 12);
211 fullscreen->pointer_x + 12,
212 fullscreen->pointer_y + 12);
216 fullscreen->pointer_x + 12,
217 fullscreen->pointer_y - 12);
219 fullscreen->pointer_x - 12,
220 fullscreen->pointer_y + 12);
223 cairo_set_source_rgb(cr, 0, 0, 0);
224 cairo_set_line_width (cr, 4);
226 fullscreen->pointer_x - 10,
227 fullscreen->pointer_y - 10);
229 fullscreen->pointer_x + 10,
230 fullscreen->pointer_y + 10);
234 fullscreen->pointer_x + 10,
235 fullscreen->pointer_y - 10);
237 fullscreen->pointer_x - 10,
238 fullscreen->pointer_y + 10);
246 key_handler(struct window *window, struct input *input, uint32_t time,
247 uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
250 struct fullscreen *fullscreen = data;
251 int transform, scale;
252 static int current_size = 0;
253 struct fs_output *fsout;
254 struct wl_output *wl_output;
255 int widths[] = { 640, 320, 800, 400 };
256 int heights[] = { 480, 240, 600, 300 };
258 if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
263 transform = window_get_buffer_transform (window);
264 transform = (transform + 1) % 8;
265 window_set_buffer_transform(window, transform);
266 window_schedule_redraw(window);
270 scale = window_get_buffer_scale (window);
275 window_set_buffer_scale(window, scale);
276 window_schedule_redraw(window);
280 current_size = (current_size + 1) % 4;
281 fullscreen->width = widths[current_size];
282 fullscreen->height = heights[current_size];
283 window_schedule_resize(fullscreen->window,
284 fullscreen->width, fullscreen->height);
288 if (!fullscreen->fshell)
292 if (fullscreen->current_output)
293 wl_output = output_get_wl_output(fullscreen->current_output->output);
294 fullscreen->present_method = (fullscreen->present_method + 1) % 5;
295 _wl_fullscreen_shell_present_surface(fullscreen->fshell,
296 window_get_wl_surface(fullscreen->window),
297 fullscreen->present_method,
299 window_schedule_redraw(window);
303 if (!fullscreen->fshell)
306 fsout = fullscreen->current_output;
307 wl_output = fsout ? output_get_wl_output(fsout->output) : NULL;
309 /* Clear the current presentation */
310 _wl_fullscreen_shell_present_surface(fullscreen->fshell, NULL,
313 if (fullscreen->current_output) {
314 if (fullscreen->current_output->link.next == &fullscreen->output_list)
317 fsout = wl_container_of(fullscreen->current_output->link.next,
320 fsout = wl_container_of(fullscreen->output_list.next,
324 fullscreen->current_output = fsout;
325 wl_output = fsout ? output_get_wl_output(fsout->output) : NULL;
326 _wl_fullscreen_shell_present_surface(fullscreen->fshell,
327 window_get_wl_surface(fullscreen->window),
328 fullscreen->present_method,
330 window_schedule_redraw(window);
334 if (!fullscreen->fshell || !fullscreen->current_output)
338 if (fullscreen->current_output)
339 wl_output = output_get_wl_output(fullscreen->current_output->output);
340 _wl_fullscreen_shell_mode_feedback_destroy(
341 _wl_fullscreen_shell_present_surface_for_mode(fullscreen->fshell,
342 window_get_wl_surface(fullscreen->window),
344 window_schedule_redraw(window);
348 if (fullscreen->fshell)
350 fullscreen->fullscreen ^= 1;
351 window_set_fullscreen(window, fullscreen->fullscreen);
361 motion_handler(struct widget *widget,
367 struct fullscreen *fullscreen = data;
369 fullscreen->pointer_x = x;
370 fullscreen->pointer_y = y;
372 widget_schedule_redraw(widget);
374 return fullscreen->draw_cursor ? CURSOR_BLANK : CURSOR_LEFT_PTR;
378 enter_handler(struct widget *widget,
380 float x, float y, void *data)
382 struct fullscreen *fullscreen = data;
384 fullscreen->pointer_x = x;
385 fullscreen->pointer_y = y;
387 widget_schedule_redraw(widget);
389 return fullscreen->draw_cursor ? CURSOR_BLANK : CURSOR_LEFT_PTR;
393 button_handler(struct widget *widget,
394 struct input *input, uint32_t time,
395 uint32_t button, enum wl_pointer_button_state state, void *data)
397 struct fullscreen *fullscreen = data;
401 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
402 window_move(fullscreen->window, input,
403 display_get_serial(fullscreen->display));
406 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
407 window_show_frame_menu(fullscreen->window, input, time);
413 touch_handler(struct widget *widget, struct input *input,
414 uint32_t serial, uint32_t time, int32_t id,
415 float x, float y, void *data)
417 struct fullscreen *fullscreen = data;
418 window_move(fullscreen->window, input, display_get_serial(fullscreen->display));
422 fshell_capability_handler(void *data, struct _wl_fullscreen_shell *fshell,
425 struct fullscreen *fullscreen = data;
427 switch (capability) {
428 case _WL_FULLSCREEN_SHELL_CAPABILITY_CURSOR_PLANE:
429 fullscreen->draw_cursor = 0;
436 struct _wl_fullscreen_shell_listener fullscreen_shell_listener = {
437 fshell_capability_handler
441 usage(int error_code)
443 fprintf(stderr, "Usage: fullscreen [OPTIONS]\n\n"
444 " -w <width>\tSet window width to <width>\n"
445 " -h <height>\tSet window height to <height>\n"
446 " --help\tShow this help text\n\n");
452 output_handler(struct output *output, void *data)
454 struct fullscreen *fullscreen = data;
455 struct fs_output *fsout;
457 /* If we've already seen this one, don't add it to the list */
458 wl_list_for_each(fsout, &fullscreen->output_list, link)
459 if (fsout->output == output)
462 fsout = calloc(1, sizeof *fsout);
463 fsout->output = output;
464 wl_list_insert(&fullscreen->output_list, &fsout->link);
468 global_handler(struct display *display, uint32_t id, const char *interface,
469 uint32_t version, void *data)
471 struct fullscreen *fullscreen = data;
473 if (strcmp(interface, "_wl_fullscreen_shell") == 0) {
474 fullscreen->fshell = display_bind(display, id,
475 &_wl_fullscreen_shell_interface,
477 _wl_fullscreen_shell_add_listener(fullscreen->fshell,
478 &fullscreen_shell_listener,
483 int main(int argc, char *argv[])
485 struct fullscreen fullscreen;
489 fullscreen.width = 640;
490 fullscreen.height = 480;
491 fullscreen.fullscreen = 0;
492 fullscreen.present_method = _WL_FULLSCREEN_SHELL_PRESENT_METHOD_DEFAULT;
493 wl_list_init(&fullscreen.output_list);
494 fullscreen.current_output = NULL;
496 for (i = 1; i < argc; i++) {
497 if (strcmp(argv[i], "-w") == 0) {
501 fullscreen.width = atol(argv[i]);
502 } else if (strcmp(argv[i], "-h") == 0) {
506 fullscreen.height = atol(argv[i]);
507 } else if (strcmp(argv[i], "--help") == 0)
513 d = display_create(&argc, argv);
515 fprintf(stderr, "failed to create display: %m\n");
519 fullscreen.display = d;
520 fullscreen.fshell = NULL;
521 display_set_user_data(fullscreen.display, &fullscreen);
522 display_set_global_handler(fullscreen.display, global_handler);
523 display_set_output_configure_handler(fullscreen.display, output_handler);
525 if (fullscreen.fshell) {
526 fullscreen.window = window_create_custom(d);
527 _wl_fullscreen_shell_present_surface(fullscreen.fshell,
528 window_get_wl_surface(fullscreen.window),
529 fullscreen.present_method,
531 /* If we get the CURSOR_PLANE capability, we'll change this */
532 fullscreen.draw_cursor = 1;
534 fullscreen.window = window_create(d);
535 fullscreen.draw_cursor = 0;
539 window_add_widget(fullscreen.window, &fullscreen);
541 window_set_title(fullscreen.window, "Fullscreen");
543 widget_set_transparent(fullscreen.widget, 0);
545 widget_set_default_cursor(fullscreen.widget, CURSOR_LEFT_PTR);
546 widget_set_redraw_handler(fullscreen.widget, redraw_handler);
547 widget_set_button_handler(fullscreen.widget, button_handler);
548 widget_set_motion_handler(fullscreen.widget, motion_handler);
549 widget_set_enter_handler(fullscreen.widget, enter_handler);
551 widget_set_touch_down_handler(fullscreen.widget, touch_handler);
553 window_set_key_handler(fullscreen.window, key_handler);
554 window_set_fullscreen_handler(fullscreen.window, fullscreen_handler);
556 window_set_user_data(fullscreen.window, &fullscreen);
557 /* Hack to set minimum allocation so we can shrink later */
558 window_schedule_resize(fullscreen.window,
560 window_schedule_resize(fullscreen.window,
561 fullscreen.width, fullscreen.height);
565 widget_destroy(fullscreen.widget);
566 window_destroy(fullscreen.window);