From 82774d2315a505d51fca5ab90ed6ff59b71be40d Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Wed, 1 Jun 2022 18:15:21 +0000 Subject: [PATCH] state: Record layout choice This does not get plugged into anything but debug prints yet. --- eekboard/eekboard-context-service.c | 7 ++++++- eekboard/eekboard-context-service.h | 3 ++- src/event_loop/driver.rs | 31 ++++++++++++++++++++++++++++- src/main.h | 1 + src/manager.rs | 2 +- src/server-main.c | 2 +- src/state.rs | 30 ++++++++++++++++++++++++++-- 7 files changed, 69 insertions(+), 7 deletions(-) diff --git a/eekboard/eekboard-context-service.c b/eekboard/eekboard-context-service.c index ec1ac005..5ad80771 100644 --- a/eekboard/eekboard-context-service.c +++ b/eekboard/eekboard-context-service.c @@ -56,6 +56,8 @@ static guint signals[LAST_SIGNAL] = { 0, }; struct _EekboardContextService { GObject parent; struct squeek_layout_state *layout; // Unowned + // FIXME: replaces layout + struct squeek_state_manager *state_manager; // shared reference LevelKeyboard *keyboard; // currently used keyboard GSettings *settings; // Owned reference @@ -169,6 +171,8 @@ static void eekboard_context_service_update_settings_layout(EekboardContextServi settings_get_layout(context->settings, &keyboard_type, &keyboard_layout); + squeek_state_send_layout_set(context->state_manager, keyboard_layout, keyboard_type, gdk_event_get_time(NULL)); + if (g_strcmp0(context->layout->layout_name, keyboard_layout) != 0 || context->layout->overlay_name) { g_free(context->layout->overlay_name); context->layout->overlay_name = NULL; @@ -325,10 +329,11 @@ eekboard_context_service_get_overlay(EekboardContextService *context) { return context->layout->overlay_name; } -EekboardContextService *eekboard_context_service_new(struct squeek_layout_state *state) +EekboardContextService *eekboard_context_service_new(struct squeek_state_manager *state_manager, struct squeek_layout_state *state) { EekboardContextService *context = g_object_new (EEKBOARD_TYPE_CONTEXT_SERVICE, NULL); context->layout = state; + context->state_manager = state_manager; eekboard_context_service_update_settings_layout(context); uint32_t time = gdk_event_get_time(NULL); eekboard_context_service_use_layout(context, context->layout, time); diff --git a/eekboard/eekboard-context-service.h b/eekboard/eekboard-context-service.h index 4b2e706a..40d8ba31 100644 --- a/eekboard/eekboard-context-service.h +++ b/eekboard/eekboard-context-service.h @@ -24,6 +24,7 @@ #include "src/submission.h" #include "src/layout.h" +#include "src/main.h" #include "virtual-keyboard-unstable-v1-client-protocol.h" #include "text-input-unstable-v3-client-protocol.h" @@ -37,7 +38,7 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(EekboardContextService, eekboard_context_service, EEKBOARD, CONTEXT_SERVICE, GObject) -EekboardContextService *eekboard_context_service_new(struct squeek_layout_state *state); +EekboardContextService *eekboard_context_service_new(struct squeek_state_manager *state_manager, struct squeek_layout_state *state); void eekboard_context_service_set_submission(EekboardContextService *context, struct submission *submission); void eekboard_context_service_destroy (EekboardContextService *context); LevelKeyboard *eekboard_context_service_get_keyboard(EekboardContextService *context); diff --git a/src/event_loop/driver.rs b/src/event_loop/driver.rs index c60a14bc..dcc22da5 100644 --- a/src/event_loop/driver.rs +++ b/src/event_loop/driver.rs @@ -39,7 +39,9 @@ type UISender = glib::Sender; /// It sends outcomes to the glib main loop using a channel. /// The outcomes are applied by the UI end of the channel in the `main` module. // This could still be reasonably tested, -// by creating a glib::Sender and checking what messages it receives. +/// by creating a glib::Sender and checking what messages it receives. +// This can/should be abstracted over Event and Commands, +// so that the C call-ins can be thrown away from here and defined near events. #[derive(Clone)] pub struct Threaded { thread: Sender, @@ -108,8 +110,11 @@ mod c { use super::*; use crate::state::Presence; + use crate::state::LayoutChoice; use crate::state::visibility; + use crate::util; use crate::util::c::Wrapped; + use std::os::raw::c_char; #[no_mangle] pub extern "C" @@ -140,4 +145,28 @@ mod c { sender.send(Event::PhysicalKeyboard(state)) .or_warn(&mut logging::Print, logging::Problem::Warning, "Can't send to state manager"); } + + #[no_mangle] + pub extern "C" + fn squeek_state_send_layout_set( + sender: Wrapped, + name: *const c_char, + source: *const c_char, + // TODO: use when synthetic events are needed + _timestamp: u32, + ) { + let sender = sender.clone_ref(); + let sender = sender.borrow(); + let string_or_empty = |v| String::from( + util::c::as_str(v) + .unwrap_or(Some("")) + .unwrap_or("") + ); + sender + .send(Event::LayoutChoice(LayoutChoice { + name: string_or_empty(&name), + source: string_or_empty(&source).into(), + })) + .or_warn(&mut logging::Print, logging::Problem::Warning, "Can't send to state manager"); + } } diff --git a/src/main.h b/src/main.h index 9b1c14d1..ba6be72b 100644 --- a/src/main.h +++ b/src/main.h @@ -33,3 +33,4 @@ void squeek_state_send_force_visible(struct squeek_state_manager *state); void squeek_state_send_force_hidden(struct squeek_state_manager *state); void squeek_state_send_keyboard_present(struct squeek_state_manager *state, uint32_t keyboard_present); +void squeek_state_send_layout_set(struct squeek_state_manager *state, char *name, char *layout, uint32_t timestamp); diff --git a/src/manager.rs b/src/manager.rs index 55fc561a..eb253411 100644 --- a/src/manager.rs +++ b/src/manager.rs @@ -1,5 +1,5 @@ /*! Procedures relating to the management of the switching of layouts */ -use ::util; +use crate::util; pub mod c { use std::os::raw::{c_char, c_void}; diff --git a/src/server-main.c b/src/server-main.c index 4807053c..db4f677f 100644 --- a/src/server-main.c +++ b/src/server-main.c @@ -400,7 +400,7 @@ main (int argc, char **argv) // Also initializes wayland struct rsobjects rsobjects = squeek_init(); - instance.settings_context = eekboard_context_service_new(&instance.layout_choice); + instance.settings_context = eekboard_context_service_new(rsobjects.state_manager, &instance.layout_choice); // set up dbus diff --git a/src/state.rs b/src/state.rs index a9b7cca4..55f1082d 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Purism SPC +/* Copyright (C) 2021,2022 Purism SPC * SPDX-License-Identifier: GPL-3.0+ */ @@ -37,6 +37,29 @@ pub enum InputMethod { InactiveSince(Instant), } +#[derive(Clone, Debug)] +pub enum LayoutSource { + Xkb, + Other(String), +} + +impl From for LayoutSource { + fn from(v: String) -> Self { + if v.as_str() == "xkb" { + LayoutSource::Xkb + } else { + LayoutSource::Other(v) + } + } +} + +/// The user's preferred layout +#[derive(Clone, Debug)] +pub struct LayoutChoice { + pub name: String, + pub source: LayoutSource, +} + /// Incoming events. /// This contains events that cause a change to the internal state. #[derive(Clone, Debug)] @@ -45,6 +68,7 @@ pub enum Event { Visibility(visibility::Event), PhysicalKeyboard(Presence), Output(outputs::Event), + LayoutChoice(LayoutChoice), Debug(debug::Event), /// Event triggered because a moment in time passed. /// Use to animate state transitions. @@ -257,7 +281,9 @@ impl Application { im: InputMethod::InactiveSince(old), ..self }, - } + }, + + Event::LayoutChoice(LayoutChoice { name, source }) => self, }; if state.debug_mode_enabled {