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;
53 int focussed, draw_cursor;
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 resize_handler(struct widget *widget, int width, int height, void *data)
71 struct fullscreen *fullscreen = data;
73 widget_set_size(widget, fullscreen->width, fullscreen->height);
77 draw_string(cairo_t *cr,
83 cairo_text_extents_t text_extents;
84 cairo_font_extents_t font_extents;
88 cairo_select_font_face(cr, "sans",
89 CAIRO_FONT_SLANT_NORMAL,
90 CAIRO_FONT_WEIGHT_NORMAL);
91 cairo_set_font_size(cr, 14);
93 cairo_font_extents (cr, &font_extents);
97 vsnprintf(buffer, sizeof(buffer), fmt, argp);
101 end = strchr(p, '\n');
105 cairo_show_text(cr, p);
106 cairo_text_extents (cr, p, &text_extents);
107 cairo_rel_move_to (cr, -text_extents.x_advance, font_extents.height);
122 redraw_handler(struct widget *widget, void *data)
124 struct fullscreen *fullscreen = data;
125 struct rectangle allocation;
126 cairo_surface_t *surface;
130 const char *method_name[] = { "default", "center", "zoom", "zoom_crop", "stretch"};
132 surface = window_get_surface(fullscreen->window);
133 if (surface == NULL ||
134 cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
135 fprintf(stderr, "failed to create cairo egl surface\n");
139 widget_get_allocation(fullscreen->widget, &allocation);
141 cr = widget_cairo_create(widget);
143 cairo_set_source_rgb(cr, 0, 0, 0);
146 cairo_set_source_rgb(cr, 0, 0, 1);
147 cairo_set_line_width (cr, 10);
148 cairo_rectangle(cr, 5, 5, allocation.width - 10, allocation.height - 10);
154 cairo_set_source_rgb(cr, 1, 1, 1);
156 if (fullscreen->fshell) {
158 "Surface size: %d, %d\n"
159 "Scale: %d, transform: %d\n"
161 "Output: %s, present method: %s\n"
162 "Keys: (s)cale, (t)ransform, si(z)e, (m)ethod,\n"
163 " (o)utput, modes(w)itch, (q)uit\n",
164 fullscreen->width, fullscreen->height,
165 window_get_buffer_scale (fullscreen->window),
166 window_get_buffer_transform (fullscreen->window),
167 fullscreen->pointer_x, fullscreen->pointer_y,
168 method_name[fullscreen->present_method],
169 fullscreen->current_output ? output_get_model(fullscreen->current_output->output): "null");
172 "Surface size: %d, %d\n"
173 "Scale: %d, transform: %d\n"
176 "Keys: (s)cale, (t)ransform, si(z)e, (f)ullscreen, (q)uit\n",
177 fullscreen->width, fullscreen->height,
178 window_get_buffer_scale (fullscreen->window),
179 window_get_buffer_transform (fullscreen->window),
180 fullscreen->pointer_x, fullscreen->pointer_y,
181 fullscreen->fullscreen);
186 while (y + 60 < fullscreen->height) {
187 border = (i++ % 2 == 0) ? 1 : 0.5;
190 cairo_set_line_width (cr, border);
191 while (x + 70 < fullscreen->width) {
192 if (fullscreen->focussed &&
193 fullscreen->pointer_x >= x && fullscreen->pointer_x < x + 50 &&
194 fullscreen->pointer_y >= y && fullscreen->pointer_y < y + 40) {
195 cairo_set_source_rgb(cr, 1, 0, 0);
201 cairo_set_source_rgb(cr, 0, 1, 0);
203 x + border/2.0, y + border/2.0,
212 if (fullscreen->focussed && fullscreen->draw_cursor) {
213 cairo_set_source_rgb(cr, 1, 1, 1);
214 cairo_set_line_width (cr, 8);
216 fullscreen->pointer_x - 12,
217 fullscreen->pointer_y - 12);
219 fullscreen->pointer_x + 12,
220 fullscreen->pointer_y + 12);
224 fullscreen->pointer_x + 12,
225 fullscreen->pointer_y - 12);
227 fullscreen->pointer_x - 12,
228 fullscreen->pointer_y + 12);
231 cairo_set_source_rgb(cr, 0, 0, 0);
232 cairo_set_line_width (cr, 4);
234 fullscreen->pointer_x - 10,
235 fullscreen->pointer_y - 10);
237 fullscreen->pointer_x + 10,
238 fullscreen->pointer_y + 10);
242 fullscreen->pointer_x + 10,
243 fullscreen->pointer_y - 10);
245 fullscreen->pointer_x - 10,
246 fullscreen->pointer_y + 10);
254 key_handler(struct window *window, struct input *input, uint32_t time,
255 uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
258 struct fullscreen *fullscreen = data;
259 int transform, scale;
260 static int current_size = 0;
261 struct fs_output *fsout;
262 struct wl_output *wl_output;
263 int widths[] = { 640, 320, 800, 400 };
264 int heights[] = { 480, 240, 600, 300 };
266 if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
271 transform = window_get_buffer_transform (window);
272 transform = (transform + 1) % 8;
273 window_set_buffer_transform(window, transform);
274 window_schedule_redraw(window);
278 scale = window_get_buffer_scale (window);
283 window_set_buffer_scale(window, scale);
284 window_schedule_redraw(window);
288 current_size = (current_size + 1) % 4;
289 fullscreen->width = widths[current_size];
290 fullscreen->height = heights[current_size];
291 window_schedule_resize(fullscreen->window,
292 fullscreen->width, fullscreen->height);
296 if (!fullscreen->fshell)
300 if (fullscreen->current_output)
301 wl_output = output_get_wl_output(fullscreen->current_output->output);
302 fullscreen->present_method = (fullscreen->present_method + 1) % 5;
303 _wl_fullscreen_shell_present_surface(fullscreen->fshell,
304 window_get_wl_surface(fullscreen->window),
305 fullscreen->present_method,
307 window_schedule_redraw(window);
311 if (!fullscreen->fshell)
314 fsout = fullscreen->current_output;
315 wl_output = fsout ? output_get_wl_output(fsout->output) : NULL;
317 /* Clear the current presentation */
318 _wl_fullscreen_shell_present_surface(fullscreen->fshell, NULL,
321 if (fullscreen->current_output) {
322 if (fullscreen->current_output->link.next == &fullscreen->output_list)
325 fsout = wl_container_of(fullscreen->current_output->link.next,
328 fsout = wl_container_of(fullscreen->output_list.next,
332 fullscreen->current_output = fsout;
333 wl_output = fsout ? output_get_wl_output(fsout->output) : NULL;
334 _wl_fullscreen_shell_present_surface(fullscreen->fshell,
335 window_get_wl_surface(fullscreen->window),
336 fullscreen->present_method,
338 window_schedule_redraw(window);
342 if (!fullscreen->fshell || !fullscreen->current_output)
346 if (fullscreen->current_output)
347 wl_output = output_get_wl_output(fullscreen->current_output->output);
348 _wl_fullscreen_shell_mode_feedback_destroy(
349 _wl_fullscreen_shell_present_surface_for_mode(fullscreen->fshell,
350 window_get_wl_surface(fullscreen->window),
352 window_schedule_redraw(window);
356 if (fullscreen->fshell)
358 fullscreen->fullscreen ^= 1;
359 window_set_fullscreen(window, fullscreen->fullscreen);
369 motion_handler(struct widget *widget,
375 struct fullscreen *fullscreen = data;
377 fullscreen->pointer_x = x;
378 fullscreen->pointer_y = y;
380 widget_schedule_redraw(widget);
382 return fullscreen->draw_cursor ? CURSOR_BLANK : CURSOR_LEFT_PTR;
386 enter_handler(struct widget *widget,
388 float x, float y, void *data)
390 struct fullscreen *fullscreen = data;
392 fullscreen->focussed++;
394 fullscreen->pointer_x = x;
395 fullscreen->pointer_y = y;
397 widget_schedule_redraw(widget);
399 return fullscreen->draw_cursor ? CURSOR_BLANK : CURSOR_LEFT_PTR;
403 leave_handler(struct widget *widget,
404 struct input *input, void *data)
406 struct fullscreen *fullscreen = data;
408 fullscreen->focussed--;
410 widget_schedule_redraw(widget);
414 button_handler(struct widget *widget,
415 struct input *input, uint32_t time,
416 uint32_t button, enum wl_pointer_button_state state, void *data)
418 struct fullscreen *fullscreen = data;
422 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
423 window_move(fullscreen->window, input,
424 display_get_serial(fullscreen->display));
427 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
428 window_show_frame_menu(fullscreen->window, input, time);
434 touch_handler(struct widget *widget, struct input *input,
435 uint32_t serial, uint32_t time, int32_t id,
436 float x, float y, void *data)
438 struct fullscreen *fullscreen = data;
439 window_move(fullscreen->window, input, display_get_serial(fullscreen->display));
443 fshell_capability_handler(void *data, struct _wl_fullscreen_shell *fshell,
446 struct fullscreen *fullscreen = data;
448 switch (capability) {
449 case _WL_FULLSCREEN_SHELL_CAPABILITY_CURSOR_PLANE:
450 fullscreen->draw_cursor = 0;
457 struct _wl_fullscreen_shell_listener fullscreen_shell_listener = {
458 fshell_capability_handler
462 usage(int error_code)
464 fprintf(stderr, "Usage: fullscreen [OPTIONS]\n\n"
465 " -w <width>\tSet window width to <width>\n"
466 " -h <height>\tSet window height to <height>\n"
467 " --help\tShow this help text\n\n");
473 output_handler(struct output *output, void *data)
475 struct fullscreen *fullscreen = data;
476 struct fs_output *fsout;
478 /* If we've already seen this one, don't add it to the list */
479 wl_list_for_each(fsout, &fullscreen->output_list, link)
480 if (fsout->output == output)
483 fsout = calloc(1, sizeof *fsout);
484 fsout->output = output;
485 wl_list_insert(&fullscreen->output_list, &fsout->link);
489 global_handler(struct display *display, uint32_t id, const char *interface,
490 uint32_t version, void *data)
492 struct fullscreen *fullscreen = data;
494 if (strcmp(interface, "_wl_fullscreen_shell") == 0) {
495 fullscreen->fshell = display_bind(display, id,
496 &_wl_fullscreen_shell_interface,
498 _wl_fullscreen_shell_add_listener(fullscreen->fshell,
499 &fullscreen_shell_listener,
504 int main(int argc, char *argv[])
506 struct fullscreen fullscreen;
510 fullscreen.width = 640;
511 fullscreen.height = 480;
512 fullscreen.fullscreen = 0;
513 fullscreen.focussed = 0;
514 fullscreen.present_method = _WL_FULLSCREEN_SHELL_PRESENT_METHOD_DEFAULT;
515 wl_list_init(&fullscreen.output_list);
516 fullscreen.current_output = NULL;
518 for (i = 1; i < argc; i++) {
519 if (strcmp(argv[i], "-w") == 0) {
523 fullscreen.width = atol(argv[i]);
524 } else if (strcmp(argv[i], "-h") == 0) {
528 fullscreen.height = atol(argv[i]);
529 } else if (strcmp(argv[i], "--help") == 0)
535 d = display_create(&argc, argv);
537 fprintf(stderr, "failed to create display: %m\n");
541 fullscreen.display = d;
542 fullscreen.fshell = NULL;
543 display_set_user_data(fullscreen.display, &fullscreen);
544 display_set_global_handler(fullscreen.display, global_handler);
545 display_set_output_configure_handler(fullscreen.display, output_handler);
547 if (fullscreen.fshell) {
548 fullscreen.window = window_create_custom(d);
549 _wl_fullscreen_shell_present_surface(fullscreen.fshell,
550 window_get_wl_surface(fullscreen.window),
551 fullscreen.present_method,
553 /* If we get the CURSOR_PLANE capability, we'll change this */
554 fullscreen.draw_cursor = 1;
556 fullscreen.window = window_create(d);
557 fullscreen.draw_cursor = 0;
561 window_add_widget(fullscreen.window, &fullscreen);
563 window_set_title(fullscreen.window, "Fullscreen");
565 widget_set_transparent(fullscreen.widget, 0);
567 widget_set_default_cursor(fullscreen.widget, CURSOR_LEFT_PTR);
568 widget_set_resize_handler(fullscreen.widget, resize_handler);
569 widget_set_redraw_handler(fullscreen.widget, redraw_handler);
570 widget_set_button_handler(fullscreen.widget, button_handler);
571 widget_set_motion_handler(fullscreen.widget, motion_handler);
572 widget_set_enter_handler(fullscreen.widget, enter_handler);
573 widget_set_leave_handler(fullscreen.widget, leave_handler);
575 widget_set_touch_down_handler(fullscreen.widget, touch_handler);
577 window_set_key_handler(fullscreen.window, key_handler);
578 window_set_fullscreen_handler(fullscreen.window, fullscreen_handler);
580 window_set_user_data(fullscreen.window, &fullscreen);
581 /* Hack to set minimum allocation so we can shrink later */
582 window_schedule_resize(fullscreen.window,
584 window_schedule_resize(fullscreen.window,
585 fullscreen.width, fullscreen.height);