From 6c66568af99c8e7717c5f50b1de0e58a2e66cd14 Mon Sep 17 00:00:00 2001 From: mallum Date: Wed, 27 Apr 2005 18:11:19 +0000 Subject: [PATCH] Make keyboard intelligently handle layout on screen orientation and rotation git-svn-id: https://svn.o-hand.com/repos/matchbox/trunk/matchbox-keyboard@1132 b067294f-1dea-0310-9683-c47a78595994 --- ChangeLog | 25 +++++ layouts/keyboard.xml | 59 +++++++++++ src/config-parser.c | 6 ++ src/matchbox-keyboard-key.c | 13 +++ src/matchbox-keyboard-row.c | 46 +++++--- src/matchbox-keyboard-ui.c | 204 +++++++++++++++++++++++++++--------- src/matchbox-keyboard.c | 21 +++- src/matchbox-keyboard.h | 20 ++++ 8 files changed, 323 insertions(+), 71 deletions(-) diff --git a/ChangeLog b/ChangeLog index 75fa9e1..07048dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2005-04-27 mallum,,, + + + * layouts/keyboard.xml: + New layout with extended keys. + + * src/config-parser.c: (config_handle_key_tag): + * src/matchbox-keyboard-key.c: (mb_kbd_key_get_extra_width_pad): + * src/matchbox-keyboard-row.c: (mb_kbd_row_height), + (mb_kbd_row_width), (mb_kbd_row_base_width): + * src/matchbox-keyboard-ui.c: (get_desktop_area), + (mb_kbd_ui_send_keysym_press), (mb_kbd_ui_send_release), + (mb_kdb_ui_unit_key_size), (mb_kbd_ui_min_key_size), + (mb_kbd_ui_allocate_ui_layout), (mb_kbd_ui_redraw_key), + (mb_kbd_ui_redraw_row), (mb_kbd_ui_resources_create), + (mb_kbd_ui_resize), (mb_kbd_ui_handle_configure), + (mb_kbd_ui_events_iteration), (mb_kbd_ui_load_font), + (mb_kbd_ui_init), (mb_kbd_ui_display_width), + (mb_kbd_ui_display_height), (mb_kbd_ui_realize): + * src/matchbox-keyboard.c: (mb_kbd_locate_key), + (mb_kbd_get_held_key): + * src/matchbox-keyboard.h: + Make keyboard 'adapt' with extended keys to screen rotation + and screen orientation. + 2005-04-26 mallum,,, * configure.ac: diff --git a/layouts/keyboard.xml b/layouts/keyboard.xml index ed28dd9..905d10a 100644 --- a/layouts/keyboard.xml +++ b/layouts/keyboard.xml @@ -26,6 +26,9 @@ --> + + + @@ -87,10 +90,24 @@ + + + + + + + + + + + + + + @@ -148,9 +165,22 @@ + + + + + + + + + + + + + @@ -202,10 +232,20 @@ + + + + + + + + + + @@ -263,10 +303,21 @@ + + + + + + + + + + + @@ -302,6 +353,14 @@ + + + + + + + + diff --git a/src/config-parser.c b/src/config-parser.c index eee2996..fa1a9eb 100644 --- a/src/config-parser.c +++ b/src/config-parser.c @@ -445,6 +445,12 @@ config_handle_key_tag(MBKeyboardConfigState *state, const char **attr) mb_kbd_key_set_obey_caps(state->current_key, True); } + if ((val = attr_get_val("extended", attr)) != NULL) + { + if (strcaseeq(val, "true")) + mb_kbd_key_set_extended(state->current_key, True); + } + if ((val = attr_get_val("width", attr)) != NULL) { if (atoi(val) > 0) diff --git a/src/matchbox-keyboard-key.c b/src/matchbox-keyboard-key.c index 235008f..5f92251 100644 --- a/src/matchbox-keyboard-key.c +++ b/src/matchbox-keyboard-key.c @@ -51,6 +51,7 @@ struct MBKeyboardKey boolean fill; /* width fills avialble space */ int req_uwidth; /* unit width in 1/1000's */ boolean is_blank; /* 'blank' keys are spacers */ + boolean extended; /* only show in landscape */ MBKeyboardStateType sets_kbdstate; /* needed */ }; @@ -211,6 +212,18 @@ mb_kbd_key_get_extra_width_pad(MBKeyboardKey *key) return key->extra_width_pad; } +void +mb_kbd_key_set_extended(MBKeyboardKey *key, boolean extend) +{ + key->extended = extend; +} + +boolean +mb_kbd_key_get_extended(MBKeyboardKey *key) +{ + return key->extended; +} + /* URG Nasty - some stuf should be public-ish */ void diff --git a/src/matchbox-keyboard-row.c b/src/matchbox-keyboard-row.c index 18ff903..bc9e31e 100644 --- a/src/matchbox-keyboard-row.c +++ b/src/matchbox-keyboard-row.c @@ -39,21 +39,31 @@ mb_kbd_row_x (MBKeyboardRow *row) int mb_kbd_row_y(MBKeyboardRow *row) -{ +{ return row->alloc_y; } int mb_kbd_row_height(MBKeyboardRow *row) { - List *key_item = mb_kdb_row_keys(row); - MBKeyboardKey *key; + List *key_item; - /* XX this is a little crazed */ + /* XX this is a little crazed + * We avoid keys with 0 height - spacers or non allocated extended ones + */ + + mb_kbd_row_for_each_key(row, key_item) + { + if (!mb_kbd_is_extended(row->kbd) + && mb_kbd_key_get_extended(key_item->data)) + continue; - key = key_item->data; - return mb_kbd_key_height(key); + if (mb_kbd_key_height(key_item->data) > 0) + return mb_kbd_key_height(key_item->data); + } + + return 0; } int @@ -66,15 +76,16 @@ mb_kbd_row_width(MBKeyboardRow *row) result = mb_kbd_col_spacing(row->kbd); - key_item = mb_kdb_row_keys(row); - - while (key_item != NULL) - { + + mb_kbd_row_for_each_key(row, key_item) + { MBKeyboardKey *key = key_item->data; - result += (mb_kbd_key_width(key) + mb_kbd_col_spacing(row->kbd)); + if (!mb_kbd_is_extended(row->kbd) + && mb_kbd_key_get_extended(key)) + continue; - key_item = util_list_next(key_item); + result += (mb_kbd_key_width(key) + mb_kbd_col_spacing(row->kbd)); } return result; @@ -88,17 +99,18 @@ mb_kbd_row_base_width(MBKeyboardRow *row) result = mb_kbd_col_spacing(row->kbd); - key_item = mb_kdb_row_keys(row); - - while (key_item != NULL) + mb_kbd_row_for_each_key(row, key_item) { MBKeyboardKey *key = key_item->data; + if (!mb_kbd_is_extended(row->kbd) + && mb_kbd_key_get_extended(key)) + continue; + result += (mb_kbd_key_width(key) + mb_kbd_col_spacing(row->kbd) - mb_kbd_key_get_extra_width_pad(key)); - - key_item = util_list_next(key_item); + } return result; diff --git a/src/matchbox-keyboard-ui.c b/src/matchbox-keyboard-ui.c index dbbc0f8..4b6c5c7 100644 --- a/src/matchbox-keyboard-ui.c +++ b/src/matchbox-keyboard-ui.c @@ -174,6 +174,31 @@ get_desktop_area(MBKeyboardUI *ui, int *x, int *y, int *width, int *height) return True; } +static void +update_display_size(MBKeyboardUI *ui) +{ + XWindowAttributes winattr; + + XGetWindowAttributes(ui->xdpy, ui->xwin_root, &winattr); + + /* XXX should actually trap an X error here */ + + ui->dpy_width = winattr.width; + ui->dpy_height = winattr.height; + + return; +} + +static boolean +want_extended(MBKeyboardUI *ui) +{ + /* Are we in portrait ? */ + if (ui->dpy_width > ui->dpy_height) + return True; + + return False; +} + void mb_kbd_ui_send_press(MBKeyboardUI *ui, const unsigned char *utf8_char_in, @@ -212,12 +237,14 @@ mb_kdb_ui_unit_key_size(MBKeyboardUI *ui, int *width, int *height) while (row_item != NULL) { - key_item = mb_kdb_row_keys((MBKeyboardRow *)row_item->data); - - while (key_item != NULL) + mb_kbd_row_for_each_key(row_item->data, key_item) { MBKeyboardKey *key = key_item->data; + if (!mb_kbd_is_extended(ui->kbd) + && mb_kbd_key_get_extended(key)) + continue; + mb_kdb_key_foreach_state(key, state) { if (mb_kbd_key_get_face_type(key, state) == MBKeyboardKeyFaceGlyph) @@ -239,7 +266,6 @@ mb_kdb_ui_unit_key_size(MBKeyboardUI *ui, int *width, int *height) /* XXX TODO, also need to check height of image keys etc */ } - key_item = util_list_next(key_item); } row_item = util_list_next(row_item); } @@ -309,17 +335,22 @@ mb_kbd_ui_allocate_ui_layout(MBKeyboardUI *ui, { MBKeyboardRow *row = row_item->data; - key_item = mb_kdb_row_keys(row); - key_x = mb_kbd_col_spacing(ui->kbd); max_row_key_height = 0; - while (key_item != NULL) + mb_kbd_row_for_each_key(row, key_item) { int key_w, key_h; MBKeyboardKey *key = key_item->data; + mb_kbd_key_set_extra_height_pad(key, 0); + mb_kbd_key_set_extra_width_pad(key, 0); + mb_kbd_key_set_geometry(key, 0, 0, 0, 0); + + if (!mb_kbd_is_extended(ui->kbd) && mb_kbd_key_get_extended(key)) + continue; + mb_kbd_ui_min_key_size(ui, key, &key_w, &key_h); if (!mb_kbd_key_get_req_uwidth(key) @@ -343,15 +374,14 @@ mb_kbd_ui_allocate_ui_layout(MBKeyboardUI *ui, max_row_key_height = key_h; mb_kbd_key_set_geometry(key, key_x, key_y, key_w, key_h); - - key_item = util_list_next(key_item); - + key_x += (mb_kbd_col_spacing(ui->kbd) + key_w); } if (key_x > max_row_width) /* key_x now represents row width */ max_row_width = key_x; + mb_kbd_row_set_y(row, row_y); row_y += max_row_key_height + mb_kbd_row_spacing(ui->kbd); @@ -372,25 +402,27 @@ mb_kbd_ui_allocate_ui_layout(MBKeyboardUI *ui, MBKeyboardRow *row = row_item->data; int n_fillers = 0, free_space = 0, new_w = 0; - key_item = mb_kdb_row_keys(row); - - while (key_item != NULL) + mb_kbd_row_for_each_key(row,key_item) { + if (!mb_kbd_is_extended(ui->kbd) + && mb_kbd_key_get_extended(key_item->data)) + continue; + if (mb_kbd_key_get_fill(key_item->data)) n_fillers++; - - key_item = util_list_next(key_item); } if (!n_fillers) goto next_row; - key_item = mb_kdb_row_keys(row); - free_space = max_row_width - mb_kbd_row_width(row); - while (key_item != NULL) + mb_kbd_row_for_each_key(row, key_item) { + if (!mb_kbd_is_extended(ui->kbd) + && mb_kbd_key_get_extended(key_item->data)) + continue; + if (mb_kbd_key_get_fill(key_item->data)) { int old_w; @@ -402,18 +434,23 @@ mb_kbd_ui_allocate_ui_layout(MBKeyboardUI *ui, mb_kbd_key_set_geometry(key_item->data, -1, -1, new_w, -1); /* nudge next keys forward */ - while (nudge_key_item) + + for (; + nudge_key_item != NULL; + nudge_key_item = util_list_next(nudge_key_item)) { + if (!mb_kbd_is_extended(ui->kbd) + && mb_kbd_key_get_extended(nudge_key_item->data)) + continue; + mb_kbd_key_set_geometry(nudge_key_item->data, mb_kbd_key_x(nudge_key_item->data) + (new_w - old_w ), -1, -1, -1); - nudge_key_item = util_list_next(nudge_key_item); + } } - key_item = util_list_next(key_item); - } + } next_row: - row_item = util_list_next(row_item); } @@ -583,13 +620,13 @@ mb_kbd_ui_redraw_row(MBKeyboardUI *ui, MBKeyboardRow *row) { List *key_item; - key_item = mb_kdb_row_keys(row); - - while (key_item != NULL) + mb_kbd_row_for_each_key(row,key_item) { - mb_kbd_ui_redraw_key(ui, key_item->data); + if (!mb_kbd_is_extended(ui->kbd) + && mb_kbd_key_get_extended(key_item->data)) + continue; - key_item = util_list_next(key_item); + mb_kbd_ui_redraw_key(ui, key_item->data); } } @@ -786,7 +823,7 @@ mb_kbd_ui_resources_create(MBKeyboardUI *ui) XChangeProperty(ui->xdpy, ui->xwin, atom_NET_WM_STATE, XA_ATOM, 32, PropModeReplace, - (unsigned char **)&states, 1); + (unsigned char **)states, 1); if (get_desktop_area(ui, NULL, NULL, &desk_width, NULL)) { @@ -852,6 +889,11 @@ mb_kbd_ui_resources_create(MBKeyboardUI *ui) alloc_color(ui, &ui->xcol_f8f8f5, "#f8f8f5"); alloc_color(ui, &ui->xcol_f4f4f4, "#f4f4f4"); alloc_color(ui, &ui->xcol_a4a4a4, "#a4a4a4"); + + /* Get root size change events for rotation */ + + /* XSelectInput(ui->xdpy, ui->xwin_root, StructureNotifyMask); */ + return 1; } @@ -922,7 +964,6 @@ mb_kbd_ui_resize(MBKeyboardUI *ui, int width, int height) next_key_x = mb_kbd_col_spacing(ui->kbd); - /* * row_base_width * -------------- X new_width = new_base_width @@ -933,15 +974,14 @@ mb_kbd_ui_resize(MBKeyboardUI *ui, int width, int height) * row_base_width */ - key_item = mb_kdb_row_keys(row_item->data); - - MARK(); - - while (key_item != NULL) + mb_kbd_row_for_each_key(row_item->data, key_item) { MBKeyboardKey *key = key_item->data; int key_base_width, key_new_pad; + if (!mb_kbd_is_extended(kbd) && mb_kbd_key_get_extended(key)) + continue; + key_base_width =( mb_kbd_key_width(key) - mb_kbd_key_get_extra_width_pad(key)); @@ -959,12 +999,8 @@ mb_kbd_ui_resize(MBKeyboardUI *ui, int width, int height) if (mb_kbd_key_get_fill(key)) n_fillers++; - - key_item = util_list_next(key_item); } - key_item = mb_kdb_row_keys(row_item->data); - /* The above ( likely due to rounding ) leaves a few pixels free. * This can be critical on a small handheld display. Therefore * we do a second parse deviding up any left over space between @@ -973,12 +1009,14 @@ mb_kbd_ui_resize(MBKeyboardUI *ui, int width, int height) if (n_fillers) { - key_item = mb_kdb_row_keys(row_item->data); - free_space = width - mb_kbd_row_width(row_item->data); - while (key_item != NULL) + mb_kbd_row_for_each_key(row_item->data, key_item) { + if (!mb_kbd_is_extended(kbd) + && mb_kbd_key_get_extended(key_item->data)) + continue; + if (mb_kbd_key_get_fill(key_item->data)) { int old_w; @@ -990,14 +1028,20 @@ mb_kbd_ui_resize(MBKeyboardUI *ui, int width, int height) mb_kbd_key_set_geometry(key_item->data, -1, -1, new_w, -1); /* nudge next keys forward */ - while (nudge_key_item) + + for (; + nudge_key_item != NULL; + nudge_key_item = util_list_next(nudge_key_item)) { + if (!mb_kbd_is_extended(ui->kbd) + && mb_kbd_key_get_extended(nudge_key_item->data)) + continue; + mb_kbd_key_set_geometry(nudge_key_item->data, mb_kbd_key_x(nudge_key_item->data) + (new_w - old_w ), -1, -1, -1); - nudge_key_item = util_list_next(nudge_key_item); } } - key_item = util_list_next(key_item); + } } @@ -1011,7 +1055,11 @@ mb_kbd_ui_resize(MBKeyboardUI *ui, int width, int height) mb_kbd_row_set_y(row_item->data, next_row_y); - DBG("************ setting row y to %i ***********", next_row_y); + DBG("************ setting row y to %i , next is %i, %i***********", + next_row_y, + mb_kbd_row_height(row_item->data) + ,mb_kbd_row_spacing(ui->kbd) + ); next_row_y += (mb_kbd_row_height(row_item->data) + mb_kbd_row_spacing(ui->kbd)); @@ -1041,6 +1089,56 @@ mb_kbd_ui_resize(MBKeyboardUI *ui, int width, int height) } } +void +mb_kbd_ui_handle_configure(MBKeyboardUI *ui, + int width, + int height) +{ + boolean old_state, new_state; + int desk_width; + + MARK(); + + /* Figure out if screen size has changed - does a round trip - bad */ + + update_display_size(ui); + + old_state = mb_kbd_is_extended(ui->kbd); + new_state = want_extended(ui); + + if (new_state == old_state) /* Not a rotation */ + { + mb_kbd_ui_resize(ui, width, height); + return; + } + + mb_kbd_set_extended(ui->kbd, new_state); + + /* realocate the layout */ + + mb_kbd_ui_allocate_ui_layout(ui, + &ui->base_alloc_width, &ui->base_alloc_height); + + mb_kbd_ui_resize(ui, width, height); + + /* + ui->xwin_width = ui->base_alloc_width; + ui->xwin_height = ui->base_alloc_height; + */ + + /* + if (get_desktop_area(ui, NULL, NULL, &desk_width, NULL)) + { + if (desk_width != ui->xwin_width) + { + mb_kbd_ui_resize(ui, + desk_width, + ( desk_width * ui->xwin_height ) / ui->xwin_width); + } + } + */ +} + int mb_kbd_ui_events_iteration(MBKeyboardUI *ui) { @@ -1066,13 +1164,12 @@ mb_kbd_ui_events_iteration(MBKeyboardUI *ui) case ButtonRelease: mb_kbd_key_release(ui->kbd); break; - case ConfigureNotify: if (xev.xconfigure.width != ui->xwin_width || xev.xconfigure.height != ui->xwin_height) - mb_kbd_ui_resize(ui, - xev.xconfigure.width, - xev.xconfigure.height); + mb_kbd_ui_handle_configure(ui, + xev.xconfigure.width, + xev.xconfigure.height); break; default: break; @@ -1116,9 +1213,12 @@ mb_kbd_ui_init(MBKeyboard *kbd) ui->xscreen = DefaultScreen(ui->xdpy); ui->xwin_root = RootWindow(ui->xdpy, ui->xscreen); + /* ui->dpy_width = DisplayWidth(ui->xdpy, ui->xscreen); ui->dpy_height = DisplayHeight(ui->xdpy, ui->xscreen); + */ + update_display_size(ui); return 1; } @@ -1143,6 +1243,10 @@ mb_kbd_ui_realize(MBKeyboardUI *ui) if (!mb_kbd_ui_load_font(ui)) return 0; + /* potrait or landscape */ + if (want_extended(ui)) + mb_kbd_set_extended(ui->kbd, True); + mb_kbd_ui_allocate_ui_layout(ui, &ui->base_alloc_width, &ui->base_alloc_height); diff --git a/src/matchbox-keyboard.c b/src/matchbox-keyboard.c index 2777247..89ba86b 100644 --- a/src/matchbox-keyboard.c +++ b/src/matchbox-keyboard.c @@ -159,18 +159,19 @@ mb_kbd_locate_key(MBKeyboard *kb, int x, int y) && y >= mb_kbd_row_y(row) && y <= mb_kbd_row_y(row) + mb_kbd_row_height(row) ) { - key_item = mb_kdb_row_keys(row); - - while (key_item != NULL) + mb_kbd_row_for_each_key(row, key_item) { MBKeyboardKey *key = key_item->data; + if (!mb_kbd_is_extended(kb) + && mb_kbd_key_get_extended(key)) + continue; + if (!mb_kbd_key_is_blank(key) && x >= mb_kbd_key_abs_x(key) && x <= mb_kbd_key_abs_x(key) + mb_kbd_key_width(key)) return key; - key_item = util_list_next(key_item); } return NULL; @@ -205,6 +206,18 @@ mb_kbd_get_held_key(MBKeyboard *kb) return kb->held_key; } +void +mb_kbd_set_extended(MBKeyboard *kb, boolean extend) +{ + kb->extended = extend; +} + +boolean +mb_kbd_is_extended(MBKeyboard *kb) +{ + return kb->extended; +} + void mb_kbd_run(MBKeyboard *kb) diff --git a/src/matchbox-keyboard.h b/src/matchbox-keyboard.h index 9d88953..ca64085 100644 --- a/src/matchbox-keyboard.h +++ b/src/matchbox-keyboard.h @@ -127,6 +127,8 @@ struct MBKeyboard int key_border, key_pad, key_margin; int row_spacing, col_spacing; + boolean extended; /* are we showing extended keys ? */ + MBKeyboardKey *held_key; MBKeyboardStateType keys_state; }; @@ -203,6 +205,12 @@ mb_kbd_remove_state(MBKeyboard *kbd, MBKeyboardStateType state); MBKeyboardKeyStateType mb_kbd_keys_current_state(MBKeyboard *kbd); +void +mb_kbd_set_extended(MBKeyboard *kb, boolean extend); + +boolean +mb_kbd_is_extended(MBKeyboard *kb); + void mb_kbd_add_layout(MBKeyboard *kb, MBKeyboardLayout *layout); @@ -270,6 +278,12 @@ mb_kbd_row_append_key(MBKeyboardRow *row, MBKeyboardKey *key); List* mb_kdb_row_keys(MBKeyboardRow *row); +#define mb_kbd_row_for_each_key(r,k) \ + for ((k) = mb_kdb_row_keys((r)); \ + (k) != NULL; \ + (k) = util_list_next((k))) + + /**** Keys ******/ MBKeyboardKey* @@ -326,6 +340,12 @@ mb_kbd_key_width(MBKeyboardKey *key) ; int mb_kbd_key_height(MBKeyboardKey *key); +void +mb_kbd_key_set_extended(MBKeyboardKey *key, boolean extend); + +boolean +mb_kbd_key_get_extended(MBKeyboardKey *key); + void mb_kbd_key_set_extra_width_pad(MBKeyboardKey *key, int pad);