state: Connect the animation state machine to the rest
This ensures that the new state machine is fed events, as well as that its results are applied. The old ad-hoc system is removed. There is one regression where the last layout will be used when the panel is brought up manually.
This commit is contained in:
13
src/animation.h
Normal file
13
src/animation.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
// from main.h
|
||||||
|
struct sender;
|
||||||
|
|
||||||
|
// from animations.rs
|
||||||
|
struct squeek_animation_visibility_manager;
|
||||||
|
|
||||||
|
struct squeek_animation_visibility_manager *squeek_animation_visibility_manager_new(struct sender *ui_sender);
|
||||||
|
|
||||||
|
void squeek_animation_visibility_manager_send_claim_visible(struct squeek_animation_visibility_manager *animman);
|
||||||
|
void squeek_animation_visibility_manager_send_force_hide(struct squeek_animation_visibility_manager *animman);
|
||||||
49
src/dbus.c
49
src/dbus.c
@ -44,11 +44,6 @@ dbus_handler_destroy(DBusHandler *service)
|
|||||||
service->introspection_data = NULL;
|
service->introspection_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (service->context) {
|
|
||||||
g_signal_handlers_disconnect_by_data (service->context, service);
|
|
||||||
service->context = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(service);
|
free(service);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,38 +52,25 @@ handle_set_visible(SmPuriOSK0 *object, GDBusMethodInvocation *invocation,
|
|||||||
gboolean arg_visible, gpointer user_data) {
|
gboolean arg_visible, gpointer user_data) {
|
||||||
DBusHandler *service = user_data;
|
DBusHandler *service = user_data;
|
||||||
|
|
||||||
if (service->context) {
|
if (arg_visible) {
|
||||||
if (arg_visible) {
|
squeek_animation_visibility_manager_send_claim_visible (service->animman);
|
||||||
server_context_service_force_show_keyboard (service->context);
|
} else {
|
||||||
} else {
|
squeek_animation_visibility_manager_send_force_hide (service->animman);
|
||||||
server_context_service_hide_keyboard (service->context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sm_puri_osk0_complete_set_visible(object, invocation);
|
sm_puri_osk0_complete_set_visible(object, invocation);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_visible(DBusHandler *service,
|
|
||||||
GParamSpec *pspec,
|
|
||||||
ServerContextService *context)
|
|
||||||
{
|
|
||||||
(void)pspec;
|
|
||||||
gboolean visible;
|
|
||||||
|
|
||||||
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE (context));
|
|
||||||
|
|
||||||
g_object_get (context, "visible", &visible, NULL);
|
|
||||||
|
|
||||||
sm_puri_osk0_set_visible(service->dbus_interface, visible);
|
|
||||||
}
|
|
||||||
|
|
||||||
DBusHandler *
|
DBusHandler *
|
||||||
dbus_handler_new (GDBusConnection *connection,
|
dbus_handler_new (GDBusConnection *connection,
|
||||||
const gchar *object_path)
|
const gchar *object_path,
|
||||||
|
struct squeek_animation_visibility_manager *animman)
|
||||||
{
|
{
|
||||||
DBusHandler *self = calloc(1, sizeof(DBusHandler));
|
DBusHandler *self = calloc(1, sizeof(DBusHandler));
|
||||||
self->object_path = g_strdup(object_path);
|
self->object_path = g_strdup(object_path);
|
||||||
self->connection = connection;
|
self->connection = connection;
|
||||||
|
self->animman = animman;
|
||||||
|
|
||||||
self->dbus_interface = sm_puri_osk0_skeleton_new();
|
self->dbus_interface = sm_puri_osk0_skeleton_new();
|
||||||
g_signal_connect(self->dbus_interface, "handle-set-visible",
|
g_signal_connect(self->dbus_interface, "handle-set-visible",
|
||||||
@ -109,16 +91,9 @@ dbus_handler_new (GDBusConnection *connection,
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
// Exported to Rust
|
||||||
dbus_handler_set_ui_context(DBusHandler *service,
|
void dbus_handler_set_visible(DBusHandler *service,
|
||||||
ServerContextService *context)
|
uint8_t visible)
|
||||||
{
|
{
|
||||||
g_return_if_fail (!service->context);
|
sm_puri_osk0_set_visible(service->dbus_interface, visible);
|
||||||
|
|
||||||
service->context = context;
|
|
||||||
|
|
||||||
g_signal_connect_swapped (service->context,
|
|
||||||
"notify::visible",
|
|
||||||
G_CALLBACK(on_visible),
|
|
||||||
service);
|
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/dbus.h
15
src/dbus.h
@ -19,7 +19,7 @@
|
|||||||
#ifndef DBUS_H_
|
#ifndef DBUS_H_
|
||||||
#define DBUS_H_ 1
|
#define DBUS_H_ 1
|
||||||
|
|
||||||
#include "server-context-service.h"
|
#include "animation.h"
|
||||||
|
|
||||||
#include "sm.puri.OSK0.h"
|
#include "sm.puri.OSK0.h"
|
||||||
|
|
||||||
@ -28,6 +28,10 @@ G_BEGIN_DECLS
|
|||||||
#define DBUS_SERVICE_PATH "/sm/puri/OSK0"
|
#define DBUS_SERVICE_PATH "/sm/puri/OSK0"
|
||||||
#define DBUS_SERVICE_INTERFACE "sm.puri.OSK0"
|
#define DBUS_SERVICE_INTERFACE "sm.puri.OSK0"
|
||||||
|
|
||||||
|
/// Two jobs: accept events, forwarding them to the visibility manager,
|
||||||
|
/// and get updated from inside to show internal state.
|
||||||
|
/// Updates are handled in the same loop as the UI.
|
||||||
|
/// See main.rs
|
||||||
typedef struct _DBusHandler
|
typedef struct _DBusHandler
|
||||||
{
|
{
|
||||||
GDBusConnection *connection;
|
GDBusConnection *connection;
|
||||||
@ -36,13 +40,14 @@ typedef struct _DBusHandler
|
|||||||
guint registration_id;
|
guint registration_id;
|
||||||
char *object_path;
|
char *object_path;
|
||||||
|
|
||||||
ServerContextService *context; // unowned reference
|
/// Forward incoming events there
|
||||||
|
struct squeek_animation_visibility_manager *animman; // shared reference
|
||||||
} DBusHandler;
|
} DBusHandler;
|
||||||
|
|
||||||
DBusHandler * dbus_handler_new (GDBusConnection *connection,
|
DBusHandler * dbus_handler_new (GDBusConnection *connection,
|
||||||
const gchar *object_path);
|
const gchar *object_path,
|
||||||
void dbus_handler_set_ui_context(DBusHandler *service,
|
struct squeek_animation_visibility_manager *animman);
|
||||||
ServerContextService *context);
|
|
||||||
void dbus_handler_destroy(DBusHandler*);
|
void dbus_handler_destroy(DBusHandler*);
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* DBUS_H_ */
|
#endif /* DBUS_H_ */
|
||||||
|
|||||||
@ -23,7 +23,6 @@ pub mod c {
|
|||||||
|
|
||||||
use std::os::raw::{c_char, c_void};
|
use std::os::raw::{c_char, c_void};
|
||||||
|
|
||||||
pub use ::ui_manager::c::UIManager;
|
|
||||||
pub use ::submission::c::StateManager;
|
pub use ::submission::c::StateManager;
|
||||||
|
|
||||||
// The following defined in C
|
// The following defined in C
|
||||||
@ -153,14 +152,14 @@ pub mod c {
|
|||||||
|
|
||||||
if active_changed {
|
if active_changed {
|
||||||
(imservice.active_callback)(imservice.current.active);
|
(imservice.active_callback)(imservice.current.active);
|
||||||
}
|
if imservice.current.active {
|
||||||
if imservice.current.active {
|
unsafe {
|
||||||
unsafe {
|
eekboard_context_service_set_hint_purpose(
|
||||||
eekboard_context_service_set_hint_purpose(
|
imservice.state_manager,
|
||||||
imservice.state_manager,
|
imservice.current.content_hint.bits(),
|
||||||
imservice.current.content_hint.bits(),
|
imservice.current.content_purpose.clone() as u32,
|
||||||
imservice.current.content_purpose.clone() as u32,
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,7 @@ pub mod imservice;
|
|||||||
mod keyboard;
|
mod keyboard;
|
||||||
mod layout;
|
mod layout;
|
||||||
mod locale;
|
mod locale;
|
||||||
|
mod main;
|
||||||
mod manager;
|
mod manager;
|
||||||
mod outputs;
|
mod outputs;
|
||||||
mod popover;
|
mod popover;
|
||||||
|
|||||||
17
src/main.h
Normal file
17
src/main.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
/// This all wraps https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/struct.MainContext.html#method.channel
|
||||||
|
|
||||||
|
#include "eek/eek-types.h"
|
||||||
|
#include "dbus.h"
|
||||||
|
|
||||||
|
struct receiver;
|
||||||
|
struct sender;
|
||||||
|
|
||||||
|
struct channel {
|
||||||
|
struct sender *sender;
|
||||||
|
struct receiver *receiver;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Creates a channel with one end inside the glib main loop
|
||||||
|
struct channel main_loop_channel_new(void);
|
||||||
|
void register_ui_loop_handler(struct receiver *receiver, ServerContextService *ui, DBusHandler *dbus_handler);
|
||||||
119
src/main.rs
Normal file
119
src/main.rs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/* Copyright (C) 2020 Purism SPC
|
||||||
|
* SPDX-License-Identifier: GPL-3.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! Glue for the main loop. */
|
||||||
|
|
||||||
|
use crate::animation::Outcome as Message;
|
||||||
|
use glib::{Continue, MainContext, PRIORITY_DEFAULT, Receiver, Sender};
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
mod c {
|
||||||
|
use super::*;
|
||||||
|
use std::os::raw::c_void;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use ::util::c::{ ArcWrapped, Wrapped };
|
||||||
|
|
||||||
|
/// ServerContextService*
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct UIManager(*const c_void);
|
||||||
|
|
||||||
|
/// DbusHandler*
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct DBusHandler(*const c_void);
|
||||||
|
|
||||||
|
/// Corresponds to main.c::channel
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Channel {
|
||||||
|
sender: ArcWrapped<Sender<Message>>,
|
||||||
|
receiver: Wrapped<Receiver<Message>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
pub fn server_context_service_real_show_keyboard(imservice: *const UIManager);
|
||||||
|
pub fn server_context_service_real_hide_keyboard(imservice: *const UIManager);
|
||||||
|
// This should probably only get called from the gtk main loop,
|
||||||
|
// given that dbus handler is using glib.
|
||||||
|
pub fn dbus_handler_set_visible(dbus: *const DBusHandler, visible: u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C"
|
||||||
|
fn main_loop_channel_new() -> Channel {
|
||||||
|
let (sender, receiver) = MainContext::channel(PRIORITY_DEFAULT);
|
||||||
|
let sender = ArcWrapped::new(sender);
|
||||||
|
let receiver = Wrapped::new(receiver);
|
||||||
|
let channel = Channel {
|
||||||
|
sender,
|
||||||
|
receiver,
|
||||||
|
};
|
||||||
|
|
||||||
|
//start_work(channel.sender.clone());
|
||||||
|
|
||||||
|
channel
|
||||||
|
}
|
||||||
|
|
||||||
|
/// testing only
|
||||||
|
fn start_work(sender: ArcWrapped<Sender<Message>>) {
|
||||||
|
let sender = sender.clone_ref();
|
||||||
|
thread::spawn(move || {
|
||||||
|
let sender = sender.lock().unwrap();
|
||||||
|
thread::sleep(Duration::from_secs(3));
|
||||||
|
sender.send(Message::Visible).unwrap();
|
||||||
|
thread::sleep(Duration::from_secs(3));
|
||||||
|
sender.send(Message::Hidden).unwrap();
|
||||||
|
thread::sleep(Duration::from_secs(3));
|
||||||
|
sender.send(Message::Visible).unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Places the UI loop callback in the glib main loop.
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C"
|
||||||
|
fn register_ui_loop_handler(
|
||||||
|
receiver: Wrapped<Receiver<Message>>,
|
||||||
|
ui_manager: *const UIManager,
|
||||||
|
dbus_handler: *const DBusHandler,
|
||||||
|
) {
|
||||||
|
let receiver = unsafe { receiver.unwrap() };
|
||||||
|
let receiver = Rc::try_unwrap(receiver).expect("References still present");
|
||||||
|
let receiver = receiver.into_inner();
|
||||||
|
let ctx = MainContext::default();
|
||||||
|
ctx.acquire();
|
||||||
|
receiver.attach(
|
||||||
|
Some(&ctx),
|
||||||
|
move |msg| {
|
||||||
|
main_loop_handle_message(msg, ui_manager, dbus_handler);
|
||||||
|
Continue(true)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ctx.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A single iteration of the UI loop.
|
||||||
|
/// Applies state outcomes to external portions of the program.
|
||||||
|
/// This is the outest layer of the imperative shell,
|
||||||
|
/// and doesn't lend itself to testing other than integration.
|
||||||
|
fn main_loop_handle_message(
|
||||||
|
msg: Message,
|
||||||
|
ui_manager: *const UIManager,
|
||||||
|
dbus_handler: *const DBusHandler,
|
||||||
|
) {
|
||||||
|
match msg {
|
||||||
|
Message::Visible => unsafe {
|
||||||
|
// FIXME: reset layout to default if no IM field is active
|
||||||
|
// Ideally: anim state stores the current IM hints,
|
||||||
|
// Message::Visible(hints) is received here
|
||||||
|
// and applied to layout
|
||||||
|
server_context_service_real_show_keyboard(ui_manager);
|
||||||
|
dbus_handler_set_visible(dbus_handler, 1);
|
||||||
|
},
|
||||||
|
Message::Hidden => unsafe {
|
||||||
|
server_context_service_real_hide_keyboard(ui_manager);
|
||||||
|
dbus_handler_set_visible(dbus_handler, 0);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -30,7 +30,6 @@
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_VISIBLE,
|
|
||||||
PROP_ENABLED,
|
PROP_ENABLED,
|
||||||
PROP_LAST
|
PROP_LAST
|
||||||
};
|
};
|
||||||
@ -45,10 +44,8 @@ struct _ServerContextService {
|
|||||||
struct ui_manager *manager; // unowned
|
struct ui_manager *manager; // unowned
|
||||||
struct vis_manager *vis_manager; // owned
|
struct vis_manager *vis_manager; // owned
|
||||||
|
|
||||||
gboolean visible;
|
|
||||||
PhoshLayerSurface *window;
|
PhoshLayerSurface *window;
|
||||||
GtkWidget *widget; // nullable
|
GtkWidget *widget; // nullable
|
||||||
guint hiding;
|
|
||||||
guint last_requested_height;
|
guint last_requested_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,23 +64,6 @@ on_destroy (ServerContextService *self, GtkWidget *widget)
|
|||||||
//eekboard_context_service_destroy (EEKBOARD_CONTEXT_SERVICE (context));
|
//eekboard_context_service_destroy (EEKBOARD_CONTEXT_SERVICE (context));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
on_notify_map (ServerContextService *self, GtkWidget *widget)
|
|
||||||
{
|
|
||||||
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE (self));
|
|
||||||
|
|
||||||
g_object_set (self, "visible", TRUE, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_notify_unmap (ServerContextService *self, GtkWidget *widget)
|
|
||||||
{
|
|
||||||
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE (self));
|
|
||||||
|
|
||||||
g_object_set (self, "visible", FALSE, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
calculate_height(int32_t width, GdkRectangle *geometry)
|
calculate_height(int32_t width, GdkRectangle *geometry)
|
||||||
{
|
{
|
||||||
@ -187,8 +167,6 @@ make_window (ServerContextService *self)
|
|||||||
|
|
||||||
g_object_connect (self->window,
|
g_object_connect (self->window,
|
||||||
"swapped-signal::destroy", G_CALLBACK(on_destroy), self,
|
"swapped-signal::destroy", G_CALLBACK(on_destroy), self,
|
||||||
"swapped-signal::map", G_CALLBACK(on_notify_map), self,
|
|
||||||
"swapped-signal::unmap", G_CALLBACK(on_notify_unmap), self,
|
|
||||||
"swapped-signal::configured", G_CALLBACK(on_surface_configure), self,
|
"swapped-signal::configured", G_CALLBACK(on_surface_configure), self,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
@ -225,7 +203,7 @@ make_widget (ServerContextService *self)
|
|||||||
gtk_widget_show_all(self->widget);
|
gtk_widget_show_all(self->widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
server_context_service_real_show_keyboard (ServerContextService *self)
|
server_context_service_real_show_keyboard (ServerContextService *self)
|
||||||
{
|
{
|
||||||
if (!self->window) {
|
if (!self->window) {
|
||||||
@ -234,92 +212,13 @@ server_context_service_real_show_keyboard (ServerContextService *self)
|
|||||||
if (!self->widget) {
|
if (!self->widget) {
|
||||||
make_widget (self);
|
make_widget (self);
|
||||||
}
|
}
|
||||||
self->visible = TRUE;
|
|
||||||
gtk_widget_show (GTK_WIDGET(self->window));
|
gtk_widget_show (GTK_WIDGET(self->window));
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
void
|
||||||
show_keyboard_source_func(ServerContextService *context)
|
|
||||||
{
|
|
||||||
server_context_service_real_show_keyboard(context);
|
|
||||||
return G_SOURCE_REMOVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
server_context_service_real_hide_keyboard (ServerContextService *self)
|
server_context_service_real_hide_keyboard (ServerContextService *self)
|
||||||
{
|
{
|
||||||
gtk_widget_hide (GTK_WIDGET(self->window));
|
gtk_widget_hide (GTK_WIDGET(self->window));
|
||||||
self->visible = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
hide_keyboard_source_func(ServerContextService *context)
|
|
||||||
{
|
|
||||||
server_context_service_real_hide_keyboard(context);
|
|
||||||
return G_SOURCE_REMOVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
on_hide (ServerContextService *self)
|
|
||||||
{
|
|
||||||
server_context_service_real_hide_keyboard(self);
|
|
||||||
self->hiding = 0;
|
|
||||||
|
|
||||||
return G_SOURCE_REMOVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
server_context_service_show_keyboard (ServerContextService *self)
|
|
||||||
{
|
|
||||||
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE(self));
|
|
||||||
|
|
||||||
if (self->hiding) {
|
|
||||||
g_source_remove (self->hiding);
|
|
||||||
self->hiding = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!self->visible) {
|
|
||||||
g_idle_add((GSourceFunc)show_keyboard_source_func, self);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
server_context_service_force_show_keyboard (ServerContextService *self)
|
|
||||||
{
|
|
||||||
if (!submission_hint_available(self->submission)) {
|
|
||||||
eekboard_context_service_set_hint_purpose(
|
|
||||||
self->state,
|
|
||||||
ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE,
|
|
||||||
ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
server_context_service_show_keyboard(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
server_context_service_hide_keyboard (ServerContextService *self)
|
|
||||||
{
|
|
||||||
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE(self));
|
|
||||||
|
|
||||||
if (self->visible) {
|
|
||||||
g_idle_add((GSourceFunc)hide_keyboard_source_func, self);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Meant for use by the input-method handler:
|
|
||||||
/// the visible keyboard is no longer needed.
|
|
||||||
/// The implementation will delay it slightly,
|
|
||||||
/// because the release may be due to switching from one text field to another.
|
|
||||||
/// In this case, the user doesn't really need the keyboard surface
|
|
||||||
/// to disappear completely.
|
|
||||||
void
|
|
||||||
server_context_service_release_visibility (ServerContextService *self)
|
|
||||||
{
|
|
||||||
g_return_if_fail (SERVER_IS_CONTEXT_SERVICE(self));
|
|
||||||
|
|
||||||
if (!self->hiding && self->visible) {
|
|
||||||
self->hiding = g_timeout_add (200, (GSourceFunc) on_hide, self);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -338,9 +237,6 @@ server_context_service_set_property (GObject *object,
|
|||||||
ServerContextService *self = SERVER_CONTEXT_SERVICE(object);
|
ServerContextService *self = SERVER_CONTEXT_SERVICE(object);
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_VISIBLE:
|
|
||||||
self->visible = g_value_get_boolean (value);
|
|
||||||
break;
|
|
||||||
case PROP_ENABLED:
|
case PROP_ENABLED:
|
||||||
server_context_service_set_physical_keyboard_present (self, !g_value_get_boolean (value));
|
server_context_service_set_physical_keyboard_present (self, !g_value_get_boolean (value));
|
||||||
break;
|
break;
|
||||||
@ -356,11 +252,7 @@ server_context_service_get_property (GObject *object,
|
|||||||
GValue *value,
|
GValue *value,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
ServerContextService *self = SERVER_CONTEXT_SERVICE(object);
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_VISIBLE:
|
|
||||||
g_value_set_boolean (value, self->visible);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -388,18 +280,6 @@ server_context_service_class_init (ServerContextServiceClass *klass)
|
|||||||
gobject_class->get_property = server_context_service_get_property;
|
gobject_class->get_property = server_context_service_get_property;
|
||||||
gobject_class->dispose = server_context_service_dispose;
|
gobject_class->dispose = server_context_service_dispose;
|
||||||
|
|
||||||
/**
|
|
||||||
* Flag to indicate if keyboard is visible or not.
|
|
||||||
*/
|
|
||||||
pspec = g_param_spec_boolean ("visible",
|
|
||||||
"Visible",
|
|
||||||
"Visible",
|
|
||||||
FALSE,
|
|
||||||
G_PARAM_READWRITE);
|
|
||||||
g_object_class_install_property (gobject_class,
|
|
||||||
PROP_VISIBLE,
|
|
||||||
pspec);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ServerContextServie:keyboard:
|
* ServerContextServie:keyboard:
|
||||||
*
|
*
|
||||||
@ -452,13 +332,3 @@ server_context_service_new (EekboardContextService *self, struct submission *sub
|
|||||||
init(ui);
|
init(ui);
|
||||||
return ui;
|
return ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
server_context_service_update_visible (ServerContextService *self, gboolean visible) {
|
|
||||||
if (visible) {
|
|
||||||
server_context_service_show_keyboard(self);
|
|
||||||
} else {
|
|
||||||
server_context_service_hide_keyboard(self);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@ -25,10 +25,12 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "animation.h"
|
||||||
#include "eek/eek.h"
|
#include "eek/eek.h"
|
||||||
#include "eekboard/eekboard-context-service.h"
|
#include "eekboard/eekboard-context-service.h"
|
||||||
#include "dbus.h"
|
#include "dbus.h"
|
||||||
#include "layout.h"
|
#include "layout.h"
|
||||||
|
#include "main.h"
|
||||||
#include "outputs.h"
|
#include "outputs.h"
|
||||||
#include "submission.h"
|
#include "submission.h"
|
||||||
#include "server-context-service.h"
|
#include "server-context-service.h"
|
||||||
@ -375,6 +377,11 @@ main (int argc, char **argv)
|
|||||||
g_warning("Wayland input method interface not available");
|
g_warning("Wayland input method interface not available");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct channel ui_channel = main_loop_channel_new();
|
||||||
|
|
||||||
|
struct squeek_animation_visibility_manager *animman = squeek_animation_visibility_manager_new(ui_channel.sender);
|
||||||
|
|
||||||
instance.ui_manager = squeek_uiman_new();
|
instance.ui_manager = squeek_uiman_new();
|
||||||
|
|
||||||
instance.settings_context = eekboard_context_service_new(&instance.layout_choice);
|
instance.settings_context = eekboard_context_service_new(&instance.layout_choice);
|
||||||
@ -394,7 +401,7 @@ main (int argc, char **argv)
|
|||||||
guint owner_id = 0;
|
guint owner_id = 0;
|
||||||
DBusHandler *service = NULL;
|
DBusHandler *service = NULL;
|
||||||
if (connection) {
|
if (connection) {
|
||||||
service = dbus_handler_new(connection, DBUS_SERVICE_PATH);
|
service = dbus_handler_new(connection, DBUS_SERVICE_PATH, animman);
|
||||||
|
|
||||||
if (service == NULL) {
|
if (service == NULL) {
|
||||||
g_printerr ("Can't create dbus server\n");
|
g_printerr ("Can't create dbus server\n");
|
||||||
@ -415,7 +422,7 @@ main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct vis_manager *vis_manager = squeek_visman_new();
|
struct vis_manager *vis_manager = squeek_visman_new(animman);
|
||||||
|
|
||||||
instance.submission = get_submission(instance.wayland.input_method_manager,
|
instance.submission = get_submission(instance.wayland.input_method_manager,
|
||||||
instance.wayland.virtual_keyboard_manager,
|
instance.wayland.virtual_keyboard_manager,
|
||||||
@ -435,13 +442,9 @@ main (int argc, char **argv)
|
|||||||
g_error("Could not initialize GUI");
|
g_error("Could not initialize GUI");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
instance.ui_context = ui_context;
|
|
||||||
squeek_visman_set_ui(vis_manager, instance.ui_context);
|
|
||||||
|
|
||||||
if (instance.dbus_handler) {
|
instance.ui_context = ui_context;
|
||||||
dbus_handler_set_ui_context(instance.dbus_handler, instance.ui_context);
|
register_ui_loop_handler(ui_channel.receiver, instance.ui_context, instance.dbus_handler);
|
||||||
}
|
|
||||||
eekboard_context_service_set_ui(instance.settings_context, instance.ui_context);
|
|
||||||
|
|
||||||
session_register();
|
session_register();
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "animation.h"
|
||||||
#include "eek/eek-types.h"
|
#include "eek/eek-types.h"
|
||||||
#include "outputs.h"
|
#include "outputs.h"
|
||||||
|
|
||||||
@ -14,7 +15,6 @@ uint32_t squeek_uiman_get_perceptual_height(struct ui_manager *uiman);
|
|||||||
|
|
||||||
struct vis_manager;
|
struct vis_manager;
|
||||||
|
|
||||||
struct vis_manager *squeek_visman_new(void);
|
struct vis_manager *squeek_visman_new(struct squeek_animation_visibility_manager *animman);
|
||||||
void squeek_visman_set_ui(struct vis_manager *visman, ServerContextService *ui_context);
|
|
||||||
void squeek_visman_set_keyboard_present(struct vis_manager *visman, uint32_t keyboard_present);
|
void squeek_visman_set_keyboard_present(struct vis_manager *visman, uint32_t keyboard_present);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -5,30 +5,35 @@
|
|||||||
/*! Centrally manages the shape of the UI widgets, and the choice of layout.
|
/*! Centrally manages the shape of the UI widgets, and the choice of layout.
|
||||||
*
|
*
|
||||||
* Coordinates this based on information collated from all possible sources.
|
* Coordinates this based on information collated from all possible sources.
|
||||||
|
*
|
||||||
|
* Somewhat obsoleted by the `animation` module
|
||||||
|
* (except keyboard presence calculation),
|
||||||
|
* and could be folded into that tracker loop as another piece of state.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use crate::animation::{
|
||||||
|
ThreadLoopDriver as Receiver,
|
||||||
|
Event as ReceiverMessage,
|
||||||
|
};
|
||||||
|
use crate::logging;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use ::outputs::c::OutputHandle;
|
use ::outputs::c::OutputHandle;
|
||||||
|
|
||||||
|
|
||||||
|
use crate::logging::Warn;
|
||||||
|
|
||||||
|
|
||||||
pub mod c {
|
pub mod c {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::os::raw::c_void;
|
|
||||||
use ::util::c::Wrapped;
|
use ::util::c::Wrapped;
|
||||||
|
|
||||||
/// ServerContextService*
|
use ::util::CloneOwned;
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct UIManager(*const c_void);
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
pub fn server_context_service_update_visible(imservice: *const UIManager, active: u32);
|
|
||||||
pub fn server_context_service_release_visibility(imservice: *const UIManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C"
|
pub extern "C"
|
||||||
fn squeek_visman_new() -> Wrapped<VisibilityManager> {
|
fn squeek_visman_new(receiver: Wrapped<Receiver>) -> Wrapped<VisibilityManager> {
|
||||||
Wrapped::new(VisibilityManager {
|
Wrapped::new(VisibilityManager {
|
||||||
ui_manager: None,
|
receiver: receiver.clone_owned(),
|
||||||
visibility_state: VisibilityFactors {
|
visibility_state: VisibilityFactors {
|
||||||
im_active: false,
|
im_active: false,
|
||||||
physical_keyboard_present: false,
|
physical_keyboard_present: false,
|
||||||
@ -36,15 +41,6 @@ pub mod c {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use to initialize the UI reference
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C"
|
|
||||||
fn squeek_visman_set_ui(visman: Wrapped<VisibilityManager>, ui_manager: *const UIManager) {
|
|
||||||
let visman = visman.clone_ref();
|
|
||||||
let mut visman = visman.borrow_mut();
|
|
||||||
visman.set_ui_manager(Some(ui_manager))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C"
|
pub extern "C"
|
||||||
fn squeek_visman_set_keyboard_present(visman: Wrapped<VisibilityManager>, present: u32) {
|
fn squeek_visman_set_keyboard_present(visman: Wrapped<VisibilityManager>, present: u32) {
|
||||||
@ -169,48 +165,24 @@ impl VisibilityFactors {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporary struct for migration. Should be integrated with Manager eventually.
|
|
||||||
pub struct VisibilityManager {
|
pub struct VisibilityManager {
|
||||||
/// Owned reference. Be careful, it's shared with C at large
|
/// Forward changes there.
|
||||||
ui_manager: Option<*const c::UIManager>,
|
receiver: Receiver,
|
||||||
visibility_state: VisibilityFactors,
|
visibility_state: VisibilityFactors,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VisibilityManager {
|
impl VisibilityManager {
|
||||||
fn set_ui_manager(&mut self, ui_manager: Option<*const c::UIManager>) {
|
|
||||||
let new = VisibilityManager {
|
|
||||||
ui_manager,
|
|
||||||
..unsafe { self.clone() }
|
|
||||||
};
|
|
||||||
self.apply_changes(new);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn apply_changes(&mut self, new: Self) {
|
fn apply_changes(&mut self, new: Self) {
|
||||||
if let Some(ui) = &new.ui_manager {
|
let request = match self.visibility_state.transition_to(&new.visibility_state) {
|
||||||
if self.ui_manager.is_none() {
|
VisibilityTransition::Hide => Some(ReceiverMessage::ForceHide),
|
||||||
// Previous state was never applied, so effectively undefined.
|
VisibilityTransition::Show => Some(ReceiverMessage::ClaimVisible),
|
||||||
// Just apply the new one.
|
VisibilityTransition::Release => Some(ReceiverMessage::ReleaseVisible),
|
||||||
let new_state = new.visibility_state.desired();
|
VisibilityTransition::NoTransition => None,
|
||||||
unsafe {
|
};
|
||||||
c::server_context_service_update_visible(
|
|
||||||
*ui,
|
if let Some(request) = request {
|
||||||
(new_state == Visibility::Visible) as u32,
|
new.receiver.send(request)
|
||||||
);
|
.or_warn(&mut logging::Print, logging::Problem::Warning, "Can't send to animation manager");
|
||||||
}
|
|
||||||
} else {
|
|
||||||
match self.visibility_state.transition_to(&new.visibility_state) {
|
|
||||||
VisibilityTransition::Hide => unsafe {
|
|
||||||
c::server_context_service_update_visible(*ui, 0);
|
|
||||||
},
|
|
||||||
VisibilityTransition::Show => unsafe {
|
|
||||||
c::server_context_service_update_visible(*ui, 1);
|
|
||||||
},
|
|
||||||
VisibilityTransition::Release => unsafe {
|
|
||||||
c::server_context_service_release_visibility(*ui);
|
|
||||||
},
|
|
||||||
VisibilityTransition::NoTransition => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*self = new;
|
*self = new;
|
||||||
}
|
}
|
||||||
@ -237,11 +209,10 @@ impl VisibilityManager {
|
|||||||
self.apply_changes(new);
|
self.apply_changes(new);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The struct is not really safe to clone due to the ui_manager reference.
|
|
||||||
/// This is only a helper for getting desired visibility.
|
/// This is only a helper for getting desired visibility.
|
||||||
unsafe fn clone(&self) -> Self {
|
unsafe fn clone(&self) -> Self {
|
||||||
VisibilityManager {
|
VisibilityManager {
|
||||||
ui_manager: self.ui_manager.clone(),
|
receiver: self.receiver.clone(),
|
||||||
visibility_state: self.visibility_state.clone(),
|
visibility_state: self.visibility_state.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user