diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index 9c98437a..7e7951c2 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -35,7 +35,6 @@ #include "eek-renderer.h" #include "eek-keyboard.h" #include "eek-section.h" -#include "eek-key.h" #include "src/symbol.h" #include "eek-gtk-keyboard.h" @@ -64,18 +63,16 @@ typedef struct _EekGtkKeyboardPrivate G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA) -static void on_key_pressed (EekKey *key, EekKeyboard *view, +static void on_button_pressed (struct squeek_button *button, EekKeyboard *view, EekGtkKeyboard *self); -static void on_key_released (EekKey *key, +static void on_button_released (struct squeek_button *button, EekKeyboard *view, EekGtkKeyboard *self); -static void render_pressed_key (GtkWidget *widget, EekKeyboard *view, - EekKey *key); -static void render_locked_key (GtkWidget *widget, - EekKeyboard *view, - EekKey *key); -static void render_released_key (GtkWidget *widget, - EekKey *key); +static void render_pressed_button (GtkWidget *widget, struct button_place *place); +static void render_locked_button (GtkWidget *widget, + struct button_place *place); +static void render_released_button (GtkWidget *widget, + struct squeek_button *button); static void eek_gtk_keyboard_real_realize (GtkWidget *self) @@ -117,15 +114,23 @@ eek_gtk_keyboard_real_draw (GtkWidget *self, EekKeyboard *view = priv->keyboard->views[priv->keyboard->level]; /* redraw pressed key */ - const GList *list = priv->keyboard->pressed_keys; + const GList *list = priv->keyboard->pressed_buttons; for (const GList *head = list; head; head = g_list_next (head)) { - render_pressed_key (self, view, head->data); + struct button_place place = eek_keyboard_get_button_by_state( + view, squeek_button_get_key(head->data) + ); + render_pressed_button (self, &place); } /* redraw locked key */ - list = priv->keyboard->locked_keys; + list = priv->keyboard->locked_buttons; for (const GList *head = list; head; head = g_list_next (head)) { - render_locked_key (self, view, ((EekModifierKey *)head->data)->key); + struct button_place place = eek_keyboard_get_button_by_state( + view, squeek_button_get_key( + ((EekModifierKey *)head->data)->button + ) + ); + render_locked_button (self, &place); } return FALSE; @@ -152,11 +157,11 @@ static void depress(EekGtkKeyboard *self, { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); EekKeyboard *view = level_keyboard_current(priv->keyboard); - EekKey *key = eek_renderer_find_key_by_position (priv->renderer, view, x, y); + struct squeek_button *button = eek_renderer_find_button_by_position (priv->renderer, view, x, y); - if (key) { - eek_keyboard_press_key(priv->keyboard, key, time); - on_key_pressed(key, view, self); + if (button) { + eek_keyboard_press_button(priv->keyboard, button, time); + on_button_pressed(button, view, self); } } @@ -164,32 +169,32 @@ static void drag(EekGtkKeyboard *self, gdouble x, gdouble y, guint32 time) { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); EekKeyboard *view = level_keyboard_current(priv->keyboard); - EekKey *key = eek_renderer_find_key_by_position (priv->renderer, view, x, y); + struct squeek_button *button = eek_renderer_find_button_by_position (priv->renderer, view, x, y); GList *list, *head; - list = g_list_copy(priv->keyboard->pressed_keys); + list = g_list_copy(priv->keyboard->pressed_buttons); - if (key) { + if (button) { gboolean found = FALSE; for (head = list; head; head = g_list_next (head)) { - if (head->data == key) { + if (head->data == button) { found = TRUE; } else { - eek_keyboard_release_key(priv->keyboard, EEK_KEY(head->data), time); - on_key_released(key, view, self); + eek_keyboard_release_button(priv->keyboard, head->data, time); + on_button_released(button, view, self); } } g_list_free (list); if (!found) { - eek_keyboard_press_key(priv->keyboard, key, time); - on_key_pressed(key, view, self); + eek_keyboard_press_button(priv->keyboard, button, time); + on_button_pressed(button, view, self); } } else { for (head = list; head; head = g_list_next (head)) { - eek_keyboard_release_key(priv->keyboard, EEK_KEY(head->data), time); - on_key_released(EEK_KEY(head->data), view, self); + eek_keyboard_release_button(priv->keyboard, button, time); + on_button_released(button, view, self); } g_list_free (list); } @@ -200,11 +205,11 @@ static void release(EekGtkKeyboard *self, guint32 time) { EekKeyboard *view = level_keyboard_current(priv->keyboard); - GList *list = g_list_copy(priv->keyboard->pressed_keys); + GList *list = g_list_copy(priv->keyboard->pressed_buttons); for (GList *head = list; head; head = g_list_next (head)) { - EekKey *key = EEK_KEY(head->data); - eek_keyboard_release_key(priv->keyboard, key, time); - on_key_released(key, view, self); + struct squeek_button *button = head->data; + eek_keyboard_release_button(priv->keyboard, button, time); + on_button_released(button, view, self); } g_list_free (list); } @@ -287,7 +292,7 @@ eek_gtk_keyboard_real_unmap (GtkWidget *self) elements, so that the default handler of EekKeyboard::key-released signal can remove elements from its internal copy */ - list = g_list_copy(priv->keyboard->pressed_keys); + list = g_list_copy(priv->keyboard->pressed_buttons); for (head = list; head; head = g_list_next (head)) { g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey released"); g_signal_emit_by_name (head->data, "released"); @@ -309,11 +314,11 @@ eek_gtk_keyboard_real_query_tooltip (GtkWidget *widget, EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); EekKeyboard *view = level_keyboard_current(priv->keyboard); - EekKey *key = eek_renderer_find_key_by_position (priv->renderer, + struct squeek_button *button = eek_renderer_find_button_by_position (priv->renderer, view, (gdouble)x, (gdouble)y); - if (key) { + if (button) { //struct squeek_symbol *symbol = eek_key_get_symbol_at_index(key, 0, priv->keyboard->level); const gchar *text = NULL; // FIXME if (text) { @@ -369,7 +374,7 @@ eek_gtk_keyboard_dispose (GObject *object) if (priv->keyboard) { GList *list, *head; - list = g_list_copy(priv->keyboard->pressed_keys); + list = g_list_copy(priv->keyboard->pressed_buttons); for (head = list; head; head = g_list_next (head)) { g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey pressed"); g_signal_emit_by_name (head->data, "released", level_keyboard_current(priv->keyboard)); @@ -452,9 +457,8 @@ eek_gtk_keyboard_new (LevelKeyboard *keyboard) } static void -render_pressed_key (GtkWidget *widget, - EekKeyboard *view, - EekKey *key) +render_pressed_button (GtkWidget *widget, + struct button_place *place) { EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); @@ -464,7 +468,7 @@ render_pressed_key (GtkWidget *widget, GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region); cairo_t *cr = gdk_drawing_context_get_cairo_context (context); - eek_renderer_render_key (priv->renderer, cr, view, key, 1.0, TRUE); + eek_renderer_render_button (priv->renderer, cr, place, 1.0, TRUE); /* eek_renderer_render_key (priv->renderer, cr, key, 1.5, TRUE); */ @@ -474,9 +478,7 @@ render_pressed_key (GtkWidget *widget, } static void -render_locked_key (GtkWidget *widget, - EekKeyboard *view, - EekKey *key) +render_locked_button (GtkWidget *widget, struct button_place *place) { EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); @@ -486,7 +488,7 @@ render_locked_key (GtkWidget *widget, GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region); cairo_t *cr = gdk_drawing_context_get_cairo_context (context); - eek_renderer_render_key (priv->renderer, cr, view, key, 1.0, TRUE); + eek_renderer_render_button (priv->renderer, cr, place, 1.0, TRUE); gdk_window_end_draw_frame (window, context); @@ -494,10 +496,10 @@ render_locked_key (GtkWidget *widget, } static void -render_released_key (GtkWidget *widget, - EekKey *key) +render_released_button (GtkWidget *widget, + struct squeek_button *button) { - (void)key; + (void)button; EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); @@ -514,7 +516,7 @@ render_released_key (GtkWidget *widget, } static void -on_key_pressed (EekKey *key, +on_button_pressed (struct squeek_button *button, EekKeyboard *view, EekGtkKeyboard *self) { @@ -524,7 +526,14 @@ on_key_pressed (EekKey *key, if (!priv->renderer) return; - render_pressed_key (GTK_WIDGET(self), view, key); + struct button_place place = { + .button = button, + .section = eek_keyboard_get_section(view, button), + }; + if (!place.section) { + return; + } + render_pressed_button (GTK_WIDGET(self), &place); gtk_widget_queue_draw (GTK_WIDGET(self)); #if HAVE_LIBCANBERRA @@ -537,7 +546,7 @@ on_key_pressed (EekKey *key, } static void -on_key_released (EekKey *key, +on_button_released (struct squeek_button *button, EekKeyboard *view, EekGtkKeyboard *self) { @@ -548,7 +557,7 @@ on_key_released (EekKey *key, if (!priv->renderer) return; - render_released_key (GTK_WIDGET(self), key); + render_released_button (GTK_WIDGET(self), button); gtk_widget_queue_draw (GTK_WIDGET(self)); #if HAVE_LIBCANBERRA diff --git a/eek/eek-key.c b/eek/eek-key.c deleted file mode 100644 index 96e6323a..00000000 --- a/eek/eek-key.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (C) 2010-2011 Daiki Ueno - * Copyright (C) 2010-2011 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -/** - * SECTION:eek-key - * @short_description: Base class of a key - * - * The #EekKeyClass class represents a key. - */ - -#include "config.h" - -#include - -#include "eek-section.h" -#include "eek-keyboard.h" -#include "src/keyboard.h" -#include "src/symbol.h" - -#include "eek-key.h" - -enum { - PROP_0, - PROP_OREF, - PROP_LAST -}; - -typedef struct _EekKeyPrivate -{ - gulong oref; // UI outline reference - struct squeek_key *state; -} EekKeyPrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (EekKey, eek_key, EEK_TYPE_ELEMENT) - -void -eek_key_set_locked (EekKey *self, gboolean value) -{ - EekKeyPrivate *priv = eek_key_get_instance_private (self); - squeek_key_set_pressed(priv->state, value); -} - -static void -eek_key_finalize (GObject *object) -{ - EekKey *self = EEK_KEY (object); - EekKeyPrivate *priv = eek_key_get_instance_private (self); - - squeek_key_free (priv->state); - - G_OBJECT_CLASS (eek_key_parent_class)->finalize (object); -} - -static void -eek_key_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (prop_id) { - case PROP_OREF: - eek_key_set_oref (EEK_KEY(object), g_value_get_uint (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -eek_key_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - switch (prop_id) { - case PROP_OREF: - g_value_set_uint (value, eek_key_get_oref (EEK_KEY(object))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -eek_key_class_init (EekKeyClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GParamSpec *pspec; - - gobject_class->set_property = eek_key_set_property; - gobject_class->get_property = eek_key_get_property; - gobject_class->finalize = eek_key_finalize; - - /** - * EekKey:oref: - * - * The outline id of #EekKey. - */ - pspec = g_param_spec_ulong ("oref", - "Oref", - "Outline id of the key", - 0, G_MAXULONG, 0, - G_PARAM_READWRITE); - g_object_class_install_property (gobject_class, PROP_OREF, pspec); -} - -static void -eek_key_init (EekKey *self) -{ - EekKeyPrivate *priv = eek_key_get_instance_private (self); - priv->state = squeek_key_new (0); -} - -void eek_key_share_state(EekKey *self, struct squeek_key *state) { - EekKeyPrivate *priv = eek_key_get_instance_private (self); - priv->state = state; -} -/** - * eek_key_set_keycode: - * @key: an #EekKey - * @keycode: keycode - * - * Set the keycode of @key to @keycode. Since typically the keycode - * value is used to find a key in a keyboard by calling - * eek_keyboard_find_key_by_keycode, it is not necessarily the same as - * the X keycode but it should be unique in the keyboard @key belongs - * to. - */ -void -eek_key_set_keycode (EekKey *key, - guint keycode) -{ - g_return_if_fail (EEK_IS_KEY (key)); - - EekKeyPrivate *priv = eek_key_get_instance_private (key); - - squeek_key_set_keycode(priv->state, keycode); -} - -/** - * eek_key_get_keycode: - * @key: an #EekKey - * - * Get keycode of @key. - * Returns: keycode or %EEK_INVALID_KEYCODE on failure - */ -guint -eek_key_get_keycode (EekKey *key) -{ - g_return_val_if_fail (EEK_IS_KEY (key), EEK_INVALID_KEYCODE); - - EekKeyPrivate *priv = eek_key_get_instance_private (key); - - return squeek_key_get_keycode(priv->state); -} - -/** - * eek_key_get_symbol_at_index: - * @key: an #EekKey - * @group: group index of the symbol matrix - * @level: level index of the symbol matrix - * @fallback_group: fallback group index - * @fallback_level: fallback level index - * - * Get the symbol at (@group, @level) in the symbol matrix of @key. - * Return value: (transfer none): an #EekSymbol at (@group, @level), or %NULL - */ -struct squeek_symbol* -eek_key_get_symbol_at_index (EekKey *key, - gint group) -{ - EekKeyPrivate *priv = eek_key_get_instance_private (key); - return squeek_key_get_symbol(priv->state); -} - -/** - * eek_key_set_oref: - * @key: an #EekKey - * @oref: outline id of @key - * - * Set the outline id of @key to @oref. - */ -void -eek_key_set_oref (EekKey *key, - guint oref) -{ - g_return_if_fail (EEK_IS_KEY(key)); - - EekKeyPrivate *priv = eek_key_get_instance_private (key); - - if (priv->oref != oref) { - priv->oref = oref; - g_object_notify (G_OBJECT(key), "oref"); - } -} - -/** - * eek_key_get_oref: - * @key: an #EekKey - * - * Get the outline id of @key. - * Returns: unsigned integer - */ -guint -eek_key_get_oref (EekKey *key) -{ - g_return_val_if_fail (EEK_IS_KEY (key), 0); - - EekKeyPrivate *priv = eek_key_get_instance_private (key); - - return priv->oref; -} - -/** - * eek_key_is_pressed: - * @key: an #EekKey - * - * Return %TRUE if key is marked as pressed. - */ -gboolean -eek_key_is_pressed (EekKey *key) -{ - g_return_val_if_fail (EEK_IS_KEY(key), FALSE); - - EekKeyPrivate *priv = (EekKeyPrivate*)eek_key_get_instance_private (key); - - return (bool)squeek_key_is_pressed(priv->state); -} - -/** - * eek_key_is_locked: - * @key: an #EekKey - * - * Return %TRUE if key is marked as locked. - */ -gboolean -eek_key_is_locked (EekKey *key) -{ - g_return_val_if_fail (EEK_IS_KEY(key), FALSE); - - EekKeyPrivate *priv = eek_key_get_instance_private (key); - - return (bool)squeek_key_is_locked(priv->state); -} - -void eek_key_set_pressed(EekKey *key, gboolean value) -{ - g_return_if_fail (EEK_IS_KEY(key)); - - EekKeyPrivate *priv = eek_key_get_instance_private (key); - - squeek_key_set_pressed(priv->state, value); -} - -struct squeek_key *eek_key_get_state(EekKey *key) { - EekKeyPrivate *priv = eek_key_get_instance_private (key); - return priv->state; -} diff --git a/eek/eek-key.h b/eek/eek-key.h deleted file mode 100644 index 47672526..00000000 --- a/eek/eek-key.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2010-2011 Daiki Ueno - * Copyright (C) 2010-2011 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION) -#error "Only can be included directly." -#endif - -#ifndef EEK_KEY_H -#define EEK_KEY_H 1 - -#include "eek-element.h" - -G_BEGIN_DECLS - -#define EEK_TYPE_KEY (eek_key_get_type()) -G_DECLARE_DERIVABLE_TYPE(EekKey, eek_key, EEK, KEY, EekElement) - -/** - * EekKeyClass: - * @pressed: class handler for #EekKey::pressed signal - * @released: class handler for #EekKey::released signal - * @locked: class handler for #EekKey::locked signal - * @unlocked: class handler for #EekKey::unlocked signal - * @cancelled: class handler for #EekKey::cancelled signal - * @is_pressed: virtual function for getting whether the key is pressed - * @is_locked: virtual function for getting whether the key is locked - */ -struct _EekKeyClass -{ - /*< private >*/ - EekElementClass parent_class; -}; - -GType eek_key_get_type (void) G_GNUC_CONST; - -void eek_key_set_keycode (EekKey *key, - guint keycode); -guint eek_key_get_keycode (EekKey *key); -struct squeek_key *eek_key_get_state(EekKey *key); -struct squeek_symbol *eek_key_get_symbol_at_index (EekKey *key, - gint group); - -void eek_key_set_oref (EekKey *key, - guint oref); -guint eek_key_get_oref (EekKey *key); - -gboolean eek_key_is_pressed (EekKey *key); -gboolean eek_key_is_locked (EekKey *key); -void eek_key_set_pressed (EekKey *key, - gboolean value); -void -eek_key_set_locked (EekKey *self, gboolean value); -void eek_key_share_state(EekKey *self, struct squeek_key *state); -G_END_DECLS -#endif /* EEK_KEY_H */ diff --git a/eek/eek-keyboard.c b/eek/eek-keyboard.c index 1b98ad70..5c52fccb 100644 --- a/eek/eek-keyboard.c +++ b/eek/eek-keyboard.c @@ -31,7 +31,6 @@ #include #include "eek-section.h" -#include "eek-key.h" #include "eek-enumtypes.h" #include "eekboard/key-emitter.h" #include "keymap.h" @@ -81,7 +80,6 @@ eek_modifier_key_copy (EekModifierKey *modkey) void eek_modifier_key_free (EekModifierKey *modkey) { - g_object_unref (modkey->key); g_slice_free (EekModifierKey, modkey); } @@ -129,30 +127,30 @@ eek_keyboard_get_property (GObject *object, /// and instead refer to the contained symbols static guint set_key_states (LevelKeyboard *keyboard, - EekKey *key, + struct squeek_button *button, guint new_level) { + struct squeek_key *key = squeek_button_get_key(button); // Keys locking rules hardcoded for the time being... - const gchar *name = eek_element_get_name(EEK_ELEMENT(key)); + const gchar *name = squeek_symbol_get_name(squeek_key_get_symbol(key)); // Lock the shift whenever it's pressed on the baselevel // TODO: need to lock shift on the destination level if (g_strcmp0(name, "Shift_L") == 0 && keyboard->level == 0) { EekModifierKey *modifier_key = g_slice_new (EekModifierKey); modifier_key->modifiers = 0; - modifier_key->key = g_object_ref (key); - keyboard->locked_keys = - g_list_prepend (keyboard->locked_keys, modifier_key); - eek_key_set_locked(modifier_key->key, true); + modifier_key->button = button; + keyboard->locked_buttons = + g_list_prepend (keyboard->locked_buttons, modifier_key); + squeek_key_set_locked(key, true); } - if (keyboard->level == 1) { // Only shift is locked in this state, unlock on any key press - for (GList *head = keyboard->locked_keys; head; ) { + for (GList *head = keyboard->locked_buttons; head; ) { EekModifierKey *modifier_key = head->data; GList *next = g_list_next (head); - keyboard->locked_keys = - g_list_remove_link (keyboard->locked_keys, head); - eek_key_set_locked(modifier_key->key, false); + keyboard->locked_buttons = + g_list_remove_link (keyboard->locked_buttons, head); + squeek_key_set_locked(squeek_button_get_key(modifier_key->button), false); g_list_free1 (head); head = next; } @@ -163,13 +161,13 @@ set_key_states (LevelKeyboard *keyboard, // FIXME: unhardcode, parse some user information as to which key triggers which view (level) static void -set_level_from_press (LevelKeyboard *keyboard, EekKey *key) +set_level_from_press (LevelKeyboard *keyboard, struct squeek_button *button) { /* The levels are: 0 Letters, 1 Upper case letters, 2 Numbers, 3 Symbols */ guint level = keyboard->level; /* Handle non-emitting keys */ - if (key) { - const gchar *name = eek_element_get_name(EEK_ELEMENT(key)); + if (button) { + const gchar *name = squeek_symbol_get_name(squeek_key_get_symbol(squeek_button_get_key(button))); if (g_strcmp0(name, "show_numbers") == 0) { level = 2; } else if (g_strcmp0(name, "show_letters") == 0) { @@ -181,18 +179,17 @@ set_level_from_press (LevelKeyboard *keyboard, EekKey *key) } } - keyboard->level = set_key_states(keyboard, key, level); + keyboard->level = set_key_states(keyboard, button, level); eek_layout_update_layout(keyboard); } -void eek_keyboard_press_key(LevelKeyboard *keyboard, EekKey *key, guint32 timestamp) { - eek_key_set_pressed(key, TRUE); - keyboard->pressed_keys = g_list_prepend (keyboard->pressed_keys, key); +void eek_keyboard_press_button(LevelKeyboard *keyboard, struct squeek_button *button, guint32 timestamp) { + struct squeek_key *key = squeek_button_get_key(button); + squeek_key_set_pressed(key, TRUE); + keyboard->pressed_buttons = g_list_prepend (keyboard->pressed_buttons, button); - struct squeek_symbol *symbol = eek_key_get_symbol_at_index( - key, 0 - ); + struct squeek_symbol *symbol = squeek_key_get_symbol(key); if (!symbol) return; @@ -201,32 +198,31 @@ void eek_keyboard_press_key(LevelKeyboard *keyboard, EekKey *key, guint32 timest // "Borrowed" from eek-context-service; doesn't influence the state but forwards the event - guint keycode = eek_key_get_keycode (key); + guint keycode = squeek_key_get_keycode (key); emit_key_activated(keyboard->manager, keyboard, keycode, TRUE, timestamp); } -void eek_keyboard_release_key(LevelKeyboard *keyboard, - EekKey *key, +void eek_keyboard_release_button(LevelKeyboard *keyboard, + struct squeek_button *button, guint32 timestamp) { - for (GList *head = keyboard->pressed_keys; head; head = g_list_next (head)) { - if (head->data == key) { - keyboard->pressed_keys = g_list_remove_link (keyboard->pressed_keys, head); + for (GList *head = keyboard->pressed_buttons; head; head = g_list_next (head)) { + if (head->data == button) { + keyboard->pressed_buttons = g_list_remove_link (keyboard->pressed_buttons, head); g_list_free1 (head); break; } } - struct squeek_symbol *symbol = eek_key_get_symbol_at_index( - key, 0); + struct squeek_symbol *symbol = squeek_button_get_symbol(button); if (!symbol) return; - set_level_from_press (keyboard, key); + set_level_from_press (keyboard, button); // "Borrowed" from eek-context-service; doesn't influence the state but forwards the event - guint keycode = eek_key_get_keycode (key); + guint keycode = squeek_key_get_keycode (squeek_button_get_key(button)); emit_key_activated(keyboard->manager, keyboard, keycode, FALSE, timestamp); } @@ -306,14 +302,14 @@ void level_keyboard_init(LevelKeyboard *self) { self->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline)); } -LevelKeyboard *level_keyboard_new(EekboardContextService *manager, EekKeyboard *views[4], GHashTable *name_key_hash) { +LevelKeyboard *level_keyboard_new(EekboardContextService *manager, EekKeyboard *views[4], GHashTable *name_button_hash) { LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1); level_keyboard_init(keyboard); for (uint i = 0; i < 4; i++) { keyboard->views[i] = views[i]; } keyboard->manager = manager; - keyboard->names = name_key_hash; + keyboard->names = name_button_hash; return keyboard; } @@ -325,8 +321,8 @@ LevelKeyboard *level_keyboard_new(EekboardContextService *manager, EekKeyboard * * Find an #EekKey whose name is @name. * Return value: (transfer none): #EekKey whose name is @name */ -EekKey * -eek_keyboard_find_key_by_name (LevelKeyboard *keyboard, +struct squeek_button* +eek_keyboard_find_button_by_name (LevelKeyboard *keyboard, const gchar *name) { return g_hash_table_lookup (keyboard->names, name); @@ -386,15 +382,16 @@ eek_keyboard_get_keymap(LevelKeyboard *keyboard) /* Iterate over the keys in the name-to-key hash table. */ GHashTableIter iter; - gchar *key_name; - gpointer key_ptr; + gchar *button_name; + gpointer button_ptr; g_hash_table_iter_init(&iter, keyboard->names); - while (g_hash_table_iter_next(&iter, (gpointer)&key_name, &key_ptr)) { + while (g_hash_table_iter_next(&iter, (gpointer)&button_name, &button_ptr)) { gchar *current, *line; - EekKey *key = EEK_KEY(key_ptr); - guint keycode = eek_key_get_keycode(key); + struct squeek_button *button = button_ptr; + struct squeek_key *key = squeek_button_get_key(button); + guint keycode = squeek_key_get_keycode(key); /* Don't include invalid keycodes in the keymap. */ if (keycode == EEK_INVALID_KEYCODE) @@ -402,7 +399,7 @@ eek_keyboard_get_keymap(LevelKeyboard *keyboard) /* Append a key name-to-keycode definition to the keycodes section. */ current = keycodes; - line = g_strdup_printf(" <%s> = %i;\n", (char *)key_name, keycode); + line = g_strdup_printf(" <%s> = %i;\n", (char *)button_name, keycode); keycodes = g_strconcat(current, line, NULL); g_free(line); @@ -410,8 +407,8 @@ eek_keyboard_get_keymap(LevelKeyboard *keyboard) // FIXME: free const char *key_str = squeek_key_to_keymap_entry( - (char*)key_name, - eek_key_get_state(key) + (char*)button_name, + key ); current = symbols; symbols = g_strconcat(current, key_str, NULL); @@ -435,34 +432,57 @@ EekKeyboard *level_keyboard_current(LevelKeyboard *keyboard) } struct GetSectionData { - const EekKey *key; + const struct squeek_button *button; EekSection *section; + const struct squeek_key *needle; }; -gint check_right_key(EekElement *element, gpointer user_data) { - EekKey *key = EEK_KEY(element); - struct GetSectionData *data = user_data; - if (key == data->key) { - return TRUE; - } else { - return FALSE; - } -} - -void find_key_in_section(EekElement *element, gpointer user_data) { +void find_button_in_section(EekElement *element, gpointer user_data) { EekSection *section = EEK_SECTION(element); struct GetSectionData *data = user_data; - if (eek_container_find(EEK_CONTAINER(section), check_right_key, &data)) { + if (data->section) { + return; + } + if (eek_section_find(section, data->button)) { data->section = section; } } EekSection *eek_keyboard_get_section(EekKeyboard *keyboard, - const EekKey *key) { + const struct squeek_button *button) { struct GetSectionData data = { - .key = key, + .button = button, .section = NULL, }; - eek_container_foreach_child(EEK_CONTAINER(keyboard), find_key_in_section, &data); + eek_container_foreach_child(EEK_CONTAINER(keyboard), find_button_in_section, &data); return data.section; } + +void find_key_in_section(EekElement *element, gpointer user_data) { + EekSection *section = EEK_SECTION(element); + struct GetSectionData *data = user_data; + if (data->button) { + return; + } + data->button = eek_section_find_key(section, data->needle); + if (data->button) { + data->section = section; + } +} + + +// TODO: return multiple +struct button_place eek_keyboard_get_button_by_state(EekKeyboard *keyboard, + const struct squeek_key *key) { + struct GetSectionData data = { + .section = NULL, + .button = NULL, + .needle = key, + }; + eek_container_foreach_child(EEK_CONTAINER(keyboard), find_key_in_section, &data); + struct button_place ret = { + .section = data.section, + .button = (struct squeek_button*)data.button, + }; + return ret; +} diff --git a/eek/eek-keyboard.h b/eek/eek-keyboard.h index 6a08812d..652a99e7 100644 --- a/eek/eek-keyboard.h +++ b/eek/eek-keyboard.h @@ -30,6 +30,7 @@ #include "eek-container.h" #include "eek-types.h" #include "eek-layout.h" +#include "src/layout.h" G_BEGIN_DECLS @@ -113,7 +114,7 @@ struct _EekKeyboardClass struct _EekModifierKey { /*< public >*/ EekModifierType modifiers; - EekKey *key; + struct squeek_button *button; }; typedef struct _EekModifierKey EekModifierKey; @@ -126,10 +127,10 @@ struct _LevelKeyboard { size_t keymap_len; // length of the data inside keymap_fd GArray *outline_array; - GList *pressed_keys; - GList *locked_keys; + GList *pressed_buttons; // struct squeek_button* + GList *locked_buttons; // struct squeek_button* - /* Map key names to key objects: */ + /* Map button names to button objects: */ GHashTable *names; guint id; // as a key to layout choices @@ -157,11 +158,18 @@ EekSection *eek_keyboard_create_section (EekKeyboard *keyboard); EekSection *eek_keyboard_get_section (EekKeyboard *keyboard, - const EekKey *key); -EekKey *eek_keyboard_find_key_by_name - (LevelKeyboard *keyboard, + const struct squeek_button *button); +struct squeek_button *eek_keyboard_find_button_by_name(LevelKeyboard *keyboard, const gchar *name); +/// Represents the path to the button within a view +struct button_place { + EekSection *section; + struct squeek_button *button; +}; + +struct button_place eek_keyboard_get_button_by_state(EekKeyboard *keyboard, + const struct squeek_key *key); EekOutline *level_keyboard_get_outline (LevelKeyboard *keyboard, @@ -171,14 +179,14 @@ EekModifierKey *eek_modifier_key_copy void eek_modifier_key_free (EekModifierKey *modkey); -void eek_keyboard_press_key(LevelKeyboard *keyboard, EekKey *key, guint32 timestamp); -void eek_keyboard_release_key(LevelKeyboard *keyboard, EekKey *key, guint32 timestamp); +void eek_keyboard_press_button(LevelKeyboard *keyboard, struct squeek_button *button, guint32 timestamp); +void eek_keyboard_release_button(LevelKeyboard *keyboard, struct squeek_button *button, guint32 timestamp); gchar * eek_keyboard_get_keymap (LevelKeyboard *keyboard); EekKeyboard *level_keyboard_current(LevelKeyboard *keyboard); -LevelKeyboard *level_keyboard_new(EekboardContextService *manager, EekKeyboard *views[4], GHashTable *name_key_hash); +LevelKeyboard *level_keyboard_new(EekboardContextService *manager, EekKeyboard *views[4], GHashTable *name_button_hash); void level_keyboard_deinit(LevelKeyboard *self); void level_keyboard_free(LevelKeyboard *self); /* Create an #EekSection instance and append it to @keyboard. This diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index 897c6957..64f244b5 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -24,7 +24,6 @@ #include #include -#include "eek-key.h" #include "eek-section.h" #include "src/symbol.h" @@ -76,33 +75,33 @@ extern void _eek_rounded_polygon (cairo_t *cr, EekPoint *points, guint num_points); -static void eek_renderer_real_render_key_label (EekRenderer *self, +static void eek_renderer_real_render_button_label (EekRenderer *self, PangoLayout *layout, - EekKey *key); + struct squeek_button *button); static void invalidate (EekRenderer *renderer); -static void render_key (EekRenderer *self, - cairo_t *cr, EekKeyboard *view, - EekKey *key, +static void render_button (EekRenderer *self, + cairo_t *cr, struct button_place *place, gboolean active); struct _CreateKeyboardSurfaceCallbackData { cairo_t *cr; EekRenderer *renderer; EekKeyboard *view; + EekSection *section; }; typedef struct _CreateKeyboardSurfaceCallbackData CreateKeyboardSurfaceCallbackData; static void -create_keyboard_surface_key_callback (EekElement *element, +create_keyboard_surface_button_callback (gpointer item, gpointer user_data) { + struct squeek_button *button = item; CreateKeyboardSurfaceCallbackData *data = user_data; - EekBounds bounds; + EekBounds bounds = squeek_button_get_bounds(button); cairo_save (data->cr); - eek_element_get_bounds (element, &bounds); cairo_translate (data->cr, bounds.x, bounds.y); cairo_rectangle (data->cr, 0.0, @@ -110,7 +109,11 @@ create_keyboard_surface_key_callback (EekElement *element, bounds.width + 100, bounds.height + 100); cairo_clip (data->cr); - render_key (data->renderer, data->cr, data->view, EEK_KEY(element), FALSE); + struct button_place place = { + .section = data->section, + .button = button, + }; + render_button (data->renderer, data->cr, &place, FALSE); cairo_restore (data->cr); } @@ -131,8 +134,9 @@ create_keyboard_surface_section_callback (EekElement *element, angle = eek_section_get_angle (EEK_SECTION(element)); cairo_rotate (data->cr, angle * G_PI / 180); - eek_container_foreach_child (EEK_CONTAINER(element), - create_keyboard_surface_key_callback, + data->section = EEK_SECTION(element); + eek_section_foreach(EEK_SECTION(element), + create_keyboard_surface_button_callback, data); cairo_restore (data->cr); @@ -185,22 +189,20 @@ render_keyboard_surface (EekRenderer *renderer, EekKeyboard *view) } static void -render_key_outline (EekRenderer *renderer, +render_button_outline (EekRenderer *renderer, cairo_t *cr, - EekKey *key, + struct squeek_button *button, gboolean active) { EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer); EekOutline *outline; - EekBounds bounds; - guint oref; - oref = eek_key_get_oref (key); + guint oref = squeek_button_get_oref(button); outline = level_keyboard_get_outline (priv->keyboard, oref); if (outline == NULL) return; - eek_element_get_bounds(EEK_ELEMENT(key), &bounds); + EekBounds bounds = squeek_button_get_bounds(button); gtk_style_context_set_state(priv->key_context, active ? GTK_STATE_FLAG_ACTIVE : GTK_STATE_FLAG_NORMAL); @@ -213,30 +215,26 @@ render_key_outline (EekRenderer *renderer, } static void -render_key (EekRenderer *self, +render_button (EekRenderer *self, cairo_t *cr, - EekKeyboard *view, - EekKey *key, + struct button_place *place, gboolean active) { EekRendererPrivate *priv = eek_renderer_get_instance_private (self); EekOutline *outline; cairo_surface_t *outline_surface; - EekBounds bounds; - guint oref; - struct squeek_symbol *symbol; GHashTable *outline_surface_cache; PangoLayout *layout; PangoRectangle extents = { 0, }; EekColor foreground; - oref = eek_key_get_oref (key); + guint oref = squeek_button_get_oref (place->button); outline = level_keyboard_get_outline (priv->keyboard, oref); if (outline == NULL) return; /* render outline */ - eek_element_get_bounds (EEK_ELEMENT(key), &bounds); + EekBounds bounds = squeek_button_get_bounds(place->button); if (active) outline_surface_cache = priv->active_outline_surface_cache; @@ -260,8 +258,8 @@ render_key (EekRenderer *self, cairo_paint (cr); cairo_save (cr); - eek_renderer_apply_transformation_for_key (self, cr, view, key, 1.0, FALSE); - render_key_outline (self, cr, key, active); + eek_renderer_apply_transformation_for_button (self, cr, place, 1.0, FALSE); + render_button_outline (self, cr, place->button, active); cairo_restore (cr); cairo_destroy (cr); @@ -276,7 +274,7 @@ render_key (EekRenderer *self, eek_renderer_get_foreground_color (self, priv->key_context, &foreground); /* render icon (if any) */ - symbol = eek_key_get_symbol_at_index (key, 0); + struct squeek_symbol *symbol = squeek_button_get_symbol(place->button); if (!symbol) return; @@ -312,7 +310,7 @@ render_key (EekRenderer *self, /* render label */ layout = pango_cairo_create_layout (cr); - eek_renderer_real_render_key_label (self, layout, key); + eek_renderer_real_render_button_label (self, layout, place->button); pango_layout_get_extents (layout, NULL, &extents); cairo_save (cr); @@ -348,23 +346,20 @@ render_key (EekRenderer *self, * normal keys for popups. */ void -eek_renderer_apply_transformation_for_key (EekRenderer *self, +eek_renderer_apply_transformation_for_button (EekRenderer *self, cairo_t *cr, - EekKeyboard *view, - EekKey *key, + struct button_place *place, gdouble scale, gboolean rotate) { - EekSection *section; EekBounds bounds, rotated_bounds; gint angle; gdouble s; - eek_renderer_get_key_bounds (self, view, key, &bounds, FALSE); - eek_renderer_get_key_bounds (self, view, key, &rotated_bounds, TRUE); + eek_renderer_get_button_bounds (self, place, &bounds, FALSE); + eek_renderer_get_button_bounds (self, place, &rotated_bounds, TRUE); - section = eek_keyboard_get_section(view, key); - angle = eek_section_get_angle (section); + angle = eek_section_get_angle (place->section); cairo_scale (cr, scale, scale); if (rotate) { @@ -378,19 +373,18 @@ eek_renderer_apply_transformation_for_key (EekRenderer *self, } static void -eek_renderer_real_render_key_label (EekRenderer *self, +eek_renderer_real_render_button_label (EekRenderer *self, PangoLayout *layout, - EekKey *key) + struct squeek_button *button) { EekRendererPrivate *priv = eek_renderer_get_instance_private (self); - struct squeek_symbol *symbol; + const gchar *label; - EekBounds bounds; PangoFontDescription *font; PangoLayoutLine *line; gdouble scale; - symbol = eek_key_get_symbol_at_index(key, 0); + struct squeek_symbol *symbol = squeek_button_get_symbol(button); if (!symbol) return; @@ -415,7 +409,7 @@ eek_renderer_real_render_key_label (EekRenderer *self, pango_font_description_set_size (priv->font, (gint)round(size * 0.6)); } - eek_element_get_bounds (EEK_ELEMENT(key), &bounds); + EekBounds bounds = squeek_button_get_bounds(button); scale = MIN((bounds.width - priv->border_width) / bounds.width, (bounds.height - priv->border_width) / bounds.height); @@ -434,16 +428,19 @@ eek_renderer_real_render_key_label (EekRenderer *self, } static void -eek_renderer_real_render_key_outline (EekRenderer *self, +eek_renderer_real_render_button_outline (EekRenderer *self, cairo_t *cr, - EekKeyboard *view, - EekKey *key, + struct button_place *place, gdouble scale, gboolean rotate) { cairo_save (cr); - eek_renderer_apply_transformation_for_key (self, cr, view, key, scale, rotate); - render_key_outline (self, cr, key, eek_key_is_pressed (key) || eek_key_is_locked (key)); + eek_renderer_apply_transformation_for_button (self, cr, place, scale, rotate); + struct squeek_key *key = squeek_button_get_key(place->button); + render_button_outline ( + self, cr, place->button, + squeek_key_is_pressed(key) || squeek_key_is_locked (key) + ); cairo_restore (cr); } @@ -459,17 +456,16 @@ eek_renderer_real_render_key_outline (EekRenderer *self, * Renders a key separately from the normal keyboard rendering. */ static void -eek_renderer_real_render_key (EekRenderer *self, +eek_renderer_real_render_button (EekRenderer *self, cairo_t *cr, - EekKeyboard *view, - EekKey *key, + struct button_place *place, gdouble scale, gboolean rotate) { EekRendererPrivate *priv = eek_renderer_get_instance_private (self); EekBounds bounds; - eek_renderer_get_key_bounds (self, view, key, &bounds, rotate); + eek_renderer_get_button_bounds (self, place, &bounds, rotate); cairo_save (cr); /* Because this function is called separately from the keyboard rendering @@ -478,8 +474,12 @@ eek_renderer_real_render_key (EekRenderer *self, cairo_scale (cr, priv->scale, priv->scale); cairo_translate (cr, bounds.x, bounds.y); - eek_renderer_apply_transformation_for_key (self, cr, view, key, scale, rotate); - render_key (self, cr, view, key, eek_key_is_pressed (key) || eek_key_is_locked (key)); + eek_renderer_apply_transformation_for_button (self, cr, place, scale, rotate); + struct squeek_key *key = squeek_button_get_key(place->button); + render_button ( + self, cr, place, + squeek_key_is_pressed(key) || squeek_key_is_locked (key) + ); cairo_restore (cr); } @@ -593,8 +593,8 @@ eek_renderer_class_init (EekRendererClass *klass) GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GParamSpec *pspec; - klass->render_key_outline = eek_renderer_real_render_key_outline; - klass->render_key = eek_renderer_real_render_key; + klass->render_key_outline = eek_renderer_real_render_button_outline; + klass->render_button = eek_renderer_real_render_button; klass->render_keyboard = eek_renderer_real_render_keyboard; gobject_class->set_property = eek_renderer_set_property; @@ -757,44 +757,43 @@ eek_renderer_get_size (EekRenderer *renderer, } void -eek_renderer_get_key_bounds (EekRenderer *renderer, - EekKeyboard *view, - EekKey *key, +eek_renderer_get_button_bounds (EekRenderer *renderer, + struct button_place *place, EekBounds *bounds, gboolean rotate) { - EekSection *section = eek_keyboard_get_section(view, key); EekBounds section_bounds, keyboard_bounds; gint angle = 0; EekPoint points[4], min, max; g_return_if_fail (EEK_IS_RENDERER(renderer)); - g_return_if_fail (EEK_IS_KEY(key)); + g_return_if_fail (place); g_return_if_fail (bounds != NULL); EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer); - eek_element_get_bounds (EEK_ELEMENT(key), bounds); - eek_element_get_bounds (EEK_ELEMENT(section), §ion_bounds); + EekBounds button_bounds = squeek_button_get_bounds(place->button); + eek_element_get_bounds (EEK_ELEMENT(place->section), §ion_bounds); eek_element_get_bounds (EEK_ELEMENT(level_keyboard_current(priv->keyboard)), &keyboard_bounds); if (!rotate) { - bounds->x += keyboard_bounds.x + section_bounds.x; - bounds->y += keyboard_bounds.y + section_bounds.y; + button_bounds.x += keyboard_bounds.x + section_bounds.x; + button_bounds.y += keyboard_bounds.y + section_bounds.y; + *bounds = button_bounds; return; } - points[0].x = bounds->x; - points[0].y = bounds->y; - points[1].x = points[0].x + bounds->width; + points[0].x = button_bounds.x; + points[0].y = button_bounds.y; + points[1].x = points[0].x + button_bounds.width; points[1].y = points[0].y; points[2].x = points[1].x; - points[2].y = points[1].y + bounds->height; + points[2].y = points[1].y + button_bounds.height; points[3].x = points[0].x; points[3].y = points[2].y; if (rotate) - angle = eek_section_get_angle (EEK_SECTION(section)); + angle = eek_section_get_angle (EEK_SECTION(place->section)); min = points[2]; max = points[0]; @@ -847,19 +846,17 @@ eek_renderer_create_pango_layout (EekRenderer *renderer) void eek_renderer_render_key_outline (EekRenderer *renderer, cairo_t *cr, - EekKeyboard *view, - EekKey *key, + struct button_place *place, gdouble scale, gboolean rotate) { g_return_if_fail (EEK_IS_RENDERER(renderer)); - g_return_if_fail (EEK_IS_KEY(key)); + g_return_if_fail (place); g_return_if_fail (scale >= 0.0); EEK_RENDERER_GET_CLASS(renderer)->render_key_outline (renderer, cr, - view, - key, + place, scale, rotate); } @@ -899,19 +896,18 @@ eek_renderer_get_icon_surface (EekRenderer *renderer, } void -eek_renderer_render_key (EekRenderer *renderer, +eek_renderer_render_button (EekRenderer *renderer, cairo_t *cr, - EekKeyboard *view, - EekKey *key, + struct button_place *place, gdouble scale, gboolean rotate) { g_return_if_fail (EEK_IS_RENDERER(renderer)); - g_return_if_fail (EEK_IS_KEY(key)); + g_return_if_fail (place); g_return_if_fail (scale >= 0.0); EEK_RENDERER_GET_CLASS(renderer)-> - render_key (renderer, cr, view, key, scale, rotate); + render_button (renderer, cr, place, scale, rotate); } void @@ -968,7 +964,7 @@ struct _FindKeyByPositionCallbackData { EekPoint point; EekPoint origin; gint angle; - EekKey *key; + struct squeek_button *button; EekRenderer *renderer; }; typedef struct _FindKeyByPositionCallbackData FindKeyByPositionCallbackData; @@ -981,16 +977,19 @@ sign (EekPoint *p1, EekPoint *p2, EekPoint *p3) (p2->x - p3->x) * (p1->y - p3->y); } -static gint -find_key_by_position_key_callback (EekElement *element, +static void +find_button_by_position_key_callback (gpointer item, gpointer user_data) { + struct squeek_button *button = item; FindKeyByPositionCallbackData *data = user_data; - EekBounds bounds; + if (data->button) { + return; + } EekPoint points[4]; gboolean b1, b2, b3; - eek_element_get_bounds (element, &bounds); + EekBounds bounds = squeek_button_get_bounds(button); points[0].x = bounds.x; points[0].y = bounds.y; @@ -1012,8 +1011,8 @@ find_key_by_position_key_callback (EekElement *element, b3 = sign (&data->point, &points[2], &points[0]) < 0.0; if (b1 == b2 && b2 == b3) { - data->key = EEK_KEY(element); - return 0; + data->button = button; + return; } b1 = sign (&data->point, &points[2], &points[3]) < 0.0; @@ -1021,17 +1020,15 @@ find_key_by_position_key_callback (EekElement *element, b3 = sign (&data->point, &points[0], &points[2]) < 0.0; if (b1 == b2 && b2 == b3) { - data->key = EEK_KEY(element); - return 0; + data->button = button; } - - return -1; } static gint -find_key_by_position_section_callback (EekElement *element, +find_button_by_position_section_callback (EekElement *element, gpointer user_data) { + EekSection *section = EEK_SECTION(element); FindKeyByPositionCallbackData *data = user_data; EekBounds bounds; EekPoint origin; @@ -1042,11 +1039,9 @@ find_key_by_position_section_callback (EekElement *element, data->origin.y += bounds.y; data->angle = eek_section_get_angle (EEK_SECTION(element)); - eek_container_find (EEK_CONTAINER(element), - find_key_by_position_key_callback, - data); + eek_section_foreach(section, find_button_by_position_key_callback, data); data->origin = origin; - return data->key ? 0 : -1; + return data->button ? 0 : -1; } /** @@ -1058,8 +1053,8 @@ find_key_by_position_section_callback (EekElement *element, * Return value: the key located at the position x, y in widget coordinates, or * NULL if no key can be found at that location **/ -EekKey * -eek_renderer_find_key_by_position (EekRenderer *renderer, +struct squeek_button * +eek_renderer_find_button_by_position (EekRenderer *renderer, EekKeyboard *view, gdouble x, gdouble y) @@ -1086,11 +1081,11 @@ eek_renderer_find_key_by_position (EekRenderer *renderer, data.point.y = y; data.origin.x = 0; data.origin.y = 0; - data.key = NULL; + data.button = NULL; data.renderer = renderer; eek_container_find (EEK_CONTAINER(view), - find_key_by_position_section_callback, + find_button_by_position_section_callback, &data); - return data.key; + return data.button; } diff --git a/eek/eek-renderer.h b/eek/eek-renderer.h index ba3ddd97..d9ba01fc 100644 --- a/eek/eek-renderer.h +++ b/eek/eek-renderer.h @@ -38,15 +38,13 @@ struct _EekRendererClass void (* render_key_outline) (EekRenderer *self, cairo_t *cr, - EekKeyboard *view, - EekKey *key, + struct button_place *place, gdouble scale, gboolean rotate); - void (* render_key) (EekRenderer *self, + void (* render_button) (EekRenderer *self, cairo_t *cr, - EekKeyboard *view, - EekKey *key, + struct button_place *place, gdouble scale, gboolean rotate); @@ -74,8 +72,8 @@ void eek_renderer_set_allocation_size void eek_renderer_get_size (EekRenderer *renderer, gdouble *width, gdouble *height); -void eek_renderer_get_key_bounds (EekRenderer *renderer, EekKeyboard *view, - EekKey *key, +void eek_renderer_get_button_bounds (EekRenderer *renderer, + struct button_place *button, EekBounds *bounds, gboolean rotate); @@ -91,15 +89,14 @@ void eek_renderer_render_key_label (EekRenderer *renderer, void eek_renderer_render_key_outline (EekRenderer *renderer, - cairo_t *cr, EekKeyboard *view, - EekKey *key, + cairo_t *cr, + struct button_place *place, gdouble scale, gboolean rotate); -void eek_renderer_render_key (EekRenderer *renderer, +void eek_renderer_render_button (EekRenderer *renderer, cairo_t *cr, - EekKeyboard *view, - EekKey *key, + struct button_place *place, gdouble scale, gboolean rotate); @@ -123,14 +120,12 @@ void eek_renderer_get_foreground_color EekColor *color); void eek_renderer_set_border_width (EekRenderer *renderer, gdouble border_width); -EekKey *eek_renderer_find_key_by_position - (EekRenderer *renderer, EekKeyboard *view, +struct squeek_button *eek_renderer_find_button_by_position(EekRenderer *renderer, EekKeyboard *view, gdouble x, gdouble y); -void eek_renderer_apply_transformation_for_key +void eek_renderer_apply_transformation_for_button (EekRenderer *renderer, - cairo_t *cr, EekKeyboard *view, - EekKey *key, + cairo_t *cr, struct button_place *place, gdouble scale, gboolean rotate); diff --git a/eek/eek-section.c b/eek/eek-section.c index 3671ce47..25d7dadd 100644 --- a/eek/eek-section.c +++ b/eek/eek-section.c @@ -32,7 +32,7 @@ #include #include "eek-keyboard.h" -#include "eek-key.h" +#include "layout.h" #include "eek-section.h" @@ -46,41 +46,32 @@ typedef struct _EekSectionPrivate { gint angle; EekModifierType modifiers; + GPtrArray *buttons; // struct squeek_button* } EekSectionPrivate; -G_DEFINE_TYPE_WITH_PRIVATE (EekSection, eek_section, EEK_TYPE_CONTAINER) +G_DEFINE_TYPE_WITH_PRIVATE (EekSection, eek_section, EEK_TYPE_ELEMENT) -static EekKey * -eek_section_real_create_key (EekSection *self, +struct squeek_button* +eek_section_create_button (EekSection *self, const gchar *name, - gint keycode, + guint keycode, guint oref) { - EekKey *key = (EekKey*)g_object_new (EEK_TYPE_KEY, - "name", name, - NULL); - g_return_val_if_fail (key, NULL); - eek_key_set_keycode(key, keycode); - eek_key_set_oref(key, oref); - - EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self), - EEK_ELEMENT(key)); - - return key; + struct squeek_button *button = squeek_button_new(keycode, oref); + g_return_val_if_fail (button, NULL); + EekSectionPrivate *priv = eek_section_get_instance_private (self); + g_ptr_array_add(priv->buttons, button); + return button; } -EekKey *eek_section_create_button(EekSection *self, +struct squeek_button *eek_section_create_button_with_state(EekSection *self, const gchar *name, - struct squeek_key *state) { - EekKey *key = (EekKey*)g_object_new (EEK_TYPE_KEY, - "name", name, - NULL); - g_return_val_if_fail (key, NULL); - eek_key_share_state(key, state); - - EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self), - EEK_ELEMENT(key)); - return key; + struct squeek_button *source) { + struct squeek_button *button = squeek_button_new_with_state(source); + g_return_val_if_fail (button, NULL); + EekSectionPrivate *priv = eek_section_get_instance_private (self); + g_ptr_array_add(priv->buttons, button); + return button; } static void @@ -122,35 +113,13 @@ eek_section_get_property (GObject *object, } } -static void -eek_section_real_child_added (EekContainer *self, - EekElement *element) -{ - (void)self; - (void)element; -} - -static void -eek_section_real_child_removed (EekContainer *self, - EekElement *element) -{ - (void)self; - (void)element; -} - static void eek_section_class_init (EekSectionClass *klass) { - EekContainerClass *container_class = EEK_CONTAINER_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GParamSpec *pspec; - klass->create_key = eek_section_real_create_key; - /* signals */ - container_class->child_added = eek_section_real_child_added; - container_class->child_removed = eek_section_real_child_removed; - gobject_class->set_property = eek_section_set_property; gobject_class->get_property = eek_section_get_property; gobject_class->finalize = eek_section_finalize; @@ -173,7 +142,8 @@ eek_section_class_init (EekSectionClass *klass) static void eek_section_init (EekSection *self) { - /* void */ + EekSectionPrivate *priv = eek_section_get_instance_private (self); + priv->buttons = g_ptr_array_new(); } /** @@ -213,30 +183,6 @@ eek_section_get_angle (EekSection *section) return priv->angle; } -/** - * eek_section_create_key: - * @section: an #EekSection - * @name: a name - * @keycode: a keycode - * @column: the column index of the key - * @row: the row index of the key - * - * Create an #EekKey instance and append it to @section. This - * function is rarely called by application but called by #EekLayout - * implementation. - */ -EekKey * -eek_section_create_key (EekSection *section, - const gchar *name, - guint keycode, - guint oref) -{ - g_return_val_if_fail (EEK_IS_SECTION(section), NULL); - return eek_section_real_create_key (section, - name, - keycode, oref); -} - const double keyspacing = 4.0; struct keys_info { @@ -245,13 +191,14 @@ struct keys_info { double biggest_height; }; +/// Set button size to match the outline. Reset position static void -keysizer(EekElement *element, gpointer user_data) +buttonsizer(gpointer item, gpointer user_data) { - EekKey *key = EEK_KEY(element); + struct squeek_button *button = item; LevelKeyboard *keyboard = user_data; - uint oref = eek_key_get_oref (key); + uint oref = squeek_button_get_oref(button); EekOutline *outline = level_keyboard_get_outline (keyboard, oref); if (outline && outline->num_points > 0) { double minx = outline->points[0].x; @@ -272,21 +219,23 @@ keysizer(EekElement *element, gpointer user_data) maxy = p.y; } } - EekBounds key_bounds = {0}; - eek_element_get_bounds(element, &key_bounds); - key_bounds.height = maxy - miny; - key_bounds.width = maxx - minx; - eek_element_set_bounds(element, &key_bounds); + EekBounds key_bounds = { + .height = maxy - miny, + .width = maxx - minx, + .x = 0, + .y = 0, + }; + squeek_button_set_bounds(button, key_bounds); } } static void -keycounter (EekElement *element, gpointer user_data) +buttoncounter (gpointer item, gpointer user_data) { + struct squeek_button *button = item; struct keys_info *data = user_data; data->count++; - EekBounds key_bounds = {0}; - eek_element_get_bounds(element, &key_bounds); + EekBounds key_bounds = squeek_button_get_bounds(button); data->total_width += key_bounds.width; if (key_bounds.height > data->biggest_height) { data->biggest_height = key_bounds.height; @@ -294,30 +243,63 @@ keycounter (EekElement *element, gpointer user_data) } static void -keyplacer(EekElement *element, gpointer user_data) +buttonplacer(gpointer item, gpointer user_data) { + struct squeek_button *button = item; double *current_offset = user_data; - EekBounds key_bounds = {0}; - eek_element_get_bounds(element, &key_bounds); + EekBounds key_bounds = squeek_button_get_bounds(button); key_bounds.x = *current_offset; key_bounds.y = 0; - eek_element_set_bounds(element, &key_bounds); + squeek_button_set_bounds(button, key_bounds); *current_offset += key_bounds.width + keyspacing; } void eek_section_place_keys(EekSection *section, LevelKeyboard *keyboard) { - eek_container_foreach_child(EEK_CONTAINER(section), keysizer, keyboard); + EekSectionPrivate *priv = eek_section_get_instance_private (section); + + g_ptr_array_foreach(priv->buttons, buttonsizer, keyboard); struct keys_info keyinfo = {0}; - eek_container_foreach_child(EEK_CONTAINER(section), keycounter, &keyinfo); + g_ptr_array_foreach(priv->buttons, buttoncounter, &keyinfo); + EekBounds section_bounds = {0}; eek_element_get_bounds(EEK_ELEMENT(section), §ion_bounds); double key_offset = (section_bounds.width - (keyinfo.total_width + (keyinfo.count - 1) * keyspacing)) / 2; - eek_container_foreach_child(EEK_CONTAINER(section), keyplacer, &key_offset); + g_ptr_array_foreach(priv->buttons, buttonplacer, &key_offset); section_bounds.height = keyinfo.biggest_height; eek_element_set_bounds(EEK_ELEMENT(section), §ion_bounds); } + +void eek_section_foreach (EekSection *section, + GFunc func, + gpointer user_data) { + EekSectionPrivate *priv = eek_section_get_instance_private (section); + g_ptr_array_foreach(priv->buttons, func, user_data); +} + +gboolean eek_section_find(EekSection *section, + const struct squeek_button *button) { + EekSectionPrivate *priv = eek_section_get_instance_private (section); + return g_ptr_array_find(priv->buttons, button, NULL); +} + +static gboolean button_has_key(gconstpointer buttonptr, gconstpointer keyptr) { + const struct squeek_button *button = buttonptr; + const struct squeek_key *key = keyptr; + return squeek_button_has_key((struct squeek_button*)button, key) != 0; +} + +struct squeek_button *eek_section_find_key(EekSection *section, + const struct squeek_key *key) { + EekSectionPrivate *priv = eek_section_get_instance_private (section); + guint index; + gboolean ret = g_ptr_array_find_with_equal_func(priv->buttons, key, button_has_key, &index); + if (ret) { + return g_ptr_array_index(priv->buttons, index); + } + return NULL;// TODO: store keys in locked_keys, pressed_keys +} diff --git a/eek/eek-section.h b/eek/eek-section.h index f5ccd07f..84375b17 100644 --- a/eek/eek-section.h +++ b/eek/eek-section.h @@ -30,11 +30,12 @@ #include "eek-types.h" #include "eek-keyboard.h" #include "src/keyboard.h" +#include "src/layout.h" G_BEGIN_DECLS #define EEK_TYPE_SECTION (eek_section_get_type()) -G_DECLARE_DERIVABLE_TYPE(EekSection, eek_section, EEK, SECTION, EekContainer) +G_DECLARE_DERIVABLE_TYPE(EekSection, eek_section, EEK, SECTION, EekElement) /** * EekSectionClass: @@ -51,13 +52,7 @@ G_DECLARE_DERIVABLE_TYPE(EekSection, eek_section, EEK, SECTION, EekContainer) struct _EekSectionClass { /*< private >*/ - EekContainerClass parent_class; - - /*< public >*/ - EekKey *(* create_key) (EekSection *self, - const gchar *name, - gint keycode, - guint oref); + EekElementClass parent_class; /*< private >*/ /* padding */ @@ -70,13 +65,21 @@ void eek_section_set_angle (EekSection *section, gint angle); gint eek_section_get_angle (EekSection *section); -EekKey *eek_section_create_key (EekSection *section, +struct squeek_button *eek_section_create_button (EekSection *section, const gchar *name, guint keycode, guint oref); -EekKey *eek_section_create_button(EekSection *self, +struct squeek_button *eek_section_create_button_with_state(EekSection *self, const gchar *name, - struct squeek_key *state); + struct squeek_button *source); void eek_section_place_keys (EekSection *section, LevelKeyboard *keyboard); +void eek_section_foreach (EekSection *section, + GFunc func, + gpointer user_data); +gboolean eek_section_find(EekSection *section, + const struct squeek_button *button); + +struct squeek_button *eek_section_find_key(EekSection *section, + const struct squeek_key *key); G_END_DECLS #endif /* EEK_SECTION_H */ diff --git a/eek/eek-xml-layout.c b/eek/eek-xml-layout.c index 8dc269cc..44e669f1 100644 --- a/eek/eek-xml-layout.c +++ b/eek/eek-xml-layout.c @@ -29,7 +29,6 @@ #include "eek-keyboard.h" #include "eek-section.h" -#include "eek-key.h" #include "src/keyboard.h" #include "src/symbol.h" @@ -68,7 +67,7 @@ static GList *parse_prerequisites (const gchar *path, GError **error); static gboolean parse_geometry (const gchar *path, - EekKeyboard **views, GArray *outline_array, GHashTable *name_key_hash, + EekKeyboard **views, GArray *outline_array, GHashTable *name_button_hash, GError **error); static gboolean parse_symbols_with_prerequisites (const gchar *keyboards_dir, @@ -236,7 +235,6 @@ struct _GeometryParseData { EekKeyboard **views; guint view_idx; EekSection *section; - EekKey *key; gint num_rows; EekOrientation orientation; gdouble corner_radius; @@ -250,14 +248,14 @@ struct _GeometryParseData { GArray *outline_array; - GHashTable *name_key_hash; // char* -> EekKey* + GHashTable *name_button_hash; // char* -> struct squeek_button* GHashTable *keyname_oref_hash; // char* -> guint GHashTable *outlineid_oref_hash; // char* -> guint }; typedef struct _GeometryParseData GeometryParseData; static GeometryParseData * -geometry_parse_data_new (EekKeyboard **views, GHashTable *name_key_hash, GArray *outline_array) +geometry_parse_data_new (EekKeyboard **views, GHashTable *name_button_hash, GArray *outline_array) { GeometryParseData *data = g_slice_new0 (GeometryParseData); @@ -274,7 +272,7 @@ geometry_parse_data_new (EekKeyboard **views, GHashTable *name_key_hash, GArray g_free, NULL); - data->name_key_hash = name_key_hash; + data->name_button_hash = name_button_hash; data->text = g_string_sized_new (BUFSIZE); data->keycode = 8; return data; @@ -418,15 +416,16 @@ geometry_start_element_callback (GMarkupParseContext *pcontext, g_strdup(name), GUINT_TO_POINTER(oref)); - EekKey *key = g_hash_table_lookup(data->name_key_hash, name); + struct squeek_button *button = g_hash_table_lookup(data->name_button_hash, name); // never gets used! this section gets executed before any buttons get defined - if (key) { + if (button) { if (keycode_name != NULL) { // This sets the keycode for all buttons, // since they share state // TODO: get rid of this in the parser; // this belongs after keymap is defined - eek_key_set_keycode(key, strtol (keycode_name, NULL, 10)); + struct squeek_key *key = squeek_button_get_key(button); + squeek_key_set_keycode(key, strtol (keycode_name, NULL, 10)); } } @@ -559,31 +558,30 @@ geometry_end_element_callback (GMarkupParseContext *pcontext, } gchar *name = g_strndup (&text[start], end - start); - EekKey *key = g_hash_table_lookup(data->name_key_hash, name); - if (!key) { + struct squeek_button *button = g_hash_table_lookup(data->name_button_hash, name); + if (!button) { // Save button name together with its level, // to account for buttons with the same name in multiple levels guint keycode = data->keycode++; guint oref = GPOINTER_TO_UINT(g_hash_table_lookup(data->keyname_oref_hash, name)); // default value gives idx 0, which is guaranteed to be occupied - key = eek_section_create_key (data->section, + button = eek_section_create_button (data->section, name, keycode, oref); - g_hash_table_insert (data->name_key_hash, + g_hash_table_insert (data->name_button_hash, g_strdup(name), - key); + button); } else { - EekKey *new_key = eek_section_create_button(data->section, name, eek_key_get_state(key)); - if (!new_key) { + struct squeek_button *new_button = eek_section_create_button_with_state(data->section, name, button); + if (!new_button) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_MISSING_ATTRIBUTE, "Couldn't create a shared button"); return; } - eek_key_set_oref(new_key, eek_key_get_oref(key)); } } @@ -736,11 +734,11 @@ symbols_end_element_callback (GMarkupParseContext *pcontext, if (g_strcmp0 (element_name, "symbol") == 0) { gchar *name = text; - EekKey *key = eek_keyboard_find_key_by_name (data->keyboard, + struct squeek_button *button = eek_keyboard_find_button_by_name (data->keyboard, name); - if (key) { + if (button) { squeek_key_add_symbol( - eek_key_get_state(key), + squeek_button_get_key(button), element_name, text, data->keyval, @@ -887,8 +885,8 @@ eek_xml_layout_real_create_keyboard (EekLayout *self, GArray *outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline)); - // char* -> EekKey* - GHashTable *name_key_hash = + // char* -> struct squeek_button* + GHashTable *name_button_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, @@ -897,7 +895,7 @@ eek_xml_layout_real_create_keyboard (EekLayout *self, EekKeyboard *views[4] = {0}; GError *error = NULL; - retval = parse_geometry (path, views, outline_array, name_key_hash, &error); + retval = parse_geometry (path, views, outline_array, name_button_hash, &error); g_free (path); if (!retval) { for (uint i = 0; i < 4; i++) { @@ -911,7 +909,7 @@ eek_xml_layout_real_create_keyboard (EekLayout *self, } - LevelKeyboard *keyboard = level_keyboard_new(manager, views, name_key_hash); + LevelKeyboard *keyboard = level_keyboard_new(manager, views, name_button_hash); keyboard->outline_array = outline_array; // FIXME: are symbols shared betwen views? @@ -1129,7 +1127,7 @@ eek_xml_keyboard_desc_free (EekXmlKeyboardDesc *desc) } static gboolean -parse_geometry (const gchar *path, EekKeyboard **views, GArray *outline_array, GHashTable *name_key_hash, GError **error) +parse_geometry (const gchar *path, EekKeyboard **views, GArray *outline_array, GHashTable *name_button_hash, GError **error) { GeometryParseData *data; GMarkupParseContext *pcontext; @@ -1146,7 +1144,7 @@ parse_geometry (const gchar *path, EekKeyboard **views, GArray *outline_array, G if (input == NULL) return FALSE; - data = geometry_parse_data_new (views, name_key_hash, outline_array); + data = geometry_parse_data_new (views, name_button_hash, outline_array); pcontext = g_markup_parse_context_new (&geometry_parser, 0, data, @@ -1357,7 +1355,7 @@ validate (const gchar **valid_path_list, GSList *element_stack, GError **error) { - gint i; + guint i; gchar *element_path; GSList *head, *p; GString *string; diff --git a/eek/eek.h b/eek/eek.h index 6f0abcb4..44f16c51 100644 --- a/eek/eek.h +++ b/eek/eek.h @@ -24,7 +24,6 @@ #include "eek-keyboard.h" #include "eek-section.h" -#include "eek-key.h" #include "eek-layout.h" #include "eek-keysym.h" #include "eek-serializable.h" diff --git a/src/keyboard.rs b/src/keyboard.rs index 7aec925b..5c7b203f 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -28,9 +28,20 @@ pub mod c { /// Since C doesn't respect borrowing rules, /// RefCell will enforce them dynamically (only 1 writer/many readers) /// Rc is implied and will ensure timely dropping + #[repr(transparent)] pub struct CKeyState(*const RefCell); + + impl Clone for CKeyState { + fn clone(&self) -> Self { + CKeyState(self.0.clone()) + } + } + impl CKeyState { - fn unwrap(self) -> Rc> { + pub fn wrap(state: Rc>) -> CKeyState { + CKeyState(Rc::into_raw(state)) + } + pub fn unwrap(self) -> Rc> { unsafe { Rc::from_raw(self.0) } } fn to_owned(self) -> KeyState { @@ -67,7 +78,7 @@ pub mod c { symbol: None, } )); - CKeyState(Rc::into_raw(state)) + CKeyState::wrap(state) } #[no_mangle] @@ -195,8 +206,8 @@ pub mod c { fn squeek_key_get_symbol(key: CKeyState) -> *const symbol::Symbol { key.borrow_mut(|key| { match key.symbol { - /// This pointer stays after the function exits, - /// so it must reference borrowed data and not any copy + // This pointer stays after the function exits, + // so it must reference borrowed data and not any copy Some(ref symbol) => symbol as *const symbol::Symbol, None => ptr::null(), } @@ -239,13 +250,51 @@ pub mod c { .expect("Couldn't convert string") .into_raw() } + + #[no_mangle] + pub extern "C" + fn squeek_key_get_action_name( + key_name: *const c_char, + key: CKeyState, + ) -> *const c_char { + let key_name = as_cstr(&key_name) + .expect("Missing key name") + .to_str() + .expect("Bad key name"); + + let symbol_name = match key.to_owned().symbol { + Some(ref symbol) => match &symbol.action { + symbol::Action::Submit { text: Some(text), .. } => { + Some( + text.clone() + .into_string().expect("Bad symbol") + ) + }, + _ => None + }, + None => { + eprintln!("Key {} has no symbol", key_name); + None + }, + }; + + let inner = match symbol_name { + Some(name) => format!("[ {} ]", name), + _ => format!("[ ]"), + }; + + CString::new(format!(" key <{}> {{ {} }};\n", key_name, inner)) + .expect("Couldn't convert string") + .into_raw() + } + } #[derive(Debug, Clone)] pub struct KeyState { - pressed: bool, - locked: bool, - keycode: u32, + pub pressed: bool, + pub locked: bool, + pub keycode: u32, // TODO: remove the optionality of a symbol - symbol: Option, + pub symbol: Option, } diff --git a/src/layout.h b/src/layout.h new file mode 100644 index 00000000..9b308025 --- /dev/null +++ b/src/layout.h @@ -0,0 +1,40 @@ +#ifndef __LAYOUT_H +#define __LAYOUT_H + +#include "inttypes.h" + +#include "eek/eek-container.h" +#include "src/keyboard.h" + +struct squeek_button; + +/* +struct squeek_buttons; + +typedef void (*ButtonCallback) (struct squeek_button *button, gpointer user_data); + +struct squeek_buttons *squeek_buttons_new(); +void squeek_buttons_free(struct squeek_buttons*); +void squeek_buttons_foreach(const struct squeek_buttons*, + ButtonCallback callback, + gpointer user_data); +struct squeek_button *squeek_buttons_find_by_position( + const struct squeek_buttons *buttons, + double x, double y, + double origin_x, double origin_y, + double angle); +void squeek_buttons_add(struct squeek_buttons*, const struct squeek_button* button); +void squeek_buttons_remove_key(struct squeek_buttons*, const struct squeek_key* key); +*/ +struct squeek_button *squeek_button_new(uint32_t keycode, uint32_t oref); +struct squeek_button *squeek_button_new_with_state(const struct squeek_button* source); +uint32_t squeek_button_get_oref(const struct squeek_button*); +EekBounds squeek_button_get_bounds(const struct squeek_button*); +void squeek_button_set_bounds(struct squeek_button* button, EekBounds bounds); + +struct squeek_symbol *squeek_button_get_symbol ( + const struct squeek_button *button); +struct squeek_key *squeek_button_get_key(struct squeek_button*); +uint32_t *squeek_button_has_key(const struct squeek_button* button, + const struct squeek_key *key); +#endif diff --git a/src/layout.rs b/src/layout.rs new file mode 100644 index 00000000..711d4e56 --- /dev/null +++ b/src/layout.rs @@ -0,0 +1,147 @@ +use std::cell::RefCell; +use std::rc::Rc; + +use ::symbol::*; +use ::keyboard::*; + +/// Gathers stuff defined in C or called by C +pub mod c { + use super::*; + + use std::ptr; + + // The following defined in C + + /// The index in the relevant outline table + #[repr(C)] + #[derive(Clone)] + pub struct OutlineRef(u32); + + /// Defined in eek-types.h + #[repr(C)] + #[derive(Clone)] + pub struct Bounds { + x: f64, + y: f64, + width: f64, + height: f64 + } + + #[no_mangle] + pub extern "C" + fn squeek_button_new(keycode: u32, oref: u32) -> *mut ::layout::Button { + let state: Rc> = Rc::new(RefCell::new( + ::keyboard::KeyState { + pressed: false, + locked: false, + keycode: keycode, + symbol: None, + } + )); + Box::into_raw(Box::new(::layout::Button { + oref: OutlineRef(oref), + bounds: None, + state: state, + })) + } + + #[no_mangle] + pub extern "C" + fn squeek_button_new_with_state(source: *mut ::layout::Button) -> *mut ::layout::Button { + let source = unsafe { &*source }; + let button = Box::new(source.clone()); + Box::into_raw(button) + } + + #[no_mangle] + pub extern "C" + fn squeek_button_get_oref(button: *const ::layout::Button) -> u32 { + let button = unsafe { &*button }; + button.oref.0 + } + + // Bounds transparently mapped to C, therefore no pointer needed + + #[no_mangle] + pub extern "C" + fn squeek_button_get_bounds(button: *const ::layout::Button) -> Bounds { + let button = unsafe { &*button }; + match &button.bounds { + Some(bounds) => bounds.clone(), + None => panic!("Button doesn't have any bounds yet"), + } + } + + /// Set bounds by consuming the value + #[no_mangle] + pub extern "C" + fn squeek_button_set_bounds(button: *mut ::layout::Button, bounds: Bounds) { + let button = unsafe { &mut *button }; + button.bounds = Some(bounds); + } + + /// Borrow a new reference to key state. Doesn't need freeing + #[no_mangle] + pub extern "C" + fn squeek_button_get_key( + button: *mut ::layout::Button + ) -> ::keyboard::c::CKeyState { + let button = unsafe { &mut *button }; + ::keyboard::c::CKeyState::wrap(button.state.clone()) + } + + /// Really should just return the label + #[no_mangle] + pub extern "C" + fn squeek_button_get_symbol( + button: *const ::layout::Button, + ) -> *const Symbol { + let button = unsafe { &*button }; + let state = button.state.borrow(); + match state.symbol { + Some(ref symbol) => symbol as *const Symbol, + None => ptr::null(), + } + } + + #[no_mangle] + pub extern "C" + fn squeek_button_has_key( + button: *const ::layout::Button, + state: ::keyboard::c::CKeyState, + ) -> u32 { + let button = unsafe { &*button }; + let state = state.unwrap(); + let equal = Rc::ptr_eq(&button.state, &state); + Rc::into_raw(state); // Prevent dropping + equal as u32 + } + + #[cfg(test)] + mod test { + use super::*; + + #[test] + fn button_has_key() { + let button = squeek_button_new(0, 0); + let state = squeek_button_get_key(button); + assert_eq!(squeek_button_has_key(button, state.clone()), 1); + let other_button = squeek_button_new(0, 0); + assert_eq!(squeek_button_has_key(other_button, state.clone()), 0); + let other_state = ::keyboard::c::squeek_key_new(0); + assert_eq!(squeek_button_has_key(button, other_state), 0); + let shared_button = squeek_button_new_with_state(button); + assert_eq!(squeek_button_has_key(shared_button, state), 1); + } + } +} + +/// The graphical representation of a button +#[derive(Clone)] +pub struct Button { + oref: c::OutlineRef, + /// TODO: abolish Option, buttons should be created with bounds fully formed + bounds: Option, + /// current state, shared with other buttons + pub state: Rc>, +} diff --git a/src/lib.rs b/src/lib.rs index c863f5df..f6b3b319 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,5 +3,6 @@ mod bitflags; mod imservice; mod keyboard; +mod layout; mod symbol; mod util; diff --git a/src/meson.build b/src/meson.build index 32a6555e..443f7cb8 100644 --- a/src/meson.build +++ b/src/meson.build @@ -19,7 +19,6 @@ sources = [ '../eek/eek-container.c', '../eek/eek-element.c', '../eek/eek-gtk-keyboard.c', - '../eek/eek-key.c', '../eek/eek-keyboard.c', '../eek/eek-keyboard-drawing.c', '../eek/eek-keysym.c', diff --git a/tests/eek-simple-test.c b/tests/eek-simple-test.c index 45fdbe51..de2a491b 100644 --- a/tests/eek-simple-test.c +++ b/tests/eek-simple-test.c @@ -26,15 +26,15 @@ test_create (void) { EekKeyboard *keyboard; EekSection *section; - EekKey *key0, *key1; + struct squeek_button *button0, *button1; keyboard = g_object_new (EEK_TYPE_KEYBOARD, NULL); section = eek_keyboard_real_create_section (keyboard); g_assert (EEK_IS_SECTION(section)); - key0 = eek_section_create_key (section, "key0", 1, 0); - g_assert (EEK_IS_KEY(key0)); - key1 = eek_section_create_key (section, "key1", 2, 0); - g_assert (EEK_IS_KEY(key1)); + button0 = eek_section_create_button (section, "key0", 1, 0); + g_assert (button0); + button1 = eek_section_create_button (section, "key1", 2, 0); + g_assert (button1); } int