2020-06-07 14:40:38 +02:00
/*
2021-02-09 21:23:50 +01:00
* Copyright ( c ) 2020 - 2021 , Andreas Kling < kling @ serenityos . org >
2021-05-18 13:13:58 +02:00
* Copyright ( c ) 2021 , Max Wipfli < mail @ maxwipfli . ch >
2020-06-07 14:40:38 +02:00
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-06-07 14:40:38 +02:00
*/
# include <LibGUI/Event.h>
2020-12-06 19:51:55 +01:00
# include <LibWeb/DOM/Range.h>
2020-08-02 12:10:01 +02:00
# include <LibWeb/DOM/Text.h>
2021-11-18 15:01:28 +01:00
# include <LibWeb/HTML/BrowsingContext.h>
2020-07-28 17:21:23 +02:00
# include <LibWeb/HTML/HTMLAnchorElement.h>
# include <LibWeb/HTML/HTMLIFrameElement.h>
2020-10-02 19:01:51 +02:00
# include <LibWeb/HTML/HTMLImageElement.h>
2021-09-08 11:27:46 +02:00
# include <LibWeb/Layout/InitialContainingBlock.h>
2020-07-28 19:27:41 +02:00
# include <LibWeb/Page/EventHandler.h>
2021-08-24 16:28:08 +02:00
# include <LibWeb/Page/Page.h>
2022-03-10 23:13:37 +01:00
# include <LibWeb/Painting/PaintableBox.h>
2020-11-21 19:15:57 +00:00
# include <LibWeb/UIEvents/EventNames.h>
2021-09-27 23:22:21 +02:00
# include <LibWeb/UIEvents/KeyboardEvent.h>
2020-07-28 17:21:23 +02:00
# include <LibWeb/UIEvents/MouseEvent.h>
2020-06-07 14:40:38 +02:00
namespace Web {
2021-02-21 20:15:00 +00:00
static Gfx : : StandardCursor cursor_css_to_gfx ( Optional < CSS : : Cursor > cursor )
{
if ( ! cursor . has_value ( ) ) {
return Gfx : : StandardCursor : : None ;
}
switch ( cursor . value ( ) ) {
case CSS : : Cursor : : Crosshair :
case CSS : : Cursor : : Cell :
return Gfx : : StandardCursor : : Crosshair ;
case CSS : : Cursor : : Grab :
case CSS : : Cursor : : Grabbing :
return Gfx : : StandardCursor : : Drag ;
case CSS : : Cursor : : Pointer :
return Gfx : : StandardCursor : : Hand ;
case CSS : : Cursor : : Help :
return Gfx : : StandardCursor : : Help ;
case CSS : : Cursor : : None :
return Gfx : : StandardCursor : : Hidden ;
case CSS : : Cursor : : Text :
case CSS : : Cursor : : VerticalText :
return Gfx : : StandardCursor : : IBeam ;
case CSS : : Cursor : : Move :
case CSS : : Cursor : : AllScroll :
return Gfx : : StandardCursor : : Move ;
case CSS : : Cursor : : Progress :
case CSS : : Cursor : : Wait :
return Gfx : : StandardCursor : : Wait ;
case CSS : : Cursor : : ColResize :
return Gfx : : StandardCursor : : ResizeColumn ;
case CSS : : Cursor : : EResize :
case CSS : : Cursor : : WResize :
case CSS : : Cursor : : EwResize :
return Gfx : : StandardCursor : : ResizeHorizontal ;
case CSS : : Cursor : : RowResize :
return Gfx : : StandardCursor : : ResizeRow ;
case CSS : : Cursor : : NResize :
case CSS : : Cursor : : SResize :
case CSS : : Cursor : : NsResize :
return Gfx : : StandardCursor : : ResizeVertical ;
case CSS : : Cursor : : NeResize :
case CSS : : Cursor : : SwResize :
case CSS : : Cursor : : NeswResize :
return Gfx : : StandardCursor : : ResizeDiagonalBLTR ;
case CSS : : Cursor : : NwResize :
case CSS : : Cursor : : SeResize :
case CSS : : Cursor : : NwseResize :
return Gfx : : StandardCursor : : ResizeDiagonalTLBR ;
2022-09-26 17:33:35 +01:00
case CSS : : Cursor : : ZoomIn :
case CSS : : Cursor : : ZoomOut :
return Gfx : : StandardCursor : : Zoom ;
2021-02-21 20:15:00 +00:00
default :
return Gfx : : StandardCursor : : None ;
}
}
2022-04-01 20:58:27 +03:00
static Gfx : : IntPoint compute_mouse_event_offset ( Gfx : : IntPoint const & position , Layout : : Node const & layout_node )
2020-06-07 14:40:38 +02:00
{
auto top_left_of_layout_node = layout_node . box_type_agnostic_position ( ) ;
return {
position . x ( ) - static_cast < int > ( top_left_of_layout_node . x ( ) ) ,
position . y ( ) - static_cast < int > ( top_left_of_layout_node . y ( ) )
} ;
}
2022-02-06 14:41:29 +01:00
EventHandler : : EventHandler ( Badge < HTML : : BrowsingContext > , HTML : : BrowsingContext & browsing_context )
: m_browsing_context ( browsing_context )
, m_edit_event_handler ( make < EditEventHandler > ( browsing_context ) )
2020-06-07 14:40:38 +02:00
{
}
2022-03-14 13:21:51 -06:00
EventHandler : : ~ EventHandler ( ) = default ;
2020-06-07 14:40:38 +02:00
2022-04-01 20:58:27 +03:00
Layout : : InitialContainingBlock const * EventHandler : : layout_root ( ) const
2020-06-07 14:40:38 +02:00
{
2022-02-06 14:41:29 +01:00
if ( ! m_browsing_context . active_document ( ) )
2020-06-07 14:40:38 +02:00
return nullptr ;
2022-02-06 14:41:29 +01:00
return m_browsing_context . active_document ( ) - > layout_node ( ) ;
2020-06-07 14:40:38 +02:00
}
2021-09-08 11:27:46 +02:00
Layout : : InitialContainingBlock * EventHandler : : layout_root ( )
2020-06-07 14:40:38 +02:00
{
2022-02-06 14:41:29 +01:00
if ( ! m_browsing_context . active_document ( ) )
2020-06-07 14:40:38 +02:00
return nullptr ;
2022-02-06 14:41:29 +01:00
return m_browsing_context . active_document ( ) - > layout_node ( ) ;
2020-06-07 14:40:38 +02:00
}
2022-03-11 00:03:28 +01:00
Painting : : PaintableBox * EventHandler : : paint_root ( )
{
if ( ! m_browsing_context . active_document ( ) )
return nullptr ;
return const_cast < Painting : : PaintableBox * > ( m_browsing_context . active_document ( ) - > paint_box ( ) ) ;
}
Painting : : PaintableBox const * EventHandler : : paint_root ( ) const
{
if ( ! m_browsing_context . active_document ( ) )
return nullptr ;
return const_cast < Painting : : PaintableBox * > ( m_browsing_context . active_document ( ) - > paint_box ( ) ) ;
}
2022-04-01 20:58:27 +03:00
bool EventHandler : : handle_mousewheel ( Gfx : : IntPoint const & position , unsigned int buttons , unsigned int modifiers , int wheel_delta_x , int wheel_delta_y )
2021-02-22 19:45:41 +01:00
{
2022-03-16 18:50:56 +01:00
if ( m_browsing_context . active_document ( ) )
m_browsing_context . active_document ( ) - > update_layout ( ) ;
2022-03-11 00:03:28 +01:00
if ( ! paint_root ( ) )
2021-02-22 19:48:24 +01:00
return false ;
2022-01-20 22:35:01 +01:00
if ( modifiers & KeyModifier : : Mod_Shift )
swap ( wheel_delta_x , wheel_delta_y ) ;
2022-02-06 14:41:29 +01:00
// FIXME: Support wheel events in nested browsing contexts.
2021-02-22 19:48:24 +01:00
2022-03-18 01:32:50 +01:00
auto result = paint_root ( ) - > hit_test ( position . to_type < float > ( ) , Painting : : HitTestType : : Exact ) ;
2022-03-21 11:11:05 +01:00
if ( result . has_value ( ) & & result - > paintable - > handle_mousewheel ( { } , position , buttons , modifiers , wheel_delta_x , wheel_delta_y ) )
2022-03-10 22:46:35 +01:00
return true ;
2021-03-02 08:39:07 +11:00
2022-02-06 14:41:29 +01:00
if ( auto * page = m_browsing_context . page ( ) ) {
2021-12-13 23:22:28 +01:00
page - > client ( ) . page_did_request_scroll ( wheel_delta_x * 20 , wheel_delta_y * 20 ) ;
2021-02-22 19:48:24 +01:00
return true ;
}
2021-02-22 19:45:41 +01:00
return false ;
}
2022-04-01 20:58:27 +03:00
bool EventHandler : : handle_mouseup ( Gfx : : IntPoint const & position , unsigned button , unsigned modifiers )
2020-06-07 14:40:38 +02:00
{
2022-03-16 18:50:56 +01:00
if ( m_browsing_context . active_document ( ) )
m_browsing_context . active_document ( ) - > update_layout ( ) ;
2022-03-11 00:03:28 +01:00
if ( ! paint_root ( ) )
2020-06-07 14:40:38 +02:00
return false ;
2020-09-11 18:15:47 +02:00
2020-06-07 14:40:38 +02:00
bool handled_event = false ;
2022-03-14 23:05:55 +00:00
RefPtr < Painting : : Paintable > paintable ;
if ( m_mouse_event_tracking_layout_node ) {
paintable = m_mouse_event_tracking_layout_node - > paintable ( ) ;
} else {
2022-03-21 11:11:05 +01:00
if ( auto result = paint_root ( ) - > hit_test ( position . to_type < float > ( ) , Painting : : HitTestType : : Exact ) ; result . has_value ( ) )
paintable = result - > paintable ;
2022-03-14 23:05:55 +00:00
}
2020-09-11 18:15:47 +02:00
2022-03-14 23:05:55 +00:00
if ( paintable & & paintable - > wants_mouse_events ( ) ) {
if ( paintable - > handle_mouseup ( { } , position , button , modifiers ) = = Painting : : Paintable : : DispatchEventOfSameName : : No )
return false ;
2020-09-12 17:55:19 +02:00
2020-11-22 15:53:01 +01:00
// Things may have changed as a consequence of Layout::Node::handle_mouseup(). Hit test again.
2022-03-11 00:03:28 +01:00
if ( ! paint_root ( ) )
2020-09-12 17:55:19 +02:00
return true ;
2022-03-21 11:11:05 +01:00
if ( auto result = paint_root ( ) - > hit_test ( position . to_type < float > ( ) , Painting : : HitTestType : : Exact ) ; result . has_value ( ) )
paintable = result - > paintable ;
2020-09-11 18:15:47 +02:00
}
2022-03-14 23:05:55 +00:00
if ( paintable ) {
2022-08-28 13:42:07 +02:00
JS : : GCPtr < DOM : : Node > node = paintable - > mouse_event_target ( ) ;
2022-03-14 23:05:55 +00:00
if ( ! node )
2022-03-21 11:19:02 +01:00
node = paintable - > dom_node ( ) ;
2022-02-07 13:27:17 +01:00
2022-03-14 23:05:55 +00:00
if ( node ) {
if ( is < HTML : : HTMLIFrameElement > ( * node ) ) {
if ( auto * nested_browsing_context = static_cast < HTML : : HTMLIFrameElement & > ( * node ) . nested_browsing_context ( ) )
return nested_browsing_context - > event_handler ( ) . handle_mouseup ( position . translated ( compute_mouse_event_offset ( { } , paintable - > layout_node ( ) ) ) , button , modifiers ) ;
return false ;
}
2022-05-03 16:50:38 +02:00
// Search for the first parent of the hit target that's an element.
// "The click event type MUST be dispatched on the topmost event target indicated by the pointer." (https://www.w3.org/TR/uievents/#event-type-click)
// "The topmost event target MUST be the element highest in the rendering order which is capable of being an event target." (https://www.w3.org/TR/uievents/#topmost-event-target)
auto * layout_node = & paintable - > layout_node ( ) ;
while ( layout_node & & node & & ! node - > is_element ( ) & & layout_node - > parent ( ) ) {
layout_node = layout_node - > parent ( ) ;
node = layout_node - > dom_node ( ) ;
}
if ( ! node | | ! layout_node ) {
// FIXME: This is pretty ugly but we need to bail out here.
goto after_node_use ;
}
auto offset = compute_mouse_event_offset ( position , * layout_node ) ;
LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
2022-09-25 18:11:21 -06:00
node - > dispatch_event ( * UIEvents : : MouseEvent : : create_from_platform_event ( node - > realm ( ) , UIEvents : : EventNames : : mouseup , offset . x ( ) , offset . y ( ) , position . x ( ) , position . y ( ) , button ) ) ;
2022-03-14 23:05:55 +00:00
handled_event = true ;
2022-04-08 21:48:00 -03:00
bool run_activation_behavior = true ;
if ( node . ptr ( ) = = m_mousedown_target & & button = = GUI : : MouseButton : : Primary ) {
LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
2022-09-25 18:11:21 -06:00
run_activation_behavior = node - > dispatch_event ( * UIEvents : : MouseEvent : : create_from_platform_event ( node - > realm ( ) , UIEvents : : EventNames : : click , offset . x ( ) , offset . y ( ) , position . x ( ) , position . y ( ) , button ) ) ;
2022-04-08 21:48:00 -03:00
}
if ( run_activation_behavior ) {
// FIXME: This is ad-hoc and incorrect. The reason this exists is
// because we are missing browsing context navigation:
//
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate
//
// Additionally, we currently cannot spawn a new top-level
// browsing context for new tab operations, because the new
// top-level browsing context would be in another process. To
// fix this, there needs to be some way to be able to
// communicate with browsing contexts in remote WebContent
// processes, and then step 8 of this algorithm needs to be
// implemented in BrowsingContext::choose_a_browsing_context:
//
// https://html.spec.whatwg.org/multipage/browsers.html#the-rules-for-choosing-a-browsing-context-given-a-browsing-context-name
2022-08-28 13:42:07 +02:00
if ( JS : : GCPtr < HTML : : HTMLAnchorElement > link = node - > enclosing_link_element ( ) ) {
JS : : NonnullGCPtr < DOM : : Document > document = * m_browsing_context . active_document ( ) ;
2022-04-08 21:48:00 -03:00
auto href = link - > href ( ) ;
auto url = document - > parse_url ( href ) ;
dbgln ( " Web::EventHandler: Clicking on a link to {} " , url ) ;
if ( button = = GUI : : MouseButton : : Primary ) {
2022-07-11 17:32:29 +00:00
if ( href . starts_with ( " javascript: " sv ) ) {
2022-04-08 21:48:00 -03:00
document - > run_javascript ( href . substring_view ( 11 , href . length ( ) - 11 ) ) ;
} else if ( ! url . fragment ( ) . is_null ( ) & & url . equals ( document - > url ( ) , AK : : URL : : ExcludeFragment : : Yes ) ) {
m_browsing_context . scroll_to_anchor ( url . fragment ( ) ) ;
} else {
if ( m_browsing_context . is_top_level ( ) ) {
if ( auto * page = m_browsing_context . page ( ) )
page - > client ( ) . page_did_click_link ( url , link - > target ( ) , modifiers ) ;
}
2022-03-15 14:37:58 +00:00
}
2022-04-08 21:48:00 -03:00
} else if ( button = = GUI : : MouseButton : : Middle ) {
if ( auto * page = m_browsing_context . page ( ) )
page - > client ( ) . page_did_middle_click_link ( url , link - > target ( ) , modifiers ) ;
} else if ( button = = GUI : : MouseButton : : Secondary ) {
if ( auto * page = m_browsing_context . page ( ) )
page - > client ( ) . page_did_request_link_context_menu ( m_browsing_context . to_top_level_position ( position ) , url , link - > target ( ) , modifiers ) ;
2022-03-15 14:37:58 +00:00
}
2022-03-30 18:38:52 +00:00
} else if ( button = = GUI : : MouseButton : : Secondary ) {
2022-04-08 21:48:00 -03:00
if ( is < HTML : : HTMLImageElement > ( * node ) ) {
auto & image_element = verify_cast < HTML : : HTMLImageElement > ( * node ) ;
auto image_url = image_element . document ( ) . parse_url ( image_element . src ( ) ) ;
if ( auto * page = m_browsing_context . page ( ) )
page - > client ( ) . page_did_request_image_context_menu ( m_browsing_context . to_top_level_position ( position ) , image_url , " " , modifiers , image_element . bitmap ( ) ) ;
} else if ( auto * page = m_browsing_context . page ( ) ) {
page - > client ( ) . page_did_request_context_menu ( m_browsing_context . to_top_level_position ( position ) ) ;
}
2022-04-07 22:43:30 +01:00
}
2022-03-15 14:37:58 +00:00
}
2022-02-07 13:27:17 +01:00
}
2020-06-07 14:40:38 +02:00
}
2022-05-03 16:50:38 +02:00
after_node_use :
2021-10-27 13:20:27 +02:00
if ( button = = GUI : : MouseButton : : Primary )
2020-06-07 14:40:38 +02:00
m_in_mouse_selection = false ;
return handled_event ;
}
2022-04-01 20:58:27 +03:00
bool EventHandler : : handle_mousedown ( Gfx : : IntPoint const & position , unsigned button , unsigned modifiers )
2020-06-07 14:40:38 +02:00
{
2022-03-16 18:50:56 +01:00
if ( m_browsing_context . active_document ( ) )
m_browsing_context . active_document ( ) - > update_layout ( ) ;
2022-03-11 00:03:28 +01:00
if ( ! paint_root ( ) )
2020-06-07 14:40:38 +02:00
return false ;
2020-09-11 18:15:47 +02:00
2022-08-28 13:42:07 +02:00
JS : : NonnullGCPtr < DOM : : Document > document = * m_browsing_context . active_document ( ) ;
JS : : GCPtr < DOM : : Node > node ;
2020-06-07 14:40:38 +02:00
2020-11-29 16:39:56 +01:00
{
2021-10-19 12:53:22 +02:00
// TODO: Allow selecting element behind if one on top has pointer-events set to none.
2022-03-14 23:05:55 +00:00
RefPtr < Painting : : Paintable > paintable ;
if ( m_mouse_event_tracking_layout_node ) {
paintable = m_mouse_event_tracking_layout_node - > paintable ( ) ;
} else {
2022-03-18 01:32:50 +01:00
auto result = paint_root ( ) - > hit_test ( position . to_type < float > ( ) , Painting : : HitTestType : : Exact ) ;
2022-03-21 11:11:05 +01:00
if ( ! result . has_value ( ) )
2022-03-14 23:05:55 +00:00
return false ;
2022-03-21 11:11:05 +01:00
paintable = result - > paintable ;
2022-03-14 23:05:55 +00:00
}
2020-06-07 14:40:38 +02:00
2022-03-14 23:05:55 +00:00
auto pointer_events = paintable - > computed_values ( ) . pointer_events ( ) ;
2022-02-07 17:19:33 +00:00
// FIXME: Handle other values for pointer-events.
2021-10-19 12:53:22 +02:00
if ( pointer_events = = CSS : : PointerEvents : : None )
return false ;
2022-03-14 23:05:55 +00:00
node = paintable - > mouse_event_target ( ) ;
if ( ! node )
2022-03-21 11:19:02 +01:00
node = paintable - > dom_node ( ) ;
2020-11-29 16:39:56 +01:00
document - > set_hovered_node ( node ) ;
2020-09-12 17:55:19 +02:00
2022-03-14 23:05:55 +00:00
if ( paintable - > wants_mouse_events ( ) ) {
if ( paintable - > handle_mousedown ( { } , position , button , modifiers ) = = Painting : : Paintable : : DispatchEventOfSameName : : No )
return false ;
2020-11-29 16:39:56 +01:00
}
2020-09-11 18:15:47 +02:00
2020-11-29 16:39:56 +01:00
if ( ! node )
return false ;
2020-06-07 14:40:38 +02:00
2020-11-29 16:39:56 +01:00
if ( is < HTML : : HTMLIFrameElement > ( * node ) ) {
2022-02-06 14:41:29 +01:00
if ( auto * nested_browsing_context = static_cast < HTML : : HTMLIFrameElement & > ( * node ) . nested_browsing_context ( ) )
2022-03-14 23:05:55 +00:00
return nested_browsing_context - > event_handler ( ) . handle_mousedown ( position . translated ( compute_mouse_event_offset ( { } , paintable - > layout_node ( ) ) ) , button , modifiers ) ;
2020-11-29 16:39:56 +01:00
return false ;
}
2020-06-07 14:40:38 +02:00
2022-02-06 14:41:29 +01:00
if ( auto * page = m_browsing_context . page ( ) )
page - > set_focused_browsing_context ( { } , m_browsing_context ) ;
2020-08-14 11:33:20 +02:00
2022-05-03 16:50:38 +02:00
// Search for the first parent of the hit target that's an element.
// "The click event type MUST be dispatched on the topmost event target indicated by the pointer." (https://www.w3.org/TR/uievents/#event-type-click)
// "The topmost event target MUST be the element highest in the rendering order which is capable of being an event target." (https://www.w3.org/TR/uievents/#topmost-event-target)
auto * layout_node = & paintable - > layout_node ( ) ;
while ( layout_node & & node & & ! node - > is_element ( ) & & layout_node - > parent ( ) ) {
layout_node = layout_node - > parent ( ) ;
node = layout_node - > dom_node ( ) ;
}
if ( ! node | | ! layout_node )
return false ;
2022-08-28 13:42:07 +02:00
m_mousedown_target = node . ptr ( ) ;
2022-05-03 16:50:38 +02:00
auto offset = compute_mouse_event_offset ( position , * layout_node ) ;
LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
2022-09-25 18:11:21 -06:00
node - > dispatch_event ( * UIEvents : : MouseEvent : : create_from_platform_event ( node - > realm ( ) , UIEvents : : EventNames : : mousedown , offset . x ( ) , offset . y ( ) , position . x ( ) , position . y ( ) , button ) ) ;
2020-11-29 16:39:56 +01:00
}
// NOTE: Dispatching an event may have disturbed the world.
2022-03-11 00:03:28 +01:00
if ( ! paint_root ( ) | | paint_root ( ) ! = node - > document ( ) . paint_box ( ) )
2020-07-10 23:43:25 +02:00
return true ;
2022-03-15 14:37:58 +00:00
if ( button = = GUI : : MouseButton : : Primary ) {
if ( auto result = paint_root ( ) - > hit_test ( position . to_type < float > ( ) , Painting : : HitTestType : : TextCursor ) ; result . has_value ( ) ) {
auto paintable = result - > paintable ;
if ( paintable - > dom_node ( ) ) {
2022-02-06 19:28:09 +01:00
// See if we want to focus something.
bool did_focus_something = false ;
for ( auto candidate = node ; candidate ; candidate = candidate - > parent ( ) ) {
if ( candidate - > is_focusable ( ) ) {
document - > set_focused_element ( verify_cast < DOM : : Element > ( candidate . ptr ( ) ) ) ;
did_focus_something = true ;
break ;
}
}
// If we didn't focus anything, place the document text cursor at the mouse position.
// FIXME: This is all rather strange. Find a better solution.
if ( ! did_focus_something ) {
2022-03-15 14:37:58 +00:00
m_browsing_context . set_cursor_position ( DOM : : Position ( * paintable - > dom_node ( ) , result - > index_in_node ) ) ;
layout_root ( ) - > set_selection ( { { paintable - > layout_node ( ) , result - > index_in_node } , { } } ) ;
2022-02-06 19:28:09 +01:00
m_in_mouse_selection = true ;
}
2020-08-05 16:55:56 +02:00
}
2020-06-27 14:21:58 -06:00
}
2020-06-07 14:40:38 +02:00
}
return true ;
}
2022-04-01 20:58:27 +03:00
bool EventHandler : : handle_mousemove ( Gfx : : IntPoint const & position , unsigned buttons , unsigned modifiers )
2020-06-07 14:40:38 +02:00
{
2022-03-16 18:50:56 +01:00
if ( m_browsing_context . active_document ( ) )
m_browsing_context . active_document ( ) - > update_layout ( ) ;
2022-03-11 00:03:28 +01:00
if ( ! paint_root ( ) )
2020-06-07 14:40:38 +02:00
return false ;
2020-09-11 18:15:47 +02:00
2022-02-06 14:41:29 +01:00
auto & document = * m_browsing_context . active_document ( ) ;
2020-06-07 14:40:38 +02:00
bool hovered_node_changed = false ;
bool is_hovering_link = false ;
2021-02-21 20:15:00 +00:00
Gfx : : StandardCursor hovered_node_cursor = Gfx : : StandardCursor : : None ;
2022-03-14 23:05:55 +00:00
RefPtr < Painting : : Paintable > paintable ;
Optional < int > start_index ;
if ( m_mouse_event_tracking_layout_node ) {
paintable = m_mouse_event_tracking_layout_node - > paintable ( ) ;
} else {
2022-03-21 11:11:05 +01:00
if ( auto result = paint_root ( ) - > hit_test ( position . to_type < float > ( ) , Painting : : HitTestType : : Exact ) ; result . has_value ( ) ) {
paintable = result - > paintable ;
start_index = result - > index_in_node ;
}
2022-03-14 23:05:55 +00:00
}
2020-07-28 18:20:36 +02:00
const HTML : : HTMLAnchorElement * hovered_link_element = nullptr ;
2022-03-14 23:05:55 +00:00
if ( paintable ) {
if ( paintable - > wants_mouse_events ( ) ) {
2022-03-21 11:19:02 +01:00
document . set_hovered_node ( paintable - > dom_node ( ) ) ;
2022-03-14 23:05:55 +00:00
if ( paintable - > handle_mousemove ( { } , position , buttons , modifiers ) = = Painting : : Paintable : : DispatchEventOfSameName : : No )
return false ;
2020-09-11 18:15:47 +02:00
// FIXME: It feels a bit aggressive to always update the cursor like this.
2022-02-06 14:41:29 +01:00
if ( auto * page = m_browsing_context . page ( ) )
2020-11-12 18:23:05 +01:00
page - > client ( ) . page_did_request_cursor_change ( Gfx : : StandardCursor : : None ) ;
2020-09-11 18:15:47 +02:00
}
2022-08-28 13:42:07 +02:00
JS : : GCPtr < DOM : : Node > node = paintable - > mouse_event_target ( ) ;
2022-03-14 23:05:55 +00:00
if ( ! node )
2022-03-21 11:19:02 +01:00
node = paintable - > dom_node ( ) ;
2020-06-07 14:40:38 +02:00
2020-07-28 18:20:36 +02:00
if ( node & & is < HTML : : HTMLIFrameElement > ( * node ) ) {
2022-02-06 14:41:29 +01:00
if ( auto * nested_browsing_context = static_cast < HTML : : HTMLIFrameElement & > ( * node ) . nested_browsing_context ( ) )
2022-03-14 23:05:55 +00:00
return nested_browsing_context - > event_handler ( ) . handle_mousemove ( position . translated ( compute_mouse_event_offset ( { } , paintable - > layout_node ( ) ) ) , buttons , modifiers ) ;
2020-06-07 14:40:38 +02:00
return false ;
}
2022-03-14 23:05:55 +00:00
auto pointer_events = paintable - > computed_values ( ) . pointer_events ( ) ;
2022-02-07 17:19:33 +00:00
// FIXME: Handle other values for pointer-events.
2021-10-05 19:47:13 +01:00
if ( pointer_events = = CSS : : PointerEvents : : None )
return false ;
2022-08-28 13:42:07 +02:00
hovered_node_changed = node . ptr ( ) ! = document . hovered_node ( ) ;
2020-06-07 14:40:38 +02:00
document . set_hovered_node ( node ) ;
if ( node ) {
hovered_link_element = node - > enclosing_link_element ( ) ;
2020-11-19 22:21:16 +01:00
if ( hovered_link_element )
2020-06-07 14:40:38 +02:00
is_hovering_link = true ;
2021-02-21 20:15:00 +00:00
2021-10-05 19:47:13 +01:00
if ( node - > is_text ( ) ) {
2022-03-14 23:05:55 +00:00
auto cursor = paintable - > computed_values ( ) . cursor ( ) ;
2021-10-05 19:47:13 +01:00
if ( cursor = = CSS : : Cursor : : Auto )
hovered_node_cursor = Gfx : : StandardCursor : : IBeam ;
else
2022-02-15 21:48:48 -05:00
hovered_node_cursor = cursor_css_to_gfx ( cursor ) ;
} else if ( node - > is_element ( ) ) {
2022-03-14 23:05:55 +00:00
auto cursor = paintable - > computed_values ( ) . cursor ( ) ;
2022-02-15 21:48:48 -05:00
if ( cursor = = CSS : : Cursor : : Auto )
hovered_node_cursor = Gfx : : StandardCursor : : Arrow ;
else
2021-10-05 19:47:13 +01:00
hovered_node_cursor = cursor_css_to_gfx ( cursor ) ;
}
2021-02-21 20:15:00 +00:00
2022-05-03 16:50:38 +02:00
// Search for the first parent of the hit target that's an element.
// "The click event type MUST be dispatched on the topmost event target indicated by the pointer." (https://www.w3.org/TR/uievents/#event-type-click)
// "The topmost event target MUST be the element highest in the rendering order which is capable of being an event target." (https://www.w3.org/TR/uievents/#topmost-event-target)
auto * layout_node = & paintable - > layout_node ( ) ;
while ( layout_node & & node & & ! node - > is_element ( ) & & layout_node - > parent ( ) ) {
layout_node = layout_node - > parent ( ) ;
node = layout_node - > dom_node ( ) ;
}
if ( ! node | | ! layout_node ) {
// FIXME: This is pretty ugly but we need to bail out here.
goto after_node_use ;
}
auto offset = compute_mouse_event_offset ( position , * layout_node ) ;
LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
2022-09-25 18:11:21 -06:00
node - > dispatch_event ( * UIEvents : : MouseEvent : : create_from_platform_event ( node - > realm ( ) , UIEvents : : EventNames : : mousemove , offset . x ( ) , offset . y ( ) , position . x ( ) , position . y ( ) ) ) ;
2020-11-29 16:39:56 +01:00
// NOTE: Dispatching an event may have disturbed the world.
2022-03-11 00:03:28 +01:00
if ( ! paint_root ( ) | | paint_root ( ) ! = node - > document ( ) . paint_box ( ) )
2020-07-10 23:43:25 +02:00
return true ;
2020-06-07 14:40:38 +02:00
}
2022-05-03 16:50:38 +02:00
after_node_use :
2020-06-07 14:40:38 +02:00
if ( m_in_mouse_selection ) {
2022-03-18 01:32:50 +01:00
auto hit = paint_root ( ) - > hit_test ( position . to_type < float > ( ) , Painting : : HitTestType : : TextCursor ) ;
2022-03-21 11:16:02 +01:00
if ( start_index . has_value ( ) & & hit . has_value ( ) & & hit - > dom_node ( ) ) {
m_browsing_context . set_cursor_position ( DOM : : Position ( * hit - > dom_node ( ) , * start_index ) ) ;
2022-03-21 11:11:05 +01:00
layout_root ( ) - > set_selection_end ( { hit - > paintable - > layout_node ( ) , hit - > index_in_node } ) ;
2022-09-16 00:34:43 +02:00
m_browsing_context . set_needs_display ( ) ;
2020-08-05 16:55:56 +02:00
}
2022-02-06 14:41:29 +01:00
if ( auto * page = m_browsing_context . page ( ) )
2020-11-12 18:23:05 +01:00
page - > client ( ) . page_did_change_selection ( ) ;
2020-06-07 14:40:38 +02:00
}
}
2020-08-17 12:54:41 +02:00
2022-02-06 14:41:29 +01:00
if ( auto * page = m_browsing_context . page ( ) ) {
2021-02-21 20:15:00 +00:00
page - > client ( ) . page_did_request_cursor_change ( hovered_node_cursor ) ;
2020-11-12 18:23:05 +01:00
if ( hovered_node_changed ) {
2022-08-28 13:42:07 +02:00
JS : : GCPtr < HTML : : HTMLElement > hovered_html_element = document . hovered_node ( ) ? document . hovered_node ( ) - > enclosing_html_element_with_attribute ( HTML : : AttributeNames : : title ) : nullptr ;
2020-11-12 18:23:05 +01:00
if ( hovered_html_element & & ! hovered_html_element - > title ( ) . is_null ( ) ) {
2022-02-06 14:41:29 +01:00
page - > client ( ) . page_did_enter_tooltip_area ( m_browsing_context . to_top_level_position ( position ) , hovered_html_element - > title ( ) ) ;
2020-11-12 18:23:05 +01:00
} else {
page - > client ( ) . page_did_leave_tooltip_area ( ) ;
}
if ( is_hovering_link )
2021-09-09 18:08:56 +02:00
page - > client ( ) . page_did_hover_link ( document . parse_url ( hovered_link_element - > href ( ) ) ) ;
2020-11-12 18:23:05 +01:00
else
page - > client ( ) . page_did_unhover_link ( ) ;
}
2020-06-07 14:40:38 +02:00
}
return true ;
}
2022-06-14 19:38:00 +02:00
bool EventHandler : : handle_doubleclick ( Gfx : : IntPoint const & position , unsigned button , unsigned modifiers )
{
if ( m_browsing_context . active_document ( ) )
m_browsing_context . active_document ( ) - > update_layout ( ) ;
if ( ! paint_root ( ) )
return false ;
// TODO: Allow selecting element behind if one on top has pointer-events set to none.
RefPtr < Painting : : Paintable > paintable ;
if ( m_mouse_event_tracking_layout_node ) {
paintable = m_mouse_event_tracking_layout_node - > paintable ( ) ;
} else {
auto result = paint_root ( ) - > hit_test ( position . to_type < float > ( ) , Painting : : HitTestType : : Exact ) ;
if ( ! result . has_value ( ) )
return false ;
paintable = result - > paintable ;
}
auto pointer_events = paintable - > computed_values ( ) . pointer_events ( ) ;
// FIXME: Handle other values for pointer-events.
if ( pointer_events = = CSS : : PointerEvents : : None )
return false ;
2022-08-28 13:42:07 +02:00
JS : : GCPtr < DOM : : Node > node = paintable - > mouse_event_target ( ) ;
2022-06-14 19:38:00 +02:00
if ( ! node )
node = paintable - > dom_node ( ) ;
if ( paintable - > wants_mouse_events ( ) ) {
// FIXME: Handle double clicks.
}
if ( ! node )
return false ;
if ( is < HTML : : HTMLIFrameElement > ( * node ) ) {
if ( auto * nested_browsing_context = static_cast < HTML : : HTMLIFrameElement & > ( * node ) . nested_browsing_context ( ) )
return nested_browsing_context - > event_handler ( ) . handle_doubleclick ( position . translated ( compute_mouse_event_offset ( { } , paintable - > layout_node ( ) ) ) , button , modifiers ) ;
return false ;
}
// Search for the first parent of the hit target that's an element.
// "The topmost event target MUST be the element highest in the rendering order which is capable of being an event target." (https://www.w3.org/TR/uievents/#topmost-event-target)
auto * layout_node = & paintable - > layout_node ( ) ;
while ( layout_node & & node & & ! node - > is_element ( ) & & layout_node - > parent ( ) ) {
layout_node = layout_node - > parent ( ) ;
node = layout_node - > dom_node ( ) ;
}
if ( ! node | | ! layout_node )
return false ;
2022-06-14 19:39:33 +02:00
auto offset = compute_mouse_event_offset ( position , * layout_node ) ;
LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
2022-09-25 18:11:21 -06:00
node - > dispatch_event ( * UIEvents : : MouseEvent : : create_from_platform_event ( node - > realm ( ) , UIEvents : : EventNames : : dblclick , offset . x ( ) , offset . y ( ) , position . x ( ) , position . y ( ) , button ) ) ;
2022-06-14 19:38:00 +02:00
2022-06-14 21:57:29 +02:00
// NOTE: Dispatching an event may have disturbed the world.
if ( ! paint_root ( ) | | paint_root ( ) ! = node - > document ( ) . paint_box ( ) )
return true ;
if ( button = = GUI : : MouseButton : : Primary ) {
if ( auto result = paint_root ( ) - > hit_test ( position . to_type < float > ( ) , Painting : : HitTestType : : TextCursor ) ; result . has_value ( ) ) {
auto paintable = result - > paintable ;
if ( ! paintable - > dom_node ( ) )
return true ;
auto const & layout_node = paintable - > layout_node ( ) ;
if ( ! layout_node . is_text_node ( ) )
return true ;
auto const & text_for_rendering = verify_cast < Layout : : TextNode > ( layout_node ) . text_for_rendering ( ) ;
int first_word_break_before = [ & ] {
// Start from one before the index position to prevent selecting only spaces between words, caused by the addition below.
// This also helps us dealing with cases where index is equal to the string length.
for ( int i = result - > index_in_node - 1 ; i > = 0 ; - - i ) {
if ( is_ascii_space ( text_for_rendering [ i ] ) ) {
// Don't include the space in the selection
return i + 1 ;
}
}
return 0 ;
} ( ) ;
int first_word_break_after = [ & ] {
for ( size_t i = result - > index_in_node ; i < text_for_rendering . length ( ) ; + + i ) {
if ( is_ascii_space ( text_for_rendering [ i ] ) )
return i ;
}
return text_for_rendering . length ( ) ;
} ( ) ;
m_browsing_context . set_cursor_position ( DOM : : Position ( * paintable - > dom_node ( ) , first_word_break_after ) ) ;
layout_root ( ) - > set_selection ( { { paintable - > layout_node ( ) , first_word_break_before } , { paintable - > layout_node ( ) , first_word_break_after } } ) ;
}
}
2022-06-14 19:38:00 +02:00
return true ;
}
2020-08-14 19:40:37 +02:00
bool EventHandler : : focus_next_element ( )
2020-08-02 12:10:01 +02:00
{
2022-02-06 14:41:29 +01:00
if ( ! m_browsing_context . active_document ( ) )
2020-08-14 19:40:37 +02:00
return false ;
2022-02-06 14:41:29 +01:00
auto * element = m_browsing_context . active_document ( ) - > focused_element ( ) ;
2020-08-14 19:40:37 +02:00
if ( ! element ) {
2022-02-06 14:41:29 +01:00
element = m_browsing_context . active_document ( ) - > first_child_of_type < DOM : : Element > ( ) ;
2020-08-14 19:40:37 +02:00
if ( element & & element - > is_focusable ( ) ) {
2022-02-06 14:41:29 +01:00
m_browsing_context . active_document ( ) - > set_focused_element ( element ) ;
2020-08-14 19:40:37 +02:00
return true ;
}
}
for ( element = element - > next_element_in_pre_order ( ) ; element & & ! element - > is_focusable ( ) ; element = element - > next_element_in_pre_order ( ) )
;
2022-02-06 14:41:29 +01:00
m_browsing_context . active_document ( ) - > set_focused_element ( element ) ;
2020-08-14 19:40:37 +02:00
return element ;
}
bool EventHandler : : focus_previous_element ( )
{
2022-02-08 21:23:43 +01:00
if ( ! m_browsing_context . active_document ( ) )
return false ;
auto * element = m_browsing_context . active_document ( ) - > focused_element ( ) ;
if ( ! element ) {
element = m_browsing_context . active_document ( ) - > last_child_of_type < DOM : : Element > ( ) ;
if ( element & & element - > is_focusable ( ) ) {
m_browsing_context . active_document ( ) - > set_focused_element ( element ) ;
return true ;
}
}
for ( element = element - > previous_element_in_pre_order ( ) ; element & & ! element - > is_focusable ( ) ; element = element - > previous_element_in_pre_order ( ) )
;
m_browsing_context . active_document ( ) - > set_focused_element ( element ) ;
return element ;
2020-08-14 19:40:37 +02:00
}
2021-06-01 10:01:11 +02:00
constexpr bool should_ignore_keydown_event ( u32 code_point )
2021-05-18 13:13:58 +02:00
{
2021-06-01 10:01:11 +02:00
// FIXME: There are probably also keys with non-zero code points that should be filtered out.
2022-02-19 22:22:45 +01:00
return code_point = = 0 | | code_point = = 27 ;
2021-05-18 13:13:58 +02:00
}
2020-08-14 19:40:37 +02:00
bool EventHandler : : handle_keydown ( KeyCode key , unsigned modifiers , u32 code_point )
{
2022-02-06 14:41:29 +01:00
if ( ! m_browsing_context . active_document ( ) )
2021-10-12 14:44:00 +02:00
return false ;
2022-08-28 13:42:07 +02:00
JS : : NonnullGCPtr < DOM : : Document > document = * m_browsing_context . active_document ( ) ;
2021-10-12 14:44:00 +02:00
if ( ! document - > layout_node ( ) )
return false ;
NonnullRefPtr < Layout : : InitialContainingBlock > layout_root = * document - > layout_node ( ) ;
2020-08-14 19:40:37 +02:00
if ( key = = KeyCode : : Key_Tab ) {
if ( modifiers & KeyModifier : : Mod_Shift )
return focus_previous_element ( ) ;
2021-10-12 14:44:52 +02:00
return focus_next_element ( ) ;
2020-08-14 19:40:37 +02:00
}
2021-10-12 14:44:00 +02:00
if ( layout_root - > selection ( ) . is_valid ( ) ) {
auto range = layout_root - > selection ( ) . to_dom_range ( ) - > normalized ( ) ;
2020-12-14 10:58:10 +01:00
if ( range - > start_container ( ) - > is_editable ( ) ) {
2021-10-12 14:44:00 +02:00
layout_root - > set_selection ( { } ) ;
2020-12-01 23:36:12 +01:00
2020-12-14 10:58:10 +01:00
// FIXME: This doesn't work for some reason?
2022-02-06 14:41:29 +01:00
m_browsing_context . set_cursor_position ( { * range - > start_container ( ) , range - > start_offset ( ) } ) ;
2020-12-03 18:20:17 +01:00
2020-12-14 10:58:10 +01:00
if ( key = = KeyCode : : Key_Backspace | | key = = KeyCode : : Key_Delete ) {
2022-08-09 01:06:47 +02:00
m_edit_event_handler - > handle_delete ( * range ) ;
2020-12-01 23:36:12 +01:00
return true ;
2021-10-12 14:44:52 +02:00
}
if ( ! should_ignore_keydown_event ( code_point ) ) {
2022-08-09 01:06:47 +02:00
m_edit_event_handler - > handle_delete ( * range ) ;
2022-02-06 14:41:29 +01:00
m_edit_event_handler - > handle_insert ( m_browsing_context . cursor_position ( ) , code_point ) ;
m_browsing_context . increment_cursor_position_offset ( ) ;
2020-12-14 10:58:10 +01:00
return true ;
}
2020-12-01 23:36:12 +01:00
}
}
2022-02-06 14:41:29 +01:00
if ( m_browsing_context . cursor_position ( ) . is_valid ( ) & & m_browsing_context . cursor_position ( ) . node ( ) - > is_editable ( ) ) {
2020-12-01 23:35:47 +01:00
if ( key = = KeyCode : : Key_Backspace ) {
2022-02-06 14:41:29 +01:00
if ( ! m_browsing_context . decrement_cursor_position_offset ( ) ) {
2021-05-18 13:08:25 +02:00
// FIXME: Move to the previous node and delete the last character there.
return true ;
}
2020-12-02 15:00:55 +01:00
2022-02-06 14:41:29 +01:00
m_edit_event_handler - > handle_delete_character_after ( m_browsing_context . cursor_position ( ) ) ;
2020-12-02 15:00:55 +01:00
return true ;
2021-10-12 14:44:52 +02:00
}
if ( key = = KeyCode : : Key_Delete ) {
2022-02-06 14:41:29 +01:00
if ( m_browsing_context . cursor_position ( ) . offset_is_at_end_of_node ( ) ) {
2021-05-18 13:08:25 +02:00
// FIXME: Move to the next node and delete the first character there.
return true ;
}
2022-02-06 14:41:29 +01:00
m_edit_event_handler - > handle_delete_character_after ( m_browsing_context . cursor_position ( ) ) ;
2020-12-02 15:00:55 +01:00
return true ;
2021-10-12 14:44:52 +02:00
}
if ( key = = KeyCode : : Key_Right ) {
2022-02-06 14:41:29 +01:00
if ( ! m_browsing_context . increment_cursor_position_offset ( ) ) {
2021-05-18 13:08:25 +02:00
// FIXME: Move to the next node.
}
2020-12-02 15:00:55 +01:00
return true ;
2021-10-12 14:44:52 +02:00
}
if ( key = = KeyCode : : Key_Left ) {
2022-02-06 14:41:29 +01:00
if ( ! m_browsing_context . decrement_cursor_position_offset ( ) ) {
2021-05-18 13:08:25 +02:00
// FIXME: Move to the previous node.
}
2020-08-02 16:05:59 +02:00
return true ;
2021-10-12 14:44:52 +02:00
}
2022-02-19 18:39:19 +01:00
if ( key = = KeyCode : : Key_Home ) {
auto & node = * static_cast < DOM : : Text * > ( const_cast < DOM : : Node * > ( m_browsing_context . cursor_position ( ) . node ( ) ) ) ;
m_browsing_context . set_cursor_position ( DOM : : Position { node , 0 } ) ;
return true ;
}
2022-02-19 18:42:08 +01:00
if ( key = = KeyCode : : Key_End ) {
auto & node = * static_cast < DOM : : Text * > ( const_cast < DOM : : Node * > ( m_browsing_context . cursor_position ( ) . node ( ) ) ) ;
m_browsing_context . set_cursor_position ( DOM : : Position { node , ( unsigned ) node . data ( ) . length ( ) } ) ;
return true ;
}
2021-10-12 14:44:52 +02:00
if ( ! should_ignore_keydown_event ( code_point ) ) {
2022-02-06 14:41:29 +01:00
m_edit_event_handler - > handle_insert ( m_browsing_context . cursor_position ( ) , code_point ) ;
m_browsing_context . increment_cursor_position_offset ( ) ;
2021-05-18 13:13:58 +02:00
return true ;
2020-08-02 16:05:59 +02:00
}
2021-10-12 14:44:52 +02:00
// NOTE: Because modifier keys should be ignored, we need to return true.
return true ;
2020-08-02 12:10:01 +02:00
}
2020-12-01 23:35:47 +01:00
LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
2022-09-25 18:11:21 -06:00
auto event = UIEvents : : KeyboardEvent : : create_from_platform_event ( document - > realm ( ) , UIEvents : : EventNames : : keydown , key , modifiers , code_point ) ;
2021-10-12 14:44:00 +02:00
2022-08-28 13:42:07 +02:00
if ( JS : : GCPtr < DOM : : Element > focused_element = document - > focused_element ( ) )
2022-08-08 22:29:40 +02:00
return focused_element - > dispatch_event ( * event ) ;
2021-10-12 14:44:00 +02:00
2022-08-28 13:42:07 +02:00
if ( JS : : GCPtr < HTML : : HTMLElement > body = m_browsing_context . active_document ( ) - > body ( ) )
2022-08-08 22:29:40 +02:00
return body - > dispatch_event ( * event ) ;
2021-10-12 14:44:00 +02:00
2022-08-08 22:29:40 +02:00
return document - > root ( ) . dispatch_event ( * event ) ;
2020-08-02 12:10:01 +02:00
}
2021-09-28 15:39:35 +02:00
bool EventHandler : : handle_keyup ( KeyCode key , unsigned modifiers , u32 code_point )
{
2022-08-28 13:42:07 +02:00
JS : : GCPtr < DOM : : Document > document = m_browsing_context . active_document ( ) ;
2021-10-12 14:38:31 +02:00
if ( ! document )
return false ;
LibWeb: Remove unecessary dependence on Window from assorted classes
These classes only needed Window to get at its realm. Pass a realm
directly to construct Crypto, Encoding, HRT, IntersectionObserver,
NavigationTiming, Page, RequestIdleCallback, Selection, Streams, URL,
and XML classes.
2022-09-25 18:11:21 -06:00
auto event = UIEvents : : KeyboardEvent : : create_from_platform_event ( document - > realm ( ) , UIEvents : : EventNames : : keyup , key , modifiers , code_point ) ;
2021-10-12 14:38:31 +02:00
2022-08-28 13:42:07 +02:00
if ( JS : : GCPtr < DOM : : Element > focused_element = document - > focused_element ( ) )
2022-08-08 22:29:40 +02:00
return document - > focused_element ( ) - > dispatch_event ( * event ) ;
2021-10-12 14:38:31 +02:00
2022-08-28 13:42:07 +02:00
if ( JS : : GCPtr < HTML : : HTMLElement > body = document - > body ( ) )
2022-08-08 22:29:40 +02:00
return body - > dispatch_event ( * event ) ;
2021-10-12 14:38:31 +02:00
2022-08-08 22:29:40 +02:00
return document - > root ( ) . dispatch_event ( * event ) ;
2021-09-28 15:39:35 +02:00
}
2020-11-22 15:53:01 +01:00
void EventHandler : : set_mouse_event_tracking_layout_node ( Layout : : Node * layout_node )
2020-09-11 18:15:47 +02:00
{
2022-07-04 00:42:44 +02:00
m_mouse_event_tracking_layout_node = layout_node ;
2020-09-11 18:15:47 +02:00
}
2020-12-03 18:46:56 +01:00
2020-06-07 14:40:38 +02:00
}