diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index 2c2c953e..bb6a6427 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -35,6 +35,7 @@ #include "eekboard/eekboard-context-service.h" #include "src/layout.h" +#include "src/popover.h" #include "src/submission.h" #define LIBFEEDBACK_USE_UNSTABLE_API @@ -48,6 +49,7 @@ typedef struct _EekGtkKeyboardPrivate struct render_geometry render_geometry; // mutable EekboardContextService *eekboard_context; // unowned reference + struct squeek_popover *popover; // shared reference struct squeek_state_manager *state_manager; // shared reference struct submission *submission; // unowned reference @@ -119,15 +121,6 @@ eek_gtk_keyboard_real_draw (GtkWidget *self, return FALSE; } -// Units of virtual pixels size -static enum squeek_arrangement_kind get_type(uint32_t width, uint32_t height) { - (void)height; - if (width < 540) { - return ARRANGEMENT_KIND_BASE; - } - return ARRANGEMENT_KIND_WIDE; -} - static void eek_gtk_keyboard_real_size_allocate (GtkWidget *self, GtkAllocation *allocation) @@ -135,15 +128,6 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget *self, EekGtkKeyboard *keyboard = EEK_GTK_KEYBOARD (self); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (keyboard); - // check if the change would switch types - enum squeek_arrangement_kind new_type = get_type( - (uint32_t)(allocation->width - allocation->x), - (uint32_t)(allocation->height - allocation->y)); - if (priv->layout->arrangement != new_type) { - priv->layout->arrangement = new_type; - uint32_t time = gdk_event_get_time(NULL); - eekboard_context_service_use_layout(priv->eekboard_context, priv->layout, time); - } if (priv->renderer) { set_allocation_size (keyboard, priv->keyboard->layout, @@ -190,7 +174,7 @@ static void drag(EekGtkKeyboard *self, squeek_layout_drag(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout, priv->submission, x, y, priv->render_geometry.widget_to_layout, time, - priv->eekboard_context, priv->state_manager, self); + priv->popover, priv->state_manager, self); } static void release(EekGtkKeyboard *self, guint32 time) @@ -201,7 +185,7 @@ static void release(EekGtkKeyboard *self, guint32 time) } squeek_layout_release(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout, priv->submission, priv->render_geometry.widget_to_layout, time, - priv->eekboard_context, priv->state_manager, self); + priv->popover, priv->state_manager, self); } static gboolean @@ -408,13 +392,14 @@ on_notify_keyboard (GObject *object, GtkWidget * eek_gtk_keyboard_new (EekboardContextService *eekservice, struct submission *submission, - struct squeek_layout_state *layout, struct squeek_state_manager *state_manager) + struct squeek_state_manager *state_manager, + struct squeek_popover *popover) { EekGtkKeyboard *ret = EEK_GTK_KEYBOARD(g_object_new (EEK_TYPE_GTK_KEYBOARD, NULL)); EekGtkKeyboardPrivate *priv = (EekGtkKeyboardPrivate*)eek_gtk_keyboard_get_instance_private (ret); + priv->popover = popover; priv->eekboard_context = eekservice; priv->submission = submission; - priv->layout = layout; priv->state_manager = state_manager; priv->renderer = NULL; // This should really be done on initialization. diff --git a/eek/eek-gtk-keyboard.h b/eek/eek-gtk-keyboard.h index 57fc9477..558d5849 100644 --- a/eek/eek-gtk-keyboard.h +++ b/eek/eek-gtk-keyboard.h @@ -31,6 +31,7 @@ #include "eek/eek-renderer.h" #include "eek/eek-types.h" #include "src/main.h" +#include "src/popover.h" struct submission; struct squeek_layout_state; @@ -49,7 +50,7 @@ struct _EekGtkKeyboardClass gpointer pdummy[24]; }; -GtkWidget *eek_gtk_keyboard_new (EekboardContextService *eekservice, struct submission *submission, struct squeek_layout_state *layout, struct squeek_state_manager *state_manager); +GtkWidget *eek_gtk_keyboard_new (EekboardContextService *eekservice, struct submission *submission, struct squeek_state_manager *state_manager, struct squeek_popover *popover); void eek_gtk_keyboard_emit_feedback (EekGtkKeyboard *self); G_END_DECLS diff --git a/eekboard/eekboard-context-service.c b/eekboard/eekboard-context-service.c index b06d9b75..92114a4e 100644 --- a/eekboard/eekboard-context-service.c +++ b/eekboard/eekboard-context-service.c @@ -55,8 +55,6 @@ 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 @@ -128,29 +126,6 @@ settings_get_layout(GSettings *settings, char **type, char **layout) g_variant_unref(inputs); } -void eekboard_context_service_set_layout(EekboardContextService *context, struct squeek_layout *layout, uint32_t timestamp); - -void -eekboard_context_service_use_layout(EekboardContextService *context, struct squeek_layout_state *state, uint32_t timestamp) { - gchar *layout_name = state->layout_name; - gchar *overlay_name = state->overlay_name; - - // try to get the best keyboard layout - if (layout_name == NULL) { - layout_name = "us"; - } - - // overlay is "Normal" for most layouts, we will only look for "terminal" in rust code. - // for now just avoid passing a null pointer - if (overlay_name == NULL) { - overlay_name = ""; // fallback to Normal - } - - // generic part follows - struct squeek_layout *layout = squeek_load_layout(layout_name, state->arrangement, state->purpose, overlay_name); - eekboard_context_service_set_layout(context, layout, timestamp); -} - void eekboard_context_service_set_layout(EekboardContextService *context, struct squeek_layout *layout, uint32_t timestamp) { LevelKeyboard *keyboard = level_keyboard_new(layout); // set as current @@ -178,18 +153,6 @@ static void eekboard_context_service_update_settings_layout(EekboardContextServi &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; - if (keyboard_layout) { - g_free(context->layout->layout_name); - context->layout->layout_name = g_strdup(keyboard_layout); - } - // This must actually update the UI. - uint32_t time = gdk_event_get_time(NULL); - eekboard_context_service_use_layout(context, context->layout, time); - } } static gboolean @@ -307,48 +270,17 @@ eekboard_context_service_get_keyboard (EekboardContextService *context) return context->keyboard; } -// Used from Rust. -// TODO: move hint management to Rust entirely -void eekboard_context_service_set_hint_purpose(EekboardContextService *context, - uint32_t hint, uint32_t purpose) -{ - if (context->layout->hint != hint || context->layout->purpose != purpose) { - context->layout->hint = hint; - context->layout->purpose = purpose; - uint32_t time = gdk_event_get_time(NULL); - eekboard_context_service_use_layout(context, context->layout, time); - } -} - -void -eekboard_context_service_set_overlay(EekboardContextService *context, const char* name) { - if (g_strcmp0(context->layout->overlay_name, name)) { - g_free(context->layout->overlay_name); - context->layout->overlay_name = g_strdup(name); - uint32_t time = gdk_event_get_time(NULL); - eekboard_context_service_use_layout(context, context->layout, time); - } -} - -const char* -eekboard_context_service_get_overlay(EekboardContextService *context) { - return context->layout->overlay_name; -} - -EekboardContextService *eekboard_context_service_new(struct squeek_state_manager *state_manager, struct squeek_layout_state *state) +EekboardContextService *eekboard_context_service_new(struct squeek_state_manager *state_manager) { 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); return context; } void eekboard_context_service_set_submission(EekboardContextService *context, struct submission *submission) { context->submission = submission; - if (context->submission) { + if (context->submission && context->keyboard) { uint32_t time = gdk_event_get_time(NULL); submission_use_layout(context->submission, context->keyboard->layout, time); } diff --git a/eekboard/eekboard-context-service.h b/eekboard/eekboard-context-service.h index 40d8ba31..50525d9f 100644 --- a/eekboard/eekboard-context-service.h +++ b/eekboard/eekboard-context-service.h @@ -38,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_state_manager *state_manager, struct squeek_layout_state *state); +EekboardContextService *eekboard_context_service_new(struct squeek_state_manager *state_manager); 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); @@ -46,7 +46,5 @@ LevelKeyboard *eekboard_context_service_get_keyboard(EekboardContextService *con void eekboard_context_service_set_keymap(EekboardContextService *context, const LevelKeyboard *keyboard); -void -eekboard_context_service_use_layout(EekboardContextService *context, struct squeek_layout_state *layout, uint32_t timestamp); G_END_DECLS #endif /* EEKBOARD_CONTEXT_SERVICE_H */ diff --git a/src/actors/mod.rs b/src/actors/mod.rs new file mode 100644 index 00000000..378da9eb --- /dev/null +++ b/src/actors/mod.rs @@ -0,0 +1,23 @@ +/* Copyright (C) 2022 Purism SPC + * SPDX-License-Identifier: GPL-3.0+ + */ + +/*! Actors are parts of Squeekboard containing state independent from the main application state. + +Because main application state is meant to be immutable, +it cannot be referenced directly by pieces of logic +interacting with the environment. + +Such impure logic is split away (actor's logic) +and combined with relevant pieces of state (actor state), +thus preserving the purity (and sometimes simplicity) of the main state. + +Actors can communicate with the main state by sending it messages, +and by receiving updates from it. +*/ + +// TODO: move crate::panel into crate::actors::panel. +// Panel contains state and logic to protect the main state from getting flooded +// with low-level wayland and gtk sizing events. + +pub mod popover; \ No newline at end of file diff --git a/src/actors/popover.rs b/src/actors/popover.rs new file mode 100644 index 00000000..e3020c2a --- /dev/null +++ b/src/actors/popover.rs @@ -0,0 +1,40 @@ +/* Copyright (C) 2022 Purism SPC + * SPDX-License-Identifier: GPL-3.0+ + */ + +/*! The popover is opened directly by the GTK surface, +without bouncing click events off the main state. +Then it must accurately show which layout has been selected. +It can get the system layout directly from gsettings on open, +but it cannot get the user-selected overlay, because it's stored in state. + +To solve this, overlay will be cached in the popover actor, +and updated by main state every time it changes. +*/ + +pub mod c { + use super::*; + use crate::util::c::Wrapped; + /// The mutable instance of state + pub type Actor = Wrapped; +} + +#[derive(Clone)] +pub struct State { + pub overlay: Option, +} + +impl State { + pub fn new() -> Self { + Self { overlay: None } + } +} + +pub fn set_overlay( + actor: &c::Actor, + overlay: Option, +) { + let actor = actor.clone_ref(); + let mut actor = actor.borrow_mut(); + actor.overlay = overlay; +} \ No newline at end of file diff --git a/src/data/loading.rs b/src/data/loading.rs index 2b173cd9..a00acae4 100644 --- a/src/data/loading.rs +++ b/src/data/loading.rs @@ -7,69 +7,16 @@ use std::env; use std::fmt; use std::path::PathBuf; -use std::convert::TryFrom; use super::{ Error, LoadError }; use super::parsing; use crate::layout; -use ::layout::ArrangementKind; -use ::logging; -use ::util::c::as_str; -use ::xdg; -use ::imservice::ContentPurpose; +use crate::layout::ArrangementKind; +use crate::logging; +use crate::xdg; +use crate::imservice::ContentPurpose; -// traits, derives -use ::logging::Warn; - - -/// Gathers stuff defined in C or called by C -pub mod c { - use super::*; - use std::os::raw::c_char; - - #[no_mangle] - pub extern "C" - fn squeek_load_layout( - name: *const c_char, // name of the keyboard - type_: u32, // type like Wide - variant: u32, // purpose variant like numeric, terminal... - // Overlay forces a variant other than specified - // (typically "terminal", "emoji") - overlay: *const c_char, - ) -> *mut layout::Layout { - let type_ = match type_ { - 0 => ArrangementKind::Base, - 1 => ArrangementKind::Wide, - _ => panic!("Bad enum value"), - }; - - let name = as_str(&name) - .expect("Bad layout name") - .expect("Empty layout name"); - - let variant = ContentPurpose::try_from(variant) - .or_print( - logging::Problem::Warning, - "Received invalid purpose value", - ) - .unwrap_or(ContentPurpose::Normal); - - let overlay_str = as_str(&overlay) - .expect("Bad overlay name") - .expect("Empty overlay name"); - let overlay_str = match overlay_str { - "" => None, - other => Some(other), - }; - - dbg!(&name, type_, variant, overlay_str); - - let (kind, layout) = load_layout_data_with_fallback(&name, type_, variant, overlay_str); - let layout = layout::Layout::new(layout, kind, variant); - Box::into_raw(Box::new(layout)) - } -} const FALLBACK_LAYOUT_NAME: &str = "us"; diff --git a/src/layout.h b/src/layout.h index b238a612..1d77876a 100644 --- a/src/layout.h +++ b/src/layout.h @@ -8,6 +8,7 @@ #include "eek/eek-renderer.h" #include "eek/eek-types.h" #include "src/main.h" +#include "src/popover.h" #include "src/submission.h" #include "virtual-keyboard-unstable-v1-client-protocol.h" #include "text-input-unstable-v3-client-protocol.h" @@ -41,7 +42,7 @@ void squeek_layout_release(struct squeek_layout *layout, struct submission *submission, struct transformation widget_to_layout, uint32_t timestamp, - EekboardContextService *manager, + struct squeek_popover *popover, struct squeek_state_manager *state, EekGtkKeyboard *ui_keyboard); void squeek_layout_release_all_only(struct squeek_layout *layout, @@ -56,7 +57,7 @@ void squeek_layout_drag(struct squeek_layout *layout, struct submission *submission, double x_widget, double y_widget, struct transformation widget_to_layout, - uint32_t timestamp, EekboardContextService *manager, + uint32_t timestamp, struct squeek_popover *popover, struct squeek_state_manager *state, EekGtkKeyboard *ui_keyboard); void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr, struct submission *submission); diff --git a/src/layout.rs b/src/layout.rs index 6d0cfa88..b472c373 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -26,12 +26,11 @@ use std::rc::Rc; use std::vec::Vec; use crate::action::Action; +use crate::actors; use crate::drawing; -use crate::event_loop::driver::Threaded as AppState; use crate::float_ord::FloatOrd; use crate::keyboard::KeyState; use crate::logging; -use crate::manager; use crate::popover; use crate::receiver; use crate::submission::{ Submission, SubmitData, Timestamp }; @@ -221,7 +220,7 @@ pub mod c { submission: CSubmission, widget_to_layout: Transformation, time: u32, - manager: manager::c::Manager, + popover: actors::popover::c::Actor, app_state: receiver::c::State, ui_keyboard: EekGtkKeyboard, ) { @@ -230,6 +229,7 @@ pub mod c { let submission = submission.clone_ref(); let mut submission = submission.borrow_mut(); let app_state = app_state.clone_owned(); + let popover_state = popover.clone_owned(); let ui_backend = UIBackend { widget_to_layout, @@ -245,7 +245,7 @@ pub mod c { &mut submission, Some(&ui_backend), time, - Some((manager, app_state.clone())), + Some((&popover_state, app_state.clone())), key, ); } @@ -324,7 +324,7 @@ pub mod c { x_widget: f64, y_widget: f64, widget_to_layout: Transformation, time: u32, - manager: manager::c::Manager, + popover: actors::popover::c::Actor, app_state: receiver::c::State, ui_keyboard: EekGtkKeyboard, ) { @@ -332,6 +332,9 @@ pub mod c { let layout = unsafe { &mut *layout }; let submission = submission.clone_ref(); let mut submission = submission.borrow_mut(); + // We only need to query state here, not update. + // A copy is enough. + let popover_state = popover.clone_owned(); let app_state = app_state.clone_owned(); let ui_backend = UIBackend { widget_to_layout, @@ -363,7 +366,7 @@ pub mod c { &mut submission, Some(&ui_backend), time, - Some((manager, app_state.clone())), + Some((&popover_state, app_state.clone())), key, ); } @@ -388,7 +391,7 @@ pub mod c { &mut submission, Some(&ui_backend), time, - Some((manager, app_state.clone())), + Some((&popover_state, app_state.clone())), key, ); } @@ -1050,7 +1053,7 @@ mod seat { // passing state conditionally because it's only used for popover. // Eventually, it should be used for sumitting button events, // and passed always. - manager: Option<(manager::c::Manager, receiver::State)>, + manager: Option<(&actors::popover::State, receiver::State)>, rckey: &Rc>, ) { let key: KeyState = { diff --git a/src/lib.rs b/src/lib.rs index 65701e17..d508d051 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,7 @@ mod assert_matches; mod logging; mod action; +mod actors; mod animation; pub mod data; mod debug; @@ -34,7 +35,6 @@ mod keyboard; mod layout; mod locale; mod main; -mod manager; mod outputs; mod panel; mod popover; diff --git a/src/main.h b/src/main.h index ba6be72b..799962ce 100644 --- a/src/main.h +++ b/src/main.h @@ -9,6 +9,7 @@ #include "eek/eek-types.h" #include "dbus.h" #include "panel.h" +#include "src/popover.h" struct receiver; @@ -23,9 +24,10 @@ struct rsobjects { struct squeek_state_manager *state_manager; struct submission *submission; struct squeek_wayland *wayland; + struct squeek_popover *popover; }; -void register_ui_loop_handler(struct receiver *receiver, struct panel_manager *panel, EekboardContextService *hint_manager, DBusHandler *dbus_handler); +void register_ui_loop_handler(struct receiver *receiver, struct panel_manager *panel, struct squeek_popover *popover, EekboardContextService *hint_manager, DBusHandler *dbus_handler); struct rsobjects squeek_init(void); diff --git a/src/main.rs b/src/main.rs index 884505a4..13c1766c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,11 +3,11 @@ */ /*! Glue for the main loop. */ +use crate::actors; use crate::animation; use crate::debug; use crate::data::loading; use crate::panel; -use crate::state; use glib::{Continue, MainContext, PRIORITY_DEFAULT, Receiver}; @@ -49,6 +49,7 @@ mod c { submission: Wrapped, /// Not wrapped, because C needs to access this. wayland: *mut Wayland, + popover: actors::popover::c::Actor, } /// Corresponds to wayland.h::squeek_wayland. @@ -81,7 +82,6 @@ mod c { extern "C" { #[allow(improper_ctypes)] fn init_wayland(wayland: *mut Wayland); - fn eekboard_context_service_set_hint_purpose(service: HintManager, hint: u32, purpose: u32); #[allow(improper_ctypes)] fn eekboard_context_service_set_layout(service: HintManager, layout: *const layout::Layout, timestamp: u32); // This should probably only get called from the gtk main loop, @@ -121,6 +121,7 @@ mod c { state_manager: Wrapped::new(state_manager), receiver: Wrapped::new(receiver), wayland: Box::into_raw(wayland), + popover: Wrapped::new(actors::popover::State::new()), } } @@ -130,6 +131,7 @@ mod c { fn register_ui_loop_handler( receiver: Wrapped>, panel_manager: panel::c::PanelManager, + popover: actors::popover::c::Actor, hint_manager: HintManager, dbus_handler: *const DBusHandler, ) { @@ -142,7 +144,13 @@ mod c { receiver.attach( Some(&ctx), move |msg| { - main_loop_handle_message(msg, panel_manager.clone(), hint_manager, dbus_handler); + main_loop_handle_message( + msg, + panel_manager.clone(), + &popover, + hint_manager, + dbus_handler, + ); Continue(true) }, ); @@ -157,6 +165,7 @@ mod c { fn main_loop_handle_message( msg: Commands, panel_manager: Wrapped, + popover: &actors::popover::c::Actor, hint_manager: HintManager, dbus_handler: *const DBusHandler, ) { @@ -169,29 +178,19 @@ mod c { unsafe { dbus_handler_set_visible(dbus_handler, visible as u8) }; } } - - if let Some(hints) = msg.layout_hint_set { - unsafe { - eekboard_context_service_set_hint_purpose( - hint_manager, - hints.hint.bits(), - hints.purpose.clone() as u32, - ) - }; - } if let Some(commands::SetLayout { description }) = msg.layout_selection { - dbg!(&description); let animation::Contents { name, kind, overlay_name, purpose, } = description; + actors::popover::set_overlay(popover, overlay_name.clone()); let layout = loading::load_layout(name, kind, purpose, overlay_name); let layout = Box::into_raw(Box::new(layout)); unsafe { - //eekboard_context_service_set_layout(hint_manager, layout, 0); + eekboard_context_service_set_layout(hint_manager, layout, 0); } } } @@ -210,7 +209,6 @@ pub mod commands { #[derive(Clone)] pub struct Commands { pub panel_visibility: Option, - pub layout_hint_set: Option, pub dbus_visible_set: Option, pub layout_selection: Option, } diff --git a/src/manager.rs b/src/manager.rs deleted file mode 100644 index eb253411..00000000 --- a/src/manager.rs +++ /dev/null @@ -1,33 +0,0 @@ -/*! Procedures relating to the management of the switching of layouts */ -use crate::util; - -pub mod c { - use std::os::raw::{c_char, c_void}; - - /// EekboardContextService* - #[repr(transparent)] - #[derive(Clone, Copy)] - pub struct Manager(*const c_void); - - extern "C" { - pub fn eekboard_context_service_set_overlay( - manager: Manager, - name: *const c_char, - ); - - pub fn eekboard_context_service_get_overlay( - manager: Manager, - ) -> *const c_char; - } -} - -/// Returns the overlay name. -/// The result lifetime is "as long as the C copy lives" -pub fn get_overlay(manager: c::Manager) -> Option { - let raw_str = unsafe { - c::eekboard_context_service_get_overlay(manager) - }; - // this string is generated from Rust, should never be invalid - util::c::as_str(&raw_str).unwrap() - .map(String::from) -} diff --git a/src/panel.c b/src/panel.c index bf49f7b2..82640dfe 100644 --- a/src/panel.c +++ b/src/panel.c @@ -52,7 +52,7 @@ make_widget (struct panel_manager *self) if (self->widget) { g_error("Widget already present"); } - self->widget = eek_gtk_keyboard_new (self->state, self->submission, self->layout, self->state_manager); + self->widget = eek_gtk_keyboard_new (self->state, self->submission, self->state_manager, self->popover); gtk_widget_set_has_tooltip (self->widget, TRUE); gtk_container_add (GTK_CONTAINER(self->window), self->widget); @@ -116,16 +116,16 @@ panel_manager_resize (struct panel_manager *self, uint32_t height) } -struct panel_manager panel_manager_new(EekboardContextService *state, struct submission *submission, struct squeek_layout_state *layout, struct squeek_state_manager *state_manager) +struct panel_manager panel_manager_new(EekboardContextService *state, struct submission *submission, struct squeek_state_manager *state_manager, struct squeek_popover *popover) { struct panel_manager mgr = { .state = state, .submission = submission, - .layout = layout, .window = NULL, .widget = NULL, .current_output = NULL, .state_manager = state_manager, + .popover = popover, }; return mgr; } diff --git a/src/panel.h b/src/panel.h index 711eda8b..00aa7f91 100644 --- a/src/panel.h +++ b/src/panel.h @@ -10,8 +10,8 @@ struct panel_manager { EekboardContextService *state; // unowned /// Needed for instantiating the widget struct squeek_state_manager *state_manager; // shared reference + struct squeek_popover *popover; // shared reference struct submission *submission; // unowned - struct squeek_layout_state *layout; PhoshLayerSurface *window; GtkWidget *widget; // nullable @@ -20,4 +20,4 @@ struct panel_manager { struct wl_output *current_output; }; -struct panel_manager panel_manager_new(EekboardContextService *state, struct submission *submission, struct squeek_layout_state *layout, struct squeek_state_manager *state_manager); +struct panel_manager panel_manager_new(EekboardContextService *state, struct submission *submission, struct squeek_state_manager *state_manager, struct squeek_popover *popover); diff --git a/src/popover.h b/src/popover.h new file mode 100644 index 00000000..cc653922 --- /dev/null +++ b/src/popover.h @@ -0,0 +1,5 @@ +#pragma once +/// Popover state. +/// Wrapped +struct squeek_popover; + diff --git a/src/popover.rs b/src/popover.rs index 0344272a..5aba7e99 100644 --- a/src/popover.rs +++ b/src/popover.rs @@ -4,10 +4,10 @@ use gio; use gtk; use std::ffi::CString; use std::cmp::Ordering; +use crate::actors; use crate::layout::c::{ Bounds, EekGtkKeyboard }; use crate::locale::{ OwnedTranslation, compare_current_locale }; use crate::logging; -use crate::manager; use crate::receiver; use crate::resources; use crate::state; @@ -129,9 +129,11 @@ fn get_settings(schema_name: &str) -> Option { .map(|_sschema| gio::Settings::new(schema_name)) } -fn set_layout(kind: String, name: String) { +fn set_layout(kind: &str, name: &str) { let settings = get_settings("org.gnome.desktop.input-sources"); if let Some(settings) = settings { + let kind = String::from(kind); + let name = String::from(name); #[cfg(feature = "glib_v0_14")] let inputs = settings.value("sources"); #[cfg(not(feature = "glib_v0_14"))] @@ -172,40 +174,23 @@ impl LayoutId { } fn set_visible_layout( - manager: manager::c::Manager, - layout_id: LayoutId, + layout_id: &LayoutId, ) { match layout_id { LayoutId::System { kind, name } => { - unsafe { - use std::ptr; - manager::c::eekboard_context_service_set_overlay( - manager, - ptr::null(), - ); - } set_layout(kind, name); - } - LayoutId::Local(name) => { - let name = CString::new(name.as_str()).unwrap(); - let name_ptr = name.as_ptr(); - unsafe { - manager::c::eekboard_context_service_set_overlay( - manager, - name_ptr, - ) - } }, + _ => {}, } } /// Takes into account first any overlays, then system layouts from the list fn get_current_layout( - manager: manager::c::Manager, + popover: &actors::popover::State, system_layouts: &Vec, ) -> Option { - match manager::get_overlay(manager) { - Some(name) => Some(LayoutId::Local(name)), + match &popover.overlay { + Some(name) => Some(LayoutId::Local(name.into())), None => system_layouts.get(0).map(LayoutId::clone), } } @@ -249,7 +234,7 @@ fn translate_layout_names(layouts: &Vec) -> Vec { pub fn show( window: EekGtkKeyboard, position: Bounds, - manager: manager::c::Manager, + popover: &actors::popover::State, app_state: receiver::State, ) { unsafe { gtk::set_initialized() }; @@ -330,7 +315,7 @@ pub fn show( let action_group = gio::SimpleActionGroup::new(); - if let Some(current_layout) = get_current_layout(manager, &system_layouts) { + if let Some(current_layout) = get_current_layout(popover, &system_layouts) { let current_layout_name = all_layouts.iter() .find( |l| l.get_name() == current_layout.get_name() @@ -365,10 +350,7 @@ pub fn show( logging::Problem::Bug, &format!("Can't send to state"), ); - set_visible_layout( - manager, - layout.clone(), - ) + set_visible_layout(layout) }); }, None => log_print!( diff --git a/src/server-main.c b/src/server-main.c index 09c2febe..ccbce2e7 100644 --- a/src/server-main.c +++ b/src/server-main.c @@ -56,8 +56,6 @@ struct squeekboard { /// Gsettings hook for visibility. TODO: this does not belong in gsettings. ServerContextService *settings_handler; struct panel_manager panel_manager; // Controls the shape of the panel. - /// Currently wanted layout. TODO: merge into state::Application - struct squeek_layout_state layout_choice; }; @@ -400,7 +398,7 @@ main (int argc, char **argv) // Also initializes wayland struct rsobjects rsobjects = squeek_init(); - instance.settings_context = eekboard_context_service_new(rsobjects.state_manager, &instance.layout_choice); + instance.settings_context = eekboard_context_service_new(rsobjects.state_manager); // set up dbus @@ -450,10 +448,10 @@ main (int argc, char **argv) instance.panel_manager = panel_manager_new(instance.settings_context, rsobjects.submission, - &instance.layout_choice, - rsobjects.state_manager); + rsobjects.state_manager, + rsobjects.popover); - register_ui_loop_handler(rsobjects.receiver, &instance.panel_manager, instance.settings_context, instance.dbus_handler); + register_ui_loop_handler(rsobjects.receiver, &instance.panel_manager, rsobjects.popover, instance.settings_context, instance.dbus_handler); session_register(); diff --git a/src/state.rs b/src/state.rs index 0fd5b6a5..ba141d3c 100644 --- a/src/state.rs +++ b/src/state.rs @@ -126,27 +126,6 @@ impl Outcome { /// The receivers of the commands bear the burden /// of checking if the commands end up being no-ops. pub fn get_commands_to_reach(&self, new_state: &Self) -> Commands { - let layout_hint_set = match new_state { - Outcome { - panel: animation::Outcome::Visible{..}, - im: InputMethod::Active(hints), - .. - } => Some(hints.clone()), - - Outcome { - panel: animation::Outcome::Visible{..}, - im: InputMethod::InactiveSince(_), - .. - } => Some(InputMethodDetails { - hint: ContentHint::NONE, - purpose: ContentPurpose::Normal, - }), - - Outcome { - panel: animation::Outcome::Hidden, - .. - } => None, - }; // FIXME: handle switching outputs let (dbus_visible_set, panel_visibility) = match new_state.panel { animation::Outcome::Visible{output, height, ..} @@ -179,7 +158,6 @@ impl Outcome { Commands { panel_visibility, - layout_hint_set, dbus_visible_set, layout_selection, }