layouts: Change type based on shape
This commit is contained in:
@ -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);
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
74
src/data.rs
74
src/data.rs
@ -33,15 +33,23 @@ use serde::Deserialize;
|
||||
pub mod c {
|
||||
use super::*;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
|
||||
#[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()));
|
||||
|
||||
if let Some(path) = keyboards_path.clone() {
|
||||
ret.push(DataSource::File(
|
||||
path.join(FALLBACK_LAYOUT_NAME).with_extension("yaml")
|
||||
))
|
||||
}
|
||||
|
||||
ret.push(DataSource::Resource(FALLBACK_LAYOUT_NAME.to_owned()));
|
||||
let mut add_by_name = |name: &str| {
|
||||
if let Some(path) = keyboards_path.clone() {
|
||||
ret.push(DataSource::File(
|
||||
path.join(name.to_owned()).with_extension("yaml")
|
||||
))
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
@ -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*);
|
||||
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user