Skip to content

Commit 907ad5b

Browse files
committed
Get text cursor to blink correctly
1 parent b2dac2c commit 907ad5b

File tree

7 files changed

+54
-13
lines changed

7 files changed

+54
-13
lines changed

api.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -5519,7 +5519,8 @@
55195519
{"on_virtual_key_down": {"type": "OptionTextInputOnVirtualKeyDown"}},
55205520
{"on_focus_lost": {"type": "OptionTextInputOnFocusLost"}},
55215521
{"update_text_input_before_calling_focus_lost_fn": {"type": "bool"}},
5522-
{"update_text_input_before_calling_vk_down_fn": {"type": "bool"}}
5522+
{"update_text_input_before_calling_vk_down_fn": {"type": "bool"}},
5523+
{"cursor_animation": {"type": "OptionTimerId"}}
55235524
]
55245525
},
55255526
"TextInputState": {

api/c/azul.h

+1
Original file line numberDiff line numberDiff line change
@@ -9487,6 +9487,7 @@ struct AzTextInputStateWrapper {
94879487
AzOptionTextInputOnFocusLost on_focus_lost;
94889488
bool update_text_input_before_calling_focus_lost_fn;
94899489
bool update_text_input_before_calling_vk_down_fn;
9490+
AzOptionTimerId cursor_animation;
94909491
};
94919492
typedef struct AzTextInputStateWrapper AzTextInputStateWrapper;
94929493

api/cpp/azul.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -8674,6 +8674,7 @@ namespace dll {
86748674
OptionTextInputOnFocusLost on_focus_lost;
86758675
bool update_text_input_before_calling_focus_lost_fn;
86768676
bool update_text_input_before_calling_vk_down_fn;
8677+
OptionTimerId cursor_animation;
86778678
TextInputStateWrapper& operator=(const TextInputStateWrapper&) = delete; /* disable assignment operator, use std::move (default) or .clone() */
86788679
TextInputStateWrapper(const TextInputStateWrapper&) = delete; /* disable copy constructor, use explicit .clone() */
86798680
TextInputStateWrapper() = delete; /* disable default constructor, use C++20 designated initializer instead */

api/rust/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8609,6 +8609,7 @@ mod dll {
86098609
pub on_focus_lost: AzOptionTextInputOnFocusLost,
86108610
pub update_text_input_before_calling_focus_lost_fn: bool,
86118611
pub update_text_input_before_calling_vk_down_fn: bool,
8612+
pub cursor_animation: AzOptionTimerId,
86128613
}
86138614

86148615
/// Re-export of rust-allocated (stack based) `ProgressBar` struct

azul-dll/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11121,6 +11121,7 @@ mod test_sizes {
1112111121
pub on_focus_lost: AzOptionTextInputOnFocusLost,
1112211122
pub update_text_input_before_calling_focus_lost_fn: bool,
1112311123
pub update_text_input_before_calling_vk_down_fn: bool,
11124+
pub cursor_animation: AzOptionTimerId,
1112411125
}
1112511126

1112611127
/// Re-export of rust-allocated (stack based) `ProgressBar` struct

azul-dll/src/python.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -6971,6 +6971,7 @@ pub struct AzTextInputStateWrapper {
69716971
pub on_focus_lost: AzOptionTextInputOnFocusLostEnumWrapper,
69726972
pub update_text_input_before_calling_focus_lost_fn: bool,
69736973
pub update_text_input_before_calling_vk_down_fn: bool,
6974+
pub cursor_animation: AzOptionTimerIdEnumWrapper,
69746975
}
69756976

69766977
/// Re-export of rust-allocated (stack based) `ProgressBar` struct
@@ -21787,14 +21788,15 @@ impl PyObjectProtocol for AzTextInput {
2178721788
#[pymethods]
2178821789
impl AzTextInputStateWrapper {
2178921790
#[new]
21790-
fn __new__(inner: AzTextInputState, on_text_input: AzOptionTextInputOnTextInputEnumWrapper, on_virtual_key_down: AzOptionTextInputOnVirtualKeyDownEnumWrapper, on_focus_lost: AzOptionTextInputOnFocusLostEnumWrapper, update_text_input_before_calling_focus_lost_fn: bool, update_text_input_before_calling_vk_down_fn: bool) -> Self {
21791+
fn __new__(inner: AzTextInputState, on_text_input: AzOptionTextInputOnTextInputEnumWrapper, on_virtual_key_down: AzOptionTextInputOnVirtualKeyDownEnumWrapper, on_focus_lost: AzOptionTextInputOnFocusLostEnumWrapper, update_text_input_before_calling_focus_lost_fn: bool, update_text_input_before_calling_vk_down_fn: bool, cursor_animation: AzOptionTimerIdEnumWrapper) -> Self {
2179121792
Self {
2179221793
inner,
2179321794
on_text_input,
2179421795
on_virtual_key_down,
2179521796
on_focus_lost,
2179621797
update_text_input_before_calling_focus_lost_fn,
2179721798
update_text_input_before_calling_vk_down_fn,
21799+
cursor_animation,
2179821800
}
2179921801
}
2180021802

azul-dll/src/widgets/text_input.rs

+45-11
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use azul_desktop::{
99
Dom, NodeDataInlineCssProperty, NodeDataInlineCssPropertyVec,
1010
NodeDataInlineCssProperty::{Normal, Hover, Focus}
1111
},
12+
task::OptionTimerId,
1213
callbacks::{RefAny, Callback, CallbackInfo, Update},
1314
};
1415
use azul_core::{callbacks::{Animation, AnimationRepeatCount}, task::SystemTimeDiff, window::{KeyboardState, VirtualKeyCode}};
@@ -43,6 +44,7 @@ pub struct TextInputStateWrapper {
4344
pub on_focus_lost: OptionTextInputOnFocusLost,
4445
pub update_text_input_before_calling_focus_lost_fn: bool,
4546
pub update_text_input_before_calling_vk_down_fn: bool,
47+
pub cursor_animation: OptionTimerId,
4648
}
4749

4850
#[derive(Debug, Copy, Clone, PartialEq)]
@@ -285,6 +287,8 @@ static TEXT_INPUT_CONTAINER_PROPS: &[NodeDataInlineCssProperty] = &[
285287

286288
#[cfg(target_os = "windows")]
287289
static TEXT_INPUT_LABEL_PROPS: &[NodeDataInlineCssProperty] = &[
290+
Normal(CssProperty::const_display(LayoutDisplay::InlineBlock)),
291+
Normal(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(0))),
288292
Normal(CssProperty::const_position(LayoutPosition::Relative)),
289293
Normal(CssProperty::const_font_size(StyleFontSize::const_px(13))),
290294
Normal(CssProperty::const_text_color(StyleTextColor { inner: COLOR_4C4C4C })),
@@ -293,15 +297,19 @@ static TEXT_INPUT_LABEL_PROPS: &[NodeDataInlineCssProperty] = &[
293297

294298
#[cfg(target_os = "linux")]
295299
static TEXT_INPUT_LABEL_PROPS: &[NodeDataInlineCssProperty] = &[
296-
Normal(CssProperty::const_position(LayoutPosition::Relative)),
300+
Normal(CssProperty::const_display(LayoutDisplay::InlineBlock)),
301+
Normal(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(0))),
302+
Normal(CssProperty::const_position(LayoutPosition::Relative)),
297303
Normal(CssProperty::const_font_size(StyleFontSize::const_px(13))),
298304
Normal(CssProperty::const_text_color(StyleTextColor { inner: COLOR_4C4C4C })),
299305
Normal(CssProperty::const_font_family(SANS_SERIF_FAMILY)),
300306
];
301307

302308
#[cfg(target_os = "macos")]
303309
static TEXT_INPUT_LABEL_PROPS: &[NodeDataInlineCssProperty] = &[
304-
Normal(CssProperty::const_position(LayoutPosition::Relative)),
310+
Normal(CssProperty::const_display(LayoutDisplay::InlineBlock)),
311+
Normal(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(0))),
312+
Normal(CssProperty::const_position(LayoutPosition::Relative)),
305313
Normal(CssProperty::const_font_size(StyleFontSize::const_px(13))),
306314
Normal(CssProperty::const_text_color(StyleTextColor { inner: COLOR_4C4C4C })),
307315
Normal(CssProperty::const_font_family(SANS_SERIF_FAMILY)),
@@ -339,6 +347,7 @@ impl Default for TextInputStateWrapper {
339347
on_focus_lost: None.into(),
340348
update_text_input_before_calling_focus_lost_fn: true,
341349
update_text_input_before_calling_vk_down_fn: true,
350+
cursor_animation: None.into(),
342351
}
343352
}
344353
}
@@ -452,6 +461,13 @@ impl TextInput {
452461
].into())
453462
.with_children(vec![
454463
Dom::text(label_text)
464+
.with_callbacks(vec![
465+
CallbackData {
466+
event: EventFilter::Hover(HoverEventFilter::LeftMouseDown),
467+
data: state_ref.clone(),
468+
callback: Callback { cb: default_on_label_click }
469+
},
470+
].into())
455471
.with_ids_and_classes(vec![Class("__azul-native-text-input-label".into())].into())
456472
.with_inline_css_props(self.label_style)
457473
.with_children(vec![
@@ -740,6 +756,9 @@ extern "C" fn default_on_container_click(text_input: &mut RefAny, info: &mut Cal
740756
Some(s) => s,
741757
None => return Update::DoNothing,
742758
};
759+
760+
println!("container clicked at position {:?}", info.get_cursor_relative_to_node());
761+
743762
// TODO: clear selection, set cursor to text hit
744763
Update::DoNothing
745764
}
@@ -749,6 +768,11 @@ extern "C" fn default_on_label_click(text_input: &mut RefAny, info: &mut Callbac
749768
Some(s) => s,
750769
None => return Update::DoNothing,
751770
};
771+
772+
println!("label clicked at position {:?}", info.get_cursor_relative_to_node());
773+
774+
info.stop_propagation();
775+
752776
// TODO: set cursor to end or start
753777
Update::DoNothing
754778
}
@@ -768,15 +792,20 @@ extern "C" fn default_on_focus_received(text_input: &mut RefAny, info: &mut Call
768792
None => return Update::DoNothing,
769793
};
770794

771-
let timer_id = info.start_animation(cursor_node_id, Animation {
772-
from: CssProperty::const_opacity(StyleOpacity::const_new(100)),
773-
to: CssProperty::const_opacity(StyleOpacity::const_new(0)),
774-
duration: Duration::System(SystemTimeDiff::from_millis(500)),
775-
repeat: AnimationRepeat::PingPong,
776-
repeat_times: AnimationRepeatCount::Infinite,
777-
easing: AnimationInterpolationFunction::EaseInOut,
778-
relayout_on_finish: false,
779-
});
795+
if text_input.cursor_animation.is_none() {
796+
let timer_id = info.start_animation(cursor_node_id, Animation {
797+
from: CssProperty::const_opacity(StyleOpacity::const_new(100)),
798+
to: CssProperty::const_opacity(StyleOpacity::const_new(0)),
799+
duration: Duration::System(SystemTimeDiff::from_millis(500)),
800+
repeat: AnimationRepeat::PingPong,
801+
repeat_times: AnimationRepeatCount::Infinite,
802+
easing: AnimationInterpolationFunction::EaseInOut,
803+
relayout_on_finish: false,
804+
});
805+
if let Some(timer_id) = timer_id {
806+
text_input.cursor_animation = Some(timer_id).into();
807+
}
808+
}
780809

781810
// TODO: start text cursor blinking
782811
Update::DoNothing
@@ -795,6 +824,11 @@ extern "C" fn default_on_focus_lost(text_input: &mut RefAny, info: &mut Callback
795824
let onfocuslost = &mut text_input.on_focus_lost;
796825
let inner = &text_input.inner;
797826

827+
if let Some(timer_id) = text_input.cursor_animation.clone().into_option() {
828+
info.stop_timer(timer_id);
829+
text_input.cursor_animation = None.into();
830+
}
831+
798832
match onfocuslost.as_mut() {
799833
Some(TextInputOnFocusLost { callback, data }) => (callback.cb)(data, info, &inner),
800834
None => Update::DoNothing,

0 commit comments

Comments
 (0)