From 0ce245761c85e989f08e4136bd91b149156e82e0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 28 Jan 2011 15:18:33 -0500 Subject: [PATCH] Add initial basic support for fullscreen surfaces --- clients/terminal.c | 5 ++- clients/window.c | 48 ++++++++++++++++--------- compositor/compositor.c | 96 +++++++++++++++++++++++++++++++++++++++---------- compositor/compositor.h | 11 +++++- compositor/shell.c | 4 +++ protocol/wayland.xml | 10 ++++++ 6 files changed, 137 insertions(+), 37 deletions(-) diff --git a/clients/terminal.c b/clients/terminal.c index dfddb7f..3573382 100644 --- a/clients/terminal.c +++ b/clients/terminal.c @@ -1017,6 +1017,10 @@ resize_handler(struct window *window, height = (pixel_height - 2 * terminal->margin) / (int32_t) terminal->extents.height; + if (terminal->fullscreen) + window_set_child_size(terminal->window, + pixel_width, pixel_height); + terminal_resize(terminal, width, height); } @@ -2283,7 +2287,6 @@ terminal_create(struct display *display, int fullscreen) terminal->display = display; terminal->margin = 5; - window_set_fullscreen(terminal->window, terminal->fullscreen); window_set_user_data(terminal->window, terminal); window_set_redraw_handler(terminal->window, redraw_handler); window_set_resize_handler(terminal->window, resize_handler); diff --git a/clients/window.c b/clients/window.c index da9055c..955db66 100644 --- a/clients/window.c +++ b/clients/window.c @@ -99,7 +99,6 @@ struct window { struct input *keyboard_device; uint32_t name; enum window_buffer_type buffer_type; - int mapped; EGLImageKHR *image; cairo_surface_t *cairo_surface, *pending_surface; @@ -599,15 +598,14 @@ window_attach_surface(struct window *window) wl_surface_attach(window->surface, buffer, x, y); wl_display_sync_callback(display->display, free_surface, window); - if (!window->mapped) { - if (!window->parent) - wl_surface_map_toplevel(window->surface); - else - wl_surface_map_transient(window->surface, - window->parent->surface, - window->x, window->y, 0); - window->mapped = 1; - } + if (window->fullscreen) + wl_surface_map_fullscreen(window->surface); + else if (!window->parent) + wl_surface_map_toplevel(window->surface); + else + wl_surface_map_transient(window->surface, + window->parent->surface, + window->x, window->y, 0); wl_surface_damage(window->surface, 0, 0, window->allocation.width, @@ -1086,10 +1084,10 @@ handle_configure(void *data, struct wl_shell *shell, struct window *window = wl_surface_get_user_data(surface); int32_t child_width, child_height; - /* FIXME this is probably the wrong place to check for width or - height <= 0, but it prevents the compositor from crashing - */ - if(width <= 0 || height <= 0) + /* FIXME: this is probably the wrong place to check for width + * or height <= 0, but it prevents the compositor from crashing + */ + if (width <= 0 || height <= 0) return; window->resize_edges = edges; @@ -1118,7 +1116,7 @@ void window_get_child_allocation(struct window *window, struct rectangle *allocation) { - if (window->fullscreen && !window->decoration) { + if (window->fullscreen || !window->decoration) { *allocation = window->allocation; } else { allocation->x = window->margin + 10; @@ -1134,8 +1132,15 @@ void window_set_child_size(struct window *window, int32_t width, int32_t height) { if (!window->fullscreen) { + window->allocation.x = 20 + window->margin; + window->allocation.y = 60 + window->margin; window->allocation.width = width + 20 + window->margin * 2; window->allocation.height = height + 60 + window->margin * 2; + } else { + window->allocation.x = 0; + window->allocation.y = 0; + window->allocation.width = width; + window->allocation.height = height; } } @@ -1163,13 +1168,22 @@ window_schedule_redraw(struct window *window) void window_set_fullscreen(struct window *window, int fullscreen) { + int32_t width, height; + + if (window->fullscreen == fullscreen) + return; + window->fullscreen = fullscreen; if (window->fullscreen) { window->saved_allocation = window->allocation; - window->allocation = window->display->screen_allocation; + width = window->display->screen_allocation.width; + height = window->display->screen_allocation.height; } else { - window->allocation = window->saved_allocation; + width = window->saved_allocation.width - 20 - window->margin * 2; + height = window->saved_allocation.height - 60 - window->margin * 2; } + + (*window->resize_handler)(window, width, height, window->user_data); } void diff --git a/compositor/compositor.c b/compositor/compositor.c index b6cdbe6..80a972e 100644 --- a/compositor/compositor.c +++ b/compositor/compositor.c @@ -131,7 +131,7 @@ wlsc_surface_create(struct wlsc_compositor *compositor, wl_list_init(&surface->surface.destroy_listener_list); wl_list_init(&surface->link); - surface->mapped = 0; + surface->map_type = WLSC_SURFACE_MAP_UNMAPPED; glGenTextures(1, &surface->texture); glBindTexture(GL_TEXTURE_2D, surface->texture); @@ -403,13 +403,21 @@ wlsc_output_repaint(struct wlsc_output *output) glViewport(0, 0, output->width, output->height); - if (output->background) - wlsc_surface_draw(output->background, output); - else - glClear(GL_COLOR_BUFFER_BIT); - - wl_list_for_each_reverse(es, &ec->surface_list, link) + es = container_of(ec->surface_list.next, struct wlsc_surface, link); + if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN && + es->fullscreen_output == output) { + if (es->width < output->width || es->height < output->height) + glClear(GL_COLOR_BUFFER_BIT); wlsc_surface_draw(es, output); + } else { + if (output->background) + wlsc_surface_draw(output->background, output); + else + glClear(GL_COLOR_BUFFER_BIT); + + wl_list_for_each_reverse(es, &ec->surface_list, link) + wlsc_surface_draw(es, output); + } if (ec->focus) wl_list_for_each(eid, &ec->input_device_list, link) @@ -475,16 +483,27 @@ surface_map_toplevel(struct wl_client *client, { struct wlsc_surface *es = (struct wlsc_surface *) surface; - if (es->mapped) + switch (es->map_type) { + case WLSC_SURFACE_MAP_UNMAPPED: + es->x = 10 + random() % 400; + es->y = 10 + random() % 400; + wlsc_surface_update_matrix(es); + wl_list_insert(&es->compositor->surface_list, &es->link); + break; + case WLSC_SURFACE_MAP_TOPLEVEL: return; + case WLSC_SURFACE_MAP_FULLSCREEN: + es->fullscreen_output = NULL; + es->x = es->saved_x; + es->y = es->saved_y; + wlsc_surface_update_matrix(es); + break; + default: + break; + } - es->x = 10 + random() % 400; - es->y = 10 + random() % 400; - - wlsc_surface_update_matrix(es); - wl_list_insert(&es->compositor->surface_list, &es->link); wlsc_compositor_schedule_repaint(es->compositor); - es->mapped = 1; + es->map_type = WLSC_SURFACE_MAP_TOPLEVEL; } static void @@ -495,16 +514,56 @@ surface_map_transient(struct wl_client *client, struct wlsc_surface *es = (struct wlsc_surface *) surface; struct wlsc_surface *pes = (struct wlsc_surface *) parent; - if (es->mapped) - return; + switch (es->map_type) { + case WLSC_SURFACE_MAP_UNMAPPED: + wl_list_insert(&es->compositor->surface_list, &es->link); + break; + case WLSC_SURFACE_MAP_FULLSCREEN: + es->fullscreen_output = NULL; + break; + default: + break; + } es->x = pes->x + x; es->y = pes->y + y; wlsc_surface_update_matrix(es); - wl_list_insert(&es->compositor->surface_list, &es->link); wlsc_compositor_schedule_repaint(es->compositor); - es->mapped = 1; + es->map_type = WLSC_SURFACE_MAP_TRANSIENT; +} + +static void +surface_map_fullscreen(struct wl_client *client, struct wl_surface *surface) +{ + struct wlsc_surface *es = (struct wlsc_surface *) surface; + struct wlsc_output *output; + + switch (es->map_type) { + case WLSC_SURFACE_MAP_UNMAPPED: + es->x = 10 + random() % 400; + es->y = 10 + random() % 400; + wl_list_insert(&es->compositor->surface_list, &es->link); + break; + case WLSC_SURFACE_MAP_FULLSCREEN: + return; + default: + break; + } + + /* FIXME: Fullscreen on first output */ + /* FIXME: Handle output going away */ + output = container_of(es->compositor->output_list.next, + struct wlsc_output, link); + + es->saved_x = es->x; + es->saved_y = es->y; + es->x = (output->width - es->width) / 2; + es->y = (output->height - es->height) / 2; + es->fullscreen_output = output; + wlsc_surface_update_matrix(es); + wlsc_compositor_schedule_repaint(es->compositor); + es->map_type = WLSC_SURFACE_MAP_FULLSCREEN; } static void @@ -523,6 +582,7 @@ const static struct wl_surface_interface surface_interface = { surface_attach, surface_map_toplevel, surface_map_transient, + surface_map_fullscreen, surface_damage }; diff --git a/compositor/compositor.h b/compositor/compositor.h index 3418b53..8127b5d 100644 --- a/compositor/compositor.h +++ b/compositor/compositor.h @@ -130,17 +130,26 @@ struct wlsc_vector { GLfloat f[4]; }; +enum wlsc_surface_map_type { + WLSC_SURFACE_MAP_UNMAPPED, + WLSC_SURFACE_MAP_TOPLEVEL, + WLSC_SURFACE_MAP_TRANSIENT, + WLSC_SURFACE_MAP_FULLSCREEN +}; + struct wlsc_surface { struct wl_surface surface; struct wlsc_compositor *compositor; GLuint texture; int32_t x, y, width, height; + int32_t saved_x, saved_y; struct wl_list link; struct wlsc_matrix matrix; struct wlsc_matrix matrix_inv; struct wl_visual *visual; struct wl_buffer *buffer; - int mapped; + enum wlsc_surface_map_type map_type; + struct wlsc_output *fullscreen_output; }; void diff --git a/compositor/shell.c b/compositor/shell.c index 2699b22..1ff32e9 100644 --- a/compositor/shell.c +++ b/compositor/shell.c @@ -80,6 +80,8 @@ shell_move(struct wl_client *client, struct wl_shell *shell, struct wlsc_surface *es = (struct wlsc_surface *) surface; struct wlsc_move_grab *move; + /* FIXME: Reject if fullscreen */ + move = malloc(sizeof *move); if (!move) { wl_client_post_no_memory(client); @@ -174,6 +176,8 @@ shell_resize(struct wl_client *client, struct wl_shell *shell, enum wlsc_pointer_type pointer = WLSC_POINTER_LEFT_PTR; struct wlsc_surface *es = (struct wlsc_surface *) surface; + /* FIXME: Reject if fullscreen */ + resize = malloc(sizeof *resize); if (!resize) { wl_client_post_no_memory(client); diff --git a/protocol/wayland.xml b/protocol/wayland.xml index 13c71bd..a9f96b6 100644 --- a/protocol/wayland.xml +++ b/protocol/wayland.xml @@ -368,6 +368,16 @@ + + +