layouts: Change type based on shape

This commit is contained in:
Dorota Czaplejewicz
2019-10-15 15:42:24 +00:00
parent 264d30d884
commit 1b1fbed7de
9 changed files with 116 additions and 49 deletions

View File

@ -31,9 +31,10 @@
LevelKeyboard *
eek_xml_layout_real_create_keyboard (const char *keyboard_type,
EekboardContextService *manager)
EekboardContextService *manager,
enum layout_type t)
{
struct squeek_layout *layout = squeek_load_layout(keyboard_type);
struct squeek_layout *layout = squeek_load_layout(keyboard_type, t);
squeek_layout_place_contents(layout);
return level_keyboard_new(manager, layout);
}

View File

@ -24,10 +24,13 @@
#define EEK_XML_LAYOUT_H 1
#include "eek-types.h"
#include "src/layout.h"
G_BEGIN_DECLS
LevelKeyboard *
eek_xml_layout_real_create_keyboard (const char *keyboard_type,
EekboardContextService *manager);
EekboardContextService *manager,
enum layout_type t);
G_END_DECLS
#endif /* EEK_XML_LAYOUT_H */

View File

@ -41,12 +41,10 @@
#include "wayland.h"
#include "eek/eek-xml-layout.h"
#include "src/server-context-service.h"
#include "eekboard/eekboard-context-service.h"
#define CSW 640
#define CSH 480
enum {
PROP_0, // Magic: without this, keyboard is not useable in g_object_notify
PROP_KEYBOARD,
@ -73,10 +71,6 @@ struct _EekboardContextServicePrivate {
LevelKeyboard *keyboard; // currently used keyboard
GHashTable *keyboard_hash; // a table of available keyboards, per layout
// TODO: make use of repeating buttons
guint repeat_timeout_id;
gboolean repeat_triggered;
GSettings *settings;
uint32_t hint;
uint32_t purpose;
@ -86,9 +80,10 @@ G_DEFINE_TYPE_WITH_PRIVATE (EekboardContextService, eekboard_context_service, G_
static LevelKeyboard *
eekboard_context_service_real_create_keyboard (EekboardContextService *self,
const gchar *keyboard_type)
const gchar *keyboard_type,
enum layout_type t)
{
LevelKeyboard *keyboard = eek_xml_layout_real_create_keyboard(keyboard_type, self);
LevelKeyboard *keyboard = eek_xml_layout_real_create_keyboard(keyboard_type, self, t);
if (!keyboard) {
g_error("Failed to create a keyboard");
}
@ -231,8 +226,8 @@ settings_get_layout(GSettings *settings, char **type, char **layout)
g_variant_unref(inputs);
}
static void
settings_update_layout(EekboardContextService *context)
void
eekboard_context_service_update_layout(EekboardContextService *context, enum layout_type t)
{
g_autofree gchar *keyboard_type = NULL;
g_autofree gchar *keyboard_layout = NULL;
@ -262,7 +257,7 @@ settings_update_layout(EekboardContextService *context)
GUINT_TO_POINTER(keyboard_id));
// create a keyboard
if (!keyboard) {
keyboard = eekboard_context_service_real_create_keyboard(context, keyboard_layout);
keyboard = eekboard_context_service_real_create_keyboard(context, keyboard_layout, t);
g_hash_table_insert (context->priv->keyboard_hash,
GUINT_TO_POINTER(keyboard_id),
@ -272,11 +267,14 @@ settings_update_layout(EekboardContextService *context)
}
// set as current
context->priv->keyboard = keyboard;
// TODO: this used to save the group, why?
//group = eek_element_get_group (EEK_ELEMENT(context->priv->keyboard));
g_object_notify (G_OBJECT(context), "keyboard");
}
static void update_layout_and_type(EekboardContextService *context) {
eekboard_context_service_update_layout(context, server_context_service_get_layout_type(context));
}
static gboolean
settings_handle_layout_changed(GSettings *s,
gpointer keys, gint n_keys,
@ -285,7 +283,7 @@ settings_handle_layout_changed(GSettings *s,
(void)keys;
(void)n_keys;
EekboardContextService *context = user_data;
settings_update_layout(context);
update_layout_and_type(context);
return TRUE;
}
@ -299,7 +297,7 @@ eekboard_context_service_constructed (GObject *object)
if (!context->virtual_keyboard) {
g_error("Programmer error: Failed to receive a virtual keyboard instance");
}
settings_update_layout(context);
update_layout_and_type(context);
}
static void
@ -518,6 +516,6 @@ void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
if (priv->hint != hint || priv->purpose != purpose) {
priv->hint = hint;
priv->purpose = purpose;
settings_update_layout(context);
update_layout_and_type(context);
}
}

View File

@ -105,6 +105,7 @@ void eekboard_context_service_set_keymap(EekboardContextService *context,
void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
uint32_t hint,
uint32_t purpose);
void
eekboard_context_service_update_layout(EekboardContextService *context, enum layout_type t);
G_END_DECLS
#endif /* EEKBOARD_CONTEXT_SERVICE_H */

View File

@ -36,12 +36,20 @@ pub mod c {
#[no_mangle]
pub extern "C"
fn squeek_load_layout(name: *const c_char) -> *mut ::layout::Layout {
fn squeek_load_layout(
name: *const c_char,
type_: u32,
) -> *mut ::layout::Layout {
let type_ = match type_ {
0 => LayoutType::Base,
1 => LayoutType::Wide,
_ => panic!("Bad enum value"),
};
let name = as_str(&name)
.expect("Bad layout name")
.expect("Empty layout name");
let layout = load_layout_with_fallback(name);
let layout = load_layout_with_fallback(&name, type_);
Box::into_raw(Box::new(layout))
}
}
@ -68,6 +76,20 @@ impl fmt::Display for LoadError {
}
}
pub enum LayoutType {
Base = 0,
Wide = 1,
}
impl LayoutType {
fn apply_to_name(&self, name: String) -> String {
match self {
LayoutType::Base => name,
LayoutType::Wide => name + "_wide",
}
}
}
#[derive(Debug, Clone, PartialEq)]
enum DataSource {
File(PathBuf),
@ -86,22 +108,35 @@ impl fmt::Display for DataSource {
/// Lists possible sources, with 0 as the most preferred one
fn list_layout_sources(
name: &str,
keyboards_path: Option<PathBuf>
type_: LayoutType,
keyboards_path: Option<PathBuf>,
) -> Vec<DataSource> {
let mut ret = Vec::new();
if let Some(path) = keyboards_path.clone() {
ret.push(DataSource::File(path.join(name).with_extension("yaml")))
}
ret.push(DataSource::Resource(name.to_owned()));
let mut add_by_name = |name: &str| {
if let Some(path) = keyboards_path.clone() {
ret.push(DataSource::File(
path.join(FALLBACK_LAYOUT_NAME).with_extension("yaml")
path.join(name.to_owned()).with_extension("yaml")
))
}
ret.push(DataSource::Resource(FALLBACK_LAYOUT_NAME.to_owned()));
ret.push(DataSource::Resource(name.into()));
};
match &type_ {
LayoutType::Base => {},
type_ => add_by_name(&type_.apply_to_name(name.into())),
};
add_by_name(name);
match &type_ {
LayoutType::Base => {},
type_ => add_by_name(&type_.apply_to_name(FALLBACK_LAYOUT_NAME.into())),
};
add_by_name(FALLBACK_LAYOUT_NAME);
ret
}
@ -124,13 +159,14 @@ fn load_layout(source: DataSource) -> Result<::layout::Layout, LoadError> {
}
fn load_layout_with_fallback(
name: &str
name: &str,
type_: LayoutType,
) -> ::layout::Layout {
let path = env::var_os("SQUEEKBOARD_KEYBOARDSDIR")
.map(PathBuf::from)
.or_else(|| xdg::data_path("squeekboard/keyboards"));
for source in list_layout_sources(name, path) {
for source in list_layout_sources(name, type_, path) {
let layout = load_layout(source.clone());
match layout {
Err(e) => match (e, source) {
@ -665,7 +701,7 @@ mod tests {
/// First fallback should be to builtin, not to FALLBACK_LAYOUT_NAME
#[test]
fn fallbacks_order() {
let sources = list_layout_sources("nb", None);
let sources = list_layout_sources("nb", LayoutType::Base, None);
assert_eq!(
sources,

View File

@ -9,6 +9,11 @@
#include "src/keyboard.h"
#include "virtual-keyboard-unstable-v1-client-protocol.h"
enum layout_type {
LAYOUT_TYPE_BASE = 0,
LAYOUT_TYPE_WIDE = 1,
};
struct squeek_button;
struct squeek_row;
struct squeek_view;
@ -52,7 +57,7 @@ void
squeek_layout_place_contents(struct squeek_layout*);
struct squeek_view *squeek_layout_get_current_view(struct squeek_layout*);
struct squeek_layout *squeek_load_layout(const char *type);
struct squeek_layout *squeek_load_layout(const char *name, uint32_t type);
const char *squeek_layout_get_keymap(const struct squeek_layout*);
void squeek_layout_free(struct squeek_layout*);

View File

@ -210,7 +210,7 @@ pub mod c {
match output_state {
Some(OutputState {
current_mode: Some(super::Mode { width, height: _ } ),
scale: scale,
scale,
}) => width / scale,
_ => {
eprintln!("No width registered on output");

View File

@ -39,10 +39,11 @@ typedef struct _ServerContextServiceClass ServerContextServiceClass;
struct _ServerContextService {
EekboardContextService parent;
GtkWidget *window;
PhoshLayerSurface *window;
GtkWidget *widget;
guint hiding;
guint last_requested_height;
enum layout_type last_type;
gdouble size_constraint_landscape[2];
gdouble size_constraint_portrait[2];
@ -59,7 +60,7 @@ on_destroy (GtkWidget *widget, gpointer user_data)
{
ServerContextService *context = user_data;
g_assert (widget == context->window);
g_assert (widget == GTK_WIDGET(context->window));
context->window = NULL;
context->widget = NULL;
@ -127,15 +128,30 @@ calculate_height(int32_t width)
return height;
}
enum layout_type get_type(uint32_t width, uint32_t height) {
(void)height;
if (width < 540) {
return LAYOUT_TYPE_BASE;
}
return LAYOUT_TYPE_WIDE;
}
static void
on_surface_configure(PhoshLayerSurface *surface, ServerContextService *context)
{
gint width;
gint height;
g_object_get(G_OBJECT(surface),
"width", &width,
"height", &height,
"configured-width", &width,
"configured-height", &height,
NULL);
// check if the change would switch types
enum layout_type new_type = get_type((uint32_t)width, (uint32_t)height);
if (context->last_type != new_type) {
context->last_type = new_type;
eekboard_context_service_update_layout(EEKBOARD_CONTEXT_SERVICE(context), context->last_type);
}
guint desired_height = calculate_height(width);
guint configured_height = (guint)height;
// if height was already requested once but a different one was given
@ -190,7 +206,7 @@ make_window (ServerContextService *context)
// and there's no space in the protocol for others.
// Those may still be useful in the future,
// or for hacks with regular windows.
gtk_widget_set_can_focus (context->window, FALSE);
gtk_widget_set_can_focus (GTK_WIDGET(context->window), FALSE);
g_object_set (G_OBJECT(context->window), "accept_focus", FALSE, NULL);
gtk_window_set_title (GTK_WINDOW(context->window),
_("Squeekboard"));
@ -239,13 +255,13 @@ server_context_service_real_show_keyboard (EekboardContextService *_context)
EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)->
show_keyboard (_context);
gtk_widget_show (context->window);
gtk_widget_show (GTK_WIDGET(context->window));
}
static gboolean
on_hide (ServerContextService *context)
{
gtk_widget_hide (context->window);
gtk_widget_hide (GTK_WIDGET(context->window));
context->hiding = 0;
return G_SOURCE_REMOVE;
@ -357,3 +373,8 @@ server_context_service_new ()
{
return EEKBOARD_CONTEXT_SERVICE(g_object_new (SERVER_TYPE_CONTEXT_SERVICE, NULL));
}
enum layout_type server_context_service_get_layout_type(EekboardContextService *service)
{
return SERVER_CONTEXT_SERVICE(service)->last_type;
}

View File

@ -19,6 +19,7 @@
#define SERVER_CONTEXT_SERVICE_H 1
#include "eekboard/eekboard-service.h"
#include "src/layout.h"
G_BEGIN_DECLS
@ -33,6 +34,7 @@ G_BEGIN_DECLS
typedef struct _ServerContextService ServerContextService;
EekboardContextService *server_context_service_new ();
enum layout_type server_context_service_get_layout_type(EekboardContextService*);
G_END_DECLS
#endif /* SERVER_CONTEXT_SERVICE_H */