From e2102cdbffd64fb0f383b2b60008d5353bbbe8d4 Mon Sep 17 00:00:00 2001 From: Nobuhiko Tanibata Date: Tue, 6 May 2014 13:37:53 +0900 Subject: weston 1.4.92 --- clients/desktop-shell.c | 7 +- clients/editor.c | 103 +++++++-- clients/keyboard.c | 280 +++++++++++++---------- clients/terminal.c | 12 +- clients/weston-info.c | 2 +- clients/window.c | 57 +++-- configure.ac | 2 +- desktop-shell/exposay.c | 8 +- desktop-shell/input-panel.c | 61 +++-- desktop-shell/shell.c | 505 +++++++++++++++++++++++++++--------------- desktop-shell/shell.h | 14 +- protocol/fullscreen-shell.xml | 2 +- shared/cairo-util.c | 15 +- src/animation.c | 62 +++--- src/compositor-drm.c | 20 +- src/compositor-wayland.c | 6 + src/compositor.c | 39 ++-- src/compositor.h | 17 +- src/data-device.c | 6 + src/evdev.c | 26 ++- src/gl-renderer.h | 5 +- src/input.c | 19 ++ src/launcher-util.c | 5 + src/libinput-device.c | 26 ++- src/libinput-seat.c | 27 ++- src/pixman-renderer.c | 4 +- src/screen-share.c | 21 +- src/screenshooter.c | 33 +-- src/udev-seat.c | 11 +- tests/.gitignore | 12 +- tests/bad-buffer-test.c | 30 +++ xwayland/launcher.c | 8 +- xwayland/window-manager.c | 45 +++- 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); @@ -4486,6 +4500,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) { @@ -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,10 +43,53 @@ 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) { @@ -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 @@ -1379,6 +1412,11 @@ touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time, weston_compositor_schedule_repaint(es->compositor); } +static void +touch_move_grab_frame(struct weston_touch_grab *grab) +{ +} + static void touch_move_grab_cancel(struct weston_touch_grab *grab) { @@ -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) @@ -1431,6 +1468,32 @@ 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) @@ -1438,16 +1501,15 @@ move_grab_motion(struct weston_pointer_grab *grab, uint32_t time, 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; @@ -1919,19 +1981,6 @@ handle_pointer_focus(struct wl_listener *listener, void *data) ping_handler(view->surface, serial); } -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) { @@ -1969,32 +2018,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) { @@ -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); } @@ -2028,6 +2051,16 @@ set_title(struct shell_surface *shsurf, const char *title) shsurf->title = strdup(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 @@ -4474,6 +4590,19 @@ touch_to_activate_binding(struct weston_seat *seat, uint32_t time, void *data) activate_binding(seat, data, seat->touch->focus->surface); } +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) { @@ -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); @@ -221,6 +219,13 @@ weston_view_animation_run(struct weston_view *view, return animation; } +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) { @@ -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 @@ -496,6 +496,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) { @@ -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 @@ -286,6 +286,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 @@ -449,6 +449,17 @@ weston_recorder_frame_notify(struct wl_listener *listener, void *data) weston_recorder_destroy(recorder); } +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) { @@ -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 #include +#include +#include #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; -- cgit v1.2.1