Commit Graph

238 Commits

Author SHA1 Message Date
Aliaksandr Kalenik
4a1e109678 LibWeb: Fix ability to modify selection outside of inputs using keyboard
Fixes regression introduced in a8077f79cc
2024-11-01 13:11:10 -04:00
Aliaksandr Kalenik
a8077f79cc LibWeb: Separate text control input events handling from contenteditable
This input event handling change is intended to address the following
design issues:
- Having `DOM::Position` is unnecessary complexity when `Selection`
  exists because caret position could be described by the selection
  object with a collapsed state. Before this change, we had to
  synchronize those whenever one of them was modified, and there were
  already bugs caused by that, i.e., caret position was not changed when
  selection offset was modified from the JS side.
- Selection API exposes selection offset within `<textarea>` and
  `<input>`, which is not supposed to happen. These objects should
  manage their selection state by themselves and have selection offset
  even when they are not displayed.
- `EventHandler` looks only at `DOM::Text` owned by `DOM::Position`
  while doing text manipulations. It works fine for `<input>` and
  `<textarea>`, but `contenteditable` needs to consider all text
  descendant text nodes; i.e., if the cursor is moved outside of
  `DOM::Text`, we need to look for an adjacent text node to move the
  cursor there.

With this change, `EventHandler` no longer does direct manipulations on
caret position or text content, but instead delegates them to the active
`InputEventsTarget`, which could be either
`FormAssociatedTextControlElement` (for `<input>` and `<textarea>`) or
`EditingHostManager` (for `contenteditable`). The `Selection` object is
used to manage both selection and caret position for `contenteditable`,
and text control elements manage their own selection state that is not
exposed by Selection API.

This change improves text editing on Discord, as now we don't have to
refocus the `contenteditable` element after character input. The problem
was that selection manipulations from the JS side were not propagated
to `DOM::Position`.

I expect this change to make future correctness improvements for
`contenteditable` (and `designMode`) easier, as now it's decoupled from
`<input>` and `<textarea>` and separated from `EventHandler`, which is
quite a busy file.
2024-10-30 19:29:56 +01:00
Aliaksandr Kalenik
da26941b50 LibWeb: Use cached word segmenter for word selection in EventHandler 2024-10-30 19:29:56 +01:00
Aliaksandr Kalenik
648fac7215 LibWeb: Fix "input" events being dispatched twice when cancelled 2024-10-22 19:41:07 -04:00
Jelle Raaijmakers
77850b3540 LibWeb/EventHandler: Ignore repeated keyup events
Platforms such as X11 will typically send repeated keyRelease/keyup
events as a result of auto-repeating:

  * KeyPress (initial)
  * KeyRelease (repeat)
  * KeyPress (repeat)
  * KeyRelease (repeat)
  * ad infinitum

Make our EventHandler more spec-compliant by ignoring all repeated keyup
events. This fixes long-pressing the arrow keys on
https://playbiolab.com/.
2024-10-22 11:20:35 -04:00
Jelle Raaijmakers
9309cc9df3 UI+LibWeb+WebContent: Implement KeyEvent repeat property
When a platform key press or release event is repeated, we now pass
along a `repeat` flag to indicate that auto-repeating is happening. This
flag eventually ends up in `KeyboardEvent.repeat`.
2024-10-22 11:20:35 -04:00
Aliaksandr Kalenik
63f502ab0a LibWeb: Implement dispatching of "beforeinput" event 2024-10-22 08:44:51 -04:00
Aliaksandr Kalenik
0de61b0f65 LibWeb: Implement dispatching of "input" event 2024-10-22 08:44:51 -04:00
Aliaksandr Kalenik
c690fb9df3 LibWeb: Rename Layout::Node::paintable() to first_paintable()
Layout node is allowed to have multiple corresponding paintables, so
first_paintable() is more explicit name for getter that returns first
paintable.
2024-10-16 20:25:42 +02:00
Timothy Flynn
96b5646fc1 LibWeb: Properly handle when (shift+)tab wraps around the page
We have support for using (shift+)tab to move focus to the next/previous
element on the page. However, there were several ways for this to crash
as written. This updates our implementation to check if we did not find
a node to move focus to, and to reset focus to the first/last node in
the document.

This doesn't seem to work when wrapping around from the first to the
last node. A FIXME has been added for that, as this would already not
work before this patch (the main focus here is not crashing).
2024-10-10 10:41:10 +02:00
Timothy Flynn
4fcaeabe1a LibWeb+UI: Detect and handle left vs. right modifier keys
Our handling of left vs. right modifiers keys (shift, ctrl, etc.) was
largely not to spec. This patch adds explicit UIEvents::KeyCode values
for these keys, and updates the UI to match native key events to these
keys (as best as we are able).
2024-10-09 19:10:02 +02:00
Timothy Flynn
448754d95d LibWeb: Only fire keypress events if the key press produced a character
For example, pressing just the shift key should not producde a keypress
event.
2024-10-09 19:10:02 +02:00
Timothy Flynn
3925317c11 LibWeb: Fire keydown and keypress events sooner
Fire the events before handling any close requests or selection changes.
Pages must have an opportunity to cancel the events.
2024-10-09 19:10:02 +02:00
Andreas Kling
cc4b3cbacc Meta: Update my e-mail address everywhere 2024-10-04 13:19:50 +02:00
Aliaksandr Kalenik
dc1a646764 LibWeb: Remove layout node check in EventHandler::handle_keydown()
This function does not rely on having a layout node.
2024-10-04 07:07:01 +02:00
Timothy Flynn
dd5a0361f2 LibWeb: Dispatch click events using the correct button/buttons
We were generating click events always using the primary mouse button
instead of the provided button, and with the buttons field set to that
provided button.
2024-09-29 19:30:27 +02:00
Timothy Flynn
ae01904369 LibWeb: Use a named enum value to generate mousemove button events
Rather than having to know what 1 means, let's use the enum value.
2024-09-29 19:30:27 +02:00
Timothy Flynn
5d71758742 LibWeb: Move initial creation of Unicode segmenters to the Document
The expensive part of creating a segmenter is doing the locale and UCD
data lookups at creation time. Instead of doing this once per text node,
cache the segmenters on the document, and clone them as needed (cloning
is much, much cheaper).

On a profile loading Ladybird's GitHub repo, the following hot methods
changed as follows:

    ChunkIterator ctor: 6.08% -> 0.21%
    Segmenter factory:  5.86% ->    0%
    Segmenter clone:    N/A   -> 0.09%
2024-09-22 18:42:31 +02:00
Timothy Flynn
541968b30d LibWeb+LibWebView+WebContent: Return a named enum from UI event handlers
UI event handlers currently return a boolean where false means the event
was cancelled by a script on the page, or otherwise dropped. It has been
a point of confusion for some time now, as it's not particularly clear
what should be returned in some special cases, or how the UI process
should handle the response.

This adds an enumeration with a few states that indicate exactly how the
WebContent process handled the event. This should remove all ambiguity,
and let us properly handle these states going forward.

There should be no behavior change with this patch. It's meant to only
introduce the enum, not change any of our decisions based on the result.
2024-09-12 17:38:36 -04:00
Gingeh
1d9c404b8c LibWeb: Don't move focus when setting input value 2024-09-12 11:45:34 +02:00
Timothy Flynn
16d003c563 LibWeb: Allow modifying non-editable text selections with the keyboard
This permits the user to use shift and the arrow/home/end keys to mutate
the document selection. Arrow key presses on non-editable text without
the shift key held has no effect.

This behavior differs browser-to-browser. The behavior here most closely
matches Firefox, though all browsers support this to some degree.
2024-09-08 09:46:18 +02:00
Timothy Flynn
bf9d05d97a LibWeb: Re-assign cmd+arrow key events to home/end keys on macOS
In text documents, pressing the left/right arrow keys with the cmd key
pressed should be treated as home/end key presses.
2024-09-06 07:42:59 +02:00
Timothy Flynn
a0072f422a LibWeb: Support jumping across word boundaries in text nodes
This also supports holding shift to modify the selection.
2024-09-06 07:42:59 +02:00
Timothy Flynn
1240aaa294 LibWeb: Update editable node selections with arrow/home/end keys
When an editable node is focused and one of the arrow/home/end keys are
pressed while shift is held, we will now create or update the document's
selection. There is a bit of nuance to the behavior here, which matches
how the cursor behaves in other engines.

We will of course want to abstract this in the future to extend any non-
editable node text selections. This also does not implement holding ctrl
to jump by word, rather than grapheme.
2024-09-05 14:37:57 +01:00
Tim Ledbetter
a56a2faf51 LibWeb: Don't handle media player key events if any modifier is pressed 2024-09-04 09:59:40 -04:00
Tim Ledbetter
63231fd276 LibWeb: Don't propagate key events that are handled by the media player
If a key is pressed when the media player is in focus, which causes the
media player to perform some action, that key event is no longer
propagated further.
2024-09-04 09:59:40 -04:00
Timothy Flynn
8fb2cc2be1 LibWeb: Do not assume the shadow root has a host when updating selection
For example, if the shadow root was detached from the document in some
manner, its host will be null.
2024-08-31 15:51:08 +02:00
Timothy Flynn
430c9d3e3f LibWeb: Use a Unicode text segmenter to select words on double-click
We currently use a naive word segmentation, looking for ASCII spaces to
mark a word boundary. Use LibUnicode's complete implementation instead.
2024-08-31 15:51:08 +02:00
Tim Ledbetter
206262cd55 LibWeb: Subclass FormAssociatedElement text selection methods
These are only relevant to HTMLInputElement and HTMLTextArea elements.
2024-08-31 07:47:54 +02:00
Jelle Raaijmakers
badcdcacf5 LibWeb: Update input/textarea selection on document selection change
This causes UI interactions with the document selection to also update
the input and textarea DOM selection state. Note that we switch around
the order of focusing a DOM node and setting the selection, so we allow
the focus event to override whatever selection we came up with.
2024-08-27 07:11:50 -04:00
Timothy Flynn
660e846e94 Revert "LibWeb: Change where content selection via mouse is allowed"
This reverts commit 6c9adf3dbc.

This change breaks e.g. typing into the search box on google.com and
comment boxes on github.com.
2024-08-26 14:08:59 -04:00
simonkrauter
6c9adf3dbc LibWeb: Change where content selection via mouse is allowed
Previously, only DOM nodes with `is_editable()` allowed selection via
the mouse. This had the unwanted consequence, that read-only
input/textarea elements did not allow selection.

Now, `EventHandler::handle_mousedown()` asks the node's non-shadow
parent element over the new virtual method `is_child_node_selectable()`,
if selection of the node is allowed.
This method is overridden for `HTMLButtonElement` and
`HTMLInputElement`, to disallow selection of buttons and placeholders.

Fixes #579
2024-08-23 09:31:05 +01:00
simonkrauter
a2e4259099 LibWeb: Introduce variable dom_node in EventHandler::handle_mousedown
to make the code more readable
2024-08-23 09:31:05 +01:00
Timothy Flynn
099956a7cd LibWeb: Do not unconditionally prevent escape keys from being propagated
We should only block the escape key from being sent to the web page if
the CloseWatcherManager actually closed something.

We use the escape key in the Inspector to cancel editing a DOM field.
This unconditional early return broke this feature.
2024-08-20 09:29:48 +02:00
Aliaksandr Kalenik
69c6e07139 LibWeb: Move m_needs_repaint and record_display_list() in Document
Let's make document responsible for display list invalidation,
considering it already takes care of style and layout.
2024-08-19 18:57:20 +02:00
Timothy Flynn
e8a1b89447 LibWeb: Begin implementing the drag-and-drop processing model
The drag-and-drop processing model allows for users to drag around
either elements within the DOM or objects completely outside the DOM.
This drag event can either end without action (via cancellation or user
input), or in a drop event, where the dragged object is dropped onto
another element within the DOM.

The processing model is rather large. This implements enough of it to
allow the UI process to specifically handle dragging objects outside of
the DOM onto the DOM. For example, dragging an image from the OS file
manager onto a file-upload input element. This does not implement the
ability to drag DOM elements.
2024-08-19 13:29:19 +02:00
Timothy Flynn
b6c99c27af LibWeb: Move EditEventHandler's inclusion to EventHandler.cpp
We can get away with using the forward declaration of EditEventHandler
in the header file (and avoid ~1k rebuilt files when EditEventHandler is
modified).

There will be an upcoming DragAndDropEventHandler class, so this patch
just sets things up so that the edit and drag-and-drop event handlers
are stored the same way in EventHandler.
2024-08-19 13:29:19 +02:00
Aliaksandr Kalenik
dd8c693725 LibWeb: Unify scroll handling between viewport and scrollable boxes
This change causes the viewport to be treated as a "scroll frame,"
similar to how it already works for boxes with "overflow: scroll."
This means that, instead of encoding the viewport translation into a
display list, the items will be assigned the scroll frame id of the
viewport and then shifted by the scroll offset before execution. In the
future it will allow us to reuse a display list for repainting if only
scroll offset has changed.

As a side effect, it also removes the need for special handling of
"position: fixed" because compensating for the viewport offset while
painting or hit-testing is no longer necessary. Instead, anything
contained within a "position: fixed" element is simply not assigned
a scroll frame id, which means it is not shifted by the scroll offset.
2024-08-11 07:53:21 +02:00
Timothy Flynn
faebbbc281 LibWeb: Move the navigable's cursor position to be owned by the document
Navigables are re-used for navigations within the same tab. Its current
ownership of the cursor position is a bit ad-hoc, so nothing in the spec
indicates when to reset the cursor, nor do we manually do so. So when a
cursor update happens on one page, that cursor is retained on the next
page.

Instead, let's have the document own the cursor. Each navigation results
in a new document, thus we don't need to worry about resetting cursors.

This also makes many of the callsites feel nicer. We were previously
often going from the node, to the document, to the navigable, to the
cursor. This patch removes the navigable hop.
2024-08-02 18:40:39 +02:00
Timothy Flynn
40b2d24d55 LibWeb: Support ctrl/cmd-clicking a link to open it in a new tab
The spec does not define activation behavior of ctrl/cmd clicks, so we
have to go a bit ad-hoc here. When an anchor element is clicked with the
cmd (on macOS) or ctrl (on other platforms) modifier pressed, we will
skip activation of that element and pass the event on to the chrome. We
still dispatch the event to allow scripts to cancel the event.
2024-08-02 08:07:00 +02:00
Timothy Flynn
c2d5e30a35 LibWeb: Remove debug spam when clicking a link 2024-08-02 08:07:00 +02:00
Tim Ledbetter
e18501f67f LibWeb: Don't dispatch click events to disabled FormAssociatedElements
Disabled FormAssociatedElements also no longer receive focus when
clicked.
2024-07-13 09:33:16 +02:00
Alec Murphy
1759b82114 LibWeb: Scroll page and nav history with keyboard
This patch implements basic keyboard functionality for page scrolling
and history traversal.
2024-07-07 08:05:22 +02:00
Tim Ledbetter
e5d1261640 LibWeb: Don't update selection if start and end node roots differ
This allows selection to work within shadow roots and prevents the
selection being cleared if the mouse moves outside of the current
document or shadow root.
2024-07-04 14:38:56 +02:00
circl
0f7623dd83 LibWeb+UI/Qt: Display 'title' tooltips only when the mouse stops moving
Now instead of sending the position in which the user entered the
tooltip area, send just the text, and let the chrome figure out how to
display it.

In the case of Qt, wait for 600 milliseconds of no mouse movement, then
display it under the mouse cursor.
2024-07-04 14:15:51 +02:00
Tim Ledbetter
8969f2e34a LibWeb: Disallow pasting into non-editable text nodes 2024-06-23 10:31:00 +02:00
Luke Warlow
b216046234 LibWeb: Implement CloseWatcher API
This implements most of the CloseWatcher API from the html spec.

AbortSignal support is unimplemented.

Integration with dialogs and popovers is also unimplemented.
2024-06-22 17:39:53 +02:00
Tim Ledbetter
31d7fa2442 LibWeb: Fire auxclick event on middle click
Previously, no event was fired on middle click. This change also allows
the UI to open a link in a new tab on middle click.
2024-06-22 14:57:36 +02:00
circl
990cf9b4e9 LibWeb: Use viewport position for did_enter_tooltip_area
This now matches the behavior of did_request_link_context_menu and
friends. Previously the coordinates relative to the page rather than
viewport were sent to the chrome.
2024-06-11 09:51:39 +02:00
Andrew Kaster
d90a9ab70c LibWeb: Add Web::UIEvents::KeyCode and KeyModifier enums, drop Kernel
This was the last Kernel header we had. Move the definitions we need
into a UIEvents header similar to MouseButton.
2024-06-07 09:44:41 +02:00