Add initial basic support for fullscreen surfaces

dev
Kristian Høgsberg 14 years ago
parent 5e4d83f499
commit 0ce245761c
  1. 5
      clients/terminal.c
  2. 48
      clients/window.c
  3. 96
      compositor/compositor.c
  4. 11
      compositor/compositor.h
  5. 4
      compositor/shell.c
  6. 10
      protocol/wayland.xml

@ -1017,6 +1017,10 @@ resize_handler(struct window *window,
height = (pixel_height - 2 * terminal->margin) / height = (pixel_height - 2 * terminal->margin) /
(int32_t) terminal->extents.height; (int32_t) terminal->extents.height;
if (terminal->fullscreen)
window_set_child_size(terminal->window,
pixel_width, pixel_height);
terminal_resize(terminal, width, height); terminal_resize(terminal, width, height);
} }
@ -2283,7 +2287,6 @@ terminal_create(struct display *display, int fullscreen)
terminal->display = display; terminal->display = display;
terminal->margin = 5; terminal->margin = 5;
window_set_fullscreen(terminal->window, terminal->fullscreen);
window_set_user_data(terminal->window, terminal); window_set_user_data(terminal->window, terminal);
window_set_redraw_handler(terminal->window, redraw_handler); window_set_redraw_handler(terminal->window, redraw_handler);
window_set_resize_handler(terminal->window, resize_handler); window_set_resize_handler(terminal->window, resize_handler);

@ -99,7 +99,6 @@ struct window {
struct input *keyboard_device; struct input *keyboard_device;
uint32_t name; uint32_t name;
enum window_buffer_type buffer_type; enum window_buffer_type buffer_type;
int mapped;
EGLImageKHR *image; EGLImageKHR *image;
cairo_surface_t *cairo_surface, *pending_surface; 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_surface_attach(window->surface, buffer, x, y);
wl_display_sync_callback(display->display, free_surface, window); wl_display_sync_callback(display->display, free_surface, window);
if (!window->mapped) { if (window->fullscreen)
if (!window->parent) wl_surface_map_fullscreen(window->surface);
wl_surface_map_toplevel(window->surface); else if (!window->parent)
else wl_surface_map_toplevel(window->surface);
wl_surface_map_transient(window->surface, else
window->parent->surface, wl_surface_map_transient(window->surface,
window->x, window->y, 0); window->parent->surface,
window->mapped = 1; window->x, window->y, 0);
}
wl_surface_damage(window->surface, 0, 0, wl_surface_damage(window->surface, 0, 0,
window->allocation.width, window->allocation.width,
@ -1086,10 +1084,10 @@ handle_configure(void *data, struct wl_shell *shell,
struct window *window = wl_surface_get_user_data(surface); struct window *window = wl_surface_get_user_data(surface);
int32_t child_width, child_height; int32_t child_width, child_height;
/* FIXME this is probably the wrong place to check for width or /* FIXME: this is probably the wrong place to check for width
height <= 0, but it prevents the compositor from crashing * or height <= 0, but it prevents the compositor from crashing
*/ */
if(width <= 0 || height <= 0) if (width <= 0 || height <= 0)
return; return;
window->resize_edges = edges; window->resize_edges = edges;
@ -1118,7 +1116,7 @@ void
window_get_child_allocation(struct window *window, window_get_child_allocation(struct window *window,
struct rectangle *allocation) struct rectangle *allocation)
{ {
if (window->fullscreen && !window->decoration) { if (window->fullscreen || !window->decoration) {
*allocation = window->allocation; *allocation = window->allocation;
} else { } else {
allocation->x = window->margin + 10; allocation->x = window->margin + 10;
@ -1134,8 +1132,15 @@ void
window_set_child_size(struct window *window, int32_t width, int32_t height) window_set_child_size(struct window *window, int32_t width, int32_t height)
{ {
if (!window->fullscreen) { 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.width = width + 20 + window->margin * 2;
window->allocation.height = height + 60 + 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 void
window_set_fullscreen(struct window *window, int fullscreen) window_set_fullscreen(struct window *window, int fullscreen)
{ {
int32_t width, height;
if (window->fullscreen == fullscreen)
return;
window->fullscreen = fullscreen; window->fullscreen = fullscreen;
if (window->fullscreen) { if (window->fullscreen) {
window->saved_allocation = window->allocation; window->saved_allocation = window->allocation;
window->allocation = window->display->screen_allocation; width = window->display->screen_allocation.width;
height = window->display->screen_allocation.height;
} else { } 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 void

@ -131,7 +131,7 @@ wlsc_surface_create(struct wlsc_compositor *compositor,
wl_list_init(&surface->surface.destroy_listener_list); wl_list_init(&surface->surface.destroy_listener_list);
wl_list_init(&surface->link); wl_list_init(&surface->link);
surface->mapped = 0; surface->map_type = WLSC_SURFACE_MAP_UNMAPPED;
glGenTextures(1, &surface->texture); glGenTextures(1, &surface->texture);
glBindTexture(GL_TEXTURE_2D, 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); glViewport(0, 0, output->width, output->height);
if (output->background) es = container_of(ec->surface_list.next, struct wlsc_surface, link);
wlsc_surface_draw(output->background, output); if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN &&
else es->fullscreen_output == output) {
glClear(GL_COLOR_BUFFER_BIT); if (es->width < output->width || es->height < output->height)
glClear(GL_COLOR_BUFFER_BIT);
wl_list_for_each_reverse(es, &ec->surface_list, link)
wlsc_surface_draw(es, output); 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) if (ec->focus)
wl_list_for_each(eid, &ec->input_device_list, link) 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; 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; 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); wlsc_compositor_schedule_repaint(es->compositor);
es->mapped = 1; es->map_type = WLSC_SURFACE_MAP_TOPLEVEL;
} }
static void static void
@ -495,16 +514,56 @@ surface_map_transient(struct wl_client *client,
struct wlsc_surface *es = (struct wlsc_surface *) surface; struct wlsc_surface *es = (struct wlsc_surface *) surface;
struct wlsc_surface *pes = (struct wlsc_surface *) parent; struct wlsc_surface *pes = (struct wlsc_surface *) parent;
if (es->mapped) switch (es->map_type) {
return; 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->x = pes->x + x;
es->y = pes->y + y; es->y = pes->y + y;
wlsc_surface_update_matrix(es); wlsc_surface_update_matrix(es);
wl_list_insert(&es->compositor->surface_list, &es->link);
wlsc_compositor_schedule_repaint(es->compositor); 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 static void
@ -523,6 +582,7 @@ const static struct wl_surface_interface surface_interface = {
surface_attach, surface_attach,
surface_map_toplevel, surface_map_toplevel,
surface_map_transient, surface_map_transient,
surface_map_fullscreen,
surface_damage surface_damage
}; };

@ -130,17 +130,26 @@ struct wlsc_vector {
GLfloat f[4]; 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 wlsc_surface {
struct wl_surface surface; struct wl_surface surface;
struct wlsc_compositor *compositor; struct wlsc_compositor *compositor;
GLuint texture; GLuint texture;
int32_t x, y, width, height; int32_t x, y, width, height;
int32_t saved_x, saved_y;
struct wl_list link; struct wl_list link;
struct wlsc_matrix matrix; struct wlsc_matrix matrix;
struct wlsc_matrix matrix_inv; struct wlsc_matrix matrix_inv;
struct wl_visual *visual; struct wl_visual *visual;
struct wl_buffer *buffer; struct wl_buffer *buffer;
int mapped; enum wlsc_surface_map_type map_type;
struct wlsc_output *fullscreen_output;
}; };
void void

@ -80,6 +80,8 @@ shell_move(struct wl_client *client, struct wl_shell *shell,
struct wlsc_surface *es = (struct wlsc_surface *) surface; struct wlsc_surface *es = (struct wlsc_surface *) surface;
struct wlsc_move_grab *move; struct wlsc_move_grab *move;
/* FIXME: Reject if fullscreen */
move = malloc(sizeof *move); move = malloc(sizeof *move);
if (!move) { if (!move) {
wl_client_post_no_memory(client); 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; enum wlsc_pointer_type pointer = WLSC_POINTER_LEFT_PTR;
struct wlsc_surface *es = (struct wlsc_surface *) surface; struct wlsc_surface *es = (struct wlsc_surface *) surface;
/* FIXME: Reject if fullscreen */
resize = malloc(sizeof *resize); resize = malloc(sizeof *resize);
if (!resize) { if (!resize) {
wl_client_post_no_memory(client); wl_client_post_no_memory(client);

@ -368,6 +368,16 @@
<arg name="flags" type="uint"/> <arg name="flags" type="uint"/>
</request> </request>
<!-- Map the surface as a fullscreen surface. There are a number
of options here: on which output? if the surface size doesn't
match the output size, do we scale, change resolution, or add
black borders? is that something the client controls? what
about transient surfaces, do they float on top of the
fullscreen? what if there's already a fullscreen surface on
the output, maybe you can only go fullscreen if you're
active? -->
<request name="map_fullscreen"/>
<!-- Notify the server that the attached buffer's contents have <!-- Notify the server that the attached buffer's contents have
changed, and request a redraw. The arguments allow you to changed, and request a redraw. The arguments allow you to
damage only a part of the surface, but the server may ignore damage only a part of the surface, but the server may ignore

Loading…
Cancel
Save