summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuhiko Tanibata <NOBUHIKO_TANIBATA@xddp.denso.co.jp>2014-05-06 13:37:53 +0900
committerNobuhiko Tanibata <NOBUHIKO_TANIBATA@xddp.denso.co.jp>2014-05-06 13:37:53 +0900
commite2102cdbffd64fb0f383b2b60008d5353bbbe8d4 (patch)
tree7c5a2721e3a6ffd9629ee673a638af257b761941
parent2991da5687fa2828d551fd7b2388d9648a19ecc2 (diff)
downloadweston-e2102cdbffd64fb0f383b2b60008d5353bbbe8d4.tar.gz
weston 1.4.92
-rw-r--r--clients/desktop-shell.c7
-rw-r--r--clients/editor.c103
-rw-r--r--clients/keyboard.c280
-rw-r--r--clients/terminal.c12
-rw-r--r--clients/weston-info.c2
-rw-r--r--clients/window.c57
-rw-r--r--configure.ac2
-rw-r--r--desktop-shell/exposay.c8
-rw-r--r--desktop-shell/input-panel.c61
-rw-r--r--desktop-shell/shell.c505
-rw-r--r--desktop-shell/shell.h14
-rw-r--r--protocol/fullscreen-shell.xml2
-rw-r--r--shared/cairo-util.c15
-rw-r--r--src/animation.c62
-rw-r--r--src/compositor-drm.c20
-rw-r--r--src/compositor-wayland.c6
-rw-r--r--src/compositor.c39
-rw-r--r--src/compositor.h17
-rw-r--r--src/data-device.c6
-rw-r--r--src/evdev.c26
-rw-r--r--src/gl-renderer.h5
-rw-r--r--src/input.c19
-rw-r--r--src/launcher-util.c5
-rw-r--r--src/libinput-device.c26
-rw-r--r--src/libinput-seat.c27
-rw-r--r--src/pixman-renderer.c4
-rw-r--r--src/screen-share.c21
-rw-r--r--src/screenshooter.c33
-rw-r--r--src/udev-seat.c11
-rw-r--r--tests/.gitignore12
-rw-r--r--tests/bad-buffer-test.c30
-rw-r--r--xwayland/launcher.c8
-rw-r--r--xwayland/window-manager.c45
33 files changed, 1019 insertions, 471 deletions
diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
index a0c6b6d4..4880888a 100644
--- a/clients/desktop-shell.c
+++ b/clients/desktop-shell.c
@@ -709,6 +709,8 @@ background_draw(struct widget *widget, void *data)
image = NULL;
if (background->image)
image = load_cairo_surface(background->image);
+ else if (background->color == 0)
+ image = load_cairo_surface(DATADIR "/weston/pattern.png");
if (image && background->type != -1) {
im_w = cairo_image_surface_get_width(image);
@@ -1057,10 +1059,9 @@ background_create(struct desktop *desktop)
s = weston_config_get_section(desktop->config, "shell", NULL, NULL);
weston_config_section_get_string(s, "background-image",
- &background->image,
- DATADIR "/weston/pattern.png");
+ &background->image, NULL);
weston_config_section_get_uint(s, "background-color",
- &background->color, 0xff002244);
+ &background->color, 0);
weston_config_section_get_string(s, "background-type",
&type, "tile");
diff --git a/clients/editor.c b/clients/editor.c
index 76e2346a..3b00833e 100644
--- a/clients/editor.c
+++ b/clients/editor.c
@@ -110,6 +110,47 @@ utf8_next_char(const char *p)
return NULL;
}
+static void
+move_up(const char *p, uint32_t *cursor)
+{
+ const char *posr, *posr_i;
+ char text[16];
+
+ xkb_keysym_to_utf8(XKB_KEY_Return, text, sizeof(text));
+
+ posr = strstr(p, text);
+ while (posr) {
+ if (*cursor > (unsigned)(posr-p)) {
+ posr_i = strstr(posr+1, text);
+ if (!posr_i || !(*cursor > (unsigned)(posr_i-p))) {
+ *cursor = posr-p;
+ break;
+ }
+ posr = posr_i;
+ } else {
+ break;
+ }
+ }
+}
+
+static void
+move_down(const char *p, uint32_t *cursor)
+{
+ const char *posr;
+ char text[16];
+
+ xkb_keysym_to_utf8(XKB_KEY_Return, text, sizeof(text));
+
+ posr = strstr(p, text);
+ while (posr) {
+ if (*cursor <= (unsigned)(posr-p)) {
+ *cursor = posr-p + 1;
+ break;
+ }
+ posr = strstr(posr+1, text);
+ }
+}
+
static void text_entry_redraw_handler(struct widget *widget, void *data);
static void text_entry_button_handler(struct widget *widget,
struct input *input, uint32_t time,
@@ -345,14 +386,8 @@ text_input_keysym(void *data,
uint32_t modifiers)
{
struct text_entry *entry = data;
- const char *state_label = "release";
- const char *key_label = "Unknown";
const char *new_char;
- if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
- state_label = "pressed";
- }
-
if (key == XKB_KEY_Left ||
key == XKB_KEY_Right) {
if (state != WL_KEYBOARD_KEY_STATE_RELEASED)
@@ -374,6 +409,23 @@ text_input_keysym(void *data,
return;
}
+ if (key == XKB_KEY_Up ||
+ key == XKB_KEY_Down) {
+ if (state != WL_KEYBOARD_KEY_STATE_RELEASED)
+ return;
+
+ if (key == XKB_KEY_Up)
+ move_up(entry->text, &entry->cursor);
+ else
+ move_down(entry->text, &entry->cursor);
+
+ if (!(modifiers & entry->keysym.shift_mask))
+ entry->anchor = entry->cursor;
+ widget_schedule_redraw(entry->widget);
+
+ return;
+ }
+
if (key == XKB_KEY_BackSpace) {
const char *start, *end;
@@ -395,17 +447,20 @@ text_input_keysym(void *data,
return;
}
- switch (key) {
- case XKB_KEY_Tab:
- key_label = "Tab";
- break;
- case XKB_KEY_KP_Enter:
- case XKB_KEY_Return:
- key_label = "Enter";
- break;
- }
+ if (key == XKB_KEY_Tab ||
+ key == XKB_KEY_KP_Enter ||
+ key == XKB_KEY_Return) {
+ char text[16];
- fprintf(stderr, "%s key was %s.\n", key_label, state_label);
+ if (state != WL_KEYBOARD_KEY_STATE_RELEASED)
+ return;
+
+ xkb_keysym_to_utf8(key, text, sizeof(text));
+
+ text_entry_insert_at_cursor(entry, text, 0, 0);
+
+ return;
+ }
}
static void
@@ -1208,6 +1263,22 @@ key_handler(struct window *window,
widget_schedule_redraw(entry->widget);
}
break;
+ case XKB_KEY_Up:
+ text_entry_commit_and_reset(entry);
+
+ move_up(entry->text, &entry->cursor);
+ if (!(input_get_modifiers(input) & MOD_SHIFT_MASK))
+ entry->anchor = entry->cursor;
+ widget_schedule_redraw(entry->widget);
+ break;
+ case XKB_KEY_Down:
+ text_entry_commit_and_reset(entry);
+
+ move_down(entry->text, &entry->cursor);
+ if (!(input_get_modifiers(input) & MOD_SHIFT_MASK))
+ entry->anchor = entry->cursor;
+ widget_schedule_redraw(entry->widget);
+ break;
case XKB_KEY_Escape:
break;
default:
diff --git a/clients/keyboard.c b/clients/keyboard.c
index 11fe21d4..cd1ad586 100644
--- a/clients/keyboard.c
+++ b/clients/keyboard.c
@@ -75,7 +75,8 @@ struct key {
enum key_type key_type;
char *label;
- char *alt;
+ char *uppercase;
+ char *symbol;
unsigned int width;
};
@@ -92,120 +93,119 @@ struct layout {
};
static const struct key normal_keys[] = {
- { keytype_default, "q", "Q", 1},
- { keytype_default, "w", "W", 1},
- { keytype_default, "e", "E", 1},
- { keytype_default, "r", "R", 1},
- { keytype_default, "t", "T", 1},
- { keytype_default, "y", "Y", 1},
- { keytype_default, "u", "U", 1},
- { keytype_default, "i", "I", 1},
- { keytype_default, "o", "O", 1},
- { keytype_default, "p", "P", 1},
- { keytype_backspace, "<--", "<--", 2},
-
- { keytype_tab, "->|", "->|", 1},
- { keytype_default, "a", "A", 1},
- { keytype_default, "s", "S", 1},
- { keytype_default, "d", "D", 1},
- { keytype_default, "f", "F", 1},
- { keytype_default, "g", "G", 1},
- { keytype_default, "h", "H", 1},
- { keytype_default, "j", "J", 1},
- { keytype_default, "k", "K", 1},
- { keytype_default, "l", "L", 1},
- { keytype_enter, "Enter", "Enter", 2},
-
- { keytype_switch, "ABC", "abc", 2},
- { keytype_default, "z", "Z", 1},
- { keytype_default, "x", "X", 1},
- { keytype_default, "c", "C", 1},
- { keytype_default, "v", "V", 1},
- { keytype_default, "b", "B", 1},
- { keytype_default, "n", "N", 1},
- { keytype_default, "m", "M", 1},
- { keytype_default, ",", ",", 1},
- { keytype_default, ".", ".", 1},
- { keytype_switch, "ABC", "abc", 1},
-
- { keytype_symbols, "?123", "?123", 1},
- { keytype_space, "", "", 5},
- { keytype_arrow_up, "/\\", "/\\", 1},
- { keytype_arrow_left, "<", "<", 1},
- { keytype_arrow_right, ">", ">", 1},
- { keytype_arrow_down, "\\/", "\\/", 1},
- { keytype_style, "", "", 2}
+ { keytype_default, "q", "Q", "1", 1},
+ { keytype_default, "w", "W", "2", 1},
+ { keytype_default, "e", "E", "3", 1},
+ { keytype_default, "r", "R", "4", 1},
+ { keytype_default, "t", "T", "5", 1},
+ { keytype_default, "y", "Y", "6", 1},
+ { keytype_default, "u", "U", "7", 1},
+ { keytype_default, "i", "I", "8", 1},
+ { keytype_default, "o", "O", "9", 1},
+ { keytype_default, "p", "P", "0", 1},
+ { keytype_backspace, "<--", "<--", "<--", 2},
+
+ { keytype_tab, "->|", "->|", "->|", 1},
+ { keytype_default, "a", "A", "-", 1},
+ { keytype_default, "s", "S", "@", 1},
+ { keytype_default, "d", "D", "*", 1},
+ { keytype_default, "f", "F", "^", 1},
+ { keytype_default, "g", "G", ":", 1},
+ { keytype_default, "h", "H", ";", 1},
+ { keytype_default, "j", "J", "(", 1},
+ { keytype_default, "k", "K", ")", 1},
+ { keytype_default, "l", "L", "~", 1},
+ { keytype_enter, "Enter", "Enter", "Enter", 2},
+
+ { keytype_switch, "ABC", "abc", "ABC", 2},
+ { keytype_default, "z", "Z", "/", 1},
+ { keytype_default, "x", "X", "\'", 1},
+ { keytype_default, "c", "C", "\"", 1},
+ { keytype_default, "v", "V", "+", 1},
+ { keytype_default, "b", "B", "=", 1},
+ { keytype_default, "n", "N", "?", 1},
+ { keytype_default, "m", "M", "!", 1},
+ { keytype_default, ",", ",", "\\", 1},
+ { keytype_default, ".", ".", "|", 1},
+ { keytype_switch, "ABC", "abc", "ABC", 1},
+
+ { keytype_symbols, "?123", "?123", "abc", 1},
+ { keytype_space, "", "", "", 5},
+ { keytype_arrow_up, "/\\", "/\\", "/\\", 1},
+ { keytype_arrow_left, "<", "<", "<", 1},
+ { keytype_arrow_right, ">", ">", ">", 1},
+ { keytype_arrow_down, "\\/", "\\/", "\\/", 1},
+ { keytype_style, "", "", "", 2}
};
static const struct key numeric_keys[] = {
- { keytype_default, "1", "1", 1},
- { keytype_default, "2", "2", 1},
- { keytype_default, "3", "3", 1},
- { keytype_default, "4", "4", 1},
- { keytype_default, "5", "5", 1},
- { keytype_default, "6", "6", 1},
- { keytype_default, "7", "7", 1},
- { keytype_default, "8", "8", 1},
- { keytype_default, "9", "9", 1},
- { keytype_default, "0", "0", 1},
- { keytype_backspace, "<--", "<--", 2},
-
- { keytype_space, "", "", 4},
- { keytype_enter, "Enter", "Enter", 2},
- { keytype_arrow_up, "/\\", "/\\", 1},
- { keytype_arrow_left, "<", "<", 1},
- { keytype_arrow_right, ">", ">", 1},
- { keytype_arrow_down, "\\/", "\\/", 1},
- { keytype_style, "", "", 2}
+ { keytype_default, "1", "1", "1", 1},
+ { keytype_default, "2", "2", "2", 1},
+ { keytype_default, "3", "3", "3", 1},
+ { keytype_default, "4", "4", "4", 1},
+ { keytype_default, "5", "5", "5", 1},
+ { keytype_default, "6", "6", "6", 1},
+ { keytype_default, "7", "7", "7", 1},
+ { keytype_default, "8", "8", "8", 1},
+ { keytype_default, "9", "9", "9", 1},
+ { keytype_default, "0", "0", "0", 1},
+ { keytype_backspace, "<--", "<--", "<--", 2},
+
+ { keytype_space, "", "", "", 4},
+ { keytype_enter, "Enter", "Enter", "Enter", 2},
+ { keytype_arrow_up, "/\\", "/\\", "/\\", 1},
+ { keytype_arrow_left, "<", "<", "<", 1},
+ { keytype_arrow_right, ">", ">", ">", 1},
+ { keytype_arrow_down, "\\/", "\\/", "\\/", 1},
+ { keytype_style, "", "", "", 2}
};
static const struct key arabic_keys[] = {
- { keytype_default, "ض", "ض", 1},
- { keytype_default, "ص", "ص", 1},
- { keytype_default, "ث", "ث", 1},
- { keytype_default, "ق", "ق", 1},
- { keytype_default, "ف", "ف", 1},
- { keytype_default, "غ", "إ", 1},
- { keytype_default, "ع", "ع", 1},
- { keytype_default, "ه", "ه", 1},
- { keytype_default, "خ", "خ", 1},
- { keytype_default, "ح", "ح", 1},
- { keytype_default, "ج", "ج", 1},
- { keytype_backspace, "-->", "-->", 2},
-
- { keytype_tab, "->|", "->|", 1},
- { keytype_default, "ش", "ش", 1},
- { keytype_default, "س", "س", 1},
- { keytype_default, "ي", "ي", 1},
- { keytype_default, "ب", "ب", 1},
- { keytype_default, "ل", "ل", 1},
- { keytype_default, "ا", "أ", 1},
- { keytype_default, "ت", "ت", 1},
- { keytype_default, "ن", "ن", 1},
- { keytype_default, "م", "م", 1},
- { keytype_default, "ك", "ك", 1},
- { keytype_default, "د", "د", 1},
- { keytype_enter, "Enter", "Enter", 2},
-
- { keytype_switch, "ABC", "abc", 2},
- { keytype_default, "ئ", "ئ", 1},
- { keytype_default, "ء", "ء", 1},
- { keytype_default, "ؤ", "ؤ", 1},
- { keytype_default, "ر", "ر", 1},
- { keytype_default, "ى", "آ", 1},
- { keytype_default, "ة", "ة", 1},
- { keytype_default, "و", "و", 1},
- { keytype_default, "ز", "ز", 1},
- { keytype_default, "ظ", "ظ", 1},
- { keytype_switch, "ABC", "abc", 2},
-
- { keytype_symbols, "؟٣٢١", "؟٣٢١", 1},
- { keytype_default, "ذ", "ذ", 1},
- { keytype_default, "،", "،", 1},
- { keytype_space, "", "", 6},
- { keytype_default, ".", ".", 1},
- { keytype_default, "ط", "ط", 1},
- { keytype_style, "", "", 2}
+ { keytype_default, "ض", "ﹶ", "۱", 1},
+ { keytype_default, "ص", "ﹰ", "۲", 1},
+ { keytype_default, "ث", "ﹸ", "۳", 1},
+ { keytype_default, "ق", "ﹲ", "۴", 1},
+ { keytype_default, "ف", "ﻹ", "۵", 1},
+ { keytype_default, "غ", "ﺇ", "۶", 1},
+ { keytype_default, "ع", "`", "۷", 1},
+ { keytype_default, "ه", "٪", "۸", 1},
+ { keytype_default, "خ", ">", "۹", 1},
+ { keytype_default, "ح", "<", "۰", 1},
+ { keytype_backspace, "-->", "-->", "-->", 2},
+
+ { keytype_tab, "->|", "->|", "->|", 1},
+ { keytype_default, "ش", "ﹺ", "ﹼ", 1},
+ { keytype_default, "س", "ﹴ", "!", 1},
+ { keytype_default, "ي", "[", "@", 1},
+ { keytype_default, "ب", "]", "#", 1},
+ { keytype_default, "ل", "ﻷ", "$", 1},
+ { keytype_default, "ا", "أ", "%", 1},
+ { keytype_default, "ت", "-", "^", 1},
+ { keytype_default, "ن", "x", "&", 1},
+ { keytype_default, "م", "/", "*", 1},
+ { keytype_default, "ك", ":", "_", 1},
+ { keytype_default, "د", "\"", "+", 1},
+ { keytype_enter, "Enter", "Enter", "Enter", 2},
+
+ { keytype_switch, "Shift", "Base", "Shift", 2},
+ { keytype_default, "ئ", "~", ")", 1},
+ { keytype_default, "ء", "°", "(", 1},
+ { keytype_default, "ؤ", "{", "\"", 1},
+ { keytype_default, "ر", "}", "\'", 1},
+ { keytype_default, "ى", "ﺁ", "؟", 1},
+ { keytype_default, "ة", "'", "!", 1},
+ { keytype_default, "و", ",", ";", 1},
+ { keytype_default, "ﺯ", ".", "\\", 1},
+ { keytype_default, "ظ", "؟", "=", 1},
+ { keytype_switch, "Shift", "Base", "Shift", 2},
+
+ { keytype_symbols, "؟٣٢١", "؟٣٢١", "Base", 1},
+ { keytype_default, "ﻻ", "ﻵ", "|", 1},
+ { keytype_default, ",", "،", "،", 1},
+ { keytype_space, "", "", "", 6},
+ { keytype_default, ".", "ذ", "]", 1},
+ { keytype_default, "ط", "ﺝ", "[", 1},
+ { keytype_style, "", "", "", 2}
};
@@ -251,8 +251,9 @@ static const double key_width = 60;
static const double key_height = 50;
enum keyboard_state {
- keyboardstate_default,
- keyboardstate_uppercase
+ KEYBOARD_STATE_DEFAULT,
+ KEYBOARD_STATE_UPPERCASE,
+ KEYBOARD_STATE_SYMBOLS
};
struct keyboard {
@@ -283,10 +284,16 @@ label_from_key(struct keyboard *keyboard,
if (key->key_type == keytype_style)
return style_labels[keyboard->keyboard->preedit_style];
- if (keyboard->state == keyboardstate_default)
+ switch(keyboard->state) {
+ case KEYBOARD_STATE_DEFAULT:
return key->label;
- else
- return key->alt;
+ case KEYBOARD_STATE_UPPERCASE:
+ return key->uppercase;
+ case KEYBOARD_STATE_SYMBOLS:
+ return key->symbol;
+ }
+
+ return "";
}
static void
@@ -523,8 +530,21 @@ append(char *s1, const char *s2)
static void
keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *key, struct input *input, enum wl_pointer_button_state state)
{
- const char *label = keyboard->state == keyboardstate_default ? key->label : key->alt;
- xkb_mod_mask_t mod_mask = keyboard->state == keyboardstate_default ? 0 : keyboard->keyboard->keysym.shift_mask;
+ const char *label;
+
+ switch(keyboard->state) {
+ case KEYBOARD_STATE_DEFAULT :
+ label = key->label;
+ break;
+ case KEYBOARD_STATE_UPPERCASE :
+ label = key->uppercase;
+ break;
+ case KEYBOARD_STATE_SYMBOLS :
+ label = key->symbol;
+ break;
+ }
+
+ xkb_mod_mask_t mod_mask = keyboard->state == KEYBOARD_STATE_DEFAULT ? 0 : keyboard->keyboard->keysym.shift_mask;
uint32_t key_state = (state == WL_POINTER_BUTTON_STATE_PRESSED) ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED;
switch (key->key_type) {
@@ -565,14 +585,32 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
case keytype_switch:
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
break;
- if (keyboard->state == keyboardstate_default)
- keyboard->state = keyboardstate_uppercase;
- else
- keyboard->state = keyboardstate_default;
+ switch(keyboard->state) {
+ case KEYBOARD_STATE_DEFAULT:
+ keyboard->state = KEYBOARD_STATE_UPPERCASE;
+ break;
+ case KEYBOARD_STATE_UPPERCASE:
+ keyboard->state = KEYBOARD_STATE_DEFAULT;
+ break;
+ case KEYBOARD_STATE_SYMBOLS:
+ keyboard->state = KEYBOARD_STATE_UPPERCASE;
+ break;
+ }
break;
case keytype_symbols:
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
break;
+ switch(keyboard->state) {
+ case KEYBOARD_STATE_DEFAULT:
+ keyboard->state = KEYBOARD_STATE_SYMBOLS;
+ break;
+ case KEYBOARD_STATE_UPPERCASE:
+ keyboard->state = KEYBOARD_STATE_SYMBOLS;
+ break;
+ case KEYBOARD_STATE_SYMBOLS:
+ keyboard->state = KEYBOARD_STATE_DEFAULT;
+ break;
+ }
break;
case keytype_tab:
virtual_keyboard_commit_preedit(keyboard->keyboard);
@@ -823,7 +861,7 @@ input_method_activate(void *data,
struct wl_array modifiers_map;
const struct layout *layout;
- keyboard->keyboard->state = keyboardstate_default;
+ keyboard->keyboard->state = KEYBOARD_STATE_DEFAULT;
if (keyboard->context)
wl_input_method_context_destroy(keyboard->context);
diff --git a/clients/terminal.c b/clients/terminal.c
index beec877f..924549e1 100644
--- a/clients/terminal.c
+++ b/clients/terminal.c
@@ -772,10 +772,10 @@ terminal_resize_cells(struct terminal *terminal,
} else {
terminal->max_width = width;
data_pitch = width * sizeof(union utf8_char);
- data = zalloc(data_pitch * terminal->buffer_height);
+ data = xzalloc(data_pitch * terminal->buffer_height);
attr_pitch = width * sizeof(struct attr);
- data_attr = malloc(attr_pitch * terminal->buffer_height);
- tab_ruler = zalloc(width);
+ data_attr = xmalloc(attr_pitch * terminal->buffer_height);
+ tab_ruler = xzalloc(width);
attr_init(data_attr, terminal->curr_attr,
width * terminal->buffer_height);
@@ -1094,6 +1094,12 @@ redraw_handler(struct widget *widget, void *data)
cairo_stroke(cr);
}
+ /* skip space glyph (RLE) we use as a placeholder of
+ the right half of a double-width character,
+ because RLE is not available in every font. */
+ if (p_row[col].ch == 0x200B)
+ continue;
+
glyph_run_add(&run, text_x, text_y, &p_row[col]);
}
}
diff --git a/clients/weston-info.c b/clients/weston-info.c
index 147dc489..df869e3b 100644
--- a/clients/weston-info.c
+++ b/clients/weston-info.c
@@ -225,7 +225,7 @@ print_output_info(void *data)
output->geometry.physical_height);
printf("\tmake: '%s', model: '%s',\n",
output->geometry.make, output->geometry.model);
- printf("\tsubpixel_orientation: %s, output_tranform: %s,\n",
+ printf("\tsubpixel_orientation: %s, output_transform: %s,\n",
subpixel_orientation, transform);
wl_list_for_each(mode, &output->modes, link) {
diff --git a/clients/window.c b/clients/window.c
index e770a040..f12ce396 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -2558,6 +2558,8 @@ input_grab(struct input *input, struct widget *widget, uint32_t button)
{
input->grab = widget;
input->grab_button = button;
+
+ input_set_focus_widget(input, widget, input->sx, input->sy);
}
void
@@ -2874,6 +2876,14 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
if (!window || !input->xkb.state)
return;
+ /* We only use input grabs for pointer events for now, so just
+ * ignore key presses if a grab is active. We expand the key
+ * event delivery mechanism to route events to widgets to
+ * properly handle key grabs. In the meantime, this prevents
+ * key event devlivery while a grab is active. */
+ if (input->grab && input->grab_button == 0)
+ return;
+
num_syms = xkb_key_get_syms(input->xkb.state, code, &syms);
sym = XKB_KEY_NoSymbol;
@@ -2969,9 +2979,12 @@ touch_handle_down(void *data, struct wl_touch *wl_touch,
return;
}
- widget = window_find_widget(input->touch_focus,
- wl_fixed_to_double(x_w),
- wl_fixed_to_double(y_w));
+ if (input->grab)
+ widget = input->grab;
+ else
+ widget = window_find_widget(input->touch_focus,
+ wl_fixed_to_double(x_w),
+ wl_fixed_to_double(y_w));
if (widget) {
struct touch_point *tp = xmalloc(sizeof *tp);
if (tp) {
@@ -3065,9 +3078,6 @@ touch_handle_frame(void *data, struct wl_touch *wl_touch)
if (tp->widget->touch_frame_handler)
(*tp->widget->touch_frame_handler)(tp->widget, input,
tp->widget->user_data);
-
- wl_list_remove(&tp->link);
- free(tp);
}
}
@@ -4341,6 +4351,17 @@ surface_create(struct window *window)
return surface;
}
+static enum window_buffer_type
+get_preferred_buffer_type(struct display *display)
+{
+#ifdef HAVE_CAIRO_EGL
+ if (display->argb_device && !getenv("TOYTOOLKIT_NO_EGL"))
+ return WINDOW_BUFFER_TYPE_EGL_WINDOW;
+#endif
+
+ return WINDOW_BUFFER_TYPE_SHM;
+}
+
static struct window *
window_create_internal(struct display *display, int custom)
{
@@ -4359,14 +4380,7 @@ window_create_internal(struct display *display, int custom)
window->custom = custom;
window->preferred_format = WINDOW_PREFERRED_FORMAT_NONE;
- if (display->argb_device)
-#ifdef HAVE_CAIRO_EGL
- surface->buffer_type = WINDOW_BUFFER_TYPE_EGL_WINDOW;
-#else
- surface->buffer_type = WINDOW_BUFFER_TYPE_SHM;
-#endif
- else
- surface->buffer_type = WINDOW_BUFFER_TYPE_SHM;
+ surface->buffer_type = get_preferred_buffer_type(display);
wl_surface_set_user_data(surface->surface, window);
wl_list_insert(display->window_list.prev, &window->link);
@@ -4487,6 +4501,20 @@ menu_button_handler(struct widget *widget,
}
static void
+menu_touch_up_handler(struct widget *widget,
+ struct input *input,
+ uint32_t serial,
+ uint32_t time,
+ int32_t id,
+ void *data)
+{
+ struct menu *menu = data;
+
+ input_ungrab(input);
+ menu_destroy(menu);
+}
+
+static void
menu_redraw_handler(struct widget *widget, void *data)
{
cairo_t *cr;
@@ -4585,6 +4613,7 @@ window_show_menu(struct display *display,
widget_set_leave_handler(menu->widget, menu_leave_handler);
widget_set_motion_handler(menu->widget, menu_motion_handler);
widget_set_button_handler(menu->widget, menu_button_handler);
+ widget_set_touch_up_handler(menu->widget, menu_touch_up_handler);
input_grab(input, menu->widget, 0);
frame_resize_inside(menu->frame, 200, count * 20);
diff --git a/configure.ac b/configure.ac
index 4cfab8b2..0252faef 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], [91])
+m4_define([weston_micro_version], [92])
m4_define([weston_version],
[weston_major_version.weston_minor_version.weston_micro_version])
diff --git a/desktop-shell/exposay.c b/desktop-shell/exposay.c
index 9c649e77..1d8b40e1 100644
--- a/desktop-shell/exposay.c
+++ b/desktop-shell/exposay.c
@@ -160,7 +160,7 @@ exposay_highlight_surface(struct desktop_shell *shell,
shell->exposay.column_current = esurface->column;
shell->exposay.cur_output = esurface->eoutput;
- activate(shell, view->surface, shell->exposay.seat);
+ activate(shell, view->surface, shell->exposay.seat, false);
shell->exposay.focus_current = view;
}
@@ -318,8 +318,6 @@ exposay_layout(struct desktop_shell *shell, struct shell_output *shell_output)
if (shell->exposay.focus_current == esurface->view)
highlight = esurface;
- set_alpha_if_fullscreen(get_shell_surface(view->surface));
-
exposay_animate_in(esurface);
i++;
@@ -538,10 +536,10 @@ exposay_transition_inactive(struct desktop_shell *shell, int switch_focus)
* to the new. */
if (switch_focus && shell->exposay.focus_current)
activate(shell, shell->exposay.focus_current->surface,
- shell->exposay.seat);
+ shell->exposay.seat, true);
else if (shell->exposay.focus_prev)
activate(shell, shell->exposay.focus_prev->surface,
- shell->exposay.seat);
+ shell->exposay.seat, true);
wl_list_for_each(esurface, &shell->exposay.surface_list, link)
exposay_animate_out(esurface);
diff --git a/desktop-shell/input-panel.c b/desktop-shell/input-panel.c
index 12fe686f..7623f6cb 100644
--- a/desktop-shell/input-panel.c
+++ b/desktop-shell/input-panel.c
@@ -43,11 +43,54 @@ struct input_panel_surface {
struct weston_view *view;
struct wl_listener surface_destroy_listener;
+ struct weston_view_animation *anim;
+
struct weston_output *output;
uint32_t panel;
};
static void
+input_panel_slide_done(struct weston_view_animation *animation, void *data)
+{
+ struct input_panel_surface *ipsurf = data;
+
+ ipsurf->anim = NULL;
+}
+
+static void
+show_input_panel_surface(struct input_panel_surface *ipsurf)
+{
+ struct desktop_shell *shell = ipsurf->shell;
+ struct weston_seat *seat;
+ struct weston_surface *focus;
+ float x, y;
+
+ wl_list_for_each(seat, &shell->compositor->seat_list, link) {
+ if (!seat->keyboard)
+ continue;
+ focus = weston_surface_get_main_surface(seat->keyboard->focus);
+ ipsurf->output = focus->output;
+ x = ipsurf->output->x + (ipsurf->output->width - ipsurf->surface->width) / 2;
+ y = ipsurf->output->y + ipsurf->output->height - ipsurf->surface->height;
+ weston_view_set_position(ipsurf->view, x, y);
+ }
+
+ wl_list_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);
+
+ if (ipsurf->anim)
+ weston_view_animation_destroy(ipsurf->anim);
+
+ ipsurf->anim =
+ weston_slide_run(ipsurf->view,
+ ipsurf->surface->height * 0.9, 0,
+ input_panel_slide_done, ipsurf);
+}
+
+static void
show_input_panels(struct wl_listener *listener, void *data)
{
struct desktop_shell *shell =
@@ -70,13 +113,8 @@ show_input_panels(struct wl_listener *listener, void *data)
&shell->input_panel.surfaces, link) {
if (ipsurf->surface->width == 0)
continue;
- wl_list_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);
- weston_slide_run(ipsurf->view, ipsurf->surface->height * 0.9,
- 0, NULL, NULL);
+
+ show_input_panel_surface(ipsurf);
}
}
@@ -135,13 +173,8 @@ input_panel_configure(struct weston_surface *surface, int32_t sx, int32_t sy)
weston_view_set_position(ip_surface->view, x, y);
- if (!weston_surface_is_mapped(surface) && shell->showing_input_panels) {
- wl_list_insert(&shell->input_panel_layer.view_list,
- &ip_surface->view->layer_link);
- weston_view_update_transform(ip_surface->view);
- weston_surface_damage(surface);
- weston_slide_run(ip_surface->view, ip_surface->view->surface->height * 0.9, 0, NULL, NULL);
- }
+ if (!weston_surface_is_mapped(surface) && shell->showing_input_panels)
+ show_input_panel_surface(ip_surface);
}
static void
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 466ea937..00922352 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -63,6 +63,8 @@ enum shell_surface_type {
SHELL_SURFACE_XWAYLAND
};
+struct shell_client;
+
/*
* Surface stacking and ordering.
*
@@ -104,6 +106,7 @@ enum shell_surface_type {
struct shell_surface {
struct wl_resource *resource;
struct wl_signal destroy_signal;
+ struct shell_client *owner;
struct weston_surface *surface;
struct weston_view *view;
@@ -163,10 +166,15 @@ struct shell_surface {
bool maximized;
bool fullscreen;
bool relative;
+ bool lowered;
} state, next_state, requested_state; /* surface states */
bool state_changed;
bool state_requested;
+ struct {
+ int left, right, top, bottom;
+ } margin;
+
int focus_count;
};
@@ -186,6 +194,7 @@ struct shell_touch_grab {
struct weston_move_grab {
struct shell_grab base;
wl_fixed_t dx, dy;
+ int client_initiated;
};
struct weston_touch_move_grab {
@@ -208,6 +217,10 @@ struct shell_seat {
struct wl_listener seat_destroy_listener;
struct weston_surface *focused_surface;
+ struct wl_listener caps_changed_listener;
+ struct wl_listener pointer_focus_listener;
+ struct wl_listener keyboard_focus_listener;
+
struct {
struct weston_pointer_grab grab;
struct wl_list surfaces_list;
@@ -226,16 +239,6 @@ struct shell_client {
int unresponsive;
};
-void
-set_alpha_if_fullscreen(struct shell_surface *shsurf)
-{
- if (shsurf && shsurf->state.fullscreen)
- shsurf->fullscreen.black_view->alpha = 0.25;
-}
-
-static struct shell_client *
-get_shell_client(struct wl_client *client);
-
static struct desktop_shell *
shell_surface_get_shell(struct shell_surface *shsurf);
@@ -248,6 +251,10 @@ shell_fade_startup(struct desktop_shell *shell);
static struct shell_seat *
get_shell_seat(struct weston_seat *seat);
+static int
+get_output_panel_height(struct desktop_shell *shell,
+ struct weston_output *output);
+
static void
shell_surface_update_child_surface_layers(struct shell_surface *shsurf);
@@ -364,6 +371,9 @@ shell_touch_grab_start(struct shell_touch_grab *grab,
{
struct desktop_shell *shell = shsurf->shell;
+ if (touch->seat->pointer)
+ popup_grab_end(touch->seat->pointer);
+
grab->grab.interface = interface;
grab->shsurf = shsurf;
grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
@@ -618,7 +628,7 @@ focus_state_surface_destroy(struct wl_listener *listener, void *data)
shell = state->seat->compositor->shell_interface.shell;
if (next) {
state->keyboard_focus = NULL;
- activate(shell, next, state->seat);
+ activate(shell, next, state->seat, true);
} else {
if (shell->focus_animation_type == ANIMATION_DIM_LAYER) {
if (state->ws->focus_animation)
@@ -694,8 +704,20 @@ restore_focus_state(struct desktop_shell *shell, struct workspace *ws)
{
struct focus_state *state, *next;
struct weston_surface *surface;
+ struct wl_list pending_seat_list;
+ struct weston_seat *seat, *next_seat;
+
+ /* Temporarily steal the list of seats so that we can keep
+ * track of the seats we've already processed */
+ wl_list_init(&pending_seat_list);
+ wl_list_insert_list(&pending_seat_list, &shell->compositor->seat_list);
+ wl_list_init(&shell->compositor->seat_list);
wl_list_for_each_safe(state, next, &ws->focus_list, link) {
+ wl_list_remove(&state->seat->link);
+ wl_list_insert(&shell->compositor->seat_list,
+ &state->seat->link);
+
if (state->seat->keyboard == NULL)
continue;
@@ -703,6 +725,17 @@ restore_focus_state(struct desktop_shell *shell, struct workspace *ws)
weston_keyboard_set_focus(state->seat->keyboard, surface);
}
+
+ /* For any remaining seats that we don't have a focus state
+ * for we'll reset the keyboard focus to NULL */
+ wl_list_for_each_safe(seat, next_seat, &pending_seat_list, link) {
+ wl_list_insert(&shell->compositor->seat_list, &seat->link);
+
+ if (state->seat->keyboard == NULL)
+ continue;
+
+ weston_keyboard_set_focus(seat->keyboard, NULL);
+ }
}
static void
@@ -1380,6 +1413,11 @@ touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
}
static void
+touch_move_grab_frame(struct weston_touch_grab *grab)
+{
+}
+
+static void
touch_move_grab_cancel(struct weston_touch_grab *grab)
{
struct weston_touch_move_grab *move =
@@ -1394,6 +1432,7 @@ static const struct weston_touch_grab_interface touch_move_grab_interface = {
touch_move_grab_down,
touch_move_grab_up,
touch_move_grab_motion,
+ touch_move_grab_frame,
touch_move_grab_cancel,
};
@@ -1407,8 +1446,6 @@ surface_touch_move(struct shell_surface *shsurf, struct weston_seat *seat)
if (shsurf->state.fullscreen)
return 0;
- if (shsurf->grabbed)
- return 0;
move = malloc(sizeof *move);
if (!move)
@@ -1432,22 +1469,47 @@ noop_grab_focus(struct weston_pointer_grab *grab)
}
static void
+constrain_position(struct weston_move_grab *move, int *cx, int *cy)
+{
+ struct shell_surface *shsurf = move->base.shsurf;
+ struct weston_pointer *pointer = move->base.grab.pointer;
+ int x, y, panel_height, bottom;
+ const int safety = 50;
+
+ x = wl_fixed_to_int(pointer->x + move->dx);
+ y = wl_fixed_to_int(pointer->y + move->dy);
+
+ panel_height = get_output_panel_height(shsurf->shell,
+ shsurf->surface->output);
+ bottom = y + shsurf->surface->height - shsurf->margin.bottom;
+ if (bottom - panel_height < safety)
+ y = panel_height + safety -
+ shsurf->surface->height + shsurf->margin.bottom;
+
+ if (move->client_initiated &&
+ y + shsurf->margin.top < panel_height)
+ y = panel_height - shsurf->margin.top;
+
+ *cx = x;
+ *cy = y;
+}
+
+static void
move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
wl_fixed_t x, wl_fixed_t y)
{
struct weston_move_grab *move = (struct weston_move_grab *) grab;
struct weston_pointer *pointer = grab->pointer;
struct shell_surface *shsurf = move->base.shsurf;
- int dx, dy;
+ int cx, cy;
weston_pointer_move(pointer, x, y);
- dx = wl_fixed_to_int(pointer->x + move->dx);
- dy = wl_fixed_to_int(pointer->y + move->dy);
-
if (!shsurf)
return;
- weston_view_set_position(shsurf->view, dx, dy);
+ constrain_position(move, &cx, &cy);
+
+ weston_view_set_position(shsurf->view, cx, cy);
weston_compositor_schedule_repaint(shsurf->surface->compositor);
}
@@ -1486,16 +1548,16 @@ static const struct weston_pointer_grab_interface move_grab_interface = {
};
static int
-surface_move(struct shell_surface *shsurf, struct weston_seat *seat)
+surface_move(struct shell_surface *shsurf, struct weston_seat *seat,
+ int client_initiated)
{
struct weston_move_grab *move;
if (!shsurf)
return -1;
- if (shsurf->grabbed)
- return 0;
- if (shsurf->state.fullscreen || shsurf->state.maximized)
+ if (shsurf->grabbed ||
+ shsurf->state.fullscreen || shsurf->state.maximized)
return 0;
move = malloc(sizeof *move);
@@ -1506,6 +1568,7 @@ surface_move(struct shell_surface *shsurf, struct weston_seat *seat)
seat->pointer->grab_x;
move->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
seat->pointer->grab_y;
+ move->client_initiated = client_initiated;
shell_grab_start(&move->base, &move_grab_interface, shsurf,
seat->pointer, DESKTOP_SHELL_CURSOR_MOVE);
@@ -1527,7 +1590,7 @@ common_surface_move(struct wl_resource *resource,
seat->pointer->grab_serial == serial) {
surface = weston_surface_get_main_surface(seat->pointer->focus->surface);
if ((surface == shsurf->surface) &&
- (surface_move(shsurf, seat) < 0))
+ (surface_move(shsurf, seat, 1) < 0))
wl_resource_post_no_memory(resource);
} else if (seat->touch &&
seat->touch->focus &&
@@ -1588,20 +1651,20 @@ resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
height += wl_fixed_to_int(to_y - from_y);
}
- shsurf->client->send_configure(shsurf->surface,
- resize->edges, width, height);
+ shsurf->client->send_configure(shsurf->surface, width, height);
}
static void
-send_configure(struct weston_surface *surface,
- uint32_t edges, int32_t width, int32_t height)
+send_configure(struct weston_surface *surface, int32_t width, int32_t height)
{
struct shell_surface *shsurf = get_shell_surface(surface);
assert(shsurf);
- wl_shell_surface_send_configure(shsurf->resource,
- edges, width, height);
+ if (shsurf->resource)
+ wl_shell_surface_send_configure(shsurf->resource,
+ shsurf->resize_edges,
+ width, height);
}
static const struct weston_shell_client shell_client = {
@@ -1680,7 +1743,8 @@ surface_resize(struct shell_surface *shsurf,
{
struct weston_resize_grab *resize;
- if (shsurf->state.fullscreen || shsurf->state.maximized)
+ if (shsurf->grabbed ||
+ shsurf->state.fullscreen || shsurf->state.maximized)
return 0;
if (edges == 0 || edges > 15 ||
@@ -1711,9 +1775,6 @@ common_surface_resize(struct wl_resource *resource,
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
struct weston_surface *surface;
- if (shsurf->state.fullscreen)
- return;
-
if (seat->pointer->button_count == 0 ||
seat->pointer->grab_serial != serial ||
seat->pointer->focus == NULL)
@@ -1769,10 +1830,10 @@ busy_cursor_grab_button(struct weston_pointer_grab *base,
struct weston_seat *seat = grab->grab.pointer->seat;
if (shsurf && button == BTN_LEFT && state) {
- activate(shsurf->shell, shsurf->surface, seat);
- surface_move(shsurf, seat);
+ activate(shsurf->shell, shsurf->surface, seat, true);
+ surface_move(shsurf, seat, 0);
} else if (shsurf && button == BTN_RIGHT && state) {
- activate(shsurf->shell, shsurf->surface, seat);
+ activate(shsurf->shell, shsurf->surface, seat, true);
surface_rotate(shsurf, seat);
}
}
@@ -1807,6 +1868,9 @@ set_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer)
shell_grab_start(grab, &busy_cursor_grab_interface, shsurf, pointer,
DESKTOP_SHELL_CURSOR_BUSY);
+ /* Mark the shsurf as ungrabbed so that button binding is able
+ * to move it. */
+ shsurf->grabbed = 0;
}
static void
@@ -1859,12 +1923,10 @@ static void
handle_xdg_ping(struct shell_surface *shsurf, uint32_t serial)
{
struct weston_compositor *compositor = shsurf->shell->compositor;
- struct wl_client *client = wl_resource_get_client(shsurf->resource);
- struct shell_client *sc;
+ struct shell_client *sc = shsurf->owner;
struct wl_event_loop *loop;
static const int ping_timeout = 200;
- sc = get_shell_client(client);
if (sc->unresponsive) {
xdg_ping_timeout_handler(sc);
return;
@@ -1920,19 +1982,6 @@ handle_pointer_focus(struct wl_listener *listener, void *data)
}
static void
-create_pointer_focus_listener(struct weston_seat *seat)
-{
- struct wl_listener *listener;
-
- if (!seat->pointer)
- return;
-
- listener = malloc(sizeof *listener);
- listener->notify = handle_pointer_focus;
- wl_signal_add(&seat->pointer->focus_signal, listener);
-}
-
-static void
shell_surface_lose_keyboard_focus(struct shell_surface *shsurf)
{
if (--shsurf->focus_count == 0)
@@ -1970,32 +2019,6 @@ handle_keyboard_focus(struct wl_listener *listener, void *data)
}
static void
-create_keyboard_focus_listener(struct weston_seat *seat)
-{
- struct wl_listener *listener;
-
- if (!seat->keyboard)
- return;
-
- listener = malloc(sizeof *listener);
- listener->notify = handle_keyboard_focus;
- wl_signal_add(&seat->keyboard->focus_signal, listener);
-}
-
-static struct shell_client *
-get_shell_client(struct wl_client *client)
-{
- struct wl_listener *listener;
-
- listener = wl_client_get_destroy_listener(client,
- handle_shell_client_destroy);
- if (listener == NULL)
- return NULL;
-
- return container_of(listener, struct shell_client, destroy_listener);
-}
-
-static void
shell_client_pong(struct shell_client *sc, uint32_t serial)
{
if (sc->ping_serial != serial)
@@ -2015,9 +2038,9 @@ static void
shell_surface_pong(struct wl_client *client,
struct wl_resource *resource, uint32_t serial)
{
- struct shell_client *sc;
+ struct shell_surface *shsurf = wl_resource_get_user_data(resource);
+ struct shell_client *sc = shsurf->owner;
- sc = get_shell_client(client);
shell_client_pong(sc, serial);
}
@@ -2029,6 +2052,16 @@ 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)
+{
+ shsurf->margin.left = left;
+ shsurf->margin.right = right;
+ shsurf->margin.top = top;
+ shsurf->margin.bottom = bottom;
+}
+
+static void
shell_surface_set_title(struct wl_client *client,
struct wl_resource *resource, const char *title)
{
@@ -2097,9 +2130,15 @@ shell_surface_calculate_layer_link (struct shell_surface *shsurf)
struct weston_view *parent;
switch (shsurf->type) {
+ case SHELL_SURFACE_XWAYLAND:
+ return &shsurf->shell->fullscreen_layer.view_list;
+
+ case SHELL_SURFACE_NONE:
+ return NULL;
+
case SHELL_SURFACE_POPUP:
case SHELL_SURFACE_TOPLEVEL:
- if (shsurf->state.fullscreen) {
+ if (shsurf->state.fullscreen && !shsurf->state.lowered) {
return &shsurf->shell->fullscreen_layer.view_list;
} else if (shsurf->parent) {
/* Move the surface to its parent layer so
@@ -2112,22 +2151,15 @@ shell_surface_calculate_layer_link (struct shell_surface *shsurf)
if (parent)
return parent->layer_link.prev;
}
- break;
-
- case SHELL_SURFACE_XWAYLAND:
- return &shsurf->shell->fullscreen_layer.view_list;
- case SHELL_SURFACE_NONE:
- default:
- /* Go to the fallback, below. */
- break;
+ /* Move the surface to a normal workspace layer so that surfaces
+ * which were previously fullscreen or transient are no longer
+ * rendered on top. */
+ ws = get_current_workspace(shsurf->shell);
+ return &ws->layer.view_list;
}
- /* Move the surface to a normal workspace layer so that surfaces
- * which were previously fullscreen or transient are no longer
- * rendered on top. */
- ws = get_current_workspace(shsurf->shell);
- return &ws->layer.view_list;
+ assert(0 && "Unknown shell surface type");
}
static void
@@ -2139,6 +2171,7 @@ shell_surface_update_child_surface_layers (struct shell_surface *shsurf)
* stacked above shsurf. */
wl_list_for_each_reverse(child, &shsurf->children_list, children_link) {
if (shsurf->view->layer_link.prev != &child->view->layer_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,
@@ -2167,6 +2200,8 @@ shell_surface_update_layer(struct shell_surface *shsurf)
new_layer_link = shell_surface_calculate_layer_link(shsurf);
+ if (new_layer_link == NULL)
+ return;
if (new_layer_link == &shsurf->view->layer_link)
return;
@@ -2293,7 +2328,7 @@ set_fullscreen(struct shell_surface *shsurf,
shsurf->type = SHELL_SURFACE_TOPLEVEL;
- shsurf->client->send_configure(shsurf->surface, 0,
+ shsurf->client->send_configure(shsurf->surface,
shsurf->output->width,
shsurf->output->height);
@@ -2313,7 +2348,6 @@ unset_fullscreen(struct shell_surface *shsurf)
shell_surface_is_top_fullscreen(shsurf)) {
restore_output_mode(shsurf->fullscreen_output);
}
- shsurf->fullscreen_output = NULL;
shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
shsurf->fullscreen.framerate = 0;
@@ -2408,15 +2442,14 @@ set_maximized(struct shell_surface *shsurf,
struct weston_output *output)
{
struct desktop_shell *shell;
- uint32_t edges = 0, panel_height = 0;
+ 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);
- edges = WL_SHELL_SURFACE_RESIZE_TOP | WL_SHELL_SURFACE_RESIZE_LEFT;
- shsurf->client->send_configure(shsurf->surface, edges,
+ shsurf->client->send_configure(shsurf->surface,
shsurf->output->width,
shsurf->output->height - panel_height);
@@ -2482,7 +2515,7 @@ set_minimized(struct weston_surface *surface, uint32_t is_true)
wl_list_for_each(seat, &shsurf->shell->compositor->seat_list, link) {
if (!seat->keyboard)
continue;
- activate(shsurf->shell, view->surface, seat);
+ activate(shsurf->shell, view->surface, seat, true);
}
}
@@ -2645,6 +2678,8 @@ shell_ensure_fullscreen_black_view(struct shell_surface *shsurf)
&shsurf->fullscreen.black_view->layer_link);
weston_view_geometry_dirty(shsurf->fullscreen.black_view);
weston_surface_damage(shsurf->surface);
+
+ shsurf->state.lowered = false;
}
/* Create black surface and append it to the associated fullscreen surface.
@@ -2661,6 +2696,10 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
if (shsurf->fullscreen.type != WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER)
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);
+
shell_ensure_fullscreen_black_view(shsurf);
surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y,
@@ -2758,6 +2797,12 @@ set_xwayland(struct shell_surface *shsurf, int x, int y, uint32_t flags)
shsurf->state_changed = true;
}
+static int
+shell_interface_move(struct shell_surface *shsurf, struct weston_seat *ws)
+{
+ return surface_move(shsurf, ws, 1);
+}
+
static const struct weston_pointer_grab_interface popup_grab_interface;
static void
@@ -2786,6 +2831,30 @@ destroy_shell_seat(struct wl_listener *listener, void *data)
free(shseat);
}
+static void
+shell_seat_caps_changed(struct wl_listener *listener, void *data)
+{
+ struct shell_seat *seat;
+
+ seat = container_of(listener, struct shell_seat, caps_changed_listener);
+
+ if (seat->seat->keyboard &&
+ wl_list_empty(&seat->keyboard_focus_listener.link)) {
+ wl_signal_add(&seat->seat->keyboard->focus_signal,
+ &seat->keyboard_focus_listener);
+ } else if (!seat->seat->keyboard) {
+ wl_list_init(&seat->keyboard_focus_listener.link);
+ }
+
+ if (seat->seat->pointer &&
+ wl_list_empty(&seat->pointer_focus_listener.link)) {
+ wl_signal_add(&seat->seat->pointer->focus_signal,
+ &seat->pointer_focus_listener);
+ } else if (!seat->seat->pointer) {
+ wl_list_init(&seat->pointer_focus_listener.link);
+ }
+}
+
static struct shell_seat *
create_shell_seat(struct weston_seat *seat)
{
@@ -2804,6 +2873,17 @@ create_shell_seat(struct weston_seat *seat)
wl_signal_add(&seat->destroy_signal,
&shseat->seat_destroy_listener);
+ shseat->keyboard_focus_listener.notify = handle_keyboard_focus;
+ wl_list_init(&shseat->keyboard_focus_listener.link);
+
+ shseat->pointer_focus_listener.notify = handle_pointer_focus;
+ wl_list_init(&shseat->pointer_focus_listener.link);
+
+ shseat->caps_changed_listener.notify = shell_seat_caps_changed;
+ wl_signal_add(&seat->updated_caps_signal,
+ &shseat->caps_changed_listener);
+ shell_seat_caps_changed(&shseat->caps_changed_listener, NULL);
+
return shseat;
}
@@ -2813,8 +2893,7 @@ get_shell_seat(struct weston_seat *seat)
struct wl_listener *listener;
listener = wl_signal_get(&seat->destroy_signal, destroy_shell_seat);
- if (listener == NULL)
- return create_shell_seat(seat);
+ assert(listener != NULL);
return container_of(listener,
struct shell_seat, seat_destroy_listener);
@@ -3064,8 +3143,8 @@ shell_handle_surface_destroy(struct wl_listener *listener, void *data)
if (shsurf->resource)
wl_resource_destroy(shsurf->resource);
- else
- destroy_shell_surface(shsurf);
+
+ destroy_shell_surface(shsurf);
}
static void
@@ -3083,15 +3162,17 @@ handle_resource_destroy(struct wl_listener *listener, void *data)
container_of(listener, struct shell_surface,
resource_destroy_listener);
+ if (!weston_surface_is_mapped(shsurf->surface))
+ return;
+
shsurf->surface->ref_count++;
pixman_region32_fini(&shsurf->surface->pending.input);
pixman_region32_init(&shsurf->surface->pending.input);
pixman_region32_fini(&shsurf->surface->input);
pixman_region32_init(&shsurf->surface->input);
- if (weston_surface_is_mapped(shsurf->surface))
- weston_fade_run(shsurf->view, 1.0, 0.0, 300.0,
- fade_out_done, shsurf);
+ weston_fade_run(shsurf->view, 1.0, 0.0, 300.0,
+ fade_out_done, shsurf);
}
static void
@@ -3107,7 +3188,8 @@ get_shell_surface(struct weston_surface *surface)
}
static struct shell_surface *
-create_common_surface(void *shell, struct weston_surface *surface,
+create_common_surface(struct shell_client *owner, void *shell,
+ struct weston_surface *surface,
const struct weston_shell_client *client)
{
struct shell_surface *shsurf;
@@ -3136,6 +3218,7 @@ create_common_surface(void *shell, struct weston_surface *surface,
shsurf->resource_destroy_listener.notify = handle_resource_destroy;
wl_resource_add_destroy_listener(surface->resource,
&shsurf->resource_destroy_listener);
+ shsurf->owner = owner;
shsurf->shell = (struct desktop_shell *) shell;
shsurf->unresponsive = 0;
@@ -3178,7 +3261,7 @@ static struct shell_surface *
create_shell_surface(void *shell, struct weston_surface *surface,
const struct weston_shell_client *client)
{
- return create_common_surface(shell, surface, client);
+ return create_common_surface(NULL, shell, surface, client);
}
static struct weston_view *
@@ -3195,7 +3278,8 @@ shell_get_shell_surface(struct wl_client *client,
{
struct weston_surface *surface =
wl_resource_get_user_data(surface_resource);
- struct desktop_shell *shell = wl_resource_get_user_data(resource);
+ struct shell_client *sc = wl_resource_get_user_data(resource);
+ struct desktop_shell *shell = sc->shell;
struct shell_surface *shsurf;
if (get_shell_surface(surface)) {
@@ -3205,7 +3289,7 @@ shell_get_shell_surface(struct wl_client *client,
return;
}
- shsurf = create_shell_surface(shell, surface, &shell_client);
+ shsurf = create_common_surface(sc, shell, surface, &shell_client);
if (!shsurf) {
wl_resource_post_error(surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
@@ -3271,8 +3355,9 @@ xdg_surface_set_margin(struct wl_client *client,
int32_t top,
int32_t bottom)
{
- /* Do nothing, Weston doesn't try to constrain or place
- * surfaces in any special manner... */
+ struct shell_surface *shsurf = wl_resource_get_user_data(resource);
+
+ set_margin(shsurf, left, right, top, bottom);
}
static void
@@ -3422,13 +3507,14 @@ static const struct xdg_surface_interface xdg_surface_implementation = {
static void
xdg_send_configure(struct weston_surface *surface,
- uint32_t edges, int32_t width, int32_t height)
+ int32_t width, int32_t height)
{
struct shell_surface *shsurf = get_shell_surface(surface);
assert(shsurf);
- xdg_surface_send_configure(shsurf->resource, width, height);
+ if (shsurf->resource)
+ xdg_surface_send_configure(shsurf->resource, width, height);
}
static const struct weston_shell_client xdg_client = {
@@ -3449,12 +3535,13 @@ xdg_use_unstable_version(struct wl_client *client,
}
static struct shell_surface *
-create_xdg_surface(void *shell, struct weston_surface *surface,
+create_xdg_surface(struct shell_client *owner, void *shell,
+ struct weston_surface *surface,
const struct weston_shell_client *client)
{
struct shell_surface *shsurf;
- shsurf = create_common_surface(shell, surface, client);
+ shsurf = create_common_surface(owner, shell, surface, client);
shsurf->type = SHELL_SURFACE_TOPLEVEL;
return shsurf;
@@ -3479,7 +3566,7 @@ xdg_get_xdg_surface(struct wl_client *client,
return;
}
- shsurf = create_xdg_surface(shell, surface, &xdg_client);
+ shsurf = create_xdg_surface(sc, shell, surface, &xdg_client);
if (!shsurf) {
wl_resource_post_error(surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
@@ -3519,7 +3606,7 @@ static const struct xdg_popup_interface xdg_popup_implementation = {
static void
xdg_popup_send_configure(struct weston_surface *surface,
- uint32_t edges, int32_t width, int32_t height)
+ int32_t width, int32_t height)
{
}
@@ -3528,7 +3615,8 @@ static const struct weston_shell_client xdg_popup_client = {
};
static struct shell_surface *
-create_xdg_popup(void *shell, struct weston_surface *surface,
+create_xdg_popup(struct shell_client *owner, void *shell,
+ struct weston_surface *surface,
const struct weston_shell_client *client,
struct weston_surface *parent,
struct shell_seat *seat,
@@ -3537,7 +3625,7 @@ create_xdg_popup(void *shell, struct weston_surface *surface,
{
struct shell_surface *shsurf;
- shsurf = create_common_surface(shell, surface, client);
+ shsurf = create_common_surface(owner, shell, surface, client);
shsurf->type = SHELL_SURFACE_POPUP;
shsurf->popup.shseat = seat;
shsurf->popup.serial = serial;
@@ -3582,7 +3670,7 @@ xdg_get_xdg_popup(struct wl_client *client,
parent = wl_resource_get_user_data(parent_resource);
seat = get_shell_seat(wl_resource_get_user_data(seat_resource));;
- shsurf = create_xdg_popup(shell, surface, &xdg_popup_client,
+ shsurf = create_xdg_popup(sc, shell, surface, &xdg_popup_client,
parent, seat, serial, x, y);
if (!shsurf) {
wl_resource_post_error(surface_resource,
@@ -3715,6 +3803,12 @@ terminate_screensaver(struct desktop_shell *shell)
if (shell->screensaver.process.pid == 0)
return;
+ /* Disarm the screensaver timer, otherwise it may fire when the
+ * compositor is not in the idle state. In that case, the screen will
+ * be locked, but the wake_signal won't fire on user input, making the
+ * system unresponsive. */
+ wl_event_source_timer_update(shell->screensaver.timer, 0);
+
kill(shell->screensaver.process.pid, SIGTERM);
}
@@ -3982,7 +4076,7 @@ move_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *dat
shsurf->state.maximized)
return;
- surface_move(shsurf, (struct weston_seat *) seat);
+ surface_move(shsurf, (struct weston_seat *) seat, 0);
}
static void
@@ -4355,8 +4449,12 @@ rotate_binding(struct weston_seat *seat, uint32_t time, uint32_t button,
surface_rotate(surface, seat);
}
-/* Move all fullscreen layers down to the current workspace in a non-reversible
- * manner. This should be used when implementing shell-wide overlays, such as
+/* Move all fullscreen layers down to the current workspace and hide their
+ * black views. The surfaces' state is set to both fullscreen and lowered,
+ * and this is reversed when such a surface is re-configured, see
+ * shell_configure_fullscreen() and shell_ensure_fullscreen_black_view().
+ *
+ * This should be used when implementing shell-wide overlays, such as
* the alt-tab switcher, which need to de-promote fullscreen layers. */
void
lower_fullscreen_layer(struct desktop_shell *shell)
@@ -4368,16 +4466,32 @@ lower_fullscreen_layer(struct desktop_shell *shell)
wl_list_for_each_reverse_safe(view, prev,
&shell->fullscreen_layer.view_list,
layer_link) {
+ struct shell_surface *shsurf = get_shell_surface(view->surface);
+
+ if (!shsurf)
+ continue;
+
+ /* We can have a non-fullscreen popup for a fullscreen surface
+ * 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);
+ }
+
+ /* Lower the view to the workspace layer */
wl_list_remove(&view->layer_link);
wl_list_insert(&ws->layer.view_list, &view->layer_link);
weston_view_damage_below(view);
weston_surface_damage(view->surface);
+
+ shsurf->state.lowered = true;
}
}
void
activate(struct desktop_shell *shell, struct weston_surface *es,
- struct weston_seat *seat)
+ struct weston_seat *seat, bool configure)
{
struct weston_surface *main_surface;
struct focus_state *state;
@@ -4385,6 +4499,8 @@ activate(struct desktop_shell *shell, struct weston_surface *es,
struct weston_surface *old_es;
struct shell_surface *shsurf;
+ lower_fullscreen_layer(shell);
+
main_surface = weston_surface_get_main_surface(es);
weston_surface_activate(es, seat);
@@ -4399,7 +4515,7 @@ activate(struct desktop_shell *shell, struct weston_surface *es,
shsurf = get_shell_surface(main_surface);
assert(shsurf);
- if (shsurf->state.fullscreen)
+ if (shsurf->state.fullscreen && configure)
shell_configure_fullscreen(shsurf);
else
restore_all_output_modes(shell->compositor);
@@ -4448,7 +4564,7 @@ activate_binding(struct weston_seat *seat,
if (get_shell_surface_type(main_surface) == SHELL_SURFACE_NONE)
return;
- activate(shell, focus, seat);
+ activate(shell, focus, seat, true);
}
static void
@@ -4475,6 +4591,19 @@ touch_to_activate_binding(struct weston_seat *seat, uint32_t time, void *data)
}
static void
+unfocus_all_seats(struct desktop_shell *shell)
+{
+ struct weston_seat *seat, *next;
+
+ wl_list_for_each_safe(seat, next, &shell->compositor->seat_list, link) {
+ if (seat->keyboard == NULL)
+ continue;
+
+ weston_keyboard_set_focus(seat->keyboard, NULL);
+ }
+}
+
+static void
lock(struct desktop_shell *shell)
{
struct workspace *ws = get_current_workspace(shell);
@@ -4500,6 +4629,11 @@ lock(struct desktop_shell *shell)
launch_screensaver(shell);
+ /* Remove the keyboard focus on all seats. This will be
+ * restored to the workspace's saved state via
+ * restore_focus_state when the compositor is unlocked */
+ unfocus_all_seats(shell);
+
/* TODO: disable bindings that should not work while locked. */
/* All this must be undone in resume_desktop(). */
@@ -4850,7 +4984,7 @@ map(struct desktop_shell *shell, struct shell_surface *shsurf,
if (shell->locked)
break;
wl_list_for_each(seat, &compositor->seat_list, link)
- activate(shell, shsurf->surface, seat);
+ activate(shell, shsurf->surface, seat, true);
break;
case SHELL_SURFACE_POPUP:
case SHELL_SURFACE_NONE:
@@ -5072,7 +5206,7 @@ bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
if (sc)
wl_resource_set_implementation(sc->resource,
&shell_implementation,
- shell, NULL);
+ sc, NULL);
}
static void
@@ -5301,7 +5435,7 @@ switcher_destroy(struct switcher *switcher)
if (switcher->current)
activate(switcher->shell, switcher->current,
- (struct weston_seat *) keyboard->seat);
+ (struct weston_seat *) keyboard->seat, true);
wl_list_remove(&switcher->listener.link);
weston_keyboard_end_grab(keyboard);
if (keyboard->input_method_resource)
@@ -5676,9 +5810,12 @@ shell_reposition_view_on_output_destroy(struct weston_view *view)
x = first_output->x + first_output->width / 4;
y = first_output->y + first_output->height / 4;
+
+ weston_view_set_position(view, x, y);
+ } else {
+ weston_view_geometry_dirty(view);
}
- weston_view_set_position(view, x, y);
shsurf = get_shell_surface(view->surface);
@@ -5690,27 +5827,35 @@ shell_reposition_view_on_output_destroy(struct weston_view *view)
}
}
+void
+shell_for_each_layer(struct desktop_shell *shell,
+ shell_for_each_layer_func_t func, void *data)
+{
+ struct workspace **ws;
+
+ func(shell, &shell->fullscreen_layer, data);
+ func(shell, &shell->panel_layer, data);
+ func(shell, &shell->background_layer, data);
+ func(shell, &shell->lock_layer, data);
+ func(shell, &shell->input_panel_layer, data);
+
+ wl_array_for_each(ws, &shell->workspaces.array)
+ func(shell, &(*ws)->layer, data);
+}
+
static void
-shell_reposition_views_on_output_destroy(struct shell_output *shell_output)
+shell_output_destroy_move_layer(struct desktop_shell *shell,
+ struct weston_layer *layer,
+ void *data)
{
- struct desktop_shell *shell = shell_output->shell;
- struct weston_output *output = shell_output->output;
- struct weston_layer *layer;
+ struct weston_output *output = data;
struct weston_view *view;
- /* Move all views in the layers owned by the shell */
- wl_list_for_each(layer, shell->fullscreen_layer.link.prev, link) {
- wl_list_for_each(view, &layer->view_list, layer_link) {
- if (view->output != output)
- continue;
-
- shell_reposition_view_on_output_destroy(view);
- }
+ wl_list_for_each(view, &layer->view_list, layer_link) {
+ if (view->output != output)
+ continue;
- /* We don't start from the beggining of the layer list, so
- * make sure we don't wrap around it. */
- if (layer == &shell->background_layer)
- break;
+ shell_reposition_view_on_output_destroy(view);
}
}
@@ -5719,8 +5864,10 @@ handle_output_destroy(struct wl_listener *listener, void *data)
{
struct shell_output *output_listener =
container_of(listener, struct shell_output, destroy_listener);
+ struct weston_output *output = output_listener->output;
+ struct desktop_shell *shell = output_listener->shell;
- shell_reposition_views_on_output_destroy(output_listener);
+ shell_for_each_layer(shell, shell_output_destroy_move_layer, output);
wl_list_remove(&output_listener->destroy_listener.link);
wl_list_remove(&output_listener->link);
@@ -5756,34 +5903,32 @@ handle_output_create(struct wl_listener *listener, void *data)
}
static void
-handle_output_move(struct wl_listener *listener, void *data)
+handle_output_move_layer(struct desktop_shell *shell,
+ struct weston_layer *layer, void *data)
{
- struct desktop_shell *shell;
- struct weston_output *output;
- struct weston_layer *layer;
+ struct weston_output *output = data;
struct weston_view *view;
float x, y;
- shell = container_of(listener, struct desktop_shell,
- output_move_listener);
- output = data;
+ wl_list_for_each(view, &layer->view_list, layer_link) {
+ if (view->output != output)
+ continue;
- /* Move all views in the layers owned by the shell */
- wl_list_for_each(layer, shell->fullscreen_layer.link.prev, link) {
- wl_list_for_each(view, &layer->view_list, layer_link) {
- if (view->output != output)
- continue;
+ x = view->geometry.x + output->move_x;
+ y = view->geometry.y + output->move_y;
+ weston_view_set_position(view, x, y);
+ }
+}
- x = view->geometry.x + output->move_x;
- y = view->geometry.y + output->move_y;
- weston_view_set_position(view, x, y);
- }
+static void
+handle_output_move(struct wl_listener *listener, void *data)
+{
+ struct desktop_shell *shell;
- /* We don't start from the beggining of the layer list, so
- * make sure we don't wrap around it. */
- if (layer == &shell->background_layer)
- break;
- }
+ shell = container_of(listener, struct desktop_shell,
+ output_move_listener);
+
+ shell_for_each_layer(shell, handle_output_move_layer, data);
}
static void
@@ -5829,6 +5974,7 @@ shell_destroy(struct wl_listener *listener, void *data)
}
wl_list_remove(&shell->output_create_listener.link);
+ wl_list_remove(&shell->output_move_listener.link);
wl_array_for_each(ws, &shell->workspaces.array)
workspace_destroy(*ws);
@@ -5931,6 +6077,14 @@ shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
debug_binding, shell);
}
+static void
+handle_seat_created(struct wl_listener *listener, void *data)
+{
+ struct weston_seat *seat = data;
+
+ create_shell_seat(seat);
+}
+
WL_EXPORT int
module_init(struct weston_compositor *ec,
int *argc, char *argv[])
@@ -5961,9 +6115,10 @@ module_init(struct weston_compositor *ec,
ec->shell_interface.set_transient = set_transient;
ec->shell_interface.set_fullscreen = set_fullscreen;
ec->shell_interface.set_xwayland = set_xwayland;
- ec->shell_interface.move = surface_move;
+ 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;
weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
@@ -6030,10 +6185,10 @@ module_init(struct weston_compositor *ec,
shell->screensaver.timer =
wl_event_loop_add_timer(loop, screensaver_timeout, shell);
- wl_list_for_each(seat, &ec->seat_list, link) {
- create_pointer_focus_listener(seat);
- create_keyboard_focus_listener(seat);
- }
+ wl_list_for_each(seat, &ec->seat_list, link)
+ handle_seat_created(NULL, seat);
+ shell->seat_create_listener.notify = handle_seat_created;
+ wl_signal_add(&ec->seat_created_signal, &shell->seat_create_listener);
screenshooter_create(ec);
diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h
index 5d127c6d..6e637850 100644
--- a/desktop-shell/shell.h
+++ b/desktop-shell/shell.h
@@ -199,6 +199,7 @@ struct desktop_shell {
struct weston_layer minimized_layer;
+ struct wl_listener seat_create_listener;
struct wl_listener output_create_listener;
struct wl_listener output_move_listener;
struct wl_list output_list;
@@ -206,9 +207,6 @@ struct desktop_shell {
char *client;
};
-void
-set_alpha_if_fullscreen(struct shell_surface *shsurf);
-
struct weston_output *
get_default_output(struct weston_compositor *compositor);
@@ -226,7 +224,7 @@ lower_fullscreen_layer(struct desktop_shell *shell);
void
activate(struct desktop_shell *shell, struct weston_surface *es,
- struct weston_seat *seat);
+ struct weston_seat *seat, bool configure);
void
exposay_binding(struct weston_seat *seat,
@@ -236,3 +234,11 @@ int
input_panel_setup(struct desktop_shell *shell);
void
input_panel_destroy(struct desktop_shell *shell);
+
+typedef void (*shell_for_each_layer_func_t)(struct desktop_shell *,
+ struct weston_layer *, void *);
+
+void
+shell_for_each_layer(struct desktop_shell *shell,
+ shell_for_each_layer_func_t func,
+ void *data);
diff --git a/protocol/fullscreen-shell.xml b/protocol/fullscreen-shell.xml
index 3c2cf3c0..939c2ba1 100644
--- a/protocol/fullscreen-shell.xml
+++ b/protocol/fullscreen-shell.xml
@@ -49,7 +49,7 @@
capability is provided, wl_fullscreen_shell.present_surface_for_mode
will almost never fail and clients should feel free to set whatever
mode they like. If the compositor does not advertise this, it may
- still suppot some modes that are not advertised through wl_global.mode
+ still support some modes that are not advertised through wl_global.mode
but it is less likely.
CURSOR_PLANE:
diff --git a/shared/cairo-util.c b/shared/cairo-util.c
index 39485729..2a332490 100644
--- a/shared/cairo-util.c
+++ b/shared/cairo-util.c
@@ -488,10 +488,15 @@ theme_get_location(struct theme *t, int x, int y,
int width, int height, int flags)
{
int vlocation, hlocation, location;
- const int grip_size = 8;
- int margin, top_margin;
+ int margin, top_margin, grip_size;
- margin = (flags & THEME_FRAME_MAXIMIZED) ? 0 : t->margin;
+ if (flags & THEME_FRAME_MAXIMIZED) {
+ margin = 0;
+ grip_size = 0;
+ } else {
+ margin = t->margin;
+ grip_size = 8;
+ }
if (flags & THEME_FRAME_NO_TITLE)
top_margin = t->width;
@@ -500,7 +505,7 @@ theme_get_location(struct theme *t, int x, int y,
if (x < margin)
hlocation = THEME_LOCATION_EXTERIOR;
- else if (margin <= x && x < margin + grip_size)
+ else if (x < margin + grip_size)
hlocation = THEME_LOCATION_RESIZING_LEFT;
else if (x < width - margin - grip_size)
hlocation = THEME_LOCATION_INTERIOR;
@@ -511,7 +516,7 @@ theme_get_location(struct theme *t, int x, int y,
if (y < margin)
vlocation = THEME_LOCATION_EXTERIOR;
- else if (margin <= y && y < margin + grip_size)
+ else if (y < margin + grip_size)
vlocation = THEME_LOCATION_RESIZING_TOP;
else if (y < height - margin - grip_size)
vlocation = THEME_LOCATION_INTERIOR;
diff --git a/src/animation.c b/src/animation.c
index 521e4f18..a29b34ad 100644
--- a/src/animation.c
+++ b/src/animation.c
@@ -181,13 +181,13 @@ weston_view_animation_frame(struct weston_animation *base,
}
static struct weston_view_animation *
-weston_view_animation_run(struct weston_view *view,
- float start, float stop,
- weston_view_animation_frame_func_t frame,
- weston_view_animation_frame_func_t reset,
- weston_view_animation_done_func_t done,
- void *data,
- void *private)
+weston_view_animation_create(struct weston_view *view,
+ float start, float stop,
+ weston_view_animation_frame_func_t frame,
+ weston_view_animation_frame_func_t reset,
+ weston_view_animation_done_func_t done,
+ void *data,
+ void *private)
{
struct weston_view_animation *animation;
@@ -203,14 +203,12 @@ weston_view_animation_run(struct weston_view *view,
animation->start = start;
animation->stop = stop;
animation->private = private;
+
weston_matrix_init(&animation->transform.matrix);
wl_list_insert(&view->geometry.transformation_list,
&animation->transform.link);
- weston_spring_init(&animation->spring, 200.0, start, stop);
- animation->spring.friction = 700;
- animation->animation.frame_counter = 0;
+
animation->animation.frame = weston_view_animation_frame;
- weston_view_animation_frame(&animation->animation, NULL, 0);
animation->listener.notify = handle_animation_view_destroy;
wl_signal_add(&view->destroy_signal, &animation->listener);
@@ -222,6 +220,13 @@ weston_view_animation_run(struct weston_view *view,
}
static void
+weston_view_animation_run(struct weston_view_animation *animation)
+{
+ animation->animation.frame_counter = 0;
+ weston_view_animation_frame(&animation->animation, NULL, 0);
+}
+
+static void
reset_alpha(struct weston_view_animation *animation)
{
struct weston_view *view = animation->view;
@@ -258,9 +263,9 @@ weston_zoom_run(struct weston_view *view, float start, float stop,
{
struct weston_view_animation *zoom;
- zoom = weston_view_animation_run(view, start, stop,
- zoom_frame, reset_alpha,
- done, data, NULL);
+ zoom = weston_view_animation_create(view, start, stop,
+ zoom_frame, reset_alpha,
+ done, data, NULL);
if (zoom == NULL)
return NULL;
@@ -269,6 +274,8 @@ weston_zoom_run(struct weston_view *view, float start, float stop,
zoom->spring.friction = 1400;
zoom->spring.previous = start - (stop - start) * 0.03;
+ weston_view_animation_run(zoom);
+
return zoom;
}
@@ -290,20 +297,21 @@ weston_fade_run(struct weston_view *view,
{
struct weston_view_animation *fade;
- fade = weston_view_animation_run(view, start, end,
- fade_frame, reset_alpha,
- done, data, NULL);
+ fade = weston_view_animation_create(view, start, end,
+ fade_frame, reset_alpha,
+ done, data, NULL);
if (fade == NULL)
return NULL;
- fade->spring.k = 1000.0;
-
+ weston_spring_init(&fade->spring, 1000.0, start, end);
fade->spring.friction = 4000;
fade->spring.previous = start - (end - start) * 0.1;
view->alpha = start;
+ weston_view_animation_run(fade);
+
return fade;
}
@@ -339,7 +347,7 @@ weston_stable_fade_run(struct weston_view *front_view, float start,
{
struct weston_view_animation *fade;
- fade = weston_view_animation_run(front_view, 0, 0,
+ fade = weston_view_animation_create(front_view, 0, 0,
stable_fade_frame, NULL,
done, data, back_view);
@@ -352,6 +360,8 @@ weston_stable_fade_run(struct weston_view *front_view, float start,
front_view->alpha = start;
back_view->alpha = end;
+ weston_view_animation_run(fade);
+
return fade;
}
@@ -373,16 +383,18 @@ weston_slide_run(struct weston_view *view, float start, float stop,
{
struct weston_view_animation *animation;
- animation = weston_view_animation_run(view, start, stop,
+ animation = weston_view_animation_create(view, start, stop,
slide_frame, NULL, done,
data, NULL);
if (!animation)
return NULL;
+ weston_spring_init(&animation->spring, 400.0, 0.0, 1.0);
animation->spring.friction = 600;
- animation->spring.k = 400;
animation->spring.clip = WESTON_SPRING_BOUNCE;
+ weston_view_animation_run(animation);
+
return animation;
}
@@ -440,13 +452,13 @@ weston_move_scale_run(struct weston_view *view, int dx, int dy,
move->reverse = reverse;
move->done = done;
- animation = weston_view_animation_run(view, start, end, move_frame,
- NULL, move_done, data, move);
+ animation = weston_view_animation_create(view, start, end, move_frame,
+ NULL, move_done, data, move);
if (animation == NULL)
return NULL;
- animation->spring.k = 400;
+ weston_spring_init(&animation->spring, 400.0, start, end);
animation->spring.friction = 1150;
return animation;
diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 3c15ec30..44413081 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -953,12 +953,15 @@ drm_output_prepare_cursor_view(struct weston_output *output_base,
{
struct drm_compositor *c =
(struct drm_compositor *) output_base->compositor;
+ struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;
struct drm_output *output = (struct drm_output *) output_base;
if (c->gbm == NULL)
return NULL;
if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL)
return NULL;
+ if (viewport->buffer.scale != output_base->current_scale)
+ return NULL;
if (output->cursor_view)
return NULL;
if (ev->output_mask != (1u << output_base->id))
@@ -2576,7 +2579,7 @@ recorder_frame_notify(struct wl_listener *listener, void *data)
return;
}
- vaapi_recorder_frame(output->recorder, fd, output->current->stride / 4);
+ vaapi_recorder_frame(output->recorder, fd, output->current->stride);
}
static void *
@@ -2783,9 +2786,15 @@ drm_compositor_create(struct wl_display *display,
wl_list_init(&ec->sprite_list);
create_sprites(ec);
+ if (udev_input_init(&ec->input,
+ &ec->base, ec->udev, param->seat_id) < 0) {
+ weston_log("failed to create input devices\n");
+ goto err_sprite;
+ }
+
if (create_outputs(ec, param->connector, drm_device) < 0) {
weston_log("failed to create output for %s\n", path);
- goto err_sprite;
+ goto err_udev_input;
}
/* A this point we have some idea of whether or not we have a working
@@ -2795,12 +2804,6 @@ drm_compositor_create(struct wl_display *display,
path = NULL;
- if (udev_input_init(&ec->input,
- &ec->base, ec->udev, param->seat_id) < 0) {
- weston_log("failed to create input devices\n");
- goto err_sprite;
- }
-
loop = wl_display_get_event_loop(ec->base.wl_display);
ec->drm_source =
wl_event_loop_add_fd(loop, ec->drm.fd,
@@ -2843,6 +2846,7 @@ err_udev_monitor:
udev_monitor_unref(ec->udev_monitor);
err_drm_source:
wl_event_source_remove(ec->drm_source);
+err_udev_input:
udev_input_destroy(&ec->input);
err_sprite:
ec->base.renderer->destroy(&ec->base);
diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index f35db9c3..67f15be9 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -256,6 +256,12 @@ 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);
+ close(fd);
+ free(data);
+ return NULL;
+ }
sb->output = output;
wl_list_init(&sb->free_link);
diff --git a/src/compositor.c b/src/compositor.c
index fd2decb3..3d65e4cd 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -675,7 +675,8 @@ weston_surface_to_buffer_float(struct weston_surface *surface,
/* first transform coordinates if the scaler is set */
scaler_surface_to_buffer(surface, sx, sy, bx, by);
- weston_transformed_coord(surface->width, surface->height,
+ weston_transformed_coord(surface->width_from_buffer,
+ surface->height_from_buffer,
vp->buffer.transform, vp->buffer.scale,
*bx, *by, bx, by);
}
@@ -709,7 +710,8 @@ weston_surface_to_buffer_rect(struct weston_surface *surface,
rect.x2 = floorf(xf);
rect.y2 = floorf(yf);
- return weston_transformed_rect(surface->width, surface->height,
+ return weston_transformed_rect(surface->width_from_buffer,
+ surface->height_from_buffer,
vp->buffer.transform, vp->buffer.scale,
rect);
}
@@ -3186,8 +3188,6 @@ WL_EXPORT void
weston_output_update_matrix(struct weston_output *output)
{
float magnification;
- struct weston_matrix camera;
- struct weston_matrix modelview;
weston_matrix_init(&output->matrix);
weston_matrix_translate(&output->matrix,
@@ -3202,14 +3202,11 @@ weston_output_update_matrix(struct weston_output *output)
if (output->zoom.active) {
magnification = 1 / (1 - output->zoom.spring_z.current);
- weston_matrix_init(&camera);
- weston_matrix_init(&modelview);
weston_output_update_zoom(output);
- weston_matrix_translate(&camera, output->zoom.trans_x,
- -output->zoom.trans_y, 0);
- weston_matrix_invert(&modelview, &camera);
- weston_matrix_scale(&modelview, magnification, magnification, 1.0);
- weston_matrix_multiply(&output->matrix, &modelview);
+ weston_matrix_translate(&output->matrix, -output->zoom.trans_x,
+ output->zoom.trans_y, 0);
+ weston_matrix_scale(&output->matrix, magnification,
+ magnification, 1.0);
}
output->dirty = 0;
@@ -3336,6 +3333,7 @@ weston_output_transform_coordinate(struct weston_output *output,
{
wl_fixed_t tx, ty;
wl_fixed_t width, height;
+ float zoom_scale, zx, zy;
width = wl_fixed_from_int(output->width * output->current_scale - 1);
height = wl_fixed_from_int(output->height * output->current_scale - 1);
@@ -3376,8 +3374,23 @@ weston_output_transform_coordinate(struct weston_output *output,
break;
}
- *x = tx / output->current_scale + wl_fixed_from_int(output->x);
- *y = ty / output->current_scale + wl_fixed_from_int(output->y);
+ tx /= output->current_scale;
+ ty /= output->current_scale;
+
+ if (output->zoom.active) {
+ zoom_scale = output->zoom.spring_z.current;
+ zx = (wl_fixed_to_double(tx) * (1.0f - zoom_scale) +
+ output->width / 2.0f *
+ (zoom_scale + output->zoom.trans_x));
+ zy = (wl_fixed_to_double(ty) * (1.0f - zoom_scale) +
+ output->height / 2.0f *
+ (zoom_scale + output->zoom.trans_y));
+ tx = wl_fixed_from_double(zx);
+ ty = wl_fixed_from_double(zy);
+ }
+
+ *x = tx + wl_fixed_from_int(output->x);
+ *y = ty + wl_fixed_from_int(output->y);
}
static void
diff --git a/src/compositor.h b/src/compositor.h
index af41b008..057f8be8 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -82,8 +82,7 @@ struct weston_mode {
};
struct weston_shell_client {
- void (*send_configure)(struct weston_surface *surface,
- uint32_t edges, int32_t width, int32_t height);
+ void (*send_configure)(struct weston_surface *surface, int32_t width, int32_t height);
};
struct weston_shell_interface {
@@ -111,7 +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);
};
struct weston_animation {
@@ -278,6 +279,7 @@ struct weston_touch_grab_interface {
int touch_id,
wl_fixed_t sx,
wl_fixed_t sy);
+ void (*frame)(struct weston_touch_grab *grab);
void (*cancel)(struct weston_touch_grab *grab);
};
@@ -907,9 +909,10 @@ struct weston_surface {
} pending;
/*
- * If non-NULL, this function will be called on surface::attach after
- * a new buffer has been set up for this surface. The integer params
- * are the sx and sy paramerters supplied to surface::attach .
+ * If non-NULL, this function will be called on
+ * wl_surface::commit after a new buffer has been set up for
+ * this surface. The integer params are the sx and sy
+ * parameters supplied to wl_surface::attach.
*/
void (*configure)(struct weston_surface *es, int32_t sx, int32_t sy);
void *configure_private;
@@ -1008,6 +1011,8 @@ notify_keyboard_focus_out(struct weston_seat *seat);
void
notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
wl_fixed_t x, wl_fixed_t y, int touch_type);
+void
+notify_touch_frame(struct weston_seat *seat);
void
weston_layer_init(struct weston_layer *layer, struct wl_list *below);
diff --git a/src/data-device.c b/src/data-device.c
index 483e22e9..6a81bc8e 100644
--- a/src/data-device.c
+++ b/src/data-device.c
@@ -497,6 +497,11 @@ drag_grab_touch_motion(struct weston_touch_grab *grab, uint32_t time,
}
static void
+drag_grab_touch_frame(struct weston_touch_grab *grab)
+{
+}
+
+static void
drag_grab_touch_cancel(struct weston_touch_grab *grab)
{
struct weston_touch_drag *touch_drag =
@@ -511,6 +516,7 @@ static const struct weston_touch_grab_interface touch_drag_grab_interface = {
drag_grab_touch_down,
drag_grab_touch_up,
drag_grab_touch_motion,
+ drag_grab_touch_frame,
drag_grab_touch_cancel
};
diff --git a/src/evdev.c b/src/evdev.c
index d9b7d320..888dfbdb 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -100,7 +100,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time)
notify_motion(master, time, device->rel.dx, device->rel.dy);
device->rel.dx = 0;
device->rel.dy = 0;
- goto handled;
+ break;
case EVDEV_ABSOLUTE_MT_DOWN:
if (device->output == NULL)
break;
@@ -113,7 +113,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time)
master->slot_map |= 1 << seat_slot;
notify_touch(master, time, seat_slot, x, y, WL_TOUCH_DOWN);
- goto handled;
+ break;
case EVDEV_ABSOLUTE_MT_MOTION:
if (device->output == NULL)
break;
@@ -123,12 +123,12 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time)
&x, &y);
seat_slot = device->mt.slots[slot].seat_slot;
notify_touch(master, time, seat_slot, x, y, WL_TOUCH_MOTION);
- goto handled;
+ break;
case EVDEV_ABSOLUTE_MT_UP:
seat_slot = device->mt.slots[slot].seat_slot;
master->slot_map &= ~(1 << seat_slot);
notify_touch(master, time, seat_slot, 0, 0, WL_TOUCH_UP);
- goto handled;
+ break;
case EVDEV_ABSOLUTE_TOUCH_DOWN:
if (device->output == NULL)
break;
@@ -141,7 +141,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time)
device->abs.seat_slot = seat_slot;
master->slot_map |= 1 << seat_slot;
notify_touch(master, time, seat_slot, x, y, WL_TOUCH_DOWN);
- goto handled;
+ break;
case EVDEV_ABSOLUTE_MOTION:
if (device->output == NULL)
break;
@@ -156,17 +156,16 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time)
x, y, WL_TOUCH_MOTION);
else if (device->seat_caps & EVDEV_SEAT_POINTER)
notify_motion_absolute(master, time, x, y);
- goto handled;
+ break;
case EVDEV_ABSOLUTE_TOUCH_UP:
seat_slot = device->abs.seat_slot;
master->slot_map &= ~(1 << seat_slot);
notify_touch(master, time, seat_slot, 0, 0, WL_TOUCH_UP);
- goto handled;
+ break;
+ default:
+ assert(0 && "Unknown pending event type");
}
- assert(0 && "Unknown pending event type");
-
-handled:
device->pending_event = EVDEV_NONE;
}
@@ -602,7 +601,7 @@ notify_output_destroy(struct wl_listener *listener, void *data)
struct weston_compositor *c = device->seat->compositor;
struct weston_output *output;
- if (device->output_name) {
+ if (!device->output_name && !wl_list_empty(&c->output_list)) {
output = container_of(c->output_list.next,
struct weston_output, link);
evdev_device_set_output(device, output);
@@ -615,6 +614,11 @@ void
evdev_device_set_output(struct evdev_device *device,
struct weston_output *output)
{
+ if (device->output_destroy_listener.notify) {
+ wl_list_remove(&device->output_destroy_listener.link);
+ device->output_destroy_listener.notify = NULL;
+ }
+
device->output = output;
device->output_destroy_listener.notify = notify_output_destroy;
wl_signal_add(&output->destroy_signal,
diff --git a/src/gl-renderer.h b/src/gl-renderer.h
index db42f6ca..77b19529 100644
--- a/src/gl-renderer.h
+++ b/src/gl-renderer.h
@@ -75,8 +75,8 @@ struct gl_renderer_interface {
* tightly packed.
*
* The top and bottom textures will extend over the sides to the
- * full width of the bordered window while. The right and left
- * edges, however, will extend only to the top and bottom of the
+ * full width of the bordered window. The right and left edges,
+ * however, will extend only to the top and bottom of the
* compositor surface. This is demonstrated by the picture below:
*
* +-----------------------+
@@ -101,4 +101,3 @@ struct gl_renderer_interface {
void (*print_egl_error_state)(void);
};
-struct gl_renderer_interface gl_renderer_interface;
diff --git a/src/input.c b/src/input.c
index 9c514689..2c799f43 100644
--- a/src/input.c
+++ b/src/input.c
@@ -287,6 +287,15 @@ default_grab_touch_motion(struct weston_touch_grab *grab, uint32_t time,
}
static void
+default_grab_touch_frame(struct weston_touch_grab *grab)
+{
+ struct wl_resource *resource;
+
+ wl_resource_for_each(resource, &grab->touch->focus_resource_list)
+ wl_touch_send_frame(resource);
+}
+
+static void
default_grab_touch_cancel(struct weston_touch_grab *grab)
{
}
@@ -295,6 +304,7 @@ static const struct weston_touch_grab_interface default_touch_grab_interface = {
default_grab_touch_down,
default_grab_touch_up,
default_grab_touch_motion,
+ default_grab_touch_frame,
default_grab_touch_cancel,
};
@@ -1512,6 +1522,15 @@ notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
}
}
+WL_EXPORT void
+notify_touch_frame(struct weston_seat *seat)
+{
+ struct weston_touch *touch = seat->touch;
+ struct weston_touch_grab *grab = touch->grab;
+
+ grab->interface->frame(grab);
+}
+
static void
pointer_cursor_surface_configure(struct weston_surface *es,
int32_t dx, int32_t dy)
diff --git a/src/launcher-util.c b/src/launcher-util.c
index 1b63458c..ac764dc8 100644
--- a/src/launcher-util.c
+++ b/src/launcher-util.c
@@ -390,6 +390,11 @@ weston_launcher_connect(struct weston_compositor *compositor, int tty,
launcher->fd = weston_environment_get_fd("WESTON_LAUNCHER_SOCK");
if (launcher->fd != -1) {
launcher->tty = weston_environment_get_fd("WESTON_TTY_FD");
+ /* We don't get a chance to read out the original kb
+ * mode for the tty, so just hard code K_UNICODE here
+ * in case we have to clean if weston-launch dies. */
+ launcher->kb_mode = K_UNICODE;
+
loop = wl_display_get_event_loop(compositor->wl_display);
launcher->source = wl_event_loop_add_fd(loop, launcher->fd,
WL_EVENT_READABLE,
diff --git a/src/libinput-device.c b/src/libinput-device.c
index c8a64431..4605a769 100644
--- a/src/libinput-device.c
+++ b/src/libinput-device.c
@@ -147,6 +147,9 @@ handle_touch_with_coords(struct libinput_device *libinput_device,
uint32_t time;
int32_t slot;
+ if (!device->output)
+ return;
+
time = libinput_event_touch_get_time(touch_event);
slot = libinput_event_touch_get_seat_slot(touch_event);
@@ -187,6 +190,17 @@ handle_touch_up(struct libinput_device *libinput_device,
notify_touch(device->seat, time, slot, 0, 0, WL_TOUCH_UP);
}
+static void
+handle_touch_frame(struct libinput_device *libinput_device,
+ struct libinput_event_touch *touch_event)
+{
+ struct evdev_device *device =
+ libinput_device_get_user_data(libinput_device);
+ struct weston_seat *seat = device->seat;
+
+ notify_touch_frame(seat);
+}
+
int
evdev_device_process_event(struct libinput_event *event)
{
@@ -227,6 +241,11 @@ evdev_device_process_event(struct libinput_event *event)
case LIBINPUT_EVENT_TOUCH_UP:
handle_touch_up(libinput_device,
libinput_event_get_touch_event(event));
+ break;
+ case LIBINPUT_EVENT_TOUCH_FRAME:
+ handle_touch_frame(libinput_device,
+ libinput_event_get_touch_event(event));
+ break;
default:
handled = 0;
weston_log("unknown libinput event %d\n",
@@ -245,7 +264,7 @@ notify_output_destroy(struct wl_listener *listener, void *data)
struct weston_compositor *c = device->seat->compositor;
struct weston_output *output;
- if (device->output_name) {
+ if (!device->output_name && !wl_list_empty(&c->output_list)) {
output = container_of(c->output_list.next,
struct weston_output, link);
evdev_device_set_output(device, output);
@@ -258,6 +277,11 @@ void
evdev_device_set_output(struct evdev_device *device,
struct weston_output *output)
{
+ if (device->output_destroy_listener.notify) {
+ wl_list_remove(&device->output_destroy_listener.link);
+ device->output_destroy_listener.notify = NULL;
+ }
+
device->output = output;
device->output_destroy_listener.notify = notify_output_destroy;
wl_signal_add(&output->destroy_signal,
diff --git a/src/libinput-seat.c b/src/libinput-seat.c
index b6adc76b..a38d4705 100644
--- a/src/libinput-seat.c
+++ b/src/libinput-seat.c
@@ -84,7 +84,7 @@ device_added(struct udev_input *input, struct libinput_device *libinput_device)
wl_list_for_each(output, &c->output_list, link)
if (strcmp(output->name, device->output_name) == 0)
evdev_device_set_output(device, output);
- } else if (device->output == NULL) {
+ } else if (device->output == NULL && !wl_list_empty(&c->output_list)) {
output = container_of(c->output_list.next,
struct weston_output, link);
evdev_device_set_output(device, output);
@@ -251,14 +251,30 @@ udev_input_enable(struct udev_input *input)
return 0;
}
+static void
+libinput_log_func(enum libinput_log_priority priority, void *user_data,
+ const char *format, va_list args)
+{
+ weston_vlog(format, args);
+}
+
int
udev_input_init(struct udev_input *input, struct weston_compositor *c, struct udev *udev,
const char *seat_id)
{
+ const char *log_priority = NULL;
+
memset(input, 0, sizeof *input);
input->compositor = c;
+ libinput_log_set_handler(&libinput_log_func, NULL);
+
+ log_priority = getenv("WESTON_LIBINPUT_LOG_PRIORITY");
+ if (log_priority) {
+ libinput_log_set_priority(strtol(log_priority, NULL, 10));
+ }
+
input->libinput = libinput_udev_create_for_seat(&libinput_interface, input,
udev, seat_id);
if (!input->libinput) {
@@ -298,12 +314,15 @@ notify_output_create(struct wl_listener *listener, void *data)
struct evdev_device *device;
struct weston_output *output = data;
- wl_list_for_each(device, &seat->devices_list, link)
+ wl_list_for_each(device, &seat->devices_list, link) {
if (device->output_name &&
strcmp(output->name, device->output_name) == 0) {
evdev_device_set_output(device, output);
- break;
}
+
+ if (device->output_name == NULL && device->output == NULL)
+ evdev_device_set_output(device, output);
+ }
}
static struct udev_seat *
@@ -313,9 +332,9 @@ udev_seat_create(struct udev_input *input, const char *seat_name)
struct udev_seat *seat;
seat = zalloc(sizeof *seat);
-
if (!seat)
return NULL;
+
weston_seat_init(&seat->base, c, seat_name);
seat->base.led_update = udev_seat_led_update;
diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c
index 74ed58f4..93be9682 100644
--- a/src/pixman-renderer.c
+++ b/src/pixman-renderer.c
@@ -291,8 +291,8 @@ repaint_region(struct weston_view *ev, struct weston_output *output,
transform_apply_viewport(&transform, ev->surface);
- fw = pixman_int_to_fixed(ev->surface->width);
- fh = pixman_int_to_fixed(ev->surface->height);
+ fw = pixman_int_to_fixed(ev->surface->width_from_buffer);
+ fh = pixman_int_to_fixed(ev->surface->height_from_buffer);
switch (vp->buffer.transform) {
case WL_OUTPUT_TRANSFORM_FLIPPED:
diff --git a/src/screen-share.c b/src/screen-share.c
index 5de20bed..6f60b81c 100644
--- a/src/screen-share.c
+++ b/src/screen-share.c
@@ -434,11 +434,12 @@ shared_output_get_shm_buffer(struct shared_output *so)
data = mmap(NULL, height * stride, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (data == MAP_FAILED) {
weston_log("mmap: %m");
- close(fd);
- return NULL;
+ goto out_close;
}
sb = zalloc(sizeof *sb);
+ if (!sb)
+ goto out_unmap;
sb->output = so;
wl_list_init(&sb->free_link);
@@ -457,14 +458,26 @@ shared_output_get_shm_buffer(struct shared_output *so)
wl_buffer_add_listener(sb->buffer, &buffer_listener, sb);
wl_shm_pool_destroy(pool);
close(fd);
+ fd = -1;
memset(data, 0, sb->size);
sb->pm_image =
pixman_image_create_bits(PIXMAN_a8r8g8b8, width, height,
(uint32_t *)data, stride);
+ if (!sb->pm_image)
+ goto out_pixman_error;
return sb;
+
+out_pixman_error:
+ pixman_region32_fini(&sb->damage);
+out_unmap:
+ munmap(data, height * stride);
+out_close:
+ if (fd != -1)
+ close(fd);
+ return NULL;
}
static void
@@ -992,10 +1005,6 @@ weston_output_share(struct weston_output *output,
}
if (pid == 0) {
- /* We don't want anything circular */
- unsetenv("WAYLAND_DISPLAY");
- unsetenv("WAYLAND_SOCKET");
-
/* do not give our signal mask to the new process */
sigfillset(&allsigs);
sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
diff --git a/src/screenshooter.c b/src/screenshooter.c
index 02146c89..369e9204 100644
--- a/src/screenshooter.c
+++ b/src/screenshooter.c
@@ -450,6 +450,17 @@ weston_recorder_frame_notify(struct wl_listener *listener, void *data)
}
static void
+weston_recorder_free(struct weston_recorder *recorder)
+{
+ if (recorder == NULL)
+ return;
+ free(recorder->rect);
+ free(recorder->tmpbuf);
+ free(recorder->frame);
+ free(recorder);
+}
+
+static void
weston_recorder_create(struct weston_output *output, const char *filename)
{
struct weston_compositor *compositor = output->compositor;
@@ -461,7 +472,6 @@ weston_recorder_create(struct weston_output *output, const char *filename)
do_yflip = !!(compositor->capabilities & WESTON_CAP_CAPTURE_YFLIP);
recorder = malloc(sizeof *recorder);
-
if (recorder == NULL) {
weston_log("%s: out of memory\n", __func__);
return;
@@ -476,6 +486,12 @@ weston_recorder_create(struct weston_output *output, const char *filename)
recorder->destroying = 0;
recorder->output = output;
+ if ((recorder->frame == NULL) || (recorder->rect == NULL)) {
+ weston_log("%s: out of memory\n", __func__);
+ weston_recorder_free(recorder);
+ return;
+ }
+
if (do_yflip)
recorder->tmpbuf = NULL;
else
@@ -493,10 +509,7 @@ weston_recorder_create(struct weston_output *output, const char *filename)
break;
default:
weston_log("unknown recorder format\n");
- free(recorder->rect);
- free(recorder->tmpbuf);
- free(recorder->frame);
- free(recorder);
+ weston_recorder_free(recorder);
return;
}
@@ -505,10 +518,7 @@ weston_recorder_create(struct weston_output *output, const char *filename)
if (recorder->fd < 0) {
weston_log("problem opening output file %s: %m\n", filename);
- free(recorder->rect);
- free(recorder->tmpbuf);
- free(recorder->frame);
- free(recorder);
+ weston_recorder_free(recorder);
return;
}
@@ -527,11 +537,8 @@ weston_recorder_destroy(struct weston_recorder *recorder)
{
wl_list_remove(&recorder->frame_listener.link);
close(recorder->fd);
- free(recorder->tmpbuf);
- free(recorder->frame);
- free(recorder->rect);
recorder->output->disable_planes--;
- free(recorder);
+ weston_recorder_free(recorder);
}
static void
diff --git a/src/udev-seat.c b/src/udev-seat.c
index 7e4330a3..8e7405d0 100644
--- a/src/udev-seat.c
+++ b/src/udev-seat.c
@@ -125,7 +125,7 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
wl_list_for_each(output, &c->output_list, link)
if (strcmp(output->name, device->output_name) == 0)
evdev_device_set_output(device, output);
- } else if (device->output == NULL) {
+ } else if (device->output == NULL && !wl_list_empty(&c->output_list)) {
output = container_of(c->output_list.next,
struct weston_output, link);
evdev_device_set_output(device, output);
@@ -357,12 +357,15 @@ notify_output_create(struct wl_listener *listener, void *data)
struct evdev_device *device;
struct weston_output *output = data;
- wl_list_for_each(device, &seat->devices_list, link)
+ wl_list_for_each(device, &seat->devices_list, link) {
if (device->output_name &&
strcmp(output->name, device->output_name) == 0) {
evdev_device_set_output(device, output);
- break;
}
+
+ if (device->output_name == NULL && device->output == NULL)
+ evdev_device_set_output(device, output);
+ }
}
static struct udev_seat *
@@ -372,9 +375,9 @@ udev_seat_create(struct udev_input *input, const char *seat_name)
struct udev_seat *seat;
seat = zalloc(sizeof *seat);
-
if (!seat)
return NULL;
+
weston_seat_init(&seat->base, c, seat_name);
seat->base.led_update = drm_led_update;
diff --git a/tests/.gitignore b/tests/.gitignore
index 67b722d1..25e7344f 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1,3 +1,9 @@
-wcap-decode
-wcap-snapshot
-
+*.log
+*.test
+*.trs
+*.weston
+logs
+matrix-test
+setbacklight
+test-client
+test-text-client
diff --git a/tests/bad-buffer-test.c b/tests/bad-buffer-test.c
index 6eae313e..86e0299b 100644
--- a/tests/bad-buffer-test.c
+++ b/tests/bad-buffer-test.c
@@ -25,6 +25,8 @@
#include <unistd.h>
#include <sys/types.h>
+#include <stdio.h>
+#include <signal.h>
#include "../shared/os-compatibility.h"
#include "weston-test-client-helper.h"
@@ -58,12 +60,34 @@ 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)
{
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);
@@ -71,6 +95,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);
diff --git a/xwayland/launcher.c b/xwayland/launcher.c
index f0a87f5b..70703a4b 100644
--- a/xwayland/launcher.c
+++ b/xwayland/launcher.c
@@ -213,8 +213,7 @@ bind_to_abstract_socket(int display)
"%c/tmp/.X11-unix/X%d", 0, display);
size = offsetof(struct sockaddr_un, sun_path) + name_size;
if (bind(fd, (struct sockaddr *) &addr, size) < 0) {
- weston_log("failed to bind to @%s: %s\n",
- addr.sun_path + 1, strerror(errno));
+ weston_log("failed to bind to @%s: %m\n", addr.sun_path + 1);
close(fd);
return -1;
}
@@ -244,8 +243,7 @@ bind_to_unix_socket(int display)
size = offsetof(struct sockaddr_un, sun_path) + name_size;
unlink(addr.sun_path);
if (bind(fd, (struct sockaddr *) &addr, size) < 0) {
- weston_log("failed to bind to %s (%s)\n",
- addr.sun_path, strerror(errno));
+ weston_log("failed to bind to %s: %m\n", addr.sun_path);
close(fd);
return -1;
}
@@ -350,6 +348,8 @@ module_init(struct weston_compositor *compositor,
char lockfile[256], display_name[8];
wxs = zalloc(sizeof *wxs);
+ if (wxs == NULL)
+ return -1;
wxs->process.cleanup = weston_xserver_cleanup;
wxs->wl_display = display;
wxs->compositor = compositor;
diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c
index 699bade5..2fb65b1a 100644
--- a/xwayland/window-manager.c
+++ b/xwayland/window-manager.c
@@ -944,7 +944,8 @@ weston_wm_window_draw_decoration(void *data)
cairo_t *cr;
int x, y, width, height;
int32_t input_x, input_y, input_w, input_h;
-
+ struct weston_shell_interface *shell_interface =
+ &wm->server->compositor->shell_interface;
uint32_t flags = 0;
weston_wm_window_read_properties(window);
@@ -1006,6 +1007,12 @@ 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);
}
}
@@ -1199,6 +1206,26 @@ weston_wm_pick_seat(struct weston_wm *wm)
struct weston_seat, link);
}
+static struct weston_seat *
+weston_wm_pick_seat_for_window(struct weston_wm_window *window)
+{
+ struct weston_wm *wm = window->wm;
+ struct weston_seat *seat, *s;
+
+ seat = NULL;
+ wl_list_for_each(s, &wm->server->compositor->seat_list, link) {
+ if (s->pointer != NULL &&
+ s->pointer->focus == window->view &&
+ s->pointer->button_count > 0 &&
+ (seat == NULL ||
+ s->pointer->grab_serial -
+ seat->pointer->grab_serial < (1 << 30)))
+ seat = s;
+ }
+
+ return seat;
+}
+
static void
weston_wm_window_handle_moveresize(struct weston_wm_window *window,
xcb_client_message_event_t *client_message)
@@ -1215,7 +1242,7 @@ weston_wm_window_handle_moveresize(struct weston_wm_window *window,
};
struct weston_wm *wm = window->wm;
- struct weston_seat *seat = weston_wm_pick_seat(wm);
+ struct weston_seat *seat = weston_wm_pick_seat_for_window(window);
int detail;
struct weston_shell_interface *shell_interface =
&wm->server->compositor->shell_interface;
@@ -1579,7 +1606,7 @@ weston_wm_handle_button(struct weston_wm *wm, xcb_generic_event_t *event)
xcb_button_press_event_t *button = (xcb_button_press_event_t *) event;
struct weston_shell_interface *shell_interface =
&wm->server->compositor->shell_interface;
- struct weston_seat *seat = weston_wm_pick_seat(wm);
+ struct weston_seat *seat;
struct weston_wm_window *window;
enum theme_location location;
enum frame_button_state button_state;
@@ -1596,10 +1623,19 @@ weston_wm_handle_button(struct weston_wm *wm, xcb_generic_event_t *event)
if (button->detail != 1 && button->detail != 2)
return;
+ seat = weston_wm_pick_seat_for_window(window);
+
button_state = button->response_type == XCB_BUTTON_PRESS ?
FRAME_BUTTON_PRESSED : FRAME_BUTTON_RELEASED;
button_id = button->detail == 1 ? BTN_LEFT : BTN_RIGHT;
+ /* Make sure we're looking at the right location. The frame
+ * could have received a motion event from a pointer from a
+ * different wl_seat, but under X it looks like our core
+ * pointer moved. Move the frame pointer to the button press
+ * location before deciding what to do. */
+ location = frame_pointer_motion(window->frame, NULL,
+ button->event_x, button->event_y);
location = frame_pointer_button(window->frame, NULL,
button_id, button_state);
if (frame_status(window->frame) & FRAME_STATUS_REPAINT)
@@ -2139,8 +2175,7 @@ weston_wm_window_configure(void *data)
}
static void
-send_configure(struct weston_surface *surface,
- uint32_t edges, int32_t width, int32_t height)
+send_configure(struct weston_surface *surface, int32_t width, int32_t height)
{
struct weston_wm_window *window = get_wm_window(surface);
struct weston_wm *wm = window->wm;