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) /
(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);

@ -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

@ -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
};

@ -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

@ -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);

@ -368,6 +368,16 @@
<arg name="flags" type="uint"/>
</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
changed, and request a redraw. The arguments allow you to
damage only a part of the surface, but the server may ignore

Loading…
Cancel
Save