eekkey: Dropped in favor of Button

Each Button has a KeyState, which may be shared with other buttons. The list of pressed and locked buttons is used as a list of keys, causing a search for the button in the current view.
This commit is contained in:
Dorota Czaplejewicz
2019-08-14 11:40:46 +00:00
parent 5630cf31f1
commit 6fc351d2e8
17 changed files with 631 additions and 735 deletions

View File

@ -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

View File

@ -1,277 +0,0 @@
/*
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
* 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 <string.h>
#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;
}

View File

@ -1,72 +0,0 @@
/*
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
* 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 <eek/eek.h> 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 */

View File

@ -31,7 +31,6 @@
#include <glib/gprintf.h>
#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;
}

View File

@ -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

View File

@ -24,7 +24,6 @@
#include <string.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#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), &section_bounds);
EekBounds button_bounds = squeek_button_get_bounds(place->button);
eek_element_get_bounds (EEK_ELEMENT(place->section), &section_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;
}

View File

@ -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);

View File

@ -32,7 +32,7 @@
#include <string.h>
#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), &section_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), &section_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
}

View File

@ -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 */

View File

@ -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;

View File

@ -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"

View File

@ -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<KeyState>);
impl Clone for CKeyState {
fn clone(&self) -> Self {
CKeyState(self.0.clone())
}
}
impl CKeyState {
fn unwrap(self) -> Rc<RefCell<KeyState>> {
pub fn wrap(state: Rc<RefCell<KeyState>>) -> CKeyState {
CKeyState(Rc::into_raw(state))
}
pub fn unwrap(self) -> Rc<RefCell<KeyState>> {
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<symbol::Symbol>,
pub symbol: Option<symbol::Symbol>,
}

40
src/layout.h Normal file
View File

@ -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

147
src/layout.rs Normal file
View File

@ -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<RefCell<::keyboard::KeyState>> = 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<c::Bounds>,
/// current state, shared with other buttons
pub state: Rc<RefCell<KeyState>>,
}

View File

@ -3,5 +3,6 @@ mod bitflags;
mod imservice;
mod keyboard;
mod layout;
mod symbol;
mod util;

View File

@ -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',

View File

@ -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