summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuhiko Tanibata <NOBUHIKO_TANIBATA@xddp.denso.co.jp>2014-08-19 17:33:02 +0900
committerNobuhiko Tanibata <NOBUHIKO_TANIBATA@xddp.denso.co.jp>2014-08-19 17:33:02 +0900
commite9568c17bbae5ad70d2b7d33299139a3cc4193ac (patch)
treed3609610c3675b480ca9aa17f67e018fa38d2dbe
parentbd2a61db01eba84c49a852338f171e5cf844308a (diff)
downloadweston-e9568c17bbae5ad70d2b7d33299139a3cc4193ac.tar.gz
Latest branch in weston 1.5.0
commit: 61917c84e3fcbb71da806a5e94a82916d77e18b1 Signed-off-by: Nobuhiko Tanibata <NOBUHIKO_TANIBATA@xddp.denso.co.jp>
-rw-r--r--Makefile.am14
-rw-r--r--clients/cliptest.c13
-rw-r--r--clients/desktop-shell.c40
-rw-r--r--clients/dnd.c11
-rw-r--r--clients/editor.c3
-rw-r--r--clients/flower.c4
-rw-r--r--clients/fullscreen.c34
-rw-r--r--clients/gears.c25
-rw-r--r--clients/image.c2
-rw-r--r--clients/nested.c9
-rw-r--r--clients/resizor.c3
-rw-r--r--clients/scaler.c3
-rw-r--r--clients/simple-damage.c880
-rw-r--r--clients/simple-egl.c99
-rw-r--r--clients/simple-shm.c25
-rw-r--r--clients/smoke.c4
-rw-r--r--clients/stacking.c11
-rw-r--r--clients/terminal.c94
-rw-r--r--clients/transformed.c3
-rw-r--r--clients/weston-info.c89
-rw-r--r--clients/window.c380
-rw-r--r--clients/window.h20
-rw-r--r--configure.ac9
-rw-r--r--desktop-shell/exposay.c8
-rw-r--r--desktop-shell/input-panel.c8
-rw-r--r--desktop-shell/shell.c562
-rw-r--r--desktop-shell/shell.h1
-rw-r--r--fullscreen-shell/fullscreen-shell.c4
-rw-r--r--m4/.gitignore5
-rw-r--r--man/weston.ini.man22
-rwxr-xr-xpatch.sh30
-rw-r--r--protocol/xdg-shell.xml223
-rw-r--r--releasing.txt43
-rw-r--r--shared/frame.c5
-rw-r--r--src/animation.c16
-rw-r--r--src/compositor-drm.c41
-rw-r--r--src/compositor-rdp.c156
-rw-r--r--src/compositor-wayland.c31
-rw-r--r--src/compositor.c561
-rw-r--r--src/compositor.h167
-rw-r--r--src/data-device.c48
-rw-r--r--src/gl-renderer.c2
-rw-r--r--src/input.c16
-rw-r--r--src/libinput-device.c52
-rw-r--r--src/libinput-seat.c32
-rw-r--r--src/pixman-renderer.c2
-rw-r--r--src/screen-share.c44
-rw-r--r--src/screenshooter.c2
-rw-r--r--src/spring-tool.c5
-rw-r--r--src/text-backend.c2
-rw-r--r--tests/bad-buffer-test.c35
-rw-r--r--tests/subsurface-test.c40
-rw-r--r--tests/weston-test-client-helper.c57
-rw-r--r--tests/weston-test-client-helper.h10
-rw-r--r--tests/weston-test.c6
-rw-r--r--weston.ini.in10
-rw-r--r--xwayland/launcher.c6
-rw-r--r--xwayland/window-manager.c28
58 files changed, 2833 insertions, 1222 deletions
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;
@@ -66,14 +66,6 @@ fullscreen_handler(struct window *window, void *data)
}
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;
@@ -400,17 +390,6 @@ enter_handler(struct widget *widget,
}
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,
uint32_t button, enum wl_pointer_button_state state, void *data)
@@ -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 <stdint.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -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
@@ -551,13 +551,6 @@ surface_set_input_region(struct wl_client *client,
}
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)
{
struct nested_surface *surface = wl_resource_get_user_data(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 <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <signal.h>
+
+#include <wayland-client.h>
+#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,
+ &registry_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;
@@ -834,12 +835,26 @@ terminal_resize_cells(struct terminal *terminal,
}
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
@@ -4241,6 +4259,13 @@ window_set_output_handler(struct window *window,
}
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)
{
free(window->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
@@ -2447,25 +2492,6 @@ shell_surface_set_popup(struct wl_client *client,
}
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)
{
/* undo all maximized things here */
@@ -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(&current_ws->layer.view_list, &view->layer_link);
+ weston_layer_entry_insert(&current_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;
@@ -3370,19 +3411,6 @@ xdg_surface_set_transient_for(struct wl_client *client,
}
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,
const char *app_id)
@@ -3394,6 +3422,17 @@ xdg_surface_set_app_id(struct wl_client *client,
}
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 @@
</description>
</request>
- <request name="set_transient_for">
+ <request name="set_parent">
<description summary="surface is a child of another surface">
- 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 @@
<arg name="parent" type="object" interface="wl_surface" allow-null="true"/>
</request>
- <request name="set_margin">
- <description summary="set the visible frame boundaries">
- 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.
- </description>
- <arg name="left_margin" type="int"/>
- <arg name="right_margin" type="int"/>
- <arg name="top_margin" type="int"/>
- <arg name="bottom_margin" type="int"/>
- </request>
-
<request name="set_title">
<description summary="set surface title">
Set a short title for the surface.
@@ -201,6 +172,26 @@
<arg name="app_id" type="string"/>
</request>
+ <request name="show_window_menu">
+ <description summary="show the window menu">
+ 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.
+ </description>
+
+ <arg name="seat" type="object" interface="wl_seat" summary="the seat to pop the window up on"/>
+ <arg name="serial" type="uint" summary="serial of the event to pop up the window for"/>
+ <arg name="x" type="int" summary="the x position to pop up the window menu at"/>
+ <arg name="y" type="int" summary="the y position to pop up the window menu at"/>
+ </request>
+
<request name="move">
<description summary="start an interactive move">
Start a pointer-driven move of the surface.
@@ -244,46 +235,12 @@
<arg name="edges" type="uint" summary="which edge or corner is being dragged"/>
</request>
- <event name="configure">
- <description summary="suggest resize">
- 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.
- </description>
-
- <arg name="width" type="int"/>
- <arg name="height" type="int"/>
- </event>
-
- <request name="set_output">
- <description summary="set the default output used by this surface">
- 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.
- </description>
- <arg name="output" type="object" interface="wl_output" allow-null="true"/>
- </request>
-
<enum name="state">
<description summary="types of state on the surface">
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
</description>
<entry name="maximized" value="1" summary="the surface is maximized">
- 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.
</entry>
<entry name="fullscreen" value="2" summary="the surface is fullscreen">
- 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.
+ </entry>
+ <entry name="resizing" value="3">
+ 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.
+ </entry>
+ <entry name="activated" value="4">
+ 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.
</entry>
</enum>
- <request name="request_change_state">
- <description summary="client requests to change a surface's state">
- 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.
+ <event name="configure">
+ <description summary="suggest a surface change">
+ 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.
- </description>
- <arg name="state_type" type="uint" summary="the state to set"/>
- <arg name="value" type="uint" summary="the value to change the state to"/>
- <arg name="serial" type="uint" summary="an event serial">
- This serial is so the client can know which change_state event corresponds
- to which request_change_state request it sent out.
- </arg>
- </request>
+ 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.
- <event name="change_state">
- <description summary="compositor wants to change a surface's state">
- 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.
</description>
- <arg name="state_type" type="uint" summary="the state to set"/>
- <arg name="value" type="uint" summary="the value to change the state to"/>
- <arg name="serial" type="uint" summary="a serial for the compositor's own tracking"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ <arg name="states" type="array"/>
+ <arg name="serial" type="uint"/>
</event>
- <request name="ack_change_state">
- <description summary="ack a change_state event">
- When a change_state event is received, a client should then ack it
- using the ack_change_state request to ensure that the compositor
+ <request name="ack_configure">
+ <description summary="ack a configure event">
+ 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.
</description>
- <arg name="state_type" type="uint" summary="the state to set"/>
- <arg name="value" type="uint" summary="the value to change the state to"/>
- <arg name="serial" type="uint" summary="a serial to pass to change_state"/>
+ <arg name="serial" type="uint" summary="a serial to configure for"/>
</request>
- <request name="set_minimized">
- <description summary="minimize the surface">
- Minimize the surface.
+ <request name="set_window_geometry">
+ <description summary="set the new window geometry">
+ 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.
</description>
+ <arg name="x" type="int"/>
+ <arg name="y" type="int"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
</request>
- <event name="activated">
- <description summary="surface was activated">
- 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.
- </description>
- </event>
+ <request name="set_maximized" />
+ <request name="unset_maximized" />
+
+ <request name="set_fullscreen">
+ <description summary="set the window as fullscreen on a monitor">
+ Make the surface fullscreen.
- <event name="deactivated">
- <description summary="surface was deactivated">
- 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.
</description>
- </event>
+ <arg name="output" type="object" interface="wl_output" allow-null="true"/>
+ </request>
+ <request name="unset_fullscreen" />
+
+ <request name="set_minimized" />
<event name="close">
<description summary="surface wants to be closed">
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 <freerdp/codec/color.h>
#include <freerdp/codec/rfx.h>
#include <freerdp/codec/nsc.h>
+#include <freerdp/locale/keyboard.h>
#include <winpr/input.h>
#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
@@ -320,23 +320,6 @@ weston_client_launch(struct weston_compositor *compositor,
}
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)
{
pixman_region32_init_rect(region, INT32_MIN, INT32_MIN,
@@ -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);
}
@@ -1869,14 +1947,55 @@ idle_repaint(void *data)
}
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)
{
struct weston_compositor *compositor = output->compositor;
@@ -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,
&region->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);
}
}
@@ -2629,30 +2725,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)
{
wl_list_remove(&sub->parent_link);
@@ -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,
@@ -1015,9 +1009,20 @@ 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,
int32_t x, int32_t y);
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
@@ -53,13 +53,6 @@ struct weston_touch_drag {
};
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 <signal.h>
#include <linux/input.h>
#include <errno.h>
+#include <ctype.h>
#include <wayland-client.h>
@@ -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 <stdio.h>
#include <string.h>
#include <unistd.h>
+#include <errno.h>
#include <sys/mman.h>
#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)