From e9568c17bbae5ad70d2b7d33299139a3cc4193ac Mon Sep 17 00:00:00 2001 From: Nobuhiko Tanibata Date: Tue, 19 Aug 2014 17:33:02 +0900 Subject: Latest branch in weston 1.5.0 commit: 61917c84e3fcbb71da806a5e94a82916d77e18b1 Signed-off-by: Nobuhiko Tanibata --- Makefile.am | 14 + clients/cliptest.c | 13 +- clients/desktop-shell.c | 40 +- clients/dnd.c | 11 + clients/editor.c | 3 + clients/flower.c | 4 + clients/fullscreen.c | 34 +- clients/gears.c | 25 +- clients/image.c | 2 + clients/nested.c | 9 +- clients/resizor.c | 3 +- clients/scaler.c | 3 + clients/simple-damage.c | 880 ++++++++++++++++++++++++++++++++++++ clients/simple-egl.c | 99 ++-- clients/simple-shm.c | 25 +- clients/smoke.c | 4 + clients/stacking.c | 11 +- clients/terminal.c | 94 +++- clients/transformed.c | 3 + clients/weston-info.c | 89 +++- clients/window.c | 380 +++++++++------- clients/window.h | 20 +- configure.ac | 9 +- desktop-shell/exposay.c | 8 +- desktop-shell/input-panel.c | 8 +- desktop-shell/shell.c | 562 +++++++++++++---------- desktop-shell/shell.h | 1 + fullscreen-shell/fullscreen-shell.c | 4 +- m4/.gitignore | 5 + man/weston.ini.man | 22 + patch.sh | 30 -- protocol/xdg-shell.xml | 223 ++++----- releasing.txt | 43 ++ shared/frame.c | 5 +- src/animation.c | 16 +- src/compositor-drm.c | 41 +- src/compositor-rdp.c | 156 +++++-- src/compositor-wayland.c | 31 +- src/compositor.c | 561 +++++++++++++---------- src/compositor.h | 167 +++---- src/data-device.c | 48 +- src/gl-renderer.c | 2 +- src/input.c | 16 +- src/libinput-device.c | 52 ++- src/libinput-seat.c | 32 +- src/pixman-renderer.c | 2 +- src/screen-share.c | 44 +- src/screenshooter.c | 2 +- src/spring-tool.c | 5 + src/text-backend.c | 2 - tests/bad-buffer-test.c | 35 +- tests/subsurface-test.c | 40 +- tests/weston-test-client-helper.c | 57 ++- tests/weston-test-client-helper.h | 10 +- tests/weston-test.c | 6 +- weston.ini.in | 10 +- xwayland/launcher.c | 6 +- xwayland/window-manager.c | 28 +- 58 files changed, 2833 insertions(+), 1222 deletions(-) create mode 100644 clients/simple-damage.c create mode 100644 m4/.gitignore delete mode 100755 patch.sh create mode 100644 releasing.txt diff --git a/Makefile.am b/Makefile.am index 343adc6c..191dcc9e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,5 @@ +ACLOCAL_AMFLAGS = -I m4 + bin_PROGRAMS = noinst_PROGRAMS = libexec_PROGRAMS = @@ -386,6 +388,7 @@ endif if BUILD_SIMPLE_CLIENTS demo_clients += \ weston-simple-shm \ + weston-simple-damage \ weston-simple-touch \ weston-multi-resource @@ -398,6 +401,17 @@ nodist_weston_simple_shm_SOURCES = \ weston_simple_shm_CFLAGS = $(AM_CFLAGS) $(SIMPLE_CLIENT_CFLAGS) weston_simple_shm_LDADD = $(SIMPLE_CLIENT_LIBS) libshared.la +weston_simple_damage_SOURCES = clients/simple-damage.c +nodist_weston_simple_damage_SOURCES = \ + protocol/scaler-protocol.c \ + protocol/scaler-client-protocol.h \ + protocol/xdg-shell-protocol.c \ + protocol/xdg-shell-client-protocol.h \ + protocol/fullscreen-shell-protocol.c \ + protocol/fullscreen-shell-client-protocol.h +weston_simple_damage_CFLAGS = $(AM_CFLAGS) $(SIMPLE_CLIENT_CFLAGS) +weston_simple_damage_LDADD = $(SIMPLE_CLIENT_LIBS) libshared.la + weston_simple_touch_SOURCES = clients/simple-touch.c weston_simple_touch_CFLAGS = $(AM_CFLAGS) $(SIMPLE_CLIENT_CFLAGS) weston_simple_touch_LDADD = $(SIMPLE_CLIENT_LIBS) libshared.la diff --git a/clients/cliptest.c b/clients/cliptest.c index 3cee343f..a1928f40 100644 --- a/clients/cliptest.c +++ b/clients/cliptest.c @@ -879,6 +879,14 @@ benchmark(void) return 0; } +static void +cliptest_destroy(struct cliptest *cliptest) +{ + widget_destroy(cliptest->widget); + window_destroy(cliptest->window); + free(cliptest); +} + int main(int argc, char *argv[]) { @@ -897,9 +905,8 @@ main(int argc, char *argv[]) cliptest = cliptest_create(d); display_run(d); - widget_destroy(cliptest->widget); - window_destroy(cliptest->window); - free(cliptest); + cliptest_destroy(cliptest); + display_destroy(d); return 0; } diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index e121cc73..db4a1fd7 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -146,7 +146,7 @@ sigchild_handler(int s) } static void -menu_func(struct window *window, struct input *input, int index, void *data) +menu_func(void *data, struct input *input, int index) { printf("Selected index %d from a panel menu.\n", index); } @@ -1130,7 +1130,8 @@ static void output_destroy(struct output *output) { background_destroy(output->background); - panel_destroy(output->panel); + if (output->panel) + panel_destroy(output->panel); wl_output_destroy(output->output); wl_list_remove(&output->link); @@ -1160,7 +1161,8 @@ output_handle_geometry(void *data, { struct output *output = data; - window_set_buffer_transform(output->panel->window, transform); + if (output->panel) + window_set_buffer_transform(output->panel->window, transform); window_set_buffer_transform(output->background->window, transform); } @@ -1187,7 +1189,8 @@ output_handle_scale(void *data, { struct output *output = data; - window_set_buffer_scale(output->panel->window, scale); + if (output->panel) + window_set_buffer_scale(output->panel->window, scale); window_set_buffer_scale(output->background->window, scale); } @@ -1198,15 +1201,36 @@ static const struct wl_output_listener output_listener = { output_handle_scale }; +static int +want_panel(struct desktop *desktop) +{ + struct weston_config_section *s; + char *location = NULL; + int ret = 1; + + s = weston_config_get_section(desktop->config, "shell", NULL, NULL); + weston_config_section_get_string(s, "panel-location", + &location, "top"); + + if (strcmp(location, "top") != 0) + ret = 0; + + free(location); + + return ret; +} + static void output_init(struct output *output, struct desktop *desktop) { struct wl_surface *surface; - output->panel = panel_create(desktop); - surface = window_get_wl_surface(output->panel->window); - desktop_shell_set_panel(desktop->shell, - output->output, surface); + if (want_panel(desktop)) { + output->panel = panel_create(desktop); + surface = window_get_wl_surface(output->panel->window); + desktop_shell_set_panel(desktop->shell, + output->output, surface); + } output->background = background_create(desktop); surface = window_get_wl_surface(output->background->window); diff --git a/clients/dnd.c b/clients/dnd.c index a463d6f6..620cfff2 100644 --- a/clients/dnd.c +++ b/clients/dnd.c @@ -639,6 +639,14 @@ dnd_create(struct display *display) return dnd; } +static void +dnd_destroy(struct dnd *dnd) +{ + widget_destroy(dnd->widget); + window_destroy(dnd->window); + free(dnd); +} + int main(int argc, char *argv[]) { @@ -660,5 +668,8 @@ main(int argc, char *argv[]) display_run(d); + dnd_destroy(dnd); + display_destroy(d); + return 0; } diff --git a/clients/editor.c b/clients/editor.c index f3f61419..08d12036 100644 --- a/clients/editor.c +++ b/clients/editor.c @@ -1382,6 +1382,9 @@ main(int argc, char *argv[]) text_entry_destroy(editor.entry); text_entry_destroy(editor.editor); + widget_destroy(editor.widget); + window_destroy(editor.window); + display_destroy(editor.display); return 0; } diff --git a/clients/flower.c b/clients/flower.c index 87694450..624525cd 100644 --- a/clients/flower.c +++ b/clients/flower.c @@ -195,5 +195,9 @@ int main(int argc, char *argv[]) display_run(d); + widget_destroy(flower.widget); + window_destroy(flower.window); + display_destroy(d); + return 0; } diff --git a/clients/fullscreen.c b/clients/fullscreen.c index fa8028a9..5c5dd2bc 100644 --- a/clients/fullscreen.c +++ b/clients/fullscreen.c @@ -50,7 +50,7 @@ struct fullscreen { int width, height; int fullscreen; float pointer_x, pointer_y; - int focussed, draw_cursor; + int draw_cursor; struct wl_list output_list; struct fs_output *current_output; @@ -65,14 +65,6 @@ fullscreen_handler(struct window *window, void *data) window_set_fullscreen(window, fullscreen->fullscreen); } -static void -resize_handler(struct widget *widget, int width, int height, void *data) -{ - struct fullscreen *fullscreen = data; - - widget_set_size(widget, fullscreen->width, fullscreen->height); -} - static void draw_string(cairo_t *cr, const char *fmt, ...) @@ -189,7 +181,7 @@ redraw_handler(struct widget *widget, void *data) x = 50; cairo_set_line_width (cr, border); while (x + 70 < fullscreen->width) { - if (fullscreen->focussed && + if (window_has_focus(fullscreen->window) && fullscreen->pointer_x >= x && fullscreen->pointer_x < x + 50 && fullscreen->pointer_y >= y && fullscreen->pointer_y < y + 40) { cairo_set_source_rgb(cr, 1, 0, 0); @@ -209,7 +201,7 @@ redraw_handler(struct widget *widget, void *data) y += 50; } - if (fullscreen->focussed && fullscreen->draw_cursor) { + if (window_has_focus(fullscreen->window) && fullscreen->draw_cursor) { cairo_set_source_rgb(cr, 1, 1, 1); cairo_set_line_width (cr, 8); cairo_move_to(cr, @@ -389,8 +381,6 @@ enter_handler(struct widget *widget, { struct fullscreen *fullscreen = data; - fullscreen->focussed++; - fullscreen->pointer_x = x; fullscreen->pointer_y = y; @@ -399,17 +389,6 @@ enter_handler(struct widget *widget, return fullscreen->draw_cursor ? CURSOR_BLANK : CURSOR_LEFT_PTR; } -static void -leave_handler(struct widget *widget, - struct input *input, void *data) -{ - struct fullscreen *fullscreen = data; - - fullscreen->focussed--; - - widget_schedule_redraw(widget); -} - static void button_handler(struct widget *widget, struct input *input, uint32_t time, @@ -510,7 +489,6 @@ int main(int argc, char *argv[]) fullscreen.width = 640; fullscreen.height = 480; fullscreen.fullscreen = 0; - fullscreen.focussed = 0; fullscreen.present_method = _WL_FULLSCREEN_SHELL_PRESENT_METHOD_DEFAULT; wl_list_init(&fullscreen.output_list); fullscreen.current_output = NULL; @@ -565,12 +543,10 @@ int main(int argc, char *argv[]) widget_set_transparent(fullscreen.widget, 0); widget_set_default_cursor(fullscreen.widget, CURSOR_LEFT_PTR); - widget_set_resize_handler(fullscreen.widget, resize_handler); widget_set_redraw_handler(fullscreen.widget, redraw_handler); widget_set_button_handler(fullscreen.widget, button_handler); widget_set_motion_handler(fullscreen.widget, motion_handler); widget_set_enter_handler(fullscreen.widget, enter_handler); - widget_set_leave_handler(fullscreen.widget, leave_handler); widget_set_touch_down_handler(fullscreen.widget, touch_handler); @@ -586,5 +562,9 @@ int main(int argc, char *argv[]) display_run(d); + widget_destroy(fullscreen.widget); + window_destroy(fullscreen.window); + display_destroy(d); + return 0; } diff --git a/clients/gears.c b/clients/gears.c index 93a86b4f..1fb77e0e 100644 --- a/clients/gears.c +++ b/clients/gears.c @@ -23,6 +23,7 @@ #include "config.h" #include +#include #include #include #include @@ -208,8 +209,13 @@ static void update_fps(struct gears *gears, uint32_t time) { long diff_ms; + static bool first_call = true; - gears->frames++; + if (first_call) { + gears->last_fps = time; + first_call = false; + } else + gears->frames++; diff_ms = time - gears->last_fps; @@ -398,7 +404,6 @@ gears_create(struct display *display) { const int width = 450, height = 500; struct gears *gears; - struct timeval tv; int i; gears = zalloc(sizeof *gears); @@ -437,8 +442,6 @@ gears_create(struct display *display) gears->view.rotx = 20.0; gears->view.roty = 30.0; - gettimeofday(&tv, NULL); - gears->last_fps = tv.tv_sec * 1000 + tv.tv_usec / 1000; printf("Warning: FPS count is limited by the wayland compositor or monitor refresh rate\n"); glEnable(GL_NORMALIZE); @@ -469,17 +472,29 @@ gears_create(struct display *display) return gears; } +static void +gears_destroy(struct gears *gears) +{ + widget_destroy(gears->widget); + window_destroy(gears->window); + free(gears); +} + int main(int argc, char *argv[]) { struct display *d; + struct gears *gears; d = display_create(&argc, argv); if (d == NULL) { fprintf(stderr, "failed to create display: %m\n"); return -1; } - gears_create(d); + gears = gears_create(d); display_run(d); + gears_destroy(gears); + display_destroy(d); + return 0; } diff --git a/clients/image.c b/clients/image.c index 054979d9..112b93d9 100644 --- a/clients/image.c +++ b/clients/image.c @@ -424,5 +424,7 @@ main(int argc, char *argv[]) if (image_counter > 0) display_run(d); + display_destroy(d); + return 0; } diff --git a/clients/nested.c b/clients/nested.c index 44389e40..2a952beb 100644 --- a/clients/nested.c +++ b/clients/nested.c @@ -550,13 +550,6 @@ surface_set_input_region(struct wl_client *client, fprintf(stderr, "surface_set_input_region\n"); } -static void -empty_region(pixman_region32_t *region) -{ - pixman_region32_fini(region); - pixman_region32_init(region); -} - static void surface_commit(struct wl_client *client, struct wl_resource *resource) { @@ -574,7 +567,7 @@ surface_commit(struct wl_client *client, struct wl_resource *resource) surface->pending.newly_attached = 0; /* wl_surface.damage */ - empty_region(&surface->pending.damage); + pixman_region32_clear(&surface->pending.damage); /* wl_surface.frame */ wl_list_insert_list(&surface->frame_callback_list, diff --git a/clients/resizor.c b/clients/resizor.c index 029042fd..19c6eeb3 100644 --- a/clients/resizor.c +++ b/clients/resizor.c @@ -200,8 +200,7 @@ key_handler(struct window *window, struct input *input, uint32_t time, } static void -menu_func(struct window *window, - struct input *input, int index, void *user_data) +menu_func(void *data, struct input *input, int index) { fprintf(stderr, "picked entry %d\n", index); } diff --git a/clients/scaler.c b/clients/scaler.c index f94e714b..39390220 100644 --- a/clients/scaler.c +++ b/clients/scaler.c @@ -321,6 +321,9 @@ main(int argc, char *argv[]) display_run(d); + widget_destroy(box.widget); window_destroy(box.window); + display_destroy(d); + return 0; } diff --git a/clients/simple-damage.c b/clients/simple-damage.c new file mode 100644 index 00000000..d7a7c700 --- /dev/null +++ b/clients/simple-damage.c @@ -0,0 +1,880 @@ +/* + * Copyright © 2014 Jason Ekstrand + * Copyright © 2011 Benjamin Franzke + * Copyright © 2010 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "../shared/os-compatibility.h" +#include "xdg-shell-client-protocol.h" +#include "fullscreen-shell-client-protocol.h" +#include "scaler-client-protocol.h" + +int print_debug = 0; + +struct display { + struct wl_display *display; + struct wl_registry *registry; + int compositor_version; + struct wl_compositor *compositor; + struct wl_scaler *scaler; + struct xdg_shell *shell; + struct _wl_fullscreen_shell *fshell; + struct wl_shm *shm; + uint32_t formats; +}; + +struct buffer { + struct wl_buffer *buffer; + uint32_t *shm_data; + int busy; +}; + +enum window_flags { + WINDOW_FLAG_USE_VIEWPORT = 0x1, + WINDOW_FLAG_ROTATING_TRANSFORM = 0x2, +}; + +struct window { + struct display *display; + int width, height, border; + struct wl_surface *surface; + struct wl_viewport *viewport; + struct xdg_surface *xdg_surface; + struct wl_callback *callback; + struct buffer buffers[2]; + struct buffer *prev_buffer; + + enum window_flags flags; + int scale; + enum wl_output_transform transform; + + struct { + float x, y; /* position in pixels */ + float dx, dy; /* velocity in pixels/second */ + int radius; /* radius in pixels */ + uint32_t prev_time; + } ball; +}; + +static int running = 1; + +static void +buffer_release(void *data, struct wl_buffer *buffer) +{ + struct buffer *mybuf = data; + + mybuf->busy = 0; +} + +static const struct wl_buffer_listener buffer_listener = { + buffer_release +}; + +static int +create_shm_buffer(struct display *display, struct buffer *buffer, + int width, int height, uint32_t format) +{ + struct wl_shm_pool *pool; + int fd, size, pitch; + void *data; + + pitch = width * 4; + size = pitch * height; + + fd = os_create_anonymous_file(size); + if (fd < 0) { + fprintf(stderr, "creating a buffer file for %d B failed: %m\n", + size); + return -1; + } + + data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (data == MAP_FAILED) { + fprintf(stderr, "mmap failed: %m\n"); + close(fd); + return -1; + } + + pool = wl_shm_create_pool(display->shm, fd, size); + buffer->buffer = wl_shm_pool_create_buffer(pool, 0, + width, height, + pitch, format); + wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer); + wl_shm_pool_destroy(pool); + close(fd); + + buffer->shm_data = data; + + return 0; +} + +static void +handle_configure(void *data, struct xdg_surface *surface, + int32_t width, int32_t height, struct wl_array *states, + uint32_t serial) +{ +} + +static void +handle_close(void *data, struct xdg_surface *xdg_surface) +{ + running = 0; +} + +static const struct xdg_surface_listener xdg_surface_listener = { + handle_configure, + handle_close, +}; + +static float +bounded_randf(float a, float b) +{ + return a + ((float)rand() / (float)RAND_MAX) * (b - a); +} + +static void +window_init_game(struct window *window) +{ + int ax1, ay1, ax2, ay2; /* playable arena size */ + struct timeval tv; + + gettimeofday(&tv, NULL); + srand(tv.tv_usec); + + window->ball.radius = 10; + + ax1 = window->border + window->ball.radius; + ay1 = window->border + window->ball.radius; + ax2 = window->width - window->border - window->ball.radius; + ay2 = window->height - window->border - window->ball.radius; + + window->ball.x = bounded_randf(ax1, ax2); + window->ball.y = bounded_randf(ay1, ay2); + + window->ball.dx = bounded_randf(0, window->width); + window->ball.dy = bounded_randf(0, window->height); + + window->ball.prev_time = 0; +} + +static void +window_advance_game(struct window *window, uint32_t timestamp) +{ + int ax1, ay1, ax2, ay2; /* Arena size */ + float dt; + + if (window->ball.prev_time == 0) { + /* first pass, don't do anything */ + window->ball.prev_time = timestamp; + return; + } + + /* dt in seconds */ + dt = (float)(timestamp - window->ball.prev_time) / 1000.0f; + + ax1 = window->border + window->ball.radius; + ay1 = window->border + window->ball.radius; + ax2 = window->width - window->border - window->ball.radius; + ay2 = window->height - window->border - window->ball.radius; + + window->ball.x += window->ball.dx * dt; + while (window->ball.x < ax1 || ax2 < window->ball.x) { + if (window->ball.x < ax1) + window->ball.x = 2 * ax1 - window->ball.x; + if (ax2 <= window->ball.x) + window->ball.x = 2 * ax2 - window->ball.x; + + window->ball.dx *= -1.0f; + } + + window->ball.y += window->ball.dy * dt; + while (window->ball.y < ay1 || ay2 < window->ball.y) { + if (window->ball.y < ay1) + window->ball.y = 2 * ay1 - window->ball.y; + if (ay2 <= window->ball.y) + window->ball.y = 2 * ay2 - window->ball.y; + + window->ball.dy *= -1.0f; + } + + window->ball.prev_time = timestamp; +} + +static struct window * +create_window(struct display *display, int width, int height, + enum wl_output_transform transform, int scale, + enum window_flags flags) +{ + struct window *window; + + if (display->compositor_version < 2 && + (transform != WL_OUTPUT_TRANSFORM_NORMAL || + flags & WINDOW_FLAG_ROTATING_TRANSFORM)) { + fprintf(stderr, "wl_surface.buffer_transform unsupported in " + "wl_surface version %d\n", + display->compositor_version); + exit(1); + } + + if (display->compositor_version < 3 && + (! (flags & WINDOW_FLAG_USE_VIEWPORT)) && scale != 1) { + fprintf(stderr, "wl_surface.buffer_scale unsupported in " + "wl_surface version %d\n", + display->compositor_version); + exit(1); + } + + if (display->scaler == NULL && (flags & WINDOW_FLAG_USE_VIEWPORT)) { + fprintf(stderr, "Compositor does not support wl_viewport"); + exit(1); + } + + window = calloc(1, sizeof *window); + if (!window) + return NULL; + + window->callback = NULL; + window->display = display; + window->width = width; + window->height = height; + window->border = 10; + window->flags = flags; + window->transform = transform; + window->scale = scale; + + window_init_game(window); + + window->surface = wl_compositor_create_surface(display->compositor); + + if (window->flags & WINDOW_FLAG_USE_VIEWPORT) + window->viewport = wl_scaler_get_viewport(display->scaler, + window->surface); + + if (display->shell) { + window->xdg_surface = + xdg_shell_get_xdg_surface(display->shell, + window->surface); + + assert(window->xdg_surface); + + xdg_surface_add_listener(window->xdg_surface, + &xdg_surface_listener, window); + + xdg_surface_set_title(window->xdg_surface, "simple-damage"); + } else if (display->fshell) { + _wl_fullscreen_shell_present_surface(display->fshell, + window->surface, + _WL_FULLSCREEN_SHELL_PRESENT_METHOD_DEFAULT, + NULL); + } else { + assert(0); + } + + /* Initialise damage to full surface, so the padding gets painted */ + wl_surface_damage(window->surface, 0, 0, INT32_MAX, INT32_MAX); + + return window; +} + +static void +destroy_window(struct window *window) +{ + if (window->callback) + wl_callback_destroy(window->callback); + + if (window->buffers[0].buffer) + wl_buffer_destroy(window->buffers[0].buffer); + if (window->buffers[1].buffer) + wl_buffer_destroy(window->buffers[1].buffer); + + if (window->xdg_surface) + xdg_surface_destroy(window->xdg_surface); + if (window->viewport) + wl_viewport_destroy(window->viewport); + wl_surface_destroy(window->surface); + free(window); +} + +static struct buffer * +window_next_buffer(struct window *window) +{ + struct buffer *buffer; + int ret = 0, bwidth, bheight; + + if (!window->buffers[0].busy) + buffer = &window->buffers[0]; + else if (!window->buffers[1].busy) + buffer = &window->buffers[1]; + else + return NULL; + + switch (window->transform) { + default: + case WL_OUTPUT_TRANSFORM_NORMAL: + case WL_OUTPUT_TRANSFORM_180: + case WL_OUTPUT_TRANSFORM_FLIPPED: + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + bwidth = window->width * window->scale; + bheight = window->height * window->scale; + break; + case WL_OUTPUT_TRANSFORM_90: + case WL_OUTPUT_TRANSFORM_270: + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + bwidth = window->height * window->scale; + bheight = window->width * window->scale; + break; + } + + if (!buffer->buffer) { + ret = create_shm_buffer(window->display, buffer, + bwidth, bheight, + WL_SHM_FORMAT_ARGB8888); + + if (ret < 0) + return NULL; + } + + return buffer; +} + +static void +paint_box(uint32_t *pixels, int pitch, int x, int y, int width, int height, + uint32_t color) +{ + int i, j; + + for (j = y; j < y + height; ++j) + for (i = x; i < x + width; ++i) + pixels[i + j * pitch] = color; +} + +static void +paint_circle(uint32_t *pixels, int pitch, float x, float y, int radius, + uint32_t color) +{ + int i, j; + + for (j = y - radius; j <= (int)(y + radius); ++j) + for (i = x - radius; i <= (int)(x + radius); ++i) + if ((j+0.5f-y)*(j+0.5f-y) + (i+0.5f-x)*(i+0.5f-x) <= radius * radius) + pixels[i + j * pitch] = color; +} + +static void +window_get_transformed_ball(struct window *window, float *bx, float *by) +{ + float wx, wy; + + wx = window->ball.x; + wy = window->ball.y; + + switch (window->transform) { + default: + case WL_OUTPUT_TRANSFORM_NORMAL: + *bx = wx; + *by = wy; + break; + case WL_OUTPUT_TRANSFORM_90: + *bx = window->height - wy; + *by = wx; + break; + case WL_OUTPUT_TRANSFORM_180: + *bx = window->width - wx; + *by = window->height - wy; + break; + case WL_OUTPUT_TRANSFORM_270: + *bx = wy; + *by = window->width - wx; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED: + *bx = window->width - wx; + *by = wy; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + *bx = window->height - wy; + *by = window->width - wx; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + *bx = wx; + *by = window->height - wy; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + *bx = wy; + *by = wx; + break; + } + + *bx *= window->scale; + *by *= window->scale; + + if (window->viewport) { + /* We're drawing half-size because of the viewport */ + *bx /= 2; + *by /= 2; + } +} + +static const struct wl_callback_listener frame_listener; + +static void +redraw(void *data, struct wl_callback *callback, uint32_t time) +{ + struct window *window = data; + struct buffer *buffer; + int off_x, off_y, bwidth, bheight, bborder, bpitch, bradius; + uint32_t *buffer_data; + float bx, by; + + buffer = window_next_buffer(window); + if (!buffer) { + fprintf(stderr, + !callback ? "Failed to create the first buffer.\n" : + "Both buffers busy at redraw(). Server bug?\n"); + abort(); + } + + /* Rotate the damage, but keep the even/odd parity so the + * dimensions of the buffers don't change */ + if (window->flags & WINDOW_FLAG_ROTATING_TRANSFORM) + window->transform = (window->transform + 2) % 8; + + switch (window->transform) { + default: + case WL_OUTPUT_TRANSFORM_NORMAL: + case WL_OUTPUT_TRANSFORM_180: + case WL_OUTPUT_TRANSFORM_FLIPPED: + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + bwidth = window->width * window->scale; + bheight = window->height * window->scale; + break; + case WL_OUTPUT_TRANSFORM_90: + case WL_OUTPUT_TRANSFORM_270: + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + bwidth = window->height * window->scale; + bheight = window->width * window->scale; + break; + } + + bpitch = bwidth; + + bborder = window->border * window->scale; + bradius = window->ball.radius * window->scale; + + buffer_data = buffer->shm_data; + if (window->viewport) { + /* Fill the whole thing with red to detect viewport errors */ + paint_box(buffer->shm_data, bpitch, 0, 0, bwidth, bheight, + 0xffff0000); + + /* The buffer is the same size. However, we crop it + * and scale it up by a factor of 2 */ + bborder /= 2; + bradius /= 2; + bwidth /= 2; + bheight /= 2; + + /* Offset the drawing region */ + off_x = (window->width / 3) * window->scale; + off_y = (window->height / 5) * window->scale; + switch (window->transform) { + default: + case WL_OUTPUT_TRANSFORM_NORMAL: + buffer_data += off_y * bpitch + off_x; + break; + case WL_OUTPUT_TRANSFORM_90: + buffer_data += off_x * bpitch + (bwidth - off_y); + break; + case WL_OUTPUT_TRANSFORM_180: + buffer_data += (bheight - off_y) * bpitch + + (bwidth - off_x); + break; + case WL_OUTPUT_TRANSFORM_270: + buffer_data += (bheight - off_x) * bpitch + off_y; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED: + buffer_data += off_y * bpitch + (bwidth - off_x); + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + buffer_data += (bheight - off_x) * bpitch + + (bwidth - off_y); + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + buffer_data += (bheight - off_y) * bpitch + off_x; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + buffer_data += off_x * bpitch + off_y; + break; + } + wl_viewport_set_source(window->viewport, + wl_fixed_from_int(window->width / 3), + wl_fixed_from_int(window->height / 5), + wl_fixed_from_int(window->width / 2), + wl_fixed_from_int(window->height / 2)); + } + + /* Paint the border */ + paint_box(buffer_data, bpitch, 0, 0, bwidth, bborder, 0xffffffff); + paint_box(buffer_data, bpitch, 0, 0, bborder, bheight, 0xffffffff); + paint_box(buffer_data, bpitch, + bwidth - bborder, 0, bborder, bheight, 0xffffffff); + paint_box(buffer_data, bpitch, + 0, bheight - bborder, bwidth, bborder, 0xffffffff); + + /* fill with translucent */ + paint_box(buffer_data, bpitch, bborder, bborder, + bwidth - 2 * bborder, bheight - 2 * bborder, 0x80000000); + + /* Damage where the ball was */ + wl_surface_damage(window->surface, + window->ball.x - window->ball.radius, + window->ball.y - window->ball.radius, + window->ball.radius * 2 + 1, + window->ball.radius * 2 + 1); + + window_advance_game(window, time); + + window_get_transformed_ball(window, &bx, &by); + + /* Paint the ball */ + paint_circle(buffer_data, bpitch, bx, by, bradius, 0xff00ff00); + + if (print_debug) { + printf("Ball now located at (%f, %f)\n", + window->ball.x, window->ball.y); + + printf("Circle painted at (%f, %f), radius %d\n", bx, by, + bradius); + + printf("Buffer damage rectangle: (%d, %d) @ %dx%d\n", + (int)(bx - bradius), (int)(by - bradius), + bradius * 2 + 1, bradius * 2 + 1); + } + + /* Damage where the ball is now */ + wl_surface_damage(window->surface, + window->ball.x - window->ball.radius, + window->ball.y - window->ball.radius, + window->ball.radius * 2 + 1, + window->ball.radius * 2 + 1); + + wl_surface_attach(window->surface, buffer->buffer, 0, 0); + + if (window->display->compositor_version >= 2 && + (window->transform != WL_OUTPUT_TRANSFORM_NORMAL || + window->flags & WINDOW_FLAG_ROTATING_TRANSFORM)) + wl_surface_set_buffer_transform(window->surface, + window->transform); + + if (window->viewport) + wl_viewport_set_destination(window->viewport, + window->width, + window->height); + + if (window->scale != 1) + wl_surface_set_buffer_scale(window->surface, + window->scale); + + if (callback) + wl_callback_destroy(callback); + + window->callback = wl_surface_frame(window->surface); + wl_callback_add_listener(window->callback, &frame_listener, window); + wl_surface_commit(window->surface); + buffer->busy = 1; +} + +static const struct wl_callback_listener frame_listener = { + redraw +}; + +static void +shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) +{ + struct display *d = data; + + d->formats |= (1 << format); +} + +struct wl_shm_listener shm_listener = { + shm_format +}; + +static void +xdg_shell_ping(void *data, struct xdg_shell *shell, uint32_t serial) +{ + xdg_shell_pong(shell, serial); +} + +static const struct xdg_shell_listener xdg_shell_listener = { + xdg_shell_ping, +}; + +#define XDG_VERSION 3 /* The version of xdg-shell that we implement */ +#ifdef static_assert +static_assert(XDG_VERSION == XDG_SHELL_VERSION_CURRENT, + "Interface version doesn't match implementation version"); +#endif + +static void +registry_handle_global(void *data, struct wl_registry *registry, + uint32_t id, const char *interface, uint32_t version) +{ + struct display *d = data; + + if (strcmp(interface, "wl_compositor") == 0) { + if (d->compositor_version > (int)version) { + fprintf(stderr, "Compositor does not support " + "wl_surface version %d\n", d->compositor_version); + exit(1); + } + + if (d->compositor_version < 0) + d->compositor_version = version; + + d->compositor = + wl_registry_bind(registry, + id, &wl_compositor_interface, + d->compositor_version); + } else if (strcmp(interface, "wl_scaler") == 0 && version >= 2) { + d->scaler = wl_registry_bind(registry, + id, &wl_scaler_interface, 2); + } else if (strcmp(interface, "xdg_shell") == 0) { + d->shell = wl_registry_bind(registry, + id, &xdg_shell_interface, 1); + xdg_shell_use_unstable_version(d->shell, XDG_VERSION); + xdg_shell_add_listener(d->shell, &xdg_shell_listener, d); + } else if (strcmp(interface, "_wl_fullscreen_shell") == 0) { + d->fshell = wl_registry_bind(registry, + id, &_wl_fullscreen_shell_interface, 1); + } else if (strcmp(interface, "wl_shm") == 0) { + d->shm = wl_registry_bind(registry, + id, &wl_shm_interface, 1); + wl_shm_add_listener(d->shm, &shm_listener, d); + } +} + +static void +registry_handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + +static struct display * +create_display(int version) +{ + struct display *display; + + display = malloc(sizeof *display); + if (display == NULL) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + display->display = wl_display_connect(NULL); + assert(display->display); + + display->compositor_version = version; + display->formats = 0; + display->registry = wl_display_get_registry(display->display); + wl_registry_add_listener(display->registry, + ®istry_listener, display); + wl_display_roundtrip(display->display); + if (display->shm == NULL) { + fprintf(stderr, "No wl_shm global\n"); + exit(1); + } + + wl_display_roundtrip(display->display); + + if (!(display->formats & (1 << WL_SHM_FORMAT_XRGB8888))) { + fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n"); + exit(1); + } + + return display; +} + +static void +destroy_display(struct display *display) +{ + if (display->shm) + wl_shm_destroy(display->shm); + + if (display->shell) + xdg_shell_destroy(display->shell); + + if (display->fshell) + _wl_fullscreen_shell_release(display->fshell); + + if (display->scaler) + wl_scaler_destroy(display->scaler); + + if (display->compositor) + wl_compositor_destroy(display->compositor); + + wl_registry_destroy(display->registry); + wl_display_flush(display->display); + wl_display_disconnect(display->display); + free(display); +} + +static void +signal_int(int signum) +{ + running = 0; +} + +static void +print_usage(int retval) +{ + printf( + "usage: weston-simple-damage [options]\n\n" + "options:\n" + " -h, --help\t\tPring this help\n" + " --verbose\t\tPrint verbose log information\n" + " --version=VERSION\tVersion of wl_surface to use\n" + " --width=WIDTH\t\tWidth of the window\n" + " --height=HEIGHT\tHeight of the window\n" + " --scale=SCALE\t\tScale factor for the surface\n" + " --transform=TRANSFORM\tTransform for the surface\n" + " --rotating-transform\tUse a different buffer_transform for each frame\n" + " --use-viewport\tUse wl_viewport\n" + ); + + exit(retval); +} + +static int +parse_transform(const char *str, enum wl_output_transform *transform) +{ + int i; + static const struct { + const char *name; + enum wl_output_transform transform; + } names[] = { + { "normal", WL_OUTPUT_TRANSFORM_NORMAL }, + { "90", WL_OUTPUT_TRANSFORM_90 }, + { "180", WL_OUTPUT_TRANSFORM_180 }, + { "270", WL_OUTPUT_TRANSFORM_270 }, + { "flipped", WL_OUTPUT_TRANSFORM_FLIPPED }, + { "flipped-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 }, + { "flipped-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 }, + { "flipped-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 }, + }; + + for (i = 0; i < 8; i++) { + if (strcmp(names[i].name, str) == 0) { + *transform = names[i].transform; + return 1; + } + } + + return 0; +} + +int +main(int argc, char **argv) +{ + struct sigaction sigint; + struct display *display; + struct window *window; + int i, ret = 0; + int version = -1; + int width = 300, height = 200, scale = 1; + enum wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; + enum window_flags flags = 0; + + for (i = 1; i < argc; ++i) { + if (strcmp(argv[i], "--help") == 0 || + strcmp(argv[i], "-h") == 0) { + print_usage(0); + } else if (sscanf(argv[i], "--version=%d", &version) > 0) { + if (version < 1 || version > 3) { + fprintf(stderr, "Unsupported wl_surface version: %d\n", + version); + return 1; + } + continue; + } else if (strcmp(argv[i], "--verbose") == 0) { + print_debug = 1; + continue; + } else if (sscanf(argv[i], "--width=%d", &width) > 0) { + continue; + } else if (sscanf(argv[i], "--height=%d", &height) > 0) { + continue; + } else if (strncmp(argv[i], "--transform=", 12) == 0 && + parse_transform(argv[i] + 12, &transform) > 0) { + continue; + } else if (strcmp(argv[i], "--rotating-transform") == 0) { + flags |= WINDOW_FLAG_ROTATING_TRANSFORM; + continue; + } else if (sscanf(argv[i], "--scale=%d", &scale) > 0) { + continue; + } else if (strcmp(argv[i], "--use-viewport") == 0) { + flags |= WINDOW_FLAG_USE_VIEWPORT; + continue; + } else { + printf("Invalid option: %s\n", argv[i]); + print_usage(255); + } + } + + display = create_display(version); + + window = create_window(display, width, height, transform, scale, flags); + if (!window) + return 1; + + sigint.sa_handler = signal_int; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + + redraw(window, NULL, 0); + + while (running && ret != -1) + ret = wl_display_dispatch(display->display); + + fprintf(stderr, "simple-shm exiting\n"); + destroy_window(window); + destroy_display(display); + + return 0; +} diff --git a/clients/simple-egl.c b/clients/simple-egl.c index 0d4673b5..f23fb8c5 100644 --- a/clients/simple-egl.c +++ b/clients/simple-egl.c @@ -268,50 +268,39 @@ init_gl(struct window *window) static void handle_surface_configure(void *data, struct xdg_surface *surface, - int32_t width, int32_t height) + int32_t width, int32_t height, + struct wl_array *states, uint32_t serial) { struct window *window = data; - - if (window->native) - wl_egl_window_resize(window->native, width, height, 0, 0); - - window->geometry.width = width; - window->geometry.height = height; - - if (!window->fullscreen) - window->window_size = window->geometry; -} - -static void -handle_surface_change_state(void *data, struct xdg_surface *xdg_surface, - uint32_t state, - uint32_t value, - uint32_t serial) -{ - struct window *window = data; - - switch (state) { - case XDG_SURFACE_STATE_FULLSCREEN: - window->fullscreen = value; - - if (!value) - handle_surface_configure(window, window->xdg_surface, - window->window_size.width, - window->window_size.height); - break; + uint32_t *p; + + window->fullscreen = 0; + wl_array_for_each(p, states) { + uint32_t state = *p; + switch (state) { + case XDG_SURFACE_STATE_FULLSCREEN: + window->fullscreen = 1; + break; + } } - xdg_surface_ack_change_state(xdg_surface, state, value, serial); -} + if (width > 0 && height > 0) { + if (!window->fullscreen) { + window->window_size.width = width; + window->window_size.height = height; + } + window->geometry.width = width; + window->geometry.height = height; + } else if (!window->fullscreen) { + window->geometry = window->window_size; + } -static void -handle_surface_activated(void *data, struct xdg_surface *xdg_surface) -{ -} + if (window->native) + wl_egl_window_resize(window->native, + window->geometry.width, + window->geometry.height, 0, 0); -static void -handle_surface_deactivated(void *data, struct xdg_surface *xdg_surface) -{ + xdg_surface_ack_configure(surface, serial); } static void @@ -322,9 +311,6 @@ handle_surface_delete(void *data, struct xdg_surface *xdg_surface) static const struct xdg_surface_listener xdg_surface_listener = { handle_surface_configure, - handle_surface_change_state, - handle_surface_activated, - handle_surface_deactivated, handle_surface_delete, }; @@ -343,8 +329,8 @@ create_surface(struct window *window) window->native = wl_egl_window_create(window->surface, - window->window_size.width, - window->window_size.height); + window->geometry.width, + window->geometry.height); window->egl_surface = eglCreateWindowSurface(display->egl.dpy, display->egl.conf, @@ -359,9 +345,8 @@ create_surface(struct window *window) if (!window->frame_sync) eglSwapInterval(display->egl.dpy, 0); - xdg_surface_request_change_state(window->xdg_surface, - XDG_SURFACE_STATE_FULLSCREEN, - window->fullscreen, 0); + if (window->fullscreen) + xdg_surface_set_fullscreen(window->xdg_surface, NULL); } static void @@ -382,8 +367,6 @@ destroy_surface(struct window *window) wl_callback_destroy(window->callback); } -static const struct wl_callback_listener frame_listener; - static void redraw(void *data, struct wl_callback *callback, uint32_t time) { @@ -484,10 +467,6 @@ redraw(void *data, struct wl_callback *callback, uint32_t time) window->frames++; } -static const struct wl_callback_listener frame_listener = { - redraw -}; - static void pointer_handle_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, @@ -620,11 +599,12 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard, { struct display *d = data; - if (key == KEY_F11 && state) - xdg_surface_request_change_state(d->window->xdg_surface, - XDG_SURFACE_STATE_FULLSCREEN, - !d->window->fullscreen, 0); - else if (key == KEY_ESC && state) + if (key == KEY_F11 && state) { + if (d->window->fullscreen) + xdg_surface_unset_fullscreen(d->window->xdg_surface); + else + xdg_surface_set_fullscreen(d->window->xdg_surface, NULL); + } else if (key == KEY_ESC && state) running = 0; } @@ -772,8 +752,9 @@ main(int argc, char **argv) window.display = &display; display.window = &window; - window.window_size.width = 250; - window.window_size.height = 250; + window.geometry.width = 250; + window.geometry.height = 250; + window.window_size = window.geometry; window.buffer_size = 32; window.frame_sync = 1; diff --git a/clients/simple-shm.c b/clients/simple-shm.c index 2087a0e6..29abb8bc 100644 --- a/clients/simple-shm.c +++ b/clients/simple-shm.c @@ -117,26 +117,10 @@ create_shm_buffer(struct display *display, struct buffer *buffer, static void handle_configure(void *data, struct xdg_surface *surface, - int32_t width, int32_t height) -{ -} - -static void -handle_change_state(void *data, struct xdg_surface *xdg_surface, - uint32_t state, - uint32_t value, - uint32_t serial) -{ -} - -static void -handle_activated(void *data, struct xdg_surface *xdg_surface) -{ -} - -static void -handle_deactivated(void *data, struct xdg_surface *xdg_surface) + int32_t width, int32_t height, + struct wl_array *states, uint32_t serial) { + xdg_surface_ack_configure(surface, serial); } static void @@ -147,9 +131,6 @@ handle_delete(void *data, struct xdg_surface *xdg_surface) static const struct xdg_surface_listener xdg_surface_listener = { handle_configure, - handle_change_state, - handle_activated, - handle_deactivated, handle_delete, }; diff --git a/clients/smoke.c b/clients/smoke.c index 5d976af1..65b6e038 100644 --- a/clients/smoke.c +++ b/clients/smoke.c @@ -329,5 +329,9 @@ int main(int argc, char *argv[]) display_run(d); + widget_destroy(smoke.widget); + window_destroy(smoke.window); + display_destroy(d); + return 0; } diff --git a/clients/stacking.c b/clients/stacking.c index 347c598d..ea6101d5 100644 --- a/clients/stacking.c +++ b/clients/stacking.c @@ -64,7 +64,7 @@ new_window(struct stacking *stacking, struct window *parent_window) struct widget *new_widget; new_window = window_create(stacking->display); - window_set_transient_for(new_window, parent_window); + window_set_parent(new_window, parent_window); new_widget = window_frame_create(new_window, new_window); @@ -82,7 +82,7 @@ new_window(struct stacking *stacking, struct window *parent_window) } static void -show_popup_cb(struct window *window, struct input *input, int index, void *data) +show_popup_cb(void *data, struct input *input, int index) { /* Ignore the selected menu item. */ } @@ -230,7 +230,7 @@ draw_string(cairo_t *cr, static void set_window_background_colour(cairo_t *cr, struct window *window) { - if (window_get_transient_for(window)) + if (window_get_parent(window)) cairo_set_source_rgba(cr, 0.0, 1.0, 0.0, 0.4); else if (window_is_maximized(window)) cairo_set_source_rgba(cr, 1.0, 1.0, 0.0, 0.6); @@ -276,7 +276,7 @@ redraw_handler(struct widget *widget, void *data) " (n)ew window, (p)opup,\n" " (q)uit, (t)ransient window\n", window, window_is_fullscreen(window), - window_is_maximized(window), window_get_transient_for(window) ? 1 : 0); + window_is_maximized(window), window_get_parent(window) ? 1 : 0); cairo_destroy(cr); } @@ -304,5 +304,8 @@ main(int argc, char *argv[]) display_run(stacking.display); + window_destroy(stacking.root_window); + display_destroy(stacking.display); + return 0; } diff --git a/clients/terminal.c b/clients/terminal.c index 924549e1..0bacbe09 100644 --- a/clients/terminal.c +++ b/clients/terminal.c @@ -447,6 +447,7 @@ struct terminal { int width, height, row, column, max_width; uint32_t buffer_height; uint32_t start, end, saved_start, log_size; + wl_fixed_t smooth_scroll; int saved_row, saved_column; int scrolling; int send_cursor_position; @@ -833,13 +834,27 @@ terminal_resize_cells(struct terminal *terminal, ioctl(terminal->master, TIOCSWINSZ, &ws); } +static void +update_title(struct terminal *terminal) +{ + if (window_is_resizing(terminal->window)) { + char *p; + if (asprintf(&p, "%s — [%dx%d]", terminal->title, terminal->width, terminal->height) > 0) { + window_set_title(terminal->window, p); + free(p); + } + } else { + window_set_title(terminal->window, terminal->title); + } +} + static void resize_handler(struct widget *widget, int32_t width, int32_t height, void *data) { struct terminal *terminal = data; int32_t columns, rows, m; - char *p; + m = 2 * terminal->margin; columns = (width - m) / (int32_t) terminal->average_width; rows = (height - m) / (int32_t) terminal->extents.height; @@ -849,14 +864,17 @@ resize_handler(struct widget *widget, width = columns * terminal->average_width + m; height = rows * terminal->extents.height + m; widget_set_size(terminal->widget, width, height); - if (asprintf(&p, "%s — [%dx%d]", terminal->title, columns, rows) > 0) { - window_set_title(terminal->window, p); - terminal->size_in_title = 1; - free(p); - } } terminal_resize_cells(terminal, columns, rows); + update_title(terminal); +} + +static void +state_changed_handler(struct window *window, void *data) +{ + struct terminal *terminal = data; + update_title(terminal); } static void @@ -2663,9 +2681,10 @@ recompute_selection(struct terminal *terminal) } static void -menu_func(struct window *window, struct input *input, int index, void *data) +menu_func(void *data, struct input *input, int index) { - struct terminal *terminal = data; + struct window *window = data; + struct terminal *terminal = window_get_user_data(window); fprintf(stderr, "picked entry %d\n", index); @@ -2745,14 +2764,6 @@ static int enter_handler(struct widget *widget, struct input *input, float x, float y, void *data) { - struct terminal *terminal = data; - - /* Reset title to get rid of resizing '[WxH]' in titlebar */ - if (terminal->size_in_title) { - window_set_title(terminal->window, terminal->title); - terminal->size_in_title = 0; - } - return CURSOR_IBEAM; } @@ -2775,6 +2786,55 @@ motion_handler(struct widget *widget, return CURSOR_IBEAM; } +/* This magnitude is chosen rather arbitrarily. Really, the scrolling + * should happen on a (fractional) pixel basis, not a line basis. */ +#define AXIS_UNITS_PER_LINE 256 + +static void +axis_handler(struct widget *widget, + struct input *input, uint32_t time, + uint32_t axis, + wl_fixed_t value, + void *data) +{ + struct terminal *terminal = data; + int lines; + + if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) + return; + + terminal->smooth_scroll += value; + lines = terminal->smooth_scroll / AXIS_UNITS_PER_LINE; + terminal->smooth_scroll -= lines * AXIS_UNITS_PER_LINE; + + if (lines > 0) { + if (terminal->scrolling) { + if ((uint32_t)lines > terminal->saved_start - terminal->start) + lines = terminal->saved_start - terminal->start; + } else { + lines = 0; + } + } else if (lines < 0) { + uint32_t neg_lines = -lines; + + if (neg_lines > terminal->log_size + terminal->start - terminal->end) + lines = terminal->end - terminal->log_size - terminal->start; + } + + if (lines) { + if (!terminal->scrolling) + terminal->saved_start = terminal->start; + terminal->scrolling = 1; + + terminal->start += lines; + terminal->row -= lines; + terminal->selection_start_row -= lines; + terminal->selection_end_row -= lines; + + widget_schedule_redraw(widget); + } +} + static void output_handler(struct window *window, struct output *output, int enter, void *data) @@ -2860,6 +2920,7 @@ terminal_create(struct display *display) window_set_fullscreen_handler(terminal->window, fullscreen_handler); window_set_output_handler(terminal->window, output_handler); window_set_close_handler(terminal->window, close_handler); + window_set_state_changed_handler(terminal->window, state_changed_handler); window_set_data_handler(terminal->window, data_handler); window_set_drop_handler(terminal->window, drop_handler); @@ -2869,6 +2930,7 @@ terminal_create(struct display *display) widget_set_button_handler(terminal->widget, button_handler); widget_set_enter_handler(terminal->widget, enter_handler); widget_set_motion_handler(terminal->widget, motion_handler); + widget_set_axis_handler(terminal->widget, axis_handler); widget_set_touch_up_handler(terminal->widget, touch_up_handler); widget_set_touch_down_handler(terminal->widget, touch_down_handler); widget_set_touch_motion_handler(terminal->widget, touch_motion_handler); diff --git a/clients/transformed.c b/clients/transformed.c index 4b1cb056..880a0a96 100644 --- a/clients/transformed.c +++ b/clients/transformed.c @@ -290,6 +290,9 @@ int main(int argc, char *argv[]) transformed.width, transformed.height); display_run(d); + widget_destroy(transformed.widget); + window_destroy(transformed.window); + display_destroy(d); return 0; } diff --git a/clients/weston-info.c b/clients/weston-info.c index df869e3b..c53ac74e 100644 --- a/clients/weston-info.c +++ b/clients/weston-info.c @@ -32,6 +32,8 @@ #include "../shared/os-compatibility.h" +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) + typedef void (*print_info_t)(void *info); typedef void (*destroy_info_t)(void *info); @@ -87,9 +89,13 @@ struct shm_info { struct seat_info { struct global_info global; struct wl_seat *seat; + struct weston_info *info; uint32_t capabilities; char *name; + + int32_t repeat_rate; + int32_t repeat_delay; }; struct weston_info { @@ -291,14 +297,89 @@ print_seat_info(void *data) printf(" touch"); printf("\n"); + + if (seat->repeat_rate > 0) + printf("\tkeyboard repeat rate: %d\n", seat->repeat_rate); + if (seat->repeat_delay > 0) + printf("\tkeyboard repeat delay: %d\n", seat->repeat_delay); +} + +static void +keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, + uint32_t format, int fd, uint32_t size) +{ +} + +static void +keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, + uint32_t serial, struct wl_surface *surface, + struct wl_array *keys) +{ +} + +static void +keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, + uint32_t serial, struct wl_surface *surface) +{ } +static void +keyboard_handle_key(void *data, struct wl_keyboard *keyboard, + uint32_t serial, uint32_t time, uint32_t key, + uint32_t state) +{ +} + +static void +keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, + uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, + uint32_t group) +{ +} + +static void +keyboard_handle_repeat_info(void *data, struct wl_keyboard *keyboard, + int32_t rate, int32_t delay) +{ + struct seat_info *seat = data; + + seat->repeat_rate = rate; + seat->repeat_delay = delay; +} + +static const struct wl_keyboard_listener keyboard_listener = { + keyboard_handle_keymap, + keyboard_handle_enter, + keyboard_handle_leave, + keyboard_handle_key, + keyboard_handle_modifiers, + keyboard_handle_repeat_info, +}; + static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) { struct seat_info *seat = data; + seat->capabilities = caps; + + /* we want listen for repeat_info from wl_keyboard, but only + * do so if the seat info is >= 4 and if we actually have a + * keyboard */ + if (seat->global.version < 4) + return; + + if (caps & WL_SEAT_CAPABILITY_KEYBOARD) { + struct wl_keyboard *keyboard; + + keyboard = wl_seat_get_keyboard(seat->seat); + wl_keyboard_add_listener(keyboard, &keyboard_listener, + seat); + + seat->info->roundtrip_needed = true; + } } static void @@ -330,14 +411,20 @@ add_seat_info(struct weston_info *info, uint32_t id, uint32_t version) { struct seat_info *seat = xzalloc(sizeof *seat); + /* required to set roundtrip_needed to true in capabilities + * handler */ + seat->info = info; + init_global_info(info, &seat->global, id, "wl_seat", version); seat->global.print = print_seat_info; seat->global.destroy = destroy_seat_info; seat->seat = wl_registry_bind(info->registry, - id, &wl_seat_interface, 2); + id, &wl_seat_interface, MIN(version, 4)); wl_seat_add_listener(seat->seat, &seat_listener, seat); + seat->repeat_rate = seat->repeat_delay = -1; + info->roundtrip_needed = true; } diff --git a/clients/window.c b/clients/window.c index 4592ef96..a8bc2602 100644 --- a/clients/window.c +++ b/clients/window.c @@ -239,12 +239,13 @@ struct window { window_close_handler_t close_handler; window_fullscreen_handler_t fullscreen_handler; window_output_handler_t output_handler; + window_state_changed_handler_t state_changed_handler; struct surface *main_surface; struct xdg_surface *xdg_surface; struct xdg_popup *xdg_popup; - struct window *transient_for; + struct window *parent; struct window_frame *frame; @@ -333,6 +334,11 @@ struct input { xkb_mod_mask_t shift_mask; } xkb; + int32_t repeat_rate_sec; + int32_t repeat_rate_nsec; + int32_t repeat_delay_sec; + int32_t repeat_delay_nsec; + struct task repeat_task; int repeat_timer_fd; uint32_t repeat_sym; @@ -362,8 +368,8 @@ struct window_frame { }; struct menu { + void *user_data; struct window *window; - struct window *parent; struct widget *widget; struct input *input; struct frame *frame; @@ -2120,12 +2126,6 @@ frame_resize_handler(struct widget *widget, interior.width = width; interior.height = height; } else { - if (widget->window->maximized) { - frame_set_flag(frame->frame, FRAME_FLAG_MAXIMIZED); - } else { - frame_unset_flag(frame->frame, FRAME_FLAG_MAXIMIZED); - } - frame_resize(frame->frame, width, height); frame_interior(frame->frame, &interior.x, &interior.y, &interior.width, &interior.height); @@ -2193,12 +2193,6 @@ frame_redraw_handler(struct widget *widget, void *data) if (window->fullscreen) return; - if (window->focused) { - frame_set_flag(frame->frame, FRAME_FLAG_ACTIVE); - } else { - frame_unset_flag(frame->frame, FRAME_FLAG_ACTIVE); - } - cr = widget_cairo_create(widget); frame_repaint(frame->frame, cr); @@ -2239,61 +2233,19 @@ frame_get_pointer_image_for_location(struct window_frame *frame, } } -static void -frame_menu_func(struct window *window, - struct input *input, int index, void *data) -{ - struct display *display; - - switch (index) { - case 0: /* close */ - window_close(window); - break; - case 1: /* move to workspace above */ - display = window->display; - if (display->workspace > 0) - workspace_manager_move_surface( - display->workspace_manager, - window->main_surface->surface, - display->workspace - 1); - break; - case 2: /* move to workspace below */ - display = window->display; - if (display->workspace < display->workspace_count - 1) - workspace_manager_move_surface( - display->workspace_manager, - window->main_surface->surface, - display->workspace + 1); - break; - case 3: /* fullscreen */ - /* we don't have a way to get out of fullscreen for now */ - if (window->fullscreen_handler) - window->fullscreen_handler(window, window->user_data); - break; - } -} - void window_show_frame_menu(struct window *window, struct input *input, uint32_t time) { int32_t x, y; - int count; - - static const char *entries[] = { - "Close", - "Move to workspace above", "Move to workspace below", - "Fullscreen" - }; - if (window->fullscreen_handler) - count = ARRAY_LENGTH(entries); - else - count = ARRAY_LENGTH(entries) - 1; - - input_get_position(input, &x, &y); - window_show_menu(window->display, input, time, window, - x - 10, y - 10, frame_menu_func, entries, count); + if (window->xdg_surface) { + input_get_position(input, &x, &y); + xdg_surface_show_window_menu(window->xdg_surface, + input_get_seat(input), + window->display->serial, + x - 10, y - 10); + } } static int @@ -2379,7 +2331,6 @@ frame_handle_status(struct window_frame *frame, struct input *input, if ((status & FRAME_STATUS_RESIZE) && window->xdg_surface) { input_ungrab(input); - window->resizing = 1; xdg_surface_resize(window->xdg_surface, input_get_seat(input), window->display->serial, @@ -2615,12 +2566,6 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer, input->pointer_enter_serial = serial; input->pointer_focus = window; - if (window->resizing) { - window->resizing = 0; - /* Schedule a redraw to free the pool */ - window_schedule_redraw(window); - } - input->sx = sx; input->sy = sy; @@ -2924,10 +2869,10 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard, input->repeat_sym = sym; input->repeat_key = key; input->repeat_time = time; - its.it_interval.tv_sec = 0; - its.it_interval.tv_nsec = 25 * 1000 * 1000; - its.it_value.tv_sec = 0; - its.it_value.tv_nsec = 400 * 1000 * 1000; + its.it_interval.tv_sec = input->repeat_rate_sec; + its.it_interval.tv_nsec = input->repeat_rate_nsec; + its.it_value.tv_sec = input->repeat_delay_sec; + its.it_value.tv_nsec = input->repeat_delay_nsec; timerfd_settime(input->repeat_timer_fd, 0, &its, NULL); } } @@ -2959,12 +2904,44 @@ keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, input->modifiers |= MOD_SHIFT_MASK; } +static void +set_repeat_info(struct input *input, int32_t rate, int32_t delay) +{ + input->repeat_rate_sec = input->repeat_rate_nsec = 0; + input->repeat_delay_sec = input->repeat_delay_nsec = 0; + + /* a rate of zero disables any repeating, regardless of the delay's + * value */ + if (rate == 0) + return; + + if (rate == 1) + input->repeat_rate_sec = 1; + else + input->repeat_rate_nsec = 1000000000 / rate; + + input->repeat_delay_sec = delay / 1000; + delay -= (input->repeat_delay_sec * 1000); + input->repeat_delay_nsec = delay * 1000 * 1000; +} + +static void +keyboard_handle_repeat_info(void *data, struct wl_keyboard *keyboard, + int32_t rate, int32_t delay) +{ + struct input *input = data; + + set_repeat_info(input, rate, delay); +} + static const struct wl_keyboard_listener keyboard_listener = { keyboard_handle_keymap, keyboard_handle_enter, keyboard_handle_leave, keyboard_handle_key, keyboard_handle_modifiers, + keyboard_handle_repeat_info + }; static void @@ -3847,53 +3824,82 @@ widget_schedule_resize(struct widget *widget, int32_t width, int32_t height) window_schedule_resize(widget->window, width, height); } -static void -handle_surface_configure(void *data, struct xdg_surface *xdg_surface, - int32_t width, int32_t height) +static int +window_get_shadow_margin(struct window *window) { - struct window *window = data; - - window_schedule_resize(window, width, height); + if (window->frame && !window->fullscreen) + return frame_get_shadow_margin(window->frame->frame); + else + return 0; } static void -handle_surface_change_state(void *data, struct xdg_surface *xdg_surface, - uint32_t state, - uint32_t value, - uint32_t serial) +handle_surface_configure(void *data, struct xdg_surface *xdg_surface, + int32_t width, int32_t height, + struct wl_array *states, uint32_t serial) { struct window *window = data; + uint32_t *p; - switch (state) { - case XDG_SURFACE_STATE_MAXIMIZED: - window->maximized = value; - break; - case XDG_SURFACE_STATE_FULLSCREEN: - window->fullscreen = value; - break; + window->maximized = 0; + window->fullscreen = 0; + window->resizing = 0; + window->focused = 0; + + wl_array_for_each(p, states) { + uint32_t state = *p; + switch (state) { + case XDG_SURFACE_STATE_MAXIMIZED: + window->maximized = 1; + break; + case XDG_SURFACE_STATE_FULLSCREEN: + window->fullscreen = 1; + break; + case XDG_SURFACE_STATE_RESIZING: + window->resizing = 1; + break; + case XDG_SURFACE_STATE_ACTIVATED: + window->focused = 1; + break; + default: + /* Unknown state */ + break; + } } - if (!window->fullscreen && !window->maximized) + if (window->frame) { + if (window->maximized) { + frame_set_flag(window->frame->frame, FRAME_FLAG_MAXIMIZED); + } else { + frame_unset_flag(window->frame->frame, FRAME_FLAG_MAXIMIZED); + } + + if (window->focused) { + frame_set_flag(window->frame->frame, FRAME_FLAG_ACTIVE); + } else { + frame_unset_flag(window->frame->frame, FRAME_FLAG_ACTIVE); + } + } + + if (width > 0 && height > 0) { + /* The width / height params are for window geometry, + * but window_schedule_resize takes allocation. Add + * on the shadow margin to get the difference. */ + int margin = window_get_shadow_margin(window); + + window_schedule_resize(window, + width + margin * 2, + height + margin * 2); + } else { window_schedule_resize(window, window->saved_allocation.width, window->saved_allocation.height); + } - xdg_surface_ack_change_state(xdg_surface, state, value, serial); - window_schedule_redraw(window); -} - -static void -handle_surface_activated(void *data, struct xdg_surface *xdg_surface) -{ - struct window *window = data; - window->focused = 1; -} + xdg_surface_ack_configure(window->xdg_surface, serial); -static void -handle_surface_deactivated(void *data, struct xdg_surface *xdg_surface) -{ - struct window *window = data; - window->focused = 0; + if (window->state_changed_handler) + window->state_changed_handler(window, window->user_data); } static void @@ -3905,47 +3911,53 @@ handle_surface_delete(void *data, struct xdg_surface *xdg_surface) static const struct xdg_surface_listener xdg_surface_listener = { handle_surface_configure, - handle_surface_change_state, - handle_surface_activated, - handle_surface_deactivated, handle_surface_delete, }; static void -window_sync_transient_for(struct window *window) +window_sync_parent(struct window *window) { struct wl_surface *parent_surface; if (!window->xdg_surface) return; - if (window->transient_for) - parent_surface = window->transient_for->main_surface->surface; + if (window->parent) + parent_surface = window->parent->main_surface->surface; else parent_surface = NULL; - xdg_surface_set_transient_for(window->xdg_surface, parent_surface); + xdg_surface_set_parent(window->xdg_surface, parent_surface); +} + +static void +window_get_geometry(struct window *window, struct rectangle *geometry) +{ + if (window->frame && !window->fullscreen) + frame_input_rect(window->frame->frame, + &geometry->x, + &geometry->y, + &geometry->width, + &geometry->height); + else + window_get_allocation(window, geometry); } static void -window_sync_margin(struct window *window) +window_sync_geometry(struct window *window) { - int margin; + struct rectangle geometry; if (!window->xdg_surface) return; - if (!window->frame) - return; + window_get_geometry(window, &geometry); - margin = frame_get_shadow_margin(window->frame->frame); - - /* Shadow size is the same on every side. */ - xdg_surface_set_margin(window->xdg_surface, - margin, - margin, - margin, - margin); + xdg_surface_set_window_geometry(window->xdg_surface, + geometry.x, + geometry.y, + geometry.width, + geometry.height); } static void @@ -3955,8 +3967,8 @@ window_flush(struct window *window) if (!window->custom) { if (window->xdg_surface) { - window_sync_transient_for(window); - window_sync_margin(window); + window_sync_parent(window); + window_sync_geometry(window); } } @@ -4145,10 +4157,10 @@ window_set_fullscreen(struct window *window, int fullscreen) if (window->fullscreen == fullscreen) return; - xdg_surface_request_change_state(window->xdg_surface, - XDG_SURFACE_STATE_FULLSCREEN, - fullscreen ? 1 : 0, - 0); + if (fullscreen) + xdg_surface_set_fullscreen(window->xdg_surface, NULL); + else + xdg_surface_unset_fullscreen(window->xdg_surface); } int @@ -4166,10 +4178,16 @@ window_set_maximized(struct window *window, int maximized) if (window->maximized == maximized) return; - xdg_surface_request_change_state(window->xdg_surface, - XDG_SURFACE_STATE_MAXIMIZED, - maximized ? 1 : 0, - 0); + if (maximized) + xdg_surface_set_maximized(window->xdg_surface); + else + xdg_surface_unset_maximized(window->xdg_surface); +} + +int +window_is_resizing(struct window *window) +{ + return window->resizing; } void @@ -4240,6 +4258,13 @@ window_set_output_handler(struct window *window, window->output_handler = handler; } +void +window_set_state_changed_handler(struct window *window, + window_state_changed_handler_t handler) +{ + window->state_changed_handler = handler; +} + void window_set_title(struct window *window, const char *title) { @@ -4428,17 +4453,17 @@ window_create_custom(struct display *display) } void -window_set_transient_for(struct window *window, - struct window *parent_window) +window_set_parent(struct window *window, + struct window *parent_window) { - window->transient_for = parent_window; - window_sync_transient_for(window); + window->parent = parent_window; + window_sync_parent(window); } struct window * -window_get_transient_for(struct window *window) +window_get_parent(struct window *window) { - return window->transient_for; + return window->parent; } static void @@ -4502,8 +4527,7 @@ menu_button_handler(struct widget *widget, (menu->release_count > 0 || time - menu->time > 500)) { /* Either relase after press-drag-release or * click-motion-click. */ - menu->func(menu->parent, input, - menu->current, menu->parent->user_data); + menu->func(menu->user_data, input, menu->current); input_ungrab(input); menu_destroy(menu); } else if (state == WL_POINTER_BUTTON_STATE_RELEASED) { @@ -4579,31 +4603,28 @@ static const struct xdg_popup_listener xdg_popup_listener = { handle_popup_popup_done, }; -void -window_show_menu(struct display *display, - struct input *input, uint32_t time, struct window *parent, - int32_t x, int32_t y, - menu_func_t func, const char **entries, int count) +static struct menu * +create_menu(struct display *display, + struct input *input, uint32_t time, + menu_func_t func, const char **entries, int count, + void *user_data) { struct window *window; struct menu *menu; - int32_t ix, iy; menu = malloc(sizeof *menu); if (!menu) - return; + return NULL; - window = window_create_internal(parent->display, 0); + window = window_create_internal(display, 0); if (!window) { free(menu); - return; + return NULL; } menu->window = window; - menu->parent = parent; + menu->user_data = user_data; menu->widget = window_add_widget(menu->window, menu); - window_set_buffer_scale (menu->window, window_get_buffer_scale (parent)); - window_set_buffer_transform (menu->window, window_get_buffer_transform (parent)); menu->frame = frame_create(window->display->theme, 0, 0, FRAME_BUTTON_NONE, NULL); fail_on_null(menu->frame); @@ -4614,8 +4635,6 @@ window_show_menu(struct display *display, menu->time = time; menu->func = func; menu->input = input; - window->x = x; - window->y = y; input_ungrab(input); @@ -4632,6 +4651,47 @@ window_show_menu(struct display *display, window_schedule_resize(window, frame_width(menu->frame), frame_height(menu->frame)); + return menu; +} + +struct window * +window_create_menu(struct display *display, + struct input *input, uint32_t time, + menu_func_t func, const char **entries, int count, + void *user_data) +{ + struct menu *menu; + menu = create_menu(display, input, time, func, entries, count, user_data); + + if (menu == NULL) + return NULL; + + return menu->window; +} + +void +window_show_menu(struct display *display, + struct input *input, uint32_t time, struct window *parent, + int32_t x, int32_t y, + menu_func_t func, const char **entries, int count) +{ + struct menu *menu; + struct window *window; + int32_t ix, iy; + + menu = create_menu(display, input, time, func, entries, count, parent); + + if (menu == NULL) + return; + + window = menu->window; + + window_set_buffer_scale (menu->window, window_get_buffer_scale (parent)); + window_set_buffer_transform (menu->window, window_get_buffer_transform (parent)); + + window->x = x; + window->y = y; + frame_interior(menu->frame, &ix, &iy, NULL, NULL); window->xdg_popup = xdg_shell_get_xdg_popup(display->xdg_shell, @@ -4946,7 +5006,7 @@ display_add_input(struct display *d, uint32_t id) input = xzalloc(sizeof *input); input->display = d; input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, - MIN(d->seat_version, 3)); + MIN(d->seat_version, 4)); input->touch_focus = NULL; input->pointer_focus = NULL; input->keyboard_focus = NULL; @@ -4967,6 +5027,8 @@ display_add_input(struct display *d, uint32_t id) input->pointer_surface = wl_compositor_create_surface(d->compositor); + set_repeat_info(input, 40, 400); + input->repeat_timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); input->repeat_task.run = keyboard_repeat_func; diff --git a/clients/window.h b/clients/window.h index 4e4ccc1d..5247f19c 100644 --- a/clients/window.h +++ b/clients/window.h @@ -219,6 +219,8 @@ typedef void (*window_fullscreen_handler_t)(struct window *window, void *data); typedef void (*window_output_handler_t)(struct window *window, struct output *output, int enter, void *data); +typedef void (*window_state_changed_handler_t)(struct window *window, + void *data); typedef void (*widget_resize_handler_t)(struct widget *widget, int32_t width, int32_t height, @@ -275,16 +277,20 @@ struct window * window_create_custom(struct display *display); void -window_set_transient_for(struct window *window, struct window *parent_window); +window_set_parent(struct window *window, struct window *parent_window); struct window * -window_get_transient_for(struct window *window); +window_get_parent(struct window *window); int window_has_focus(struct window *window); -typedef void (*menu_func_t)(struct window *window, - struct input *input, int index, void *data); +typedef void (*menu_func_t)(void *data, struct input *input, int index); +struct window * +window_create_menu(struct display *display, + struct input *input, uint32_t time, + menu_func_t func, const char **entries, int count, + void *user_data); void window_show_menu(struct display *display, struct input *input, uint32_t time, struct window *parent, @@ -381,6 +387,9 @@ window_is_maximized(struct window *window); void window_set_maximized(struct window *window, int maximized); +int +window_is_resizing(struct window *window); + void window_set_minimized(struct window *window); @@ -415,6 +424,9 @@ window_set_fullscreen_handler(struct window *window, void window_set_output_handler(struct window *window, window_output_handler_t handler); +void +window_set_state_changed_handler(struct window *window, + window_state_changed_handler_t handler); void window_set_title(struct window *window, const char *title); diff --git a/configure.ac b/configure.ac index 031a26f1..354db145 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ m4_define([weston_major_version], [1]) -m4_define([weston_minor_version], [4]) -m4_define([weston_micro_version], [93]) +m4_define([weston_minor_version], [5]) +m4_define([weston_micro_version], [90]) m4_define([weston_version], [weston_major_version.weston_minor_version.weston_micro_version]) @@ -18,6 +18,7 @@ AC_SUBST([WESTON_VERSION], [weston_version]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) AC_USE_SYSTEM_EXTENSIONS AC_SYS_LARGEFILE @@ -58,7 +59,7 @@ AC_CHECK_HEADERS([execinfo.h]) AC_CHECK_FUNCS([mkostemp strchrnul initgroups posix_fallocate]) -COMPOSITOR_MODULES="wayland-server >= 1.3.90 pixman-1" +COMPOSITOR_MODULES="wayland-server >= 1.3.90 pixman-1 >= 0.25.2" AC_ARG_ENABLE(egl, [ --disable-egl],, enable_egl=yes) @@ -159,7 +160,7 @@ AC_ARG_ENABLE(libinput-backend, [ --enable-libinput-backend],, AM_CONDITIONAL([ENABLE_LIBINPUT_BACKEND], [test x$enable_libinput_backend = xyes]) if test x$enable_libinput_backend = xyes; then AC_DEFINE([BUILD_LIBINPUT_BACKEND], [1], [Build the libinput input device backend]) - PKG_CHECK_MODULES(LIBINPUT_BACKEND, [libinput >= 0.1.0]) + PKG_CHECK_MODULES(LIBINPUT_BACKEND, [libinput >= 0.5.0]) fi diff --git a/desktop-shell/exposay.c b/desktop-shell/exposay.c index 1d8b40e1..4b65cbd1 100644 --- a/desktop-shell/exposay.c +++ b/desktop-shell/exposay.c @@ -219,7 +219,7 @@ exposay_layout(struct desktop_shell *shell, struct shell_output *shell_output) int last_row_removed = 0; eoutput->num_surfaces = 0; - wl_list_for_each(view, &workspace->layer.view_list, layer_link) { + wl_list_for_each(view, &workspace->layer.view_list.link, layer_link.link) { if (!get_shell_surface(view->surface)) continue; if (view->output != output) @@ -272,7 +272,7 @@ exposay_layout(struct desktop_shell *shell, struct shell_output *shell_output) eoutput->surface_size = output->height / 2; i = 0; - wl_list_for_each(view, &workspace->layer.view_list, layer_link) { + wl_list_for_each(view, &workspace->layer.view_list.link, layer_link.link) { int pad; pad = eoutput->surface_size + eoutput->padding_inner; @@ -323,8 +323,10 @@ exposay_layout(struct desktop_shell *shell, struct shell_output *shell_output) i++; } - if (highlight) + if (highlight) { + shell->exposay.focus_current = NULL; exposay_highlight_surface(shell, highlight); + } weston_compositor_schedule_repaint(shell->compositor); diff --git a/desktop-shell/input-panel.c b/desktop-shell/input-panel.c index 7623f6cb..435cd5d6 100644 --- a/desktop-shell/input-panel.c +++ b/desktop-shell/input-panel.c @@ -75,8 +75,8 @@ show_input_panel_surface(struct input_panel_surface *ipsurf) weston_view_set_position(ipsurf->view, x, y); } - wl_list_insert(&shell->input_panel_layer.view_list, - &ipsurf->view->layer_link); + weston_layer_entry_insert(&shell->input_panel_layer.view_list, + &ipsurf->view->layer_link); weston_view_geometry_dirty(ipsurf->view); weston_view_update_transform(ipsurf->view); weston_surface_damage(ipsurf->surface); @@ -135,7 +135,8 @@ hide_input_panels(struct wl_listener *listener, void *data) wl_list_remove(&shell->input_panel_layer.link); wl_list_for_each_safe(view, next, - &shell->input_panel_layer.view_list, layer_link) + &shell->input_panel_layer.view_list.link, + layer_link.link) weston_view_unmap(view); } @@ -355,7 +356,6 @@ bind_input_panel(struct wl_client *client, wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "interface object already bound"); - wl_resource_destroy(resource); } void diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index 84f5c838..ec722874 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -157,12 +157,11 @@ struct shell_surface { struct weston_output *fullscreen_output; struct weston_output *output; - struct weston_output *recommended_output; struct wl_list link; const struct weston_shell_client *client; - struct { + struct surface_state { bool maximized; bool fullscreen; bool relative; @@ -172,8 +171,9 @@ struct shell_surface { bool state_requested; struct { - int left, right, top, bottom; - } margin; + int32_t x, y, width, height; + } geometry, next_geometry; + bool has_set_geometry, has_next_geometry; int focus_count; }; @@ -279,12 +279,12 @@ shell_surface_is_top_fullscreen(struct shell_surface *shsurf) shell = shell_surface_get_shell(shsurf); - if (wl_list_empty(&shell->fullscreen_layer.view_list)) + if (wl_list_empty(&shell->fullscreen_layer.view_list.link)) return false; - top_fs_ev = container_of(shell->fullscreen_layer.view_list.next, + top_fs_ev = container_of(shell->fullscreen_layer.view_list.link.next, struct weston_view, - layer_link); + layer_link.link); return (shsurf == get_shell_surface(top_fs_ev->surface)); } @@ -351,13 +351,77 @@ shell_grab_start(struct shell_grab *grab, } } +static int +get_output_panel_height(struct desktop_shell *shell, + struct weston_output *output) +{ + struct weston_view *view; + int panel_height = 0; + + if (!output) + return 0; + + wl_list_for_each(view, &shell->panel_layer.view_list.link, layer_link.link) { + if (view->surface->output == output) { + panel_height = view->surface->height; + break; + } + } + + return panel_height; +} + +static void +send_configure_for_surface(struct shell_surface *shsurf) +{ + int32_t width, height; + struct surface_state *state; + + if (shsurf->state_requested) + state = &shsurf->requested_state; + else if (shsurf->state_changed) + state = &shsurf->next_state; + else + state = &shsurf->state; + + if (state->fullscreen) { + width = shsurf->output->width; + height = shsurf->output->height; + } else if (state->maximized) { + struct desktop_shell *shell; + uint32_t panel_height = 0; + + shell = shell_surface_get_shell(shsurf); + panel_height = get_output_panel_height(shell, shsurf->output); + + width = shsurf->output->width; + height = shsurf->output->height - panel_height; + } else { + width = 0; + height = 0; + } + + shsurf->client->send_configure(shsurf->surface, width, height); +} + +static void +shell_surface_state_changed(struct shell_surface *shsurf) +{ + if (shell_surface_is_xdg_surface(shsurf)) + send_configure_for_surface(shsurf); +} + static void shell_grab_end(struct shell_grab *grab) { if (grab->shsurf) { wl_list_remove(&grab->shsurf_destroy_listener.link); grab->shsurf->grabbed = 0; - grab->shsurf->resize_edges = 0; + + if (grab->shsurf->resize_edges) { + grab->shsurf->resize_edges = 0; + shell_surface_state_changed(grab->shsurf); + } } weston_pointer_end_grab(grab->grab.pointer); @@ -471,6 +535,9 @@ shell_configuration(struct desktop_shell *shell) weston_config_section_get_string(section, "animation", &s, "none"); shell->win_animation_type = get_animation_type(s); free(s); + weston_config_section_get_string(section, "close-animation", &s, "fade"); + shell->win_close_animation_type = get_animation_type(s); + free(s); weston_config_section_get_string(section, "startup-animation", &s, "fade"); shell->startup_animation_type = get_animation_type(s); @@ -611,7 +678,8 @@ focus_state_surface_destroy(struct wl_listener *listener, void *data) main_surface = weston_surface_get_main_surface(state->keyboard_focus); next = NULL; - wl_list_for_each(view, &state->ws->layer.view_list, layer_link) { + wl_list_for_each(view, + &state->ws->layer.view_list.link, layer_link.link) { if (view->surface == main_surface) continue; if (is_focus_view(view)) @@ -790,8 +858,8 @@ animate_focus_change(struct desktop_shell *shell, struct workspace *ws, focus_surface_created = true; } else { - wl_list_remove(&ws->fsurf_front->view->layer_link); - wl_list_remove(&ws->fsurf_back->view->layer_link); + weston_layer_entry_remove(&ws->fsurf_front->view->layer_link); + weston_layer_entry_remove(&ws->fsurf_back->view->layer_link); } if (ws->focus_animation) { @@ -800,30 +868,30 @@ animate_focus_change(struct desktop_shell *shell, struct workspace *ws, } if (to) - wl_list_insert(&to->layer_link, - &ws->fsurf_front->view->layer_link); + weston_layer_entry_insert(&to->layer_link, + &ws->fsurf_front->view->layer_link); else if (from) - wl_list_insert(&ws->layer.view_list, - &ws->fsurf_front->view->layer_link); + weston_layer_entry_insert(&ws->layer.view_list, + &ws->fsurf_front->view->layer_link); if (focus_surface_created) { ws->focus_animation = weston_fade_run( ws->fsurf_front->view, - ws->fsurf_front->view->alpha, 0.6, 300, + ws->fsurf_front->view->alpha, 0.4, 300, focus_animation_done, ws); } else if (from) { - wl_list_insert(&from->layer_link, - &ws->fsurf_back->view->layer_link); + weston_layer_entry_insert(&from->layer_link, + &ws->fsurf_back->view->layer_link); ws->focus_animation = weston_stable_fade_run( ws->fsurf_front->view, 0.0, - ws->fsurf_back->view, 0.6, + ws->fsurf_back->view, 0.4, focus_animation_done, ws); } else if (to) { - wl_list_insert(&ws->layer.view_list, - &ws->fsurf_back->view->layer_link); + weston_layer_entry_insert(&ws->layer.view_list, + &ws->fsurf_back->view->layer_link); ws->focus_animation = weston_stable_fade_run( ws->fsurf_front->view, 0.0, - ws->fsurf_back->view, 0.6, + ws->fsurf_back->view, 0.4, focus_animation_done, ws); } } @@ -880,7 +948,7 @@ workspace_create(void) static int workspace_is_empty(struct workspace *ws) { - return wl_list_empty(&ws->layer.view_list); + return wl_list_empty(&ws->layer.view_list.link); } static struct workspace * @@ -945,7 +1013,7 @@ workspace_translate_out(struct workspace *ws, double fraction) unsigned int height; double d; - wl_list_for_each(view, &ws->layer.view_list, layer_link) { + wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) { height = get_output_height(view->surface->output); d = height * fraction; @@ -960,7 +1028,7 @@ workspace_translate_in(struct workspace *ws, double fraction) unsigned int height; double d; - wl_list_for_each(view, &ws->layer.view_list, layer_link) { + wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) { height = get_output_height(view->surface->output); if (fraction > 0) @@ -1005,7 +1073,7 @@ workspace_deactivate_transforms(struct workspace *ws) struct weston_view *view; struct weston_transform *transform; - wl_list_for_each(view, &ws->layer.view_list, layer_link) { + wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) { if (is_focus_view(view)) { struct focus_surface *fsurf = get_focus_surface(view->surface); transform = &fsurf->workspace_transform; @@ -1035,7 +1103,7 @@ finish_workspace_change_animation(struct desktop_shell *shell, * visible after the workspace animation ends but before its layer * is hidden. In that case, we need to damage below those views so * that the screen is properly repainted. */ - wl_list_for_each(view, &from->layer.view_list, layer_link) + wl_list_for_each(view, &from->layer.view_list.link, layer_link.link) weston_view_damage_below(view); wl_list_remove(&shell->workspaces.animation.link); @@ -1154,7 +1222,7 @@ change_workspace(struct desktop_shell *shell, unsigned int index) return; /* Don't change workspace when there is any fullscreen surfaces. */ - if (!wl_list_empty(&shell->fullscreen_layer.view_list)) + if (!wl_list_empty(&shell->fullscreen_layer.view_list.link)) return; from = get_current_workspace(shell); @@ -1198,7 +1266,7 @@ change_workspace(struct desktop_shell *shell, unsigned int index) static bool workspace_has_only(struct workspace *ws, struct weston_surface *surface) { - struct wl_list *list = &ws->layer.view_list; + struct wl_list *list = &ws->layer.view_list.link; struct wl_list *e; if (wl_list_empty(list)) @@ -1209,7 +1277,7 @@ workspace_has_only(struct workspace *ws, struct weston_surface *surface) if (e->next != list) return false; - return container_of(e, struct weston_view, layer_link)->surface == surface; + return container_of(e, struct weston_view, layer_link.link)->surface == surface; } static void @@ -1238,8 +1306,8 @@ move_surface_to_workspace(struct desktop_shell *shell, from = get_current_workspace(shell); to = get_workspace(shell, workspace); - wl_list_remove(&view->layer_link); - wl_list_insert(&to->layer.view_list, &view->layer_link); + weston_layer_entry_remove(&view->layer_link); + weston_layer_entry_insert(&to->layer.view_list, &view->layer_link); shell_surface_update_child_surface_layers(shsurf); @@ -1278,8 +1346,8 @@ take_surface_to_workspace_by_seat(struct desktop_shell *shell, from = get_current_workspace(shell); to = get_workspace(shell, index); - wl_list_remove(&view->layer_link); - wl_list_insert(&to->layer.view_list, &view->layer_link); + weston_layer_entry_remove(&view->layer_link); + weston_layer_entry_insert(&to->layer.view_list, &view->layer_link); shsurf = get_shell_surface(surface); if (shsurf != NULL) @@ -1490,14 +1558,12 @@ constrain_position(struct weston_move_grab *move, int *cx, int *cy) panel_height = get_output_panel_height(shsurf->shell, shsurf->surface->output); - bottom = y + shsurf->surface->height - shsurf->margin.bottom; + bottom = y + shsurf->geometry.height; if (bottom - panel_height < safety) - y = panel_height + safety - - shsurf->surface->height + shsurf->margin.bottom; + y = panel_height + safety - shsurf->geometry.height; - if (move->client_initiated && - y + shsurf->margin.top < panel_height) - y = panel_height - shsurf->margin.top; + if (move->client_initiated && y + shsurf->geometry.y < panel_height) + y = panel_height - shsurf->geometry.y; *cx = x; *cy = y; @@ -1765,10 +1831,12 @@ surface_resize(struct shell_surface *shsurf, return -1; resize->edges = edges; - surface_subsurfaces_boundingbox(shsurf->surface, NULL, NULL, - &resize->width, &resize->height); + + resize->width = shsurf->geometry.width; + resize->height = shsurf->geometry.height; shsurf->resize_edges = edges; + shell_surface_state_changed(shsurf); shell_grab_start(&resize->base, &resize_grab_interface, shsurf, seat->pointer, edges); @@ -1784,7 +1852,8 @@ common_surface_resize(struct wl_resource *resource, struct shell_surface *shsurf = wl_resource_get_user_data(resource); struct weston_surface *surface; - if (seat->pointer->button_count == 0 || + if (seat->pointer == NULL || + seat->pointer->button_count == 0 || seat->pointer->grab_serial != serial || seat->pointer->focus == NULL) return; @@ -1994,16 +2063,14 @@ static void shell_surface_lose_keyboard_focus(struct shell_surface *shsurf) { if (--shsurf->focus_count == 0) - if (shell_surface_is_xdg_surface(shsurf)) - xdg_surface_send_deactivated(shsurf->resource); + shell_surface_state_changed(shsurf); } static void shell_surface_gain_keyboard_focus(struct shell_surface *shsurf) { if (shsurf->focus_count++ == 0) - if (shell_surface_is_xdg_surface(shsurf)) - xdg_surface_send_activated(shsurf->resource); + shell_surface_state_changed(shsurf); } static void @@ -2061,13 +2128,14 @@ set_title(struct shell_surface *shsurf, const char *title) } static void -set_margin(struct shell_surface *shsurf, - int32_t left, int32_t right, int32_t top, int32_t bottom) +set_window_geometry(struct shell_surface *shsurf, + int32_t x, int32_t y, int32_t width, int32_t height) { - shsurf->margin.left = left; - shsurf->margin.right = right; - shsurf->margin.top = top; - shsurf->margin.bottom = bottom; + shsurf->next_geometry.x = x; + shsurf->next_geometry.y = y; + shsurf->next_geometry.width = width; + shsurf->next_geometry.height = height; + shsurf->has_next_geometry = true; } static void @@ -2109,30 +2177,10 @@ restore_all_output_modes(struct weston_compositor *compositor) restore_output_mode(output); } -static int -get_output_panel_height(struct desktop_shell *shell, - struct weston_output *output) -{ - struct weston_view *view; - int panel_height = 0; - - if (!output) - return 0; - - wl_list_for_each(view, &shell->panel_layer.view_list, layer_link) { - if (view->surface->output == output) { - panel_height = view->surface->height; - break; - } - } - - return panel_height; -} - /* The surface will be inserted into the list immediately after the link * returned by this function (i.e. will be stacked immediately above the * returned link). */ -static struct wl_list * +static struct weston_layer_entry * shell_surface_calculate_layer_link (struct shell_surface *shsurf) { struct workspace *ws; @@ -2158,7 +2206,8 @@ shell_surface_calculate_layer_link (struct shell_surface *shsurf) /* TODO: Handle a parent with multiple views */ parent = get_default_view(shsurf->parent); if (parent) - return parent->layer_link.prev; + return container_of(parent->layer_link.link.prev, + struct weston_layer_entry, link); } /* Move the surface to a normal workspace layer so that surfaces @@ -2175,16 +2224,19 @@ static void shell_surface_update_child_surface_layers (struct shell_surface *shsurf) { struct shell_surface *child; + struct weston_layer_entry *prev; /* Move the child layers to the same workspace as shsurf. They will be * stacked above shsurf. */ wl_list_for_each_reverse(child, &shsurf->children_list, children_link) { - if (shsurf->view->layer_link.prev != &child->view->layer_link) { + if (shsurf->view->layer_link.link.prev != &child->view->layer_link.link) { weston_view_damage_below(child->view); weston_view_geometry_dirty(child->view); - wl_list_remove(&child->view->layer_link); - wl_list_insert(shsurf->view->layer_link.prev, - &child->view->layer_link); + prev = container_of(shsurf->view->layer_link.link.prev, + struct weston_layer_entry, link); + weston_layer_entry_remove(&child->view->layer_link); + weston_layer_entry_insert(prev, + &child->view->layer_link); weston_view_geometry_dirty(child->view); weston_surface_damage(child->surface); @@ -2205,7 +2257,7 @@ shell_surface_update_child_surface_layers (struct shell_surface *shsurf) static void shell_surface_update_layer(struct shell_surface *shsurf) { - struct wl_list *new_layer_link; + struct weston_layer_entry *new_layer_link; new_layer_link = shell_surface_calculate_layer_link(shsurf); @@ -2215,8 +2267,8 @@ shell_surface_update_layer(struct shell_surface *shsurf) return; weston_view_geometry_dirty(shsurf->view); - wl_list_remove(&shsurf->view->layer_link); - wl_list_insert(new_layer_link, &shsurf->view->layer_link); + weston_layer_entry_remove(&shsurf->view->layer_link); + weston_layer_entry_insert(new_layer_link, &shsurf->view->layer_link); weston_view_geometry_dirty(shsurf->view); weston_surface_damage(shsurf->surface); @@ -2330,19 +2382,13 @@ set_fullscreen(struct shell_surface *shsurf, struct weston_output *output) { shell_surface_set_output(shsurf, output); + shsurf->type = SHELL_SURFACE_TOPLEVEL; shsurf->fullscreen_output = shsurf->output; shsurf->fullscreen.type = method; shsurf->fullscreen.framerate = framerate; - shsurf->type = SHELL_SURFACE_TOPLEVEL; - - shsurf->client->send_configure(shsurf->surface, - shsurf->output->width, - shsurf->output->height); - - /* The layer_link is updated in set_surface_type(), - * called from configure. */ + send_configure_for_surface(shsurf); } static void @@ -2401,10 +2447,9 @@ shell_surface_set_fullscreen(struct wl_client *client, shell_surface_set_parent(shsurf, NULL); surface_clear_next_states(shsurf); - set_fullscreen(shsurf, method, framerate, output); - shsurf->next_state.fullscreen = true; shsurf->state_changed = true; + set_fullscreen(shsurf, method, framerate, output); } static void @@ -2446,25 +2491,6 @@ shell_surface_set_popup(struct wl_client *client, serial, x, y); } -static void -set_maximized(struct shell_surface *shsurf, - struct weston_output *output) -{ - struct desktop_shell *shell; - uint32_t panel_height = 0; - - shell_surface_set_output(shsurf, output); - - shell = shell_surface_get_shell(shsurf); - panel_height = get_output_panel_height(shell, shsurf->output); - - shsurf->client->send_configure(shsurf->surface, - shsurf->output->width, - shsurf->output->height - panel_height); - - shsurf->type = SHELL_SURFACE_TOPLEVEL; -} - static void unset_maximized(struct shell_surface *shsurf) { @@ -2504,10 +2530,10 @@ set_minimized(struct weston_surface *surface, uint32_t is_true) shsurf = get_shell_surface(surface); current_ws = get_current_workspace(shsurf->shell); - wl_list_remove(&view->layer_link); + weston_layer_entry_remove(&view->layer_link); /* hide or show, depending on the state */ if (is_true) { - wl_list_insert(&shsurf->shell->minimized_layer.view_list, &view->layer_link); + weston_layer_entry_insert(&shsurf->shell->minimized_layer.view_list, &view->layer_link); drop_focus_state(shsurf->shell, current_ws, view->surface); wl_list_for_each(seat, &shsurf->shell->compositor->seat_list, link) { @@ -2519,7 +2545,7 @@ set_minimized(struct weston_surface *surface, uint32_t is_true) } } else { - wl_list_insert(¤t_ws->layer.view_list, &view->layer_link); + weston_layer_entry_insert(¤t_ws->layer.view_list, &view->layer_link); wl_list_for_each(seat, &shsurf->shell->compositor->seat_list, link) { if (!seat->keyboard) @@ -2541,18 +2567,21 @@ shell_surface_set_maximized(struct wl_client *client, struct shell_surface *shsurf = wl_resource_get_user_data(resource); struct weston_output *output; + surface_clear_next_states(shsurf); + shsurf->next_state.maximized = true; + shsurf->state_changed = true; + + shsurf->type = SHELL_SURFACE_TOPLEVEL; + shell_surface_set_parent(shsurf, NULL); + if (output_resource) output = wl_resource_get_user_data(output_resource); else output = NULL; - shell_surface_set_parent(shsurf, NULL); - - surface_clear_next_states(shsurf); - set_maximized(shsurf, output); + shell_surface_set_output(shsurf, output); - shsurf->next_state.maximized = true; - shsurf->state_changed = true; + send_configure_for_surface(shsurf); } /* This is only ever called from set_surface_type(), so there’s no need to @@ -2682,9 +2711,9 @@ shell_ensure_fullscreen_black_view(struct shell_surface *shsurf) output->height); weston_view_geometry_dirty(shsurf->fullscreen.black_view); - wl_list_remove(&shsurf->fullscreen.black_view->layer_link); - wl_list_insert(&shsurf->view->layer_link, - &shsurf->fullscreen.black_view->layer_link); + weston_layer_entry_remove(&shsurf->fullscreen.black_view->layer_link); + weston_layer_entry_insert(&shsurf->view->layer_link, + &shsurf->fullscreen.black_view->layer_link); weston_view_geometry_dirty(shsurf->fullscreen.black_view); weston_surface_damage(shsurf->surface); @@ -2706,8 +2735,8 @@ shell_configure_fullscreen(struct shell_surface *shsurf) restore_output_mode(output); /* Reverse the effect of lower_fullscreen_layer() */ - wl_list_remove(&shsurf->view->layer_link); - wl_list_insert(&shsurf->shell->fullscreen_layer.view_list, &shsurf->view->layer_link); + weston_layer_entry_remove(&shsurf->view->layer_link); + weston_layer_entry_insert(&shsurf->shell->fullscreen_layer.view_list, &shsurf->view->layer_link); shell_ensure_fullscreen_black_view(shsurf); @@ -2953,6 +2982,11 @@ popup_grab_motion(struct weston_pointer_grab *grab, uint32_t time, struct wl_resource *resource; wl_fixed_t sx, sy; + if (pointer->focus) { + weston_view_from_global_fixed(pointer->focus, x, y, + &pointer->sx, &pointer->sy); + } + weston_pointer_move(pointer, x, y); wl_resource_for_each(resource, &pointer->focus_resource_list) { @@ -3090,7 +3124,8 @@ shell_map_popup(struct shell_surface *shsurf) weston_view_set_position(shsurf->view, shsurf->popup.x, shsurf->popup.y); weston_view_update_transform(shsurf->view); - if (shseat->seat->pointer->grab_serial == shsurf->popup.serial) { + if (shseat->seat->pointer && + shseat->seat->pointer->grab_serial == shsurf->popup.serial) { add_popup_grab(shsurf, shseat); } else { shell_surface_send_popup_done(shsurf); @@ -3193,8 +3228,12 @@ handle_resource_destroy(struct wl_listener *listener, void *data) pixman_region32_init(&shsurf->surface->pending.input); pixman_region32_fini(&shsurf->surface->input); pixman_region32_init(&shsurf->surface->input); - weston_fade_run(shsurf->view, 1.0, 0.0, 300.0, - fade_out_done, shsurf); + if (shsurf->shell->win_close_animation_type == ANIMATION_FADE) { + weston_fade_run(shsurf->view, 1.0, 0.0, 300.0, + fade_out_done, shsurf); + } else { + weston_surface_destroy(shsurf->surface); + } } static void @@ -3253,6 +3292,8 @@ create_common_surface(struct shell_client *owner, void *shell, shsurf->fullscreen.black_view = NULL; wl_list_init(&shsurf->fullscreen.transform.link); + shsurf->output = get_default_output(shsurf->shell->compositor); + wl_signal_init(&shsurf->destroy_signal); shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy; wl_signal_add(&surface->destroy_signal, @@ -3354,9 +3395,9 @@ xdg_surface_destroy(struct wl_client *client, } static void -xdg_surface_set_transient_for(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *parent_resource) +xdg_surface_set_parent(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *parent_resource) { struct shell_surface *shsurf = wl_resource_get_user_data(resource); struct weston_surface *parent; @@ -3369,19 +3410,6 @@ xdg_surface_set_transient_for(struct wl_client *client, shell_surface_set_parent(shsurf, parent); } -static void -xdg_surface_set_margin(struct wl_client *client, - struct wl_resource *resource, - int32_t left, - int32_t right, - int32_t top, - int32_t bottom) -{ - struct shell_surface *shsurf = wl_resource_get_user_data(resource); - - set_margin(shsurf, left, right, top, bottom); -} - static void xdg_surface_set_app_id(struct wl_client *client, struct wl_resource *resource, @@ -3393,6 +3421,17 @@ xdg_surface_set_app_id(struct wl_client *client, shsurf->class = strdup(app_id); } +static void +xdg_surface_show_window_menu(struct wl_client *client, + struct wl_resource *surface_resource, + struct wl_resource *seat_resource, + uint32_t serial, + int32_t x, + int32_t y) +{ + /* TODO */ +} + static void xdg_surface_set_title(struct wl_client *client, struct wl_resource *resource, const char *title) @@ -3418,86 +3457,85 @@ xdg_surface_resize(struct wl_client *client, struct wl_resource *resource, } static void -xdg_surface_set_output(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *output_resource) +xdg_surface_ack_configure(struct wl_client *client, + struct wl_resource *resource, + uint32_t serial) { struct shell_surface *shsurf = wl_resource_get_user_data(resource); - struct weston_output *output; - if (output_resource) - output = wl_resource_get_user_data(output_resource); - else - output = NULL; + if (shsurf->state_requested) { + shsurf->next_state = shsurf->requested_state; + shsurf->state_changed = true; + shsurf->state_requested = false; + } +} - shsurf->recommended_output = output; +static void +xdg_surface_set_window_geometry(struct wl_client *client, + struct wl_resource *resource, + int32_t x, + int32_t y, + int32_t width, + int32_t height) +{ + struct shell_surface *shsurf = wl_resource_get_user_data(resource); + + set_window_geometry(shsurf, x, y, width, height); } static void -xdg_surface_change_state(struct shell_surface *shsurf, - uint32_t state, uint32_t value, uint32_t serial) +xdg_surface_set_maximized(struct wl_client *client, + struct wl_resource *resource) { - xdg_surface_send_change_state(shsurf->resource, state, value, serial); + struct shell_surface *shsurf = wl_resource_get_user_data(resource); + shsurf->state_requested = true; + shsurf->requested_state.maximized = true; + send_configure_for_surface(shsurf); +} - switch (state) { - case XDG_SURFACE_STATE_MAXIMIZED: - shsurf->requested_state.maximized = value; - if (value) - set_maximized(shsurf, NULL); - break; - case XDG_SURFACE_STATE_FULLSCREEN: - shsurf->requested_state.fullscreen = value; +static void +xdg_surface_unset_maximized(struct wl_client *client, + struct wl_resource *resource) +{ + struct shell_surface *shsurf = wl_resource_get_user_data(resource); - if (value) - set_fullscreen(shsurf, - WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, - 0, shsurf->recommended_output); - break; - } + shsurf->state_requested = true; + shsurf->requested_state.maximized = false; + send_configure_for_surface(shsurf); } static void -xdg_surface_request_change_state(struct wl_client *client, - struct wl_resource *resource, - uint32_t state, - uint32_t value, - uint32_t serial) +xdg_surface_set_fullscreen(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *output_resource) { struct shell_surface *shsurf = wl_resource_get_user_data(resource); + struct weston_output *output; - /* The client can't know what the current state is, so we need - to always send a state change in response. */ + shsurf->state_requested = true; + shsurf->requested_state.fullscreen = true; - if (shsurf->type != SHELL_SURFACE_TOPLEVEL) - return; + if (output_resource) + output = wl_resource_get_user_data(output_resource); + else + output = NULL; - switch (state) { - case XDG_SURFACE_STATE_MAXIMIZED: - case XDG_SURFACE_STATE_FULLSCREEN: - break; - default: - /* send error? ignore? send change state with value 0? */ - return; - } + shell_surface_set_output(shsurf, output); + shsurf->fullscreen_output = shsurf->output; - xdg_surface_change_state(shsurf, state, value, serial); + send_configure_for_surface(shsurf); } static void -xdg_surface_ack_change_state(struct wl_client *client, - struct wl_resource *resource, - uint32_t state, - uint32_t value, - uint32_t serial) +xdg_surface_unset_fullscreen(struct wl_client *client, + struct wl_resource *resource) { struct shell_surface *shsurf = wl_resource_get_user_data(resource); - if (shsurf->state_requested) { - shsurf->next_state = shsurf->requested_state; - shsurf->state_changed = true; - shsurf->state_requested = false; - } + shsurf->state_requested = true; + shsurf->requested_state.fullscreen = false; + send_configure_for_surface(shsurf); } static void @@ -3515,16 +3553,19 @@ xdg_surface_set_minimized(struct wl_client *client, static const struct xdg_surface_interface xdg_surface_implementation = { xdg_surface_destroy, - xdg_surface_set_transient_for, - xdg_surface_set_margin, + xdg_surface_set_parent, xdg_surface_set_title, xdg_surface_set_app_id, + xdg_surface_show_window_menu, xdg_surface_move, xdg_surface_resize, - xdg_surface_set_output, - xdg_surface_request_change_state, - xdg_surface_ack_change_state, - xdg_surface_set_minimized + xdg_surface_ack_configure, + xdg_surface_set_window_geometry, + xdg_surface_set_maximized, + xdg_surface_unset_maximized, + xdg_surface_set_fullscreen, + xdg_surface_unset_fullscreen, + xdg_surface_set_minimized, }; static void @@ -3532,11 +3573,36 @@ xdg_send_configure(struct weston_surface *surface, int32_t width, int32_t height) { struct shell_surface *shsurf = get_shell_surface(surface); + uint32_t *s; + struct wl_array states; + uint32_t serial; assert(shsurf); - if (shsurf->resource) - xdg_surface_send_configure(shsurf->resource, width, height); + if (!shsurf->resource) + return; + + wl_array_init(&states); + if (shsurf->requested_state.fullscreen) { + s = wl_array_add(&states, sizeof *s); + *s = XDG_SURFACE_STATE_FULLSCREEN; + } else if (shsurf->requested_state.maximized) { + s = wl_array_add(&states, sizeof *s); + *s = XDG_SURFACE_STATE_MAXIMIZED; + } + if (shsurf->resize_edges != 0) { + s = wl_array_add(&states, sizeof *s); + *s = XDG_SURFACE_STATE_RESIZING; + } + if (shsurf->focus_count > 0) { + s = wl_array_add(&states, sizeof *s); + *s = XDG_SURFACE_STATE_ACTIVATED; + } + + serial = wl_display_next_serial(shsurf->surface->compositor->wl_display); + xdg_surface_send_configure(shsurf->resource, width, height, &states, serial); + + wl_array_release(&states); } static const struct weston_shell_client xdg_client = { @@ -3687,6 +3753,7 @@ xdg_get_xdg_popup(struct wl_client *client, wl_resource_post_error(surface_resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "xdg_shell::get_xdg_popup requires a parent shell surface"); + return; } parent = wl_resource_get_user_data(parent_resource); @@ -3839,7 +3906,7 @@ configure_static_view(struct weston_view *ev, struct weston_layer *layer) { struct weston_view *v, *next; - wl_list_for_each_safe(v, next, &layer->view_list, layer_link) { + wl_list_for_each_safe(v, next, &layer->view_list.link, layer_link.link) { if (v->output == ev->output && v != ev) { weston_view_unmap(v); v->surface->configure = NULL; @@ -3848,8 +3915,8 @@ configure_static_view(struct weston_view *ev, struct weston_layer *layer) weston_view_set_position(ev, ev->output->x, ev->output->y); - if (wl_list_empty(&ev->layer_link)) { - wl_list_insert(&layer->view_list, &ev->layer_link); + if (wl_list_empty(&ev->layer_link.link)) { + weston_layer_entry_insert(&layer->view_list, &ev->layer_link); weston_compositor_schedule_repaint(ev->surface->compositor); } } @@ -3954,8 +4021,8 @@ lock_surface_configure(struct weston_surface *surface, int32_t sx, int32_t sy) center_on_output(view, get_default_output(shell->compositor)); if (!weston_surface_is_mapped(surface)) { - wl_list_insert(&shell->lock_layer.view_list, - &view->layer_link); + weston_layer_entry_insert(&shell->lock_layer.view_list, + &view->layer_link); weston_view_update_transform(view); shell_fade(shell, FADE_IN); } @@ -4107,7 +4174,6 @@ maximize_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void struct weston_surface *focus = seat->keyboard->focus; struct weston_surface *surface; struct shell_surface *shsurf; - uint32_t serial; surface = weston_surface_get_main_surface(focus); if (surface == NULL) @@ -4120,9 +4186,9 @@ maximize_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void if (!shell_surface_is_xdg_surface(shsurf)) return; - serial = wl_display_next_serial(seat->compositor->wl_display); - xdg_surface_change_state(shsurf, XDG_SURFACE_STATE_MAXIMIZED, - !shsurf->state.maximized, serial); + shsurf->state_requested = true; + shsurf->requested_state.maximized = !shsurf->state.maximized; + send_configure_for_surface(shsurf); } static void @@ -4131,7 +4197,6 @@ fullscreen_binding(struct weston_seat *seat, uint32_t time, uint32_t button, voi struct weston_surface *focus = seat->keyboard->focus; struct weston_surface *surface; struct shell_surface *shsurf; - uint32_t serial; surface = weston_surface_get_main_surface(focus); if (surface == NULL) @@ -4144,9 +4209,10 @@ fullscreen_binding(struct weston_seat *seat, uint32_t time, uint32_t button, voi if (!shell_surface_is_xdg_surface(shsurf)) return; - serial = wl_display_next_serial(seat->compositor->wl_display); - xdg_surface_change_state(shsurf, XDG_SURFACE_STATE_FULLSCREEN, - !shsurf->state.fullscreen, serial); + shsurf->state_requested = true; + shsurf->requested_state.fullscreen = !shsurf->state.fullscreen; + shsurf->fullscreen_output = shsurf->output; + send_configure_for_surface(shsurf); } static void @@ -4486,8 +4552,8 @@ lower_fullscreen_layer(struct desktop_shell *shell) ws = get_current_workspace(shell); wl_list_for_each_reverse_safe(view, prev, - &shell->fullscreen_layer.view_list, - layer_link) { + &shell->fullscreen_layer.view_list.link, + layer_link.link) { struct shell_surface *shsurf = get_shell_surface(view->surface); if (!shsurf) @@ -4497,15 +4563,15 @@ lower_fullscreen_layer(struct desktop_shell *shell) * in the fullscreen layer. */ if (shsurf->state.fullscreen) { /* Hide the black view */ - wl_list_remove(&shsurf->fullscreen.black_view->layer_link); - wl_list_init(&shsurf->fullscreen.black_view->layer_link); + weston_layer_entry_remove(&shsurf->fullscreen.black_view->layer_link); + wl_list_init(&shsurf->fullscreen.black_view->layer_link.link); weston_view_damage_below(shsurf->fullscreen.black_view); } /* Lower the view to the workspace layer */ - wl_list_remove(&view->layer_link); - wl_list_insert(&ws->layer.view_list, &view->layer_link); + weston_layer_entry_remove(&view->layer_link); + weston_layer_entry_insert(&ws->layer.view_list, &view->layer_link); weston_view_damage_below(view); weston_surface_damage(view->surface); @@ -4724,8 +4790,8 @@ shell_fade_create_surface(struct desktop_shell *shell) weston_surface_set_size(surface, 8192, 8192); weston_view_set_position(view, 0, 0); weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0); - wl_list_insert(&compositor->fade_layer.view_list, - &view->layer_link); + weston_layer_entry_insert(&compositor->fade_layer.view_list, + &view->layer_link); pixman_region32_init(&surface->input); return view; @@ -5088,6 +5154,18 @@ shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy) if (es->width == 0) return; + if (shsurf->has_next_geometry) { + shsurf->geometry = shsurf->next_geometry; + shsurf->has_next_geometry = false; + shsurf->has_set_geometry = true; + } else if (!shsurf->has_set_geometry) { + surface_subsurfaces_boundingbox(shsurf->surface, + &shsurf->geometry.x, + &shsurf->geometry.y, + &shsurf->geometry.width, + &shsurf->geometry.height); + } + if (shsurf->state_changed) { set_surface_type(shsurf); type_changed = 1; @@ -5282,7 +5360,6 @@ bind_desktop_shell(struct wl_client *client, wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "permission to bind desktop_shell denied"); - wl_resource_destroy(resource); } static void @@ -5290,6 +5367,7 @@ screensaver_configure(struct weston_surface *surface, int32_t sx, int32_t sy) { struct desktop_shell *shell = surface->configure_private; struct weston_view *view; + struct weston_layer_entry *prev; if (surface->width == 0) return; @@ -5301,9 +5379,10 @@ screensaver_configure(struct weston_surface *surface, int32_t sx, int32_t sy) view = container_of(surface->views.next, struct weston_view, surface_link); center_on_output(view, surface->output); - if (wl_list_empty(&view->layer_link)) { - wl_list_insert(shell->lock_layer.view_list.prev, - &view->layer_link); + if (wl_list_empty(&view->layer_link.link)) { + prev = container_of(shell->lock_layer.view_list.link.prev, + struct weston_layer_entry, link); + weston_layer_entry_insert(prev, &view->layer_link); weston_view_update_transform(view); wl_event_source_timer_update(shell->screensaver.timer, shell->screensaver.duration); @@ -5364,7 +5443,6 @@ bind_screensaver(struct wl_client *client, wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "interface object already bound"); - wl_resource_destroy(resource); } struct switcher { @@ -5386,14 +5464,14 @@ switcher_next(struct switcher *switcher) /* temporary re-display minimized surfaces */ struct weston_view *tmp; struct weston_view **minimized; - wl_list_for_each_safe(view, tmp, &switcher->shell->minimized_layer.view_list, layer_link) { - wl_list_remove(&view->layer_link); - wl_list_insert(&ws->layer.view_list, &view->layer_link); + wl_list_for_each_safe(view, tmp, &switcher->shell->minimized_layer.view_list.link, layer_link.link) { + weston_layer_entry_remove(&view->layer_link); + weston_layer_entry_insert(&ws->layer.view_list, &view->layer_link); minimized = wl_array_add(&switcher->minimized_array, sizeof *minimized); *minimized = view; } - wl_list_for_each(view, &ws->layer.view_list, layer_link) { + wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) { shsurf = get_shell_surface(view->surface); if (shsurf && shsurf->type == SHELL_SURFACE_TOPLEVEL && @@ -5449,7 +5527,7 @@ switcher_destroy(struct switcher *switcher) struct weston_keyboard *keyboard = switcher->grab.keyboard; struct workspace *ws = get_current_workspace(switcher->shell); - wl_list_for_each(view, &ws->layer.view_list, layer_link) { + wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) { if (is_focus_view(view)) continue; @@ -5470,8 +5548,8 @@ switcher_destroy(struct switcher *switcher) wl_array_for_each(minimized, &switcher->minimized_array) { /* with the exception of the current selected */ if ((*minimized)->surface != switcher->current) { - wl_list_remove(&(*minimized)->layer_link); - wl_list_insert(&switcher->shell->minimized_layer.view_list, &(*minimized)->layer_link); + weston_layer_entry_remove(&(*minimized)->layer_link); + weston_layer_entry_insert(&switcher->shell->minimized_layer.view_list, &(*minimized)->layer_link); weston_view_damage_below(*minimized); } } @@ -5875,7 +5953,7 @@ shell_output_destroy_move_layer(struct desktop_shell *shell, struct weston_output *output = data; struct weston_view *view; - wl_list_for_each(view, &layer->view_list, layer_link) { + wl_list_for_each(view, &layer->view_list.link, layer_link.link) { if (view->output != output) continue; @@ -5934,7 +6012,7 @@ handle_output_move_layer(struct desktop_shell *shell, struct weston_view *view; float x, y; - wl_list_for_each(view, &layer->view_list, layer_link) { + wl_list_for_each(view, &layer->view_list.link, layer_link.link) { if (view->output != output) continue; @@ -6142,7 +6220,7 @@ module_init(struct weston_compositor *ec, ec->shell_interface.move = shell_interface_move; ec->shell_interface.resize = surface_resize; ec->shell_interface.set_title = set_title; - ec->shell_interface.set_margin = set_margin; + ec->shell_interface.set_window_geometry = set_window_geometry; weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link); weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link); diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h index 6e637850..e994cdbe 100644 --- a/desktop-shell/shell.h +++ b/desktop-shell/shell.h @@ -194,6 +194,7 @@ struct desktop_shell { uint32_t binding_modifier; uint32_t exposay_modifier; enum animation_type win_animation_type; + enum animation_type win_close_animation_type; enum animation_type startup_animation_type; enum animation_type focus_animation_type; diff --git a/fullscreen-shell/fullscreen-shell.c b/fullscreen-shell/fullscreen-shell.c index a8dad8e6..25932d44 100644 --- a/fullscreen-shell/fullscreen-shell.c +++ b/fullscreen-shell/fullscreen-shell.c @@ -262,7 +262,7 @@ fs_output_create(struct fullscreen_shell *shell, struct weston_output *output) fsout->black_view = create_black_surface(shell->compositor, fsout, output->x, output->y, output->width, output->height); - wl_list_insert(&shell->layer.view_list, + weston_layer_entry_insert(&shell->layer.view_list, &fsout->black_view->layer_link); wl_list_init(&fsout->transform.link); return fsout; @@ -573,7 +573,7 @@ fs_output_apply_pending(struct fs_output *fsout) wl_signal_add(&fsout->surface->destroy_signal, &fsout->surface_destroyed); - wl_list_insert(&fsout->shell->layer.view_list, + weston_layer_entry_insert(&fsout->shell->layer.view_list, &fsout->view->layer_link); } diff --git a/m4/.gitignore b/m4/.gitignore new file mode 100644 index 00000000..38066ddf --- /dev/null +++ b/m4/.gitignore @@ -0,0 +1,5 @@ +libtool.m4 +ltoptions.m4 +ltsugar.m4 +ltversion.m4 +lt~obsolete.m4 diff --git a/man/weston.ini.man b/man/weston.ini.man index 667f70a0..fbcec81a 100644 --- a/man/weston.ini.man +++ b/man/weston.ini.man @@ -186,6 +186,11 @@ digit pairs are in order transparency, red, green, and blue. Examples: .fi .RE .TP 7 +.BI "panel-location=" top +sets the location of the panel (string). Can be +.B top, +.B none. +.TP 7 .BI "locking=" true enables screen locking (boolean). .TP 7 @@ -196,6 +201,12 @@ sets the effect used for opening new windows (string). Can be .B none. By default, no animation is used. .TP 7 +.BI "close-animation=" fade +sets the effect used when closing windows (string). Can be +.B fade, +.B none. +By default, the fade animation is used. +.TP 7 .BI "startup-animation=" fade sets the effect used for opening new windows (string). Can be .B fade, @@ -396,6 +407,17 @@ sets the keymap options (string). See the Options section in .B "xkeyboard-config(7)." .RE .RE +.TP 7 +.BI "repeat-rate=" "40" +sets the rate of repeating keys in characters per second (unsigned integer) +.RE +.RE +.TP 7 +.BI "repeat-delay=" "400" +sets the delay in milliseconds since key down until repeating starts (unsigned +integer) +.RE +.RE .SH "TERMINAL SECTION" Contains settings for the weston terminal application (weston-terminal). It allows to customize the font and shell of the command line interface. diff --git a/patch.sh b/patch.sh deleted file mode 100755 index f92531b4..00000000 --- a/patch.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh -patch -p1 < ../weston/0001-xwayland-Fix-fullscreen-mode.patch -patch -p1 < ../weston/0002-wcap-Check-for-mmap-and-malloc-return-value-in-wcap-.patch -patch -p1 < ../weston/0003-compositor-drm-Don-t-use-vaapi-recorder-with-unsuppo.patch -patch -p1 < ../weston/0004-Apply-the-zoom-transformation-before-the-output-tran.patch -patch -p1 < ../weston/0005-compositor-wayland-free-output-before-returning.patch -patch -p1 < ../weston/0006-compositor-wayland-assign-the-correct-mode.patch -patch -p1 < ../weston/0007-compositor-wayland-avoid-possible-NULL-deref-in-hand.patch -patch -p1 < ../weston/0008-clients-Initialize-label-in-keyboard-handling-code.patch -patch -p1 < ../weston/0009-shell-Fix-artifacts-caused-by-workspace-change-anima.patch -patch -p1 < ../weston/0010-simple-touch-Handle-multiple-seats-properly.patch -patch -p1 < ../weston/0011-shell-Fix-crash-when-restoring-focus-state-during-wo.patch -patch -p1 < ../weston/0012-shell-Don-t-allow-maximized-surfaces-to-be-moved-wit.patch -patch -p1 < ../weston/0013-desktop-shell-Fix-black-edges-on-scaled-desktop-patt.patch -patch -p1 < ../weston/0014-rpi-build-fix-for-compute_rects-debug.patch -patch -p1 < ../weston/0015-vaapi-recorder-Don-t-loop-trying-to-write-on-out-of-.patch -patch -p1 < ../weston/0016-libinput-seat-literal-values-for-WESTON_LIBINPUT_LOG.patch -patch -p1 < ../weston/0017-compositor-add-no-config-command-line-option.patch -patch -p1 < ../weston/0018-tests-use-no-config.patch -patch -p1 < ../weston/0019-tests-load-the-right-xwayland-plugin.patch -patch -p1 < ../weston/0020-tests-load-the-right-shell-plugin.patch -patch -p1 < ../weston/0021-tests-rename-xwayland-test.patch -patch -p1 < ../weston/0022-editor-Fix-cursor-positioning-with-pointer-and-touch.patch -patch -p1 < ../weston/0023-configure.ac-Fix-indent-for-screen-share-option.patch -patch -p1 < ../weston/0024-desktop-shell-Damage-the-black-view-when-we-remove-i.patch -patch -p1 < ../weston/0025-desktop-shell-Fix-order-of-desktop_shell-messages.patch -patch -p1 < ../weston/0026-gitignore-log-files-now-in-root-directory.patch -patch -p1 < ../weston/0027-build-let-make-clean-remove-logs-again.patch -patch -p1 < ../weston/0028-window-Ignore-input-events-from-subsurfaces.patch -patch -p1 < ../weston/0029-configure.ac-Bump-version-1.4.93.patch diff --git a/protocol/xdg-shell.xml b/protocol/xdg-shell.xml index 79a28317..bd36231a 100644 --- a/protocol/xdg-shell.xml +++ b/protocol/xdg-shell.xml @@ -137,11 +137,8 @@ - + - Setting a surface as transient of another means that it is child - of another surface. - Child surfaces are stacked above their parents, and will be unmapped if the parent is unmapped too. They should not appear on task bars and alt+tab. @@ -149,32 +146,6 @@ - - - This tells the compositor what the visible size of the window - should be, so it can use it to determine what borders to use for - constrainment and alignment. - - CSD often has invisible areas for decoration purposes, like drop - shadows. These "shadow" drawings need to be subtracted out of the - normal boundaries of the window when computing where to place - windows (e.g. to set this window so it's centered on top of another, - or to put it to the left or right of the screen.) - - This value should change as little as possible at runtime, to - prevent flicker. - - This value is also ignored when the window is maximized or - fullscreen, and assumed to be 0. - - If never called, this value is assumed to be 0. - - - - - - - Set a short title for the surface. @@ -201,6 +172,26 @@ + + + Clients implementing client-side decorations might want to show + a context menu when right-clicking on the decorations, giving the + user a menu that they can use to maximize or minimize the window. + + This request asks the compositor to pop up such a window menu at + the given position, relative to the parent surface. There are + no guarantees as to what the window menu contains. + + Your surface must have focus on the seat passed in to pop up the + window menu. + + + + + + + + Start a pointer-driven move of the surface. @@ -244,46 +235,12 @@ - - - The configure event asks the client to resize its surface. - - The size is a hint, in the sense that the client is free to - ignore it if it doesn't resize, pick a smaller size (to - satisfy aspect ratio or resize in steps of NxM pixels). - - The client is free to dismiss all but the last configure - event it received. - - The width and height arguments specify the size of the window - in surface local coordinates. - - - - - - - - - Set the default output used by this surface when it is first mapped. - - If this value is NULL (default), it's up to the compositor to choose - which display will be used to map this surface. - - When fullscreen or maximized state are set on this surface, and it - wasn't mapped yet, the output set with this method will be used. - Otherwise, the output where the surface is currently mapped will be - used. - - - - The different state values used on the surface. This is designed for state values like maximized, fullscreen. It is paired with the - request_change_state event to ensure that both the client and the - compositor setting the state can be synchronized. + configure event to ensure that both the client and the compositor + setting the state can be synchronized. States set in this way are double-buffered. They will get applied on the next commit. @@ -300,89 +257,101 @@ 0x1000 - 0x1FFF: GNOME - A non-zero value indicates the surface is maximized. Otherwise, - the surface is unmaximized. + The surface is maximized. The window geometry specified in the configure + event must be obeyed by the client. - A non-zero value indicates the surface is fullscreen. Otherwise, - the surface is not fullscreen. + The surface is fullscreen. The window geometry specified in the configure + event must be obeyed by the client. + + + The surface is being resized. The window geometry specified in the + configure event is a maximum; the client cannot resize beyond it. + Clients that have aspect ratio or cell sizing configuration can use + a smaller size, however. + + + Client window decorations should be painted as if the window is + active. Do not assume this means that the window actually has + keyboard or pointer focus. - - - This asks the compositor to change the state. If the compositor wants - to change the state, it will send a change_state event with the same - state_type, value, and serial, and the event flow continues as if it - it was initiated by the compositor. + + + The configure event asks the client to resize its surface. - If the compositor does not want to change the state, it will send a - change_state to the client with the old value of the state. - - - - - This serial is so the client can know which change_state event corresponds - to which request_change_state request it sent out. - - + The width and height arguments specify a hint to the window + about how its surface should be resized in window geometry + coordinates. The states listed in the event specify how the + width/height arguments should be interpreted. + + A client should arrange a new surface, and then send a + ack_configure request with the serial sent in this configure + event before attaching a new surface. - - - This event tells the client to change a surface's state. The client - should respond with an ack_change_state request to the compositor to - guarantee that the compositor knows that the client has seen it. + If the client receives multiple configure events before it + can respond to one, it is free to discard all but the last + event it received. - - - + + + + - - - When a change_state event is received, a client should then ack it - using the ack_change_state request to ensure that the compositor + + + When a configure event is received, a client should then ack it + using the ack_configure request to ensure that the compositor knows the client has seen the event. By this point, the state is confirmed, and the next attach should - contain the buffer drawn for the new state value. - - The values here need to be the same as the values in the cooresponding - change_state event. + contain the buffer drawn for the configure event you are acking. - - - + - - - Minimize the surface. + + + The window geometry of a window is its "visible bounds" from the + user's perspective. Client-side decorations often have invisible + portions like drop-shadows which should be ignored for the + purposes of aligning, placing and constraining windows. + + The default value is the full bounds of the surface, including any + subsurfaces. Once the window geometry of the surface is set once, + it is not possible to unset it, and it will remain the same until + set_window_geometry is called again, even if a new subsurface or + buffer is attached. + + If responding to a configure event, the window geometry in here + must respect the sizing negotiations specified by the states in + the configure event. + + + + - - - The activated_set event is sent when this surface has been - activated, which means that the surface has user attention. - Window decorations should be updated accordingly. You should - not use this event for anything but the style of decorations - you display, use wl_keyboard.enter and wl_keyboard.leave for - determining keyboard focus. - - + + + + + + Make the surface fullscreen. - - - The deactivate event is sent when this surface has been - deactivated, which means that the surface lost user attention. - Window decorations should be updated accordingly. You should - not use this event for anything but the style of decorations - you display, use wl_keyboard.enter and wl_keyboard.leave for - determining keyboard focus. + You can specify an output that you would prefer to be fullscreen. + If this value is NULL, it's up to the compositor to choose which + display will be used to map this surface. - + + + + + diff --git a/releasing.txt b/releasing.txt new file mode 100644 index 00000000..1432d18e --- /dev/null +++ b/releasing.txt @@ -0,0 +1,43 @@ +To make a release follow these steps. + + 1. Update configure.ac to intended version, commit. + + 2. make distcheck (for weston I do make distcheck TESTS= to avoid + running the tests... most of the tests pass, but the xwayland one + is flaky) + + 3. git tag -am 1.5.0 1.5.0 + + 4. scp tarballs to /srv/wayland.freedesktop.org/www/releases on + people.freedesktop.org + + 5. Put SHA1 for tarballs and tagged commits in release announcement + + 6. Push configure.ac commits and tags. + + 7. Send out release announcement. + + 8. Get the release email URL from + http://lists.freedesktop.org/archives/wayland-devel/ + + 9. Update releases.html in wayland-web with links to tarballs and + release email. + + 10. Update topic in #wayland to point to release announcement + +For x.y.0 releases, also create the x.y branch. The x.y branch is for +bug fixes and conservetive changes to the x.y.0 release, and is where +we release x.y.z releases from. Creating the x.y branch opens up +master for new development and lets new development move on. We've +done this both after the x.y.0 release (to focus development on bug +fixing for the x.y.1 release for a little longer) or before the x.y.0 +release (like we did with the 1.5.0 release, to unblock master +development early). + +The master branch configure.ac version should always be (at least) +x.y.90, with x.y being the most recent stable branch. Stable branch +configure version is just whatever was most recently released from +that branch. + +For stable branches, we commit fixes to master first, then cherry-pick +them back to the stable branch. diff --git a/shared/frame.c b/shared/frame.c index 35e6b65e..53f3f5f7 100644 --- a/shared/frame.c +++ b/shared/frame.c @@ -385,6 +385,7 @@ frame_set_title(struct frame *frame, const char *title) free(frame->title); frame->title = dup; + frame->geometry_dirty = 1; frame->status |= FRAME_STATUS_REPAINT; return 0; @@ -426,7 +427,7 @@ frame_resize_inside(struct frame *frame, int32_t width, int32_t height) struct theme *t = frame->theme; int decoration_width, decoration_height, titlebar_height; - if (frame->title) + if (frame->title || !wl_list_empty(&frame->buttons)) titlebar_height = t->titlebar_height; else titlebar_height = t->width; @@ -467,7 +468,7 @@ frame_refresh_geometry(struct frame *frame) if (!frame->geometry_dirty) return; - if (frame->title) + if (frame->title || !wl_list_empty(&frame->buttons)) titlebar_height = t->titlebar_height; else titlebar_height = t->width; diff --git a/src/animation.c b/src/animation.c index a29b34ad..0febe413 100644 --- a/src/animation.c +++ b/src/animation.c @@ -161,6 +161,8 @@ weston_view_animation_frame(struct weston_animation *base, struct weston_view_animation *animation = container_of(base, struct weston_view_animation, animation); + struct weston_compositor *compositor = + animation->view->surface->compositor; if (base->frame_counter <= 1) animation->spring.timestamp = msecs; @@ -178,6 +180,15 @@ weston_view_animation_frame(struct weston_animation *base, weston_view_geometry_dirty(animation->view); weston_view_schedule_repaint(animation->view); + + /* The view's output_mask will be zero if its position is + * offscreen. Animations should always run but as they are also + * run off the repaint cycle, if there's nothing to repaint + * the animation stops running. Therefore if we catch this situation + * and schedule a repaint on all outputs it will be avoided. + */ + if (animation->view->output_mask == 0) + weston_compositor_schedule_repaint(compositor); } static struct weston_view_animation * @@ -319,6 +330,7 @@ WL_EXPORT void weston_fade_update(struct weston_view_animation *fade, float target) { fade->spring.target = target; + fade->stop = target; } static void @@ -458,8 +470,10 @@ weston_move_scale_run(struct weston_view *view, int dx, int dy, if (animation == NULL) return NULL; - weston_spring_init(&animation->spring, 400.0, start, end); + weston_spring_init(&animation->spring, 400.0, 0.0, 1.0); animation->spring.friction = 1150; + weston_view_animation_run(animation); + return animation; } diff --git a/src/compositor-drm.c b/src/compositor-drm.c index 7d514e40..9c83b1a7 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -55,6 +55,18 @@ #define DRM_CAP_TIMESTAMP_MONOTONIC 0x6 #endif +#ifndef DRM_CAP_CURSOR_WIDTH +#define DRM_CAP_CURSOR_WIDTH 0x8 +#endif + +#ifndef DRM_CAP_CURSOR_HEIGHT +#define DRM_CAP_CURSOR_HEIGHT 0x9 +#endif + +#ifndef GBM_BO_USE_CURSOR +#define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64 +#endif + static int option_current_mode = 0; enum output_config { @@ -108,6 +120,9 @@ struct drm_compositor { clockid_t clock; struct udev_input input; + + uint32_t cursor_width; + uint32_t cursor_height; }; struct drm_mode { @@ -987,7 +1002,7 @@ drm_output_set_cursor(struct drm_output *output) (struct drm_compositor *) output->base.compositor; EGLint handle, stride; struct gbm_bo *bo; - uint32_t buf[64 * 64]; + uint32_t buf[c->cursor_width * c->cursor_height]; unsigned char *s; int i, x, y; @@ -1010,7 +1025,7 @@ drm_output_set_cursor(struct drm_output *output) s = wl_shm_buffer_get_data(buffer->shm_buffer); wl_shm_buffer_begin_access(buffer->shm_buffer); for (i = 0; i < ev->surface->height; i++) - memcpy(buf + i * 64, s + i * stride, + memcpy(buf + i * c->cursor_width, s + i * stride, ev->surface->width * 4); wl_shm_buffer_end_access(buffer->shm_buffer); @@ -1018,8 +1033,8 @@ drm_output_set_cursor(struct drm_output *output) weston_log("failed update cursor: %m\n"); handle = gbm_bo_get_handle(bo).s32; - if (drmModeSetCursor(c->drm.fd, - output->crtc_id, handle, 64, 64)) { + if (drmModeSetCursor(c->drm.fd, output->crtc_id, handle, + c->cursor_width, c->cursor_height)) { weston_log("failed to set cursor: %m\n"); c->cursors_are_broken = 1; } @@ -1296,6 +1311,18 @@ init_drm(struct drm_compositor *ec, struct udev_device *device) else ec->clock = CLOCK_REALTIME; + ret = drmGetCap(fd, DRM_CAP_CURSOR_WIDTH, &cap); + if (ret == 0) + ec->cursor_width = cap; + else + ec->cursor_width = 64; + + ret = drmGetCap(fd, DRM_CAP_CURSOR_HEIGHT, &cap); + if (ret == 0) + ec->cursor_height = cap; + else + ec->cursor_height = 64; + return 0; } @@ -1554,15 +1581,15 @@ drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec) return -1; } - flags = GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE; + flags = GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE; for (i = 0; i < 2; i++) { if (output->cursor_bo[i]) continue; output->cursor_bo[i] = - gbm_bo_create(ec->gbm, 64, 64, GBM_FORMAT_ARGB8888, - flags); + gbm_bo_create(ec->gbm, ec->cursor_width, ec->cursor_height, + GBM_FORMAT_ARGB8888, flags); } if (output->cursor_bo[0] == NULL || output->cursor_bo[1] == NULL) { diff --git a/src/compositor-rdp.c b/src/compositor-rdp.c index aecc0a81..b7491297 100644 --- a/src/compositor-rdp.c +++ b/src/compositor-rdp.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include "compositor.h" @@ -618,21 +619,127 @@ xf_peer_capabilities(freerdp_peer* client) return TRUE; } - struct rdp_to_xkb_keyboard_layout { UINT32 rdpLayoutCode; - char *xkbLayout; + const char *xkbLayout; + const char *xkbVariant; }; -/* picked from http://technet.microsoft.com/en-us/library/cc766503(WS.10).aspx */ -static struct rdp_to_xkb_keyboard_layout rdp_keyboards[] = { - {0x00000406, "dk"}, - {0x00000407, "de"}, - {0x00000409, "us"}, - {0x0000040c, "fr"}, - {0x00000410, "it"}, - {0x00000813, "be"}, - {0x00000000, 0}, +/* table reversed from + https://github.com/awakecoding/FreeRDP/blob/master/libfreerdp/locale/xkb_layout_ids.c#L811 */ +static +struct rdp_to_xkb_keyboard_layout rdp_keyboards[] = { + {KBD_ARABIC_101, "ara", 0}, + {KBD_BULGARIAN, 0, 0}, + {KBD_CHINESE_TRADITIONAL_US, 0}, + {KBD_CZECH, "cz", 0}, + {KBD_CZECH_PROGRAMMERS, "cz", "bksl"}, + {KBD_CZECH_QWERTY, "cz", "qwerty"}, + {KBD_DANISH, "dk", 0}, + {KBD_GERMAN, "de", 0}, + {KBD_GERMAN_NEO, "de", "neo"}, + {KBD_GERMAN_IBM, "de", "qwerty"}, + {KBD_GREEK, "gr", 0}, + {KBD_GREEK_220, "gr", "simple"}, + {KBD_GREEK_319, "gr", "extended"}, + {KBD_GREEK_POLYTONIC, "gr", "polytonic"}, + {KBD_US, "us", 0}, + {KBD_US_ENGLISH_TABLE_FOR_IBM_ARABIC_238_L, "ara", "buckwalter"}, + {KBD_SPANISH, "es", 0}, + {KBD_SPANISH_VARIATION, "es", "nodeadkeys"}, + {KBD_FINNISH, "fi", 0}, + {KBD_FRENCH, "fr", 0}, + {KBD_HEBREW, "il", 0}, + {KBD_HUNGARIAN, "hu", 0}, + {KBD_HUNGARIAN_101_KEY, "hu", "standard"}, + {KBD_ICELANDIC, "is", 0}, + {KBD_ITALIAN, "it", 0}, + {KBD_ITALIAN_142, "it", "nodeadkeys"}, + {KBD_JAPANESE, "jp", 0}, + {KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002, "jp", "kana"}, + {KBD_KOREAN, "kr", 0}, + {KBD_KOREAN_INPUT_SYSTEM_IME_2000, "kr", "kr104"}, + {KBD_DUTCH, "nl", 0}, + {KBD_NORWEGIAN, "no", 0}, + {KBD_POLISH_PROGRAMMERS, "pl", 0}, + {KBD_POLISH_214, "pl", "qwertz"}, + // {KBD_PORTUGUESE_BRAZILIAN_ABN0416, 0}, + {KBD_ROMANIAN, "ro", 0}, + {KBD_RUSSIAN, "ru", 0}, + {KBD_RUSSIAN_TYPEWRITER, "ru", "typewriter"}, + {KBD_CROATIAN, "hr", 0}, + {KBD_SLOVAK, "sk", 0}, + {KBD_SLOVAK_QWERTY, "sk", "qwerty"}, + {KBD_ALBANIAN, 0, 0}, + {KBD_SWEDISH, "se", 0}, + {KBD_THAI_KEDMANEE, "th", 0}, + {KBD_THAI_KEDMANEE_NON_SHIFTLOCK, "th", "tis"}, + {KBD_TURKISH_Q, "tr", 0}, + {KBD_TURKISH_F, "tr", "f"}, + {KBD_URDU, "in", "urd-phonetic3"}, + {KBD_UKRAINIAN, "ua", 0}, + {KBD_BELARUSIAN, "by", 0}, + {KBD_SLOVENIAN, "si", 0}, + {KBD_ESTONIAN, "ee", 0}, + {KBD_LATVIAN, "lv", 0}, + {KBD_LITHUANIAN_IBM, "lt", "ibm"}, + {KBD_FARSI, "af", 0}, + {KBD_VIETNAMESE, "vn", 0}, + {KBD_ARMENIAN_EASTERN, "am", 0}, + {KBD_AZERI_LATIN, 0, 0}, + {KBD_FYRO_MACEDONIAN, "mk", 0}, + {KBD_GEORGIAN, "ge", 0}, + {KBD_FAEROESE, 0, 0}, + {KBD_DEVANAGARI_INSCRIPT, 0, 0}, + {KBD_MALTESE_47_KEY, 0, 0}, + {KBD_NORWEGIAN_WITH_SAMI, "no", "smi"}, + {KBD_KAZAKH, "kz", 0}, + {KBD_KYRGYZ_CYRILLIC, "kg", "phonetic"}, + {KBD_TATAR, "ru", "tt"}, + {KBD_BENGALI, "bd", 0}, + {KBD_BENGALI_INSCRIPT, "bd", "probhat"}, + {KBD_PUNJABI, 0, 0}, + {KBD_GUJARATI, "in", "guj"}, + {KBD_TAMIL, "in", "tam"}, + {KBD_TELUGU, "in", "tel"}, + {KBD_KANNADA, "in", "kan"}, + {KBD_MALAYALAM, "in", "mal"}, + {KBD_HINDI_TRADITIONAL, "in", 0}, + {KBD_MARATHI, 0, 0}, + {KBD_MONGOLIAN_CYRILLIC, "mn", 0}, + {KBD_UNITED_KINGDOM_EXTENDED, "gb", "intl"}, + {KBD_SYRIAC, "syc", 0}, + {KBD_SYRIAC_PHONETIC, "syc", "syc_phonetic"}, + {KBD_NEPALI, "np", 0}, + {KBD_PASHTO, "af", "ps"}, + {KBD_DIVEHI_PHONETIC, 0, 0}, + {KBD_LUXEMBOURGISH, 0, 0}, + {KBD_MAORI, "mao", 0}, + {KBD_CHINESE_SIMPLIFIED_US, 0, 0}, + {KBD_SWISS_GERMAN, "ch", "de_nodeadkeys"}, + {KBD_UNITED_KINGDOM, "gb", 0}, + {KBD_LATIN_AMERICAN, "latam", 0}, + {KBD_BELGIAN_FRENCH, "be", 0}, + {KBD_BELGIAN_PERIOD, "be", "oss_sundeadkeys"}, + {KBD_PORTUGUESE, "pt", 0}, + {KBD_SERBIAN_LATIN, "rs", 0}, + {KBD_AZERI_CYRILLIC, "az", "cyrillic"}, + {KBD_SWEDISH_WITH_SAMI, "se", "smi"}, + {KBD_UZBEK_CYRILLIC, "af", "uz"}, + {KBD_INUKTITUT_LATIN, "ca", "ike"}, + {KBD_CANADIAN_FRENCH_LEGACY, "ca", "fr-legacy"}, + {KBD_SERBIAN_CYRILLIC, "rs", 0}, + {KBD_CANADIAN_FRENCH, "ca", "fr-legacy"}, + {KBD_SWISS_FRENCH, "ch", "fr"}, + {KBD_BOSNIAN, "ba", 0}, + {KBD_IRISH, 0, 0}, + {KBD_BOSNIAN_CYRILLIC, "ba", "us"}, + {KBD_UNITED_STATES_DVORAK, "us", "dvorak"}, + {KBD_PORTUGUESE_BRAZILIAN_ABNT2, "br", "nativo"}, + {KBD_CANADIAN_MULTILINGUAL_STANDARD, "ca", "multix"}, + {KBD_GAELIC, "ie", "CloGaelach"}, + + {0x00000000, 0, 0}, }; /* taken from 2.2.7.1.6 Input Capability Set (TS_INPUT_CAPABILITYSET) */ @@ -711,9 +818,12 @@ xf_peer_post_connect(freerdp_peer* client) memset(&xkbRuleNames, 0, sizeof(xkbRuleNames)); if (settings->KeyboardType <= 7) xkbRuleNames.model = rdp_keyboard_types[settings->KeyboardType]; - for(i = 0; rdp_keyboards[i].xkbLayout; i++) { + for(i = 0; rdp_keyboards[i].rdpLayoutCode; i++) { if (rdp_keyboards[i].rdpLayoutCode == settings->KeyboardLayout) { xkbRuleNames.layout = rdp_keyboards[i].xkbLayout; + xkbRuleNames.variant = rdp_keyboards[i].xkbVariant; + weston_log("%s: matching layout=%s variant=%s\n", __FUNCTION__, + xkbRuleNames.layout, xkbRuleNames.variant); break; } } @@ -844,17 +954,6 @@ xf_input_synchronize_event(rdpInput *input, UINT32 flags) pixman_region32_fini(&damage); } -extern DWORD KEYCODE_TO_VKCODE_EVDEV[]; -static uint32_t vk_to_keycode[256]; -static void -init_vk_translator(void) -{ - int i; - - memset(vk_to_keycode, 0, sizeof(vk_to_keycode)); - for(i = 0; i < 256; i++) - vk_to_keycode[KEYCODE_TO_VKCODE_EVDEV[i] & 0xff] = i-8; -} static void xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code) @@ -878,17 +977,15 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code) full_code |= KBD_FLAGS_EXTENDED; vk_code = GetVirtualKeyCodeFromVirtualScanCode(full_code, 4); - if (vk_code > 0xff) { - weston_log("invalid vk_code %x", vk_code); - return; - } - scan_code = vk_to_keycode[vk_code]; + if(flags & KBD_FLAGS_EXTENDED) + vk_code |= KBDEXT; + scan_code = GetKeycodeFromVirtualKeyCode(vk_code, KEYCODE_TYPE_EVDEV); /*weston_log("code=%x ext=%d vk_code=%x scan_code=%x\n", code, (flags & KBD_FLAGS_EXTENDED) ? 1 : 0, vk_code, scan_code);*/ notify_key(&peerContext->item.seat, weston_compositor_get_time(), - scan_code, keyState, STATE_UPDATE_AUTOMATIC); + scan_code - 8, keyState, STATE_UPDATE_AUTOMATIC); } } @@ -1080,7 +1177,6 @@ backend_init(struct wl_display *display, int *argc, char *argv[], freerdp_get_version(&major, &minor, &revision); weston_log("using FreeRDP version %d.%d.%d\n", major, minor, revision); - init_vk_translator(); const struct weston_option rdp_options[] = { { WESTON_OPTION_BOOLEAN, "env-socket", 0, &config.env_socket }, diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c index a08b71ab..d5ea9251 100644 --- a/src/compositor-wayland.c +++ b/src/compositor-wayland.c @@ -257,7 +257,7 @@ wayland_output_get_shm_buffer(struct wayland_output *output) sb = zalloc(sizeof *sb); if (sb == NULL) { - weston_log("could not zalloc %ld memory for sb: %m\n", sizeof *sb); + weston_log("could not zalloc %zu memory for sb: %m\n", sizeof *sb); close(fd); free(data); return NULL; @@ -1573,12 +1573,24 @@ input_handle_modifiers(void *data, struct wl_keyboard *keyboard, notify_modifiers(&input->base, serial_out); } +static void +input_handle_repeat_info(void *data, struct wl_keyboard *keyboard, + int32_t rate, int32_t delay) +{ + struct wayland_input *input = data; + struct wayland_compositor *c = input->compositor; + + c->base.kb_repeat_rate = rate; + c->base.kb_repeat_delay = delay; +} + static const struct wl_keyboard_listener keyboard_listener = { input_handle_keymap, input_handle_keyboard_enter, input_handle_keyboard_leave, input_handle_key, input_handle_modifiers, + input_handle_repeat_info, }; static void @@ -1609,12 +1621,19 @@ input_handle_capabilities(void *data, struct wl_seat *seat, } } +static void +input_handle_name(void *data, struct wl_seat *seat, + const char *name) +{ +} + static const struct wl_seat_listener seat_listener = { input_handle_capabilities, + input_handle_name, }; static void -display_add_seat(struct wayland_compositor *c, uint32_t id) +display_add_seat(struct wayland_compositor *c, uint32_t id, uint32_t version) { struct wayland_input *input; @@ -1625,7 +1644,7 @@ display_add_seat(struct wayland_compositor *c, uint32_t id) weston_seat_init(&input->base, &c->base, "default"); input->compositor = c; input->parent.seat = wl_registry_bind(c->parent.registry, id, - &wl_seat_interface, 1); + &wl_seat_interface, MIN(version, 4)); wl_list_insert(c->input_list.prev, &input->link); wl_seat_add_listener(input->parent.seat, &seat_listener, input); @@ -1781,7 +1800,7 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, wl_registry_bind(registry, name, &_wl_fullscreen_shell_interface, 1); } else if (strcmp(interface, "wl_seat") == 0) { - display_add_seat(c, name); + display_add_seat(c, name, version); } else if (strcmp(interface, "wl_output") == 0) { wayland_compositor_register_output(c, name); } else if (strcmp(interface, "wl_shm") == 0) { @@ -1997,9 +2016,9 @@ err_free: static void wayland_compositor_destroy(struct wayland_compositor *c) { - struct weston_output *output; + struct weston_output *output, *next; - wl_list_for_each(output, &c->base.output_list, link) + wl_list_for_each_safe(output, next, &c->base.output_list, link) wayland_output_destroy(output); c->base.renderer->destroy(&c->base); diff --git a/src/compositor.c b/src/compositor.c index 574db2de..96e3435f 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -319,23 +319,6 @@ weston_client_launch(struct weston_compositor *compositor, return client; } -static void -surface_handle_pending_buffer_destroy(struct wl_listener *listener, void *data) -{ - struct weston_surface *surface = - container_of(listener, struct weston_surface, - pending.buffer_destroy_listener); - - surface->pending.buffer = NULL; -} - -static void -empty_region(pixman_region32_t *region) -{ - pixman_region32_fini(region); - pixman_region32_init(region); -} - static void region_init_infinite(pixman_region32_t *region) { @@ -362,11 +345,15 @@ weston_view_create(struct weston_surface *surface) wl_signal_init(&view->destroy_signal); wl_list_init(&view->link); - wl_list_init(&view->layer_link); + wl_list_init(&view->layer_link.link); view->plane = NULL; + view->layer_link.layer = NULL; + view->parent_view = NULL; pixman_region32_init(&view->clip); + pixman_region32_init(&view->transform.masked_boundingbox); + pixman_region32_init(&view->transform.masked_opaque); view->alpha = 1.0; pixman_region32_init(&view->transform.opaque); @@ -384,6 +371,77 @@ weston_view_create(struct weston_surface *surface) return view; } +struct weston_frame_callback { + struct wl_resource *resource; + struct wl_list link; +}; + +static void +surface_state_handle_buffer_destroy(struct wl_listener *listener, void *data) +{ + struct weston_surface_state *state = + container_of(listener, struct weston_surface_state, + buffer_destroy_listener); + + state->buffer = NULL; +} + +static void +weston_surface_state_init(struct weston_surface_state *state) +{ + state->newly_attached = 0; + state->buffer = NULL; + state->buffer_destroy_listener.notify = + surface_state_handle_buffer_destroy; + state->sx = 0; + state->sy = 0; + + pixman_region32_init(&state->damage); + pixman_region32_init(&state->opaque); + region_init_infinite(&state->input); + + wl_list_init(&state->frame_callback_list); + + state->buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL; + state->buffer_viewport.buffer.scale = 1; + state->buffer_viewport.buffer.src_width = wl_fixed_from_int(-1); + state->buffer_viewport.surface.width = -1; + state->buffer_viewport.changed = 0; +} + +static void +weston_surface_state_fini(struct weston_surface_state *state) +{ + struct weston_frame_callback *cb, *next; + + wl_list_for_each_safe(cb, next, + &state->frame_callback_list, link) + wl_resource_destroy(cb->resource); + + pixman_region32_fini(&state->input); + pixman_region32_fini(&state->opaque); + pixman_region32_fini(&state->damage); + + if (state->buffer) + wl_list_remove(&state->buffer_destroy_listener.link); + state->buffer = NULL; +} + +static void +weston_surface_state_set_buffer(struct weston_surface_state *state, + struct weston_buffer *buffer) +{ + if (state->buffer == buffer) + return; + + if (state->buffer) + wl_list_remove(&state->buffer_destroy_listener.link); + state->buffer = buffer; + if (state->buffer) + wl_signal_add(&state->buffer->destroy_signal, + &state->buffer_destroy_listener); +} + WL_EXPORT struct weston_surface * weston_surface_create(struct weston_compositor *compositor) { @@ -404,9 +462,10 @@ weston_surface_create(struct weston_compositor *compositor) surface->buffer_viewport.buffer.scale = 1; surface->buffer_viewport.buffer.src_width = wl_fixed_from_int(-1); surface->buffer_viewport.surface.width = -1; - surface->pending.buffer_viewport = surface->buffer_viewport; + + weston_surface_state_init(&surface->pending); + surface->output = NULL; - surface->pending.newly_attached = 0; surface->viewport_resource = NULL; @@ -418,13 +477,6 @@ weston_surface_create(struct weston_compositor *compositor) wl_list_init(&surface->frame_callback_list); - surface->pending.buffer_destroy_listener.notify = - surface_handle_pending_buffer_destroy; - pixman_region32_init(&surface->pending.damage); - pixman_region32_init(&surface->pending.opaque); - region_init_infinite(&surface->pending.input); - wl_list_init(&surface->pending.frame_callback_list); - wl_list_init(&surface->subsurface_list); wl_list_init(&surface->subsurface_list_pending); @@ -734,7 +786,7 @@ weston_view_damage_below(struct weston_view *view) pixman_region32_t damage; pixman_region32_init(&damage); - pixman_region32_subtract(&damage, &view->transform.boundingbox, + pixman_region32_subtract(&damage, &view->transform.masked_boundingbox, &view->clip); if (view->plane) pixman_region32_union(&view->plane->damage, @@ -960,10 +1012,20 @@ weston_view_update_transform_enable(struct weston_view *view) return 0; } +static struct weston_layer * +get_view_layer(struct weston_view *view) +{ + if (view->parent_view) + return get_view_layer(view->parent_view); + return view->layer_link.layer; +} + WL_EXPORT void weston_view_update_transform(struct weston_view *view) { struct weston_view *parent = view->geometry.parent; + struct weston_layer *layer; + pixman_region32_t mask; if (!view->transform.dirty) return; @@ -991,6 +1053,16 @@ weston_view_update_transform(struct weston_view *view) weston_view_update_transform_disable(view); } + layer = get_view_layer(view); + if (layer) { + pixman_region32_init_with_extents(&mask, &layer->mask); + pixman_region32_intersect(&view->transform.masked_boundingbox, + &view->transform.boundingbox, &mask); + pixman_region32_intersect(&view->transform.masked_opaque, + &view->transform.opaque, &mask); + pixman_region32_fini(&mask); + } + weston_view_damage_below(view); weston_view_assign_output(view); @@ -1211,13 +1283,12 @@ fixed_round_up_to_int(wl_fixed_t f) } static void -weston_surface_set_size_from_buffer(struct weston_surface *surface) +weston_surface_calculate_size_from_buffer(struct weston_surface *surface) { struct weston_buffer_viewport *vp = &surface->buffer_viewport; int32_t width, height; if (!surface->buffer_ref.buffer) { - surface_set_size(surface, 0, 0); surface->width_from_buffer = 0; surface->height_from_buffer = 0; return; @@ -1239,14 +1310,24 @@ weston_surface_set_size_from_buffer(struct weston_surface *surface) surface->width_from_buffer = width; surface->height_from_buffer = height; +} + +static void +weston_surface_update_size(struct weston_surface *surface) +{ + struct weston_buffer_viewport *vp = &surface->buffer_viewport; + int32_t width, height; - if (vp->surface.width != -1) { + width = surface->width_from_buffer; + height = surface->height_from_buffer; + + if (width != 0 && vp->surface.width != -1) { surface_set_size(surface, vp->surface.width, vp->surface.height); return; } - if (vp->buffer.src_width != wl_fixed_from_int(-1)) { + if (width != 0 && vp->buffer.src_width != wl_fixed_from_int(-1)) { int32_t w = fixed_round_up_to_int(vp->buffer.src_width); int32_t h = fixed_round_up_to_int(vp->buffer.src_height); @@ -1273,10 +1354,15 @@ weston_compositor_pick_view(struct weston_compositor *compositor, wl_fixed_t *vx, wl_fixed_t *vy) { struct weston_view *view; + int ix = wl_fixed_to_int(x); + int iy = wl_fixed_to_int(y); wl_list_for_each(view, &compositor->view_list, link) { weston_view_from_global_fixed(view, x, y, vx, vy); - if (pixman_region32_contains_point(&view->surface->input, + if (pixman_region32_contains_point( + &view->transform.masked_boundingbox, + ix, iy, NULL) && + pixman_region32_contains_point(&view->surface->input, wl_fixed_to_int(*vx), wl_fixed_to_int(*vy), NULL)) @@ -1309,8 +1395,7 @@ weston_view_unmap(struct weston_view *view) weston_view_damage_below(view); view->output = NULL; view->plane = NULL; - wl_list_remove(&view->layer_link); - wl_list_init(&view->layer_link); + weston_layer_entry_remove(&view->layer_link); wl_list_remove(&view->link); wl_list_init(&view->link); view->output_mask = 0; @@ -1345,19 +1430,13 @@ weston_surface_unmap(struct weston_surface *surface) static void weston_surface_reset_pending_buffer(struct weston_surface *surface) { - if (surface->pending.buffer) - wl_list_remove(&surface->pending.buffer_destroy_listener.link); - surface->pending.buffer = NULL; + weston_surface_state_set_buffer(&surface->pending, NULL); surface->pending.sx = 0; surface->pending.sy = 0; surface->pending.newly_attached = 0; + surface->pending.buffer_viewport.changed = 0; } -struct weston_frame_callback { - struct wl_resource *resource; - struct wl_list link; -}; - WL_EXPORT void weston_view_destroy(struct weston_view *view) { @@ -1371,10 +1450,12 @@ weston_view_destroy(struct weston_view *view) } wl_list_remove(&view->link); - wl_list_remove(&view->layer_link); + weston_layer_entry_remove(&view->layer_link); pixman_region32_fini(&view->clip); pixman_region32_fini(&view->transform.boundingbox); + pixman_region32_fini(&view->transform.masked_boundingbox); + pixman_region32_fini(&view->transform.masked_opaque); weston_view_set_transform_parent(view, NULL); @@ -1400,16 +1481,7 @@ weston_surface_destroy(struct weston_surface *surface) wl_list_for_each_safe(ev, nv, &surface->views, surface_link) weston_view_destroy(ev); - wl_list_for_each_safe(cb, next, - &surface->pending.frame_callback_list, link) - wl_resource_destroy(cb->resource); - - pixman_region32_fini(&surface->pending.input); - pixman_region32_fini(&surface->pending.opaque); - pixman_region32_fini(&surface->pending.damage); - - if (surface->pending.buffer) - wl_list_remove(&surface->pending.buffer_destroy_listener.link); + weston_surface_state_fini(&surface->pending); weston_buffer_reference(&surface->buffer_ref, NULL); @@ -1520,7 +1592,7 @@ weston_surface_attach(struct weston_surface *surface, surface->compositor->renderer->attach(surface, buffer); - weston_surface_set_size_from_buffer(surface); + weston_surface_calculate_size_from_buffer(surface); } WL_EXPORT void @@ -1550,7 +1622,7 @@ surface_flush_damage(struct weston_surface *surface) wl_shm_buffer_get(surface->buffer_ref.buffer->resource)) surface->compositor->renderer->flush_damage(surface); - empty_region(&surface->damage); + pixman_region32_clear(&surface->damage); } static void @@ -1583,7 +1655,7 @@ view_accumulate_damage(struct weston_view *view, &view->plane->damage, &damage); pixman_region32_fini(&damage); pixman_region32_copy(&view->clip, opaque); - pixman_region32_union(opaque, opaque, &view->transform.opaque); + pixman_region32_union(opaque, opaque, &view->transform.masked_opaque); } static void @@ -1662,8 +1734,10 @@ surface_free_unused_subsurface_views(struct weston_surface *surface) if (sub->surface == surface) continue; - wl_list_for_each_safe(view, nv, &sub->unused_views, surface_link) + wl_list_for_each_safe(view, nv, &sub->unused_views, surface_link) { + weston_view_unmap (view); weston_view_destroy(view); + } surface_free_unused_subsurface_views(sub->surface); } @@ -1677,6 +1751,9 @@ view_list_add_subsurface_view(struct weston_compositor *compositor, struct weston_subsurface *child; struct weston_view *view = NULL, *iv; + if (!weston_surface_is_mapped(sub->surface)) + return; + wl_list_for_each(iv, &sub->unused_views, surface_link) { if (iv->geometry.parent == parent) { view = iv; @@ -1696,6 +1773,7 @@ view_list_add_subsurface_view(struct weston_compositor *compositor, weston_view_set_transform_parent(view, parent); } + view->parent_view = parent; weston_view_update_transform(view); if (wl_list_empty(&sub->surface->subsurface_list)) { @@ -1739,18 +1817,18 @@ weston_compositor_build_view_list(struct weston_compositor *compositor) struct weston_layer *layer; wl_list_for_each(layer, &compositor->layer_list, link) - wl_list_for_each(view, &layer->view_list, layer_link) + wl_list_for_each(view, &layer->view_list.link, layer_link.link) surface_stash_subsurface_views(view->surface); wl_list_init(&compositor->view_list); wl_list_for_each(layer, &compositor->layer_list, link) { - wl_list_for_each(view, &layer->view_list, layer_link) { + wl_list_for_each(view, &layer->view_list.link, layer_link.link) { view_list_add(compositor, view); } } wl_list_for_each(layer, &compositor->layer_list, link) - wl_list_for_each(view, &layer->view_list, layer_link) + wl_list_for_each(view, &layer->view_list.link, layer_link.link) surface_free_unused_subsurface_views(view->surface); } @@ -1868,14 +1946,55 @@ idle_repaint(void *data) output->start_repaint_loop(output); } +WL_EXPORT void +weston_layer_entry_insert(struct weston_layer_entry *list, + struct weston_layer_entry *entry) +{ + wl_list_insert(&list->link, &entry->link); + entry->layer = list->layer; +} + +WL_EXPORT void +weston_layer_entry_remove(struct weston_layer_entry *entry) +{ + wl_list_remove(&entry->link); + wl_list_init(&entry->link); + entry->layer = NULL; +} + WL_EXPORT void weston_layer_init(struct weston_layer *layer, struct wl_list *below) { - wl_list_init(&layer->view_list); + wl_list_init(&layer->view_list.link); + layer->view_list.layer = layer; + weston_layer_set_mask_infinite(layer); if (below != NULL) wl_list_insert(below, &layer->link); } +WL_EXPORT void +weston_layer_set_mask(struct weston_layer *layer, + int x, int y, int width, int height) +{ + struct weston_view *view; + + layer->mask.x1 = x; + layer->mask.x2 = x + width; + layer->mask.y1 = y; + layer->mask.y2 = y + height; + + wl_list_for_each(view, &layer->view_list.link, layer_link.link) { + weston_view_geometry_dirty(view); + } +} + +WL_EXPORT void +weston_layer_set_mask_infinite(struct weston_layer *layer) +{ + weston_layer_set_mask(layer, INT32_MIN, INT32_MIN, + UINT32_MAX, UINT32_MAX); +} + WL_EXPORT void weston_output_schedule_repaint(struct weston_output *output) { @@ -1933,17 +2052,11 @@ surface_attach(struct wl_client *client, /* Attach, attach, without commit in between does not send * wl_buffer.release. */ - if (surface->pending.buffer) - wl_list_remove(&surface->pending.buffer_destroy_listener.link); + weston_surface_state_set_buffer(&surface->pending, buffer); surface->pending.sx = sx; surface->pending.sy = sy; - surface->pending.buffer = buffer; surface->pending.newly_attached = 1; - if (buffer) { - wl_signal_add(&buffer->destroy_signal, - &surface->pending.buffer_destroy_listener); - } } static void @@ -2007,7 +2120,7 @@ surface_set_opaque_region(struct wl_client *client, pixman_region32_copy(&surface->pending.opaque, ®ion->region); } else { - empty_region(&surface->pending.opaque); + pixman_region32_clear(&surface->pending.opaque); } } @@ -2042,43 +2155,44 @@ weston_surface_commit_subsurface_order(struct weston_surface *surface) } static void -weston_surface_commit(struct weston_surface *surface) +weston_surface_commit_state(struct weston_surface *surface, + struct weston_surface_state *state) { struct weston_view *view; pixman_region32_t opaque; - /* XXX: wl_viewport.set without an attach should call configure */ - /* wl_surface.set_buffer_transform */ /* wl_surface.set_buffer_scale */ /* wl_viewport.set */ - surface->buffer_viewport = surface->pending.buffer_viewport; + surface->buffer_viewport = state->buffer_viewport; /* wl_surface.attach */ - if (surface->pending.newly_attached) - weston_surface_attach(surface, surface->pending.buffer); + if (state->newly_attached) + weston_surface_attach(surface, state->buffer); + weston_surface_state_set_buffer(state, NULL); - if (surface->configure && surface->pending.newly_attached) - surface->configure(surface, - surface->pending.sx, surface->pending.sy); + if (state->newly_attached || state->buffer_viewport.changed) { + weston_surface_update_size(surface); + if (surface->configure) + surface->configure(surface, state->sx, state->sy); + } - weston_surface_reset_pending_buffer(surface); + state->sx = 0; + state->sy = 0; + state->newly_attached = 0; + state->buffer_viewport.changed = 0; /* wl_surface.damage */ pixman_region32_union(&surface->damage, &surface->damage, - &surface->pending.damage); + &state->damage); pixman_region32_intersect_rect(&surface->damage, &surface->damage, - 0, 0, - surface->width, - surface->height); - empty_region(&surface->pending.damage); + 0, 0, surface->width, surface->height); + pixman_region32_clear(&surface->pending.damage); /* wl_surface.set_opaque_region */ - pixman_region32_init_rect(&opaque, 0, 0, - surface->width, - surface->height); - pixman_region32_intersect(&opaque, - &opaque, &surface->pending.opaque); + pixman_region32_init(&opaque); + pixman_region32_intersect_rect(&opaque, &state->opaque, + 0, 0, surface->width, surface->height); if (!pixman_region32_equal(&opaque, &surface->opaque)) { pixman_region32_copy(&surface->opaque, &opaque); @@ -2089,17 +2203,19 @@ weston_surface_commit(struct weston_surface *surface) pixman_region32_fini(&opaque); /* wl_surface.set_input_region */ - pixman_region32_fini(&surface->input); - pixman_region32_init_rect(&surface->input, 0, 0, - surface->width, - surface->height); - pixman_region32_intersect(&surface->input, - &surface->input, &surface->pending.input); + pixman_region32_intersect_rect(&surface->input, &state->input, + 0, 0, surface->width, surface->height); /* wl_surface.frame */ wl_list_insert_list(&surface->frame_callback_list, - &surface->pending.frame_callback_list); - wl_list_init(&surface->pending.frame_callback_list); + &state->frame_callback_list); + wl_list_init(&state->frame_callback_list); +} + +static void +weston_surface_commit(struct weston_surface *surface) +{ + weston_surface_commit_state(surface, &surface->pending); weston_surface_commit_subsurface_order(surface); @@ -2138,7 +2254,18 @@ surface_set_buffer_transform(struct wl_client *client, { struct weston_surface *surface = wl_resource_get_user_data(resource); + /* if wl_output.transform grows more members this will need to be updated. */ + if (transform < 0 || + transform > WL_OUTPUT_TRANSFORM_FLIPPED_270) { + wl_resource_post_error(resource, + WL_SURFACE_ERROR_INVALID_TRANSFORM, + "buffer transform must be a valid transform " + "('%d' specified)", transform); + return; + } + surface->pending.buffer_viewport.buffer.transform = transform; + surface->pending.buffer_viewport.changed = 1; } static void @@ -2148,7 +2275,16 @@ surface_set_buffer_scale(struct wl_client *client, { struct weston_surface *surface = wl_resource_get_user_data(resource); + if (scale < 1) { + wl_resource_post_error(resource, + WL_SURFACE_ERROR_INVALID_SCALE, + "buffer scale must be at least one " + "('%d' specified)", scale); + return; + } + surface->pending.buffer_viewport.buffer.scale = scale; + surface->pending.buffer_viewport.changed = 1; } static const struct wl_surface_interface surface_interface = { @@ -2267,67 +2403,15 @@ static void weston_subsurface_commit_from_cache(struct weston_subsurface *sub) { struct weston_surface *surface = sub->surface; - struct weston_view *view; - pixman_region32_t opaque; - - /* wl_surface.set_buffer_transform */ - /* wl_surface.set_buffer_scale */ - /* wl_viewport.set */ - surface->buffer_viewport = sub->cached.buffer_viewport; - - /* wl_surface.attach */ - if (sub->cached.newly_attached) - weston_surface_attach(surface, sub->cached.buffer_ref.buffer); - weston_buffer_reference(&sub->cached.buffer_ref, NULL); - - if (surface->configure && sub->cached.newly_attached) - surface->configure(surface, sub->cached.sx, sub->cached.sy); - sub->cached.sx = 0; - sub->cached.sy = 0; - sub->cached.newly_attached = 0; - - /* wl_surface.damage */ - pixman_region32_union(&surface->damage, &surface->damage, - &sub->cached.damage); - pixman_region32_intersect_rect(&surface->damage, &surface->damage, - 0, 0, - surface->width, - surface->height); - empty_region(&sub->cached.damage); - - /* wl_surface.set_opaque_region */ - pixman_region32_init_rect(&opaque, 0, 0, - surface->width, - surface->height); - pixman_region32_intersect(&opaque, - &opaque, &sub->cached.opaque); - - if (!pixman_region32_equal(&opaque, &surface->opaque)) { - pixman_region32_copy(&surface->opaque, &opaque); - wl_list_for_each(view, &surface->views, surface_link) - weston_view_geometry_dirty(view); - } - - pixman_region32_fini(&opaque); - /* wl_surface.set_input_region */ - pixman_region32_fini(&surface->input); - pixman_region32_init_rect(&surface->input, 0, 0, - surface->width, - surface->height); - pixman_region32_intersect(&surface->input, - &surface->input, &sub->cached.input); - - /* wl_surface.frame */ - wl_list_insert_list(&surface->frame_callback_list, - &sub->cached.frame_callback_list); - wl_list_init(&sub->cached.frame_callback_list); + weston_surface_commit_state(surface, &sub->cached); + weston_buffer_reference(&sub->cached_buffer_ref, NULL); weston_surface_commit_subsurface_order(surface); weston_surface_schedule_repaint(surface); - sub->cached.has_data = 0; + sub->has_cached_data = 0; } static void @@ -2345,19 +2429,26 @@ weston_subsurface_commit_to_cache(struct weston_subsurface *sub) -surface->pending.sx, -surface->pending.sy); pixman_region32_union(&sub->cached.damage, &sub->cached.damage, &surface->pending.damage); - empty_region(&surface->pending.damage); + pixman_region32_clear(&surface->pending.damage); if (surface->pending.newly_attached) { sub->cached.newly_attached = 1; - weston_buffer_reference(&sub->cached.buffer_ref, + weston_surface_state_set_buffer(&sub->cached, + surface->pending.buffer); + weston_buffer_reference(&sub->cached_buffer_ref, surface->pending.buffer); } sub->cached.sx += surface->pending.sx; sub->cached.sy += surface->pending.sy; - weston_surface_reset_pending_buffer(surface); + sub->cached.buffer_viewport.changed |= + surface->pending.buffer_viewport.changed; + sub->cached.buffer_viewport.buffer = + surface->pending.buffer_viewport.buffer; + sub->cached.buffer_viewport.surface = + surface->pending.buffer_viewport.surface; - sub->cached.buffer_viewport = surface->pending.buffer_viewport; + weston_surface_reset_pending_buffer(surface); pixman_region32_copy(&sub->cached.opaque, &surface->pending.opaque); @@ -2367,7 +2458,7 @@ weston_subsurface_commit_to_cache(struct weston_subsurface *sub) &surface->pending.frame_callback_list); wl_list_init(&surface->pending.frame_callback_list); - sub->cached.has_data = 1; + sub->has_cached_data = 1; } static int @@ -2396,7 +2487,7 @@ weston_subsurface_commit(struct weston_subsurface *sub) if (weston_subsurface_is_synchronized(sub)) { weston_subsurface_commit_to_cache(sub); } else { - if (sub->cached.has_data) { + if (sub->has_cached_data) { /* flush accumulated state from cache */ weston_subsurface_commit_to_cache(sub); weston_subsurface_commit_from_cache(sub); @@ -2423,7 +2514,7 @@ weston_subsurface_synchronized_commit(struct weston_subsurface *sub) * all the way down. */ - if (sub->cached.has_data) + if (sub->has_cached_data) weston_subsurface_commit_from_cache(sub); wl_list_for_each(tmp, &surface->subsurface_list, parent_link) { @@ -2466,6 +2557,8 @@ subsurface_configure(struct weston_surface *surface, int32_t dx, int32_t dy) * will not be drawn either. */ if (!weston_surface_is_mapped(surface)) { + struct weston_output *output; + /* Cannot call weston_surface_update_transform(), * because that would call it also for the parent surface, * which might not be mapped yet. That would lead to @@ -2475,11 +2568,14 @@ subsurface_configure(struct weston_surface *surface, int32_t dx, int32_t dy) * Instead just assing any output, to make * weston_surface_is_mapped() return true, so that when the * parent surface does get mapped, this one will get - * included, too. See surface_list_add(). + * included, too. See view_list_add(). */ assert(!wl_list_empty(&compositor->output_list)); - surface->output = container_of(compositor->output_list.next, - struct weston_output, link); + output = container_of(compositor->output_list.next, + struct weston_output, link); + + surface->output = output; + weston_surface_update_output_mask(surface, 1 << output->id); } } @@ -2628,30 +2724,6 @@ subsurface_set_desync(struct wl_client *client, struct wl_resource *resource) } } -static void -weston_subsurface_cache_init(struct weston_subsurface *sub) -{ - pixman_region32_init(&sub->cached.damage); - pixman_region32_init(&sub->cached.opaque); - pixman_region32_init(&sub->cached.input); - wl_list_init(&sub->cached.frame_callback_list); - sub->cached.buffer_ref.buffer = NULL; -} - -static void -weston_subsurface_cache_fini(struct weston_subsurface *sub) -{ - struct weston_frame_callback *cb, *tmp; - - wl_list_for_each_safe(cb, tmp, &sub->cached.frame_callback_list, link) - wl_resource_destroy(cb->resource); - - weston_buffer_reference(&sub->cached.buffer_ref, NULL); - pixman_region32_fini(&sub->cached.damage); - pixman_region32_fini(&sub->cached.opaque); - pixman_region32_fini(&sub->cached.input); -} - static void weston_subsurface_unlink_parent(struct weston_subsurface *sub) { @@ -2746,13 +2818,16 @@ weston_subsurface_destroy(struct weston_subsurface *sub) assert(sub->parent_destroy_listener.notify == subsurface_handle_parent_destroy); - wl_list_for_each_safe(view, next, &sub->surface->views, surface_link) + wl_list_for_each_safe(view, next, &sub->surface->views, surface_link) { + weston_view_unmap(view); weston_view_destroy(view); + } if (sub->parent) weston_subsurface_unlink_parent(sub); - weston_subsurface_cache_fini(sub); + weston_surface_state_fini(&sub->cached); + weston_buffer_reference(&sub->cached_buffer_ref, NULL); sub->surface->configure = NULL; sub->surface->configure_private = NULL; @@ -2801,7 +2876,8 @@ weston_subsurface_create(uint32_t id, struct weston_surface *surface, sub, subsurface_resource_destroy); weston_subsurface_link_surface(sub, surface); weston_subsurface_link_parent(sub, parent); - weston_subsurface_cache_init(sub); + weston_surface_state_init(&sub->cached); + sub->cached_buffer_ref.buffer = NULL; sub->synchronized = 1; return sub; @@ -3069,7 +3145,7 @@ bind_output(struct wl_client *client, output->subpixel, output->make, output->model, output->transform); - if (version >= 2) + if (version >= WL_OUTPUT_SCALE_SINCE_VERSION) wl_output_send_scale(resource, output->current_scale); @@ -3081,7 +3157,7 @@ bind_output(struct wl_client *client, mode->refresh); } - if (version >= 2) + if (version >= WL_OUTPUT_DONE_SINCE_VERSION) wl_output_send_done(resource); } @@ -3403,6 +3479,7 @@ destroy_viewport(struct wl_resource *resource) surface->pending.buffer_viewport.buffer.src_width = wl_fixed_from_int(-1); surface->pending.buffer_viewport.surface.width = -1; + surface->pending.buffer_viewport.changed = 1; } static void @@ -3451,6 +3528,7 @@ viewport_set(struct wl_client *client, surface->pending.buffer_viewport.buffer.src_height = src_height; surface->pending.buffer_viewport.surface.width = dst_width; surface->pending.buffer_viewport.surface.height = dst_height; + surface->pending.buffer_viewport.changed = 1; } static void @@ -3471,6 +3549,7 @@ viewport_set_source(struct wl_client *client, /* unset source size */ surface->pending.buffer_viewport.buffer.src_width = wl_fixed_from_int(-1); + surface->pending.buffer_viewport.changed = 1; return; } @@ -3487,6 +3566,7 @@ viewport_set_source(struct wl_client *client, surface->pending.buffer_viewport.buffer.src_y = src_y; surface->pending.buffer_viewport.buffer.src_width = src_width; surface->pending.buffer_viewport.buffer.src_height = src_height; + surface->pending.buffer_viewport.changed = 1; } static void @@ -3503,6 +3583,7 @@ viewport_set_destination(struct wl_client *client, if (dst_width == -1 && dst_height == -1) { /* unset destination size */ surface->pending.buffer_viewport.surface.width = -1; + surface->pending.buffer_viewport.changed = 1; return; } @@ -3516,6 +3597,7 @@ viewport_set_destination(struct wl_client *client, surface->pending.buffer_viewport.surface.width = dst_width; surface->pending.buffer_viewport.surface.height = dst_height; + surface->pending.buffer_viewport.changed = 1; } static const struct wl_viewport_interface viewport_interface = { @@ -3710,6 +3792,11 @@ weston_compositor_init(struct weston_compositor *ec, if (weston_compositor_xkb_init(ec, &xkb_names) < 0) return -1; + weston_config_section_get_int(s, "repeat-rate", + &ec->kb_repeat_rate, 40); + weston_config_section_get_int(s, "repeat-delay", + &ec->kb_repeat_delay, 400); + text_backend_init(ec); wl_data_device_manager_init(ec->wl_display); @@ -4151,7 +4238,7 @@ int main(int argc, char *argv[]) char *server_socket = NULL, *end; int32_t idle_time = 300; int32_t help = 0; - char *socket_name = "wayland-0"; + const char *socket_name = NULL; int32_t version = 0; int32_t noconfig = 0; struct weston_config *config = NULL; @@ -4207,6 +4294,11 @@ int main(int argc, char *argv[]) signals[3] = wl_event_loop_add_signal(loop, SIGCHLD, sigchld_handler, NULL); + if (!signals[0] || !signals[1] || !signals[2] || !signals[3]) { + ret = EXIT_FAILURE; + goto out_signals; + } + if (noconfig == 0) config = weston_config_parse("weston.ini"); if (config != NULL) { @@ -4234,13 +4326,16 @@ int main(int argc, char *argv[]) backend_init = weston_load_module(backend, "backend_init"); free(backend); - if (!backend_init) - exit(EXIT_FAILURE); + if (!backend_init) { + ret = EXIT_FAILURE; + goto out_signals; + } ec = backend_init(display, &argc, argv, config); if (ec == NULL) { weston_log("fatal: failed to create compositor\n"); - exit(EXIT_FAILURE); + ret = EXIT_FAILURE; + goto out_signals; } catch_signals(); @@ -4249,30 +4344,6 @@ int main(int argc, char *argv[]) ec->idle_time = idle_time; ec->default_pointer_grab = NULL; - setenv("WAYLAND_DISPLAY", socket_name, 1); - - if (option_shell) - shell = strdup(option_shell); - else - weston_config_section_get_string(section, "shell", &shell, - "desktop-shell.so"); - - if (load_modules(ec, shell, &argc, argv) < 0) { - free(shell); - goto out; - } - free(shell); - - weston_config_section_get_string(section, "modules", &modules, ""); - if (load_modules(ec, modules, &argc, argv) < 0) { - free(modules); - goto out; - } - free(modules); - - if (load_modules(ec, option_modules, &argc, argv) < 0) - goto out; - for (i = 1; i < argc; i++) weston_log("fatal: unhandled option: %s\n", argv[i]); if (argc > 1) { @@ -4304,12 +4375,45 @@ int main(int argc, char *argv[]) wl_client_add_destroy_listener(primary_client, &primary_client_destroyed); } else { - if (wl_display_add_socket(display, socket_name)) { - weston_log("fatal: failed to add socket: %m\n"); - ret = EXIT_FAILURE; - goto out; + if (socket_name) { + if (wl_display_add_socket(display, socket_name)) { + weston_log("fatal: failed to add socket: %m\n"); + ret = EXIT_FAILURE; + goto out; + } + } else { + socket_name = wl_display_add_socket_auto(display); + if (!socket_name) { + weston_log("fatal: failed to add socket: %m\n"); + ret = EXIT_FAILURE; + goto out; + } } + + setenv("WAYLAND_DISPLAY", socket_name, 1); + } + + if (option_shell) + shell = strdup(option_shell); + else + weston_config_section_get_string(section, "shell", &shell, + "desktop-shell.so"); + + if (load_modules(ec, shell, &argc, argv) < 0) { + free(shell); + goto out; } + free(shell); + + weston_config_section_get_string(section, "modules", &modules, ""); + if (load_modules(ec, modules, &argc, argv) < 0) { + free(modules); + goto out; + } + free(modules); + + if (load_modules(ec, option_modules, &argc, argv) < 0) + goto out; weston_compositor_wake(ec); @@ -4321,12 +4425,15 @@ int main(int argc, char *argv[]) wl_signal_emit(&ec->destroy_signal, ec); - for (i = ARRAY_LENGTH(signals); i;) - wl_event_source_remove(signals[--i]); - weston_compositor_xkb_destroy(ec); ec->destroy(ec); + +out_signals: + for (i = ARRAY_LENGTH(signals) - 1; i >= 0; i--) + if (signals[i]) + wl_event_source_remove(signals[i]); + wl_display_destroy(display); weston_log_file_close(); diff --git a/src/compositor.h b/src/compositor.h index 057f8be8..c0fc0a6e 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -110,9 +110,9 @@ struct weston_shell_interface { struct weston_seat *ws, uint32_t edges); void (*set_title)(struct shell_surface *shsurf, const char *title); - void (*set_margin)(struct shell_surface *shsurf, - int32_t left, int32_t right, - int32_t top, int32_t bottom); + void (*set_window_geometry)(struct shell_surface *shsurf, + int32_t x, int32_t y, + int32_t width, int32_t height); }; struct weston_animation { @@ -526,9 +526,15 @@ enum { * to off */ }; +struct weston_layer_entry { + struct wl_list link; + struct weston_layer *layer; +}; + struct weston_layer { - struct wl_list view_list; + struct weston_layer_entry view_list; struct wl_list link; + pixman_box32_t mask; }; struct weston_plane { @@ -643,6 +649,9 @@ struct weston_compositor { /* Raw keyboard processing (no libxkbcommon initialization or handling) */ int use_xkbcommon; + + int32_t kb_repeat_rate; + int32_t kb_repeat_delay; }; struct weston_buffer { @@ -686,6 +695,8 @@ struct weston_buffer_viewport { */ int32_t width, height; } surface; + + int changed; }; struct weston_region { @@ -693,57 +704,6 @@ struct weston_region { pixman_region32_t region; }; -struct weston_subsurface { - struct wl_resource *resource; - - /* guaranteed to be valid and non-NULL */ - struct weston_surface *surface; - struct wl_listener surface_destroy_listener; - - /* can be NULL */ - struct weston_surface *parent; - struct wl_listener parent_destroy_listener; - struct wl_list parent_link; - struct wl_list parent_link_pending; - - struct { - int32_t x; - int32_t y; - int set; - } position; - - struct { - int has_data; - - /* wl_surface.attach */ - int newly_attached; - struct weston_buffer_reference buffer_ref; - int32_t sx; - int32_t sy; - - /* wl_surface.damage */ - pixman_region32_t damage; - - /* wl_surface.set_opaque_region */ - pixman_region32_t opaque; - - /* wl_surface.set_input_region */ - pixman_region32_t input; - - /* wl_surface.frame */ - struct wl_list frame_callback_list; - - /* wl_surface.set_buffer_transform */ - /* wl_surface.set_buffer_scale */ - struct weston_buffer_viewport buffer_viewport; - } cached; - - int synchronized; - - /* Used for constructing the view tree */ - struct wl_list unused_views; -}; - /* Using weston_view transformations * * To add a transformation to a view, create a struct weston_transform, and @@ -780,8 +740,9 @@ struct weston_view { struct wl_signal destroy_signal; struct wl_list link; - struct wl_list layer_link; + struct weston_layer_entry layer_link; struct weston_plane *plane; + struct weston_view *parent_view; pixman_region32_t clip; float alpha; /* part of geometry, see below */ @@ -813,6 +774,8 @@ struct weston_view { pixman_region32_t boundingbox; pixman_region32_t opaque; + pixman_region32_t masked_boundingbox; + pixman_region32_t masked_opaque; /* matrix and inverse are used only if enabled = 1. * If enabled = 0, use x, y, width, height directly. @@ -838,6 +801,32 @@ struct weston_view { uint32_t output_mask; }; +struct weston_surface_state { + /* wl_surface.attach */ + int newly_attached; + struct weston_buffer *buffer; + struct wl_listener buffer_destroy_listener; + int32_t sx; + int32_t sy; + + /* wl_surface.damage */ + pixman_region32_t damage; + + /* wl_surface.set_opaque_region */ + pixman_region32_t opaque; + + /* wl_surface.set_input_region */ + pixman_region32_t input; + + /* wl_surface.frame */ + struct wl_list frame_callback_list; + + /* wl_surface.set_buffer_transform */ + /* wl_surface.set_scaling_factor */ + /* wl_viewport.set */ + struct weston_buffer_viewport buffer_viewport; +}; + struct weston_surface { struct wl_resource *resource; struct wl_signal destroy_signal; @@ -882,31 +871,7 @@ struct weston_surface { struct wl_resource *viewport_resource; /* All the pending state, that wl_surface.commit will apply. */ - struct { - /* wl_surface.attach */ - int newly_attached; - struct weston_buffer *buffer; - struct wl_listener buffer_destroy_listener; - int32_t sx; - int32_t sy; - - /* wl_surface.damage */ - pixman_region32_t damage; - - /* wl_surface.set_opaque_region */ - pixman_region32_t opaque; - - /* wl_surface.set_input_region */ - pixman_region32_t input; - - /* wl_surface.frame */ - struct wl_list frame_callback_list; - - /* wl_surface.set_buffer_transform */ - /* wl_surface.set_scaling_factor */ - /* wl_viewport.set */ - struct weston_buffer_viewport buffer_viewport; - } pending; + struct weston_surface_state pending; /* * If non-NULL, this function will be called on @@ -925,6 +890,35 @@ struct weston_surface { struct wl_list subsurface_list_pending; /* ...::parent_link_pending */ }; +struct weston_subsurface { + struct wl_resource *resource; + + /* guaranteed to be valid and non-NULL */ + struct weston_surface *surface; + struct wl_listener surface_destroy_listener; + + /* can be NULL */ + struct weston_surface *parent; + struct wl_listener parent_destroy_listener; + struct wl_list parent_link; + struct wl_list parent_link_pending; + + struct { + int32_t x; + int32_t y; + int set; + } position; + + int has_cached_data; + struct weston_surface_state cached; + struct weston_buffer_reference cached_buffer_ref; + + int synchronized; + + /* Used for constructing the view tree */ + struct wl_list unused_views; +}; + enum weston_key_state_update { STATE_UPDATE_AUTOMATIC, STATE_UPDATE_NONE, @@ -1014,9 +1008,20 @@ notify_touch(struct weston_seat *seat, uint32_t time, int touch_id, void notify_touch_frame(struct weston_seat *seat); +void +weston_layer_entry_insert(struct weston_layer_entry *list, + struct weston_layer_entry *entry); +void +weston_layer_entry_remove(struct weston_layer_entry *entry); void weston_layer_init(struct weston_layer *layer, struct wl_list *below); +void +weston_layer_set_mask(struct weston_layer *layer, int x, int y, int width, int height); + +void +weston_layer_set_mask_infinite(struct weston_layer *layer); + void weston_plane_init(struct weston_plane *plane, struct weston_compositor *ec, diff --git a/src/data-device.c b/src/data-device.c index 6a81bc8e..75fc60cb 100644 --- a/src/data-device.c +++ b/src/data-device.c @@ -52,13 +52,6 @@ struct weston_touch_drag { struct weston_touch_grab grab; }; -static void -empty_region(pixman_region32_t *region) -{ - pixman_region32_fini(region); - pixman_region32_init(region); -} - static void data_offer_accept(struct wl_client *client, struct wl_resource *resource, uint32_t serial, const char *mime_type) @@ -187,7 +180,7 @@ drag_surface_configure(struct weston_drag *drag, struct weston_surface *es, int32_t sx, int32_t sy) { - struct wl_list *list; + struct weston_layer_entry *list; float fx, fy; assert((pointer != NULL && touch == NULL) || @@ -200,10 +193,10 @@ drag_surface_configure(struct weston_drag *drag, else list = &es->compositor->cursor_layer.view_list; - wl_list_remove(&drag->icon->layer_link); - wl_list_insert(list, &drag->icon->layer_link); + weston_layer_entry_remove(&drag->icon->layer_link); + weston_layer_entry_insert(list, &drag->icon->layer_link); weston_view_update_transform(drag->icon); - empty_region(&es->pending.input); + pixman_region32_clear(&es->pending.input); } drag->dx += sx; @@ -358,7 +351,7 @@ data_device_end_drag_grab(struct weston_drag *drag, weston_view_unmap(drag->icon); drag->icon->surface->configure = NULL; - empty_region(&drag->icon->surface->pending.input); + pixman_region32_clear(&drag->icon->surface->pending.input); wl_list_remove(&drag->icon_destroy_listener.link); weston_view_destroy(drag->icon); } @@ -646,17 +639,25 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource, struct wl_resource *icon_resource, uint32_t serial) { struct weston_seat *seat = wl_resource_get_user_data(resource); + struct weston_surface *origin = wl_resource_get_user_data(origin_resource); struct weston_data_source *source = NULL; struct weston_surface *icon = NULL; + int is_pointer_grab, is_touch_grab; int32_t ret = 0; - if ((seat->pointer->button_count == 0 || - seat->pointer->grab_serial != serial || - !seat->pointer->focus || - seat->pointer->focus->surface != wl_resource_get_user_data(origin_resource)) && - (seat->touch->grab_serial != serial || - !seat->touch->focus || - seat->touch->focus->surface != wl_resource_get_user_data(origin_resource))) + is_pointer_grab = seat->pointer && + seat->pointer->button_count == 1 && + seat->pointer->grab_serial == serial && + seat->pointer->focus && + seat->pointer->focus->surface == origin; + + is_touch_grab = seat->touch && + seat->touch->num_tp == 1 && + seat->touch->grab_serial == serial && + seat->touch->focus && + seat->touch->focus->surface == origin; + + if (!is_pointer_grab && !is_touch_grab) return; /* FIXME: Check that the data source type array isn't empty. */ @@ -672,14 +673,9 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource, return; } - if (seat->pointer->button_count == 1 && - seat->pointer->grab_serial == serial && - seat->pointer->focus && - seat->pointer->focus->surface == wl_resource_get_user_data(origin_resource)) + if (is_pointer_grab) ret = weston_pointer_start_drag(seat->pointer, source, icon, client); - else if (seat->touch->grab_serial != serial || - seat->touch->focus || - seat->touch->focus->surface != wl_resource_get_user_data(origin_resource)) + else if (is_touch_grab) ret = weston_touch_start_drag(seat->touch, source, icon, client); if (ret < 0) diff --git a/src/gl-renderer.c b/src/gl-renderer.c index 63af75da..f7f29b3d 100644 --- a/src/gl-renderer.c +++ b/src/gl-renderer.c @@ -542,7 +542,7 @@ draw_view(struct weston_view *ev, struct weston_output *output, pixman_region32_init(&repaint); pixman_region32_intersect(&repaint, - &ev->transform.boundingbox, damage); + &ev->transform.masked_boundingbox, damage); pixman_region32_subtract(&repaint, &repaint, &ev->clip); if (!pixman_region32_not_empty(&repaint)) diff --git a/src/input.c b/src/input.c index 2c799f43..1ab55cea 100644 --- a/src/input.c +++ b/src/input.c @@ -1555,8 +1555,8 @@ pointer_cursor_surface_configure(struct weston_surface *es, empty_region(&es->input); if (!weston_surface_is_mapped(es)) { - wl_list_insert(&es->compositor->cursor_layer.view_list, - &pointer->sprite->layer_link); + weston_layer_entry_insert(&es->compositor->cursor_layer.view_list, + &pointer->sprite->layer_link); weston_view_update_transform(pointer->sprite); } } @@ -1721,6 +1721,12 @@ seat_get_keyboard(struct wl_client *client, struct wl_resource *resource, wl_resource_set_implementation(cr, &keyboard_interface, seat, unbind_resource); + if (wl_resource_get_version(cr) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) { + wl_keyboard_send_repeat_info(cr, + seat->compositor->kb_repeat_rate, + seat->compositor->kb_repeat_delay); + } + if (seat->compositor->use_xkbcommon) { wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keyboard->xkb_info->keymap_fd, @@ -1813,7 +1819,7 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id) enum wl_seat_capability caps = 0; resource = wl_resource_create(client, - &wl_seat_interface, MIN(version, 3), id); + &wl_seat_interface, MIN(version, 4), id); wl_list_insert(&seat->base_resource_list, wl_resource_get_link(resource)); wl_resource_set_implementation(resource, &seat_interface, data, unbind_resource); @@ -1826,7 +1832,7 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id) caps |= WL_SEAT_CAPABILITY_TOUCH; wl_seat_send_capabilities(resource, caps); - if (version >= 2) + if (version >= WL_SEAT_NAME_SINCE_VERSION) wl_seat_send_name(resource, seat->seat_name); } @@ -2207,7 +2213,7 @@ weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec, wl_signal_init(&seat->destroy_signal); wl_signal_init(&seat->updated_caps_signal); - seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 3, + seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 4, seat, bind_seat); seat->compositor = ec; diff --git a/src/libinput-device.c b/src/libinput-device.c index 4605a769..6e50eebb 100644 --- a/src/libinput-device.c +++ b/src/libinput-device.c @@ -73,11 +73,14 @@ handle_pointer_motion(struct libinput_device *libinput_device, { struct evdev_device *device = libinput_device_get_user_data(libinput_device); + wl_fixed_t dx, dy; + dx = wl_fixed_from_double(libinput_event_pointer_get_dx(pointer_event)); + dy = wl_fixed_from_double(libinput_event_pointer_get_dy(pointer_event)); notify_motion(device->seat, libinput_event_pointer_get_time(pointer_event), - libinput_event_pointer_get_dx(pointer_event), - libinput_event_pointer_get_dy(pointer_event)); + dx, + dy); } static void @@ -99,10 +102,12 @@ handle_pointer_motion_absolute( width = device->output->current_mode->width; height = device->output->current_mode->height; - x = libinput_event_pointer_get_absolute_x_transformed(pointer_event, - width); - y = libinput_event_pointer_get_absolute_y_transformed(pointer_event, - height); + x = wl_fixed_from_double( + libinput_event_pointer_get_absolute_x_transformed(pointer_event, + width)); + y = wl_fixed_from_double( + libinput_event_pointer_get_absolute_y_transformed(pointer_event, + height)); weston_output_transform_coordinate(device->output, x, y, &x, &y); notify_motion_absolute(device->seat, time, x, y); @@ -127,11 +132,13 @@ handle_pointer_axis(struct libinput_device *libinput_device, { struct evdev_device *device = libinput_device_get_user_data(libinput_device); + double value; + value = libinput_event_pointer_get_axis_value(pointer_event); notify_axis(device->seat, libinput_event_pointer_get_time(pointer_event), libinput_event_pointer_get_axis(pointer_event), - libinput_event_pointer_get_axis_value(pointer_event)); + wl_fixed_from_double(value)); } static void @@ -155,8 +162,10 @@ handle_touch_with_coords(struct libinput_device *libinput_device, width = device->output->current_mode->width; height = device->output->current_mode->height; - x = libinput_event_touch_get_x_transformed(touch_event, width); - y = libinput_event_touch_get_y_transformed(touch_event, height); + x = wl_fixed_from_double( + libinput_event_touch_get_x_transformed(touch_event, width)); + y = wl_fixed_from_double( + libinput_event_touch_get_y_transformed(touch_event, height)); weston_output_transform_coordinate(device->output, x, y, &x, &y); @@ -288,6 +297,29 @@ evdev_device_set_output(struct evdev_device *device, &device->output_destroy_listener); } +static void +configure_device(struct evdev_device *device) +{ + struct weston_compositor *compositor = device->seat->compositor; + struct weston_config_section *s; + int enable_tap; + int enable_tap_default; + + s = weston_config_get_section(compositor->config, + "libinput", NULL, NULL); + + if (libinput_device_config_tap_get_finger_count(device->device) > 0) { + enable_tap_default = + libinput_device_config_tap_get_default_enabled( + device->device); + weston_config_section_get_bool(s, "enable_tap", + &enable_tap, + enable_tap_default); + libinput_device_config_tap_set_enabled(device->device, + enable_tap); + } +} + struct evdev_device * evdev_device_create(struct libinput_device *libinput_device, struct weston_seat *seat) @@ -321,6 +353,8 @@ evdev_device_create(struct libinput_device *libinput_device, libinput_device_set_user_data(libinput_device, device); libinput_device_ref(libinput_device); + configure_device(device); + return device; } diff --git a/src/libinput-seat.c b/src/libinput-seat.c index d59ae429..09cf7c7e 100644 --- a/src/libinput-seat.c +++ b/src/libinput-seat.c @@ -252,8 +252,9 @@ udev_input_enable(struct udev_input *input) } static void -libinput_log_func(enum libinput_log_priority priority, void *user_data, - const char *format, va_list args) +libinput_log_func(struct libinput *libinput, + enum libinput_log_priority priority, + const char *format, va_list args) { weston_vlog(format, args); } @@ -268,25 +269,34 @@ udev_input_init(struct udev_input *input, struct weston_compositor *c, struct ud input->compositor = c; - libinput_log_set_handler(&libinput_log_func, NULL); - log_priority = getenv("WESTON_LIBINPUT_LOG_PRIORITY"); + input->libinput = libinput_udev_create_context(&libinput_interface, + input, udev); + if (!input->libinput) { + return -1; + } + + libinput_log_set_handler(input->libinput, &libinput_log_func); + if (log_priority) { if (strcmp(log_priority, "debug") == 0) { - libinput_log_set_priority(LIBINPUT_LOG_PRIORITY_DEBUG); + libinput_log_set_priority(input->libinput, + LIBINPUT_LOG_PRIORITY_DEBUG); } else if (strcmp(log_priority, "info") == 0) { - libinput_log_set_priority(LIBINPUT_LOG_PRIORITY_INFO); + libinput_log_set_priority(input->libinput, + LIBINPUT_LOG_PRIORITY_INFO); } else if (strcmp(log_priority, "error") == 0) { - libinput_log_set_priority(LIBINPUT_LOG_PRIORITY_ERROR); + libinput_log_set_priority(input->libinput, + LIBINPUT_LOG_PRIORITY_ERROR); } } - input->libinput = libinput_udev_create_for_seat(&libinput_interface, input, - udev, seat_id); - if (!input->libinput) { + if (libinput_udev_assign_seat(input->libinput, seat_id) != 0) { + libinput_unref(input->libinput); return -1; } + process_events(input); return udev_input_enable(input); @@ -300,7 +310,7 @@ udev_input_destroy(struct udev_input *input) wl_event_source_remove(input->libinput_source); wl_list_for_each_safe(seat, next, &input->compositor->seat_list, base.link) udev_seat_destroy(seat); - libinput_destroy(input->libinput); + libinput_unref(input->libinput); } static void diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c index 93be9682..a816d02e 100644 --- a/src/pixman-renderer.c +++ b/src/pixman-renderer.c @@ -397,7 +397,7 @@ draw_view(struct weston_view *ev, struct weston_output *output, pixman_region32_init(&repaint); pixman_region32_intersect(&repaint, - &ev->transform.boundingbox, damage); + &ev->transform.masked_boundingbox, damage); pixman_region32_subtract(&repaint, &repaint, &ev->clip); if (!pixman_region32_not_empty(&repaint)) diff --git a/src/screen-share.c b/src/screen-share.c index 6f60b81c..f9dcba1c 100644 --- a/src/screen-share.c +++ b/src/screen-share.c @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -101,6 +102,11 @@ struct ss_shm_buffer { pixman_image_t *pm_image; }; +struct screen_share { + struct weston_compositor *compositor; + char *command; +}; + static void ss_seat_handle_pointer_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, @@ -982,13 +988,18 @@ shared_output_destroy(struct shared_output *so) } static struct shared_output * -weston_output_share(struct weston_output *output, - const char *path, char *const argv[]) +weston_output_share(struct weston_output *output, const char* command) { int sv[2]; char str[32]; pid_t pid; sigset_t allsigs; + char *const argv[] = { + "/bin/sh", + "-c", + (char*)command, + NULL + }; if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) { weston_log("weston_output_share: socketpair failed: %m\n"); @@ -1025,7 +1036,7 @@ weston_output_share(struct weston_output *output, snprintf(str, sizeof str, "%d", sv[1]); setenv("WAYLAND_SERVER_SOCKET", str, 1); - execv(path, argv); + execv(argv[0], argv); weston_log("weston_output_share: exec failed: %m\n"); abort(); } else { @@ -1056,7 +1067,7 @@ share_output_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data) { struct weston_output *output; - const char *path = BINDIR "/weston"; + struct screen_share *ss = data; if (!seat->pointer) { weston_log("Cannot pick output: Seat does not have pointer\n"); @@ -1071,23 +1082,28 @@ share_output_binding(struct weston_seat *seat, uint32_t time, uint32_t key, return; } - char *const argv[] = { - "weston", - "--backend=rdp-backend.so", - "--shell=fullscreen-shell.so", - "--no-clients-resize", - NULL - }; - - weston_output_share(output, path, argv); + weston_output_share(output, ss->command); } WL_EXPORT int module_init(struct weston_compositor *compositor, int *argc, char *argv[]) { + struct screen_share *ss; + struct weston_config_section *section; + + ss = zalloc(sizeof *ss); + if (ss == NULL) + return -1; + ss->compositor = compositor; + + section = weston_config_get_section(compositor->config, "screen-share", + NULL, NULL); + + weston_config_section_get_string(section, "command", &ss->command, ""); + weston_compositor_add_key_binding(compositor, KEY_S, MODIFIER_CTRL | MODIFIER_ALT, - share_output_binding, compositor); + share_output_binding, ss); return 0; } diff --git a/src/screenshooter.c b/src/screenshooter.c index 369e9204..44039332 100644 --- a/src/screenshooter.c +++ b/src/screenshooter.c @@ -265,7 +265,7 @@ bind_shooter(struct wl_client *client, if (client != shooter->client) { wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "screenshooter failed: permission denied"); - wl_resource_destroy(resource); + return; } wl_resource_set_implementation(resource, &screenshooter_implementation, diff --git a/src/spring-tool.c b/src/spring-tool.c index 41cc52ce..685bfd9f 100644 --- a/src/spring-tool.c +++ b/src/spring-tool.c @@ -40,6 +40,11 @@ weston_view_schedule_repaint(struct weston_view *view) { } +WL_EXPORT void +weston_compositor_schedule_repaint(struct weston_compositor *compositor) +{ +} + int main(int argc, char *argv[]) { diff --git a/src/text-backend.c b/src/text-backend.c index d6a6f3b3..1d549d43 100644 --- a/src/text-backend.c +++ b/src/text-backend.c @@ -790,14 +790,12 @@ bind_input_method(struct wl_client *client, if (input_method->input_method_binding != NULL) { wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "interface object already bound"); - wl_resource_destroy(resource); return; } if (text_backend->input_method.client != client) { wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "permission to bind input_method denied"); - wl_resource_destroy(resource); return; } diff --git a/tests/bad-buffer-test.c b/tests/bad-buffer-test.c index 86e0299b..3b54ac6a 100644 --- a/tests/bad-buffer-test.c +++ b/tests/bad-buffer-test.c @@ -60,34 +60,12 @@ create_bad_shm_buffer(struct client *client, int width, int height) return buffer; } -static void sighandler(int signum) -{ - /* this means failure */ - exit(0); -} - -FAIL_TEST(test_truncated_shm_file) +TEST(test_truncated_shm_file) { struct client *client; struct wl_buffer *bad_buffer; struct wl_surface *surface; int frame; - struct sigaction new_action, old_action; - - /* until the bad buffer creation, the SIGABRT or SIGSEGV signals - * should fail the test. That means returning 0 */ - new_action.sa_handler = sighandler; - sigemptyset(&new_action.sa_mask); - new_action.sa_flags = 0; - - if (sigaction(SIGSEGV, &new_action, NULL) != 0) { - fprintf(stderr, "Failed setting new sigaction for SIGSEGV"); - exit(0); - } - if (sigaction(SIGABRT, &new_action, &old_action) != 0) { - fprintf(stderr, "Failed setting new sigaction for SIGABRT"); - exit(0); - } client = client_create(46, 76, 111, 134); assert(client); @@ -95,15 +73,12 @@ FAIL_TEST(test_truncated_shm_file) bad_buffer = create_bad_shm_buffer(client, 200, 200); - /* from this point we expect the signal */ - if (sigaction(SIGABRT, &old_action, NULL) != 0) { - fprintf(stderr, "Failed setting old sigaction for SIGABRT"); - exit(0); - } - wl_surface_attach(surface, bad_buffer, 0, 0); wl_surface_damage(surface, 0, 0, 200, 200); frame_callback_set(surface, &frame); wl_surface_commit(surface); - frame_callback_wait(client, &frame); + frame_callback_wait_nofail(client, &frame); + + expect_protocol_error(client, &wl_buffer_interface, + WL_SHM_ERROR_INVALID_FD); } diff --git a/tests/subsurface-test.c b/tests/subsurface-test.c index 0670e7f7..bee249b4 100644 --- a/tests/subsurface-test.c +++ b/tests/subsurface-test.c @@ -133,7 +133,7 @@ TEST(test_subsurface_placement_protocol) client_roundtrip(client); } -FAIL_TEST(test_subsurface_paradox) +TEST(test_subsurface_paradox) { struct client *client; struct wl_surface *parent; @@ -148,10 +148,11 @@ FAIL_TEST(test_subsurface_paradox) /* surface is its own parent */ wl_subcompositor_get_subsurface(subco, parent, parent); - client_roundtrip(client); + expect_protocol_error(client, &wl_subcompositor_interface, + WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE); } -FAIL_TEST(test_subsurface_identical_link) +TEST(test_subsurface_identical_link) { struct client *client; struct compound_surface com; @@ -164,10 +165,11 @@ FAIL_TEST(test_subsurface_identical_link) /* surface is already a subsurface */ wl_subcompositor_get_subsurface(com.subco, com.child[0], com.parent); - client_roundtrip(client); + expect_protocol_error(client, &wl_subcompositor_interface, + WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE); } -FAIL_TEST(test_subsurface_change_link) +TEST(test_subsurface_change_link) { struct client *client; struct compound_surface com; @@ -182,7 +184,8 @@ FAIL_TEST(test_subsurface_change_link) /* surface is already a subsurface */ wl_subcompositor_get_subsurface(com.subco, com.child[0], stranger); - client_roundtrip(client); + expect_protocol_error(client, &wl_subcompositor_interface, + WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE); } TEST(test_subsurface_nesting) @@ -221,7 +224,7 @@ TEST(test_subsurface_nesting_parent) client_roundtrip(client); } -FAIL_TEST(test_subsurface_loop_paradox) +TEST(test_subsurface_loop_paradox) { struct client *client; struct wl_surface *surface[3]; @@ -240,10 +243,11 @@ FAIL_TEST(test_subsurface_loop_paradox) wl_subcompositor_get_subsurface(subco, surface[2], surface[1]); wl_subcompositor_get_subsurface(subco, surface[0], surface[2]); - client_roundtrip(client); + expect_protocol_error(client, &wl_subcompositor_interface, + WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE); } -FAIL_TEST(test_subsurface_place_above_stranger) +TEST(test_subsurface_place_above_stranger) { struct client *client; struct compound_surface com; @@ -258,10 +262,11 @@ FAIL_TEST(test_subsurface_place_above_stranger) /* bad sibling */ wl_subsurface_place_above(com.sub[0], stranger); - client_roundtrip(client); + expect_protocol_error(client, &wl_subsurface_interface, + WL_SUBSURFACE_ERROR_BAD_SURFACE); } -FAIL_TEST(test_subsurface_place_below_stranger) +TEST(test_subsurface_place_below_stranger) { struct client *client; struct compound_surface com; @@ -276,10 +281,11 @@ FAIL_TEST(test_subsurface_place_below_stranger) /* bad sibling */ wl_subsurface_place_below(com.sub[0], stranger); - client_roundtrip(client); + expect_protocol_error(client, &wl_subsurface_interface, + WL_SUBSURFACE_ERROR_BAD_SURFACE); } -FAIL_TEST(test_subsurface_place_above_foreign) +TEST(test_subsurface_place_above_foreign) { struct client *client; struct compound_surface com1; @@ -294,10 +300,11 @@ FAIL_TEST(test_subsurface_place_above_foreign) /* bad sibling */ wl_subsurface_place_above(com1.sub[0], com2.child[0]); - client_roundtrip(client); + expect_protocol_error(client, &wl_subsurface_interface, + WL_SUBSURFACE_ERROR_BAD_SURFACE); } -FAIL_TEST(test_subsurface_place_below_foreign) +TEST(test_subsurface_place_below_foreign) { struct client *client; struct compound_surface com1; @@ -312,7 +319,8 @@ FAIL_TEST(test_subsurface_place_below_foreign) /* bad sibling */ wl_subsurface_place_below(com1.sub[0], com2.child[0]); - client_roundtrip(client); + expect_protocol_error(client, &wl_subsurface_interface, + WL_SUBSURFACE_ERROR_BAD_SURFACE); } TEST(test_subsurface_destroy_protocol) diff --git a/tests/weston-test-client-helper.c b/tests/weston-test-client-helper.c index 186b3956..79097fa1 100644 --- a/tests/weston-test-client-helper.c +++ b/tests/weston-test-client-helper.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "../shared/os-compatibility.h" @@ -79,12 +80,15 @@ frame_callback_set(struct wl_surface *surface, int *done) return callback; } -void -frame_callback_wait(struct client *client, int *done) +int +frame_callback_wait_nofail(struct client *client, int *done) { while (!*done) { - assert(wl_display_dispatch(client->wl_display) >= 0); + if (wl_display_dispatch(client->wl_display) < 0) + return 0; } + + return 1; } void @@ -512,6 +516,53 @@ skip(const char *fmt, ...) exit(77); } +void +expect_protocol_error(struct client *client, + const struct wl_interface *intf, + uint32_t code) +{ + int err; + uint32_t errcode, failed = 0; + const struct wl_interface *interface; + unsigned int id; + + /* if the error has not come yet, make it happen */ + wl_display_roundtrip(client->wl_display); + + err = wl_display_get_error(client->wl_display); + + assert(err && "Expected protocol error but nothing came"); + assert(err == EPROTO && "Expected protocol error but got local error"); + + errcode = wl_display_get_protocol_error(client->wl_display, + &interface, &id); + + /* check error */ + if (errcode != code) { + fprintf(stderr, "Should get error code %d but got %d\n", + code, errcode); + failed = 1; + } + + /* this should be definitely set */ + assert(interface); + + if (strcmp(intf->name, interface->name) != 0) { + fprintf(stderr, "Should get interface '%s' but got '%s'\n", + intf->name, interface->name); + failed = 1; + } + + if (failed) { + fprintf(stderr, "Expected other protocol error\n"); + abort(); + } + + /* all OK */ + fprintf(stderr, "Got expected protocol error on '%s' (object id: %d) " + "with code %d\n", interface->name, id, errcode); +} + static void log_handler(const char *fmt, va_list args) { diff --git a/tests/weston-test-client-helper.h b/tests/weston-test-client-helper.h index 4bfc3fac..684afc6f 100644 --- a/tests/weston-test-client-helper.h +++ b/tests/weston-test-client-helper.h @@ -120,8 +120,10 @@ move_client(struct client *client, int x, int y); struct wl_callback * frame_callback_set(struct wl_surface *surface, int *done); -void -frame_callback_wait(struct client *client, int *done); +int +frame_callback_wait_nofail(struct client *client, int *done); + +#define frame_callback_wait(c, d) assert(frame_callback_wait_nofail((c), (d))) int get_n_egl_buffers(struct client *client); @@ -129,4 +131,8 @@ get_n_egl_buffers(struct client *client); void skip(const char *fmt, ...); +void +expect_protocol_error(struct client *client, + const struct wl_interface *intf, uint32_t code); + #endif diff --git a/tests/weston-test.c b/tests/weston-test.c index 35ccaa40..ca2f2194 100644 --- a/tests/weston-test.c +++ b/tests/weston-test.c @@ -93,9 +93,9 @@ test_surface_configure(struct weston_surface *surface, int32_t sx, int32_t sy) struct weston_test_surface *test_surface = surface->configure_private; struct weston_test *test = test_surface->test; - if (wl_list_empty(&test_surface->view->layer_link)) - wl_list_insert(&test->layer.view_list, - &test_surface->view->layer_link); + if (wl_list_empty(&test_surface->view->layer_link.link)) + weston_layer_entry_insert(&test->layer.view_list, + &test_surface->view->layer_link); weston_view_set_position(test_surface->view, test_surface->x, test_surface->y); diff --git a/weston.ini.in b/weston.ini.in index 2c391779..4fca0bbb 100644 --- a/weston.ini.in +++ b/weston.ini.in @@ -38,7 +38,7 @@ icon=/usr/share/icons/gnome/24x24/apps/arts.png path=@abs_top_builddir@/weston-flower [screensaver] -# Uncomment path to disable screensaver +# Comment path to disable screensaver path=@libexecdir@/weston-screensaver duration=600 @@ -59,9 +59,15 @@ path=@libexecdir@/weston-keyboard #[output] #name=X1 #mode=1024x768 -#transform=flipped-270 +#transform=flipped-90 + +#[libinput] +#enable_tap=true #[touchpad] #constant_accel_factor = 50 #min_accel_factor = 0.16 #max_accel_factor = 1.0 + +[screen-share] +command=@bindir@/weston --backend=rdp-backend.so --shell=fullscreen-shell.so --no-clients-resize diff --git a/xwayland/launcher.c b/xwayland/launcher.c index 70703a4b..bf1e17eb 100644 --- a/xwayland/launcher.c +++ b/xwayland/launcher.c @@ -117,7 +117,11 @@ weston_xserver_handle_event(int listen_fd, uint32_t mask, void *data) "-wm", wm_fd, "-terminate", NULL) < 0) - weston_log("exec failed: %m\n"); + weston_log("exec of '%s %s -rootless " + "-listen %s -listen %s -wm %s " + "-terminate' failed: %m\n", + xserver, display, + abstract_fd, unix_fd, wm_fd); fail: _exit(EXIT_FAILURE); diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c index 2fb65b1a..6cac2782 100644 --- a/xwayland/window-manager.c +++ b/xwayland/window-manager.c @@ -1007,12 +1007,9 @@ weston_wm_window_draw_decoration(void *data) pixman_region32_init_rect(&window->surface->pending.input, input_x, input_y, input_w, input_h); - - shell_interface->set_margin(window->shsurf, - input_x, - width - input_w - input_x, - input_y, - height - input_h - input_y); + + shell_interface->set_window_geometry(window->shsurf, + input_x, input_y, input_w, input_h); } } @@ -1374,14 +1371,17 @@ weston_wm_window_handle_surface_id(struct weston_wm_window *window, * hasn't been created yet. In that case put the window on * the unpaired window list and continue when the surface gets * created. */ - window->surface_id = client_message->data.data32[0]; - resource = wl_client_get_object(wm->server->client, - window->surface_id); - if (resource) + uint32_t id = client_message->data.data32[0]; + resource = wl_client_get_object(wm->server->client, id); + if (resource) { + window->surface_id = 0; xserver_map_shell_surface(window, wl_resource_get_user_data(resource)); - else + } + else { + window->surface_id = id; wl_list_insert(&wm->unpaired_window_list, &window->link); + } } static void @@ -1403,6 +1403,12 @@ weston_wm_handle_client_message(struct weston_wm *wm, client_message->data.data32[4], client_message->window); + /* The window may get created and destroyed before we actually + * handle the message. If it doesn't exist, bail. + */ + if (!window) + return; + if (client_message->type == wm->atom.net_wm_moveresize) weston_wm_window_handle_moveresize(window, client_message); else if (client_message->type == wm->atom.net_wm_state) -- cgit v1.2.1