state: Store layout override

Not used for any externally observable effects
This commit is contained in:
Dorota Czaplejewicz
2022-06-03 16:32:42 +00:00
parent 8ff72f312a
commit 590cd71f49
11 changed files with 101 additions and 38 deletions

View File

@ -48,6 +48,7 @@ typedef struct _EekGtkKeyboardPrivate
struct render_geometry render_geometry; // mutable struct render_geometry render_geometry; // mutable
EekboardContextService *eekboard_context; // unowned reference EekboardContextService *eekboard_context; // unowned reference
struct squeek_state_manager *state_manager; // shared reference
struct submission *submission; // unowned reference struct submission *submission; // unowned reference
struct squeek_layout_state *layout; // unowned struct squeek_layout_state *layout; // unowned
@ -158,6 +159,7 @@ on_event_triggered (LfbEvent *event,
GAsyncResult *res, GAsyncResult *res,
gpointer unused) gpointer unused)
{ {
(void)unused;
g_autoptr (GError) err = NULL; g_autoptr (GError) err = NULL;
if (!lfb_event_trigger_feedback_finish (event, res, &err)) { if (!lfb_event_trigger_feedback_finish (event, res, &err)) {
@ -188,7 +190,7 @@ static void drag(EekGtkKeyboard *self,
squeek_layout_drag(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout, squeek_layout_drag(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout,
priv->submission, priv->submission,
x, y, priv->render_geometry.widget_to_layout, time, x, y, priv->render_geometry.widget_to_layout, time,
priv->eekboard_context, self); priv->eekboard_context, priv->state_manager, self);
} }
static void release(EekGtkKeyboard *self, guint32 time) static void release(EekGtkKeyboard *self, guint32 time)
@ -199,7 +201,7 @@ static void release(EekGtkKeyboard *self, guint32 time)
} }
squeek_layout_release(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout, squeek_layout_release(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout,
priv->submission, priv->render_geometry.widget_to_layout, time, priv->submission, priv->render_geometry.widget_to_layout, time,
priv->eekboard_context, self); priv->eekboard_context, priv->state_manager, self);
} }
static gboolean static gboolean
@ -406,13 +408,14 @@ on_notify_keyboard (GObject *object,
GtkWidget * GtkWidget *
eek_gtk_keyboard_new (EekboardContextService *eekservice, eek_gtk_keyboard_new (EekboardContextService *eekservice,
struct submission *submission, struct submission *submission,
struct squeek_layout_state *layout) struct squeek_layout_state *layout, struct squeek_state_manager *state_manager)
{ {
EekGtkKeyboard *ret = EEK_GTK_KEYBOARD(g_object_new (EEK_TYPE_GTK_KEYBOARD, NULL)); EekGtkKeyboard *ret = EEK_GTK_KEYBOARD(g_object_new (EEK_TYPE_GTK_KEYBOARD, NULL));
EekGtkKeyboardPrivate *priv = (EekGtkKeyboardPrivate*)eek_gtk_keyboard_get_instance_private (ret); EekGtkKeyboardPrivate *priv = (EekGtkKeyboardPrivate*)eek_gtk_keyboard_get_instance_private (ret);
priv->eekboard_context = eekservice; priv->eekboard_context = eekservice;
priv->submission = submission; priv->submission = submission;
priv->layout = layout; priv->layout = layout;
priv->state_manager = state_manager;
priv->renderer = NULL; priv->renderer = NULL;
// This should really be done on initialization. // This should really be done on initialization.
// Before the widget is allocated, // Before the widget is allocated,

View File

@ -30,6 +30,7 @@
#include "eek/eek-renderer.h" #include "eek/eek-renderer.h"
#include "eek/eek-types.h" #include "eek/eek-types.h"
#include "src/main.h"
struct submission; struct submission;
struct squeek_layout_state; struct squeek_layout_state;
@ -48,7 +49,7 @@ struct _EekGtkKeyboardClass
gpointer pdummy[24]; gpointer pdummy[24];
}; };
GtkWidget *eek_gtk_keyboard_new (EekboardContextService *eekservice, struct submission *submission, struct squeek_layout_state *layout); GtkWidget *eek_gtk_keyboard_new (EekboardContextService *eekservice, struct submission *submission, struct squeek_layout_state *layout, struct squeek_state_manager *state_manager);
void eek_gtk_keyboard_emit_feedback (EekGtkKeyboard *self); void eek_gtk_keyboard_emit_feedback (EekGtkKeyboard *self);
G_END_DECLS G_END_DECLS

View File

@ -7,6 +7,7 @@
#include "eek/eek-gtk-keyboard.h" #include "eek/eek-gtk-keyboard.h"
#include "eek/eek-renderer.h" #include "eek/eek-renderer.h"
#include "eek/eek-types.h" #include "eek/eek-types.h"
#include "src/main.h"
#include "src/submission.h" #include "src/submission.h"
#include "virtual-keyboard-unstable-v1-client-protocol.h" #include "virtual-keyboard-unstable-v1-client-protocol.h"
#include "text-input-unstable-v3-client-protocol.h" #include "text-input-unstable-v3-client-protocol.h"
@ -41,6 +42,7 @@ void squeek_layout_release(struct squeek_layout *layout,
struct transformation widget_to_layout, struct transformation widget_to_layout,
uint32_t timestamp, uint32_t timestamp,
EekboardContextService *manager, EekboardContextService *manager,
struct squeek_state_manager *state,
EekGtkKeyboard *ui_keyboard); EekGtkKeyboard *ui_keyboard);
void squeek_layout_release_all_only(struct squeek_layout *layout, void squeek_layout_release_all_only(struct squeek_layout *layout,
struct submission *submission, struct submission *submission,
@ -55,6 +57,7 @@ void squeek_layout_drag(struct squeek_layout *layout,
double x_widget, double y_widget, double x_widget, double y_widget,
struct transformation widget_to_layout, struct transformation widget_to_layout,
uint32_t timestamp, EekboardContextService *manager, uint32_t timestamp, EekboardContextService *manager,
struct squeek_state_manager *state,
EekGtkKeyboard *ui_keyboard); EekGtkKeyboard *ui_keyboard);
void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr, struct submission *submission); void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr, struct submission *submission);
void squeek_draw_layout_base_view(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr); void squeek_draw_layout_base_view(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr);

View File

@ -25,30 +25,36 @@ use std::fmt;
use std::rc::Rc; use std::rc::Rc;
use std::vec::Vec; use std::vec::Vec;
use ::action::Action; use crate::action::Action;
use ::drawing; use crate::drawing;
use ::float_ord::FloatOrd; use crate::event_loop::driver::Threaded as AppState;
use ::keyboard::KeyState; use crate::float_ord::FloatOrd;
use ::logging; use crate::keyboard::KeyState;
use ::manager; use crate::logging;
use ::submission::{ Submission, SubmitData, Timestamp }; use crate::manager;
use ::util::find_max_double; use crate::popover;
use crate::receiver;
use crate::submission::{ Submission, SubmitData, Timestamp };
use crate::util::find_max_double;
use ::imservice::ContentPurpose; use crate::imservice::ContentPurpose;
// Traits // Traits
use std::borrow::Borrow; use std::borrow::Borrow;
use ::logging::Warn; use crate::logging::Warn;
/// Gathers stuff defined in C or called by C /// Gathers stuff defined in C or called by C
pub mod c { pub mod c {
use super::*; use super::*;
use gtk_sys; use crate::receiver;
use std::os::raw::c_void;
use crate::submission::c::Submission as CSubmission; use crate::submission::c::Submission as CSubmission;
use gtk_sys;
use std::ops::{ Add, Sub }; use std::ops::{ Add, Sub };
use std::os::raw::c_void;
use crate::util::CloneOwned;
// The following defined in C // The following defined in C
#[repr(transparent)] #[repr(transparent)]
@ -216,12 +222,15 @@ pub mod c {
widget_to_layout: Transformation, widget_to_layout: Transformation,
time: u32, time: u32,
manager: manager::c::Manager, manager: manager::c::Manager,
app_state: receiver::c::State,
ui_keyboard: EekGtkKeyboard, ui_keyboard: EekGtkKeyboard,
) { ) {
let time = Timestamp(time); let time = Timestamp(time);
let layout = unsafe { &mut *layout }; let layout = unsafe { &mut *layout };
let submission = submission.clone_ref(); let submission = submission.clone_ref();
let mut submission = submission.borrow_mut(); let mut submission = submission.borrow_mut();
let app_state = app_state.clone_owned();
let ui_backend = UIBackend { let ui_backend = UIBackend {
widget_to_layout, widget_to_layout,
keyboard: ui_keyboard, keyboard: ui_keyboard,
@ -236,7 +245,7 @@ pub mod c {
&mut submission, &mut submission,
Some(&ui_backend), Some(&ui_backend),
time, time,
Some(manager), Some((manager, app_state.clone())),
key, key,
); );
} }
@ -316,12 +325,14 @@ pub mod c {
widget_to_layout: Transformation, widget_to_layout: Transformation,
time: u32, time: u32,
manager: manager::c::Manager, manager: manager::c::Manager,
app_state: receiver::c::State,
ui_keyboard: EekGtkKeyboard, ui_keyboard: EekGtkKeyboard,
) { ) {
let time = Timestamp(time); let time = Timestamp(time);
let layout = unsafe { &mut *layout }; let layout = unsafe { &mut *layout };
let submission = submission.clone_ref(); let submission = submission.clone_ref();
let mut submission = submission.borrow_mut(); let mut submission = submission.borrow_mut();
let app_state = app_state.clone_owned();
let ui_backend = UIBackend { let ui_backend = UIBackend {
widget_to_layout, widget_to_layout,
keyboard: ui_keyboard, keyboard: ui_keyboard,
@ -352,7 +363,7 @@ pub mod c {
&mut submission, &mut submission,
Some(&ui_backend), Some(&ui_backend),
time, time,
Some(manager), Some((manager, app_state.clone())),
key, key,
); );
} }
@ -377,7 +388,7 @@ pub mod c {
&mut submission, &mut submission,
Some(&ui_backend), Some(&ui_backend),
time, time,
Some(manager), Some((manager, app_state.clone())),
key, key,
); );
} }
@ -1035,7 +1046,11 @@ mod seat {
submission: &mut Submission, submission: &mut Submission,
ui: Option<&UIBackend>, ui: Option<&UIBackend>,
time: Timestamp, time: Timestamp,
manager: Option<manager::c::Manager>, // TODO: intermediate measure:
// 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)>,
rckey: &Rc<RefCell<KeyState>>, rckey: &Rc<RefCell<KeyState>>,
) { ) {
let key: KeyState = { let key: KeyState = {
@ -1070,7 +1085,7 @@ mod seat {
// only show when UI is present // only show when UI is present
Action::ShowPreferences => if let Some(ui) = &ui { Action::ShowPreferences => if let Some(ui) = &ui {
// only show when layout manager is available // only show when layout manager is available
if let Some(manager) = manager { if let Some((manager, app_state)) = manager {
let view = layout.get_current_view(); let view = layout.get_current_view();
let places = ::layout::procedures::find_key_places( let places = ::layout::procedures::find_key_places(
view, &rckey, view, &rckey,
@ -1085,10 +1100,11 @@ mod seat {
width: button.size.width, width: button.size.width,
height: button.size.height, height: button.size.height,
}; };
::popover::show( popover::show(
ui.keyboard, ui.keyboard,
ui.widget_to_layout.reverse_bounds(bounds), ui.widget_to_layout.reverse_bounds(bounds),
manager, manager,
app_state,
); );
} }
} }

View File

@ -38,6 +38,7 @@ mod manager;
mod outputs; mod outputs;
mod panel; mod panel;
mod popover; mod popover;
mod receiver;
mod resources; mod resources;
mod state; mod state;
mod style; mod style;

View File

@ -52,7 +52,7 @@ make_widget (struct panel_manager *self)
if (self->widget) { if (self->widget) {
g_error("Widget already present"); g_error("Widget already present");
} }
self->widget = eek_gtk_keyboard_new (self->state, self->submission, self->layout); self->widget = eek_gtk_keyboard_new (self->state, self->submission, self->layout, self->state_manager);
gtk_widget_set_has_tooltip (self->widget, TRUE); gtk_widget_set_has_tooltip (self->widget, TRUE);
gtk_container_add (GTK_CONTAINER(self->window), self->widget); gtk_container_add (GTK_CONTAINER(self->window), self->widget);
@ -116,7 +116,7 @@ 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 panel_manager panel_manager_new(EekboardContextService *state, struct submission *submission, struct squeek_layout_state *layout, struct squeek_state_manager *state_manager)
{ {
struct panel_manager mgr = { struct panel_manager mgr = {
.state = state, .state = state,
@ -125,6 +125,7 @@ struct panel_manager panel_manager_new(EekboardContextService *state, struct sub
.window = NULL, .window = NULL,
.widget = NULL, .widget = NULL,
.current_output = NULL, .current_output = NULL,
.state_manager = state_manager,
}; };
return mgr; return mgr;
} }

View File

@ -2,12 +2,14 @@
#include "eek/layersurface.h" #include "eek/layersurface.h"
#include "src/layout.h" #include "src/layout.h"
#include "src/main.h"
#include "src/submission.h" #include "src/submission.h"
// Stores the objects that the panel and its widget will refer to // Stores the objects that the panel and its widget will refer to
struct panel_manager { struct panel_manager {
EekboardContextService *state; // unowned EekboardContextService *state; // unowned
/// Needed for instantiating the widget /// Needed for instantiating the widget
struct squeek_state_manager *state_manager; // shared reference
struct submission *submission; // unowned struct submission *submission; // unowned
struct squeek_layout_state *layout; struct squeek_layout_state *layout;
@ -18,4 +20,4 @@ struct panel_manager {
struct wl_output *current_output; struct wl_output *current_output;
}; };
struct panel_manager panel_manager_new(EekboardContextService *state, struct submission *submission, struct squeek_layout_state *layout); struct panel_manager panel_manager_new(EekboardContextService *state, struct submission *submission, struct squeek_layout_state *layout, struct squeek_state_manager *state_manager);

View File

@ -4,11 +4,13 @@ use gio;
use gtk; use gtk;
use std::ffi::CString; use std::ffi::CString;
use std::cmp::Ordering; use std::cmp::Ordering;
use ::layout::c::{ Bounds, EekGtkKeyboard }; use crate::layout::c::{ Bounds, EekGtkKeyboard };
use ::locale::{ OwnedTranslation, compare_current_locale }; use crate::locale::{ OwnedTranslation, compare_current_locale };
use ::logging; use crate::logging;
use ::manager; use crate::manager;
use ::resources; use crate::receiver;
use crate::resources;
use crate::state;
// Traits // Traits
use gio::prelude::ActionMapExt; use gio::prelude::ActionMapExt;
@ -16,7 +18,7 @@ use gio::prelude::SettingsExt;
use glib::translate::FromGlibPtrNone; use glib::translate::FromGlibPtrNone;
use glib::variant::ToVariant; use glib::variant::ToVariant;
use gtk::prelude::*; use gtk::prelude::*;
use ::logging::Warn; use crate::logging::Warn;
mod c { mod c {
use std::os::raw::c_char; use std::os::raw::c_char;
@ -150,7 +152,7 @@ fn set_layout(kind: String, name: String) {
/// A reference to what the user wants to see /// A reference to what the user wants to see
#[derive(PartialEq, Clone, Debug)] #[derive(PartialEq, Clone, Debug)]
enum LayoutId { pub enum LayoutId {
/// Affects the layout in system settings /// Affects the layout in system settings
System { System {
kind: String, kind: String,
@ -248,6 +250,7 @@ pub fn show(
window: EekGtkKeyboard, window: EekGtkKeyboard,
position: Bounds, position: Bounds,
manager: manager::c::Manager, manager: manager::c::Manager,
app_state: receiver::State,
) { ) {
unsafe { gtk::set_initialized() }; unsafe { gtk::set_initialized() };
let window = unsafe { gtk::Widget::from_glib_none(window.0) }; let window = unsafe { gtk::Widget::from_glib_none(window.0) };
@ -356,6 +359,12 @@ pub fn show(
.find( .find(
|choices| state == choices.get_name() |choices| state == choices.get_name()
).unwrap(); ).unwrap();
app_state
.send(state::Event::OverlayChanged(layout.clone()))
.or_print(
logging::Problem::Bug,
&format!("Can't send to state"),
);
set_visible_layout( set_visible_layout(
manager, manager,
layout.clone(), layout.clone(),

15
src/receiver.rs Normal file
View File

@ -0,0 +1,15 @@
/*! Defines the application-wide message bus for updating state.*/
use crate::event_loop::driver::Threaded;
pub mod c {
use super::*;
use crate::util::c::Wrapped;
pub type State = Wrapped<Threaded>;
}
// The state receiver is an endpoint of a channel, so it's safely cloneable.
// There's no need to keep it in a Rc.
// The C version uses Wrapped with an underlying Rc,
// because Wrapped is well-tested already.
pub type State = Threaded;

View File

@ -450,7 +450,8 @@ main (int argc, char **argv)
instance.panel_manager = panel_manager_new(instance.settings_context, instance.panel_manager = panel_manager_new(instance.settings_context,
rsobjects.submission, rsobjects.submission,
&instance.layout_choice); &instance.layout_choice,
rsobjects.state_manager);
register_ui_loop_handler(rsobjects.receiver, &instance.panel_manager, instance.settings_context, instance.dbus_handler); register_ui_loop_handler(rsobjects.receiver, &instance.panel_manager, instance.settings_context, instance.dbus_handler);

View File

@ -13,6 +13,7 @@ use crate::outputs;
use crate::outputs::{Millimeter, OutputId, OutputState}; use crate::outputs::{Millimeter, OutputId, OutputState};
use crate::panel; use crate::panel;
use crate::panel::PixelSize; use crate::panel::PixelSize;
use crate::popover;
use crate::util::Rational; use crate::util::Rational;
use std::cmp; use std::cmp;
use std::collections::HashMap; use std::collections::HashMap;
@ -53,7 +54,7 @@ impl From<String> for LayoutSource {
} }
} }
/// The user's preferred layout /// The user's preferred system layout
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct LayoutChoice { pub struct LayoutChoice {
pub name: String, pub name: String,
@ -69,6 +70,7 @@ pub enum Event {
PhysicalKeyboard(Presence), PhysicalKeyboard(Presence),
Output(outputs::Event), Output(outputs::Event),
LayoutChoice(LayoutChoice), LayoutChoice(LayoutChoice),
OverlayChanged(popover::LayoutId),
Debug(debug::Event), Debug(debug::Event),
/// Event triggered because a moment in time passed. /// Event triggered because a moment in time passed.
/// Use to animate state transitions. /// Use to animate state transitions.
@ -188,6 +190,8 @@ pub struct Application {
/// and we might not receive one at all (gsettings missing). /// and we might not receive one at all (gsettings missing).
/// Then a default is used. /// Then a default is used.
pub layout_choice: LayoutChoice, pub layout_choice: LayoutChoice,
/// Manual override of the system layout
pub overlay_layout: Option<popover::LayoutId>,
} }
impl Application { impl Application {
@ -209,6 +213,7 @@ impl Application {
name: String::from("us"), name: String::from("us"),
source: LayoutSource::Xkb, source: LayoutSource::Xkb,
}, },
overlay_layout: None,
} }
} }
@ -295,8 +300,14 @@ impl Application {
}, },
}, },
Event::LayoutChoice(choice) => Self { Event::LayoutChoice(layout_choice) => Self {
layout_choice: choice, layout_choice,
overlay_layout: None,
..self
},
Event::OverlayChanged(overlay_layout) => Self {
overlay_layout: Some(overlay_layout),
..self ..self
}, },
}; };