@@ -158,37 +158,37 @@ void OutOfProcessWebView::handle_resize()
158
158
159
159
void OutOfProcessWebView::keydown_event (GUI::KeyEvent& event)
160
160
{
161
- client (). async_key_down ( event. key (), event. modifiers (), event. code_point () );
161
+ enqueue_input_event ( event);
162
162
}
163
163
164
164
void OutOfProcessWebView::keyup_event (GUI::KeyEvent& event)
165
165
{
166
- client (). async_key_up ( event. key (), event. modifiers (), event. code_point () );
166
+ enqueue_input_event ( event);
167
167
}
168
168
169
169
void OutOfProcessWebView::mousedown_event (GUI::MouseEvent& event)
170
170
{
171
- client (). async_mouse_down ( to_content_position ( event. position ()), event. button (), event. buttons (), event. modifiers () );
171
+ enqueue_input_event ( event);
172
172
}
173
173
174
174
void OutOfProcessWebView::mouseup_event (GUI::MouseEvent& event)
175
175
{
176
- client (). async_mouse_up ( to_content_position ( event. position ()), event. button (), event. buttons (), event. modifiers () );
176
+ enqueue_input_event ( event);
177
177
}
178
178
179
179
void OutOfProcessWebView::mousemove_event (GUI::MouseEvent& event)
180
180
{
181
- client (). async_mouse_move ( to_content_position ( event. position ()), event. button (), event. buttons (), event. modifiers () );
181
+ enqueue_input_event ( event);
182
182
}
183
183
184
184
void OutOfProcessWebView::mousewheel_event (GUI::MouseEvent& event)
185
185
{
186
- client (). async_mouse_wheel ( to_content_position ( event. position ()), event. button (), event. buttons (), event. modifiers (), event. wheel_delta_x (), event. wheel_delta_y () );
186
+ enqueue_input_event ( event);
187
187
}
188
188
189
189
void OutOfProcessWebView::doubleclick_event (GUI::MouseEvent& event)
190
190
{
191
- client (). async_doubleclick ( to_content_position ( event. position ()), event. button (), event. buttons (), event. modifiers () );
191
+ enqueue_input_event ( event);
192
192
}
193
193
194
194
void OutOfProcessWebView::theme_change_event (GUI::ThemeChangeEvent& event)
@@ -695,4 +695,133 @@ void OutOfProcessWebView::hide_event(GUI::HideEvent&)
695
695
set_system_visibility_state (false );
696
696
}
697
697
698
+ void OutOfProcessWebView::enqueue_input_event (InputEvent const & event)
699
+ {
700
+ m_pending_input_events.enqueue (event);
701
+ process_next_input_event ();
702
+ }
703
+
704
+ void OutOfProcessWebView::process_next_input_event ()
705
+ {
706
+ if (m_pending_input_events.is_empty ())
707
+ return ;
708
+
709
+ if (m_is_awaiting_response_for_input_event)
710
+ return ;
711
+ m_is_awaiting_response_for_input_event = true ;
712
+
713
+ // Send the next event over to the web content to be handled by JS.
714
+ // We'll later get a message to say whether JS prevented the default event behavior,
715
+ // at which point we either discard or handle that event, then try and process the next one.
716
+ auto event = m_pending_input_events.head ();
717
+ event.visit (
718
+ [this ](GUI::KeyEvent const & event) {
719
+ switch (event.type ()) {
720
+ case GUI::Event::Type::KeyDown:
721
+ client ().async_key_down (event.key (), event.modifiers (), event.code_point ());
722
+ break ;
723
+ case GUI::Event::Type::KeyUp:
724
+ client ().async_key_up (event.key (), event.modifiers (), event.code_point ());
725
+ break ;
726
+ default :
727
+ dbgln (" Unrecognized key event type in OOPWV input event queue: {}" , event.type ());
728
+ VERIFY_NOT_REACHED ();
729
+ }
730
+ },
731
+ [this ](GUI::MouseEvent const & event) {
732
+ switch (event.type ()) {
733
+ case GUI::Event::Type::MouseDown:
734
+ client ().async_mouse_down (to_content_position (event.position ()), event.button (), event.buttons (), event.modifiers ());
735
+ break ;
736
+ case GUI::Event::Type::MouseUp:
737
+ client ().async_mouse_up (to_content_position (event.position ()), event.button (), event.buttons (), event.modifiers ());
738
+ break ;
739
+ case GUI::Event::Type::MouseMove:
740
+ client ().async_mouse_move (to_content_position (event.position ()), event.button (), event.buttons (), event.modifiers ());
741
+ break ;
742
+ case GUI::Event::Type::MouseWheel:
743
+ client ().async_mouse_wheel (to_content_position (event.position ()), event.button (), event.buttons (), event.modifiers (), event.wheel_delta_x (), event.wheel_delta_y ());
744
+ break ;
745
+ case GUI::Event::Type::MouseDoubleClick:
746
+ client ().async_doubleclick (to_content_position (event.position ()), event.button (), event.buttons (), event.modifiers ());
747
+ break ;
748
+ default :
749
+ dbgln (" Unrecognized mouse event type in OOPWV input event queue: {}" , event.type ());
750
+ VERIFY_NOT_REACHED ();
751
+ }
752
+ });
753
+ }
754
+
755
+ void OutOfProcessWebView::notify_server_did_finish_handling_input_event (bool event_was_accepted)
756
+ {
757
+ VERIFY (m_is_awaiting_response_for_input_event);
758
+
759
+ auto event = m_pending_input_events.dequeue ();
760
+ m_is_awaiting_response_for_input_event = false ;
761
+
762
+ if (!event_was_accepted) {
763
+ // Here we handle events that were not consumed or cancelled by web content.
764
+ // That is, we manually implement the steps that would have happened if the original
765
+ // OutOfProcessWebView::foo_event() had called event.ignore().
766
+ //
767
+ // The first step is to give our superclass a chance to handle the event.
768
+ //
769
+ // Then, if it does not, we dispatch the event to our parent widget, but limited so
770
+ // that it will never bubble up to the Window. (Otherwise, it would then dispatch the
771
+ // event to us since we are the focused widget, and it would go round indefinitely.)
772
+ //
773
+ // Finally, any unhandled KeyDown events are propagated to trigger any Actions.
774
+ event.visit (
775
+ [this ](GUI::KeyEvent& event) {
776
+ switch (event.type ()) {
777
+ case GUI::Event::Type::KeyDown:
778
+ Super::keydown_event (event);
779
+ break ;
780
+ case GUI::Event::Type::KeyUp:
781
+ Super::keyup_event (event);
782
+ break ;
783
+ default :
784
+ dbgln (" Unhandled key event type in OOPWV input event queue: {}" , event.type ());
785
+ VERIFY_NOT_REACHED ();
786
+ }
787
+
788
+ if (!event.is_accepted ()) {
789
+ parent_widget ()->dispatch_event (event, window ());
790
+
791
+ // NOTE: If other events can ever trigger shortcuts, propagate those here.
792
+ if (!event.is_accepted () && event.type () == GUI::Event::Type::KeyDown)
793
+ window ()->propagate_shortcuts_up_to_application (event, this );
794
+ }
795
+ },
796
+ [this ](GUI::MouseEvent& event) {
797
+ switch (event.type ()) {
798
+ case GUI::Event::Type::MouseDown:
799
+ Super::mousedown_event (event);
800
+ break ;
801
+ case GUI::Event::Type::MouseUp:
802
+ Super::mouseup_event (event);
803
+ break ;
804
+ case GUI::Event::Type::MouseMove:
805
+ Super::mousemove_event (event);
806
+ break ;
807
+ case GUI::Event::Type::MouseWheel:
808
+ Super::mousewheel_event (event);
809
+ break ;
810
+ case GUI::Event::Type::MouseDoubleClick:
811
+ Super::doubleclick_event (event);
812
+ break ;
813
+ default :
814
+ dbgln (" Unhandled mouse event type in OOPWV input event queue: {}" , event.type ());
815
+ VERIFY_NOT_REACHED ();
816
+ }
817
+
818
+ if (!event.is_accepted ())
819
+ parent_widget ()->dispatch_event (event, window ());
820
+ // FIXME: Propagate event for mouse-button shortcuts once that is implemented.
821
+ });
822
+ }
823
+
824
+ process_next_input_event ();
825
+ }
826
+
698
827
}
0 commit comments