Merge branch 'feature/vkbd_design' into 'main'

Virtual Keyboard: Design Overhaul and Bug Fixes

See merge request wayland/weston!2043
This commit is contained in:
Joscha Wloch 2026-05-04 07:48:24 +00:00
commit af8958ee4f
4 changed files with 361 additions and 138 deletions

View file

@ -62,6 +62,8 @@ struct virtual_keyboard {
bool toplevel;
bool overlay;
struct zwp_input_panel_surface_v1 *ips;
struct weston_config *config;
};
enum key_type {
@ -76,7 +78,8 @@ enum key_type {
keytype_arrow_left,
keytype_arrow_right,
keytype_arrow_down,
keytype_style
keytype_style,
keytype_none,
};
struct key {
@ -101,126 +104,121 @@ struct layout {
};
static const struct key normal_keys[] = {
{ 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_none, "", "", "", 2},
{ keytype_default, "q", "Q", "1", 2},
{ keytype_default, "w", "W", "2", 2},
{ keytype_default, "e", "E", "3", 2},
{ keytype_default, "r", "R", "4", 2},
{ keytype_default, "t", "T", "5", 2},
{ keytype_default, "y", "Y", "6", 2},
{ keytype_default, "u", "U", "7", 2},
{ keytype_default, "i", "I", "8", 2},
{ keytype_default, "o", "O", "9", 2},
{ keytype_default, "p", "P", "0", 2},
{ 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_tab, "->|", "->|", "->|", 3},
{ keytype_default, "a", "A", "-", 2},
{ keytype_default, "s", "S", "@", 2},
{ keytype_default, "d", "D", "*", 2},
{ keytype_default, "f", "F", "^", 2},
{ keytype_default, "g", "G", ":", 2},
{ keytype_default, "h", "H", ";", 2},
{ keytype_default, "j", "J", "(", 2},
{ keytype_default, "k", "K", ")", 2},
{ keytype_default, "l", "L", "~", 2},
{ keytype_enter, "Enter", "Enter", "Enter", 3},
{ keytype_switch, "ABC", "abc", "ABC", 4},
{ keytype_default, "z", "Z", "/", 2},
{ keytype_default, "x", "X", "\'", 2},
{ keytype_default, "c", "C", "\"", 2},
{ keytype_default, "v", "V", "+", 2},
{ keytype_default, "b", "B", "=", 2},
{ keytype_default, "n", "N", "?", 2},
{ keytype_default, "m", "M", "!", 2},
{ keytype_default, ",", ",", "\\", 2},
{ keytype_default, ".", ".", "|", 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}
{ keytype_symbols, "?123", "?123", "abc", 2},
{ keytype_space, "", "", "", 10},
{ keytype_arrow_up, "/\\", "/\\", "/\\", 2},
{ keytype_arrow_left, "<", "<", "<", 2},
{ keytype_arrow_right, ">", ">", ">", 2},
{ keytype_arrow_down, "\\/", "\\/", "\\/", 2},
{ keytype_style, "", "", "", 4}
};
static const struct key numeric_keys[] = {
{ 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}
{ keytype_default, "7", "7", "7", 2},
{ keytype_default, "8", "8", "8", 2},
{ keytype_default, "9", "9", "9", 2},
{ keytype_default, "4", "4", "4", 2},
{ keytype_default, "5", "5", "5", 2},
{ keytype_default, "6", "6", "6", 2},
{ keytype_default, "1", "1", "1", 2},
{ keytype_default, "2", "2", "2", 2},
{ keytype_default, "3", "3", "3", 2},
{ keytype_default, "0", "0", "0", 4},
{ keytype_default,".", ".", ".", 2},
{ keytype_enter, "Enter", "Enter", "Enter", 3},
{ keytype_backspace, "<--", "<--", "<--", 3},
};
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_backspace, "-->", "-->", "-->", 2},
{ keytype_default, "ض", "", "۱", 2},
{ keytype_default, "ص", "", "۲", 2},
{ keytype_default, "ث", "", "۳", 2},
{ keytype_default, "ق", "", "۴", 2},
{ keytype_default, "ف", "", "۵", 2},
{ keytype_default, "غ", "", "۶", 2},
{ keytype_default, "ع", "`", "۷", 2},
{ keytype_default, "ه", "٪", "۸", 2},
{ keytype_default, "خ", ">", "۹", 2},
{ keytype_default, "ح", "<", "۰", 2},
{ keytype_backspace, "-->", "-->", "-->", 4},
{ 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_tab, "->|", "->|", "->|", 2},
{ keytype_default, "ش", "", "", 2},
{ keytype_default, "س", "", "!", 2},
{ keytype_default, "ي", "[", "@", 2},
{ keytype_default, "ب", "]", "#", 2},
{ keytype_default, "ل", "", "$", 2},
{ keytype_default, "ا", "أ", "%", 2},
{ keytype_default, "ت", "-", "^", 2},
{ keytype_default, "ن", "x", "&", 2},
{ keytype_default, "م", "/", "*", 2},
{ keytype_default, "ك", ":", "_", 2},
{ keytype_default, "د", "\"", "+", 2},
{ keytype_enter, "Enter", "Enter", "Enter", 4},
{ 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_switch, "Shift", "Base", "Shift", 4},
{ keytype_default, "ئ", "~", ")", 2},
{ keytype_default, "ء", "°", "(", 2},
{ keytype_default, "ؤ", "{", "\"", 2},
{ keytype_default, "ر", "}", "\'", 2},
{ keytype_default, "ى", "", "؟", 2},
{ keytype_default, "ة", "'", "!", 2},
{ keytype_default, "و", ",", ";", 2},
{ keytype_default, "", ".", "\\", 2},
{ keytype_default, "ظ", "؟", "=", 2},
{ keytype_switch, "Shift", "Base", "Shift", 4},
{ keytype_symbols, "؟٣٢١", "؟٣٢١", "Base", 1},
{ keytype_default, "", "", "|", 1},
{ keytype_default, ",", "،", "،", 1},
{ keytype_space, "", "", "", 6},
{ keytype_default, ".", "ذ", "]", 1},
{ keytype_default, "ط", "", "[", 1},
{ keytype_style, "", "", "", 2}
{ keytype_symbols, "؟٣٢١", "؟٣٢١", "Base", 2},
{ keytype_default, "", "", "|", 2},
{ keytype_default, ",", "،", "،", 2},
{ keytype_space, "", "", "", 12},
{ keytype_default, ".", "ذ", "]", 2},
{ keytype_default, "ط", "", "[", 2},
{ keytype_style, "", "", "", 4}
};
static const struct layout normal_layout = {
normal_keys,
sizeof(normal_keys) / sizeof(*normal_keys),
12,
24,
4,
"en",
ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_LTR
@ -229,8 +227,8 @@ static const struct layout normal_layout = {
static const struct layout numeric_layout = {
numeric_keys,
sizeof(numeric_keys) / sizeof(*numeric_keys),
12,
2,
6,
5,
"en",
ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_LTR
};
@ -238,12 +236,19 @@ static const struct layout numeric_layout = {
static const struct layout arabic_layout = {
arabic_keys,
sizeof(arabic_keys) / sizeof(*arabic_keys),
13,
26,
4,
"ar",
ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_RTL
};
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define max_count MAX(MAX(sizeof(arabic_keys) / sizeof(*arabic_keys), sizeof(numeric_keys) / sizeof(*numeric_keys) ), sizeof(normal_keys) / sizeof(*normal_keys))
#define min_columns MIN(MIN(normal_layout.columns, numeric_layout.columns), arabic_layout.columns)
#define min_rows MIN(MIN(normal_layout.rows, numeric_layout.rows), arabic_layout.rows)
static const char *style_labels[] = {
"default",
"none",
@ -255,8 +260,8 @@ static const char *style_labels[] = {
"incorrect"
};
static const double key_width = 60;
static const double key_height = 50;
static const double key_width = 30;
static const double key_height = 60;
enum keyboard_state {
KEYBOARD_STATE_DEFAULT,
@ -270,6 +275,22 @@ struct keyboard {
struct widget *widget;
enum keyboard_state state;
uint32_t key_state[max_count];
int32_t key_touch_event_id[max_count];
uint32_t key_margin;
uint32_t key_radius;
uint32_t key_fg_color;
uint32_t key_bg_color;
uint32_t key_pressed_fg_color;
uint32_t key_pressed_bg_color;
uint32_t special_key_fg_color;
uint32_t special_key_bg_color;
uint32_t special_key_pressed_fg_color;
uint32_t special_key_pressed_bg_color;
uint32_t panel_fg_color;
uint32_t panel_bg_color;
};
static void __attribute__ ((format (printf, 1, 2)))
@ -284,6 +305,29 @@ dbg(const char *fmt, ...)
#endif
}
static void
set_hex_color(cairo_t *cr, uint32_t color)
{
cairo_set_source_rgba(cr,
((color >> 16) & 0xff) / 255.0,
((color >> 8) & 0xff) / 255.0,
((color >> 0) & 0xff) / 255.0,
((color >> 24) & 0xff) / 255.0);
}
static bool
contains_decimal_point(const char* str)
{
for (size_t i = 0; i < strlen(str); ++i)
{
if (str[i] == '.')
{
return true;
}
}
return false;
}
static const char *
label_from_key(struct keyboard *keyboard,
const struct key *key)
@ -291,6 +335,9 @@ label_from_key(struct keyboard *keyboard,
if (key->key_type == keytype_style)
return style_labels[keyboard->keyboard->preedit_style];
if (key->key_type == keytype_none)
return "";
switch(keyboard->state) {
case KEYBOARD_STATE_DEFAULT:
return key->label;
@ -303,26 +350,62 @@ label_from_key(struct keyboard *keyboard,
return "";
}
static void
rounded_rectangle_path(cairo_t *cr, double x, double y, double width, double height, double radius)
{
double degrees = M_PI / 180.0;
cairo_new_sub_path (cr);
cairo_arc (cr, x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees);
cairo_arc (cr, x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees);
cairo_arc (cr, x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees);
cairo_arc (cr, x + radius, y + radius, radius, 180 * degrees, 270 * degrees);
cairo_close_path (cr);
}
static void
draw_key(struct keyboard *keyboard,
const struct key *key,
uint32_t key_state,
cairo_t *cr,
unsigned int row,
unsigned int col)
{
const uint32_t margin = keyboard->key_margin;
const char *label;
cairo_text_extents_t extents;
uint32_t fg_color = keyboard->key_fg_color;
uint32_t bg_color = keyboard->key_bg_color;
if (key_state == WL_KEYBOARD_KEY_STATE_RELEASED) {
fg_color = (key->key_type == keytype_default ? keyboard->key_fg_color : keyboard->special_key_fg_color);
bg_color = (key->key_type == keytype_default ? keyboard->key_bg_color : keyboard->special_key_bg_color);
} else {
fg_color = (key->key_type == keytype_default ? keyboard->key_pressed_fg_color : keyboard->special_key_pressed_fg_color);
bg_color = (key->key_type == keytype_default ? keyboard->key_pressed_bg_color : keyboard->special_key_pressed_bg_color);
}
if (key->key_type == keytype_none)
return;
cairo_save(cr);
cairo_rectangle(cr,
col * key_width, row * key_height,
key->width * key_width, key_height);
cairo_clip(cr);
rounded_rectangle_path(cr,
col * key_width + margin, row * key_height + margin,
key->width * key_width - 2*margin, key_height - 2*margin,
key_width / 5);
/* Paint key background */
set_hex_color(cr, bg_color);
cairo_fill_preserve(cr);
/* Paint frame */
cairo_rectangle(cr,
col * key_width, row * key_height,
key->width * key_width, key_height);
set_hex_color(cr, fg_color);
cairo_set_line_width(cr, 3);
cairo_stroke(cr);
@ -377,21 +460,22 @@ redraw_handler(struct widget *widget, void *data)
cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
cairo_clip(cr);
cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(cr, 16);
cairo_translate(cr, allocation.x, allocation.y);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_set_source_rgba(cr, 1, 1, 1, 0.75);
cairo_rectangle(cr, 0, 0, layout->columns * key_width, layout->rows * key_height);
cairo_paint(cr);
set_hex_color(cr, keyboard->panel_bg_color);
cairo_fill_preserve(cr);
set_hex_color(cr, keyboard->panel_fg_color);
cairo_stroke(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
for (i = 0; i < layout->count; ++i) {
cairo_set_source_rgb(cr, 0, 0, 0);
draw_key(keyboard, &layout->keys[i], cr, row, col);
draw_key(keyboard, &layout->keys[i], keyboard->key_state[i], cr, row, col);
col += layout->keys[i].width;
if (col >= layout->columns) {
row += 1;
@ -486,6 +570,22 @@ prev_utf8_char(const char *s, const char *p)
return NULL;
}
static int utf8_char_size(const char* c)
{
if (c != NULL)
{
if ((*c & 0x80) == 0)
return 1;
if ((*c & 0xe0) == 0xc0)
return 2;
if ((*c & 0xf0) == 0xe0)
return 3;
if ((*c & 0xf8) == 0xf0)
return 4;
}
return 0;
}
static void
delete_before_cursor(struct virtual_keyboard *keyboard)
{
@ -506,8 +606,8 @@ delete_before_cursor(struct virtual_keyboard *keyboard)
end = keyboard->surrounding_text + keyboard->surrounding_cursor;
zwp_input_method_context_v1_delete_surrounding_text(keyboard->context,
start - keyboard->surrounding_text,
end - start);
(start - keyboard->surrounding_text) - keyboard->surrounding_cursor,
0);
zwp_input_method_context_v1_commit_string(keyboard->context,
keyboard->serial,
"");
@ -535,8 +635,13 @@ 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)
keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *key, uint32_t key_num, struct input *input, enum wl_pointer_button_state state)
{
if (keyboard->keyboard->context == NULL)
{
return;
}
const char *label = NULL;
switch(keyboard->state) {
@ -551,14 +656,27 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
break;
}
xkb_mod_mask_t mod_mask = keyboard->state == KEYBOARD_STATE_DEFAULT ? 0 : keyboard->keyboard->keysym.shift_mask;
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;
keyboard->key_state[key_num] = key_state;
switch (key->key_type) {
case keytype_default:
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
break;
// Check if content purpose is number
if ((((keyboard->keyboard->content_purpose == ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DIGITS) ||
(keyboard->keyboard->content_purpose == ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NUMBER)) &&
contains_decimal_point(label)) &&
(contains_decimal_point(keyboard->keyboard->surrounding_text) ||
contains_decimal_point(keyboard->keyboard->preedit_string)))
{
// Do not enter a second decimal point.
return;
}
keyboard->keyboard->preedit_string =
append(keyboard->keyboard->preedit_string,
label);
@ -571,7 +689,23 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
if (strlen(keyboard->keyboard->preedit_string) == 0) {
delete_before_cursor(keyboard->keyboard);
} else {
keyboard->keyboard->preedit_string[strlen(keyboard->keyboard->preedit_string) - 1] = '\0';
const size_t len = strlen(keyboard->keyboard->preedit_string);
const char *prev_utf8 = prev_utf8_char(keyboard->keyboard->preedit_string + (len - MIN(len, 4)),
keyboard->keyboard->preedit_string + strlen(keyboard->keyboard->preedit_string));
if (prev_utf8)
{
const int pref_utf8_offset = prev_utf8 - keyboard->keyboard->preedit_string;
if ((strlen(keyboard->keyboard->preedit_string + pref_utf8_offset) - utf8_char_size(prev_utf8)) == 0)
{
keyboard->keyboard->preedit_string[pref_utf8_offset] = '\0';
}
else
{
keyboard->keyboard->preedit_string[strlen(keyboard->keyboard->preedit_string) - 1] = '\0';
}
}
virtual_keyboard_send_preedit(keyboard->keyboard, -1);
}
break;
@ -594,14 +728,12 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
break;
switch(keyboard->state) {
case KEYBOARD_STATE_DEFAULT:
case KEYBOARD_STATE_SYMBOLS:
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:
@ -609,8 +741,6 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
break;
switch(keyboard->state) {
case KEYBOARD_STATE_DEFAULT:
keyboard->state = KEYBOARD_STATE_SYMBOLS;
break;
case KEYBOARD_STATE_UPPERCASE:
keyboard->state = KEYBOARD_STATE_SYMBOLS;
break;
@ -660,6 +790,8 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
keyboard->keyboard->preedit_style = (keyboard->keyboard->preedit_style + 1) % 8; /* TODO */
virtual_keyboard_send_preedit(keyboard->keyboard, -1);
break;
case keytype_none:
break;
}
}
@ -669,6 +801,10 @@ button_handler(struct widget *widget,
uint32_t button,
enum wl_pointer_button_state state, void *data)
{
if (button != BTN_LEFT) {
return;
}
struct keyboard *keyboard = data;
struct rectangle allocation;
int32_t x, y;
@ -678,10 +814,6 @@ button_handler(struct widget *widget,
layout = get_current_layout(keyboard->keyboard);
if (button != BTN_LEFT) {
return;
}
input_get_position(input, &x, &y);
widget_get_allocation(keyboard->widget, &allocation);
@ -689,11 +821,11 @@ button_handler(struct widget *widget,
y -= allocation.y;
row = y / key_height;
col = x / key_width + row * layout->columns;
col = x / (key_width + (row * layout->columns));
for (i = 0; i < layout->count; ++i) {
col -= layout->keys[i].width;
if (col < 0) {
keyboard_handle_key(keyboard, time, &layout->keys[i], input, state);
keyboard_handle_key(keyboard, time, &layout->keys[i], i, input, state);
break;
}
}
@ -702,7 +834,7 @@ button_handler(struct widget *widget,
}
static void
touch_handler(struct input *input, uint32_t time,
touch_handler(struct input *input, uint32_t time, int32_t id,
float x, float y, uint32_t state, void *data)
{
struct keyboard *keyboard = data;
@ -723,8 +855,9 @@ touch_handler(struct input *input, uint32_t time,
for (i = 0; i < layout->count; ++i) {
col -= layout->keys[i].width;
if (col < 0) {
keyboard->key_touch_event_id[i] = id;
keyboard_handle_key(keyboard, time,
&layout->keys[i], input, state);
&layout->keys[i], i, input, state);
break;
}
}
@ -737,7 +870,7 @@ touch_down_handler(struct widget *widget, struct input *input,
uint32_t serial, uint32_t time, int32_t id,
float x, float y, void *data)
{
touch_handler(input, time, x, y,
touch_handler(input, time, id, x, y,
WL_POINTER_BUTTON_STATE_PRESSED, data);
}
@ -746,11 +879,21 @@ touch_up_handler(struct widget *widget, struct input *input,
uint32_t serial, uint32_t time, int32_t id,
void *data)
{
float x, y;
struct keyboard *keyboard = data;
input_get_touch(input, id, &x, &y);
for (size_t i = 0; i < max_count; ++i)
{
if (id == keyboard->key_touch_event_id[i])
{
keyboard->key_touch_event_id[i] = -1;
keyboard->key_state[i] = WL_KEYBOARD_KEY_STATE_RELEASED;
}
}
touch_handler(input, time, x, y,
float x, y;
input_get_touch(input, id, &x, &y);
touch_handler(input, time, id, x, y,
WL_POINTER_BUTTON_STATE_RELEASED, data);
}
@ -791,8 +934,28 @@ handle_content_type(void *data,
{
struct virtual_keyboard *keyboard = data;
keyboard->content_hint = hint;
keyboard->content_purpose = purpose;
if ((keyboard->content_hint != hint) || (keyboard->content_purpose != purpose))
{
keyboard->content_hint = hint;
keyboard->content_purpose = purpose;
// A change of the content type means a new layout.
// So we have to update.
const struct layout *layout = get_current_layout(keyboard);
zwp_input_method_context_v1_language(context,
keyboard->serial,
layout->language);
zwp_input_method_context_v1_text_direction(context,
keyboard->serial,
layout->text_direction);
window_schedule_resize(keyboard->keyboard->window,
layout->columns * key_width,
layout->rows * key_height);
widget_schedule_redraw(keyboard->keyboard->widget);
}
}
static void
@ -1011,6 +1174,7 @@ keyboard_create(struct virtual_keyboard *virtual_keyboard)
window_set_appid(keyboard->window,
"org.freedesktop.weston.virtual-keyboard");
window_set_user_data(keyboard->window, keyboard);
window_set_min_allocation(keyboard->window, min_columns * (int32_t)key_width, min_rows * (int32_t)key_height);
widget_set_redraw_handler(keyboard->widget, redraw_handler);
widget_set_resize_handler(keyboard->widget, resize_handler);
@ -1043,6 +1207,45 @@ keyboard_destroy(struct virtual_keyboard *virtual_keyboard)
free(virtual_keyboard->keyboard);
}
static void
config_load(struct virtual_keyboard *virtual_keyboard)
{
struct weston_config_section *s;
const char *config_file;
config_file = weston_config_get_name_from_env();
virtual_keyboard->config = weston_config_parse(config_file);
s = weston_config_get_section(virtual_keyboard->config, "keyboard", NULL, NULL);
weston_config_section_get_uint(s, "key-margin", &virtual_keyboard->keyboard->key_margin, 0);
weston_config_section_get_uint(s, "key-radius", &virtual_keyboard->keyboard->key_radius, 0);
weston_config_section_get_color(s, "key-fg",
&virtual_keyboard->keyboard->key_fg_color, 0xcc000000);
weston_config_section_get_color(s, "key-bg",
&virtual_keyboard->keyboard->key_bg_color, 0xccffffff);
weston_config_section_get_color(s, "key-pressed-fg",
&virtual_keyboard->keyboard->key_pressed_fg_color, 0xcc000000);
weston_config_section_get_color(s, "key-pressed-bg",
&virtual_keyboard->keyboard->key_pressed_bg_color, 0xccffffff);
weston_config_section_get_color(s, "special-key-fg",
&virtual_keyboard->keyboard->special_key_fg_color, 0xcc000000);
weston_config_section_get_color(s, "special-key-bg",
&virtual_keyboard->keyboard->special_key_bg_color, 0xccffffff);
weston_config_section_get_color(s, "special-key-pressed-fg",
&virtual_keyboard->keyboard->special_key_pressed_fg_color, 0xcc000000);
weston_config_section_get_color(s, "special-key-pressed-bg",
&virtual_keyboard->keyboard->special_key_pressed_bg_color, 0xccffffff);
weston_config_section_get_color(s, "panel-bg",
&virtual_keyboard->keyboard->panel_bg_color, 0xccffffff);
weston_config_section_get_color(s, "panel-fg",
&virtual_keyboard->keyboard->panel_fg_color, 0xcc000000);
}
static void config_destroy(struct virtual_keyboard *virtual_keyboard)
{
weston_config_destroy(virtual_keyboard->config);
}
int
main(int argc, char *argv[])
{
@ -1067,10 +1270,13 @@ main(int argc, char *argv[])
keyboard_create(&virtual_keyboard);
config_load(&virtual_keyboard);
display_run(virtual_keyboard.display);
keyboard_destroy(&virtual_keyboard);
display_destroy(virtual_keyboard.display);
config_destroy(&virtual_keyboard);
return 0;
}

View file

@ -4871,6 +4871,12 @@ window_is_resizing(struct window *window)
return window->resizing;
}
void window_set_min_allocation(struct window *window, int32_t width, int32_t height)
{
window->min_allocation.width = width;
window->min_allocation.height = height;
}
void
window_set_minimized(struct window *window)
{

View file

@ -481,6 +481,9 @@ window_set_maximized(struct window *window, int maximized);
int
window_is_resizing(struct window *window);
void
window_set_min_allocation(struct window *window, int32_t width, int32_t height);
void
window_set_minimized(struct window *window);

View file

@ -191,7 +191,15 @@ input_panel_committed(struct weston_surface *surface,
return;
if (weston_surface_is_mapped(surface))
{
if (shell->showing_input_panels)
{
struct weston_coord_global pos;
if (!calc_input_panel_position(ip_surface, &pos))
weston_view_set_position(ip_surface->view, pos);
}
return;
}
weston_surface_map(surface);