#Text Input

449 messages Β· Page 1 of 1 (latest)

livid cape
#

@cedar sentinel @dire ginkgo

long pendant
#

Awesome

golden cypress
analog moon
#

I'm not sure there's much to discuss here; we know what we want, pretty much, and what we need to do. It's just a question of doing it.

#

@cedar sentinel 's earlier PR, based on cosmic-edit, had pretty much everything I could have asked for; it had a few rough edges but it worked.

cedar sentinel
#

Yep there's really not much to do to make a minimal implementation either, I've got most of it done just not had time yet this week to put everything together

analog moon
#

Let me summarize what we know:

  • We know what features we eventually want (there are several lists, see alice's PR)
  • We know roughly the shape of the API, the people working on this have generally good instincts/taste for this sort of thing
  • We know what an MVP looks like (Alice's PR sketches this out)
  • I have a pretty good idea of what the feathers wrapper will look like (focus rings, adornments like "clear" "search" icons and so on)
#

I guess there is some controversy around whether or not we are going to adopt a general undo solution

#

But that can be decided post-MVP

cedar sentinel
#

yeah, I'm just going to leave out undo and copy and paste from the initial PR

#

I can't be bothered to deal with the discussions etc

analog moon
#

If it were me, I'd use undo_2 and arboard. While Bevy tries to be minimal dependencies, this is not going to happen with clipboard support.

cedar sentinel
#

yes that's what i'd do too, and what I used for my other implementations

#

only minor snag is how to handle async clipboard access

dire ginkgo
pallid hemlock
#

The plain-text clipboard support is so simple that it seems not very controversial to me. It's ~20 LoC in Blitz. And half of that is matching on the keyboard events that trigger the actions. So it'd be easy to just add it and migrate to something else later if desired.

analog moon
dire ginkgo
#

I agree, but starting with plain text seems very sensible

tough matrix
#

Does seem worth it to reinvent it though. We're probably not going to write a complete clipboard impl for ourselves, and we'll need it => we'll eventually use something like arboard. So might as well do that now. (Unless there's some argument against arboard but it seems good to me as an outsider.)

analog moon
#

Clipboard support is one of those areas where the different OSs have significantly different features and semantics, and coming up with a "least common denominator" (other than plain text) is a non-trivial puzzle.

tough matrix
#

Yeah that's exactly why I don't foresee bevy pulling through this effort

terse scarab
#

Ime clipboard is one of those domains where people are tolerant of jank for a while

#

If it isn't supported at all, that's too far. If it's limited but works in an intuitive way (binary blobs don't get dumped into text input boxes) there is understanding.

analog moon
#

Undo is a different story; we could certainly write our own undo manager, as it doesn't rely on any platform APIs; however, coming up with an abstraction that satisfies the needs of every stakeholder (text input, bevy editor, third-party editors, etc.) is going to require a very broad vision, and the existing third-party crates have already solved this adequately.

#

Up to this point we've seen numerous proposals for undo coming from stakeholders that solve that particular stakeholder's needs.

terse scarab
#

Do we know how other projects (i.e. Godot, blender) solve this?

analog moon
#

I've done undo many times in different languages (TypeScript, C#, C++, etc.)

dire ginkgo
analog moon
#

Actually, the question that has me scratching my head is "how do browsers solve this?"

terse scarab
terse scarab
analog moon
#

That is, there's a perfectly nice API exposed to JavaScript in the browser. But I don't see how you get from there to the Windows clipboard API.

#

In Linux and MacOS, clipboard types are identified by MIME types, but windows has its own bespoke system of type ids.

#

Crates like arboard offer an abstraction which somehow papers over the fact that windows is an outlier.

terse scarab
#

I'm looking through the firefox repo and I'm struggling to get a clear answer, there's a lot of different contexts in which a clipboard needs to be wrapped. Mozilla has its XPCOM framework to abstract over these things, with nsiClipboard/nsiClipboardHelper being the central classes clipboard functionality is based around. I'll be back in a bit if I find anything more.

pallid hemlock
terse scarab
pallid hemlock
#

On Windows, follow the convention described below:

  • If osFormatName "UnicodeText", then set mimeTypeString to "text/plain".
  • Else, if osFormatName "HTML Format", then set mimeTypeString to "text/html".
  • Else, if osFormatName "PNG", then set mimeTypeString to "image/png".
  • Else, if osFormatName CFSTR_MIME_SVG_XML, then set mimeTypeString to "image/svg+xml".
terse scarab
#

so there is just a consensus in cross-platform management by "windows is weird and inconsistent, match on its inputs and make it look like unix"

terse scarab
analog moon
#

"Classic" undo has two stacks: an undo stack and a redo stack, invoking the undo command pops an entry off the undo stack and pushes it on the redo stack.

#

The difference between these is in classic undo, typing (or doing any edit other than an undo or redo) clears the redo stack.

#

That means if you undo a whole bunch of edits, and then type a single key, you can no longer redo those edits. This is the way that most apps work.

#

In GURQ-style undo, there's only a single timeline, and making edits does not clear the redo chain, so you don't lose anything. The downside is that users may not be used to this behavior.

#

If we were going to go with classic undo, then I would vote for building our own; the two-stack design is trivial.

#

If we wanted to use GURQ-style undo, however, the algorithm is subtle and somewhat non-intuitive, I'd rather use a battle-tested crate than roll our own.

terse scarab
#

the GURQ style sounds a bit like a right-click-to-select situation

#

I'm sure there's people who swear by it but it doesn't make much sense as a default.

golden cypress
golden cypress
#

I suggest you go commit-by-commit

dire ginkgo
steady gulch
#

hiya! coming over from jackdaw - we are heavily relying on bevy_ui_text_input for pretty much all of our text input widgets. was wondering if i could help here at all πŸ™‚

dire ginkgo
analog moon
#

@cedar sentinel I thought you had a new text input PR in the works, is that still happening?

#

Or are we going with @golden cypress 's work?

golden cypress
#

Mine is built on Alice and Ickshonpe's branches

dire ginkgo
golden cypress
#

Figured out the cursor/ selection not being in the right spot - scale factor!

golden cypress
golden cypress
dire ginkgo
dire ginkgo
golden cypress
#

Thanks @dire ginkgo , should be good to go

dire ginkgo
cedar sentinel
#

The main problem left that's concerning me is scrolling support

#

And the API for editable value fields, an InputField<T> component seems ideal but I don't how well require works with generics

#

maybe if it just implements From/Into String it's probably okay

dire ginkgo
#

@cedar sentinel really nice review here, thanks

analog moon
#

I'd like for someone to test bidi text

#

Although, if it doesn't work we can fix it later

dire ginkgo
cedar sentinel
dire ginkgo
golden cypress
#

Hey @cedar sentinel thank you for the review. I've πŸ‘ most of the comments, some I will need to check when I'm at my computer, and just a few I have some pushback on. I will push some changes then change back to S-Needs-Review

golden cypress
#

Okay would love your thoughts now πŸ˜„

dire ginkgo
#

We can and maybe should refine it a bit more before 0.19

#

But this should still be useful

cedar sentinel
#

needs another review but it's not very complicated

analog moon
cedar sentinel
#

the size of the node minus padding, margin, and scrollbar areas

analog moon
cedar sentinel
#

yep should be changed

#

I think it's probably the ContentSize component that needs to be renamed

#

the docs need an overhaul as well and there should be a custom measure func example

analog moon
# cedar sentinel yep should be changed

Also; it seems like this is now effectively a layout input property, like the properties in Node; as you know, I have been a proponent of splitting up Node, but there's also a faction that believes that Node should be unitary. My question would be, is this intended to be a slippery slope introduction to a non-unitary Node?

cedar sentinel
#

not really, ContentSize is normally updated by the widget implementations, not users, so it shouldn't be included in Node

#

imo

analog moon
cedar sentinel
#

part of the problem is I wasn't really clear how it was meant to work when I added it originally, there were some confusing bugs in taffy and I got it working through trial and error mostly

cedar sentinel
analog moon
#

This would allow you to isolate clipboard support - and its dependencies - in a separate add-on.

cedar sentinel
#

in on_focused_keyboard_input if a key is pressed the event is consumed but the corresponding release event is propagated, is that a bug

cedar sentinel
cedar sentinel
analog moon
cedar sentinel
#

it's complicated a bit because of clipboard access being async on web

analog moon
# cedar sentinel it's complicated a bit because of clipboard access being async on web

The most important thing, I think, is to ensure that in an app that supports both clipboard use on an individual text field level, but which also supports cut/copy/paste at some larger scope (such as copying parts of a scene or node graph) that we handle both contexts consistently. This probably won't apply to most games, but will to some editors.

#

So for example, if we build in support for arboard at the text input level (a choice which is convenient for people who only need clipboard support at the text input level), then a user writing an advanced editor either has the choice to also use arboard, or to have two different clipboard crates in their app.

dire ginkgo
analog moon
#

I'm going to cut and paste the list of text input features here, we should probably make a roadmap-style issue:

  • Home / End key support for moving the cursor to the start / end of the text
  • Placeholder text (displayed when the input is empty)
  • Click to place cursor
  • Cursor blinking
  • Clipboard operations (copy, cut, paste)
  • Undo/redo functionality
  • Newline support for multi-line input
  • Input Method Editor (IME) support for complex scripts
  • Text validation (e.g., email format, numeric input, max length)
  • Password-style character masking
  • Soft-wrapping of long lines
  • Vertical scrolling for multi-line input
  • Horizontal scrolling for long lines
  • Mobile pop-up keyboard support
  • Overwrite mode (typically toggled by the Insert key)
  • Bidirectional text support (e.g., mixing left-to-right and right-to-left scripts)
  • AccessKit integration for screen readers and other assistive technologies
  • World-space text input
  • Text input labels (used for accessibility, tooltips or form descriptions)
  • Input consumption (preventing other systems from receiving keyboard input events when the text input is focused)
  • Text form submission handling
    Some of these appear to already be done, I'm just pasting what's in the comment
#

The comment says "these features are planned but currently not implemented" but that's not correct

#

Actually, I think I'll just put these bullet points in a comment on the Goal issue

cedar sentinel
cedar sentinel
cedar sentinel
analog moon
#

@cedar sentinel I'm particularly interested in the re-instatement of your validation logic, as that will be useful for the feathers numeric input widget

cedar sentinel
#

yep what design have you got in mind for the feathers input widgets?

#

there mostly shouldn't be that much difference as the construction for the input widgets is relatively trival because its only one entity

#

so there's no need for internal communication between entities which is where a lot of the complexity and sychronisation problems seem to come in usually

analog moon
cedar sentinel
#

oh yes those dragger inputs I've always hated those but I've had to implement them before for work projects because some people for indecipherable reasons seem to love them

analog moon
#

For regular text input, my plan is to have an outer frame entity which draws a border, and then contains internal decorations (like a "clear" button), with the actual text widget being an inner child.

cedar sentinel
#

oh yes and for numeric units you'd want to to display the units

analog moon
cedar sentinel
#

can be but it's maybe simpler just for it to be a separate text node and lay it out with the text node left to right

analog moon
cedar sentinel
#

selection might be tricky with a custom formatter too

analog moon
#

Sometimes you have combo sliders with the slider label and the value all contained within the slider bounds

cedar sentinel
#

and someone might want the units to be a dropdown so you change from kg to pounds or something

analog moon
#

For placeholders, we can either do them built-in to the text input widget, or we can do them externally at the feathers level.

  • Making them built-in is convenient for people who just want a basic text input
  • Making the placeholder external allows for greater stylistic flexibility - I've seen (on the web) widgets where the placeholders smoothly animate out of the way
#

Or more realistically, say I want the placeholders to be italic - building that flexibility into the text widget itself makes things more complex

cedar sentinel
#

for placeholder text I think a second node stacked on top occupying the same layout space is probably a simpler design, and then you just hide one by setting the color to transparent or whatever

analog moon
cedar sentinel
#

I made builtin placeholders on the same Node with my previous text input implementation and they were a pain

analog moon
#

Specifically, what I saw was a version of quantum paper (an early incarnation of material design), where the placeholder turned into a title: the text shrank and moved above the input field. This was a bit overdone - artists being too clever

cedar sentinel
#

yep that sort of fanciness isn't uncommon in games

cedar sentinel
steady gulch
#

hey @cedar sentinel i'm working on porting jackdaw over to your new text input stuff, but i see the cursor is basically static on all input fields, is this expected?

cedar sentinel
#

Got it implemented but waiting for the current batch of prs to get merged

steady gulch
#

amazing, i was hoping it wasn't a bug on my end! i've been testing loads now in jackdaw and can find these features are missing (correct me if i'm wrong here):

  • Ctrl+A (select all)
  • Ctrl+C/V/X (copy/cut/paste)
  • Home/End (line start/end)
  • Ctrl+Left/Right (word jump)
  • Click to place cursor
  • Drag to select
#

and also correct me if any of these have open PRs

pallid hemlock
#

On macOS, it should be Meta rather than Ctrl

steady gulch
#

woo! i might be able to cherry-pick those PRs and test them in jackdaw if you like?

cedar sentinel
#

they've got enough reviews I think but got more PRs I'm going to publish in an hour or two

steady gulch
cedar sentinel
dire ginkgo
cedar sentinel
dire ginkgo
analog moon
#

Q: It's been a while since I used a terminal that had a blinking cursor; do you remember if the blink rate is completely independent of user action, or does the timer reset when the user types?

terse scarab
#

in vs code the cursor stays visible while you're typing

cedar sentinel
analog moon
cedar sentinel
#

yep, maybe needs a mechanism to queue errors or suspend processing the edits buffer until the next update

#

oh queue errors what am I thinking of, that would just be an event

cedar sentinel
cedar sentinel
cedar sentinel
#

from then it's just bikeshedding the API and features like placeholder text, filters and overwrite cursors etc

dire ginkgo
analog moon
cedar sentinel
#

Then there's no need for any validation, as every input is valid? Except for an empty string but that can just be interpreted as zero.

#

we don't have any notion of locking InputFocus yet right? That's useful as well for text inputs where you need some input from the user to proceed

analog moon
analog moon
#

@cedar sentinel In order for EditableText to be used in BSN, it needs to impl either Clone or FromTemplate. Any thoughts?

cedar sentinel
#

PlainEditor is cloneable, so there's no problem with implementing Clone for EditableText

analog moon
#

Also, I kind of wish that the text edit state and the configuration params were separated into different components

cedar sentinel
#

yeah I agree very strongly I've just been going along with the design of the initial PR for now

#

and figured once all the features are added it can get split up

analog moon
#

If you look at this shot from the editor mocks, you can see that the text input has extra decorations like the filter dropdown button. I always assumed that feathers would add this stuff by wrapping the text input in an outer entity which would hold both the raw text input and the decorations. However, it means that when we want to get and set the state of the text input, we have to work with a child element.

cedar sentinel
#

that's the same for a lot of widgets

#

or is the current design making that more awkward?

analog moon
#

It also means that the text input is going to have to handle focus indicators in a custom way

#

because it's the opposite of a checkbox: the outer element wants an indicator when the inner entity is focused

#

which is fine; I kind of like focus outlines on text inputs to be inset rather than outset anyway

cedar sentinel
#

ah

#

yeah because the EditableText node has InputFocus

#

when normally with the other designs the root entity of the widget has the focus

analog moon
#

@cedar sentinel Seeing a couple problems:

  • Selection highlight drawn on top of text
  • Can't figure out how to disable soft wrap
cedar sentinel
#

yep those were two problems with the inital PR implementation

#

I've fixed the wrapping in the scrolling branch I was working there was just edge cases with cursors I was trying to work out the cleanest way to fix

#

but

#

I'll make a PR

#

with just the basic changes

analog moon
#

I can also push my WiP if it would be of any help

cedar sentinel
#

yeah it'll be good to have as many examples as we can get

cedar sentinel
#

I'd forgotten about the selection highlight thing it should be possible to set separate colors for highlighted text and text under the cursor as well

analog moon
#
fn update_text_cursor_color(
    mut q_text_input: Query<&mut TextCursorStyle, With<FeathersTextInputInner>>,
    theme: Res<UiTheme>,
) {
    if theme.is_changed() {
        for mut cursor_style in q_text_input.iter_mut() {
            cursor_style.color = theme.color(&tokens::TEXT_INPUT_CURSOR);
            cursor_style.selection_color = theme.color(&tokens::TEXT_INPUT_SELECTION);
        }
    }
}
cedar sentinel
#

there's some flaws, depending on the width of the node sometimes the cursor can get clipped, allow_newlines: false doesn't block pasting in a section of text with a newline

#

there's no support for scroll margins yet

analog moon
# cedar sentinel https://github.com/bevyengine/bevy/pull/23646

Just a general comment. The allow_newlines option seems, erm, rather fine-grained in terms of customization options. In most traditional UI toolkits (Java Swing, HTML), you have a choice of either multiline or not. This controls both what you can type and how scrolling behaves. Of course, code editing apps don't fit this model, as they permit both horizontal and vertical scrolling.

I think I'd prefer a relatively opinionated API that offers them a few sensible choices:

  • single line with no wrapping - useful for asset names in the editor, user login, passwords
  • multi-line with soft wrap - useful for user chat, editing character dialogues
  • and perhaps multi-line without soft wrap, useful for editing scripts (although it might be better to have a dedicated editor for this, one that supports syntax highlighting)
cedar sentinel
#

But thinking about it maybe it makes sense to do the editabletext split up now as hsvong a more opinionated API would make it a lot simpler to fix the remaining issues

analog moon
cedar sentinel
#

No it's much simpler to do it lower down, especially as like multiline without soft wrap is the problematic case and the least important

analog moon
cedar sentinel
#

Yeah numeric fields are far more important for instance

analog moon
#

We can make the choice an enum rather than a boolean flag, so that if someone wants to add a third option later they can

cedar sentinel
#

Do you have an opinion on what the primary components should be called, I was calling single line inputs fields before and multiline inputs boxes

#

But some people seem to prefer it the other way around

analog moon
#

I'd probably pick textinput and textarea

cedar sentinel
#

TextArea is okay

analog moon
#

This would at least be familiar to web coders

cedar sentinel
#

It has the right implication of 2d sizeness

#

And textinput seems fine too

#

Let's go with those for now

analog moon
#

BTW, on the web a single line text input is <input type="text">, so even though it's not literally called "textinput", if you say those words everyone will know what you mean.

cedar sentinel
#

Particularly as we are calling the other one an area

analog moon
#

@cedar sentinel @livid cape I've decided to trade two awkwardnesses for one: separating the feathers text input into a separate "frame" widget like so:

(
    :text_input_frame
    Node {
        flex_grow: 1.0,
    }
    Children [
        (
            text_input(TextInputProps {
                max_characters: None,
            })
            HexColorInput
        )
    ]
)

While this means that users have to know how to arrange the two widgets, it has some benefits:

  • It means that we no longer have to worry about slots for adornments, they can just be regular children
  • It means that users can access the text content directly instead of having to probe the widget's children to get access to the buffer.
dire ginkgo
analog moon
#

@cedar sentinel How hard would it be to emit an observable event when the text buffer changed?

dire ginkgo
analog moon
#

I think I also need to come up with a general "lost focus" event

#

I've managed to hook up the color sliders to set the text input buffer to the hex color, but now I need to go the other direction

dire ginkgo
#

Just a simple Focus Gained / Focus Lost pair

analog moon
#

For editing hex colors, we can either update the color as you type, or update on lost focus

dire ginkgo
analog moon
#

@cedar sentinel Another thing to mention on the topic of multiline: in single-line mode, ENTER should propagate - so that observers can treat that as a submit. In multiline mode, however, it should not propagate.

#

This goes with the general principle that "widgets consume what they use"

cedar sentinel
#

yep that's what I was thinking, any key press that isn't consumed must be propagated

golden cypress
#

Hmm, so this is weird, taking screen recordings on my Mac for text editing isn't working for me, maybe something to do with Focus changes?

dry galleon
#

i frequently hit that with egui apps and have to hit a modifier key to unblock some interactions

#

i forget which modifier key

analog moon
#

@cedar sentinel @dire ginkgo So I'm still not clear on the "right" way to monitor the text buffer for changes. Since this is going to be part of the official feathers example, I want to do it the "canonical" way.

The use case I'm working on adding a hex color input field for the color picker, so that you can type ff88ff etc. I've decided to update the colors in real time rather than waiting for focus loss / submit, since I want the color swatch and sliders to update immediately on paste.

I can think of two ways to do this:

  • Using regular change detection on the EditableText component. However, this will likely trigger on cursor movement (since that also mutates the component), leading to lots of spurious updates.
  • Using observers. The problem here is that because text changes are queued, we don't want to react to changes until the queue is empty, after the changes have been applied. So the event emitter needs to be hooked into the queue machinery.

I'll also need to add logic to avoid cyclic updates: typing into the field modifies the color resource, which triggers replacement of the hex color text; we don't want that to happen while you are typing, so probably I will need to disable those updates while the input has focus.

dire ginkgo
analog moon
dire ginkgo
analog moon
dire ginkgo
#

(and note this behavior)

analog moon
#

Although ValueChange takes a payload (the new value) and I'm not sure we want to copy the text buffer for every event

dire ginkgo
#

Yeah, that may be better / simpler. I'm not actually convinced that my approach would work well, since our methods have &mut self, not Mut<self> πŸ€”

#

Hooking into the queue machinery here seems fine

cedar sentinel
#

What I think is copying/cloning the input contents doesn't matter too much

#

There is only one input active at a time and when they are it's usually exclusive

#

So we should just have like a TextInput(pub String) component

#

That's copied into the plaineditor on changes

#

And copied back after the textedit buffer is applied

#

Then everything will work seamlessly with change detection

analog moon
#

One idea is to modify TextEdit::apply to return a boolean, indicating whether the action actually changed the text; then change apply_text_edits to trigger an event

cedar sentinel
#

I thought it already did something like this

analog moon
#

You might be thinking of

editable_text.text_edited = !editable_text.pending_edits.is_empty();
cedar sentinel
#

But it sets a flag on editabletext atm

#

Yes

analog moon
#

That only tells us if there were any actions, not whether those actions changed the buffer or not. For example, we probably don't want to emit ValueChange on a Copy action

#

Three possibilities:

  • ValueChange(String)
  • ValueChange(()) and let them poll the buffer themselves
  • a new event type, TextEditChange
cedar sentinel
#

I think the first is easiest

#

Unless we're doing a full text editor for large files copying or cloning one string on frames where there is an edit won't matter

#

And even more so for non text inputs

#

As then it can just store the numeric value

analog moon
#

For all other widgets, ValueChange is the proposed new value - because they are all controlled widgets

#

It's the difference between "here's what's going to happen" and "here's what's already happened"

cedar sentinel
#

oh right I see so it's where you click on a button -> an event is sent -> an observer system or something decides whether to update the button state

#

instead of directly updating the button state

golden cypress
#

Why not just emit an event at the end of EditableText::apply_pending_edits() (with an exit early if pending_edits is empty), and just eat the cost of cursor moves?

golden cypress
livid cape
analog moon
# livid cape Yeah it seems like you've struck a solid balance to me.

Yes, but I have a caveat: I don't want this to become a habit. What I mean is, I dodged a bullet here by breaking up a unitary scene into fragments. But this is not a pattern that should be replicated too much - because it undermines scene integrity, it breaks encapsulation and exposes the internals of the scene to the caller.

#

Up to this point we haven't seen too many problems of this kind because all of the feathers widgets are leaf widgets

#

But I expect to see it crop up more as we start moving up the hierarchy

livid cape
#

I believe a combination of β€œstruct scenes”, β€œBsn in Bsn ergonomics”, and reactivity are the path to building proper abstractions.

However I don’t think abstracting over structure is universally a good idea. I think the current approach has a lot going for it

golden cypress
analog moon
cedar sentinel
analog moon
#

@dire ginkgo @cedar sentinel A comment about the hex color input, since you both had things to say about validation: I was trying to keep the example simple, and since Srgb::to_hex() produces a string with a leading # I went with that. A proper color picker would likely make the # a fixed decoration, which would also mean stripping the # or any other extraneous characters on paste or typing.

#

I don't feel super strongly about this, however

cedar sentinel
#

yes it's not that important atm

analog moon
pallid hemlock
cedar sentinel
#

Yep with "#" it doesn't bother me either way, we should go whatever users expect or whichever is the lowest friction option

#

@Talin I was going to start to split up EditableText next, and I was wondering if it would make sense to just get rid of the text edits buffer and make TextEdits into events

analog moon
golden cypress
#

What's the goal of splitting it?

analog moon
# golden cypress What's the goal of splitting it?

Well, one goal is to make change detection more fine-grained; another goal is to make it easier to override the initial state of the buffer. For example, if you have a standard text input widget which adds all the needed components, but you want to give it an initial value, right now you have to replace everything.

cedar sentinel
#

Yes, it's awkward for stuff like the line height measure function, either we need to put those options in another component or copy them somewhere so we can do a comparison to detect changes

cedar sentinel
analog moon
cedar sentinel
#

well to detect changes to the layout with it you can just query for changed TextLayoutInfo or EditableTextGeneration

#

and there's no need to mess around with those flags any more

cedar sentinel
#

and then the EditableText isn't Changed on changes to the parley plain editor, as that can be tracked by EditableTextGeneration

analog moon
#

What about observers?

cedar sentinel
#

we could add a EditableTextModified entity event that triggers on the generation value changing I guess?

analog moon
#

The idea would be to only fire it when there's an actual change

cedar sentinel
#

to do that we'd have to have keep a second copy of the text buffer in a string and compare it on changes

#

as the generation changes with cursor moves too

analog moon
cedar sentinel
#

we could make a fully controlled input that way it's not very hard but we would need to copy the buffers

#

for numeric inputs though it's easier as you can just parse and copy the number

analog moon
#

(I suspect it would not be easy for us to make it bi-modal like this)

#

BTW react's implementation of controlled text has some gnarly hacks, for example the controlled callback can't be asynchronous because otherwise the browser's built in text editing behavior overrules what the javascript is doing

cedar sentinel
#

maybe not, the main thing I'm not happy about is whether the primary component should contain the PlainEditor

#

we could have a TextInput component with a default: Option<String> field

#

but it seems annoying how the default value string would only be used once and then ignored?

#

oh wait I'm being stupid

#

we only need to store the cursor values

#

when the generation changes we can compare the cached cursor + selection with the PlainEditor's

#

and if they are equal, then the text must have changed

#

or the style values, but normally those aren't changed very often or at all once the input is created

analog moon
cedar sentinel
#

we could compare the styles as well i guess

analog moon
#

So I'm not sure what that buys you

cedar sentinel
#

oh yeah, it's not a solution

#

then

#

backspace will move the cursor and delete a character

analog moon
#

Does the generation advance in response to idempotent actions (like hitting backspace at the beginning of the text, or cursor right while at the end)?

cedar sentinel
#

no, not in those cases anyway

pallid hemlock
#

(upstreaming this logic would make a lot of sense)

cedar sentinel
dire ginkgo
#

Currently about to take a nap though, so expect a few hours

cedar sentinel
#

I'm just about to go to sleep too so np

analog moon
#

I noticed that we don't have double-click to select, which I'm guessing is because we don't have double click support in Bevy.

cedar sentinel
#

I have it on the text input crate

#

It shouldn't be difficult I think, it just wasn't a priority

cedar sentinel
analog moon
#

@dire ginkgo @cedar sentinel I could have made use of cut and paste today; would it be possible to get the clipboard PR back on track?

dire ginkgo
#

I need to fix some ambiguities but it's basically done

analog moon
#

That reminds me, I noticed a certain amount of friction dealing with String / SmolStr / SplitString - for example, say I have a string slice, and I want to:

  • test the current value of the text buffer to see if it matches the slice
  • if it doesn't match, update the text buffer, replacing the text
    Since I can't compare a str slice with a SplitString, I need to convert the StringSlice to a common representation - String - and then compare them; then afterwards I need to convert the slice to a SmolStr so that I can queue it.
dire ginkgo
#

Yeah, I feel that

#

Not sure what to do though

analog moon
dire ginkgo
#

Could we compare as &str or something?

analog moon
dire ginkgo
#

But yeah, custom comparator trait or something is probably the way

#

Thanks @pale pecan for the IME testing; much harder to debug as a non-speaker

pale pecan
#

The two longer comments I wrote can be addressed after merge; I'm more interested in moving things forward

dire ginkgo
#

Thanks y'all; this was significantly more involved than I expected

cedar sentinel
#

just took three lines on top of the ime changes

#

also there's some sort of bug that shifts the ime window position if you summon it when it's already active

dire ginkgo
analog moon
#

@dire ginkgo On the list of text input features: there are two items on that list (placeholder support, and mobile pop-up keyboard support) which might be better to implement at a higher level.

  • placeholder support: in CSS, placeholders can be styled differently than the regular input text - often dimmer, italicized, and so on. Having to pass in a bunch of additional style parameters to the input widget might be too much. Feathers could support placeholders directly, with theming support; the question is, do we need to support placeholders for non-feathers inputs? I don't know of too many games that use this.
  • mobile pop-up: I suspect that this is something enabled by a compile-time flag - that is, when compiling for android (or in the future, xbox or ps), the entire editable text machinery will be swapped out, won't even be included in the binary. Instead, it will be replaced by some simple text display widget which, when clicked, will pull up the os keyboard.
#

Form submission handling is another one. So long as the ENTER key is allowed to propagate (which it is), it can be handled at a higher level.

dire ginkgo
#

Mhmm

cedar sentinel
#

There's also completion suggestion text which would need lower level support

#

But that's low priority for now

analog moon
#

For the mobile pop-up work, what we could do right now is build a simple read-only replacement for EditableText to run on console / mobile platforms, and then later work out how to invoke the popup keyboard on click.

#

Hmmm, maybe not, I need to think about this

cedar sentinel
#

There's also previous entry history that's not too difficult using a drop down menu or something

#

Needed for file dialogs and things

analog moon
#

Actually, what we really want for mobile is a way to embed the platform's native input widget. The native input has features that would be hard for us to replicate.

cedar sentinel
#

Yes that's true

analog moon
dire ginkgo
#

This also comes up on Steam Deck

pallid hemlock
pallid hemlock
#

And I believe Slint has selection handles working on Android

pallid hemlock
#

Also, support is better in Winit 0.31-beta

terse scarab
#

This has, so far, been a pretty straightforward migration from bevy_ui_text_input. To be expected I guess, but I'm grateful :)

cedar sentinel
#

I just have some glitches with to fix with scrolling I'm going to work on now, then the fundamentals are pretty good.

dire ginkgo
#

@analog moon @cedar sentinel @split magnet @golden cypress I think I'm finally happy with 19106 as an MVP for clipboard support

GitHub

Objective
Add a platform-agnostic interface for interacting with the clipboard.
Solution
New crate bevy_clipboard with a ClipboardPlugin that adds a Clipboard resource. The clipboard is accessed us...

#

That was rather complex; definitely not just a simple arboard wrapper to do right.

analog moon
#

Unfortunately the "lowest common denominator" is quite low.

dire ginkgo
#

We might want to consider other clipboard crates underneath this in the future, but this should be Good Enoughβ„’ for an MVP

analog moon
dire ginkgo
#

Even if we have to do weird stuff on Windows

golden cypress
split magnet
analog moon
cedar sentinel
#

I'm not sure what a text input label is either

#

umn

analog moon
#

Let's just drop it from the list then

cedar sentinel
#

Maybe it means the AccessibilityNode labels for AccessKit

analog moon
cedar sentinel
#

It must mean popover tooltips then

dire ginkgo
cedar sentinel
#

but it should say tooltip

dire ginkgo
#

Or tooltip!

dire ginkgo
#

I think I have a workable design for paste-polling BTW

analog moon
cedar sentinel
dire ginkgo
cedar sentinel
#

okay, taking a look now

dire ginkgo
#

@cedar sentinel thanks for being gracious about me just working directly on your branch; this was a really helpful workflow

cedar sentinel
#

np, I kind of hated that PR I only made it to push things along

#

the clipboard apis are so annoying

dire ginkgo
#

Yeah, both this and IME support were very much something I did out of a sense of duty and honor lol

split magnet
#

Most people don't even bother supporting it or internationalization at all, so bevy doing it puts it above just another "indie" endeavor into something a little more serious

dire ginkgo
#

nod I'll make sure to add a section to that effect

#

We're not done with text input yet, but we are trying to do it right

split magnet
#

I still have a few things I'd like to fix with it

#

Nothing that should block the 0.19 release but still things I'd expect a text input to do

dire ginkgo
#

@cedar sentinel the example used for testing has been yeet, and I've split apart the feature. I didn't realize that arboard's image functionality was broken on web, ty

cedar sentinel
#

Yeah that clipboard example I wrote was really terrible, it was only included as an "it works" sanity test, there's no need for it now with the text input widgets available for testing

cedar sentinel
#

oh so confused for a moment what was going on, I can't approve my pull request ofc hehe

pallid hemlock
#

I've been in a lot of conversations over the past N years of being involved in Rust UI where someone has said something like "Winit has poor IME support because it was primarily designed for games and games don't care about IME. So it's fun to see Bevy excited about implementing IME.

cedar sentinel
#

"excited"

pallid hemlock
#

And if I can get y'all pushing for better IME APIs in Winit that would be a big win for everyone.

analog moon
pallid hemlock
#

I would actually be quite interested to play that

analog moon
#

Like, typing tutor for emojis

pallid hemlock
#

I imagine it could be quite tricky!

#

I've found it's a difficult thing to test, because different IMEs seem to behave very differently to each other. That's partly platforms differences, but also different language IMEs on the same platform!

#

And the output usually ends up being text in a language I don't understand!

dire ginkgo
#

System clipboard support is finally in!

#

Very pleased to have both that and IME support in the initial release

#

Was not expecting that

#

Next cycle we should do a real pass on our AccessKit integration

#

There's a ton of tech debt there

cedar sentinel
#

same as with IME it needs someone who uses a screenreader to take charge of it really, I look at it sometimes and fix some issues but I'm just guessing at the intent a lot of the time

dire ginkgo
#

My hope is that we can get to "good enough to use" in order to actually attract and retain those users πŸ™‚

split magnet
#

Tomorrow if I'm not busy after work I'll try my hand at adding the ability to tell if a widget was "tabbed into"

analog moon
analog moon
cedar sentinel