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,45 +5,41 @@
 | 
				
			|||||||
/*! 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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    use ::util::CloneOwned;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// ServerContextService*
 | 
					 | 
				
			||||||
    #[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,
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    /// 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"
 | 
				
			||||||
@ -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