1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License in the LICENSE-APACHE file or at:
//     https://www.apache.org/licenses/LICENSE-2.0

//! Event handling
//!
//! Event handling uses *event* messages, passed from the parent into a widget,
//! with responses passed back to the parent. This model is simpler than that
//! commonly used by GUI frameworks: widgets do not need a pointer to their
//! parent and any result is pushed back up the call stack. The model allows
//! type-safety while allowing user-defined result types.
//!
//! We deliver events only on a "need to know" basis: typically, only one widget
//! will receive an event.
//!
//! ## Event delivery
//!
//! Events can be addressed only to a [`WidgetId`], so the first step (for
//! mouse and touch events) is to use [`kas::Layout::find_id`] to translate a
//! coordinate to a [`WidgetId`].
//!
//! Events then process from root to leaf. [`SendEvent::send`] is responsible
//! for forwarding an event to the appropriate child. Once the target widget is
//! reached, `send` (usually) calls [`Manager::handle_generic`] which may apply
//! some transformations to events, then calls [`Handler::handle`] on target
//! widget. Finally, a [`Response`] is emitted.
//!
//! The [`Response`] enum has a few variants; most important is `Msg(msg)`
//! which passes a user-defined payload up to a parent widget. The
//! `Unhandled(event)` and `Focus(rect)` variants may be trapped by any parent
//! for secondary purposes, e.g. to adjust a `ScrollRegion`.
//!
//! ## Mouse and touch events
//!
//! Mouse events and touch events are unified: both have a "press" which starts
//! somewhere, moves, and ends somewhere. The main difference concerns move
//! events, which may occur with any number of mouse buttons pressed.
//!
//! Motion and release events are only delivered when a "press grab" is active.
//! This is achieved by calling [`Manager::request_grab`] and allows receiving
//! both relative and absolute press coordinates.
//! A special "pan" grab allows receiving two-finger scroll/scale/rotate input.
//!
//! Each touch event is considered independent. The mouse cursor and multiple
//! fingers may all interact with different parts of a UI simultaneously. The
//! same is partly true of keyboard input, though some actions force keyboard
//! focus.
//!
//! ### Pop-ups
//!
//! When a pop-up widget is created, this forces keyboard focus to that widget
//! and receives a "weak" grab on press actions, meaning that the widget
//! receives this input first, but if returned via `Response::Unhandled` the
//! input passes immediately to the next target. This allows pop-up menus to
//! get first chance of handling input and to dismiss themselves when input is
//! for other widgets without blocking other widgets from accepting that input.
//! (This "weak grab" behaviour is intentional to align UI response with a
//! user's intuition that any visible non-grey part of the UI is interactive.)
//!
//! ## Drawing
//!
//! Widgets do not usually track input events for the purpose of drawn effects
//! such as mouse-hover. Instead, a widget calls [`WidgetCore::input_state`]
//! with a reference to the [`ManagerState`] (which is passed to
//! [`Layout::draw`] calls) in order to obtain an [`InputState`] instance.
//!
//! [`WidgetId`]: crate::WidgetId

mod callback;
#[cfg(not(feature = "winit"))]
mod enums;
mod events;
mod handler;
mod manager;
mod response;
mod update;

use smallvec::SmallVec;
use std::fmt::Debug;

// doc imports
#[allow(unused)]
use kas::{draw::InputState, Layout, WidgetCore};

#[cfg(feature = "winit")]
pub use winit::event::{ModifiersState, MouseButton, VirtualKeyCode};
#[cfg(feature = "winit")]
pub use winit::window::CursorIcon;

pub use callback::Callback;
#[cfg(not(feature = "winit"))]
pub use enums::{CursorIcon, ModifiersState, MouseButton, VirtualKeyCode};
pub use events::*;
pub use handler::{Handler, SendEvent};
pub use manager::{ConfigureManager, GrabMode, Manager, ManagerState};
pub use response::Response;
pub use update::UpdateHandle;

/// A type supporting a small number of key bindings
///
/// This type may be used where it is desirable to support a small number of
/// key bindings. The type is allowed to silently ignore extra bindings beyond
/// some *small* number of at least 3. (Currently numbers over 5 are accepted
/// but cause allocation.)
pub type VirtualKeyCodes = SmallVec<[VirtualKeyCode; 5]>;

#[test]
fn size_of_virtual_key_codes() {
    // Currently sized to maximise use of available space on 64-bit platforms
    assert!(std::mem::size_of::<VirtualKeyCodes>() <= 32);
}

/// A void message
///
/// This type is not constructible, therefore `Response<VoidMsg>` is known at
/// compile-time not to contain a `Response::Msg(..)` variant.
///
/// It is trivial to implement `From<VoidMsg>` for any type `T`; unfortunately
/// Rust's type system is too restrictive for us to provide a blanket
/// implementation (due both to orphan rules for trait implementations and to
/// conflicting implementations; it is possible that this may change in the
/// future).
///
/// `From<VoidMsg>` is implemented for a number of language types;
/// custom message types are required to implement this via the
/// [`derive(VoidMsg)`](../macros/index.html#the-derivevoidmsg-macro) macro.
#[derive(Clone, Debug)]
pub enum VoidMsg {}

/// Alias for `Response<VoidMsg>`
pub type VoidResponse = Response<VoidMsg>;

// TODO(specialization): replace below impls with impl<T> From<VoidMsg> for T
macro_rules! impl_void_msg {
    () => {};
    ($t:ty) => {
        impl From<VoidMsg> for $t {
            fn from(_: VoidMsg) -> $t {
                unreachable!()
            }
        }
    };
    ($t:ty, $($tt:ty,)*) => {
        impl_void_msg!($t);
        impl_void_msg!($($tt,)*);
    };
}
impl_void_msg!(bool, char,);
impl_void_msg!(u8, u16, u32, u64, u128, usize,);
impl_void_msg!(i8, i16, i32, i64, i128, isize,);
impl_void_msg!(f32, f64,);
impl_void_msg!(&'static str, String, kas::string::CowString,);