summaryrefslogtreecommitdiff
path: root/chromium/ui
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-09-03 13:32:17 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-10-01 14:31:55 +0200
commit21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (patch)
tree91be119f694044dfc1ff9fdc054459e925de9df0 /chromium/ui
parent03c549e0392f92c02536d3f86d5e1d8dfa3435ac (diff)
downloadqtwebengine-chromium-21ba0c5d4bf8fba15dddd97cd693bad2358b77fd.tar.gz
BASELINE: Update Chromium to 92.0.4515.166
Change-Id: I42a050486714e9e54fc271f2a8939223a02ae364
Diffstat (limited to 'chromium/ui')
-rw-r--r--chromium/ui/OWNERS2
-rw-r--r--chromium/ui/accelerated_widget_mac/accelerated_widget_mac.h1
-rw-r--r--chromium/ui/accelerated_widget_mac/ca_layer_frame_sink.h1
-rw-r--r--chromium/ui/accelerated_widget_mac/ca_layer_tree_coordinator.h6
-rw-r--r--chromium/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm5
-rw-r--r--chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.h87
-rw-r--r--chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm554
-rw-r--r--chromium/ui/accelerated_widget_mac/ca_transaction_observer.mm4
-rw-r--r--chromium/ui/accelerated_widget_mac/io_surface_context.h2
-rw-r--r--chromium/ui/accessibility/BUILD.gn4
-rw-r--r--chromium/ui/accessibility/PRESUBMIT.py3
-rw-r--r--chromium/ui/accessibility/accessibility_features.cc27
-rw-r--r--chromium/ui/accessibility/accessibility_features.h26
-rw-r--r--chromium/ui/accessibility/accessibility_switches.cc11
-rw-r--r--chromium/ui/accessibility/accessibility_switches.h4
-rw-r--r--chromium/ui/accessibility/ax_action_data.h2
-rw-r--r--chromium/ui/accessibility/ax_active_popup.cc10
-rw-r--r--chromium/ui/accessibility/ax_active_popup.h6
-rw-r--r--chromium/ui/accessibility/ax_assistant_structure.cc69
-rw-r--r--chromium/ui/accessibility/ax_assistant_structure.h11
-rw-r--r--chromium/ui/accessibility/ax_enum_util.cc28
-rw-r--r--chromium/ui/accessibility/ax_enums.mojom243
-rw-r--r--chromium/ui/accessibility/ax_event_generator.cc8
-rw-r--r--chromium/ui/accessibility/ax_event_generator.h2
-rw-r--r--chromium/ui/accessibility/ax_event_generator_unittest.cc5
-rw-r--r--chromium/ui/accessibility/ax_hypertext.cc14
-rw-r--r--chromium/ui/accessibility/ax_hypertext.h50
-rw-r--r--chromium/ui/accessibility/ax_node.cc212
-rw-r--r--chromium/ui/accessibility/ax_node.h99
-rw-r--r--chromium/ui/accessibility/ax_node_data.cc53
-rw-r--r--chromium/ui/accessibility/ax_node_data.h21
-rw-r--r--chromium/ui/accessibility/ax_node_position.cc14
-rw-r--r--chromium/ui/accessibility/ax_node_position_perftest.cc2
-rw-r--r--chromium/ui/accessibility/ax_node_position_unittest.cc186
-rw-r--r--chromium/ui/accessibility/ax_node_unittest.cc2
-rw-r--r--chromium/ui/accessibility/ax_position.h62
-rw-r--r--chromium/ui/accessibility/ax_range.h7
-rw-r--r--chromium/ui/accessibility/ax_range_unittest.cc52
-rw-r--r--chromium/ui/accessibility/ax_relative_bounds.h2
-rw-r--r--chromium/ui/accessibility/ax_role_properties.cc150
-rw-r--r--chromium/ui/accessibility/ax_role_properties.h27
-rw-r--r--chromium/ui/accessibility/ax_table_fuzzer.cc2
-rw-r--r--chromium/ui/accessibility/ax_table_info.h2
-rw-r--r--chromium/ui/accessibility/ax_table_info_unittest.cc2
-rw-r--r--chromium/ui/accessibility/ax_text_utils.cc2
-rw-r--r--chromium/ui/accessibility/ax_text_utils_unittest.cc17
-rw-r--r--chromium/ui/accessibility/ax_tree.cc123
-rw-r--r--chromium/ui/accessibility/ax_tree.h14
-rw-r--r--chromium/ui/accessibility/ax_tree_data.cc1
-rw-r--r--chromium/ui/accessibility/ax_tree_data.h2
-rw-r--r--chromium/ui/accessibility/ax_tree_id.cc2
-rw-r--r--chromium/ui/accessibility/ax_tree_id.h4
-rw-r--r--chromium/ui/accessibility/ax_tree_serializer.h57
-rw-r--r--chromium/ui/accessibility/ax_tree_serializer_unittest.cc66
-rw-r--r--chromium/ui/accessibility/ax_tree_unittest.cc28
-rw-r--r--chromium/ui/accessibility/ax_tree_update.h1
-rw-r--r--chromium/ui/accessibility/extensions/chromevoxclassic/BUILD.gn2
-rw-r--r--chromium/ui/accessibility/mojom/BUILD.gn63
-rw-r--r--chromium/ui/accessibility/mojom/ax_action_data.mojom2
-rw-r--r--chromium/ui/accessibility/mojom/ax_assistant_structure_mojom_traits.h4
-rw-r--r--chromium/ui/accessibility/mojom/ax_tree_id.mojom2
-rw-r--r--chromium/ui/accessibility/platform/BUILD.gn3
-rw-r--r--chromium/ui/accessibility/platform/atk_util_auralinux_unittest.cc12
-rw-r--r--chromium/ui/accessibility/platform/ax_android_constants.h1
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_atk_hyperlink.cc4
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node.cc13
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node.h19
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc149
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_auralinux.h26
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc236
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_base.cc225
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_base.h84
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_base_unittest.cc26
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_delegate.h55
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_delegate_base.cc91
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_delegate_base.h43
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_mac.mm37
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_textchildprovider_win_unittest.cc1
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_textprovider_win.h1
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc52
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h2
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc356
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_unittest.cc10
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_unittest.h2
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_win.cc437
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_win.h64
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc410
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_win_unittest.h3
-rw-r--r--chromium/ui/accessibility/platform/compute_attributes.cc30
-rw-r--r--chromium/ui/accessibility/platform/compute_attributes.h4
-rw-r--r--chromium/ui/accessibility/platform/inspect/ax_inspect.h4
-rw-r--r--chromium/ui/accessibility/platform/inspect/ax_inspect_scenario.cc23
-rw-r--r--chromium/ui/accessibility/platform/inspect/ax_inspect_scenario_unittest.cc84
-rw-r--r--chromium/ui/accessibility/platform/inspect/ax_inspect_utils.cc98
-rw-r--r--chromium/ui/accessibility/platform/inspect/ax_inspect_utils.h45
-rw-r--r--chromium/ui/accessibility/platform/inspect/ax_inspect_utils_unittest.cc65
-rw-r--r--chromium/ui/accessibility/platform/inspect/ax_inspect_utils_win.cc1
-rw-r--r--chromium/ui/accessibility/platform/inspect/ax_property_node.cc14
-rw-r--r--chromium/ui/accessibility/platform/inspect/ax_property_node.h12
-rw-r--r--chromium/ui/accessibility/platform/inspect/ax_property_node_unittest.cc7
-rw-r--r--chromium/ui/accessibility/platform/inspect/ax_tree_formatter_base.cc30
-rw-r--r--chromium/ui/accessibility/platform/inspect/ax_tree_formatter_base.h3
-rw-r--r--chromium/ui/accessibility/platform/inspect/ax_tree_indexer.h86
-rw-r--r--chromium/ui/accessibility/platform/test_ax_node_wrapper.cc74
-rw-r--r--chromium/ui/accessibility/platform/test_ax_node_wrapper.h39
-rw-r--r--chromium/ui/android/BUILD.gn1
-rw-r--r--chromium/ui/android/DIR_METADATA3
-rw-r--r--chromium/ui/android/color_helpers.cc8
-rw-r--r--chromium/ui/android/color_helpers.h8
-rw-r--r--chromium/ui/android/color_helpers_unittest.cc4
-rw-r--r--chromium/ui/android/delegated_frame_host_android.cc2
-rw-r--r--chromium/ui/android/dummy_screen_android.h6
-rw-r--r--chromium/ui/android/edge_effect.h1
-rw-r--r--chromium/ui/android/junit/src/org/chromium/ui/base/DIR_METADATA11
-rw-r--r--chromium/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java66
-rw-r--r--chromium/ui/android/junit/src/org/chromium/ui/modaldialog/DIR_METADATA1
-rw-r--r--chromium/ui/android/resources/resource_manager.h4
-rw-r--r--chromium/ui/android/resources/resource_manager_impl.h2
-rw-r--r--chromium/ui/android/view_android.cc12
-rw-r--r--chromium/ui/android/view_android.h7
-rw-r--r--chromium/ui/aura/BUILD.gn1
-rw-r--r--chromium/ui/aura/client/aura_constants.cc1
-rw-r--r--chromium/ui/aura/client/aura_constants.h4
-rw-r--r--chromium/ui/aura/client/cursor_client.h1
-rw-r--r--chromium/ui/aura/client/drag_drop_client.h13
-rw-r--r--chromium/ui/aura/client/drag_drop_delegate.h15
-rw-r--r--chromium/ui/aura/client/screen_position_client.h6
-rw-r--r--chromium/ui/aura/client/window_stacking_client.h1
-rw-r--r--chromium/ui/aura/demo/demo_main.cc10
-rw-r--r--chromium/ui/aura/env.cc20
-rw-r--r--chromium/ui/aura/env.h1
-rw-r--r--chromium/ui/aura/gestures/gesture_recognizer_unittest.cc7
-rw-r--r--chromium/ui/aura/native_window_occlusion_tracker_win.cc4
-rw-r--r--chromium/ui/aura/native_window_occlusion_tracker_win.h3
-rw-r--r--chromium/ui/aura/scoped_simple_keyboard_hook.cc2
-rw-r--r--chromium/ui/aura/scoped_simple_keyboard_hook.h6
-rw-r--r--chromium/ui/aura/window.cc257
-rw-r--r--chromium/ui/aura/window.h79
-rw-r--r--chromium/ui/aura/window_event_dispatcher.cc2
-rw-r--r--chromium/ui/aura/window_event_dispatcher_unittest.cc37
-rw-r--r--chromium/ui/aura/window_observer.h1
-rw-r--r--chromium/ui/aura/window_occlusion_tracker.cc9
-rw-r--r--chromium/ui/aura/window_occlusion_tracker.h2
-rw-r--r--chromium/ui/aura/window_occlusion_tracker_unittest.cc3
-rw-r--r--chromium/ui/aura/window_targeter.cc1
-rw-r--r--chromium/ui/aura/window_targeter_unittest.cc3
-rw-r--r--chromium/ui/aura/window_tree_host.cc2
-rw-r--r--chromium/ui/aura/window_tree_host.h6
-rw-r--r--chromium/ui/aura/window_tree_host_platform.cc5
-rw-r--r--chromium/ui/aura/window_tree_host_platform.h2
-rw-r--r--chromium/ui/aura/window_unittest.cc188
-rw-r--r--chromium/ui/aura_extra/aura_extra_export.h6
-rw-r--r--chromium/ui/aura_extra/window_occlusion_win.h2
-rw-r--r--chromium/ui/base/BUILD.gn49
-rw-r--r--chromium/ui/base/DEPS1
-rw-r--r--chromium/ui/base/accelerators/OWNERS1
-rw-r--r--chromium/ui/base/accelerators/accelerator.cc29
-rw-r--r--chromium/ui/base/accelerators/accelerator.h34
-rw-r--r--chromium/ui/base/accelerators/accelerator_manager.cc41
-rw-r--r--chromium/ui/base/accelerators/accelerator_manager.h17
-rw-r--r--chromium/ui/base/accelerators/accelerator_manager_unittest.cc142
-rw-r--r--chromium/ui/base/accelerators/accelerator_map.h191
-rw-r--r--chromium/ui/base/accelerators/accelerator_map_unittest.cc235
-rw-r--r--chromium/ui/base/accelerators/accelerator_unittest.cc33
-rw-r--r--chromium/ui/base/class_property.h4
-rw-r--r--chromium/ui/base/clipboard/BUILD.gn9
-rw-r--r--chromium/ui/base/clipboard/clipboard.cc33
-rw-r--r--chromium/ui/base/clipboard/clipboard.h7
-rw-r--r--chromium/ui/base/clipboard/clipboard_android.cc16
-rw-r--r--chromium/ui/base/clipboard/clipboard_android.h3
-rw-r--r--chromium/ui/base/clipboard/clipboard_constants.cc2
-rw-r--r--chromium/ui/base/clipboard/clipboard_constants.h3
-rw-r--r--chromium/ui/base/clipboard/clipboard_data.cc21
-rw-r--r--chromium/ui/base/clipboard/clipboard_data.h15
-rw-r--r--chromium/ui/base/clipboard/clipboard_data_endpoint.cc4
-rw-r--r--chromium/ui/base/clipboard/clipboard_data_unittest.cc14
-rw-r--r--chromium/ui/base/clipboard/clipboard_format_type.h2
-rw-r--r--chromium/ui/base/clipboard/clipboard_format_type_android.cc7
-rw-r--r--chromium/ui/base/clipboard/clipboard_format_type_aura.cc7
-rw-r--r--chromium/ui/base/clipboard/clipboard_format_type_mac.mm6
-rw-r--r--chromium/ui/base/clipboard/clipboard_format_type_win.cc9
-rw-r--r--chromium/ui/base/clipboard/clipboard_mac.h3
-rw-r--r--chromium/ui/base/clipboard/clipboard_mac.mm10
-rw-r--r--chromium/ui/base/clipboard/clipboard_metrics.h7
-rw-r--r--chromium/ui/base/clipboard/clipboard_monitor.cc1
-rw-r--r--chromium/ui/base/clipboard/clipboard_non_backed.cc17
-rw-r--r--chromium/ui/base/clipboard/clipboard_non_backed.h5
-rw-r--r--chromium/ui/base/clipboard/clipboard_ozone.cc75
-rw-r--r--chromium/ui/base/clipboard/clipboard_ozone.h3
-rw-r--r--chromium/ui/base/clipboard/clipboard_test_template.h33
-rw-r--r--chromium/ui/base/clipboard/clipboard_win.cc95
-rw-r--r--chromium/ui/base/clipboard/clipboard_win.h9
-rw-r--r--chromium/ui/base/clipboard/clipboard_x11.cc10
-rw-r--r--chromium/ui/base/clipboard/clipboard_x11.h3
-rw-r--r--chromium/ui/base/clipboard/custom_data_helper.h2
-rw-r--r--chromium/ui/base/clipboard/file_info_unittest.cc4
-rw-r--r--chromium/ui/base/clipboard/scoped_clipboard_writer.h2
-rw-r--r--chromium/ui/base/cocoa/DIR_METADATA11
-rw-r--r--chromium/ui/base/cocoa/animation_utils.h6
-rw-r--r--chromium/ui/base/cocoa/appkit_utils.h6
-rw-r--r--chromium/ui/base/cocoa/defaults_utils.h2
-rw-r--r--chromium/ui/base/cocoa/focus_window_set.h33
-rw-r--r--chromium/ui/base/cocoa/focus_window_set.mm92
-rw-r--r--chromium/ui/base/cocoa/menu_controller.h1
-rw-r--r--chromium/ui/base/cocoa/secure_password_input.mm2
-rw-r--r--chromium/ui/base/cocoa/touch_bar_util.h6
-rw-r--r--chromium/ui/base/cursor/BUILD.gn5
-rw-r--r--chromium/ui/base/cursor/cursor.cc48
-rw-r--r--chromium/ui/base/cursor/cursor.h28
-rw-r--r--chromium/ui/base/cursor/cursor_aura.cc21
-rw-r--r--chromium/ui/base/cursor/cursor_factory.cc41
-rw-r--r--chromium/ui/base/cursor/cursor_factory.h62
-rw-r--r--chromium/ui/base/cursor/cursor_loader.cc22
-rw-r--r--chromium/ui/base/cursor/cursor_loader.h18
-rw-r--r--chromium/ui/base/cursor/cursor_loader_unittest.cc25
-rw-r--r--chromium/ui/base/cursor/cursors_aura.cc4
-rw-r--r--chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc46
-rw-r--r--chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h36
-rw-r--r--chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone_unittest.cc18
-rw-r--r--chromium/ui/base/cursor/platform_cursor.h36
-rw-r--r--chromium/ui/base/cursor/win/win_cursor.cc16
-rw-r--r--chromium/ui/base/cursor/win/win_cursor.h20
-rw-r--r--chromium/ui/base/cursor/win/win_cursor_factory.cc38
-rw-r--r--chromium/ui/base/cursor/win/win_cursor_factory.h12
-rw-r--r--chromium/ui/base/data_transfer_policy/OWNERS2
-rw-r--r--chromium/ui/base/data_transfer_policy/data_transfer_endpoint.cc4
-rw-r--r--chromium/ui/base/data_transfer_policy/data_transfer_endpoint.h4
-rw-r--r--chromium/ui/base/dragdrop/BUILD.gn5
-rw-r--r--chromium/ui/base/dragdrop/cocoa_dnd_util.h6
-rw-r--r--chromium/ui/base/dragdrop/drag_drop_types.cc10
-rw-r--r--chromium/ui/base/dragdrop/drag_drop_types.h4
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data.cc8
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data.h5
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed_unittest.cc22
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_provider_win.h1
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_provider_x11_unittest.cc128
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_unittest.cc8
-rw-r--r--chromium/ui/base/glib/glib_cast.h3
-rw-r--r--chromium/ui/base/glib/glib_signal.h2
-rw-r--r--chromium/ui/base/idle/BUILD.gn8
-rw-r--r--chromium/ui/base/idle/DEPS1
-rw-r--r--chromium/ui/base/idle/idle_internal.cc4
-rw-r--r--chromium/ui/base/idle/idle_internal.h4
-rw-r--r--chromium/ui/base/idle/idle_linux.cc152
-rw-r--r--chromium/ui/base/idle/idle_stub.cc21
-rw-r--r--chromium/ui/base/idle/scoped_set_idle_state.h4
-rw-r--r--chromium/ui/base/ime/BUILD.gn2
-rw-r--r--chromium/ui/base/ime/OWNERS2
-rw-r--r--chromium/ui/base/ime/chromeos/BUILD.gn17
-rw-r--r--chromium/ui/base/ime/dummy_text_input_client.cc21
-rw-r--r--chromium/ui/base/ime/dummy_text_input_client.h13
-rw-r--r--chromium/ui/base/ime/fake_text_input_client.cc14
-rw-r--r--chromium/ui/base/ime/fake_text_input_client.h7
-rw-r--r--chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc14
-rw-r--r--chromium/ui/base/ime/fuchsia/input_method_fuchsia.h4
-rw-r--r--chromium/ui/base/ime/fuchsia/keyboard_client.h1
-rw-r--r--chromium/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.cc74
-rw-r--r--chromium/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.h8
-rw-r--r--chromium/ui/base/ime/grammar_fragment.cc25
-rw-r--r--chromium/ui/base/ime/grammar_fragment.h34
-rw-r--r--chromium/ui/base/ime/ime_text_span.h2
-rw-r--r--chromium/ui/base/ime/input_method.h3
-rw-r--r--chromium/ui/base/ime/linux/BUILD.gn4
-rw-r--r--chromium/ui/base/ime/linux/input_method_auralinux.cc66
-rw-r--r--chromium/ui/base/ime/linux/input_method_auralinux.h4
-rw-r--r--chromium/ui/base/ime/linux/input_method_auralinux_unittest.cc74
-rw-r--r--chromium/ui/base/ime/mock_input_method.h1
-rw-r--r--chromium/ui/base/ime/mojom/ime_types.mojom1
-rw-r--r--chromium/ui/base/ime/mojom/ime_types_mojom_traits.cc5
-rw-r--r--chromium/ui/base/ime/mojom/text_input_state.mojom4
-rw-r--r--chromium/ui/base/ime/text_input_client.cc16
-rw-r--r--chromium/ui/base/ime/text_input_client.h27
-rw-r--r--chromium/ui/base/ime/text_input_mode.h2
-rw-r--r--chromium/ui/base/ime/utf_offset.cc12
-rw-r--r--chromium/ui/base/ime/utf_offset.h6
-rw-r--r--chromium/ui/base/ime/utf_offset_unittest.cc70
-rw-r--r--chromium/ui/base/ime/win/imm32_manager.h6
-rw-r--r--chromium/ui/base/ime/win/input_method_win_imm32.h1
-rw-r--r--chromium/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h6
-rw-r--r--chromium/ui/base/ime/win/on_screen_keyboard_display_manager_unittest.cc7
-rw-r--r--chromium/ui/base/ime/win/tsf_bridge.cc40
-rw-r--r--chromium/ui/base/ime/win/tsf_event_router.h1
-rw-r--r--chromium/ui/base/ime/win/tsf_text_store.cc21
-rw-r--r--chromium/ui/base/ime/win/tsf_text_store.h5
-rw-r--r--chromium/ui/base/ime/win/tsf_text_store_unittest.cc5
-rw-r--r--chromium/ui/base/interaction/OWNERS2
-rw-r--r--chromium/ui/base/interaction/README.md401
-rw-r--r--chromium/ui/base/interaction/element_identifier.cc21
-rw-r--r--chromium/ui/base/interaction/element_identifier.h258
-rw-r--r--chromium/ui/base/interaction/element_test_util.cc68
-rw-r--r--chromium/ui/base/interaction/element_test_util.h55
-rw-r--r--chromium/ui/base/interaction/element_tracker.cc333
-rw-r--r--chromium/ui/base/interaction/element_tracker.h235
-rw-r--r--chromium/ui/base/interaction/element_tracker_unittest.cc554
-rw-r--r--chromium/ui/base/interaction/expect_call_in_scope.h56
-rw-r--r--chromium/ui/base/interaction/interaction_sequence.cc515
-rw-r--r--chromium/ui/base/interaction/interaction_sequence.h278
-rw-r--r--chromium/ui/base/interaction/interaction_sequence_unittest.cc1402
-rw-r--r--chromium/ui/base/l10n/OWNERS2
-rw-r--r--chromium/ui/base/l10n/l10n_font_util.h6
-rw-r--r--chromium/ui/base/l10n/l10n_util.cc28
-rw-r--r--chromium/ui/base/linux/linux_ui_delegate.cc46
-rw-r--r--chromium/ui/base/linux/linux_ui_delegate.h44
-rw-r--r--chromium/ui/base/metadata/OWNERS1
-rw-r--r--chromium/ui/base/metadata/base_type_conversion.cc602
-rw-r--r--chromium/ui/base/metadata/base_type_conversion.h378
-rw-r--r--chromium/ui/base/metadata/base_type_conversion_unittest.cc258
-rw-r--r--chromium/ui/base/metadata/metadata_cache.cc (renamed from chromium/ui/views/metadata/metadata_cache.cc)8
-rw-r--r--chromium/ui/base/metadata/metadata_cache.h (renamed from chromium/ui/views/metadata/metadata_cache.h)19
-rw-r--r--chromium/ui/base/metadata/metadata_header_macros.h (renamed from chromium/ui/views/metadata/metadata_header_macros.h)8
-rw-r--r--chromium/ui/base/metadata/metadata_impl_macros.h (renamed from chromium/ui/views/metadata/metadata_impl_macros.h)12
-rw-r--r--chromium/ui/base/metadata/metadata_macros_internal.h (renamed from chromium/ui/views/metadata/metadata_macros_internal.h)89
-rw-r--r--chromium/ui/base/metadata/metadata_types.cc (renamed from chromium/ui/views/metadata/metadata_types.cc)45
-rw-r--r--chromium/ui/base/metadata/metadata_types.h (renamed from chromium/ui/views/metadata/metadata_types.h)68
-rw-r--r--chromium/ui/base/metadata/metadata_unittest.cc (renamed from chromium/ui/views/metadata/metadata_unittest.cc)128
-rw-r--r--chromium/ui/base/metadata/property_metadata.h (renamed from chromium/ui/views/metadata/property_metadata.h)76
-rw-r--r--chromium/ui/base/models/dialog_model.h14
-rw-r--r--chromium/ui/base/models/image_model.cc39
-rw-r--r--chromium/ui/base/models/image_model.h27
-rw-r--r--chromium/ui/base/models/image_model_unittest.cc25
-rw-r--r--chromium/ui/base/models/menu_model.cc4
-rw-r--r--chromium/ui/base/models/menu_model.h5
-rw-r--r--chromium/ui/base/models/simple_combobox_model.cc39
-rw-r--r--chromium/ui/base/models/simple_combobox_model.h30
-rw-r--r--chromium/ui/base/models/simple_combobox_model_unittest.cc43
-rw-r--r--chromium/ui/base/models/simple_menu_model.cc9
-rw-r--r--chromium/ui/base/models/simple_menu_model.h5
-rw-r--r--chromium/ui/base/models/simple_menu_model_unittest.cc19
-rw-r--r--chromium/ui/base/mojom/ui_base_types.mojom1
-rw-r--r--chromium/ui/base/prediction/empty_predictor.cc2
-rw-r--r--chromium/ui/base/prediction/empty_predictor.h4
-rw-r--r--chromium/ui/base/prediction/linear_resampling.cc1
-rw-r--r--chromium/ui/base/prediction/prediction_metrics_handler.cc4
-rw-r--r--chromium/ui/base/prediction/prediction_metrics_handler.h10
-rw-r--r--chromium/ui/base/resource/OWNERS2
-rw-r--r--chromium/ui/base/resource/allowlist.h2
-rw-r--r--chromium/ui/base/resource/data_pack_unittest.cc4
-rw-r--r--chromium/ui/base/resource/mock_resource_bundle_delegate.h2
-rw-r--r--chromium/ui/base/resource/resource_bundle.cc13
-rw-r--r--chromium/ui/base/resource/resource_bundle.h8
-rw-r--r--chromium/ui/base/resource/resource_bundle_win.h6
-rw-r--r--chromium/ui/base/scoped_visibility_tracker.h1
-rw-r--r--chromium/ui/base/template_expressions.cc18
-rw-r--r--chromium/ui/base/ui_base_features.cc32
-rw-r--r--chromium/ui/base/ui_base_features.h19
-rw-r--r--chromium/ui/base/webui/jstemplate_builder.cc23
-rw-r--r--chromium/ui/base/win/session_change_observer.cc1
-rw-r--r--chromium/ui/base/x/BUILD.gn18
-rw-r--r--chromium/ui/base/x/visual_picker_glx.cc (renamed from chromium/ui/gl/gl_visual_picker_glx.cc)89
-rw-r--r--chromium/ui/base/x/visual_picker_glx.h (renamed from chromium/ui/gl/gl_visual_picker_glx.h)35
-rw-r--r--chromium/ui/base/x/x11_cursor.cc7
-rw-r--r--chromium/ui/base/x/x11_cursor.h19
-rw-r--r--chromium/ui/base/x/x11_cursor_factory.cc51
-rw-r--r--chromium/ui/base/x/x11_cursor_factory.h23
-rw-r--r--chromium/ui/base/x/x11_cursor_factory_unittest.cc22
-rw-r--r--chromium/ui/base/x/x11_drag_drop_client.cc82
-rw-r--r--chromium/ui/base/x/x11_drag_drop_client.h25
-rw-r--r--chromium/ui/base/x/x11_gl_egl_utility.cc24
-rw-r--r--chromium/ui/base/x/x11_gl_egl_utility.h7
-rw-r--r--chromium/ui/base/x/x11_keyboard_hook.cc122
-rw-r--r--chromium/ui/base/x/x11_keyboard_hook.h53
-rw-r--r--chromium/ui/base/x/x11_screensaver.cc99
-rw-r--r--chromium/ui/base/x/x11_screensaver.h16
-rw-r--r--chromium/ui/base/x/x11_screensaver_window_finder.cc86
-rw-r--r--chromium/ui/base/x/x11_screensaver_window_finder.h34
-rw-r--r--chromium/ui/base/x/x11_util.cc200
-rw-r--r--chromium/ui/base/x/x11_util.h61
-rw-r--r--chromium/ui/base/x/x11_whole_screen_move_loop.h2
-rw-r--r--chromium/ui/chromeos/events/BUILD.gn1
-rw-r--r--chromium/ui/color/DIR_METADATA3
-rw-r--r--chromium/ui/color/color_id.h17
-rw-r--r--chromium/ui/color/color_provider_manager.cc21
-rw-r--r--chromium/ui/color/color_provider_manager.h5
-rw-r--r--chromium/ui/color/color_provider_manager_unittest.cc5
-rw-r--r--chromium/ui/color/color_transform.cc14
-rw-r--r--chromium/ui/color/color_transform.h6
-rw-r--r--chromium/ui/color/mac/scoped_current_nsappearance.h2
-rw-r--r--chromium/ui/color/ui_color_mixer.cc14
-rw-r--r--chromium/ui/compositor/BUILD.gn1
-rw-r--r--chromium/ui/compositor/animation_throughput_reporter.cc6
-rw-r--r--chromium/ui/compositor/compositor.cc54
-rw-r--r--chromium/ui/compositor/compositor.h27
-rw-r--r--chromium/ui/compositor/compositor_unittest.cc44
-rw-r--r--chromium/ui/compositor/layer.cc92
-rw-r--r--chromium/ui/compositor/layer.h50
-rw-r--r--chromium/ui/compositor/layer_animation_delegate.h6
-rw-r--r--chromium/ui/compositor/layer_animator.h2
-rw-r--r--chromium/ui/compositor/layer_owner.cc7
-rw-r--r--chromium/ui/compositor/layer_owner.h3
-rw-r--r--chromium/ui/compositor/layer_unittest.cc54
-rw-r--r--chromium/ui/compositor/overscroll/scroll_input_handler.h2
-rw-r--r--chromium/ui/compositor/paint_cache.h2
-rw-r--r--chromium/ui/compositor/paint_context.h1
-rw-r--r--chromium/ui/compositor/paint_recorder.h1
-rw-r--r--chromium/ui/compositor/scoped_animation_duration_scale_mode.h2
-rw-r--r--chromium/ui/compositor/throughput_tracker.cc6
-rw-r--r--chromium/ui/compositor/throughput_tracker.h9
-rw-r--r--chromium/ui/compositor/throughput_tracker_host.h5
-rw-r--r--chromium/ui/compositor/total_animation_throughput_reporter.h6
-rw-r--r--chromium/ui/content_accelerators/accelerator_util.cc9
-rw-r--r--chromium/ui/display/BUILD.gn2
-rw-r--r--chromium/ui/display/display.h4
-rw-r--r--chromium/ui/display/display_change_notifier.cc7
-rw-r--r--chromium/ui/display/display_layout.cc1
-rw-r--r--chromium/ui/display/display_list.cc160
-rw-r--r--chromium/ui/display/display_list.h72
-rw-r--r--chromium/ui/display/display_list_unittest.cc140
-rw-r--r--chromium/ui/display/display_observer.cc2
-rw-r--r--chromium/ui/display/display_observer.h7
-rw-r--r--chromium/ui/display/fake/fake_display_delegate.cc1
-rw-r--r--chromium/ui/display/fake/fake_display_snapshot.cc3
-rw-r--r--chromium/ui/display/mac/display_link_mac.h1
-rw-r--r--chromium/ui/display/mac/screen_mac.mm14
-rw-r--r--chromium/ui/display/manager/content_protection_manager.cc4
-rw-r--r--chromium/ui/display/manager/content_protection_manager.h4
-rw-r--r--chromium/ui/display/manager/display_change_observer.cc3
-rw-r--r--chromium/ui/display/manager/display_change_observer.h2
-rw-r--r--chromium/ui/display/manager/display_change_observer_unittest.cc39
-rw-r--r--chromium/ui/display/manager/display_configurator.h8
-rw-r--r--chromium/ui/display/manager/display_manager.cc30
-rw-r--r--chromium/ui/display/manager/display_manager.h12
-rw-r--r--chromium/ui/display/manager/display_util.cc1
-rw-r--r--chromium/ui/display/manager/display_util.h2
-rw-r--r--chromium/ui/display/manager/json_converter.cc180
-rw-r--r--chromium/ui/display/manager/query_content_protection_task_unittest.cc4
-rw-r--r--chromium/ui/display/manager/update_display_configuration_task.cc6
-rw-r--r--chromium/ui/display/manager/update_display_configuration_task.h4
-rw-r--r--chromium/ui/display/mojom/BUILD.gn12
-rw-r--r--chromium/ui/display/mojom/display_configuration_params_mojom_traits.cc2
-rw-r--r--chromium/ui/display/mojom/display_configuration_params_mojom_traits.h2
-rw-r--r--chromium/ui/display/mojom/display_layout_mojom_traits.h2
-rw-r--r--chromium/ui/display/mojom/display_list.mojom20
-rw-r--r--chromium/ui/display/mojom/display_list_mojom_traits.cc21
-rw-r--r--chromium/ui/display/mojom/display_list_mojom_traits.h41
-rw-r--r--chromium/ui/display/mojom/display_list_mojom_traits_unittest.cc101
-rw-r--r--chromium/ui/display/mojom/display_snapshot_mojom_traits.h1
-rw-r--r--chromium/ui/display/screen.cc42
-rw-r--r--chromium/ui/display/screen.h14
-rw-r--r--chromium/ui/display/screen_unittest.cc12
-rw-r--r--chromium/ui/display/types/display_configuration_params.h4
-rw-r--r--chromium/ui/display/types/display_constants.h54
-rw-r--r--chromium/ui/display/types/display_types_export.h6
-rw-r--r--chromium/ui/display/util/edid_parser.cc14
-rw-r--r--chromium/ui/display/util/edid_parser.h27
-rw-r--r--chromium/ui/display/util/edid_parser_unittest.cc43
-rw-r--r--chromium/ui/display/win/screen_win.cc30
-rw-r--r--chromium/ui/events/BUILD.gn165
-rw-r--r--chromium/ui/events/DEPS3
-rw-r--r--chromium/ui/events/OWNERS2
-rw-r--r--chromium/ui/events/android/drag_event_android.cc9
-rw-r--r--chromium/ui/events/android/event_handler_android.cc2
-rw-r--r--chromium/ui/events/android/event_handler_android.h4
-rw-r--r--chromium/ui/events/android/gesture_event_android.cc6
-rw-r--r--chromium/ui/events/android/gesture_event_type.h6
-rw-r--r--chromium/ui/events/android/key_event_utils.h2
-rw-r--r--chromium/ui/events/android/keyboard_hook_android.cc4
-rw-r--r--chromium/ui/events/base_event_utils.h1
-rw-r--r--chromium/ui/events/blink/blink_event_util.cc27
-rw-r--r--chromium/ui/events/blink/blink_event_util.h6
-rw-r--r--chromium/ui/events/blink/web_input_event.cc8
-rw-r--r--chromium/ui/events/blink/web_input_event_builders_win.cc10
-rw-r--r--chromium/ui/events/blink/web_input_event_builders_win_unittest.cc51
-rw-r--r--chromium/ui/events/cocoa/events_mac.mm5
-rw-r--r--chromium/ui/events/devices/BUILD.gn2
-rw-r--r--chromium/ui/events/devices/microphone_mute_switch_monitor.cc37
-rw-r--r--chromium/ui/events/devices/microphone_mute_switch_monitor.h62
-rw-r--r--chromium/ui/events/devices/touchscreen_device.cc12
-rw-r--r--chromium/ui/events/devices/touchscreen_device.h9
-rw-r--r--chromium/ui/events/devices/x11/touch_factory_x11.cc3
-rw-r--r--chromium/ui/events/devices/x11/touch_factory_x11.h2
-rw-r--r--chromium/ui/events/event.cc52
-rw-r--r--chromium/ui/events/event.h2
-rw-r--r--chromium/ui/events/event_handler.cc10
-rw-r--r--chromium/ui/events/event_handler.h23
-rw-r--r--chromium/ui/events/event_switches.h6
-rw-r--r--chromium/ui/events/event_target.cc8
-rw-r--r--chromium/ui/events/event_unittest.cc327
-rw-r--r--chromium/ui/events/event_utils.cc237
-rw-r--r--chromium/ui/events/event_utils.h36
-rw-r--r--chromium/ui/events/events_default.cc5
-rw-r--r--chromium/ui/events/events_stub.cc5
-rw-r--r--chromium/ui/events/fraction_of_time_without_user_input_recorder.h6
-rw-r--r--chromium/ui/events/gesture_detection/filtered_gesture_provider.cc4
-rw-r--r--chromium/ui/events/gesture_detection/filtered_gesture_provider.h3
-rw-r--r--chromium/ui/events/gesture_detection/gesture_provider.cc162
-rw-r--r--chromium/ui/events/gesture_detection/gesture_provider.h3
-rw-r--r--chromium/ui/events/gesture_detection/gesture_touch_uma_histogram.h1
-rw-r--r--chromium/ui/events/gesture_detection/motion_event_generic.h6
-rw-r--r--chromium/ui/events/gesture_event_details.h6
-rw-r--r--chromium/ui/events/gestures/OWNERS2
-rw-r--r--chromium/ui/events/gestures/gesture_provider_aura.cc4
-rw-r--r--chromium/ui/events/gestures/gesture_provider_aura.h9
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer.h7
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer_impl.cc15
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer_impl.h2
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer_impl_mac.cc8
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer_impl_mac.h2
-rw-r--r--chromium/ui/events/gestures/motion_event_aura.h9
-rw-r--r--chromium/ui/events/keyboard_hook.h8
-rw-r--r--chromium/ui/events/keyboard_hook_base.cc2
-rw-r--r--chromium/ui/events/keyboard_hook_base.h7
-rw-r--r--chromium/ui/events/keyboard_hook_linux.cc32
-rw-r--r--chromium/ui/events/keycodes/DEPS1
-rw-r--r--chromium/ui/events/keycodes/dom/dom_code.h6
-rw-r--r--chromium/ui/events/keycodes/dom/dom_key.h12
-rw-r--r--chromium/ui/events/keycodes/dom/keycode_converter.cc54
-rw-r--r--chromium/ui/events/keycodes/dom/keycode_converter.h18
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion.cc17
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion.h5
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion_fuchsia.cc38
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion_fuchsia.h27
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion_fuchsia_unittest.cc67
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion_x.cc7
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion_x.h1
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion_xkb.h1
-rw-r--r--chromium/ui/events/mac/keyboard_hook_mac.mm2
-rw-r--r--chromium/ui/events/mojom/event_mojom_traits.cc4
-rw-r--r--chromium/ui/events/ozone/device/device_event.h6
-rw-r--r--chromium/ui/events/ozone/device/device_event_observer.h7
-rw-r--r--chromium/ui/events/ozone/evdev/BUILD.gn46
-rw-r--r--chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.cc6
-rw-r--r--chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.h11
-rw-r--r--chromium/ui/events/ozone/evdev/event_converter_evdev.cc10
-rw-r--r--chromium/ui/events/ozone/evdev/event_converter_evdev.h10
-rw-r--r--chromium/ui/events/ozone/evdev/event_converter_evdev_impl.cc22
-rw-r--r--chromium/ui/events/ozone/evdev/event_converter_evdev_impl.h6
-rw-r--r--chromium/ui/events/ozone/evdev/event_converter_test_util.cc4
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_info.cc10
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_info.h8
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_info_unittest.cc51
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_test_util.cc46
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_test_util.h2
-rw-r--r--chromium/ui/events/ozone/evdev/event_factory_evdev.cc15
-rw-r--r--chromium/ui/events/ozone/evdev/event_factory_evdev.h2
-rw-r--r--chromium/ui/events/ozone/evdev/event_factory_evdev_unittest.cc2
-rw-r--r--chromium/ui/events/ozone/evdev/event_thread_evdev.cc7
-rw-r--r--chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev.h6
-rw-r--r--chromium/ui/events/ozone/evdev/input_controller_evdev.cc9
-rw-r--r--chromium/ui/events/ozone/evdev/input_controller_evdev.h2
-rw-r--r--chromium/ui/events/ozone/evdev/input_device_factory_evdev.cc48
-rw-r--r--chromium/ui/events/ozone/evdev/input_device_factory_evdev.h2
-rw-r--r--chromium/ui/events/ozone/evdev/input_device_factory_evdev_proxy.cc20
-rw-r--r--chromium/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h4
-rw-r--r--chromium/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc5
-rw-r--r--chromium/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h2
-rw-r--r--chromium/ui/events/ozone/evdev/libgestures_glue/gesture_properties_service.h6
-rw-r--r--chromium/ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev.cc95
-rw-r--r--chromium/ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev.h51
-rw-r--r--chromium/ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev_unittest.cc140
-rw-r--r--chromium/ui/events/ozone/evdev/switches.cc14
-rw-r--r--chromium/ui/events/ozone/evdev/switches.h17
-rw-r--r--chromium/ui/events/ozone/evdev/tablet_event_converter_evdev.h6
-rw-r--r--chromium/ui/events/ozone/evdev/touch_evdev_debug_buffer.h6
-rw-r--r--chromium/ui/events/ozone/evdev/touch_evdev_types.h1
-rw-r--r--chromium/ui/events/ozone/evdev/touch_event_converter_evdev.cc45
-rw-r--r--chromium/ui/events/ozone/evdev/touch_event_converter_evdev.h19
-rw-r--r--chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc56
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/edge_touch_filter.cc1
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc4
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_unittest.cc7
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_report_filter_unittest.cc6
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/open_palm_detection_filter_unittest.cc6
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory.cc4
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.h2
-rw-r--r--chromium/ui/events/ozone/gamepad/gamepad_observer.h1
-rw-r--r--chromium/ui/events/ozone/gamepad/gamepad_provider_ozone.h1
-rw-r--r--chromium/ui/events/ozone/keyboard/event_auto_repeat_handler.h6
-rw-r--r--chromium/ui/events/ozone/keyboard_hook_ozone.cc34
-rw-r--r--chromium/ui/events/ozone/keyboard_hook_ozone.h28
-rw-r--r--chromium/ui/events/ozone/layout/BUILD.gn14
-rw-r--r--chromium/ui/events/ozone/layout/keyboard_layout_engine.h12
-rw-r--r--chromium/ui/events/ozone/layout/keyboard_layout_engine_manager.h7
-rw-r--r--chromium/ui/events/ozone/layout/keyboard_layout_engine_test_utils.cc31
-rw-r--r--chromium/ui/events/ozone/layout/keyboard_layout_engine_test_utils.h16
-rw-r--r--chromium/ui/events/ozone/layout/no/no_keyboard_layout_engine.cc4
-rw-r--r--chromium/ui/events/ozone/layout/no/no_keyboard_layout_engine.h1
-rw-r--r--chromium/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.cc5
-rw-r--r--chromium/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h1
-rw-r--r--chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc14
-rw-r--r--chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h4
-rw-r--r--chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc438
-rw-r--r--chromium/ui/events/platform/platform_event_source.cc11
-rw-r--r--chromium/ui/events/platform/platform_event_source.h5
-rw-r--r--chromium/ui/events/platform/platform_event_source_unittest.cc106
-rw-r--r--chromium/ui/events/platform/x11/x11_event_source.cc18
-rw-r--r--chromium/ui/events/platform/x11/x11_event_source.h13
-rw-r--r--chromium/ui/events/platform/x11/x11_event_watcher_fdwatch.cc4
-rw-r--r--chromium/ui/events/platform/x11/x11_event_watcher_glib.cc45
-rw-r--r--chromium/ui/events/pointer_details.cc10
-rw-r--r--chromium/ui/events/pointer_details.h2
-rw-r--r--chromium/ui/events/scoped_target_handler.h2
-rw-r--r--chromium/ui/events/win/events_win.cc10
-rw-r--r--chromium/ui/events/win/events_win_utils.cc61
-rw-r--r--chromium/ui/events/win/events_win_utils.h71
-rw-r--r--chromium/ui/events/win/keyboard_hook_monitor.h4
-rw-r--r--chromium/ui/events/win/keyboard_hook_monitor_impl.h5
-rw-r--r--chromium/ui/events/win/keyboard_hook_observer.h5
-rw-r--r--chromium/ui/events/win/keyboard_hook_win_base.cc2
-rw-r--r--chromium/ui/events/win/keyboard_hook_win_base.h11
-rw-r--r--chromium/ui/events/win/media_keyboard_hook_win.cc2
-rw-r--r--chromium/ui/events/win/modifier_keyboard_hook_win.cc10
-rw-r--r--chromium/ui/events/win/modifier_keyboard_hook_win_unittest.cc4
-rw-r--r--chromium/ui/events/x/events_x_utils.h1
-rw-r--r--chromium/ui/events/x/keyboard_hook_x11.cc115
-rw-r--r--chromium/ui/events/x/keyboard_hook_x11.h26
-rw-r--r--chromium/ui/file_manager/BUILD.gn33
-rw-r--r--chromium/ui/file_manager/audio_player/elements/BUILD.gn149
-rw-r--r--chromium/ui/file_manager/audio_player/js/BUILD.gn16
-rw-r--r--chromium/ui/file_manager/file_manager/BUILD.gn1
-rw-r--r--chromium/ui/file_manager/file_manager/background/js/BUILD.gn32
-rw-r--r--chromium/ui/file_manager/file_manager/common/js/BUILD.gn2
-rw-r--r--chromium/ui/file_manager/file_manager/cws_widget/BUILD.gn134
-rw-r--r--chromium/ui/file_manager/file_manager/externs/BUILD.gn2
-rw-r--r--chromium/ui/file_manager/file_manager/externs/background/BUILD.gn2
-rw-r--r--chromium/ui/file_manager/file_manager/foreground/elements/BUILD.gn63
-rw-r--r--chromium/ui/file_manager/file_manager/foreground/js/BUILD.gn130
-rw-r--r--chromium/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn3
-rw-r--r--chromium/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn72
-rw-r--r--chromium/ui/file_manager/file_manager/foreground/js/ui/table/BUILD.gn2
-rw-r--r--chromium/ui/file_manager/image_loader/BUILD.gn2
-rw-r--r--chromium/ui/file_manager/integration_tests/file_manager/BUILD.gn10
-rw-r--r--chromium/ui/file_manager/video_player/js/BUILD.gn2
-rw-r--r--chromium/ui/gfx/BUILD.gn7
-rw-r--r--chromium/ui/gfx/android/android_surface_control_compat.cc102
-rw-r--r--chromium/ui/gfx/android/android_surface_control_compat.h15
-rw-r--r--chromium/ui/gfx/animation/animation.cc2
-rw-r--r--chromium/ui/gfx/animation/animation.h4
-rw-r--r--chromium/ui/gfx/animation/keyframe/animation_curve.h3
-rw-r--r--chromium/ui/gfx/animation/keyframe/keyframe_animation_unittest.cc387
-rw-r--r--chromium/ui/gfx/animation/keyframe/keyframe_effect.cc53
-rw-r--r--chromium/ui/gfx/animation/keyframe/keyframe_effect.h3
-rw-r--r--chromium/ui/gfx/animation/keyframe/keyframe_model.cc8
-rw-r--r--chromium/ui/gfx/animation/keyframe/keyframe_model.h19
-rw-r--r--chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.cc129
-rw-r--r--chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.h61
-rw-r--r--chromium/ui/gfx/animation/keyframe/transition.cc4
-rw-r--r--chromium/ui/gfx/animation/keyframe/transition.h5
-rw-r--r--chromium/ui/gfx/animation/linear_animation.h2
-rw-r--r--chromium/ui/gfx/animation/slide_animation.cc4
-rw-r--r--chromium/ui/gfx/animation/slide_animation.h4
-rw-r--r--chromium/ui/gfx/bidi_line_iterator_unittest.cc7
-rw-r--r--chromium/ui/gfx/buffer_format_util.cc26
-rw-r--r--chromium/ui/gfx/buffer_format_util.h9
-rw-r--r--chromium/ui/gfx/buffer_types.h22
-rw-r--r--chromium/ui/gfx/canvas.cc1
-rw-r--r--chromium/ui/gfx/canvas.h6
-rw-r--r--chromium/ui/gfx/codec/vector_wstream.h6
-rw-r--r--chromium/ui/gfx/color_analysis.cc4
-rw-r--r--chromium/ui/gfx/color_analysis.h2
-rw-r--r--chromium/ui/gfx/color_analysis_unittest.cc6
-rw-r--r--chromium/ui/gfx/color_space.h12
-rw-r--r--chromium/ui/gfx/color_space_win.h2
-rw-r--r--chromium/ui/gfx/color_transform_unittest.cc6
-rw-r--r--chromium/ui/gfx/color_utils.cc24
-rw-r--r--chromium/ui/gfx/color_utils.h15
-rw-r--r--chromium/ui/gfx/color_utils_unittest.cc33
-rw-r--r--chromium/ui/gfx/display_color_spaces.h1
-rw-r--r--chromium/ui/gfx/font_fallback_mac.mm2
-rw-r--r--chromium/ui/gfx/font_fallback_skia.cc4
-rw-r--r--chromium/ui/gfx/font_fallback_win.cc3
-rw-r--r--chromium/ui/gfx/font_list.h4
-rw-r--r--chromium/ui/gfx/font_names_testing.h2
-rw-r--r--chromium/ui/gfx/font_render_params_linux.cc24
-rw-r--r--chromium/ui/gfx/gdi_util.h1
-rw-r--r--chromium/ui/gfx/geometry/axis_transform2d.cc2
-rw-r--r--chromium/ui/gfx/geometry/axis_transform2d.h47
-rw-r--r--chromium/ui/gfx/geometry/axis_transform2d_unittest.cc4
-rw-r--r--chromium/ui/gfx/geometry/mojom/geometry.mojom1
-rw-r--r--chromium/ui/gfx/geometry/point.cc2
-rw-r--r--chromium/ui/gfx/geometry/quaternion.h18
-rw-r--r--chromium/ui/gfx/geometry/quaternion_unittest.cc21
-rw-r--r--chromium/ui/gfx/geometry/rect.cc2
-rw-r--r--chromium/ui/gfx/geometry/rect_f.cc2
-rw-r--r--chromium/ui/gfx/geometry/size.cc2
-rw-r--r--chromium/ui/gfx/gpu_extra_info.h3
-rw-r--r--chromium/ui/gfx/gpu_fence.h6
-rw-r--r--chromium/ui/gfx/gpu_fence_handle.cc3
-rw-r--r--chromium/ui/gfx/gpu_memory_buffer.cc12
-rw-r--r--chromium/ui/gfx/gpu_memory_buffer.h5
-rw-r--r--chromium/ui/gfx/half_float.h6
-rw-r--r--chromium/ui/gfx/hdr_static_metadata.cc14
-rw-r--r--chromium/ui/gfx/hdr_static_metadata.h40
-rw-r--r--chromium/ui/gfx/image/image.cc18
-rw-r--r--chromium/ui/gfx/image/image.h4
-rw-r--r--chromium/ui/gfx/image/image_platform.h6
-rw-r--r--chromium/ui/gfx/image/image_skia_source.h1
-rw-r--r--chromium/ui/gfx/image/image_skia_unittest.cc4
-rw-r--r--chromium/ui/gfx/image/image_unittest.cc2
-rw-r--r--chromium/ui/gfx/image/image_unittest_util.cc10
-rw-r--r--chromium/ui/gfx/image/image_unittest_util.h2
-rw-r--r--chromium/ui/gfx/image/image_util.cc4
-rw-r--r--chromium/ui/gfx/ios/NSString+CrStringDrawing.h6
-rw-r--r--chromium/ui/gfx/ipc/buffer_types/gfx_param_traits.cc2
-rw-r--r--chromium/ui/gfx/ipc/buffer_types/gfx_param_traits_macros.h2
-rw-r--r--chromium/ui/gfx/ipc/geometry/gfx_param_traits.cc1
-rw-r--r--chromium/ui/gfx/ipc/gfx_param_traits.cc1
-rw-r--r--chromium/ui/gfx/linux/client_native_pixmap_dmabuf.cc1
-rw-r--r--chromium/ui/gfx/mac/io_surface.cc4
-rw-r--r--chromium/ui/gfx/mac/io_surface_unittest.cc10
-rw-r--r--chromium/ui/gfx/mojom/BUILD.gn5
-rw-r--r--chromium/ui/gfx/mojom/buffer_types.mojom8
-rw-r--r--chromium/ui/gfx/mojom/buffer_types_mojom_traits.h44
-rw-r--r--chromium/ui/gfx/mojom/delegated_ink_point_renderer.mojom25
-rw-r--r--chromium/ui/gfx/mojom/gpu_extra_info.mojom4
-rw-r--r--chromium/ui/gfx/mojom/gpu_extra_info_mojom_traits.cc8
-rw-r--r--chromium/ui/gfx/mojom/gpu_extra_info_mojom_traits.h8
-rw-r--r--chromium/ui/gfx/mojom/mask_filter_info_mojom_traits.h2
-rw-r--r--chromium/ui/gfx/mojom/native_handle_types.mojom2
-rw-r--r--chromium/ui/gfx/mojom/native_handle_types_mojom_traits.h2
-rw-r--r--chromium/ui/gfx/mojom/presentation_feedback.mojom1
-rw-r--r--chromium/ui/gfx/mojom/presentation_feedback_mojom_traits.h8
-rw-r--r--chromium/ui/gfx/native_pixmap_handle.h4
-rw-r--r--chromium/ui/gfx/paint_throbber.cc10
-rw-r--r--chromium/ui/gfx/paint_throbber.h8
-rw-r--r--chromium/ui/gfx/paint_vector_icon.cc13
-rw-r--r--chromium/ui/gfx/paint_vector_icon.h4
-rw-r--r--chromium/ui/gfx/platform_font.h4
-rw-r--r--chromium/ui/gfx/platform_font_mac.h10
-rw-r--r--chromium/ui/gfx/platform_font_mac.mm18
-rw-r--r--chromium/ui/gfx/platform_font_skia.cc8
-rw-r--r--chromium/ui/gfx/platform_font_skia.h2
-rw-r--r--chromium/ui/gfx/presentation_feedback.h13
-rw-r--r--chromium/ui/gfx/range/gfx_range_export.h6
-rw-r--r--chromium/ui/gfx/render_text.cc4
-rw-r--r--chromium/ui/gfx/render_text.h34
-rw-r--r--chromium/ui/gfx/render_text_harfbuzz.cc2
-rw-r--r--chromium/ui/gfx/render_text_unittest.cc2176
-rw-r--r--chromium/ui/gfx/rrect_f.cc1
-rw-r--r--chromium/ui/gfx/shadow_value.cc17
-rw-r--r--chromium/ui/gfx/shadow_value.h13
-rw-r--r--chromium/ui/gfx/skia_paint_util.h2
-rw-r--r--chromium/ui/gfx/skia_util.h2
-rw-r--r--chromium/ui/gfx/swap_result.cc7
-rw-r--r--chromium/ui/gfx/swap_result.h6
-rw-r--r--chromium/ui/gfx/switches.cc13
-rw-r--r--chromium/ui/gfx/switches.h5
-rw-r--r--chromium/ui/gfx/text_elider.cc2
-rw-r--r--chromium/ui/gfx/text_elider.h6
-rw-r--r--chromium/ui/gfx/text_elider_unittest.cc1137
-rw-r--r--chromium/ui/gfx/vector_icon_utils.cc24
-rw-r--r--chromium/ui/gfx/vector_icon_utils.h20
-rw-r--r--chromium/ui/gfx/win/direct_write.cc16
-rw-r--r--chromium/ui/gfx/win/direct_write.h6
-rw-r--r--chromium/ui/gfx/win/physical_size.h2
-rw-r--r--chromium/ui/gfx/win/singleton_hwnd.h1
-rw-r--r--chromium/ui/gfx/win/singleton_hwnd_hot_key_observer.cc8
-rw-r--r--chromium/ui/gfx/win/window_impl.cc1
-rw-r--r--chromium/ui/gfx/x/connection.cc13
-rw-r--r--chromium/ui/gfx/x/connection.h15
-rw-r--r--chromium/ui/gfx/x/gen_xproto.py6
-rw-r--r--chromium/ui/gfx/x/generated_protos/bigreq.h4
-rw-r--r--chromium/ui/gfx/x/generated_protos/composite.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/damage.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/dpms.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/dri2.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/dri3.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/ge.h4
-rw-r--r--chromium/ui/gfx/x/generated_protos/glx.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/present.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/randr.h16
-rw-r--r--chromium/ui/gfx/x/generated_protos/record.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/render.cc52
-rw-r--r--chromium/ui/gfx/x/generated_protos/render.h106
-rw-r--r--chromium/ui/gfx/x/generated_protos/res.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/screensaver.cc30
-rw-r--r--chromium/ui/gfx/x/generated_protos/screensaver.h62
-rw-r--r--chromium/ui/gfx/x/generated_protos/shape.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/shm.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/sync.cc24
-rw-r--r--chromium/ui/gfx/x/generated_protos/sync.h50
-rw-r--r--chromium/ui/gfx/x/generated_protos/xc_misc.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/xevie.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/xf86dri.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/xf86vidmode.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/xfixes.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/xinerama.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/xinput.cc12
-rw-r--r--chromium/ui/gfx/x/generated_protos/xinput.h134
-rw-r--r--chromium/ui/gfx/x/generated_protos/xkb.cc92
-rw-r--r--chromium/ui/gfx/x/generated_protos/xkb.h296
-rw-r--r--chromium/ui/gfx/x/generated_protos/xprint.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/xproto.cc182
-rw-r--r--chromium/ui/gfx/x/generated_protos/xproto.h366
-rw-r--r--chromium/ui/gfx/x/generated_protos/xselinux.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/xtest.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/xv.h2
-rw-r--r--chromium/ui/gfx/x/generated_protos/xvmc.h2
-rw-r--r--chromium/ui/gfx/x/property_cache.h4
-rw-r--r--chromium/ui/gfx/x/xproto_internal.h2
-rw-r--r--chromium/ui/gfx/x/xproto_types.h2
-rw-r--r--chromium/ui/gl/BUILD.gn5
-rw-r--r--chromium/ui/gl/DEPS5
-rw-r--r--chromium/ui/gl/GL/glextchromium.h6
-rw-r--r--chromium/ui/gl/angle_platform_impl.h1
-rw-r--r--chromium/ui/gl/ca_renderer_layer_params.cc6
-rw-r--r--chromium/ui/gl/ca_renderer_layer_params.h5
-rw-r--r--chromium/ui/gl/dc_layer_tree.cc14
-rw-r--r--chromium/ui/gl/dc_layer_tree.h20
-rw-r--r--chromium/ui/gl/dc_renderer_layer_params.h6
-rw-r--r--chromium/ui/gl/delegated_ink_point_renderer_gpu.h288
-rw-r--r--chromium/ui/gl/delegated_ink_point_renderer_gpu_unittest.cc262
-rw-r--r--chromium/ui/gl/direct_composition_surface_win.cc7
-rw-r--r--chromium/ui/gl/direct_composition_surface_win.h9
-rw-r--r--chromium/ui/gl/direct_composition_surface_win_unittest.cc8
-rw-r--r--chromium/ui/gl/dual_gpu_state_mac.h1
-rw-r--r--chromium/ui/gl/egl_timestamps.h1
-rw-r--r--chromium/ui/gl/gl_context_glx.h1
-rw-r--r--chromium/ui/gl/gl_context_glx_unittest.cc2
-rw-r--r--chromium/ui/gl/gl_features.cc83
-rw-r--r--chromium/ui/gl/gl_features.h2
-rw-r--r--chromium/ui/gl/gl_fence_win.h2
-rw-r--r--chromium/ui/gl/gl_image_d3d.cc42
-rw-r--r--chromium/ui/gl/gl_image_d3d.h29
-rw-r--r--chromium/ui/gl/gl_image_d3d_unittest.cc7
-rw-r--r--chromium/ui/gl/gl_image_egl_pixmap.cc2
-rw-r--r--chromium/ui/gl/gl_image_glx.cc4
-rw-r--r--chromium/ui/gl/gl_image_io_surface.h7
-rw-r--r--chromium/ui/gl/gl_image_io_surface.mm9
-rw-r--r--chromium/ui/gl/gl_image_io_surface_egl.mm2
-rw-r--r--chromium/ui/gl/gl_image_io_surface_unittest.cc10
-rw-r--r--chromium/ui/gl/gl_image_memory.cc20
-rw-r--r--chromium/ui/gl/gl_image_native_pixmap_unittest.cc6
-rw-r--r--chromium/ui/gl/gl_implementation.cc13
-rw-r--r--chromium/ui/gl/gl_implementation.h5
-rw-r--r--chromium/ui/gl/gl_share_group.h1
-rw-r--r--chromium/ui/gl/gl_stub_autogen_gl.h6
-rw-r--r--chromium/ui/gl/gl_surface.cc12
-rw-r--r--chromium/ui/gl/gl_surface.h10
-rw-r--r--chromium/ui/gl/gl_surface_egl.cc20
-rw-r--r--chromium/ui/gl/gl_surface_egl.h2
-rw-r--r--chromium/ui/gl/gl_surface_egl_surface_control.cc60
-rw-r--r--chromium/ui/gl/gl_surface_egl_surface_control.h16
-rw-r--r--chromium/ui/gl/gl_surface_egl_x11.cc2
-rw-r--r--chromium/ui/gl/gl_surface_egl_x11_gles2.h1
-rw-r--r--chromium/ui/gl/gl_surface_glx.cc4
-rw-r--r--chromium/ui/gl/gl_surface_presentation_helper.cc12
-rw-r--r--chromium/ui/gl/gl_surface_presentation_helper.h1
-rw-r--r--chromium/ui/gl/gl_switches.cc1
-rw-r--r--chromium/ui/gl/gl_switches.h1
-rw-r--r--chromium/ui/gl/gl_utils.cc13
-rw-r--r--chromium/ui/gl/gl_version_info.cc4
-rw-r--r--chromium/ui/gl/hdr_metadata_helper_win.cc2
-rw-r--r--chromium/ui/gl/hdr_metadata_helper_win.h10
-rw-r--r--chromium/ui/gl/init/BUILD.gn1
-rw-r--r--chromium/ui/gl/init/gl_factory.cc7
-rw-r--r--chromium/ui/gl/init/gl_initializer_win.cc1
-rw-r--r--chromium/ui/gl/scoped_make_current.h2
-rw-r--r--chromium/ui/gl/swap_chain_presenter.cc175
-rw-r--r--chromium/ui/gl/swap_chain_presenter.h29
-rw-r--r--chromium/ui/gl/yuv_to_rgb_converter.h6
-rw-r--r--chromium/ui/gtk/BUILD.gn67
-rw-r--r--chromium/ui/gtk/gdk.sigs16
-rw-r--r--chromium/ui/gtk/gtk.sigs132
-rw-r--r--chromium/ui/gtk/gtk_color_mixers.cc10
-rw-r--r--chromium/ui/gtk/gtk_color_mixers.h3
-rw-r--r--chromium/ui/gtk/gtk_compat.cc153
-rw-r--r--chromium/ui/gtk/gtk_compat.h53
-rw-r--r--chromium/ui/gtk/gtk_key_bindings_handler.cc26
-rw-r--r--chromium/ui/gtk/gtk_key_bindings_handler.h52
-rw-r--r--chromium/ui/gtk/gtk_types.h26
-rw-r--r--chromium/ui/gtk/gtk_ui.cc73
-rw-r--r--chromium/ui/gtk/gtk_ui.h14
-rw-r--r--chromium/ui/gtk/gtk_ui_delegate.cc23
-rw-r--r--chromium/ui/gtk/gtk_ui_factory.cc11
-rw-r--r--chromium/ui/gtk/gtk_ui_factory.h21
-rw-r--r--chromium/ui/gtk/gtk_ui_platform.h (renamed from chromium/ui/gtk/gtk_ui_delegate.h)34
-rw-r--r--chromium/ui/gtk/gtk_util.cc226
-rw-r--r--chromium/ui/gtk/gtk_util.h19
-rw-r--r--chromium/ui/gtk/input_method_context_impl_gtk.cc11
-rw-r--r--chromium/ui/gtk/input_method_context_impl_gtk.h1
-rw-r--r--chromium/ui/gtk/native_theme_gtk.cc42
-rw-r--r--chromium/ui/gtk/native_theme_gtk.h8
-rw-r--r--chromium/ui/gtk/native_theme_gtk_unittest.cc22
-rw-r--r--chromium/ui/gtk/nav_button_provider_gtk.cc10
-rw-r--r--chromium/ui/gtk/nav_button_provider_gtk.h4
-rw-r--r--chromium/ui/gtk/printing/print_dialog_gtk.cc21
-rw-r--r--chromium/ui/gtk/printing/print_dialog_gtk.h3
-rw-r--r--chromium/ui/gtk/printing/printing_gtk_util.cc4
-rw-r--r--chromium/ui/gtk/select_file_dialog_impl_gtk.cc19
-rw-r--r--chromium/ui/gtk/settings_provider_gtk.cc14
-rw-r--r--chromium/ui/gtk/wayland/BUILD.gn21
-rw-r--r--chromium/ui/gtk/wayland/gtk_ui_delegate_wayland_base.cc91
-rw-r--r--chromium/ui/gtk/wayland/gtk_ui_platform_wayland.cc84
-rw-r--r--chromium/ui/gtk/wayland/gtk_ui_platform_wayland.h (renamed from chromium/ui/gtk/wayland/gtk_ui_delegate_wayland_base.h)34
-rw-r--r--chromium/ui/gtk/x/BUILD.gn28
-rw-r--r--chromium/ui/gtk/x/gtk_event_loop_x11.cc99
-rw-r--r--chromium/ui/gtk/x/gtk_event_loop_x11.h19
-rw-r--r--chromium/ui/gtk/x/gtk_ui_platform_x11.cc (renamed from chromium/ui/gtk/x/gtk_ui_delegate_x11.cc)74
-rw-r--r--chromium/ui/gtk/x/gtk_ui_platform_x11.h (renamed from chromium/ui/gtk/x/gtk_ui_delegate_x11.h)31
-rw-r--r--chromium/ui/latency/latency_info.cc1
-rw-r--r--chromium/ui/latency/latency_tracker.cc34
-rw-r--r--chromium/ui/latency/latency_tracker.h5
-rw-r--r--chromium/ui/message_center/lock_screen/fake_lock_screen_controller.h2
-rw-r--r--chromium/ui/message_center/message_center_impl.cc27
-rw-r--r--chromium/ui/message_center/message_center_impl.h8
-rw-r--r--chromium/ui/message_center/message_center_impl_unittest.cc8
-rw-r--r--chromium/ui/message_center/message_center_observer.h6
-rw-r--r--chromium/ui/message_center/message_center_stats_collector.cc4
-rw-r--r--chromium/ui/message_center/message_center_stats_collector.h4
-rw-r--r--chromium/ui/message_center/notification_list_unittest.cc65
-rw-r--r--chromium/ui/message_center/public/cpp/notification.h9
-rw-r--r--chromium/ui/message_center/public/cpp/notification_delegate.cc10
-rw-r--r--chromium/ui/message_center/public/cpp/notification_delegate.h16
-rw-r--r--chromium/ui/message_center/public/cpp/notification_delegate_unittest.cc14
-rw-r--r--chromium/ui/message_center/views/message_popup_collection_unittest.cc4
-rw-r--r--chromium/ui/message_center/views/message_popup_view.cc5
-rw-r--r--chromium/ui/message_center/views/message_view.cc5
-rw-r--r--chromium/ui/message_center/views/message_view.h9
-rw-r--r--chromium/ui/message_center/views/message_view_factory.h6
-rw-r--r--chromium/ui/message_center/views/notification_control_buttons_view.cc2
-rw-r--r--chromium/ui/message_center/views/notification_header_view.cc10
-rw-r--r--chromium/ui/message_center/views/notification_header_view.h16
-rw-r--r--chromium/ui/message_center/views/notification_view_md.cc122
-rw-r--r--chromium/ui/message_center/views/notification_view_md.h31
-rw-r--r--chromium/ui/message_center/views/notification_view_md_unittest.cc187
-rw-r--r--chromium/ui/message_center/views/padded_button.cc18
-rw-r--r--chromium/ui/message_center/views/padded_button.h3
-rw-r--r--chromium/ui/message_center/views/proportional_image_view.cc2
-rw-r--r--chromium/ui/native_theme/DIR_METADATA3
-rw-r--r--chromium/ui/native_theme/caption_style.cc10
-rw-r--r--chromium/ui/native_theme/caption_style.h6
-rw-r--r--chromium/ui/native_theme/caption_style_mac.mm4
-rw-r--r--chromium/ui/native_theme/caption_style_win.cc30
-rw-r--r--chromium/ui/native_theme/caption_style_win_unittest.cc2
-rw-r--r--chromium/ui/native_theme/common_theme.cc58
-rw-r--r--chromium/ui/native_theme/common_theme.h1
-rw-r--r--chromium/ui/native_theme/native_theme.cc27
-rw-r--r--chromium/ui/native_theme/native_theme.h17
-rw-r--r--chromium/ui/native_theme/native_theme_base.cc33
-rw-r--r--chromium/ui/native_theme/native_theme_base.h15
-rw-r--r--chromium/ui/native_theme/native_theme_color_id.h14
-rw-r--r--chromium/ui/native_theme/native_theme_mac.h6
-rw-r--r--chromium/ui/native_theme/native_theme_mac.mm12
-rw-r--r--chromium/ui/native_theme/native_theme_unittest.cc1
-rw-r--r--chromium/ui/native_theme/native_theme_utils.cc21
-rw-r--r--chromium/ui/native_theme/native_theme_utils.h2
-rw-r--r--chromium/ui/native_theme/native_theme_win.cc10
-rw-r--r--chromium/ui/native_theme/native_theme_win.h6
-rw-r--r--chromium/ui/native_theme/test_native_theme.cc2
-rw-r--r--chromium/ui/native_theme/test_native_theme.h2
-rw-r--r--chromium/ui/native_theme/themed_vector_icon.cc44
-rw-r--r--chromium/ui/native_theme/themed_vector_icon.h18
-rw-r--r--chromium/ui/ozone/BUILD.gn10
-rw-r--r--chromium/ui/ozone/common/base_keyboard_hook.cc39
-rw-r--r--chromium/ui/ozone/common/base_keyboard_hook.h60
-rw-r--r--chromium/ui/ozone/demo/gl_renderer.cc4
-rw-r--r--chromium/ui/ozone/demo/simple_renderer_factory.cc1
-rw-r--r--chromium/ui/ozone/demo/skia/skia_gl_renderer.cc4
-rw-r--r--chromium/ui/ozone/demo/skia/skia_renderer_factory.cc1
-rw-r--r--chromium/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc1
-rw-r--r--chromium/ui/ozone/demo/software_renderer.cc1
-rw-r--r--chromium/ui/ozone/demo/surfaceless_gl_renderer.cc5
-rw-r--r--chromium/ui/ozone/demo/vulkan_overlay_renderer.cc6
-rw-r--r--chromium/ui/ozone/demo/vulkan_renderer.cc5
-rw-r--r--chromium/ui/ozone/platform/cast/gl_ozone_egl_cast.cc1
-rw-r--r--chromium/ui/ozone/platform/cast/ozone_platform_cast.cc1
-rw-r--r--chromium/ui/ozone/platform/cast/ozone_platform_cast.h6
-rw-r--r--chromium/ui/ozone/platform/cast/surface_factory_cast.cc2
-rw-r--r--chromium/ui/ozone/platform/cast/surface_factory_cast.h2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.cc2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/crtc_controller.h1
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_device.cc6
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_display_unittest.cc2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.h6
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc15
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc11
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread.cc6
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_window.cc11
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_window.h5
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_window_unittest.cc3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_overlay_surface.cc3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_overlay_surface.h9
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.h6
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc5
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h5
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc7
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.h4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc64
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h16
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc351
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc10
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h8
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc27
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h7
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc22
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc35
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h10
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/page_flip_request.h1
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/screen_manager.cc163
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/screen_manager.h26
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc270
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_cursor.cc22
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_cursor.h9
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_device_connector.cc21
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_device_connector.h3
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_window_host.cc7
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_window_host.h2
-rw-r--r--chromium/ui/ozone/platform/drm/host/host_drm_device.cc7
-rw-r--r--chromium/ui/ozone/platform/drm/host/host_drm_device.h2
-rw-r--r--chromium/ui/ozone/platform/drm/ozone_platform_drm.cc5
-rw-r--r--chromium/ui/ozone/platform/headless/BUILD.gn6
-rw-r--r--chromium/ui/ozone/platform/headless/DEPS1
-rw-r--r--chromium/ui/ozone/platform/headless/headless_surface_factory.cc3
-rw-r--r--chromium/ui/ozone/platform/headless/headless_surface_factory.h2
-rw-r--r--chromium/ui/ozone/platform/headless/headless_window_manager.h3
-rw-r--r--chromium/ui/ozone/platform/headless/ozone_platform_headless.cc10
-rw-r--r--chromium/ui/ozone/platform/scenic/safe_presenter.h2
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_gpu_host.cc17
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_gpu_host.h2
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_screen.cc23
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_screen.h1
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_surface_factory.cc11
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_surface_factory.h5
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_window.cc36
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_window.h16
-rw-r--r--chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.cc17
-rw-r--r--chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.h5
-rw-r--r--chromium/ui/ozone/platform/scenic/sysmem_buffer_manager.cc18
-rw-r--r--chromium/ui/ozone/platform/scenic/sysmem_buffer_manager.h1
-rw-r--r--chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc20
-rw-r--r--chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.h3
-rw-r--r--chromium/ui/ozone/platform/wayland/BUILD.gn34
-rw-r--r--chromium/ui/ozone/platform/wayland/DEPS3
-rw-r--r--chromium/ui/ozone/platform/wayland/OWNERS1
-rw-r--r--chromium/ui/ozone/platform/wayland/common/data_util.cc11
-rw-r--r--chromium/ui/ozone/platform/wayland/common/wayland_object.cc28
-rw-r--r--chromium/ui/ozone/platform/wayland/common/wayland_object.h44
-rw-r--r--chromium/ui/ozone/platform/wayland/common/wayland_util.cc5
-rw-r--r--chromium/ui/ozone/platform/wayland/common/wayland_util.h3
-rw-r--r--chromium/ui/ozone/platform/wayland/emulate/wayland_input_emulate.cc5
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc50
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h5
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc24
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h7
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.cc4
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.h3
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc11
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h6
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc4
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h3
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.cc4
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc8
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory.h5
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc24
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h5
-rw-r--r--chromium/ui/ozone/platform/wayland/host/DEPS4
-rw-r--r--chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.cc6
-rw-r--r--chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.h3
-rw-r--r--chromium/ui/ozone/platform/wayland/host/gtk_shell1.cc23
-rw-r--r--chromium/ui/ozone/platform/wayland/host/gtk_shell1.h32
-rw-r--r--chromium/ui/ozone/platform/wayland/host/gtk_surface1.cc21
-rw-r--r--chromium/ui/ozone/platform/wayland/host/gtk_surface1.h28
-rw-r--r--chromium/ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.h33
-rw-r--r--chromium/ui/ozone/platform/wayland/host/linux_ui_delegate_wayland.cc (renamed from chromium/ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.cc)15
-rw-r--r--chromium/ui/ozone/platform/wayland/host/linux_ui_delegate_wayland.h33
-rw-r--r--chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy.h8
-rw-r--r--chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.cc8
-rw-r--r--chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.h2
-rw-r--r--chromium/ui/ozone/platform/wayland/host/shell_popup_wrapper.cc70
-rw-r--r--chromium/ui/ozone/platform/wayland/host/shell_popup_wrapper.h19
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.cc51
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.h6
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc39
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h3
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_clipboard.cc57
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_clipboard.h4
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc40
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_connection.cc218
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_connection.h56
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_connection_unittest.cc7
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_cursor.cc7
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.cc8
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.h3
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory_unittest.cc107
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_data_device.cc4
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_data_device_base.cc3
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc41
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc84
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_data_source.cc2
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_drm.cc4
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_event_source.cc94
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_event_source.h43
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_event_source_unittest.cc7
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_event_watcher.cc152
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_event_watcher.h50
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.cc14
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc7
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_keyboard.cc2
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_keyboard_unittest.cc7
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_output.h2
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_pointer.cc7
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_pointer.h5
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_pointer_unittest.cc62
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_popup.cc65
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_popup.h3
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_screen.h6
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc14
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_shm.h1
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_shm_buffer.h3
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_surface.cc7
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc66
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.h21
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_touch_unittest.cc7
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_window.cc155
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_window.h26
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc6
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc74
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_window_factory.cc6
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc8
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_window_unittest.cc285
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_zaura_shell.h1
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_zaura_shell_unittest.cc4
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.cc8
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h4
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc6
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h4
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc100
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.h79
-rw-r--r--chromium/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc11
-rw-r--r--chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h1
-rw-r--r--chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h2
-rw-r--r--chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.cc6
-rw-r--r--chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.h6
-rw-r--r--chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.h6
-rw-r--r--chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_offer.h6
-rw-r--r--chromium/ui/ozone/platform/wayland/host/zxdg_popup_v6_wrapper_impl.cc11
-rw-r--r--chromium/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h1
-rw-r--r--chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc22
-rw-r--r--chromium/ui/ozone/platform/wayland/ozone_platform_wayland.h6
-rw-r--r--chromium/ui/ozone/platform/wayland/test/mock_surface.h2
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_data_offer.cc3
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_output.cc2
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_output.h7
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_subcompositor.h1
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_subsurface.h2
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc10
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.h13
-rw-r--r--chromium/ui/ozone/platform/wayland/test/wayland_test.cc4
-rw-r--r--chromium/ui/ozone/platform/wayland/test/wayland_test.h5
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc105
-rw-r--r--chromium/ui/ozone/platform/windows/windows_surface_factory.h1
-rw-r--r--chromium/ui/ozone/platform/windows/windows_window_manager.h3
-rw-r--r--chromium/ui/ozone/platform/x11/BUILD.gn7
-rw-r--r--chromium/ui/ozone/platform/x11/DEPS2
-rw-r--r--chromium/ui/ozone/platform/x11/gl_egl_utility_x11.cc9
-rw-r--r--chromium/ui/ozone/platform/x11/gl_egl_utility_x11.h3
-rw-r--r--chromium/ui/ozone/platform/x11/gl_surface_egl_readback_x11.cc1
-rw-r--r--chromium/ui/ozone/platform/x11/ozone_platform_x11.cc61
-rw-r--r--chromium/ui/ozone/platform/x11/x11_clipboard_ozone.cc10
-rw-r--r--chromium/ui/ozone/platform/x11/x11_clipboard_ozone.h7
-rw-r--r--chromium/ui/ozone/platform/x11/x11_keyboard_hook_ozone.cc24
-rw-r--r--chromium/ui/ozone/platform/x11/x11_keyboard_hook_ozone.h29
-rw-r--r--chromium/ui/ozone/platform/x11/x11_screen_ozone.cc10
-rw-r--r--chromium/ui/ozone/platform/x11/x11_surface_factory.cc5
-rw-r--r--chromium/ui/ozone/platform/x11/x11_surface_factory.h5
-rw-r--r--chromium/ui/ozone/platform_constructor_list.h1
-rw-r--r--chromium/ui/ozone/public/gpu_platform_support_host.cc2
-rw-r--r--chromium/ui/ozone/public/gpu_platform_support_host.h7
-rw-r--r--chromium/ui/ozone/public/input_controller.cc4
-rw-r--r--chromium/ui/ozone/public/input_controller.h10
-rw-r--r--chromium/ui/ozone/public/mojom/wayland/wayland_buffer_manager.mojom4
-rw-r--r--chromium/ui/ozone/public/overlay_surface_candidate.h13
-rw-r--r--chromium/ui/ozone/public/ozone_gpu_test_helper.h6
-rw-r--r--chromium/ui/ozone/public/ozone_platform.cc17
-rw-r--r--chromium/ui/ozone/public/ozone_platform.h24
-rw-r--r--chromium/ui/ozone/public/platform_clipboard.h17
-rw-r--r--chromium/ui/ozone/public/platform_gl_egl_utility.cc9
-rw-r--r--chromium/ui/ozone/public/platform_gl_egl_utility.h9
-rw-r--r--chromium/ui/ozone/public/platform_keyboard_hook.cc18
-rw-r--r--chromium/ui/ozone/public/platform_keyboard_hook.h36
-rw-r--r--chromium/ui/ozone/public/platform_user_input_monitor.h1
-rw-r--r--chromium/ui/ozone/public/surface_factory_ozone.cc5
-rw-r--r--chromium/ui/ozone/public/surface_factory_ozone.h7
-rw-r--r--chromium/ui/ozone/public/swap_completion_callback.h5
-rw-r--r--chromium/ui/ozone/test/mock_platform_window_delegate.h4
-rw-r--r--chromium/ui/platform_window/extensions/wayland_extension.h5
-rw-r--r--chromium/ui/platform_window/platform_window.cc2
-rw-r--r--chromium/ui/platform_window/platform_window.h19
-rw-r--r--chromium/ui/platform_window/platform_window_delegate.cc8
-rw-r--r--chromium/ui/platform_window/platform_window_delegate.h6
-rw-r--r--chromium/ui/platform_window/platform_window_init_properties.h4
-rw-r--r--chromium/ui/platform_window/stub/stub_window.cc4
-rw-r--r--chromium/ui/platform_window/stub/stub_window.h2
-rw-r--r--chromium/ui/platform_window/stub/stub_window_export.h2
-rw-r--r--chromium/ui/platform_window/win/win_window.cc18
-rw-r--r--chromium/ui/platform_window/win/win_window.h8
-rw-r--r--chromium/ui/platform_window/win/win_window_export.h3
-rw-r--r--chromium/ui/platform_window/wm/BUILD.gn2
-rw-r--r--chromium/ui/platform_window/wm/wm_drag_handler.h7
-rw-r--r--chromium/ui/platform_window/x11/BUILD.gn15
-rw-r--r--chromium/ui/platform_window/x11/x11_topmost_window_finder.cc94
-rw-r--r--chromium/ui/platform_window/x11/x11_topmost_window_finder.h6
-rw-r--r--chromium/ui/platform_window/x11/x11_window.cc74
-rw-r--r--chromium/ui/platform_window/x11/x11_window.h21
-rw-r--r--chromium/ui/platform_window/x11/x11_window_export.h3
-rw-r--r--chromium/ui/resources/DIR_METADATA3
-rw-r--r--chromium/ui/resources/default_100_percent/common/pointers/sb_horizontal_double_arrow.png (renamed from chromium/ui/resources/default_100_percent/common/pointers/sb_h_double_arrow.png)bin368 -> 368 bytes
-rw-r--r--chromium/ui/resources/default_100_percent/common/pointers/sb_horizontal_double_arrow_big.png (renamed from chromium/ui/resources/default_100_percent/common/pointers/sb_h_double_arrow_big.png)bin827 -> 827 bytes
-rw-r--r--chromium/ui/resources/default_100_percent/common/pointers/sb_vertical_double_arrow.png (renamed from chromium/ui/resources/default_100_percent/common/pointers/sb_v_double_arrow.png)bin381 -> 381 bytes
-rw-r--r--chromium/ui/resources/default_100_percent/common/pointers/sb_vertical_double_arrow_big.png (renamed from chromium/ui/resources/default_100_percent/common/pointers/sb_v_double_arrow_big.png)bin800 -> 800 bytes
-rw-r--r--chromium/ui/resources/default_200_percent/common/pointers/sb_horizontal_double_arrow.png (renamed from chromium/ui/resources/default_200_percent/common/pointers/sb_h_double_arrow.png)bin800 -> 800 bytes
-rw-r--r--chromium/ui/resources/default_200_percent/common/pointers/sb_vertical_double_arrow.png (renamed from chromium/ui/resources/default_200_percent/common/pointers/sb_v_double_arrow.png)bin808 -> 808 bytes
-rw-r--r--chromium/ui/resources/ui_resources.grd32
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog.h1
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_android.h7
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_lacros.cc9
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_win.cc1
-rw-r--r--chromium/ui/shell_dialogs/selected_file_info.h6
-rw-r--r--chromium/ui/snapshot/screenshot_grabber.h1
-rw-r--r--chromium/ui/snapshot/snapshot.h1
-rw-r--r--chromium/ui/snapshot/snapshot_aura_unittest.cc3
-rw-r--r--chromium/ui/snapshot/snapshot_export.h6
-rw-r--r--chromium/ui/snapshot/snapshot_win.cc1
-rw-r--r--chromium/ui/strings/translations/ui_strings_az.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_gu.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_sv.xtb4
-rw-r--r--chromium/ui/strings/translations/ui_strings_ta.xtb4
-rw-r--r--chromium/ui/strings/translations/ui_strings_te.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_uz.xtb2
-rw-r--r--chromium/ui/strings/ui_strings.grd2
-rw-r--r--chromium/ui/strings/ui_strings_grd/IDS_CLIPBOARD_HISTORY_MENU_PNG_IMAGE.png.sha1 (renamed from chromium/ui/strings/ui_strings_grd/IDS_CLIPBOARD_HISTORY_MENU_BITMAP_IMAGE.png.sha1)0
-rw-r--r--chromium/ui/surface/DIR_METADATA3
-rw-r--r--chromium/ui/touch_selection/DEPS1
-rw-r--r--chromium/ui/touch_selection/selection_event_type.h6
-rw-r--r--chromium/ui/touch_selection/touch_handle_drawable_aura.cc1
-rw-r--r--chromium/ui/touch_selection/touch_handle_orientation.h6
-rw-r--r--chromium/ui/touch_selection/touch_selection_draggable.h6
-rw-r--r--chromium/ui/views/.clang-tidy1
-rw-r--r--chromium/ui/views/BUILD.gn48
-rw-r--r--chromium/ui/views/accessibility/ax_aura_obj_cache.cc21
-rw-r--r--chromium/ui/views/accessibility/ax_aura_obj_cache.h5
-rw-r--r--chromium/ui/views/accessibility/ax_aura_obj_cache_unittest.cc33
-rw-r--r--chromium/ui/views/accessibility/ax_event_manager.cc6
-rw-r--r--chromium/ui/views/accessibility/ax_event_manager.h3
-rw-r--r--chromium/ui/views/accessibility/ax_event_observer.h3
-rw-r--r--chromium/ui/views/accessibility/ax_virtual_view.cc24
-rw-r--r--chromium/ui/views/accessibility/ax_virtual_view.h24
-rw-r--r--chromium/ui/views/accessibility/ax_virtual_view_unittest.cc15
-rw-r--r--chromium/ui/views/accessibility/ax_virtual_view_wrapper.cc14
-rw-r--r--chromium/ui/views/accessibility/ax_virtual_view_wrapper.h2
-rw-r--r--chromium/ui/views/accessibility/ax_window_obj_wrapper.cc4
-rw-r--r--chromium/ui/views/accessibility/test_list_grid_view.cc16
-rw-r--r--chromium/ui/views/accessibility/test_list_grid_view.h8
-rw-r--r--chromium/ui/views/accessibility/view_accessibility.cc6
-rw-r--r--chromium/ui/views/accessibility/view_accessibility.h6
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc26
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate.h12
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate_auralinux_unittest.cc10
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate_unittest.cc69
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate_win.cc1
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate_win_unittest.cc2
-rw-r--r--chromium/ui/views/accessibility/widget_ax_tree_id_map.cc3
-rw-r--r--chromium/ui/views/accessible_pane_view.cc2
-rw-r--r--chromium/ui/views/accessible_pane_view_unittest.cc2
-rw-r--r--chromium/ui/views/animation/animation_delegate_views.h1
-rw-r--r--chromium/ui/views/animation/bounds_animator.h2
-rw-r--r--chromium/ui/views/animation/bubble_slide_animator.cc4
-rw-r--r--chromium/ui/views/animation/compositor_animation_runner.h1
-rw-r--r--chromium/ui/views/animation/flood_fill_ink_drop_ripple.h2
-rw-r--r--chromium/ui/views/animation/ink_drop.cc94
-rw-r--r--chromium/ui/views/animation/ink_drop.h50
-rw-r--r--chromium/ui/views/animation/ink_drop_event_handler.cc4
-rw-r--r--chromium/ui/views/animation/ink_drop_event_handler.h2
-rw-r--r--chromium/ui/views/animation/ink_drop_highlight_observer.h1
-rw-r--r--chromium/ui/views/animation/ink_drop_host_view.cc317
-rw-r--r--chromium/ui/views/animation/ink_drop_host_view.h247
-rw-r--r--chromium/ui/views/animation/ink_drop_host_view_unittest.cc158
-rw-r--r--chromium/ui/views/animation/ink_drop_impl.cc28
-rw-r--r--chromium/ui/views/animation/ink_drop_impl.h51
-rw-r--r--chromium/ui/views/animation/ink_drop_impl_unittest.cc37
-rw-r--r--chromium/ui/views/animation/ink_drop_observer.h1
-rw-r--r--chromium/ui/views/animation/ink_drop_ripple_observer.h1
-rw-r--r--chromium/ui/views/animation/ink_drop_unittest.cc5
-rw-r--r--chromium/ui/views/animation/ink_drop_util.cc5
-rw-r--r--chromium/ui/views/animation/installable_ink_drop.cc21
-rw-r--r--chromium/ui/views/animation/installable_ink_drop.h12
-rw-r--r--chromium/ui/views/animation/installable_ink_drop_animator.h2
-rw-r--r--chromium/ui/views/animation/installable_ink_drop_painter.h2
-rw-r--r--chromium/ui/views/animation/installable_ink_drop_unittest.cc8
-rw-r--r--chromium/ui/views/animation/scroll_animator.cc1
-rw-r--r--chromium/ui/views/animation/scroll_animator.h3
-rw-r--r--chromium/ui/views/animation/slide_out_controller_unittest.cc5
-rw-r--r--chromium/ui/views/background.cc3
-rw-r--r--chromium/ui/views/border.cc1
-rw-r--r--chromium/ui/views/border_unittest.cc1
-rw-r--r--chromium/ui/views/bubble/bubble_border.cc87
-rw-r--r--chromium/ui/views/bubble/bubble_border.h39
-rw-r--r--chromium/ui/views/bubble/bubble_dialog_delegate_view.cc96
-rw-r--r--chromium/ui/views/bubble/bubble_dialog_delegate_view.h55
-rw-r--r--chromium/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc40
-rw-r--r--chromium/ui/views/bubble/bubble_dialog_model_host.cc49
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view.cc46
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view.h7
-rw-r--r--chromium/ui/views/bubble/footnote_container_view.cc13
-rw-r--r--chromium/ui/views/bubble/info_bubble.cc2
-rw-r--r--chromium/ui/views/bubble/tooltip_icon.cc11
-rw-r--r--chromium/ui/views/bubble/tooltip_icon.h1
-rw-r--r--chromium/ui/views/button_drag_utils.cc1
-rw-r--r--chromium/ui/views/cocoa/drag_drop_client_mac_unittest.mm4
-rw-r--r--chromium/ui/views/cocoa/native_widget_mac_ns_window_host.h7
-rw-r--r--chromium/ui/views/cocoa/native_widget_mac_ns_window_host.mm27
-rw-r--r--chromium/ui/views/color_chooser/color_chooser_unittest.cc1
-rw-r--r--chromium/ui/views/color_chooser/color_chooser_view.cc4
-rw-r--r--chromium/ui/views/controls/button/button.cc137
-rw-r--r--chromium/ui/views/controls/button/button.h19
-rw-r--r--chromium/ui/views/controls/button/button_controller.cc7
-rw-r--r--chromium/ui/views/controls/button/button_unittest.cc66
-rw-r--r--chromium/ui/views/controls/button/checkbox.cc42
-rw-r--r--chromium/ui/views/controls/button/checkbox.h3
-rw-r--r--chromium/ui/views/controls/button/image_button.cc25
-rw-r--r--chromium/ui/views/controls/button/image_button_factory.cc7
-rw-r--r--chromium/ui/views/controls/button/image_button_factory.h2
-rw-r--r--chromium/ui/views/controls/button/image_button_factory_unittest.cc4
-rw-r--r--chromium/ui/views/controls/button/label_button.cc20
-rw-r--r--chromium/ui/views/controls/button/label_button.h4
-rw-r--r--chromium/ui/views/controls/button/label_button_label.cc8
-rw-r--r--chromium/ui/views/controls/button/label_button_label.h8
-rw-r--r--chromium/ui/views/controls/button/label_button_unittest.cc36
-rw-r--r--chromium/ui/views/controls/button/md_text_button.cc42
-rw-r--r--chromium/ui/views/controls/button/md_text_button.h21
-rw-r--r--chromium/ui/views/controls/button/menu_button.cc3
-rw-r--r--chromium/ui/views/controls/button/menu_button.h2
-rw-r--r--chromium/ui/views/controls/button/menu_button_controller.cc30
-rw-r--r--chromium/ui/views/controls/button/menu_button_unittest.cc62
-rw-r--r--chromium/ui/views/controls/button/radio_button.cc19
-rw-r--r--chromium/ui/views/controls/button/radio_button.h1
-rw-r--r--chromium/ui/views/controls/button/toggle_button.cc156
-rw-r--r--chromium/ui/views/controls/button/toggle_button.h40
-rw-r--r--chromium/ui/views/controls/button/toggle_button_unittest.cc25
-rw-r--r--chromium/ui/views/controls/combobox/combobox.cc62
-rw-r--r--chromium/ui/views/controls/combobox/combobox.h2
-rw-r--r--chromium/ui/views/controls/combobox/combobox_unittest.cc8
-rw-r--r--chromium/ui/views/controls/dot_indicator.cc2
-rw-r--r--chromium/ui/views/controls/editable_combobox/editable_combobox.cc76
-rw-r--r--chromium/ui/views/controls/editable_combobox/editable_combobox.h4
-rw-r--r--chromium/ui/views/controls/editable_combobox/editable_combobox_unittest.cc100
-rw-r--r--chromium/ui/views/controls/focus_ring.cc79
-rw-r--r--chromium/ui/views/controls/focus_ring.h18
-rw-r--r--chromium/ui/views/controls/focusable_border.cc2
-rw-r--r--chromium/ui/views/controls/focusable_border.h6
-rw-r--r--chromium/ui/views/controls/highlight_path_generator.cc24
-rw-r--r--chromium/ui/views/controls/highlight_path_generator.h20
-rw-r--r--chromium/ui/views/controls/image_view.cc128
-rw-r--r--chromium/ui/views/controls/image_view.h38
-rw-r--r--chromium/ui/views/controls/label.cc57
-rw-r--r--chromium/ui/views/controls/label.h6
-rw-r--r--chromium/ui/views/controls/label_unittest.cc86
-rw-r--r--chromium/ui/views/controls/link.cc13
-rw-r--r--chromium/ui/views/controls/link.h4
-rw-r--r--chromium/ui/views/controls/link_unittest.cc1
-rw-r--r--chromium/ui/views/controls/menu/menu_controller.cc38
-rw-r--r--chromium/ui/views/controls/menu/menu_controller.h6
-rw-r--r--chromium/ui/views/controls/menu/menu_controller_unittest.cc23
-rw-r--r--chromium/ui/views/controls/menu/menu_host.cc17
-rw-r--r--chromium/ui/views/controls/menu/menu_host.h3
-rw-r--r--chromium/ui/views/controls/menu/menu_host_root_view.cc2
-rw-r--r--chromium/ui/views/controls/menu/menu_image_util.cc3
-rw-r--r--chromium/ui/views/controls/menu/menu_item_view.cc139
-rw-r--r--chromium/ui/views/controls/menu/menu_item_view.h32
-rw-r--r--chromium/ui/views/controls/menu/menu_item_view_unittest.cc49
-rw-r--r--chromium/ui/views/controls/menu/menu_model_adapter.cc34
-rw-r--r--chromium/ui/views/controls/menu/menu_runner.cc13
-rw-r--r--chromium/ui/views/controls/menu/menu_runner_cocoa_unittest.mm1
-rw-r--r--chromium/ui/views/controls/menu/menu_runner_impl.cc5
-rw-r--r--chromium/ui/views/controls/menu/menu_runner_impl_cocoa.mm5
-rw-r--r--chromium/ui/views/controls/menu/menu_runner_unittest.cc10
-rw-r--r--chromium/ui/views/controls/menu/menu_scroll_view_container.cc25
-rw-r--r--chromium/ui/views/controls/menu/menu_separator.cc2
-rw-r--r--chromium/ui/views/controls/menu/menu_separator.h2
-rw-r--r--chromium/ui/views/controls/menu/submenu_view.cc2
-rw-r--r--chromium/ui/views/controls/message_box_view.cc24
-rw-r--r--chromium/ui/views/controls/message_box_view_unittest.cc16
-rw-r--r--chromium/ui/views/controls/native/native_view_host.cc2
-rw-r--r--chromium/ui/views/controls/native/native_view_host_aura.cc5
-rw-r--r--chromium/ui/views/controls/native/native_view_host_mac.mm1
-rw-r--r--chromium/ui/views/controls/prefix_selector.cc9
-rw-r--r--chromium/ui/views/controls/prefix_selector.h5
-rw-r--r--chromium/ui/views/controls/progress_bar.cc7
-rw-r--r--chromium/ui/views/controls/progress_bar.h6
-rw-r--r--chromium/ui/views/controls/resize_area.cc3
-rw-r--r--chromium/ui/views/controls/resize_area.h1
-rw-r--r--chromium/ui/views/controls/resize_area_unittest.cc6
-rw-r--r--chromium/ui/views/controls/scroll_view.cc190
-rw-r--r--chromium/ui/views/controls/scroll_view.h62
-rw-r--r--chromium/ui/views/controls/scroll_view_unittest.cc79
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc56
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar_button.h54
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc3
-rw-r--r--chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm3
-rw-r--r--chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc4
-rw-r--r--chromium/ui/views/controls/scrollbar/scroll_bar.cc61
-rw-r--r--chromium/ui/views/controls/scrollbar/scroll_bar.h29
-rw-r--r--chromium/ui/views/controls/scrollbar/scroll_bar_button.cc120
-rw-r--r--chromium/ui/views/controls/scrollbar/scroll_bar_button.h72
-rw-r--r--chromium/ui/views/controls/scrollbar/scroll_bar_button_unittest.cc (renamed from chromium/ui/views/controls/scrollbar/base_scroll_bar_button_unittest.cc)25
-rw-r--r--chromium/ui/views/controls/scrollbar/scroll_bar_views.cc107
-rw-r--r--chromium/ui/views/controls/scrollbar/scroll_bar_views.h2
-rw-r--r--chromium/ui/views/controls/scrollbar/scrollbar_unittest.cc2
-rw-r--r--chromium/ui/views/controls/separator.cc6
-rw-r--r--chromium/ui/views/controls/separator.h5
-rw-r--r--chromium/ui/views/controls/separator_unittest.cc125
-rw-r--r--chromium/ui/views/controls/slider.cc5
-rw-r--r--chromium/ui/views/controls/slider_unittest.cc7
-rw-r--r--chromium/ui/views/controls/styled_label.cc8
-rw-r--r--chromium/ui/views/controls/styled_label.h16
-rw-r--r--chromium/ui/views/controls/styled_label_unittest.cc4
-rw-r--r--chromium/ui/views/controls/tabbed_pane/DIR_METADATA3
-rw-r--r--chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc25
-rw-r--r--chromium/ui/views/controls/table/table_header.cc3
-rw-r--r--chromium/ui/views/controls/table/table_header.h2
-rw-r--r--chromium/ui/views/controls/table/table_view.cc77
-rw-r--r--chromium/ui/views/controls/table/table_view.h36
-rw-r--r--chromium/ui/views/controls/table/table_view_unittest.cc36
-rw-r--r--chromium/ui/views/controls/textarea/textarea.cc2
-rw-r--r--chromium/ui/views/controls/textarea/textarea_unittest.cc20
-rw-r--r--chromium/ui/views/controls/textfield/DIR_METADATA3
-rw-r--r--chromium/ui/views/controls/textfield/textfield.cc111
-rw-r--r--chromium/ui/views/controls/textfield/textfield.h33
-rw-r--r--chromium/ui/views/controls/textfield/textfield_model_unittest.cc642
-rw-r--r--chromium/ui/views/controls/textfield/textfield_unittest.cc595
-rw-r--r--chromium/ui/views/controls/textfield/textfield_unittest.h6
-rw-r--r--chromium/ui/views/controls/theme_tracking_image_view.cc2
-rw-r--r--chromium/ui/views/controls/throbber.cc2
-rw-r--r--chromium/ui/views/controls/tree/tree_view.cc37
-rw-r--r--chromium/ui/views/controls/tree/tree_view.h8
-rw-r--r--chromium/ui/views/controls/tree/tree_view_unittest.cc4
-rw-r--r--chromium/ui/views/controls/views_text_services_context_menu_base.cc9
-rw-r--r--chromium/ui/views/controls/views_text_services_context_menu_base.h2
-rw-r--r--chromium/ui/views/controls/webview/web_dialog_view.cc2
-rw-r--r--chromium/ui/views/controls/webview/web_dialog_view.h2
-rw-r--r--chromium/ui/views/controls/webview/webview.cc3
-rw-r--r--chromium/ui/views/corewm/DEPS4
-rw-r--r--chromium/ui/views/corewm/tooltip_aura.cc8
-rw-r--r--chromium/ui/views/corewm/tooltip_aura.h1
-rw-r--r--chromium/ui/views/corewm/tooltip_controller.cc53
-rw-r--r--chromium/ui/views/corewm/tooltip_controller_unittest.cc263
-rw-r--r--chromium/ui/views/corewm/tooltip_state_manager.cc13
-rw-r--r--chromium/ui/views/corewm/tooltip_state_manager.h10
-rw-r--r--chromium/ui/views/corewm/tooltip_win.h2
-rw-r--r--chromium/ui/views/debug/debugger_utils.cc6
-rw-r--r--chromium/ui/views/debug/debugger_utils.h4
-rw-r--r--chromium/ui/views/debug_utils.cc1
-rw-r--r--chromium/ui/views/examples/BUILD.gn2
-rw-r--r--chromium/ui/views/examples/animation_example.cc161
-rw-r--r--chromium/ui/views/examples/animation_example.h27
-rw-r--r--chromium/ui/views/examples/button_example.cc16
-rw-r--r--chromium/ui/views/examples/checkbox_example.cc1
-rw-r--r--chromium/ui/views/examples/colored_dialog_example.cc2
-rw-r--r--chromium/ui/views/examples/create_examples.cc3
-rw-r--r--chromium/ui/views/examples/create_examples.h2
-rw-r--r--chromium/ui/views/examples/dialog_example.cc12
-rw-r--r--chromium/ui/views/examples/examples_main_proc.cc2
-rw-r--r--chromium/ui/views/examples/examples_window.cc1
-rw-r--r--chromium/ui/views/examples/examples_with_content_main.cc6
-rw-r--r--chromium/ui/views/examples/label_example.cc16
-rw-r--r--chromium/ui/views/examples/layout_example_base.cc15
-rw-r--r--chromium/ui/views/examples/login_bubble_dialog_example.cc5
-rw-r--r--chromium/ui/views/examples/menu_example.cc1
-rw-r--r--chromium/ui/views/examples/message_box_example.cc3
-rw-r--r--chromium/ui/views/examples/message_box_example.h1
-rw-r--r--chromium/ui/views/examples/multiline_example.cc7
-rw-r--r--chromium/ui/views/examples/native_theme_example.cc40
-rw-r--r--chromium/ui/views/examples/radio_button_example.cc1
-rw-r--r--chromium/ui/views/examples/scroll_view_example.cc1
-rw-r--r--chromium/ui/views/examples/scroll_view_example.h1
-rw-r--r--chromium/ui/views/examples/tabbed_pane_example.cc1
-rw-r--r--chromium/ui/views/examples/text_example.cc34
-rw-r--r--chromium/ui/views/examples/text_example.h2
-rw-r--r--chromium/ui/views/examples/textarea_example.cc18
-rw-r--r--chromium/ui/views/examples/textfield_example.h1
-rw-r--r--chromium/ui/views/examples/toggle_button_example.cc1
-rw-r--r--chromium/ui/views/focus/focus_manager.cc16
-rw-r--r--chromium/ui/views/focus/focus_manager.h8
-rw-r--r--chromium/ui/views/focus/focus_manager_unittest.cc2
-rw-r--r--chromium/ui/views/focus/focus_search.cc2
-rw-r--r--chromium/ui/views/focus/focus_traversal_unittest.cc4
-rw-r--r--chromium/ui/views/interaction/OWNERS1
-rw-r--r--chromium/ui/views/interaction/element_tracker_views.cc256
-rw-r--r--chromium/ui/views/interaction/element_tracker_views.h97
-rw-r--r--chromium/ui/views/interaction/element_tracker_views_unittest.cc986
-rw-r--r--chromium/ui/views/interaction/interaction_sequence_views.cc44
-rw-r--r--chromium/ui/views/interaction/interaction_sequence_views.h33
-rw-r--r--chromium/ui/views/interaction/interaction_sequence_views_unittest.cc618
-rw-r--r--chromium/ui/views/layout/animating_layout_manager.cc30
-rw-r--r--chromium/ui/views/layout/animating_layout_manager_unittest.cc82
-rw-r--r--chromium/ui/views/layout/box_layout_view.cc35
-rw-r--r--chromium/ui/views/layout/box_layout_view.h2
-rw-r--r--chromium/ui/views/layout/composite_layout_tests.cc6
-rw-r--r--chromium/ui/views/layout/flex_layout.cc32
-rw-r--r--chromium/ui/views/layout/flex_layout.h6
-rw-r--r--chromium/ui/views/layout/flex_layout_types.cc3
-rw-r--r--chromium/ui/views/layout/flex_layout_types.h2
-rw-r--r--chromium/ui/views/layout/flex_layout_unittest.cc22
-rw-r--r--chromium/ui/views/layout/flex_layout_view.cc30
-rw-r--r--chromium/ui/views/layout/flex_layout_view.h2
-rw-r--r--chromium/ui/views/layout/layout_manager_base.h26
-rw-r--r--chromium/ui/views/layout/layout_manager_base_unittest.cc2
-rw-r--r--chromium/ui/views/layout/layout_provider.cc9
-rw-r--r--chromium/ui/views/layout/layout_provider.h13
-rw-r--r--chromium/ui/views/layout/layout_types.h5
-rw-r--r--chromium/ui/views/layout/normalized_geometry.h2
-rw-r--r--chromium/ui/views/linux_ui/linux_ui.cc12
-rw-r--r--chromium/ui/views/linux_ui/linux_ui.h2
-rw-r--r--chromium/ui/views/masked_targeter_delegate.cc1
-rw-r--r--chromium/ui/views/metadata/type_conversion.cc640
-rw-r--r--chromium/ui/views/metadata/type_conversion.h355
-rw-r--r--chromium/ui/views/metadata/type_conversion_unittest.cc259
-rw-r--r--chromium/ui/views/metadata/view_factory.h25
-rw-r--r--chromium/ui/views/metadata/view_factory_internal.h5
-rw-r--r--chromium/ui/views/selection_controller.cc13
-rw-r--r--chromium/ui/views/style/platform_style.cc5
-rw-r--r--chromium/ui/views/style/platform_style.h4
-rw-r--r--chromium/ui/views/style/platform_style_mac.mm1
-rw-r--r--chromium/ui/views/style/typography_provider.cc4
-rw-r--r--chromium/ui/views/touchui/touch_selection_controller_impl.cc16
-rw-r--r--chromium/ui/views/touchui/touch_selection_menu_runner_views.h1
-rw-r--r--chromium/ui/views/touchui/touch_selection_menu_views.cc2
-rw-r--r--chromium/ui/views/vector_icons/submenu_arrow.icon19
-rw-r--r--chromium/ui/views/view.cc88
-rw-r--r--chromium/ui/views/view.h77
-rw-r--r--chromium/ui/views/view_class_properties.cc4
-rw-r--r--chromium/ui/views/view_class_properties.h6
-rw-r--r--chromium/ui/views/view_observer.h6
-rw-r--r--chromium/ui/views/view_unittest.cc23
-rw-r--r--chromium/ui/views/view_unittest_mac.mm10
-rw-r--r--chromium/ui/views/view_utils.cc6
-rw-r--r--chromium/ui/views/view_utils.h6
-rw-r--r--chromium/ui/views/views_delegate.cc2
-rw-r--r--chromium/ui/views/views_delegate.h4
-rw-r--r--chromium/ui/views/views_features.cc10
-rw-r--r--chromium/ui/views/views_features.h2
-rw-r--r--chromium/ui/views/views_test_suite.h16
-rw-r--r--chromium/ui/views/widget/any_widget_observer_unittest.cc8
-rw-r--r--chromium/ui/views/widget/ax_native_widget_mac_unittest.mm13
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc34
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h25
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc69
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc15
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h15
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc33
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h3
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen.cc24
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen.h8
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_linux.cc6
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc6
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_position_client.cc2
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc6
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc12
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h2
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.cc3
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.h7
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc30
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h7
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc100
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h25
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_unittest.cc72
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc14
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h2
-rw-r--r--chromium/ui/views/widget/desktop_aura/window_shape_updater.cc80
-rw-r--r--chromium/ui/views/widget/desktop_aura/window_shape_updater.h49
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_drag_drop_client_unittest.cc69
-rw-r--r--chromium/ui/views/widget/drop_helper.cc26
-rw-r--r--chromium/ui/views/widget/drop_helper.h11
-rw-r--r--chromium/ui/views/widget/native_widget_aura.cc38
-rw-r--r--chromium/ui/views/widget/native_widget_aura.h5
-rw-r--r--chromium/ui/views/widget/native_widget_aura_unittest.cc89
-rw-r--r--chromium/ui/views/widget/native_widget_mac.h1
-rw-r--r--chromium/ui/views/widget/native_widget_mac.mm18
-rw-r--r--chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm36
-rw-r--r--chromium/ui/views/widget/native_widget_mac_unittest.mm101
-rw-r--r--chromium/ui/views/widget/native_widget_private.h1
-rw-r--r--chromium/ui/views/widget/root_view.cc50
-rw-r--r--chromium/ui/views/widget/root_view.h10
-rw-r--r--chromium/ui/views/widget/root_view_unittest.cc98
-rw-r--r--chromium/ui/views/widget/tooltip_manager.h1
-rw-r--r--chromium/ui/views/widget/widget.cc160
-rw-r--r--chromium/ui/views/widget/widget.h70
-rw-r--r--chromium/ui/views/widget/widget_delegate.cc2
-rw-r--r--chromium/ui/views/widget/widget_delegate.h4
-rw-r--r--chromium/ui/views/widget/widget_hwnd_utils.cc4
-rw-r--r--chromium/ui/views/widget/widget_interactive_uitest.cc49
-rw-r--r--chromium/ui/views/widget/widget_observer.h2
-rw-r--r--chromium/ui/views/widget/widget_unittest.cc275
-rw-r--r--chromium/ui/views/widget/widget_utils.h2
-rw-r--r--chromium/ui/views/widget/window_reorderer.cc1
-rw-r--r--chromium/ui/views/win/fullscreen_handler.h1
-rw-r--r--chromium/ui/views/win/hwnd_message_handler.cc41
-rw-r--r--chromium/ui/views/win/hwnd_message_handler.h13
-rw-r--r--chromium/ui/views/win/pen_event_processor.cc9
-rw-r--r--chromium/ui/views/win/pen_event_processor.h4
-rw-r--r--chromium/ui/views/win/scoped_enable_unadjusted_mouse_events_win.cc1
-rw-r--r--chromium/ui/views/window/client_view.cc4
-rw-r--r--chromium/ui/views/window/custom_frame_view.cc1
-rw-r--r--chromium/ui/views/window/custom_frame_view_unittest.cc4
-rw-r--r--chromium/ui/views/window/dialog_client_view.cc4
-rw-r--r--chromium/ui/views/window/dialog_client_view.h1
-rw-r--r--chromium/ui/views/window/dialog_delegate.cc4
-rw-r--r--chromium/ui/views/window/dialog_delegate.h8
-rw-r--r--chromium/ui/views/window/dialog_delegate_unittest.cc12
-rw-r--r--chromium/ui/views/window/frame_caption_button.cc97
-rw-r--r--chromium/ui/views/window/frame_caption_button.h13
-rw-r--r--chromium/ui/views/window/native_frame_view.cc2
-rw-r--r--chromium/ui/views/window/native_frame_view.h2
-rw-r--r--chromium/ui/views/window/non_client_view.cc62
-rw-r--r--chromium/ui/views/window/non_client_view.h33
-rw-r--r--chromium/ui/views/window/non_client_view_unittest.cc102
-rw-r--r--chromium/ui/views_content_client/views_content_client_main_parts.cc2
-rw-r--r--chromium/ui/views_content_client/views_content_client_main_parts.h3
-rw-r--r--chromium/ui/views_content_client/views_content_client_main_parts_desktop_aura.cc12
-rw-r--r--chromium/ui/views_content_client/views_content_client_main_parts_mac.mm2
-rw-r--r--chromium/ui/views_content_client/views_content_main_delegate.cc6
-rw-r--r--chromium/ui/views_content_client/views_content_main_delegate.h2
-rw-r--r--chromium/ui/web_dialogs/web_dialog_ui.h2
-rw-r--r--chromium/ui/webui/PLATFORM_OWNERS1
-rw-r--r--chromium/ui/webui/mojo_bubble_web_ui_controller.h1
-rw-r--r--chromium/ui/webui/resources/BUILD.gn135
-rw-r--r--chromium/ui/webui/resources/cr_components/BUILD.gn34
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn39
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html137
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.js80
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_verification_page.html40
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_verification_page.js13
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/base_page.html12
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/button_bar.html6
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.html71
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.js (renamed from chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_popup.js)35
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_popup.html96
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.html1
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.js15
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup_icons.html1
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/confirmation_code_page.html8
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.html19
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.js60
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_utils.js93
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page.html1
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.html9
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.js28
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/setup_loading_page.html42
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/setup_loading_page.js89
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/BUILD.gn3
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/cellular_locked.svg3
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/cellular_utils.js34
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html1
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.js19
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_config.js1
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_icon.html15
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_icon.js15
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html28
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js43
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.html57
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.js159
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_password_input.html41
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_password_input.js22
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list_mojo.js4
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_select.js43
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html104
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js130
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js3
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.html131
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.js174
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/os_cr_components.gni8
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn6
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/DIR_METADATA11
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/smb_shares/OWNERS2
-rw-r--r--chromium/ui/webui/resources/cr_components/customize_themes/OWNERS1
-rw-r--r--chromium/ui/webui/resources/cr_components/customize_themes/customize_themes.html1
-rw-r--r--chromium/ui/webui/resources/cr_components/managed_footnote/BUILD.gn29
-rw-r--r--chromium/ui/webui/resources/cr_components/managed_footnote/managed_footnote.d.ts17
-rw-r--r--chromium/ui/webui/resources/cr_components/managed_footnote/managed_footnote.html15
-rw-r--r--chromium/ui/webui/resources/cr_components/managed_footnote/managed_footnote.js15
-rw-r--r--chromium/ui/webui/resources/cr_elements/BUILD.gn38
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.m.d.ts58
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_actionable_row_style.html15
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_button/cr_button.html1
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_button/cr_button.m.d.ts19
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.m.d.ts22
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_container_shadow_behavior.m.d.ts12
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html8
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.m.d.ts32
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.d.ts26
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_grid/cr_grid.js9
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.m.d.ts20
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_input/cr_input.html3
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_input/cr_input.js5
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_input/cr_input.m.d.ts42
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_lazy_render/cr_lazy_render.m.d.ts18
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/BUILD.gn67
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html15
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js17
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector_grid.html10
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector_grid.js8
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js4
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.d.ts20
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_slider/OWNERS1
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.js4
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.js8
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_tabs/cr_tabs.html27
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_tabs/cr_tabs.js18
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_toast/cr_toast.m.d.ts20
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.js134
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.d.ts30
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js164
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.js106
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.d.ts19
-rw-r--r--chromium/ui/webui/resources/cr_elements/find_shortcut_behavior.d.ts17
-rw-r--r--chromium/ui/webui/resources/cr_elements/find_shortcut_behavior.js25
-rw-r--r--chromium/ui/webui/resources/cr_elements/mouse_hoverable_mixin.js50
-rw-r--r--chromium/ui/webui/resources/cr_elements/mwb_shared_style.html2
-rw-r--r--chromium/ui/webui/resources/css/text_defaults.css5
-rw-r--r--chromium/ui/webui/resources/css/text_defaults_md.css5
-rw-r--r--chromium/ui/webui/resources/html/BUILD.gn1
-rw-r--r--chromium/ui/webui/resources/html/search_highlight_utils.html2
-rw-r--r--chromium/ui/webui/resources/images/BUILD.gn4
-rw-r--r--chromium/ui/webui/resources/images/incognito_icon.svg1
-rw-r--r--chromium/ui/webui/resources/js/BUILD.gn81
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/context_menu_handler.js4
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/focus_grid.js4
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/focus_row.js4
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/focus_row_behavior.m.d.ts22
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/menu_button.js2
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/store_client.js27
-rw-r--r--chromium/ui/webui/resources/js/event_tracker.js143
-rw-r--r--chromium/ui/webui/resources/js/i18n_behavior.js66
-rw-r--r--chromium/ui/webui/resources/js/i18n_behavior.m.d.ts21
-rw-r--r--chromium/ui/webui/resources/js/ios/web_ui.js79
-rw-r--r--chromium/ui/webui/resources/js/list_property_update_behavior.js14
-rw-r--r--chromium/ui/webui/resources/js/load_time_data.m.js (renamed from chromium/ui/webui/resources/js/load_time_data.js)57
-rw-r--r--chromium/ui/webui/resources/js/parse_html_subset.js26
-rw-r--r--chromium/ui/webui/resources/js/search_highlight_utils.js319
-rw-r--r--chromium/ui/webui/resources/js/web_ui_listener_behavior.js9
-rw-r--r--chromium/ui/webui/resources/js/web_ui_listener_behavior.m.d.ts13
-rw-r--r--chromium/ui/webui/resources/tools/js_modulizer.gni31
-rw-r--r--chromium/ui/webui/resources/tools/js_unmodulizer.gni26
-rw-r--r--chromium/ui/webui/resources/tools/js_unmodulizer.py68
-rw-r--r--chromium/ui/webui/untrusted_web_ui_browsertest_util.cc13
-rw-r--r--chromium/ui/webui/untrusted_web_ui_browsertest_util.h11
-rw-r--r--chromium/ui/wm/DIR_METADATA3
-rw-r--r--chromium/ui/wm/core/capture_controller_unittest.cc7
-rw-r--r--chromium/ui/wm/core/compound_event_filter.cc33
-rw-r--r--chromium/ui/wm/core/compound_event_filter.h4
-rw-r--r--chromium/ui/wm/core/focus_controller.cc4
-rw-r--r--chromium/ui/wm/core/focus_controller.h4
-rw-r--r--chromium/ui/wm/core/focus_controller_unittest.cc4
-rw-r--r--chromium/ui/wm/core/native_cursor_manager.h1
-rw-r--r--chromium/ui/wm/core/shadow_types.cc2
-rw-r--r--chromium/ui/wm/core/transient_window_manager_unittest.cc2
-rw-r--r--chromium/ui/wm/core/transient_window_stacking_client_unittest.cc1
-rw-r--r--chromium/ui/wm/core/visibility_controller.cc4
-rw-r--r--chromium/ui/wm/core/window_animations.cc7
-rw-r--r--chromium/ui/wm/core/window_animations.h1
1752 files changed, 37306 insertions, 19190 deletions
diff --git a/chromium/ui/OWNERS b/chromium/ui/OWNERS
index cd4f28bc0c8..cde8127abc8 100644
--- a/chromium/ui/OWNERS
+++ b/chromium/ui/OWNERS
@@ -11,7 +11,7 @@ ccameron@chromium.org
per-file BUILD.gn=*
# Translation artifacts:
-per-file *.xtb=file://tools/translation/TRANSLATION_OWNERS
+per-file ....xtb=file://tools/translation/TRANSLATION_OWNERS
# For Fuchsia-specific changes:
per-file *fuchsia*=file://build/fuchsia/OWNERS
diff --git a/chromium/ui/accelerated_widget_mac/accelerated_widget_mac.h b/chromium/ui/accelerated_widget_mac/accelerated_widget_mac.h
index 44b1dfc6c72..317173d9337 100644
--- a/chromium/ui/accelerated_widget_mac/accelerated_widget_mac.h
+++ b/chromium/ui/accelerated_widget_mac/accelerated_widget_mac.h
@@ -5,7 +5,6 @@
#ifndef UI_ACCELERATED_WIDGET_MAC_ACCELERATED_WIDGET_MAC_H_
#define UI_ACCELERATED_WIDGET_MAC_ACCELERATED_WIDGET_MAC_H_
-#include <vector>
#include "ui/accelerated_widget_mac/accelerated_widget_mac_export.h"
#include "ui/accelerated_widget_mac/ca_layer_frame_sink.h"
diff --git a/chromium/ui/accelerated_widget_mac/ca_layer_frame_sink.h b/chromium/ui/accelerated_widget_mac/ca_layer_frame_sink.h
index b8dde02402a..c56ca68ddbb 100644
--- a/chromium/ui/accelerated_widget_mac/ca_layer_frame_sink.h
+++ b/chromium/ui/accelerated_widget_mac/ca_layer_frame_sink.h
@@ -5,7 +5,6 @@
#ifndef UI_ACCELERATED_WIDGET_MAC_CA_LAYER_FRAME_SINK_H_
#define UI_ACCELERATED_WIDGET_MAC_CA_LAYER_FRAME_SINK_H_
-#include "base/time/time.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac_export.h"
#include "ui/gfx/ca_layer_params.h"
#include "ui/gfx/native_widget_types.h"
diff --git a/chromium/ui/accelerated_widget_mac/ca_layer_tree_coordinator.h b/chromium/ui/accelerated_widget_mac/ca_layer_tree_coordinator.h
index c6ae9a055f3..9d786ba4a58 100644
--- a/chromium/ui/accelerated_widget_mac/ca_layer_tree_coordinator.h
+++ b/chromium/ui/accelerated_widget_mac/ca_layer_tree_coordinator.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_ACCELERATED_WIDGET_MAC_CA_LAYER_TREE_HOST_H_
-#define UI_ACCELERATED_WIDGET_MAC_CA_LAYER_TREE_HOST_H_
+#ifndef UI_ACCELERATED_WIDGET_MAC_CA_LAYER_TREE_COORDINATOR_H_
+#define UI_ACCELERATED_WIDGET_MAC_CA_LAYER_TREE_COORDINATOR_H_
#include "ui/accelerated_widget_mac/accelerated_widget_mac_export.h"
#include "ui/accelerated_widget_mac/ca_renderer_layer_tree.h"
@@ -66,4 +66,4 @@ class ACCELERATED_WIDGET_MAC_EXPORT CALayerTreeCoordinator {
} // namespace ui
-#endif // UI_ACCELERATED_WIDGET_MAC_CA_LAYER_TREE_HOST_H_
+#endif // UI_ACCELERATED_WIDGET_MAC_CA_LAYER_TREE_COORDINATOR_H_
diff --git a/chromium/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm b/chromium/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm
index a850776871b..a7df344c691 100644
--- a/chromium/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm
+++ b/chromium/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm
@@ -61,7 +61,7 @@ scoped_refptr<gl::GLImageIOSurface> CreateGLImage(const gfx::Size& size,
gl_image->InitializeWithCVPixelBuffer(cv_pixel_buffer,
gfx::GenericSharedMemoryId(), format);
} else {
- gl_image->Initialize(io_surface, gfx::GenericSharedMemoryId(), format);
+ gl_image->Initialize(io_surface, 0, gfx::GenericSharedMemoryId(), format);
}
return gl_image;
}
@@ -73,7 +73,8 @@ bool ScheduleCALayer(ui::CARendererLayerTree* tree,
properties->rounded_corner_bounds, properties->sorting_context_id,
properties->transform, properties->gl_image.get(),
properties->contents_rect, properties->rect, properties->background_color,
- properties->edge_aa_mask, properties->opacity, properties->filter));
+ properties->edge_aa_mask, properties->opacity, properties->filter,
+ gfx::ProtectedVideoType::kClear));
}
void UpdateCALayerTree(std::unique_ptr<ui::CARendererLayerTree>& ca_layer_tree,
diff --git a/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.h b/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
index 60459a38297..f5da8fedf51 100644
--- a/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
+++ b/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
@@ -20,6 +20,7 @@
#include "ui/gfx/mac/io_surface.h"
#include "ui/gfx/rrect_f.h"
#include "ui/gfx/transform.h"
+#include "ui/gfx/video_types.h"
@class AVSampleBufferDisplayLayer;
@@ -72,13 +73,14 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
private:
class SolidColorContents;
- struct RootLayer;
- struct ClipAndSortingLayer;
- struct TransformLayer;
- struct ContentLayer;
- friend struct ContentLayer;
-
- struct RootLayer {
+ class RootLayer;
+ class ClipAndSortingLayer;
+ class TransformLayer;
+ class ContentLayer;
+ friend class ContentLayer;
+
+ class RootLayer {
+ public:
RootLayer();
// This will remove |ca_layer| from its superlayer, if |ca_layer| is
@@ -108,13 +110,14 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
// transparent background, false otherwise.
bool WantsFullcreenLowPowerBackdrop() const;
- std::vector<ClipAndSortingLayer> clip_and_sorting_layers;
- base::scoped_nsobject<CALayer> ca_layer;
+ std::vector<ClipAndSortingLayer> clip_and_sorting_layers_;
+ base::scoped_nsobject<CALayer> ca_layer_;
private:
DISALLOW_COPY_AND_ASSIGN(RootLayer);
};
- struct ClipAndSortingLayer {
+ class ClipAndSortingLayer {
+ public:
ClipAndSortingLayer(bool is_clipped,
gfx::Rect clip_rect,
gfx::RRectF rounded_corner_bounds,
@@ -131,19 +134,20 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
ClipAndSortingLayer* old_layer,
float scale_factor);
- std::vector<TransformLayer> transform_layers;
- bool is_clipped = false;
- gfx::Rect clip_rect;
- gfx::RRectF rounded_corner_bounds;
- unsigned sorting_context_id = 0;
- bool is_singleton_sorting_context = false;
- base::scoped_nsobject<CALayer> clipping_ca_layer;
- base::scoped_nsobject<CALayer> rounded_corner_ca_layer;
+ std::vector<TransformLayer> transform_layers_;
+ bool is_clipped_ = false;
+ gfx::Rect clip_rect_;
+ gfx::RRectF rounded_corner_bounds_;
+ unsigned sorting_context_id_ = 0;
+ bool is_singleton_sorting_context_ = false;
+ base::scoped_nsobject<CALayer> clipping_ca_layer_;
+ base::scoped_nsobject<CALayer> rounded_corner_ca_layer_;
private:
DISALLOW_COPY_AND_ASSIGN(ClipAndSortingLayer);
};
- struct TransformLayer {
+ class TransformLayer {
+ public:
TransformLayer(const gfx::Transform& transform);
TransformLayer(TransformLayer&& layer);
@@ -156,14 +160,15 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
TransformLayer* old_layer,
float scale_factor);
- gfx::Transform transform;
- std::vector<ContentLayer> content_layers;
- base::scoped_nsobject<CALayer> ca_layer;
+ gfx::Transform transform_;
+ std::vector<ContentLayer> content_layers_;
+ base::scoped_nsobject<CALayer> ca_layer_;
private:
DISALLOW_COPY_AND_ASSIGN(TransformLayer);
};
- struct ContentLayer {
+ class ContentLayer {
+ public:
ContentLayer(CARendererLayerTree* tree,
base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer,
@@ -173,7 +178,8 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
const gfx::ColorSpace& color_space,
unsigned edge_aa_mask,
float opacity,
- unsigned filter);
+ unsigned filter,
+ gfx::ProtectedVideoType protected_video_type);
ContentLayer(ContentLayer&& layer);
// See the behavior of RootLayer for the effects of these functions on the
@@ -186,33 +192,36 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
// Ensure that the IOSurface be marked as in-use as soon as it is received.
// When they are committed to the window server, that will also increment
// their use count.
- const gfx::ScopedInUseIOSurface io_surface;
- const base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer;
- scoped_refptr<SolidColorContents> solid_color_contents;
- gfx::RectF contents_rect;
- gfx::RectF rect;
- unsigned background_color = 0;
+ const gfx::ScopedInUseIOSurface io_surface_;
+ const base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer_;
+ scoped_refptr<SolidColorContents> solid_color_contents_;
+ gfx::RectF contents_rect_;
+ gfx::RectF rect_;
+ unsigned background_color_ = 0;
// The color space of |io_surface|. Used for HDR tonemapping.
- gfx::ColorSpace io_surface_color_space;
+ gfx::ColorSpace io_surface_color_space_;
// Note that the CoreAnimation edge antialiasing mask is not the same as
// the edge antialiasing mask passed to the constructor.
- CAEdgeAntialiasingMask ca_edge_aa_mask = 0;
- float opacity = 1;
- NSString* const ca_filter = nil;
+ CAEdgeAntialiasingMask ca_edge_aa_mask_ = 0;
+ float opacity_ = 1;
+ NSString* const ca_filter_ = nil;
- CALayerType type = CALayerType::kDefault;
+ CALayerType type_ = CALayerType::kDefault;
// If |type| is CALayerType::kVideo and |video_type_can_downgrade| then
// |type| can be downgraded to kDefault. This can be set to false for
// HDR video (that cannot be displayed by a regular CALayer) or for
// protected content (see https://crbug.com/1026703).
- bool video_type_can_downgrade = true;
+ bool video_type_can_downgrade_ = true;
+
+ gfx::ProtectedVideoType protected_video_type_ =
+ gfx::ProtectedVideoType::kClear;
- base::scoped_nsobject<CALayer> ca_layer;
+ base::scoped_nsobject<CALayer> ca_layer_;
// If this layer's contents can be represented as an
// AVSampleBufferDisplayLayer, then |ca_layer| will point to |av_layer|.
- base::scoped_nsobject<AVSampleBufferDisplayLayer> av_layer;
+ base::scoped_nsobject<AVSampleBufferDisplayLayer> av_layer_;
private:
DISALLOW_COPY_AND_ASSIGN(ContentLayer);
@@ -230,4 +239,4 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
} // namespace ui
-#endif // UI_ACCELERATED_WIDGET_MAC_CA_LAYER_TREE_MAC_H_
+#endif // UI_ACCELERATED_WIDGET_MAC_CA_RENDERER_LAYER_TREE_H_
diff --git a/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm b/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
index e4610b0da4e..c959d1f81f2 100644
--- a/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
+++ b/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
@@ -288,29 +288,29 @@ void CARendererLayerTree::CommitScheduledCALayers(
bool CARendererLayerTree::RootLayer::WantsFullcreenLowPowerBackdrop() const {
bool found_video_layer = false;
- for (auto& clip_layer : clip_and_sorting_layers) {
- for (auto& transform_layer : clip_layer.transform_layers) {
- for (auto& content_layer : transform_layer.content_layers) {
+ for (auto& clip_layer : clip_and_sorting_layers_) {
+ for (auto& transform_layer : clip_layer.transform_layers_) {
+ for (auto& content_layer : transform_layer.content_layers_) {
// Detached mode requires that no layers be on top of the video layer.
if (found_video_layer)
return false;
// See if this is the video layer.
- if (content_layer.type == CALayerType::kVideo) {
+ if (content_layer.type_ == CALayerType::kVideo) {
found_video_layer = true;
- if (!transform_layer.transform.IsPositiveScaleOrTranslation())
+ if (!transform_layer.transform_.IsPositiveScaleOrTranslation())
return false;
- if (content_layer.opacity != 1)
+ if (content_layer.opacity_ != 1)
return false;
continue;
}
// If we haven't found the video layer yet, make sure everything is
// solid black or transparent
- if (content_layer.io_surface)
+ if (content_layer.io_surface_)
return false;
- if (content_layer.background_color != SK_ColorBLACK &&
- content_layer.background_color != SK_ColorTRANSPARENT) {
+ if (content_layer.background_color_ != SK_ColorBLACK &&
+ content_layer.background_color_ != SK_ColorTRANSPARENT) {
return false;
}
}
@@ -320,12 +320,12 @@ bool CARendererLayerTree::RootLayer::WantsFullcreenLowPowerBackdrop() const {
}
void CARendererLayerTree::RootLayer::DowngradeAVLayersToCALayers() {
- for (auto& clip_layer : clip_and_sorting_layers) {
- for (auto& transform_layer : clip_layer.transform_layers) {
- for (auto& content_layer : transform_layer.content_layers) {
- if (content_layer.type == CALayerType::kVideo &&
- content_layer.video_type_can_downgrade) {
- content_layer.type = CALayerType::kDefault;
+ for (auto& clip_layer : clip_and_sorting_layers_) {
+ for (auto& transform_layer : clip_layer.transform_layers_) {
+ for (auto& content_layer : transform_layer.content_layers_) {
+ if (content_layer.type_ == CALayerType::kVideo &&
+ content_layer.video_type_can_downgrade_) {
+ content_layer.type_ = CALayerType::kDefault;
}
}
}
@@ -337,29 +337,29 @@ id CARendererLayerTree::ContentsForSolidColorForTesting(SkColor color) {
}
IOSurfaceRef CARendererLayerTree::GetContentIOSurface() const {
- size_t clip_count = root_layer_.clip_and_sorting_layers.size();
+ size_t clip_count = root_layer_.clip_and_sorting_layers_.size();
if (clip_count != 1) {
DLOG(ERROR) << "Can only return contents IOSurface when there is 1 "
<< "ClipAndSortingLayer, there are " << clip_count << ".";
return nullptr;
}
const ClipAndSortingLayer& clip_and_sorting =
- root_layer_.clip_and_sorting_layers[0];
- size_t transform_count = clip_and_sorting.transform_layers.size();
+ root_layer_.clip_and_sorting_layers_[0];
+ size_t transform_count = clip_and_sorting.transform_layers_.size();
if (transform_count != 1) {
DLOG(ERROR) << "Can only return contents IOSurface when there is 1 "
<< "TransformLayer, there are " << transform_count << ".";
return nullptr;
}
- const TransformLayer& transform = clip_and_sorting.transform_layers[0];
- size_t content_count = transform.content_layers.size();
+ const TransformLayer& transform = clip_and_sorting.transform_layers_[0];
+ size_t content_count = transform.content_layers_.size();
if (content_count != 1) {
DLOG(ERROR) << "Can only return contents IOSurface when there is 1 "
<< "ContentLayer, there are " << transform_count << ".";
return nullptr;
}
- const ContentLayer& content = transform.content_layers[0];
- return content.io_surface.get();
+ const ContentLayer& content = transform.content_layers_[0];
+ return content.io_surface_.get();
}
CARendererLayerTree::RootLayer::RootLayer() {}
@@ -367,7 +367,7 @@ CARendererLayerTree::RootLayer::RootLayer() {}
// Note that for all destructors, the the CALayer will have been reset to nil if
// another layer has taken it.
CARendererLayerTree::RootLayer::~RootLayer() {
- [ca_layer removeFromSuperlayer];
+ [ca_layer_ removeFromSuperlayer];
}
CARendererLayerTree::ClipAndSortingLayer::ClipAndSortingLayer(
@@ -376,48 +376,48 @@ CARendererLayerTree::ClipAndSortingLayer::ClipAndSortingLayer(
gfx::RRectF rounded_corner_bounds_arg,
unsigned sorting_context_id,
bool is_singleton_sorting_context)
- : is_clipped(is_clipped),
- clip_rect(clip_rect),
- rounded_corner_bounds(rounded_corner_bounds_arg),
- sorting_context_id(sorting_context_id),
- is_singleton_sorting_context(is_singleton_sorting_context) {}
+ : is_clipped_(is_clipped),
+ clip_rect_(clip_rect),
+ rounded_corner_bounds_(rounded_corner_bounds_arg),
+ sorting_context_id_(sorting_context_id),
+ is_singleton_sorting_context_(is_singleton_sorting_context) {}
CARendererLayerTree::ClipAndSortingLayer::ClipAndSortingLayer(
ClipAndSortingLayer&& layer)
- : transform_layers(std::move(layer.transform_layers)),
- is_clipped(layer.is_clipped),
- clip_rect(layer.clip_rect),
- rounded_corner_bounds(layer.rounded_corner_bounds),
- sorting_context_id(layer.sorting_context_id),
- is_singleton_sorting_context(layer.is_singleton_sorting_context),
- clipping_ca_layer(layer.clipping_ca_layer),
- rounded_corner_ca_layer(layer.rounded_corner_ca_layer) {
+ : transform_layers_(std::move(layer.transform_layers_)),
+ is_clipped_(layer.is_clipped_),
+ clip_rect_(layer.clip_rect_),
+ rounded_corner_bounds_(layer.rounded_corner_bounds_),
+ sorting_context_id_(layer.sorting_context_id_),
+ is_singleton_sorting_context_(layer.is_singleton_sorting_context_),
+ clipping_ca_layer_(layer.clipping_ca_layer_),
+ rounded_corner_ca_layer_(layer.rounded_corner_ca_layer_) {
// Ensure that the ca_layer be reset, so that when the destructor is called,
// the layer hierarchy is unaffected.
// TODO(ccameron): Add a move constructor for scoped_nsobject to do this
// automatically.
- layer.clipping_ca_layer.reset();
- layer.rounded_corner_ca_layer.reset();
+ layer.clipping_ca_layer_.reset();
+ layer.rounded_corner_ca_layer_.reset();
}
CARendererLayerTree::ClipAndSortingLayer::~ClipAndSortingLayer() {
- [clipping_ca_layer removeFromSuperlayer];
- [rounded_corner_ca_layer removeFromSuperlayer];
+ [clipping_ca_layer_ removeFromSuperlayer];
+ [rounded_corner_ca_layer_ removeFromSuperlayer];
}
CARendererLayerTree::TransformLayer::TransformLayer(
const gfx::Transform& transform)
- : transform(transform) {}
+ : transform_(transform) {}
CARendererLayerTree::TransformLayer::TransformLayer(TransformLayer&& layer)
- : transform(layer.transform),
- content_layers(std::move(layer.content_layers)),
- ca_layer(layer.ca_layer) {
- layer.ca_layer.reset();
+ : transform_(layer.transform_),
+ content_layers_(std::move(layer.content_layers_)),
+ ca_layer_(layer.ca_layer_) {
+ layer.ca_layer_.reset();
}
CARendererLayerTree::TransformLayer::~TransformLayer() {
- [ca_layer removeFromSuperlayer];
+ [ca_layer_ removeFromSuperlayer];
}
CARendererLayerTree::ContentLayer::ContentLayer(
@@ -425,36 +425,38 @@ CARendererLayerTree::ContentLayer::ContentLayer(
base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer,
const gfx::RectF& contents_rect,
- const gfx::Rect& rect_in,
+ const gfx::Rect& rect,
unsigned background_color,
const gfx::ColorSpace& io_surface_color_space,
unsigned edge_aa_mask,
float opacity,
- unsigned filter)
- : io_surface(io_surface),
- cv_pixel_buffer(cv_pixel_buffer),
- contents_rect(contents_rect),
- rect(rect_in),
- background_color(background_color),
- io_surface_color_space(io_surface_color_space),
- ca_edge_aa_mask(0),
- opacity(opacity),
- ca_filter(filter == GL_LINEAR ? kCAFilterLinear : kCAFilterNearest) {
+ unsigned filter,
+ gfx::ProtectedVideoType protected_video_type)
+ : io_surface_(io_surface),
+ cv_pixel_buffer_(cv_pixel_buffer),
+ contents_rect_(contents_rect),
+ rect_(rect),
+ background_color_(background_color),
+ io_surface_color_space_(io_surface_color_space),
+ ca_edge_aa_mask_(0),
+ opacity_(opacity),
+ ca_filter_(filter == GL_LINEAR ? kCAFilterLinear : kCAFilterNearest),
+ protected_video_type_(protected_video_type) {
DCHECK(filter == GL_LINEAR || filter == GL_NEAREST);
- // On Mac OS Sierra, solid color layers are not color color corrected to the
- // output monitor color space, but IOSurface-backed layers are color
- // corrected. Note that this is only the case when the CALayers are shared
- // across processes. To make colors consistent across both solid color and
- // IOSurface-backed layers, use a cache of solid-color IOSurfaces as
- // contents. Black and transparent layers must use real colors to be eligible
- // for low power detachment in fullscreen.
+ // On Mac OS Sierra, solid color layers are not color converted to the output
+ // monitor color space, but IOSurface-backed layers are color converted. Note
+ // that this is only the case when the CALayers are shared across processes.
+ // To make colors consistent across both solid color and IOSurface-backed
+ // layers, use a cache of solid-color IOSurfaces as contents. Black and
+ // transparent layers must use real colors to be eligible for low power
+ // detachment in fullscreen.
// https://crbug.com/633805
if (!io_surface && !tree->allow_solid_color_layers_ &&
- background_color != SK_ColorBLACK &&
- background_color != SK_ColorTRANSPARENT) {
- solid_color_contents = SolidColorContents::Get(background_color);
- ContentLayer::contents_rect = gfx::RectF(0, 0, 1, 1);
+ background_color_ != SK_ColorBLACK &&
+ background_color_ != SK_ColorTRANSPARENT) {
+ solid_color_contents_ = SolidColorContents::Get(background_color);
+ contents_rect_ = gfx::RectF(0, 0, 1, 1);
}
// Because the root layer has setGeometryFlipped:YES, there is some ambiguity
@@ -466,45 +468,54 @@ CARendererLayerTree::ContentLayer::ContentLayer(
// top edge on-screen.
// https://crbug.com/567946
if (edge_aa_mask & GL_CA_LAYER_EDGE_LEFT_CHROMIUM)
- ca_edge_aa_mask |= kCALayerLeftEdge;
+ ca_edge_aa_mask_ |= kCALayerLeftEdge;
if (edge_aa_mask & GL_CA_LAYER_EDGE_RIGHT_CHROMIUM)
- ca_edge_aa_mask |= kCALayerRightEdge;
- if (io_surface || solid_color_contents) {
+ ca_edge_aa_mask_ |= kCALayerRightEdge;
+ if (io_surface || solid_color_contents_) {
if (edge_aa_mask & GL_CA_LAYER_EDGE_TOP_CHROMIUM)
- ca_edge_aa_mask |= kCALayerBottomEdge;
+ ca_edge_aa_mask_ |= kCALayerBottomEdge;
if (edge_aa_mask & GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM)
- ca_edge_aa_mask |= kCALayerTopEdge;
+ ca_edge_aa_mask_ |= kCALayerTopEdge;
} else {
if (edge_aa_mask & GL_CA_LAYER_EDGE_TOP_CHROMIUM)
- ca_edge_aa_mask |= kCALayerTopEdge;
+ ca_edge_aa_mask_ |= kCALayerTopEdge;
if (edge_aa_mask & GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM)
- ca_edge_aa_mask |= kCALayerBottomEdge;
+ ca_edge_aa_mask_ |= kCALayerBottomEdge;
}
// Determine which type of CALayer subclass we should use.
if (metal::ShouldUseHDRCopier(io_surface, io_surface_color_space)) {
- type = CALayerType::kHDRCopier;
+ type_ = CALayerType::kHDRCopier;
} else if (io_surface) {
- // Only allow 4:2:0 frames which fill the layer's contents to be
- // promoted to AV layers.
- if (tree->allow_av_sample_buffer_display_layer_ &&
- contents_rect == gfx::RectF(0, 0, 1, 1)) {
- switch (IOSurfaceGetPixelFormat(io_surface)) {
- case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange:
- type = CALayerType::kVideo;
- video_type_can_downgrade = !io_surface_color_space.IsHDR();
- break;
- case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange:
- type = CALayerType::kVideo;
- video_type_can_downgrade = false;
- break;
- default:
- break;
+ // Only allow 4:2:0 frames which fill the layer's contents or protected
+ // video to be promoted to AV layers.
+ if (tree->allow_av_sample_buffer_display_layer_) {
+ if (contents_rect == gfx::RectF(0, 0, 1, 1)) {
+ switch (IOSurfaceGetPixelFormat(io_surface)) {
+ case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange:
+ type_ = CALayerType::kVideo;
+ video_type_can_downgrade_ = !io_surface_color_space.IsHDR();
+ break;
+ case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange:
+ type_ = CALayerType::kVideo;
+ video_type_can_downgrade_ = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (protected_video_type_ ==
+ gfx::ProtectedVideoType::kHardwareProtected) {
+ if (@available(macOS 10.15, *)) {
+ type_ = CALayerType::kVideo;
+ video_type_can_downgrade_ = false;
+ }
}
}
}
- if (type == CALayerType::kVideo) {
+ if (type_ == CALayerType::kVideo) {
// If the layer's aspect ratio could be made to match the video's aspect
// ratio by expanding either dimension by a fractional pixel, do so. The
// mismatch probably resulted from rounding the dimensions to integers.
@@ -516,43 +527,45 @@ CARendererLayerTree::ContentLayer::ContentLayer(
: gfx::RectF(IOSurfaceGetWidth(io_surface),
IOSurfaceGetHeight(io_surface)));
const CGFloat av_ratio = av_rect.width() / av_rect.height();
- const CGFloat layer_ratio = rect.width() / rect.height();
+ const CGFloat layer_ratio = rect_.width() / rect_.height();
const CGFloat ratio_error = av_ratio / layer_ratio;
if (ratio_error > 1) {
- const float width_correction = rect.width() * ratio_error - rect.width();
+ const float width_correction =
+ rect_.width() * ratio_error - rect_.width();
if (width_correction < 1)
- rect.Inset(-width_correction / 2, 0);
+ rect_.Inset(-width_correction / 2, 0);
} else if (ratio_error < 1) {
const float height_correction =
- rect.height() / ratio_error - rect.height();
+ rect_.height() / ratio_error - rect_.height();
if (height_correction < 1)
- rect.Inset(0, -height_correction / 2);
+ rect_.Inset(0, -height_correction / 2);
}
}
}
CARendererLayerTree::ContentLayer::ContentLayer(ContentLayer&& layer)
- : io_surface(layer.io_surface),
- cv_pixel_buffer(layer.cv_pixel_buffer),
- solid_color_contents(layer.solid_color_contents),
- contents_rect(layer.contents_rect),
- rect(layer.rect),
- background_color(layer.background_color),
- io_surface_color_space(layer.io_surface_color_space),
- ca_edge_aa_mask(layer.ca_edge_aa_mask),
- opacity(layer.opacity),
- ca_filter(layer.ca_filter),
- type(layer.type),
- video_type_can_downgrade(layer.video_type_can_downgrade),
- ca_layer(std::move(layer.ca_layer)),
- av_layer(std::move(layer.av_layer)) {
- DCHECK(!layer.ca_layer);
- DCHECK(!layer.av_layer);
+ : io_surface_(layer.io_surface_),
+ cv_pixel_buffer_(layer.cv_pixel_buffer_),
+ solid_color_contents_(layer.solid_color_contents_),
+ contents_rect_(layer.contents_rect_),
+ rect_(layer.rect_),
+ background_color_(layer.background_color_),
+ io_surface_color_space_(layer.io_surface_color_space_),
+ ca_edge_aa_mask_(layer.ca_edge_aa_mask_),
+ opacity_(layer.opacity_),
+ ca_filter_(layer.ca_filter_),
+ type_(layer.type_),
+ video_type_can_downgrade_(layer.video_type_can_downgrade_),
+ protected_video_type_(layer.protected_video_type_),
+ ca_layer_(std::move(layer.ca_layer_)),
+ av_layer_(std::move(layer.av_layer_)) {
+ DCHECK(!layer.ca_layer_);
+ DCHECK(!layer.av_layer_);
}
CARendererLayerTree::ContentLayer::~ContentLayer() {
- [ca_layer removeFromSuperlayer];
+ [ca_layer_ removeFromSuperlayer];
}
bool CARendererLayerTree::RootLayer::AddContentLayer(
@@ -567,33 +580,34 @@ bool CARendererLayerTree::RootLayer::AddContentLayer(
bool is_singleton_sorting_context =
!params.sorting_context_id && !params.transform.IsFlat();
- if (!clip_and_sorting_layers.empty()) {
- ClipAndSortingLayer& current_layer = clip_and_sorting_layers.back();
+ if (!clip_and_sorting_layers_.empty()) {
+ ClipAndSortingLayer& current_layer = clip_and_sorting_layers_.back();
// It is in error to change the clipping settings within a non-zero sorting
// context. The result will be incorrect layering and intersection.
if (params.sorting_context_id &&
- current_layer.sorting_context_id == params.sorting_context_id &&
- (current_layer.is_clipped != params.is_clipped ||
- current_layer.clip_rect != params.clip_rect ||
- current_layer.rounded_corner_bounds != params.rounded_corner_bounds)) {
+ current_layer.sorting_context_id_ == params.sorting_context_id &&
+ (current_layer.is_clipped_ != params.is_clipped ||
+ current_layer.clip_rect_ != params.clip_rect ||
+ current_layer.rounded_corner_bounds_ !=
+ params.rounded_corner_bounds)) {
DLOG(ERROR) << "CALayer changed clip inside non-zero sorting context.";
return false;
}
if (!is_singleton_sorting_context &&
- !current_layer.is_singleton_sorting_context &&
- current_layer.is_clipped == params.is_clipped &&
- current_layer.clip_rect == params.clip_rect &&
- current_layer.rounded_corner_bounds == params.rounded_corner_bounds &&
- current_layer.sorting_context_id == params.sorting_context_id) {
+ !current_layer.is_singleton_sorting_context_ &&
+ current_layer.is_clipped_ == params.is_clipped &&
+ current_layer.clip_rect_ == params.clip_rect &&
+ current_layer.rounded_corner_bounds_ == params.rounded_corner_bounds &&
+ current_layer.sorting_context_id_ == params.sorting_context_id) {
needs_new_clip_and_sorting_layer = false;
}
}
if (needs_new_clip_and_sorting_layer) {
- clip_and_sorting_layers.push_back(ClipAndSortingLayer(
+ clip_and_sorting_layers_.push_back(ClipAndSortingLayer(
params.is_clipped, params.clip_rect, params.rounded_corner_bounds,
params.sorting_context_id, is_singleton_sorting_context));
}
- clip_and_sorting_layers.back().AddContentLayer(tree, params);
+ clip_and_sorting_layers_.back().AddContentLayer(tree, params);
return true;
}
@@ -601,14 +615,14 @@ void CARendererLayerTree::ClipAndSortingLayer::AddContentLayer(
CARendererLayerTree* tree,
const CARendererLayerParams& params) {
bool needs_new_transform_layer = true;
- if (!transform_layers.empty()) {
- const TransformLayer& current_layer = transform_layers.back();
- if (current_layer.transform == params.transform)
+ if (!transform_layers_.empty()) {
+ const TransformLayer& current_layer = transform_layers_.back();
+ if (current_layer.transform_ == params.transform)
needs_new_transform_layer = false;
}
if (needs_new_transform_layer)
- transform_layers.push_back(TransformLayer(params.transform));
- transform_layers.back().AddContentLayer(tree, params);
+ transform_layers_.push_back(TransformLayer(params.transform));
+ transform_layers_.back().AddContentLayer(tree, params);
}
void CARendererLayerTree::TransformLayer::AddContentLayer(
@@ -632,10 +646,10 @@ void CARendererLayerTree::TransformLayer::AddContentLayer(
// cv_pixel_buffer = io_surface_image->cv_pixel_buffer();
io_surface_color_space = params.image->color_space();
}
- content_layers.push_back(
- ContentLayer(tree, io_surface, cv_pixel_buffer, params.contents_rect,
- params.rect, params.background_color, io_surface_color_space,
- params.edge_aa_mask, params.opacity, params.filter));
+ content_layers_.push_back(ContentLayer(
+ tree, io_surface, cv_pixel_buffer, params.contents_rect, params.rect,
+ params.background_color, io_surface_color_space, params.edge_aa_mask,
+ params.opacity, params.filter, params.protected_video_type));
}
void CARendererLayerTree::RootLayer::CommitToCA(CALayer* superlayer,
@@ -643,16 +657,16 @@ void CARendererLayerTree::RootLayer::CommitToCA(CALayer* superlayer,
const gfx::Size& pixel_size,
float scale_factor) {
if (old_layer) {
- DCHECK(old_layer->ca_layer);
- std::swap(ca_layer, old_layer->ca_layer);
+ DCHECK(old_layer->ca_layer_);
+ std::swap(ca_layer_, old_layer->ca_layer_);
} else {
- ca_layer.reset([[CALayer alloc] init]);
- [ca_layer setAnchorPoint:CGPointZero];
+ ca_layer_.reset([[CALayer alloc] init]);
+ [ca_layer_ setAnchorPoint:CGPointZero];
[superlayer setSublayers:nil];
- [superlayer addSublayer:ca_layer];
+ [superlayer addSublayer:ca_layer_];
[superlayer setBorderWidth:0];
}
- if ([ca_layer superlayer] != superlayer) {
+ if ([ca_layer_ superlayer] != superlayer) {
DLOG(ERROR) << "CARendererLayerTree root layer not attached to tree.";
}
@@ -661,15 +675,15 @@ void CARendererLayerTree::RootLayer::CommitToCA(CALayer* superlayer,
// solid black background.
const gfx::RectF bg_rect(
ScaleSize(gfx::SizeF(pixel_size), 1 / scale_factor));
- if (gfx::RectF([ca_layer frame]) != bg_rect)
- [ca_layer setFrame:bg_rect.ToCGRect()];
- if (![ca_layer backgroundColor])
- [ca_layer setBackgroundColor:CGColorGetConstantColor(kCGColorBlack)];
+ if (gfx::RectF([ca_layer_ frame]) != bg_rect)
+ [ca_layer_ setFrame:bg_rect.ToCGRect()];
+ if (![ca_layer_ backgroundColor])
+ [ca_layer_ setBackgroundColor:CGColorGetConstantColor(kCGColorBlack)];
} else {
- if (gfx::RectF([ca_layer frame]) != gfx::RectF())
- [ca_layer setFrame:CGRectZero];
- if ([ca_layer backgroundColor])
- [ca_layer setBackgroundColor:nil];
+ if (gfx::RectF([ca_layer_ frame]) != gfx::RectF())
+ [ca_layer_ setFrame:CGRectZero];
+ if ([ca_layer_ backgroundColor])
+ [ca_layer_ setBackgroundColor:nil];
// We know that we are not in fullscreen low power mode, so there is no
// power savings (and a slight power cost) to using
// AVSampleBufferDisplayLayer.
@@ -682,13 +696,13 @@ void CARendererLayerTree::RootLayer::CommitToCA(CALayer* superlayer,
DowngradeAVLayersToCALayers();
}
- for (size_t i = 0; i < clip_and_sorting_layers.size(); ++i) {
+ for (size_t i = 0; i < clip_and_sorting_layers_.size(); ++i) {
ClipAndSortingLayer* old_clip_and_sorting_layer = nullptr;
- if (old_layer && i < old_layer->clip_and_sorting_layers.size()) {
- old_clip_and_sorting_layer = &old_layer->clip_and_sorting_layers[i];
+ if (old_layer && i < old_layer->clip_and_sorting_layers_.size()) {
+ old_clip_and_sorting_layer = &old_layer->clip_and_sorting_layers_[i];
}
- clip_and_sorting_layers[i].CommitToCA(
- ca_layer.get(), old_clip_and_sorting_layer, scale_factor);
+ clip_and_sorting_layers_[i].CommitToCA(
+ ca_layer_.get(), old_clip_and_sorting_layer, scale_factor);
}
}
@@ -699,83 +713,83 @@ void CARendererLayerTree::ClipAndSortingLayer::CommitToCA(
bool update_is_clipped = true;
bool update_clip_rect = true;
if (old_layer) {
- DCHECK(old_layer->clipping_ca_layer);
- DCHECK(old_layer->rounded_corner_ca_layer);
- std::swap(clipping_ca_layer, old_layer->clipping_ca_layer);
- std::swap(rounded_corner_ca_layer, old_layer->rounded_corner_ca_layer);
- update_is_clipped = old_layer->is_clipped != is_clipped;
- update_clip_rect = update_is_clipped || old_layer->clip_rect != clip_rect;
+ DCHECK(old_layer->clipping_ca_layer_);
+ DCHECK(old_layer->rounded_corner_ca_layer_);
+ std::swap(clipping_ca_layer_, old_layer->clipping_ca_layer_);
+ std::swap(rounded_corner_ca_layer_, old_layer->rounded_corner_ca_layer_);
+ update_is_clipped = old_layer->is_clipped_ != is_clipped_;
+ update_clip_rect = update_is_clipped || old_layer->clip_rect_ != clip_rect_;
} else {
- clipping_ca_layer.reset([[CALayer alloc] init]);
- [clipping_ca_layer setAnchorPoint:CGPointZero];
- [superlayer addSublayer:clipping_ca_layer];
- rounded_corner_ca_layer.reset([[CALayer alloc] init]);
- [rounded_corner_ca_layer setAnchorPoint:CGPointZero];
- [clipping_ca_layer addSublayer:rounded_corner_ca_layer];
+ clipping_ca_layer_.reset([[CALayer alloc] init]);
+ [clipping_ca_layer_ setAnchorPoint:CGPointZero];
+ [superlayer addSublayer:clipping_ca_layer_];
+ rounded_corner_ca_layer_.reset([[CALayer alloc] init]);
+ [rounded_corner_ca_layer_ setAnchorPoint:CGPointZero];
+ [clipping_ca_layer_ addSublayer:rounded_corner_ca_layer_];
}
- if (!rounded_corner_bounds.IsEmpty()) {
+ if (!rounded_corner_bounds_.IsEmpty()) {
if (!old_layer ||
- old_layer->rounded_corner_bounds != rounded_corner_bounds) {
+ old_layer->rounded_corner_bounds_ != rounded_corner_bounds_) {
gfx::RectF dip_rounded_corner_bounds =
- gfx::RectF(rounded_corner_bounds.rect());
+ gfx::RectF(rounded_corner_bounds_.rect());
dip_rounded_corner_bounds.Scale(1 / scale_factor);
- [rounded_corner_ca_layer setMasksToBounds:true];
+ [rounded_corner_ca_layer_ setMasksToBounds:true];
- [rounded_corner_ca_layer
+ [rounded_corner_ca_layer_
setPosition:CGPointMake(dip_rounded_corner_bounds.x(),
dip_rounded_corner_bounds.y())];
- [rounded_corner_ca_layer
+ [rounded_corner_ca_layer_
setBounds:CGRectMake(0, 0, dip_rounded_corner_bounds.width(),
dip_rounded_corner_bounds.height())];
- [rounded_corner_ca_layer
+ [rounded_corner_ca_layer_
setSublayerTransform:CATransform3DMakeTranslation(
-dip_rounded_corner_bounds.x(),
-dip_rounded_corner_bounds.y(), 0)];
- [rounded_corner_ca_layer
- setCornerRadius:rounded_corner_bounds.GetSimpleRadius() /
+ [rounded_corner_ca_layer_
+ setCornerRadius:rounded_corner_bounds_.GetSimpleRadius() /
scale_factor];
}
} else {
- [rounded_corner_ca_layer setMasksToBounds:false];
- [rounded_corner_ca_layer setPosition:CGPointZero];
- [rounded_corner_ca_layer setBounds:CGRectZero];
- [rounded_corner_ca_layer setSublayerTransform:CATransform3DIdentity];
- [rounded_corner_ca_layer setCornerRadius:0];
+ [rounded_corner_ca_layer_ setMasksToBounds:false];
+ [rounded_corner_ca_layer_ setPosition:CGPointZero];
+ [rounded_corner_ca_layer_ setBounds:CGRectZero];
+ [rounded_corner_ca_layer_ setSublayerTransform:CATransform3DIdentity];
+ [rounded_corner_ca_layer_ setCornerRadius:0];
}
- if ([clipping_ca_layer superlayer] != superlayer) {
+ if ([clipping_ca_layer_ superlayer] != superlayer) {
DLOG(ERROR) << "CARendererLayerTree root layer not attached to tree.";
}
if (update_is_clipped)
- [clipping_ca_layer setMasksToBounds:is_clipped];
+ [clipping_ca_layer_ setMasksToBounds:is_clipped_];
if (update_clip_rect) {
- if (is_clipped) {
- gfx::RectF dip_clip_rect = gfx::RectF(clip_rect);
+ if (is_clipped_) {
+ gfx::RectF dip_clip_rect = gfx::RectF(clip_rect_);
dip_clip_rect.Scale(1 / scale_factor);
- [clipping_ca_layer
+ [clipping_ca_layer_
setPosition:CGPointMake(dip_clip_rect.x(), dip_clip_rect.y())];
- [clipping_ca_layer setBounds:CGRectMake(0, 0, dip_clip_rect.width(),
- dip_clip_rect.height())];
- [clipping_ca_layer
+ [clipping_ca_layer_ setBounds:CGRectMake(0, 0, dip_clip_rect.width(),
+ dip_clip_rect.height())];
+ [clipping_ca_layer_
setSublayerTransform:CATransform3DMakeTranslation(
-dip_clip_rect.x(), -dip_clip_rect.y(), 0)];
} else {
- [clipping_ca_layer setPosition:CGPointZero];
- [clipping_ca_layer setBounds:CGRectZero];
- [clipping_ca_layer setSublayerTransform:CATransform3DIdentity];
+ [clipping_ca_layer_ setPosition:CGPointZero];
+ [clipping_ca_layer_ setBounds:CGRectZero];
+ [clipping_ca_layer_ setSublayerTransform:CATransform3DIdentity];
}
}
- for (size_t i = 0; i < transform_layers.size(); ++i) {
+ for (size_t i = 0; i < transform_layers_.size(); ++i) {
TransformLayer* old_transform_layer = nullptr;
- if (old_layer && i < old_layer->transform_layers.size())
- old_transform_layer = &old_layer->transform_layers[i];
- transform_layers[i].CommitToCA(rounded_corner_ca_layer, old_transform_layer,
- scale_factor);
+ if (old_layer && i < old_layer->transform_layers_.size())
+ old_transform_layer = &old_layer->transform_layers_[i];
+ transform_layers_[i].CommitToCA(rounded_corner_ca_layer_,
+ old_transform_layer, scale_factor);
}
}
@@ -784,33 +798,33 @@ void CARendererLayerTree::TransformLayer::CommitToCA(CALayer* superlayer,
float scale_factor) {
bool update_transform = true;
if (old_layer) {
- DCHECK(old_layer->ca_layer);
- std::swap(ca_layer, old_layer->ca_layer);
- update_transform = old_layer->transform != transform;
+ DCHECK(old_layer->ca_layer_);
+ std::swap(ca_layer_, old_layer->ca_layer_);
+ update_transform = old_layer->transform_ != transform_;
} else {
- ca_layer.reset([[CATransformLayer alloc] init]);
- [superlayer addSublayer:ca_layer];
+ ca_layer_.reset([[CATransformLayer alloc] init]);
+ [superlayer addSublayer:ca_layer_];
}
- DCHECK_EQ([ca_layer superlayer], superlayer);
+ DCHECK_EQ([ca_layer_ superlayer], superlayer);
if (update_transform) {
gfx::Transform pre_scale;
gfx::Transform post_scale;
pre_scale.Scale(1 / scale_factor, 1 / scale_factor);
post_scale.Scale(scale_factor, scale_factor);
- gfx::Transform conjugated_transform = pre_scale * transform * post_scale;
+ gfx::Transform conjugated_transform = pre_scale * transform_ * post_scale;
CATransform3D ca_transform;
conjugated_transform.matrix().asColMajord(&ca_transform.m11);
- [ca_layer setTransform:ca_transform];
+ [ca_layer_ setTransform:ca_transform];
}
- for (size_t i = 0; i < content_layers.size(); ++i) {
+ for (size_t i = 0; i < content_layers_.size(); ++i) {
ContentLayer* old_content_layer = nullptr;
- if (old_layer && i < old_layer->content_layers.size())
- old_content_layer = &old_layer->content_layers[i];
- content_layers[i].CommitToCA(ca_layer.get(), old_content_layer,
- scale_factor);
+ if (old_layer && i < old_layer->content_layers_.size())
+ old_content_layer = &old_layer->content_layers_[i];
+ content_layers_[i].CommitToCA(ca_layer_.get(), old_content_layer,
+ scale_factor);
}
}
@@ -824,64 +838,70 @@ void CARendererLayerTree::ContentLayer::CommitToCA(CALayer* superlayer,
bool update_ca_edge_aa_mask = true;
bool update_opacity = true;
bool update_ca_filter = true;
- if (old_layer && old_layer->type == type) {
- DCHECK(old_layer->ca_layer);
- std::swap(ca_layer, old_layer->ca_layer);
- std::swap(av_layer, old_layer->av_layer);
- update_contents = old_layer->io_surface != io_surface ||
- old_layer->cv_pixel_buffer != cv_pixel_buffer ||
- old_layer->solid_color_contents != solid_color_contents;
- update_contents_rect = old_layer->contents_rect != contents_rect;
- update_rect = old_layer->rect != rect;
- update_background_color = old_layer->background_color != background_color;
- update_ca_edge_aa_mask = old_layer->ca_edge_aa_mask != ca_edge_aa_mask;
- update_opacity = old_layer->opacity != opacity;
- update_ca_filter = old_layer->ca_filter != ca_filter;
+ if (old_layer && old_layer->type_ == type_) {
+ DCHECK(old_layer->ca_layer_);
+ std::swap(ca_layer_, old_layer->ca_layer_);
+ std::swap(av_layer_, old_layer->av_layer_);
+ update_contents = old_layer->io_surface_ != io_surface_ ||
+ old_layer->cv_pixel_buffer_ != cv_pixel_buffer_ ||
+ old_layer->solid_color_contents_ != solid_color_contents_;
+ update_contents_rect = old_layer->contents_rect_ != contents_rect_;
+ update_rect = old_layer->rect_ != rect_;
+ update_background_color = old_layer->background_color_ != background_color_;
+ update_ca_edge_aa_mask = old_layer->ca_edge_aa_mask_ != ca_edge_aa_mask_;
+ update_opacity = old_layer->opacity_ != opacity_;
+ update_ca_filter = old_layer->ca_filter_ != ca_filter_;
} else {
- switch (type) {
+ switch (type_) {
case CALayerType::kHDRCopier:
- ca_layer.reset(metal::CreateHDRCopierLayer());
+ ca_layer_.reset(metal::CreateHDRCopierLayer());
break;
case CALayerType::kVideo:
- av_layer.reset([[AVSampleBufferDisplayLayer alloc] init]);
- ca_layer.reset([av_layer retain]);
- [av_layer setVideoGravity:AVLayerVideoGravityResize];
+ av_layer_.reset([[AVSampleBufferDisplayLayer alloc] init]);
+ ca_layer_.reset([av_layer_ retain]);
+ [av_layer_ setVideoGravity:AVLayerVideoGravityResize];
+ if (protected_video_type_ ==
+ gfx::ProtectedVideoType::kHardwareProtected) {
+ if (@available(macOS 10.15, *)) {
+ [av_layer_ setPreventsCapture:true];
+ }
+ }
break;
case CALayerType::kDefault:
- ca_layer.reset([[CALayer alloc] init]);
+ ca_layer_.reset([[CALayer alloc] init]);
}
- [ca_layer setAnchorPoint:CGPointZero];
- if (old_layer && old_layer->ca_layer)
- [superlayer replaceSublayer:old_layer->ca_layer with:ca_layer];
+ [ca_layer_ setAnchorPoint:CGPointZero];
+ if (old_layer && old_layer->ca_layer_)
+ [superlayer replaceSublayer:old_layer->ca_layer_ with:ca_layer_];
else
- [superlayer addSublayer:ca_layer];
+ [superlayer addSublayer:ca_layer_];
}
- DCHECK_EQ([ca_layer superlayer], superlayer);
+ DCHECK_EQ([ca_layer_ superlayer], superlayer);
bool update_anything = update_contents || update_contents_rect ||
update_rect || update_background_color ||
update_ca_edge_aa_mask || update_opacity ||
update_ca_filter;
- switch (type) {
+ switch (type_) {
case CALayerType::kHDRCopier:
if (update_contents) {
- metal::UpdateHDRCopierLayer(ca_layer.get(), io_surface.get(),
- io_surface_color_space);
+ metal::UpdateHDRCopierLayer(ca_layer_.get(), io_surface_.get(),
+ io_surface_color_space_);
}
break;
case CALayerType::kVideo:
if (update_contents) {
bool result = false;
- if (cv_pixel_buffer) {
+ if (cv_pixel_buffer_) {
result = AVSampleBufferDisplayLayerEnqueueCVPixelBuffer(
- av_layer, cv_pixel_buffer);
+ av_layer_, cv_pixel_buffer_);
if (!result) {
LOG(ERROR)
<< "AVSampleBufferDisplayLayerEnqueueCVPixelBuffer failed";
}
} else {
result = AVSampleBufferDisplayLayerEnqueueIOSurface(
- av_layer, io_surface, io_surface_color_space);
+ av_layer_, io_surface_, io_surface_color_space_);
if (!result) {
LOG(ERROR) << "AVSampleBufferDisplayLayerEnqueueIOSurface failed";
}
@@ -894,47 +914,47 @@ void CARendererLayerTree::ContentLayer::CommitToCA(CALayer* superlayer,
break;
case CALayerType::kDefault:
if (update_contents) {
- if (io_surface) {
- [ca_layer setContents:static_cast<id>(io_surface.get())];
- } else if (solid_color_contents) {
- [ca_layer setContents:solid_color_contents->GetContents()];
+ if (io_surface_) {
+ [ca_layer_ setContents:static_cast<id>(io_surface_.get())];
+ } else if (solid_color_contents_) {
+ [ca_layer_ setContents:solid_color_contents_->GetContents()];
} else {
- [ca_layer setContents:nil];
+ [ca_layer_ setContents:nil];
}
- if ([ca_layer respondsToSelector:(@selector(setContentsScale:))])
- [ca_layer setContentsScale:scale_factor];
+ if ([ca_layer_ respondsToSelector:(@selector(setContentsScale:))])
+ [ca_layer_ setContentsScale:scale_factor];
}
break;
}
if (update_contents_rect) {
- if (type != CALayerType::kVideo)
- [ca_layer setContentsRect:contents_rect.ToCGRect()];
+ if (type_ != CALayerType::kVideo)
+ [ca_layer_ setContentsRect:contents_rect_.ToCGRect()];
}
if (update_rect) {
- gfx::RectF dip_rect = gfx::RectF(rect);
+ gfx::RectF dip_rect = gfx::RectF(rect_);
dip_rect.Scale(1 / scale_factor);
- [ca_layer setPosition:CGPointMake(dip_rect.x(), dip_rect.y())];
- [ca_layer setBounds:CGRectMake(0, 0, dip_rect.width(), dip_rect.height())];
+ [ca_layer_ setPosition:CGPointMake(dip_rect.x(), dip_rect.y())];
+ [ca_layer_ setBounds:CGRectMake(0, 0, dip_rect.width(), dip_rect.height())];
}
if (update_background_color) {
CGFloat rgba_color_components[4] = {
- SkColorGetR(background_color) / 255.,
- SkColorGetG(background_color) / 255.,
- SkColorGetB(background_color) / 255.,
- SkColorGetA(background_color) / 255.,
+ SkColorGetR(background_color_) / 255.,
+ SkColorGetG(background_color_) / 255.,
+ SkColorGetB(background_color_) / 255.,
+ SkColorGetA(background_color_) / 255.,
};
base::ScopedCFTypeRef<CGColorRef> srgb_background_color(CGColorCreate(
CGColorSpaceCreateWithName(kCGColorSpaceSRGB), rgba_color_components));
- [ca_layer setBackgroundColor:srgb_background_color];
+ [ca_layer_ setBackgroundColor:srgb_background_color];
}
if (update_ca_edge_aa_mask)
- [ca_layer setEdgeAntialiasingMask:ca_edge_aa_mask];
+ [ca_layer_ setEdgeAntialiasingMask:ca_edge_aa_mask_];
if (update_opacity)
- [ca_layer setOpacity:opacity];
+ [ca_layer_ setOpacity:opacity_];
if (update_ca_filter) {
- [ca_layer setMagnificationFilter:ca_filter];
- [ca_layer setMinificationFilter:ca_filter];
+ [ca_layer_ setMagnificationFilter:ca_filter_];
+ [ca_layer_ setMinificationFilter:ca_filter_];
}
static bool show_borders = base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -942,24 +962,24 @@ void CARendererLayerTree::ContentLayer::CommitToCA(CALayer* superlayer,
if (show_borders) {
base::ScopedCFTypeRef<CGColorRef> color;
float alpha = update_anything ? 1.f : 0.2f;
- if (type == CALayerType::kHDRCopier) {
+ if (type_ == CALayerType::kHDRCopier) {
// Blue represents an HDR layer.
color.reset(CGColorCreateGenericRGB(0, 0, 1, alpha));
- } else if (type == CALayerType::kVideo) {
+ } else if (type_ == CALayerType::kVideo) {
// Yellow represents an AV layer.
color.reset(CGColorCreateGenericRGB(1, 1, 0, alpha));
- } else if (io_surface) {
+ } else if (io_surface_) {
// Magenta represents a CALayer.
color.reset(CGColorCreateGenericRGB(1, 0, 1, alpha));
- } else if (solid_color_contents) {
+ } else if (solid_color_contents_) {
// Cyan represents a solid color.
color.reset(CGColorCreateGenericRGB(0, 1, 1, alpha));
} else {
// Grey represents a CALayer that has not changed.
color.reset(CGColorCreateGenericRGB(0.5, 0.5, 0.5, 1));
}
- [ca_layer setBorderWidth:1];
- [ca_layer setBorderColor:color];
+ [ca_layer_ setBorderWidth:1];
+ [ca_layer_ setBorderColor:color];
}
}
diff --git a/chromium/ui/accelerated_widget_mac/ca_transaction_observer.mm b/chromium/ui/accelerated_widget_mac/ca_transaction_observer.mm
index af02cc27bcb..03bdf5fe8a3 100644
--- a/chromium/ui/accelerated_widget_mac/ca_transaction_observer.mm
+++ b/chromium/ui/accelerated_widget_mac/ca_transaction_observer.mm
@@ -13,11 +13,11 @@
#import <CoreFoundation/CoreFoundation.h>
#import <QuartzCore/QuartzCore.h>
-typedef enum {
+typedef NS_ENUM(unsigned int, CATransactionPhase) {
kCATransactionPhasePreLayout,
kCATransactionPhasePreCommit,
kCATransactionPhasePostCommit,
-} CATransactionPhase;
+};
@interface CATransaction ()
+ (void)addCommitHandler:(void (^)(void))block
diff --git a/chromium/ui/accelerated_widget_mac/io_surface_context.h b/chromium/ui/accelerated_widget_mac/io_surface_context.h
index 504a52b3b60..a46878285b3 100644
--- a/chromium/ui/accelerated_widget_mac/io_surface_context.h
+++ b/chromium/ui/accelerated_widget_mac/io_surface_context.h
@@ -7,8 +7,6 @@
#include <OpenGL/OpenGL.h>
-#include <map>
-#include <memory>
#include "base/mac/scoped_nsobject.h"
#include "base/memory/ref_counted.h"
diff --git a/chromium/ui/accessibility/BUILD.gn b/chromium/ui/accessibility/BUILD.gn
index b4707c34628..cf03156c5c0 100644
--- a/chromium/ui/accessibility/BUILD.gn
+++ b/chromium/ui/accessibility/BUILD.gn
@@ -111,6 +111,8 @@ component("accessibility") {
"ax_event_generator.cc",
"ax_event_generator.h",
"ax_export.h",
+ "ax_hypertext.cc",
+ "ax_hypertext.h",
"ax_language_detection.cc",
"ax_language_detection.h",
"ax_mode_observer.h",
@@ -242,6 +244,8 @@ test("accessibility_unittests") {
"platform/ax_platform_node_unittest.cc",
"platform/ax_platform_node_unittest.h",
"platform/ax_unique_id_unittest.cc",
+ "platform/inspect/ax_inspect_scenario_unittest.cc",
+ "platform/inspect/ax_inspect_utils_unittest.cc",
"platform/inspect/ax_property_node_unittest.cc",
"run_all_unittests.cc",
]
diff --git a/chromium/ui/accessibility/PRESUBMIT.py b/chromium/ui/accessibility/PRESUBMIT.py
index c97381a70c1..e61f4cbdc7f 100644
--- a/chromium/ui/accessibility/PRESUBMIT.py
+++ b/chromium/ui/accessibility/PRESUBMIT.py
@@ -34,6 +34,9 @@ def GetEnumsFromFile(fullpath):
# Strip out comments
line = re.sub('//.*', '', line)
+ # Strip out mojo annotations.
+ line = re.sub('\[(.*)\]', '', line)
+
# Look for lines of the form "enum ENUM_NAME {" and get the enum_name
m = re.search('enum ([\w]+) {', line)
if m:
diff --git a/chromium/ui/accessibility/accessibility_features.cc b/chromium/ui/accessibility/accessibility_features.cc
index 07cd30ebfe1..57551faa5f0 100644
--- a/chromium/ui/accessibility/accessibility_features.cc
+++ b/chromium/ui/accessibility/accessibility_features.cc
@@ -94,13 +94,6 @@ bool IsIChromeAccessibleEnabled() {
#endif // defined(OS_WIN)
#if BUILDFLAG(IS_CHROMEOS_ASH)
-const base::Feature kMagnifierNewFocusFollowing{
- "MagnifierNewFocusFollowing", base::FEATURE_ENABLED_BY_DEFAULT};
-
-bool IsMagnifierNewFocusFollowingEnabled() {
- return base::FeatureList::IsEnabled(::features::kMagnifierNewFocusFollowing);
-}
-
const base::Feature kMagnifierPanningImprovements{
"MagnifierPanningImprovements", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -119,12 +112,21 @@ bool IsMagnifierContinuousMouseFollowingModeSettingEnabled() {
}
const base::Feature kEnableSwitchAccessPointScanning{
- "EnableSwitchAccessPointScanning", base::FEATURE_DISABLED_BY_DEFAULT};
+ "EnableSwitchAccessPointScanning", base::FEATURE_ENABLED_BY_DEFAULT};
bool IsSwitchAccessPointScanningEnabled() {
return base::FeatureList::IsEnabled(
::features::kEnableSwitchAccessPointScanning);
}
+
+const base::Feature kExperimentalAccessibilityDictationListening{
+ "ExperimentalAccessibilityDictationListening",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+bool IsExperimentalAccessibilityDictationListeningEnabled() {
+ return base::FeatureList::IsEnabled(
+ ::features::kExperimentalAccessibilityDictationListening);
+}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
const base::Feature kAugmentExistingImageLabels{
@@ -159,4 +161,13 @@ bool IsSelectToSpeakNavigationControlEnabled() {
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_ANDROID)
+const base::Feature kComputeAXMode{"ComputeAXMode",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+bool IsComputeAXModeEnabled() {
+ return base::FeatureList::IsEnabled(::features::kComputeAXMode);
+}
+#endif // defined(OS_ANDROID)
+
} // namespace features
diff --git a/chromium/ui/accessibility/accessibility_features.h b/chromium/ui/accessibility/accessibility_features.h
index 848656cc4af..09e87f2dd62 100644
--- a/chromium/ui/accessibility/accessibility_features.h
+++ b/chromium/ui/accessibility/accessibility_features.h
@@ -78,13 +78,6 @@ AX_BASE_EXPORT bool IsIChromeAccessibleEnabled();
#endif // defined(OS_WIN)
#if BUILDFLAG(IS_CHROMEOS_ASH)
-// Enables new magnifier focus following feature, which provides a richer
-// focus following experience.
-AX_BASE_EXPORT extern const base::Feature kMagnifierNewFocusFollowing;
-
-// Returns true if the new magnifier focus following feature is enabled.
-AX_BASE_EXPORT bool IsMagnifierNewFocusFollowingEnabled();
-
// Enables new magnifier panning improvements feature, which adds
// additional keyboard and mouse panning functionality in Magnifier.
AX_BASE_EXPORT extern const base::Feature kMagnifierPanningImprovements;
@@ -107,6 +100,16 @@ AX_BASE_EXPORT extern const base::Feature kEnableSwitchAccessPointScanning;
// Returns true if the feature to allow point scanning in switch access is
// enabled.
AX_BASE_EXPORT bool IsSwitchAccessPointScanningEnabled();
+
+// Enables dictation using web speech to listen for a longer duration and
+// allow profanity, and for dictation with web speech or on-device speech
+// to continue listening after speech is finalized.
+AX_BASE_EXPORT extern const base::Feature
+ kExperimentalAccessibilityDictationListening;
+
+// Returns true if the feature to allow experimental listening features for
+// Dictation is enabled.
+AX_BASE_EXPORT bool IsExperimentalAccessibilityDictationListeningEnabled();
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
// Enables Get Image Descriptions to augment existing images labels,
@@ -144,6 +147,15 @@ AX_BASE_EXPORT extern const base::Feature kSelectToSpeakNavigationControl;
AX_BASE_EXPORT bool IsSelectToSpeakNavigationControlEnabled();
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_ANDROID)
+// Compute the AXMode based on AccessibilityServiceInfo. If disabled,
+// the AXMode is either entirely on or entirely off.
+AX_BASE_EXPORT extern const base::Feature kComputeAXMode;
+
+// Returns true if the IChromeAccessible COM API is enabled.
+AX_BASE_EXPORT bool IsComputeAXModeEnabled();
+#endif // defined(OS_ANDROID)
+
} // namespace features
#endif // UI_ACCESSIBILITY_ACCESSIBILITY_FEATURES_H_
diff --git a/chromium/ui/accessibility/accessibility_switches.cc b/chromium/ui/accessibility/accessibility_switches.cc
index 3bd01485bb3..b4ffa8e9806 100644
--- a/chromium/ui/accessibility/accessibility_switches.cc
+++ b/chromium/ui/accessibility/accessibility_switches.cc
@@ -22,12 +22,6 @@ const char kEnableExperimentalAccessibilityDictationExtension[] =
const char kEnableExperimentalAccessibilityDictationOffline[] =
"enable-experimental-accessibility-dictation-offline";
-// Enables dictation using web speech to listen for a longer duration,
-// and for dictation with web speech or on-device speech to continue listening
-// after speech is finalized.
-const char kEnableExperimentalAccessibilityDictationListening[] =
- "enable-experimental-accessibility-dictation-listening";
-
// Enables support for visually debugging the accessibility labels
// feature, which provides images descriptions for screen reader users.
const char kEnableExperimentalAccessibilityLabelsDebugging[] =
@@ -65,11 +59,6 @@ bool IsExperimentalAccessibilityDictationOfflineEnabled() {
::switches::kEnableExperimentalAccessibilityDictationOffline);
}
-bool IsExperimentalAccessibilityDictationListeningEnabled() {
- return base::CommandLine::ForCurrentProcess()->HasSwitch(
- ::switches::kEnableExperimentalAccessibilityDictationListening);
-}
-
bool IsExperimentalAccessibilityLanguageDetectionEnabled() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kEnableExperimentalAccessibilityLanguageDetection);
diff --git a/chromium/ui/accessibility/accessibility_switches.h b/chromium/ui/accessibility/accessibility_switches.h
index 5dfeba83b64..634b7808717 100644
--- a/chromium/ui/accessibility/accessibility_switches.h
+++ b/chromium/ui/accessibility/accessibility_switches.h
@@ -35,10 +35,6 @@ AX_BASE_EXPORT bool IsExperimentalAccessibilityDictationExtensionEnabled();
// Returns true if experimental accessibility offline dictation is enabled.
AX_BASE_EXPORT bool IsExperimentalAccessibilityDictationOfflineEnabled();
-// Returns true if experimental accessibility dictation listening features are
-// enabled.
-AX_BASE_EXPORT bool IsExperimentalAccessibilityDictationListeningEnabled();
-
// Returns true if experimental accessibility language detection is enabled.
AX_BASE_EXPORT bool IsExperimentalAccessibilityLanguageDetectionEnabled();
diff --git a/chromium/ui/accessibility/ax_action_data.h b/chromium/ui/accessibility/ax_action_data.h
index 796f04c40ea..4fe1b186602 100644
--- a/chromium/ui/accessibility/ax_action_data.h
+++ b/chromium/ui/accessibility/ax_action_data.h
@@ -66,7 +66,7 @@ struct AX_BASE_EXPORT AXActionData {
// The target rect for the action.
gfx::Rect target_rect;
- // The target point for the action.
+ // The target point for the action in screen coordinates.
gfx::Point target_point;
// The new value for a node, for the SET_VALUE action. UTF-8 encoded.
diff --git a/chromium/ui/accessibility/ax_active_popup.cc b/chromium/ui/accessibility/ax_active_popup.cc
index f459bbf3a31..40ef023245f 100644
--- a/chromium/ui/accessibility/ax_active_popup.cc
+++ b/chromium/ui/accessibility/ax_active_popup.cc
@@ -11,23 +11,23 @@ namespace ui {
namespace {
-base::Optional<AXNodeID>& GetActivePopupAXUniqueIdInstance() {
+absl::optional<AXNodeID>& GetActivePopupAXUniqueIdInstance() {
// Keeps track of the unique ID that can be used to retrieve the
// `ViewAccessibility` object that is handling the accessibility for the
// currently active autofill popup. This singleton is used for communicating
// the live status of the autofill popup between web contents and Views. The
// assumption here is that only one autofill popup can exist at a time.
- static base::NoDestructor<base::Optional<AXNodeID>> active_popup_ax_unique_id;
+ static base::NoDestructor<absl::optional<AXNodeID>> active_popup_ax_unique_id;
return *active_popup_ax_unique_id;
}
} // namespace
-base::Optional<AXNodeID> GetActivePopupAxUniqueId() {
+absl::optional<AXNodeID> GetActivePopupAxUniqueId() {
return GetActivePopupAXUniqueIdInstance();
}
-void SetActivePopupAxUniqueId(base::Optional<AXNodeID> ax_unique_id) {
+void SetActivePopupAxUniqueId(absl::optional<AXNodeID> ax_unique_id) {
// When an instance of autofill popup hides, the caller of popup hide should
// make sure active_popup_ax_unique_id is cleared. The assumption is that
// there can only be one active autofill popup existing at a time. If on
@@ -41,7 +41,7 @@ void SetActivePopupAxUniqueId(base::Optional<AXNodeID> ax_unique_id) {
}
void ClearActivePopupAxUniqueId() {
- GetActivePopupAXUniqueIdInstance() = base::nullopt;
+ GetActivePopupAXUniqueIdInstance() = absl::nullopt;
}
} // namespace ui
diff --git a/chromium/ui/accessibility/ax_active_popup.h b/chromium/ui/accessibility/ax_active_popup.h
index 9d6f1abb775..82ba49dd4d0 100644
--- a/chromium/ui/accessibility/ax_active_popup.h
+++ b/chromium/ui/accessibility/ax_active_popup.h
@@ -5,15 +5,15 @@
#ifndef UI_ACCESSIBILITY_AX_ACTIVE_POPUP_H_
#define UI_ACCESSIBILITY_AX_ACTIVE_POPUP_H_
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_export.h"
#include "ui/accessibility/ax_node_data.h"
namespace ui {
-AX_EXPORT base::Optional<AXNodeID> GetActivePopupAxUniqueId();
+AX_EXPORT absl::optional<AXNodeID> GetActivePopupAxUniqueId();
-AX_EXPORT void SetActivePopupAxUniqueId(base::Optional<AXNodeID> ax_unique_id);
+AX_EXPORT void SetActivePopupAxUniqueId(absl::optional<AXNodeID> ax_unique_id);
AX_EXPORT void ClearActivePopupAxUniqueId();
diff --git a/chromium/ui/accessibility/ax_assistant_structure.cc b/chromium/ui/accessibility/ax_assistant_structure.cc
index ffc101c9509..6e7155334cb 100644
--- a/chromium/ui/accessibility/ax_assistant_structure.cc
+++ b/chromium/ui/accessibility/ax_assistant_structure.cc
@@ -7,9 +7,9 @@
#include <utility>
#include "base/logging.h"
-#include "base/optional.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node.h"
#include "ui/accessibility/ax_role_properties.h"
@@ -35,13 +35,8 @@ bool HasFocusableChild(const AXNode* node) {
}
// TODO(muyuanli): share with BrowserAccessibility.
-bool IsSimpleTextControl(const AXNode* node, uint32_t state) {
- return (node->data().role == ax::mojom::Role::kTextField ||
- node->data().role == ax::mojom::Role::kTextFieldWithComboBox ||
- node->data().role == ax::mojom::Role::kSearchBox ||
- node->data().HasBoolAttribute(
- ax::mojom::BoolAttribute::kEditableRoot)) &&
- !node->data().HasState(ax::mojom::State::kRichlyEditable);
+bool IsTextField(const AXNode* node, uint32_t state) {
+ return node->data().IsTextField();
}
bool IsRichTextEditable(const AXNode* node) {
@@ -51,7 +46,7 @@ bool IsRichTextEditable(const AXNode* node) {
!parent->data().HasState(ax::mojom::State::kRichlyEditable));
}
-bool IsNativeTextControl(const AXNode* node) {
+bool IsAtomicTextField(const AXNode* node) {
const std::string& html_tag =
node->data().GetStringAttribute(ax::mojom::StringAttribute::kHtmlTag);
if (html_tag == "input") {
@@ -70,7 +65,7 @@ bool IsLeaf(const AXNode* node) {
if (node->children().empty())
return true;
- if (IsNativeTextControl(node) || node->IsText()) {
+ if (IsAtomicTextField(node) || node->IsText()) {
return true;
}
@@ -107,9 +102,8 @@ std::u16string GetValue(const AXNode* node) {
node->data().GetString16Attribute(ax::mojom::StringAttribute::kValue);
if (value.empty() &&
- (IsSimpleTextControl(node, node->data().state) ||
- IsRichTextEditable(node)) &&
- !IsNativeTextControl(node)) {
+ (IsTextField(node, node->data().state) || IsRichTextEditable(node)) &&
+ !IsAtomicTextField(node)) {
value = GetInnerText(node);
}
@@ -198,44 +192,44 @@ std::u16string GetText(const AXNode* node) {
// Get string representation of ax::mojom::Role. We are not using ToString() in
// ax_enums.h since the names are subject to change in the future and
// we are only interested in a subset of the roles.
-base::Optional<std::string> AXRoleToString(ax::mojom::Role role) {
+absl::optional<std::string> AXRoleToString(ax::mojom::Role role) {
switch (role) {
case ax::mojom::Role::kArticle:
- return base::Optional<std::string>("article");
+ return absl::optional<std::string>("article");
case ax::mojom::Role::kBanner:
- return base::Optional<std::string>("banner");
+ return absl::optional<std::string>("banner");
case ax::mojom::Role::kCaption:
- return base::Optional<std::string>("caption");
+ return absl::optional<std::string>("caption");
case ax::mojom::Role::kComplementary:
- return base::Optional<std::string>("complementary");
+ return absl::optional<std::string>("complementary");
case ax::mojom::Role::kDate:
- return base::Optional<std::string>("date");
+ return absl::optional<std::string>("date");
case ax::mojom::Role::kDateTime:
- return base::Optional<std::string>("date_time");
+ return absl::optional<std::string>("date_time");
case ax::mojom::Role::kDefinition:
- return base::Optional<std::string>("definition");
+ return absl::optional<std::string>("definition");
case ax::mojom::Role::kDetails:
- return base::Optional<std::string>("details");
+ return absl::optional<std::string>("details");
case ax::mojom::Role::kDocument:
- return base::Optional<std::string>("document");
+ return absl::optional<std::string>("document");
case ax::mojom::Role::kFeed:
- return base::Optional<std::string>("feed");
+ return absl::optional<std::string>("feed");
case ax::mojom::Role::kHeading:
- return base::Optional<std::string>("heading");
+ return absl::optional<std::string>("heading");
case ax::mojom::Role::kIframe:
- return base::Optional<std::string>("iframe");
+ return absl::optional<std::string>("iframe");
case ax::mojom::Role::kIframePresentational:
- return base::Optional<std::string>("iframe_presentational");
+ return absl::optional<std::string>("iframe_presentational");
case ax::mojom::Role::kList:
- return base::Optional<std::string>("list");
+ return absl::optional<std::string>("list");
case ax::mojom::Role::kListItem:
- return base::Optional<std::string>("list_item");
+ return absl::optional<std::string>("list_item");
case ax::mojom::Role::kMain:
- return base::Optional<std::string>("main");
+ return absl::optional<std::string>("main");
case ax::mojom::Role::kParagraph:
- return base::Optional<std::string>("paragraph");
+ return absl::optional<std::string>("paragraph");
default:
- return base::Optional<std::string>();
+ return absl::optional<std::string>();
}
}
@@ -318,16 +312,19 @@ void WalkAXTreeDepthFirst(const AXNode* node,
}
if (end_selection > 0)
result->selection =
- base::make_optional<gfx::Range>(start_selection, end_selection);
+ absl::make_optional<gfx::Range>(start_selection, end_selection);
}
result->html_tag =
node->GetStringAttribute(ax::mojom::StringAttribute::kHtmlTag);
- node->GetHtmlAttribute("id", &result->html_id);
- result->html_class =
- node->GetStringAttribute(ax::mojom::StringAttribute::kClassName);
result->css_display =
node->GetStringAttribute(ax::mojom::StringAttribute::kDisplay);
+ result->html_attributes = node->data().html_attributes;
+
+ std::string class_name =
+ node->GetStringAttribute(ax::mojom::StringAttribute::kClassName);
+ if (!class_name.empty())
+ result->html_attributes.push_back({"class", class_name});
for (size_t i = 0; i < node->GetUnignoredChildCount(); ++i) {
AXNode* child = node->GetUnignoredChildAtIndex(i);
diff --git a/chromium/ui/accessibility/ax_assistant_structure.h b/chromium/ui/accessibility/ax_assistant_structure.h
index c9003cfd36f..87cae9df62f 100644
--- a/chromium/ui/accessibility/ax_assistant_structure.h
+++ b/chromium/ui/accessibility/ax_assistant_structure.h
@@ -12,7 +12,7 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_enums.mojom-forward.h"
#include "ui/accessibility/ax_export.h"
#include "ui/accessibility/ax_tree_update.h"
@@ -45,7 +45,7 @@ struct AssistantNode {
bool line_through;
// Selected portion of the text.
- base::Optional<gfx::Range> selection;
+ absl::optional<gfx::Range> selection;
// Fake Android view class name of the element. Each node is assigned
// a closest approximation of Android's views to keep the server happy.
@@ -53,13 +53,14 @@ struct AssistantNode {
// HTML and CSS attributes.
std::string html_tag;
- std::string html_id;
- std::string html_class;
std::string css_display;
+ // HTML attributes: map from lowercase ASCII HTML attribute name to value.
+ base::StringPairs html_attributes;
+
// Accessibility functionality of the node inferred from DOM or based on HTML
// role attribute.
- base::Optional<std::string> role;
+ absl::optional<std::string> role;
};
struct AssistantTree {
diff --git a/chromium/ui/accessibility/ax_enum_util.cc b/chromium/ui/accessibility/ax_enum_util.cc
index dcd52498110..2e3200de4f1 100644
--- a/chromium/ui/accessibility/ax_enum_util.cc
+++ b/chromium/ui/accessibility/ax_enum_util.cc
@@ -338,8 +338,6 @@ const char* ToString(ax::mojom::Role role) {
return "iframe";
case ax::mojom::Role::kIframePresentational:
return "iframePresentational";
- case ax::mojom::Role::kIgnored:
- return "ignored";
case ax::mojom::Role::kImage:
return "image";
case ax::mojom::Role::kImeCandidate:
@@ -422,8 +420,6 @@ const char* ToString(ax::mojom::Role role) {
return "portal";
case ax::mojom::Role::kPre:
return "pre";
- case ax::mojom::Role::kPresentational:
- return "presentational";
case ax::mojom::Role::kProgressIndicator:
return "progressIndicator";
case ax::mojom::Role::kRadioButton:
@@ -792,8 +788,8 @@ const char* ToString(ax::mojom::StringAttribute string_attribute) {
return "liveRelevant";
case ax::mojom::StringAttribute::kLiveStatus:
return "liveStatus";
- case ax::mojom::StringAttribute::kParentTreeNodeAppId:
- return "parentTreeNodeAppId";
+ case ax::mojom::StringAttribute::kAppId:
+ return "appId";
case ax::mojom::StringAttribute::kPlaceholder:
return "placeholder";
case ax::mojom::StringAttribute::kRole:
@@ -971,8 +967,8 @@ const char* ToString(ax::mojom::BoolAttribute bool_attribute) {
return "none";
case ax::mojom::BoolAttribute::kBusy:
return "busy";
- case ax::mojom::BoolAttribute::kEditableRoot:
- return "editableRoot";
+ case ax::mojom::BoolAttribute::kContentEditableRoot:
+ return "contentEditableRoot";
case ax::mojom::BoolAttribute::kContainerLiveAtomic:
return "containerLiveAtomic";
case ax::mojom::BoolAttribute::kContainerLiveBusy:
@@ -1498,14 +1494,18 @@ const char* ToString(ax::mojom::DescriptionFrom description_from) {
switch (description_from) {
case ax::mojom::DescriptionFrom::kNone:
return "none";
- case ax::mojom::DescriptionFrom::kUninitialized:
- return "uninitialized";
- case ax::mojom::DescriptionFrom::kAttribute:
- return "attribute";
- case ax::mojom::DescriptionFrom::kContents:
- return "contents";
+ case ax::mojom::DescriptionFrom::kAriaDescription:
+ return "ariaDescription";
+ case ax::mojom::DescriptionFrom::kButtonLabel:
+ return "buttonLabel";
case ax::mojom::DescriptionFrom::kRelatedElement:
return "relatedElement";
+ case ax::mojom::DescriptionFrom::kRubyAnnotation:
+ return "rubyAnnotation";
+ case ax::mojom::DescriptionFrom::kSummary:
+ return "summary";
+ case ax::mojom::DescriptionFrom::kTableCaption:
+ return "tableCaption";
case ax::mojom::DescriptionFrom::kTitle:
return "title";
}
diff --git a/chromium/ui/accessibility/ax_enums.mojom b/chromium/ui/accessibility/ax_enums.mojom
index 6ff101120cc..5097998533f 100644
--- a/chromium/ui/accessibility/ax_enums.mojom
+++ b/chromium/ui/accessibility/ax_enums.mojom
@@ -25,68 +25,73 @@ module ax.mojom;
// If unspecified, the attribute is used across web and native on multiple
// platforms.
+// Next version: 1
+// Next value: 59
+[Extensible, Stable, Uuid="686e661e-f8c7-4214-8713-1f66d95d3ffa"]
enum Event {
- kNone,
- kActiveDescendantChanged,
- kAlert,
- kAriaAttributeChanged, // Implicit
- kAutocorrectionOccured, // Unknown: http://crbug.com/392498
- kBlur, // Remove: http://crbug.com/392502
- kCheckedStateChanged, // Implicit
- kChildrenChanged,
- kClicked,
- kControlsChanged,
- kDocumentSelectionChanged,
- kDocumentTitleChanged,
- kEndOfTest, // Sentinel value indicating the end of a test
- kExpandedChanged, // Web
- kFocus,
- kFocusAfterMenuClose,
- kFocusContext, // Contextual focus event that must delay the next focus event
- kHide, // Remove: http://crbug.com/392502
- kHitTestResult,
- kHover,
- kImageFrameUpdated, // Web
- kLayoutComplete, // Web
- kLiveRegionCreated, // Implicit
- kLiveRegionChanged, // Web
- kLoadComplete, // Web
- kLoadStart, // Web / AuraLinux
- kLocationChanged, // Web
- kMediaStartedPlaying, // Native / Automation
- kMediaStoppedPlaying, // Native / Automation
- kMenuEnd, // Native / web: menu interaction has ended.
- kMenuListValueChanged, // Web
- kMenuPopupEnd, // Native / web: a menu/submenu is hidden/closed.
- kMenuPopupStart, // Native / web: a menu/submenu is shown/opened.
- kMenuStart, // Native / web: menu interaction has begun.
- kMouseCanceled,
- kMouseDragged,
- kMouseMoved,
- kMousePressed,
- kMouseReleased,
- kRowCollapsed,
- kRowCountChanged,
- kRowExpanded,
- kScrollPositionChanged, // Web
- kScrolledToAnchor, // Web
- kSelectedChildrenChanged, // Web
- kSelection, // Native
- kSelectionAdd, // Native
- kSelectionRemove, // Native
- kShow, // Native / Automation
- kStateChanged, // Native / Automation
- kTextChanged,
+ [Default]kNone = 0,
+ kActiveDescendantChanged = 1,
+ kAlert = 2,
+ kAriaAttributeChanged = 3, // Implicit
+ kAutocorrectionOccured = 4, // Unknown: http://crbug.com/392498
+ kBlur = 5, // Remove: http://crbug.com/392502
+ kCheckedStateChanged = 6, // Implicit
+ kChildrenChanged = 7,
+ kClicked = 8,
+ kControlsChanged = 9,
+ kDocumentSelectionChanged = 10,
+ kDocumentTitleChanged = 11,
+ kEndOfTest = 12, // Sentinel value indicating the end of a test
+ kExpandedChanged = 13, // Web
+ kFocus = 14,
+ kFocusAfterMenuClose = 15,
+
+ // Contextual focus event that must delay the next focus event.
+ kFocusContext = 16,
+ kHide = 17, // Remove: http://crbug.com/392502
+ kHitTestResult = 18,
+ kHover = 19,
+ kImageFrameUpdated = 20, // Web
+ kLayoutComplete = 21, // Web
+ kLiveRegionCreated = 22, // Implicit
+ kLiveRegionChanged = 23, // Web
+ kLoadComplete = 24, // Web
+ kLoadStart = 25, // Web / AuraLinux
+ kLocationChanged = 26, // Web
+ kMediaStartedPlaying = 27, // Native / Automation
+ kMediaStoppedPlaying = 28, // Native / Automation
+ kMenuEnd = 29, // Native / web: menu interaction has ended.
+ kMenuListValueChanged = 30, // Web
+ kMenuPopupEnd = 31, // Native / web: a menu/submenu is hidden/closed.
+ kMenuPopupStart = 32, // Native / web: a menu/submenu is shown/opened.
+ kMenuStart = 33, // Native / web: menu interaction has begun.
+ kMouseCanceled = 34,
+ kMouseDragged = 35,
+ kMouseMoved = 36,
+ kMousePressed = 37,
+ kMouseReleased = 38,
+ kRowCollapsed = 39,
+ kRowCountChanged = 40,
+ kRowExpanded = 41,
+ kScrollPositionChanged = 42, // Web
+ kScrolledToAnchor = 43, // Web
+ kSelectedChildrenChanged = 44, // Web
+ kSelection = 45, // Native
+ kSelectionAdd = 46, // Native
+ kSelectionRemove = 47, // Native
+ kShow = 48, // Native / Automation
+ kStateChanged = 49, // Native / Automation
+ kTextChanged = 50,
// TODO(nektar): Remove kTextSelectionChanged.
- kTextSelectionChanged,
- kTooltipClosed,
- kTooltipOpened,
- kTreeChanged, // Don't explicitly fire this event.
+ kTextSelectionChanged = 51,
+ kTooltipClosed = 52,
+ kTooltipOpened = 53,
+ kTreeChanged = 54, // Don't explicitly fire this event.
// TODO(nektar): Remove kValueChanged.
- kValueChanged,
- kWindowActivated, // Native
- kWindowDeactivated, // Native
- kWindowVisibilityChanged, // Native
+ kValueChanged = 55,
+ kWindowActivated = 56, // Native
+ kWindowDeactivated = 57, // Native
+ kWindowVisibilityChanged = 58, // Native
};
// Accessibility object roles.
@@ -102,7 +107,7 @@ enum Event {
//
// Native: this attribute is only used in native UI.
enum Role {
- kNone,
+ kNone, // Used for role="none"/"presentation" -- ignored in platform tree.
kAbbr,
kAlert,
kAlertDialog,
@@ -212,7 +217,6 @@ enum Role {
kHeading,
kIframe,
kIframePresentational,
- kIgnored,
kImage,
kImeCandidate,
kInlineTextBox,
@@ -257,7 +261,6 @@ enum Role {
kPopUpButton,
kPortal,
kPre,
- kPresentational,
kProgressIndicator,
kRadioButton,
kRadioGroup,
@@ -333,102 +336,105 @@ enum State {
// An action to be taken on an accessibility node.
// In contrast to |AXDefaultActionVerb|, these describe what happens to the
// object, e.g. "FOCUS".
+// Next version: 1
+// Next value: 33
+[Extensible, Stable, Uuid="ed8e4466-0522-4f98-ac28-59a523b70232"]
enum Action {
- kNone,
+ [Default]kNone = 0,
// Request image annotations for all the eligible images on a page.
- kAnnotatePageImages,
+ kAnnotatePageImages = 1,
- kBlur,
+ kBlur = 2,
// Notifies a node that it no longer has accessibility focus.
// Currently used only on Android and only internally, it's not
// exposed to the open web. See kSetAccessibilityFocus, below.
- kClearAccessibilityFocus,
+ kClearAccessibilityFocus = 3,
// Collapse the collapsible node.
- kCollapse,
+ kCollapse = 4,
- kCustomAction,
+ kCustomAction = 5,
// Decrement a slider or range control by one step value.
- kDecrement,
+ kDecrement = 6,
// Do the default action for an object, typically this means "click".
- kDoDefault,
+ kDoDefault = 7,
// Expand the expandable node.
- kExpand,
+ kExpand = 8,
- kFocus,
+ kFocus = 9,
// Return the content of this image object in the image_data attribute.
- kGetImageData,
+ kGetImageData = 10,
// Gets the bounding rect for a range of text.
- kGetTextLocation,
+ kGetTextLocation = 11,
- kHideTooltip,
+ kHideTooltip = 12,
// Given a point, find the object it corresponds to and fire a
// |AXActionData.hit_test_event_to_fire| event on it in response.
- kHitTest,
+ kHitTest = 13,
// Increment a slider or range control by one step value.
- kIncrement,
+ kIncrement = 14,
// For internal use only; signals to tree sources to invalidate an entire
// tree.
- kInternalInvalidateTree,
+ kInternalInvalidateTree = 15,
// Load inline text boxes for this subtree, providing information
// about word boundaries, line layout, and individual character
// bounding boxes.
- kLoadInlineTextBoxes,
+ kLoadInlineTextBoxes = 16,
// Delete any selected text in the control's text value and
// insert |AXActionData::value| in its place, like when typing or pasting.
- kReplaceSelectedText,
+ kReplaceSelectedText = 17,
// Scrolls by approximately one screen in a specific direction. Should be
// called on a node that has scrollable boolean set to true.
- kScrollBackward,
- kScrollDown,
- kScrollForward,
- kScrollLeft,
- kScrollRight,
- kScrollUp,
+ kScrollBackward = 18,
+ kScrollDown = 19,
+ kScrollForward = 20,
+ kScrollLeft = 21,
+ kScrollRight = 22,
+ kScrollUp = 23,
// Scroll any scrollable containers to make the target object visible
// on the screen. Optionally pass a subfocus rect in
// AXActionData.target_rect, in node-local coordinates.
- kScrollToMakeVisible,
+ kScrollToMakeVisible = 24,
// Scroll the given object to a specified point on the screen in
// global screen coordinates. Pass a point in AXActionData.target_point.
- kScrollToPoint,
+ kScrollToPoint = 25,
// Notifies a node that it has accessibility focus.
// Currently used only on Android and only internally, it's not
// exposed to the open web. See kClearAccessibilityFocus, above.
- kSetAccessibilityFocus,
+ kSetAccessibilityFocus = 26,
- kSetScrollOffset,
- kSetSelection,
+ kSetScrollOffset = 27,
+ kSetSelection = 28,
// Don't focus this node, but set it as the sequential focus navigation
// starting point, so that pressing Tab moves to the next element
// following this one, for example.
- kSetSequentialFocusNavigationStartingPoint,
+ kSetSequentialFocusNavigationStartingPoint = 29,
// Replace the value of the control with AXActionData::value and
// reset the selection, if applicable.
- kSetValue,
- kShowContextMenu,
+ kSetValue = 30,
+ kShowContextMenu = 31,
// Send an event signaling the end of a test.
- kSignalEndOfTest,
- kShowTooltip,
+ kSignalEndOfTest = 32,
+ kShowTooltip = 33,
};
enum ActionFlags {
@@ -440,23 +446,28 @@ enum ActionFlags {
// A list of valid values for the horizontal and vertical scroll alignment
// arguments in |AXActionData|. These values control where a node is scrolled
// in the viewport.
+// Next version: 1
+// Next value: 6
+[Extensible, Stable, Uuid="a9d4f137-4f2e-4533-a4ac-cabdc433ecee"]
enum ScrollAlignment {
- kNone,
- kScrollAlignmentCenter,
- kScrollAlignmentTop,
- kScrollAlignmentBottom,
- kScrollAlignmentLeft,
- kScrollAlignmentRight,
- kScrollAlignmentClosestEdge
+ [Default]kNone = 0,
+ kScrollAlignmentCenter = 1,
+ kScrollAlignmentTop = 2,
+ kScrollAlignmentBottom = 3,
+ kScrollAlignmentLeft = 4,
+ kScrollAlignmentRight = 5,
+ kScrollAlignmentClosestEdge = 6
};
// A list of valid values for the scroll behavior argument to argument in
// |AXActionData|. These values control whether a node is scrolled in the
// viewport if it is already visible.
+// Next version: 1
+[Extensible, Stable, Uuid="8bf2a1cb-2edb-4e41-8d7e-a6c8baa95c85"]
enum ScrollBehavior {
- kNone,
- kDoNotScrollIfVisible,
- kScrollIfVisible,
+ [Default]kNone = 0,
+ kDoNotScrollIfVisible = 1,
+ kScrollIfVisible = 2,
};
// A list of valid values for the |AXIntAttribute| |default_action_verb|.
@@ -496,6 +507,7 @@ enum Mutation {
enum StringAttribute {
kNone,
kAccessKey,
+ kAppId,
// Only used when invalid_state == invalid_state_other.
kAriaInvalidValue,
kAutoComplete,
@@ -505,7 +517,7 @@ enum StringAttribute {
kClassName,
kContainerLiveRelevant,
kContainerLiveStatus,
- kDescription,
+ kDescription, // Any description, from any description source.
kDisplay,
// Only present when different from parent.
kFontFamily,
@@ -522,7 +534,6 @@ enum StringAttribute {
kName,
kLiveRelevant,
kLiveStatus,
- kParentTreeNodeAppId,
// Only if not already exposed in kName (NameFrom::kPlaceholder)
kPlaceholder,
kRole,
@@ -708,9 +719,9 @@ enum BoolAttribute {
// Generic busy state, does not have to be on a live region.
kBusy,
- // The object is at the root of an editable field, such as a content
- // editable.
- kEditableRoot,
+ // The object is at the root of a content editable region, or at a <body>
+ // element that has "design-mode" set to "on".
+ kContentEditableRoot,
// Live region attributes.
kContainerLiveAtomic,
@@ -1079,11 +1090,13 @@ enum NameFrom {
enum DescriptionFrom {
kNone,
- kUninitialized,
- kAttribute,
- kContents,
+ kAriaDescription,
+ kButtonLabel, // HTML-AAM 5.2.2
kRelatedElement,
- kTitle,
+ kRubyAnnotation,
+ kSummary, // HTML-AAM 5.8.2
+ kTableCaption, // HTML-AAM 5.9.2
+ kTitle
};
enum EventFrom {
diff --git a/chromium/ui/accessibility/ax_event_generator.cc b/chromium/ui/accessibility/ax_event_generator.cc
index ebc55f7490f..6290c3932b3 100644
--- a/chromium/ui/accessibility/ax_event_generator.cc
+++ b/chromium/ui/accessibility/ax_event_generator.cc
@@ -342,6 +342,10 @@ void AXEventGenerator::OnStateChanged(AXTree* tree,
AddEvent(node, Event::IGNORED_CHANGED);
if (!new_value)
AddEvent(node, Event::SUBTREE_CREATED);
+ if (node->data().role == ax::mojom::Role::kMenu) {
+ new_value ? AddEvent(node, Event::MENU_POPUP_END)
+ : AddEvent(node, Event::MENU_POPUP_START);
+ }
break;
}
case ax::mojom::State::kMultiline:
@@ -1195,6 +1199,10 @@ const char* ToString(AXEventGenerator::Event event) {
return "loadStart";
case AXEventGenerator::Event::MENU_ITEM_SELECTED:
return "menuItemSelected";
+ case ui::AXEventGenerator::Event::MENU_POPUP_END:
+ return "menuPopupEnd";
+ case ui::AXEventGenerator::Event::MENU_POPUP_START:
+ return "menuPopupStart";
case AXEventGenerator::Event::MULTILINE_STATE_CHANGED:
return "multilineStateChanged";
case AXEventGenerator::Event::MULTISELECTABLE_STATE_CHANGED:
diff --git a/chromium/ui/accessibility/ax_event_generator.h b/chromium/ui/accessibility/ax_event_generator.h
index 96dbf98525e..71d124e1501 100644
--- a/chromium/ui/accessibility/ax_event_generator.h
+++ b/chromium/ui/accessibility/ax_event_generator.h
@@ -82,6 +82,8 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver {
LOAD_COMPLETE,
LOAD_START,
MENU_ITEM_SELECTED,
+ MENU_POPUP_END,
+ MENU_POPUP_START,
MULTILINE_STATE_CHANGED,
MULTISELECTABLE_STATE_CHANGED,
NAME_CHANGED,
diff --git a/chromium/ui/accessibility/ax_event_generator_unittest.cc b/chromium/ui/accessibility/ax_event_generator_unittest.cc
index e612489e4b7..9ed23892c9b 100644
--- a/chromium/ui/accessibility/ax_event_generator_unittest.cc
+++ b/chromium/ui/accessibility/ax_event_generator_unittest.cc
@@ -523,7 +523,6 @@ TEST(AXEventGeneratorTest, SelectionInTextFieldChanged) {
text_field.role = ax::mojom::Role::kTextField;
text_field.SetValue("Testing");
text_field.AddState(ax::mojom::State::kEditable);
- text_field.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot, true);
root.child_ids = {text_field.id};
@@ -615,7 +614,6 @@ TEST(AXEventGeneratorTest, ValueInTextFieldChanged) {
text_field.id = 1;
text_field.role = ax::mojom::Role::kTextField;
text_field.AddState(ax::mojom::State::kEditable);
- text_field.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot, true);
text_field.SetValue("Before");
AXTreeUpdate initial_state;
@@ -665,7 +663,6 @@ TEST(AXEventGeneratorTest, InvalidStatusChanged) {
text_field.id = 1;
text_field.role = ax::mojom::Role::kTextField;
text_field.AddState(ax::mojom::State::kEditable);
- text_field.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot, true);
text_field.AddStringAttribute(ax::mojom::StringAttribute::kValue, "Text");
AXTreeUpdate initial_state;
@@ -2442,7 +2439,6 @@ TEST(AXEventGeneratorTest, RequiredStateChanged) {
text_field.id = 1;
text_field.role = ax::mojom::Role::kTextField;
text_field.AddState(ax::mojom::State::kEditable);
- text_field.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot, true);
AXTreeUpdate initial_state;
initial_state.root_id = text_field.id;
@@ -2654,7 +2650,6 @@ TEST(AXEventGeneratorTest, EditableTextChanged) {
text_field.id = 2;
text_field.role = ax::mojom::Role::kTextField;
text_field.AddState(ax::mojom::State::kEditable);
- text_field.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot, true);
text_field.SetValue("Before");
root.child_ids = {text_field.id};
diff --git a/chromium/ui/accessibility/ax_hypertext.cc b/chromium/ui/accessibility/ax_hypertext.cc
new file mode 100644
index 00000000000..a6770a16f33
--- /dev/null
+++ b/chromium/ui/accessibility/ax_hypertext.cc
@@ -0,0 +1,14 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/ax_hypertext.h"
+
+namespace ui {
+
+AXHypertext::AXHypertext() = default;
+AXHypertext::~AXHypertext() = default;
+AXHypertext::AXHypertext(const AXHypertext& other) = default;
+AXHypertext& AXHypertext::operator=(const AXHypertext& other) = default;
+
+} // namespace ui
diff --git a/chromium/ui/accessibility/ax_hypertext.h b/chromium/ui/accessibility/ax_hypertext.h
new file mode 100644
index 00000000000..6abb3d7498a
--- /dev/null
+++ b/chromium/ui/accessibility/ax_hypertext.h
@@ -0,0 +1,50 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ACCESSIBILITY_AX_HYPERTEXT_H_
+#define UI_ACCESSIBILITY_AX_HYPERTEXT_H_
+
+#include <map>
+#include <ostream>
+#include <string>
+#include <vector>
+
+#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/ax_node_data.h"
+
+namespace ui {
+
+// Stores the hypertext for an `AXNode` in the accessibility tree. Hypertext has
+// nothing to do with HTML but is how displayed text and embedded objects are
+// represented in ATK and IAccessible2 APIs.
+//
+// Hypertext is computed as follows: If this node is a leaf, returns the inner
+// text of this node. This is equivalent to its visible accessible name.
+// Otherwise, if this node is not a leaf, represents every non-textual child
+// node with a special "embedded object character", and every textual child node
+// with its inner text. Textual nodes include e.g. static text and white space.
+// Each non-textual child node is also called a hyperlink.
+struct AX_EXPORT AXHypertext {
+ AXHypertext();
+ ~AXHypertext();
+ AXHypertext(const AXHypertext& other);
+ AXHypertext& operator=(const AXHypertext& other);
+
+ // A flag that should be set if the hypertext information in this struct is
+ // out-of-date and needs to be updated. This flag should always be set upon
+ // construction because constructing this struct doesn't compute the
+ // hypertext.
+ bool needs_update = true;
+
+ // Maps an embedded character offset in |hypertext| to an index in the list of
+ // unignored children. A hyperlink is defined as any non-textual child.
+ std::map<int, int> hypertext_offset_to_hyperlink_child_index;
+
+ // See class comment for information on how this is computed.
+ std::u16string hypertext;
+};
+
+} // namespace ui
+
+#endif // UI_ACCESSIBILITY_AX_HYPERTEXT_H_
diff --git a/chromium/ui/accessibility/ax_node.cc b/chromium/ui/accessibility/ax_node.cc
index 4f6ca792e4d..e6cf4b3c4df 100644
--- a/chromium/ui/accessibility/ax_node.cc
+++ b/chromium/ui/accessibility/ax_node.cc
@@ -15,6 +15,7 @@
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/accessibility/ax_hypertext.h"
#include "ui/accessibility/ax_language_detection.h"
#include "ui/accessibility/ax_role_properties.h"
#include "ui/accessibility/ax_table_info.h"
@@ -629,13 +630,16 @@ void AXNode::ClearLanguageInfo() {
std::u16string AXNode::GetHypertext() const {
DCHECK(!tree_->GetTreeUpdateInProgressState());
+ // TODO(nektar): Introduce proper caching of hypertext via
+ // `AXHypertext::needs_update`.
+ hypertext_ = AXHypertext();
// Hypertext is not exposed for descendants of leaf nodes. For such nodes,
// their inner text is equivalent to their hypertext. Otherwise, we would
- // never be able to compute equivalent ancestor positions in text fields given
- // an AXPosition on an inline text box descendant, because there is often an
- // ignored generic container between the text descendants and the text field
- // node.
+ // never be able to compute equivalent ancestor positions in atomic text
+ // fields given an AXPosition on an inline text box descendant, because there
+ // is often an ignored generic container between the text descendants and the
+ // text field node.
//
// For example, look at the following accessibility tree and the text
// positions indicated using "<>" symbols in the inner text of every node, and
@@ -646,29 +650,62 @@ std::u16string AXNode::GetHypertext() const {
// ++++kGenericContainer "Hell<o>" ignored IsChildOfLeaf=true
// ++++++kStaticText "Hell<o>" IsChildOfLeaf=true
// ++++++++kInlineTextBox "Hell<o>" IsChildOfLeaf=true
- if (IsLeaf() || IsChildOfLeaf())
- return base::UTF8ToUTF16(GetInnerText());
- // Construct the hypertext for this node, which contains the concatenation of
- // the inner text of this node's textual children, and an "object replacement
- // character" for all the other children.
- //
- // Note that the word "hypertext" comes from the IAccessible2 Standard and has
- // nothing to do with HTML.
- const std::u16string embedded_character_str(kEmbeddedCharacter);
- DCHECK_EQ(int{embedded_character_str.length()}, kEmbeddedCharacterLength);
- std::u16string hypertext;
- for (auto it = UnignoredChildrenBegin(); it != UnignoredChildrenEnd(); ++it) {
- // Similar to Firefox, we don't expose text nodes in IAccessible2 and ATK
- // hypertext with the embedded object character. We copy all of their text
- // instead.
- if (it->IsText()) {
- hypertext += base::UTF8ToUTF16(it->GetInnerText());
- } else {
- hypertext += embedded_character_str;
+ if (IsLeaf() || IsChildOfLeaf()) {
+ hypertext_.hypertext = base::UTF8ToUTF16(GetInnerText());
+ } else {
+ // Construct the hypertext for this node, which contains the concatenation
+ // of the inner text of this node's textual children, and an "object
+ // replacement character" for all the other children.
+ //
+ // Note that the word "hypertext" comes from the IAccessible2 Standard and
+ // has nothing to do with HTML.
+ const std::u16string embedded_character_str(kEmbeddedCharacter);
+ DCHECK_EQ(int{embedded_character_str.length()}, kEmbeddedCharacterLength);
+ for (size_t i = 0; i < GetUnignoredChildCountCrossingTreeBoundary(); ++i) {
+ const AXNode* child = GetUnignoredChildAtIndexCrossingTreeBoundary(i);
+ // Similar to Firefox, we don't expose text nodes in IAccessible2 and ATK
+ // hypertext with the embedded object character. We copy all of their text
+ // instead.
+ if (child->IsText()) {
+ hypertext_.hypertext += base::UTF8ToUTF16(child->GetInnerText());
+ } else {
+ int character_offset = int{hypertext_.hypertext.size()};
+ auto inserted =
+ hypertext_.hypertext_offset_to_hyperlink_child_index.emplace(
+ character_offset, int{i});
+ DCHECK(inserted.second) << "An embedded object at " << character_offset
+ << " has already been encountered.";
+ hypertext_.hypertext += embedded_character_str;
+ }
}
}
- return hypertext;
+
+ hypertext_.needs_update = false;
+ return hypertext_.hypertext;
+}
+
+void AXNode::SetNeedsToUpdateHypertext() {
+ old_hypertext_ = hypertext_;
+ hypertext_.needs_update = true;
+ // TODO(nektar): Introduce proper caching of hypertext via
+ // `AXHypertext::needs_update`.
+ GetHypertext(); // Forces `hypertext_` to immediately update.
+}
+
+const std::map<int, int>& AXNode::GetHypertextOffsetToHyperlinkChildIndex()
+ const {
+ // TODO(nektar): Introduce proper caching of hypertext via
+ // `AXHypertext::needs_update`.
+ GetHypertext(); // Update `hypertext_` if not up-to-date.
+ return hypertext_.hypertext_offset_to_hyperlink_child_index;
+}
+
+const AXHypertext& AXNode::GetOldHypertext() const {
+ // TODO(nektar): Introduce proper caching of hypertext via
+ // `AXHypertext::needs_update`.
+ GetHypertext(); // Update `hypertext_` if not up-to-date.
+ return old_hypertext_;
}
std::string AXNode::GetInnerText() const {
@@ -690,9 +727,9 @@ std::string AXNode::GetInnerText() const {
// value or its placeholder. Otherwise we prefer to look at its descendant
// text nodes because Blink doesn't always add all trailing white space to the
// value attribute.
- const bool is_plain_text_field_without_descendants =
+ const bool is_atomic_text_field_without_descendants =
(node->data().IsTextField() && !node->GetUnignoredChildCount());
- if (is_plain_text_field_without_descendants) {
+ if (is_atomic_text_field_without_descendants) {
std::string value =
node->data().GetStringAttribute(ax::mojom::StringAttribute::kValue);
// If the value is empty, then there might be some placeholder text in the
@@ -702,13 +739,13 @@ std::string AXNode::GetInnerText() const {
return value;
}
- // Ordinarily, plain text fields are leaves. We need to exclude them from the
+ // Ordinarily, atomic text fields are leaves. We need to exclude them from the
// set of leaf nodes when they expose any descendants. This is because we want
// to compute their inner text from their descendant text nodes as we don't
// always trust the "value" attribute provided by Blink.
- const bool is_plain_text_field_with_descendants =
+ const bool is_atomic_text_field_with_descendants =
(node->data().IsTextField() && node->GetUnignoredChildCount());
- if (node->IsLeaf() && !is_plain_text_field_with_descendants) {
+ if (node->IsLeaf() && !is_atomic_text_field_with_descendants) {
switch (node->data().GetNameFrom()) {
case ax::mojom::NameFrom::kNone:
case ax::mojom::NameFrom::kUninitialized:
@@ -767,12 +804,12 @@ int AXNode::GetInnerTextLength() const {
DCHECK(node) << "All child trees should have a non-null rootnode.";
}
- const bool is_plain_text_field_with_descendants =
+ const bool is_atomic_text_field_with_descendants =
(node->data().IsTextField() && node->GetUnignoredChildCount());
- // Plain text fields are always leaves so we need to exclude them when
+ // Atomic text fields are always leaves so we need to exclude them when
// computing the length of their inner text if that text should be derived
// from their descendant nodes.
- if (node->IsLeaf() && !is_plain_text_field_with_descendants)
+ if (node->IsLeaf() && !is_atomic_text_field_with_descendants)
return int{node->GetInnerText().length()};
int inner_text_length = 0;
@@ -824,52 +861,52 @@ bool AXNode::IsTable() const {
return IsTableLike(data().role);
}
-base::Optional<int> AXNode::GetTableColCount() const {
+absl::optional<int> AXNode::GetTableColCount() const {
DCHECK(!tree_->GetTreeUpdateInProgressState());
const AXTableInfo* table_info = GetAncestorTableInfo();
if (!table_info)
- return base::nullopt;
+ return absl::nullopt;
return int{table_info->col_count};
}
-base::Optional<int> AXNode::GetTableRowCount() const {
+absl::optional<int> AXNode::GetTableRowCount() const {
DCHECK(!tree_->GetTreeUpdateInProgressState());
const AXTableInfo* table_info = GetAncestorTableInfo();
if (!table_info)
- return base::nullopt;
+ return absl::nullopt;
return int{table_info->row_count};
}
-base::Optional<int> AXNode::GetTableAriaColCount() const {
+absl::optional<int> AXNode::GetTableAriaColCount() const {
DCHECK(!tree_->GetTreeUpdateInProgressState());
const AXTableInfo* table_info = GetAncestorTableInfo();
if (!table_info)
- return base::nullopt;
- return base::make_optional(table_info->aria_col_count);
+ return absl::nullopt;
+ return absl::make_optional(table_info->aria_col_count);
}
-base::Optional<int> AXNode::GetTableAriaRowCount() const {
+absl::optional<int> AXNode::GetTableAriaRowCount() const {
DCHECK(!tree_->GetTreeUpdateInProgressState());
const AXTableInfo* table_info = GetAncestorTableInfo();
if (!table_info)
- return base::nullopt;
- return base::make_optional(table_info->aria_row_count);
+ return absl::nullopt;
+ return absl::make_optional(table_info->aria_row_count);
}
-base::Optional<int> AXNode::GetTableCellCount() const {
+absl::optional<int> AXNode::GetTableCellCount() const {
DCHECK(!tree_->GetTreeUpdateInProgressState());
const AXTableInfo* table_info = GetAncestorTableInfo();
if (!table_info)
- return base::nullopt;
+ return absl::nullopt;
return static_cast<int>(table_info->unique_cell_ids.size());
}
-base::Optional<bool> AXNode::GetTableHasColumnOrRowHeaderNode() const {
+absl::optional<bool> AXNode::GetTableHasColumnOrRowHeaderNode() const {
DCHECK(!tree_->GetTreeUpdateInProgressState());
const AXTableInfo* table_info = GetAncestorTableInfo();
if (!table_info)
- return base::nullopt;
+ return absl::nullopt;
return !table_info->all_headers.empty();
}
@@ -980,17 +1017,17 @@ bool AXNode::IsTableRow() const {
return ui::IsTableRow(data().role);
}
-base::Optional<int> AXNode::GetTableRowRowIndex() const {
+absl::optional<int> AXNode::GetTableRowRowIndex() const {
if (!IsTableRow())
- return base::nullopt;
+ return absl::nullopt;
const AXTableInfo* table_info = GetAncestorTableInfo();
if (!table_info)
- return base::nullopt;
+ return absl::nullopt;
const auto& iter = table_info->row_id_to_index.find(id());
if (iter == table_info->row_id_to_index.end())
- return base::nullopt;
+ return absl::nullopt;
return int{iter->second};
}
@@ -1016,13 +1053,13 @@ bool AXNode::IsTableColumn() const {
return ui::IsTableColumn(data().role);
}
-base::Optional<int> AXNode::GetTableColColIndex() const {
+absl::optional<int> AXNode::GetTableColColIndex() const {
if (!IsTableColumn())
- return base::nullopt;
+ return absl::nullopt;
const AXTableInfo* table_info = GetAncestorTableInfo();
if (!table_info)
- return base::nullopt;
+ return absl::nullopt;
int index = 0;
for (const AXNode* node : table_info->extra_mac_nodes) {
@@ -1043,48 +1080,48 @@ bool AXNode::IsTableCellOrHeader() const {
return IsCellOrTableHeader(data().role);
}
-base::Optional<int> AXNode::GetTableCellIndex() const {
+absl::optional<int> AXNode::GetTableCellIndex() const {
if (!IsTableCellOrHeader())
- return base::nullopt;
+ return absl::nullopt;
const AXTableInfo* table_info = GetAncestorTableInfo();
if (!table_info)
- return base::nullopt;
+ return absl::nullopt;
const auto& iter = table_info->cell_id_to_index.find(id());
if (iter != table_info->cell_id_to_index.end())
return int{iter->second};
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<int> AXNode::GetTableCellColIndex() const {
+absl::optional<int> AXNode::GetTableCellColIndex() const {
const AXTableInfo* table_info = GetAncestorTableInfo();
if (!table_info)
- return base::nullopt;
+ return absl::nullopt;
- base::Optional<int> index = GetTableCellIndex();
+ absl::optional<int> index = GetTableCellIndex();
if (!index)
- return base::nullopt;
+ return absl::nullopt;
return int{table_info->cell_data_vector[*index].col_index};
}
-base::Optional<int> AXNode::GetTableCellRowIndex() const {
+absl::optional<int> AXNode::GetTableCellRowIndex() const {
const AXTableInfo* table_info = GetAncestorTableInfo();
if (!table_info)
- return base::nullopt;
+ return absl::nullopt;
- base::Optional<int> index = GetTableCellIndex();
+ absl::optional<int> index = GetTableCellIndex();
if (!index)
- return base::nullopt;
+ return absl::nullopt;
return int{table_info->cell_data_vector[*index].row_index};
}
-base::Optional<int> AXNode::GetTableCellColSpan() const {
+absl::optional<int> AXNode::GetTableCellColSpan() const {
// If it's not a table cell, don't return a col span.
if (!IsTableCellOrHeader())
- return base::nullopt;
+ return absl::nullopt;
// Otherwise, try to return a colspan, with 1 as the default if it's not
// specified.
@@ -1094,10 +1131,10 @@ base::Optional<int> AXNode::GetTableCellColSpan() const {
return 1;
}
-base::Optional<int> AXNode::GetTableCellRowSpan() const {
+absl::optional<int> AXNode::GetTableCellRowSpan() const {
// If it's not a table cell, don't return a row span.
if (!IsTableCellOrHeader())
- return base::nullopt;
+ return absl::nullopt;
// Otherwise, try to return a row span, with 1 as the default if it's not
// specified.
@@ -1107,26 +1144,26 @@ base::Optional<int> AXNode::GetTableCellRowSpan() const {
return 1;
}
-base::Optional<int> AXNode::GetTableCellAriaColIndex() const {
+absl::optional<int> AXNode::GetTableCellAriaColIndex() const {
const AXTableInfo* table_info = GetAncestorTableInfo();
if (!table_info)
- return base::nullopt;
+ return absl::nullopt;
- base::Optional<int> index = GetTableCellIndex();
+ absl::optional<int> index = GetTableCellIndex();
if (!index)
- return base::nullopt;
+ return absl::nullopt;
return int{table_info->cell_data_vector[*index].aria_col_index};
}
-base::Optional<int> AXNode::GetTableCellAriaRowIndex() const {
+absl::optional<int> AXNode::GetTableCellAriaRowIndex() const {
const AXTableInfo* table_info = GetAncestorTableInfo();
if (!table_info)
- return base::nullopt;
+ return absl::nullopt;
- base::Optional<int> index = GetTableCellIndex();
+ absl::optional<int> index = GetTableCellIndex();
if (!index)
- return base::nullopt;
+ return absl::nullopt;
return int{table_info->cell_data_vector[*index].aria_row_index};
}
@@ -1212,7 +1249,7 @@ void AXNode::IdVectorToNodeVector(const std::vector<AXNodeID>& ids,
}
}
-base::Optional<int> AXNode::GetHierarchicalLevel() const {
+absl::optional<int> AXNode::GetHierarchicalLevel() const {
int hierarchical_level =
GetIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel);
@@ -1222,7 +1259,7 @@ base::Optional<int> AXNode::GetHierarchicalLevel() const {
if (hierarchical_level > 0)
return hierarchical_level;
- return base::nullopt;
+ return absl::nullopt;
}
bool AXNode::IsOrderedSetItem() const {
@@ -1234,12 +1271,12 @@ bool AXNode::IsOrderedSet() const {
}
// Uses AXTree's cache to calculate node's PosInSet.
-base::Optional<int> AXNode::GetPosInSet() {
+absl::optional<int> AXNode::GetPosInSet() {
return tree_->GetPosInSet(*this);
}
// Uses AXTree's cache to calculate node's SetSize.
-base::Optional<int> AXNode::GetSetSize() {
+absl::optional<int> AXNode::GetSetSize() {
return tree_->GetSetSize(*this);
}
@@ -1392,7 +1429,7 @@ std::string AXNode::GetValueForTextField() const {
// Some screen readers like Jaws and VoiceOver require a value to be set in
// text fields with rich content, even though the same information is
// available on the children.
- if (value.empty() && data().IsRichTextField())
+ if (value.empty() && data().IsNonAtomicTextField())
return GetInnerText();
return value;
}
@@ -1483,7 +1520,7 @@ bool AXNode::IsLeaf() const {
// different return values here, even though 'contenteditable' has no effect.
// This needs to be modified from the Blink side, so 'kRichlyEditable' isn't
// added in this case.
- if (data().IsPlainTextField() || IsText())
+ if (data().IsAtomicTextField() || IsText())
return true;
// Roles whose children are only presentational according to the ARIA and
@@ -1507,6 +1544,7 @@ bool AXNode::IsLeaf() const {
case ax::mojom::Role::kGraphicsSymbol:
case ax::mojom::Role::kMeter:
case ax::mojom::Role::kScrollBar:
+ case ax::mojom::Role::kSpinButton:
case ax::mojom::Role::kSlider:
case ax::mojom::Role::kSplitter:
case ax::mojom::Role::kProgressIndicator:
@@ -1606,13 +1644,13 @@ AXNode* AXNode::GetTextFieldAncestor() const {
// The descendants of a text field usually have State::kEditable, however in
// the case of Role::kSearchBox or Role::kSpinButton being the text field
// ancestor, its immediate descendant can have Role::kGenericContainer without
- // State::kEditable. Same with inline text boxes.
+ // State::kEditable. Same with inline text boxes and placeholder text.
// TODO(nektar): Fix all such inconsistencies in Blink.
for (AXNode* ancestor = const_cast<AXNode*>(this);
ancestor &&
(ancestor->data().HasState(ax::mojom::State::kEditable) ||
ancestor->data().role == ax::mojom::Role::kGenericContainer ||
- ancestor->data().role == ax::mojom::Role::kInlineTextBox);
+ ancestor->IsText());
ancestor = ancestor->GetUnignoredParent()) {
if (ancestor->data().IsTextField())
return ancestor;
@@ -1620,9 +1658,9 @@ AXNode* AXNode::GetTextFieldAncestor() const {
return nullptr;
}
-bool AXNode::IsDescendantOfPlainTextField() const {
+bool AXNode::IsDescendantOfAtomicTextField() const {
AXNode* text_field_node = GetTextFieldAncestor();
- return text_field_node && text_field_node->data().IsPlainTextField();
+ return text_field_node && text_field_node->data().IsAtomicTextField();
}
} // namespace ui
diff --git a/chromium/ui/accessibility/ax_node.h b/chromium/ui/accessibility/ax_node.h
index 2a5841c04f8..8e192d5da27 100644
--- a/chromium/ui/accessibility/ax_node.h
+++ b/chromium/ui/accessibility/ax_node.h
@@ -12,11 +12,12 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "base/strings/char_traits.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/ax_hypertext.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_tree_id.h"
@@ -26,7 +27,7 @@ class AXTableInfo;
struct AXLanguageInfo;
struct AXTreeData;
-// One node in an AXTree.
+// This class is used to represent a node in an accessibility tree (`AXTree`).
class AX_EXPORT AXNode final {
public:
// Replacement character used to represent an embedded (or, additionally for
@@ -69,8 +70,8 @@ class AX_EXPORT AXNode final {
// See AXTree::data.
virtual const AXTreeData& data() const = 0;
- virtual base::Optional<int> GetPosInSet(const AXNode& node) = 0;
- virtual base::Optional<int> GetSetSize(const AXNode& node) = 0;
+ virtual absl::optional<int> GetPosInSet(const AXNode& node) = 0;
+ virtual absl::optional<int> GetSetSize(const AXNode& node) = 0;
virtual Selection GetUnignoredSelection() const = 0;
virtual bool GetTreeUpdateInProgressState() const = 0;
@@ -313,13 +314,13 @@ class AX_EXPORT AXNode final {
}
// Return the hierarchical level if supported.
- base::Optional<int> GetHierarchicalLevel() const;
+ absl::optional<int> GetHierarchicalLevel() const;
// PosInSet and SetSize public methods.
bool IsOrderedSetItem() const;
bool IsOrderedSet() const;
- base::Optional<int> GetPosInSet();
- base::Optional<int> GetSetSize();
+ absl::optional<int> GetPosInSet();
+ absl::optional<int> GetSetSize();
// Helpers for GetPosInSet and GetSetSize.
// Returns true if the role of ordered set matches the role of item.
@@ -347,6 +348,14 @@ class AX_EXPORT AXNode final {
// TODO(nektar): Consider changing the return value to std::string.
std::u16string GetHypertext() const;
+ // Temporary method that marks `hypertext_` dirty. This will eventually be
+ // handled by the AX tree in a followup patch.
+ void SetNeedsToUpdateHypertext();
+ // Temporary accessor methods until hypertext is fully migrated to this class.
+ // Hypertext won't eventually need to be accessed outside this class.
+ const std::map<int, int>& GetHypertextOffsetToHyperlinkChildIndex() const;
+ const AXHypertext& GetOldHypertext() const;
+
// Returns the text that is found inside this node and all its descendants;
// including text found in embedded objects.
//
@@ -376,14 +385,14 @@ class AX_EXPORT AXNode final {
// Returns empty string if no appropriate language was found.
std::string GetLanguage() const;
- // Returns the value of a control such as a plain text field, a content
- // editable, a submit button, a slider, a progress bar, a scroll bar, a meter,
- // a spinner, a <select> element, a date picker or an ARIA combo box. In order
- // to minimize cross-process communication between the renderer and the
- // browser, this method may compute the value from the control's inner text in
- // the case of a content editable. For range controls, such as sliders and
- // scroll bars, the value of aria-valuetext takes priority over the value of
- // aria-valuenow.
+ // Returns the value of a control such as an atomic text field (<input> or
+ // <textarea>), a content editable, a submit button, a slider, a progress bar,
+ // a scroll bar, a meter, a spinner, a <select> element, a date picker or an
+ // ARIA combo box. In order to minimize cross-process communication between
+ // the renderer and the browser, this method may compute the value from the
+ // control's inner text in the case of a content editable. For range controls,
+ // such as sliders and scroll bars, the value of aria-valuetext takes priority
+ // over the value of aria-valuenow.
std::string GetValueForControl() const;
//
@@ -403,15 +412,15 @@ class AX_EXPORT AXNode final {
// of the table is row 0, column 0, cell index 0 - but that same cell
// has a minimum ARIA row index of 1 and column index of 1.
//
- // The below methods return base::nullopt if the AXNode they are called on is
+ // The below methods return absl::nullopt if the AXNode they are called on is
// not inside a table.
bool IsTable() const;
- base::Optional<int> GetTableColCount() const;
- base::Optional<int> GetTableRowCount() const;
- base::Optional<int> GetTableAriaColCount() const;
- base::Optional<int> GetTableAriaRowCount() const;
- base::Optional<int> GetTableCellCount() const;
- base::Optional<bool> GetTableHasColumnOrRowHeaderNode() const;
+ absl::optional<int> GetTableColCount() const;
+ absl::optional<int> GetTableRowCount() const;
+ absl::optional<int> GetTableAriaColCount() const;
+ absl::optional<int> GetTableAriaRowCount() const;
+ absl::optional<int> GetTableCellCount() const;
+ absl::optional<bool> GetTableHasColumnOrRowHeaderNode() const;
AXNode* GetTableCaption() const;
AXNode* GetTableCellFromIndex(int index) const;
AXNode* GetTableCellFromCoords(int row_index, int col_index) const;
@@ -429,25 +438,25 @@ class AX_EXPORT AXNode final {
// Table row-like nodes.
bool IsTableRow() const;
- base::Optional<int> GetTableRowRowIndex() const;
+ absl::optional<int> GetTableRowRowIndex() const;
// Get the node ids that represent rows in a table.
std::vector<AXNodeID> GetTableRowNodeIds() const;
#if defined(OS_APPLE)
// Table column-like nodes. These nodes are only present on macOS.
bool IsTableColumn() const;
- base::Optional<int> GetTableColColIndex() const;
+ absl::optional<int> GetTableColColIndex() const;
#endif // defined(OS_APPLE)
// Table cell-like nodes.
bool IsTableCellOrHeader() const;
- base::Optional<int> GetTableCellIndex() const;
- base::Optional<int> GetTableCellColIndex() const;
- base::Optional<int> GetTableCellRowIndex() const;
- base::Optional<int> GetTableCellColSpan() const;
- base::Optional<int> GetTableCellRowSpan() const;
- base::Optional<int> GetTableCellAriaColIndex() const;
- base::Optional<int> GetTableCellAriaRowIndex() const;
+ absl::optional<int> GetTableCellIndex() const;
+ absl::optional<int> GetTableCellColIndex() const;
+ absl::optional<int> GetTableCellRowIndex() const;
+ absl::optional<int> GetTableCellColSpan() const;
+ absl::optional<int> GetTableCellRowSpan() const;
+ absl::optional<int> GetTableCellAriaColIndex() const;
+ absl::optional<int> GetTableCellAriaRowIndex() const;
std::vector<AXNodeID> GetTableCellColHeaderNodeIds() const;
std::vector<AXNodeID> GetTableCellRowHeaderNodeIds() const;
void GetTableCellColHeaders(std::vector<AXNode*>* col_headers) const;
@@ -514,10 +523,10 @@ class AX_EXPORT AXNode final {
// layer.
//
// The definition of a leaf includes nodes with children that are exclusively
- // an internal renderer implementation, such as the children of an HTML native
- // text field, as well as nodes with presentational children according to the
- // ARIA and HTML5 Specs. Also returns true if all of the node's descendants
- // are ignored.
+ // an internal renderer implementation, such as the children of an HTML-based
+ // text field (<input> and <textarea>), as well as nodes with presentational
+ // children according to the ARIA and HTML5 Specs. Also returns true if all of
+ // the node's descendants are ignored.
//
// A leaf node should never have children that are focusable or
// that might send notifications.
@@ -544,12 +553,17 @@ class AX_EXPORT AXNode final {
// If this node is within an editable region, returns the node that is at the
// root of that editable region, otherwise returns nullptr. In accessibility,
- // an editable region is synonymous to a text field.
+ // an editable region is synonymous to a node with the kTextField role, or a
+ // contenteditable without the role, (see `AXNodeData::IsTextField()`).
AXNode* GetTextFieldAncestor() const;
- // Returns true if this node is either a plain text field , or one of its
- // ancestors is.
- bool IsDescendantOfPlainTextField() const;
+ // Returns true if this node is either an atomic text field , or one of its
+ // ancestors is. An atomic text field does not expose its internal
+ // implementation to assistive software, appearing as a single leaf node in
+ // the accessibility tree. Examples include: An <input> or a <textarea> on the
+ // Web, a text field in a PDF form, a Views-based text field, or a native
+ // Android one.
+ bool IsDescendantOfAtomicTextField() const;
// Finds and returns a pointer to ordered set containing node.
AXNode* GetOrderedSet() const;
@@ -563,7 +577,7 @@ class AX_EXPORT AXNode final {
void IdVectorToNodeVector(const std::vector<AXNodeID>& ids,
std::vector<AXNode*>* nodes) const;
- int UpdateUnignoredCachedValuesRecursive(int startIndex);
+ int UpdateUnignoredCachedValuesRecursive(int start_index);
AXNode* ComputeLastUnignoredChildRecursive() const;
AXNode* ComputeFirstUnignoredChildRecursive() const;
@@ -593,6 +607,11 @@ class AX_EXPORT AXNode final {
std::vector<AXNode*> children_;
AXNodeData data_;
+ // See the class comment in "ax_hypertext.h" for an explanation of this
+ // member.
+ mutable AXHypertext hypertext_;
+ mutable AXHypertext old_hypertext_;
+
// Stores the detected language computed from the node's text.
std::unique_ptr<AXLanguageInfo> language_info_;
};
diff --git a/chromium/ui/accessibility/ax_node_data.cc b/chromium/ui/accessibility/ax_node_data.cc
index 6ce31b37e3a..e9e4c84f6d0 100644
--- a/chromium/ui/accessibility/ax_node_data.cc
+++ b/chromium/ui/accessibility/ax_node_data.cc
@@ -458,7 +458,7 @@ void AXNodeData::AddStringAttribute(ax::mojom::StringAttribute attribute,
string_attributes.push_back(std::make_pair(attribute, value));
}
-void AXNodeData::AddChildTreeId(const ui::AXTreeID& tree_id) {
+void AXNodeData::AddChildTreeId(const AXTreeID& tree_id) {
ax::mojom::StringAttribute attribute =
ax::mojom::StringAttribute::kChildTreeId;
if (HasStringAttribute(attribute))
@@ -984,8 +984,7 @@ bool AXNodeData::IsSelectable() const {
}
bool AXNodeData::IsIgnored() const {
- return HasState(ax::mojom::State::kIgnored) ||
- role == ax::mojom::Role::kIgnored;
+ return HasState(ax::mojom::State::kIgnored) || role == ax::mojom::Role::kNone;
}
bool AXNodeData::IsInvisible() const {
@@ -1022,43 +1021,25 @@ bool AXNodeData::IsMenuButton() const {
}
bool AXNodeData::IsTextField() const {
- return IsPlainTextField() || IsRichTextField();
+ return IsAtomicTextField() || IsNonAtomicTextField();
}
bool AXNodeData::IsPasswordField() const {
return IsTextField() && HasState(ax::mojom::State::kProtected);
}
-bool AXNodeData::IsPlainTextField() const {
- // We need to check both the role and editable state, because some ARIA text
- // fields may in fact not be editable, whilst some editable fields might not
- // have the role.
- if (HasState(ax::mojom::State::kRichlyEditable))
- return false;
-
- // Blink adds the "kEditableRoot" attribute to all nodes that are at the root
- // of any editable region, such as an <input> or a <textarea> field.
- if (GetBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot)) {
- DCHECK(HasState(ax::mojom::State::kEditable));
- return true;
- }
-
- // Has editable ARIA role, but is not actually editable.
- // In theory, a webpage author could create a plain text field by using any of
- // the following ARIA roles, even on elements that do not have the
- // contenteditable attribute set. For example, <div role="textbox">. However,
- // in practice it might be difficult to create such a plain text field because
- // it would be hard to support text selection and a caret without specifying
- // contenteditable="true"
- // Exposing these roles as plain text fields is harmless and simplifies tests.
- return role == ax::mojom::Role::kTextField ||
- role == ax::mojom::Role::kTextFieldWithComboBox ||
- role == ax::mojom::Role::kSearchBox;
+bool AXNodeData::IsAtomicTextField() const {
+ // ARIA-based textboxes or searchboxes could mistakenly be identified as
+ // atomic text fields, i.e. be identified as an <input> or a <textarea>. This
+ // can only occur when the web author hasn't specified the "contenteditable"
+ // attribute. Since these kinds of text fields are not really usable, we
+ // decide not to support them.
+ return ui::IsTextField(role) &&
+ !HasBoolAttribute(ax::mojom::BoolAttribute::kContentEditableRoot);
}
-bool AXNodeData::IsRichTextField() const {
- return GetBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot) &&
- HasState(ax::mojom::State::kRichlyEditable);
+bool AXNodeData::IsNonAtomicTextField() const {
+ return HasBoolAttribute(ax::mojom::BoolAttribute::kContentEditableRoot);
}
bool AXNodeData::IsReadOnlyOrDisabled() const {
@@ -1540,8 +1521,8 @@ std::string AXNodeData::ToString() const {
case ax::mojom::StringAttribute::kContainerLiveStatus:
result += " container_live=" + value;
break;
- case ax::mojom::StringAttribute::kParentTreeNodeAppId:
- result += " parent_tree_node_app_id=" + value.substr(0, 8);
+ case ax::mojom::StringAttribute::kAppId:
+ result += " app_id=" + value.substr(0, 8);
break;
case ax::mojom::StringAttribute::kPlaceholder:
result += " placeholder=" + value;
@@ -1606,8 +1587,8 @@ std::string AXNodeData::ToString() const {
bool_attributes) {
std::string value = bool_attribute.second ? "true" : "false";
switch (bool_attribute.first) {
- case ax::mojom::BoolAttribute::kEditableRoot:
- result += " editable_root=" + value;
+ case ax::mojom::BoolAttribute::kContentEditableRoot:
+ result += " contentEditable_root=" + value;
break;
case ax::mojom::BoolAttribute::kLiveAtomic:
result += " atomic=" + value;
diff --git a/chromium/ui/accessibility/ax_node_data.h b/chromium/ui/accessibility/ax_node_data.h
index 0dabcb6ae55..92fd9450043 100644
--- a/chromium/ui/accessibility/ax_node_data.h
+++ b/chromium/ui/accessibility/ax_node_data.h
@@ -267,13 +267,20 @@ struct AX_BASE_EXPORT AXNodeData {
// This data belongs to a text field that is used for entering passwords.
bool IsPasswordField() const;
- // This data belongs to a text field that doesn't accept rich text content,
- // such as text with special formatting or styling.
- bool IsPlainTextField() const;
-
- // This data belongs to a text field that accepts rich text content, such as
- // text with special formatting or styling.
- bool IsRichTextField() const;
+ // This data belongs to an atomic text field. An atomic text field does not
+ // expose its internal implementation to assistive software, appearing as a
+ // single leaf node in the accessibility tree. Examples include: An <input> or
+ // a <textarea> on the Web, a text field in a PDF form, a Views-based text
+ // field, or a native Android one.
+ bool IsAtomicTextField() const;
+
+ // This data belongs to a text field whose value is exposed both on the field
+ // itself as well as on descendant nodes which are expose to platform
+ // accessibility APIs. A non-native text field also exposes stylistic and
+ // document marker information on descendant nodes. Examples include fields
+ // created using the CSS "user-modify" property, or the "contenteditable"
+ // attribute.
+ bool IsNonAtomicTextField() const;
// Helper to determine if |GetRestriction| is either ReadOnly or Disabled.
// By default, all nodes that can't be edited are readonly.
diff --git a/chromium/ui/accessibility/ax_node_position.cc b/chromium/ui/accessibility/ax_node_position.cc
index 71a3c950d40..b3a8cc8fccf 100644
--- a/chromium/ui/accessibility/ax_node_position.cc
+++ b/chromium/ui/accessibility/ax_node_position.cc
@@ -22,6 +22,20 @@ AXEmbeddedObjectBehavior g_ax_embedded_object_behavior =
AXEmbeddedObjectBehavior::kSuppressCharacter;
#endif // defined(OS_WIN) || BUILDFLAG(USE_ATK)
+namespace testing {
+
+ScopedAXEmbeddedObjectBehaviorSetter::ScopedAXEmbeddedObjectBehaviorSetter(
+ AXEmbeddedObjectBehavior behavior) {
+ prev_behavior_ = g_ax_embedded_object_behavior;
+ g_ax_embedded_object_behavior = behavior;
+}
+
+ScopedAXEmbeddedObjectBehaviorSetter::~ScopedAXEmbeddedObjectBehaviorSetter() {
+ g_ax_embedded_object_behavior = prev_behavior_;
+}
+
+} // namespace testing
+
// static
AXNodePosition::AXPositionInstance AXNodePosition::CreatePosition(
const AXNode& node,
diff --git a/chromium/ui/accessibility/ax_node_position_perftest.cc b/chromium/ui/accessibility/ax_node_position_perftest.cc
index 7489a2f12fa..3d4162fd8ce 100644
--- a/chromium/ui/accessibility/ax_node_position_perftest.cc
+++ b/chromium/ui/accessibility/ax_node_position_perftest.cc
@@ -21,7 +21,7 @@ constexpr int kLaps = 5000;
constexpr int kWarmupLaps = 5;
constexpr char kMetricCallsPerSecondRunsPerS[] = "calls_per_second";
-class AXPositionPerfTest : public testing::Test, public TestAXTreeManager {
+class AXPositionPerfTest : public ::testing::Test, public TestAXTreeManager {
public:
AXPositionPerfTest() = default;
~AXPositionPerfTest() override = default;
diff --git a/chromium/ui/accessibility/ax_node_position_unittest.cc b/chromium/ui/accessibility/ax_node_position_unittest.cc
index 2f14e80355d..d3ac09577d6 100644
--- a/chromium/ui/accessibility/ax_node_position_unittest.cc
+++ b/chromium/ui/accessibility/ax_node_position_unittest.cc
@@ -60,9 +60,9 @@ constexpr const wchar_t* kGraphemeClusters[] = {
L"\x0E01",
};
-class AXPositionTest : public testing::Test, public TestAXTreeManager {
+class AXPositionTest : public ::testing::Test, public TestAXTreeManager {
public:
- AXPositionTest() = default;
+ AXPositionTest();
~AXPositionTest() override = default;
protected:
@@ -121,6 +121,7 @@ class AXPositionTest : public testing::Test, public TestAXTreeManager {
AXNodeData inline_box2_;
private:
+ testing::ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behaviour_;
// Manages a minimalistic Views tree that is hosting the test webpage.
TestAXTreeManager views_tree_manager_;
@@ -161,7 +162,7 @@ struct ExpandToEnclosingTextBoundaryTestParam {
// |ExpandToEnclosingTextBoundary| method with all possible input arguments.
class AXPositionExpandToEnclosingTextBoundaryTestWithParam
: public AXPositionTest,
- public testing::WithParamInterface<
+ public ::testing::WithParamInterface<
ExpandToEnclosingTextBoundaryTestParam> {
public:
AXPositionExpandToEnclosingTextBoundaryTestWithParam() = default;
@@ -207,7 +208,7 @@ struct CreatePositionAtTextBoundaryTestParam {
// |CreatePositionAtTextBoundary| method with all possible input arguments.
class AXPositionCreatePositionAtTextBoundaryTestWithParam
: public AXPositionTest,
- public testing::WithParamInterface<
+ public ::testing::WithParamInterface<
CreatePositionAtTextBoundaryTestParam> {
public:
AXPositionCreatePositionAtTextBoundaryTestWithParam() = default;
@@ -255,7 +256,7 @@ struct TextNavigationTestParam {
// TODO(nektar): Only text positions are tested for now.
class AXPositionTextNavigationTestWithParam
: public AXPositionTest,
- public testing::WithParamInterface<TextNavigationTestParam> {
+ public ::testing::WithParamInterface<TextNavigationTestParam> {
public:
AXPositionTextNavigationTestWithParam() = default;
~AXPositionTextNavigationTestWithParam() override = default;
@@ -263,12 +264,14 @@ class AXPositionTextNavigationTestWithParam
DISALLOW_COPY_AND_ASSIGN(AXPositionTextNavigationTestWithParam);
};
+// Most tests use kSuppressCharacter behavior.
+AXPositionTest::AXPositionTest()
+ : ax_embedded_object_behaviour_(
+ AXEmbeddedObjectBehavior::kSuppressCharacter) {}
+
const char* AXPositionTest::TEXT_VALUE = "Line 1\nLine 2";
void AXPositionTest::SetUp() {
- // Most tests use kSuppressCharacter behavior.
- g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kSuppressCharacter;
-
// First create a minimalistic Views tree that would host the test webpage.
// Window (BrowserRootView)
// ++NonClientView
@@ -1765,8 +1768,6 @@ TEST_F(AXPositionTest, AtStartAndEndOfLineInsideTextField) {
AXNodeData text_field_data_1;
text_field_data_1.id = 2;
text_field_data_1.role = ax::mojom::Role::kTextField;
- text_field_data_1.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot,
- true);
text_field_data_1.AddState(ax::mojom::State::kEditable);
// "kIsLineBreakingObject" is not strictly necessary.
text_field_data_1.AddBoolAttribute(
@@ -1812,8 +1813,6 @@ TEST_F(AXPositionTest, AtStartAndEndOfLineInsideTextField) {
text_field_data_2.id = 7;
text_field_data_2.role = ax::mojom::Role::kTextField;
text_field_data_2.AddState(ax::mojom::State::kEditable);
- text_field_data_2.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot,
- true);
// "kIsLineBreakingObject" is not strictly necessary.
text_field_data_2.AddBoolAttribute(
ax::mojom::BoolAttribute::kIsLineBreakingObject, true);
@@ -2908,14 +2907,15 @@ TEST_F(AXPositionTest, AtStartOrEndOfParagraphWithIgnoredNodes) {
}
TEST_F(AXPositionTest, AtStartOrEndOfParagraphWithEmbeddedObjectCharacter) {
- g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kExposeCharacter;
+ testing::ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
+ AXEmbeddedObjectBehavior::kExposeCharacter);
// This test ensures that "At{Start|End}OfParagraph" work correctly when there
// are embedded objects present near a paragraph boundary.
//
- // Nodes represented by an embedded object character, such as a plain text
- // field or a check box, should create an implicit paragraph boundary for
- // assistive software.
+ // Nodes represented by an embedded object character, such as an <input> or a
+ // <textarea> text field, or a check box, should create an implicit paragraph
+ // boundary for assistive software.
// ++1 kRootWebArea isLineBreakingObject
// ++++2 kLink
// ++++++3 kStaticText "hello"
@@ -3697,7 +3697,8 @@ TEST_F(AXPositionTest, AsLeafTextPositionWithTextPositionAndEmptyTextSandwich) {
}
TEST_F(AXPositionTest, AsLeafTextPositionWithTextPositionAndEmbeddedObject) {
- g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kExposeCharacter;
+ testing::ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
+ AXEmbeddedObjectBehavior::kExposeCharacter);
// ++1 kRootWebArea "<embedded_object><embedded_object>"
// ++++2 kImage alt="Test image"
@@ -3982,6 +3983,10 @@ TEST_F(AXPositionTest, AsUnignoredPosition) {
inline_box_data_2, container_data, static_text_data_2,
inline_box_data_3}));
+ // TODO(nektar): AXTree has a bug whereby it doesn't update the unignored
+ // cached values when the ignored state is flipped on the root.
+ GetNodeFromTree(root_data.id)->UpdateUnignoredCachedValues();
+
text_position = AXNodePosition::CreateTextPosition(
GetTreeID(), root_data.id, 0 /* text_offset */,
ax::mojom::TextAffinity::kDownstream);
@@ -6990,7 +6995,8 @@ TEST_F(AXPositionTest, CreateParentPositionWithMoveDirection) {
// This test only applies when "object replacement characters" are used in the
// accessibility tree, e.g., in IAccessible2, UI Automation and Linux ATK
// APIs.
- g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kExposeCharacter;
+ testing::ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
+ AXEmbeddedObjectBehavior::kExposeCharacter);
// This test ensures that "CreateParentPosition" (and by extension
// "CreateAncestorPosition") works correctly when it is given either a tree or
@@ -7850,7 +7856,8 @@ TEST_F(AXPositionTest, CreateParentAndLeafPositionWithEmptyNodes) {
}
TEST_F(AXPositionTest, CreateParentAndLeafPositionWithEmbeddedObjects) {
- g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kExposeCharacter;
+ testing::ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
+ AXEmbeddedObjectBehavior::kExposeCharacter);
// ++kRootWebArea "<embedded>Hello<embedded>"
// ++++kParagraph "Paragraph"
@@ -8813,7 +8820,8 @@ TEST_F(AXPositionTest, AsValidPosition) {
}
TEST_F(AXPositionTest, AsValidPositionInDescendantOfEmptyObject) {
- g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kExposeCharacter;
+ testing::ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
+ AXEmbeddedObjectBehavior::kExposeCharacter);
// ++1 kRootWebArea
// ++++2 kButton
@@ -9247,7 +9255,7 @@ TEST_F(AXPositionTest, CreateNextCharacterPositionAtGraphemeBoundary) {
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
- testing::Message message;
+ ::testing::Message message;
message << "Expecting character boundary at " << text_offset << " in\n"
<< *test_position;
SCOPED_TRACE(message);
@@ -9322,7 +9330,7 @@ TEST_F(AXPositionTest, CreatePreviousCharacterPositionAtGraphemeBoundary) {
ASSERT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
- testing::Message message;
+ ::testing::Message message;
message << "Expecting character boundary at " << text_offset << " in\n"
<< *test_position;
SCOPED_TRACE(message);
@@ -9638,7 +9646,8 @@ TEST_F(AXPositionTest, OperatorEqualsSameTextOffsetDifferentAnchorIdLeaf) {
}
TEST_F(AXPositionTest, OperatorEqualsTextPositionsInTextField) {
- g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kExposeCharacter;
+ testing::ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
+ AXEmbeddedObjectBehavior::kExposeCharacter);
// ++1 kRootWebArea
// ++++2 kTextField editable
@@ -9662,7 +9671,9 @@ TEST_F(AXPositionTest, OperatorEqualsTextPositionsInTextField) {
text_field_2.role = ax::mojom::Role::kTextField;
text_field_2.AddState(ax::mojom::State::kEditable);
- text_field_2.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot, true);
+ text_field_2.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag,
+ "input");
+
text_field_2.child_ids = {generic_container_3.id};
generic_container_3.role = ax::mojom::Role::kGenericContainer;
@@ -9700,10 +9711,11 @@ TEST_F(AXPositionTest, OperatorEqualsTextPositionsInTextField) {
}
TEST_F(AXPositionTest, OperatorEqualsTextPositionsInSearchBox) {
- g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kExposeCharacter;
+ testing::ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
+ AXEmbeddedObjectBehavior::kExposeCharacter);
// ++1 kRootWebArea
- // ++++2 kSearchBox editable editableRoot=true
+ // ++++2 kSearchBox editable
// ++++++3 kGenericContainer
// ++++++++4 kGenericContainer editable
// ++++++++++5 kStaticText editable "Hello"
@@ -9736,7 +9748,8 @@ TEST_F(AXPositionTest, OperatorEqualsTextPositionsInSearchBox) {
search_box_2.role = ax::mojom::Role::kSearchBox;
search_box_2.AddState(ax::mojom::State::kEditable);
- search_box_2.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot, true);
+ search_box_2.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag,
+ "input");
search_box_2.child_ids = {generic_container_3.id};
generic_container_3.role = ax::mojom::Role::kGenericContainer;
@@ -9800,7 +9813,8 @@ TEST_F(AXPositionTest, OperatorEqualsTextPositionsInSearchBox) {
}
TEST_F(AXPositionTest, OperatorsTreePositionsAroundEmbeddedCharacter) {
- g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kExposeCharacter;
+ testing::ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
+ AXEmbeddedObjectBehavior::kExposeCharacter);
// ++1 kRootWebArea "<embedded_object><embedded_object>"
// ++++2 kParagraph "<embedded_object>"
@@ -9933,7 +9947,8 @@ TEST_F(AXPositionTest, OperatorsTreePositionsAroundEmbeddedCharacter) {
}
TEST_F(AXPositionTest, OperatorsTextPositionsAroundEmbeddedCharacter) {
- g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kExposeCharacter;
+ testing::ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
+ AXEmbeddedObjectBehavior::kExposeCharacter);
// ++1 kRootWebArea "<embedded_object><embedded_object>"
// ++++2 kParagraph "<embedded_object>"
@@ -10318,6 +10333,9 @@ TEST_F(AXPositionTest, CreateNextAnchorPosition) {
AXNodeData text_field_data;
text_field_data.id = 3;
text_field_data.role = ax::mojom::Role::kTextField;
+ text_field_data.AddState(ax::mojom::State::kEditable);
+ text_field_data.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag,
+ "input");
AXNodeData empty_text_data;
empty_text_data.id = 4;
@@ -10797,7 +10815,8 @@ TEST_F(AXPositionTest, CreatePreviousWordPositionInList) {
}
TEST_F(AXPositionTest, EmptyObjectReplacedByCharacterTextNavigation) {
- g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kExposeCharacter;
+ testing::ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
+ AXEmbeddedObjectBehavior::kExposeCharacter);
// ++1 kRootWebArea
// ++++2 kStaticText
@@ -10867,7 +10886,6 @@ TEST_F(AXPositionTest, EmptyObjectReplacedByCharacterTextNavigation) {
std::vector<int32_t>{6});
text_field_4.role = ax::mojom::Role::kTextField;
- text_field_4.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot, true);
text_field_4.child_ids = {generic_container_5.id};
generic_container_5.role = ax::mojom::Role::kGenericContainer;
@@ -11117,7 +11135,8 @@ TEST_F(AXPositionTest, EmptyObjectReplacedByCharacterTextNavigation) {
}
TEST_F(AXPositionTest, EmptyObjectReplacedByCharacterEmbedObject) {
- g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kExposeCharacter;
+ testing::ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
+ AXEmbeddedObjectBehavior::kExposeCharacter);
// Parent Tree
// ++1 kRootWebArea
@@ -11168,7 +11187,8 @@ TEST_F(AXPositionTest, TextNavigationWithCollapsedCombobox) {
// collapsed, the subtree of that combobox needs to be hidden and, when
// expanded, it must be accessible in the tree. This test ensures we can't
// navigate into the options of a collapsed menu list popup.
- g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kExposeCharacter;
+ testing::ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
+ AXEmbeddedObjectBehavior::kExposeCharacter);
// ++1 kRootWebArea
// ++++2 kStaticText "Hi"
@@ -11375,7 +11395,7 @@ TEST_P(AXPositionTextNavigationTestWithParam,
INSTANTIATE_TEST_SUITE_P(
ExpandToEnclosingTextBoundary,
AXPositionExpandToEnclosingTextBoundaryTestWithParam,
- testing::Values(
+ ::testing::Values(
ExpandToEnclosingTextBoundaryTestParam{
ax::mojom::TextBoundary::kCharacter,
AXRangeExpandBehavior::kLeftFirst,
@@ -11563,7 +11583,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePositionAtTextBoundary,
AXPositionCreatePositionAtTextBoundaryTestWithParam,
- testing::Values(
+ ::testing::Values(
CreatePositionAtTextBoundaryTestParam{
ax::mojom::TextBoundary::kCharacter,
ax::mojom::MoveDirection::kBackward,
@@ -11721,7 +11741,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextWordStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
@@ -11778,7 +11798,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextWordStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
@@ -11835,7 +11855,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextWordStartPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
@@ -11884,7 +11904,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextWordStartPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordStartPosition(
@@ -11953,7 +11973,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
@@ -12014,7 +12034,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
@@ -12075,7 +12095,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordStartPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
@@ -12122,7 +12142,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordStartPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordStartPosition(
@@ -12187,7 +12207,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextWordEndPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
@@ -12250,7 +12270,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextWordEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
@@ -12313,7 +12333,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextWordEndPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
@@ -12360,7 +12380,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextWordEndPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextWordEndPosition(
@@ -12427,7 +12447,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordEndPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
@@ -12482,7 +12502,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
@@ -12539,7 +12559,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordEndPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
@@ -12582,7 +12602,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousWordEndPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousWordEndPosition(
@@ -12649,7 +12669,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextLineStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
@@ -12692,7 +12712,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextLineStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
@@ -12737,7 +12757,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextLineStartPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
@@ -12783,7 +12803,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextLineStartPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineStartPosition(
@@ -12838,7 +12858,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
@@ -12889,7 +12909,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
@@ -12942,7 +12962,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineStartPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
@@ -12991,7 +13011,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineStartPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineStartPosition(
@@ -13046,7 +13066,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextLineEndPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
@@ -13097,7 +13117,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextLineEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
@@ -13150,7 +13170,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextLineEndPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
@@ -13199,7 +13219,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextLineEndPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextLineEndPosition(
@@ -13254,7 +13274,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineEndPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
@@ -13315,7 +13335,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
@@ -13386,7 +13406,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineEndPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
@@ -13443,7 +13463,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousLineEndPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousLineEndPosition(
@@ -13522,7 +13542,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
@@ -13562,7 +13582,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
@@ -13607,7 +13627,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphStartPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
@@ -13653,7 +13673,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphStartPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphStartPosition(
@@ -13708,7 +13728,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
@@ -13759,7 +13779,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
@@ -13812,7 +13832,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphStartPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
@@ -13861,7 +13881,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphStartPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphStartPosition(
@@ -13918,7 +13938,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphEndPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
@@ -13969,7 +13989,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
@@ -14026,7 +14046,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphEndPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
@@ -14097,7 +14117,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreateNextParagraphEndPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreateNextParagraphEndPosition(
@@ -14152,7 +14172,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphEndPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
@@ -14223,7 +14243,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
@@ -14298,7 +14318,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphEndPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
@@ -14380,7 +14400,7 @@ INSTANTIATE_TEST_SUITE_P(
INSTANTIATE_TEST_SUITE_P(
CreatePreviousParagraphEndPositionWithBoundaryBehaviorStopAtLastAnchorBoundary,
AXPositionTextNavigationTestWithParam,
- testing::Values(
+ ::testing::Values(
TextNavigationTestParam{
base::BindRepeating([](const TestPositionType& position) {
return position->CreatePreviousParagraphEndPosition(
diff --git a/chromium/ui/accessibility/ax_node_unittest.cc b/chromium/ui/accessibility/ax_node_unittest.cc
index ce7500ef022..f3e13572deb 100644
--- a/chromium/ui/accessibility/ax_node_unittest.cc
+++ b/chromium/ui/accessibility/ax_node_unittest.cc
@@ -60,7 +60,7 @@ TEST(AXNodeTest, GetLowestPlatformAncestor) {
text_field.role = ax::mojom::Role::kTextField;
text_field.AddState(ax::mojom::State::kEditable);
- text_field.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot, true);
+ text_field.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag, "input");
text_field.SetValue("World");
text_field.child_ids = {static_text_2.id};
diff --git a/chromium/ui/accessibility/ax_position.h b/chromium/ui/accessibility/ax_position.h
index 1cc3f1d0a9e..da51be470a5 100644
--- a/chromium/ui/accessibility/ax_position.h
+++ b/chromium/ui/accessibility/ax_position.h
@@ -19,10 +19,10 @@
#include "base/containers/contains.h"
#include "base/containers/stack.h"
#include "base/i18n/break_iterator.h"
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_enum_util.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node.h"
@@ -126,7 +126,23 @@ enum class AXEmbeddedObjectBehavior {
// character and a word boundary. For example, an empty text field should act as
// a character and a word boundary when a screen reader user tries to navigate
// through it, otherwise the text field would be missed by the user.
-AX_EXPORT extern AXEmbeddedObjectBehavior g_ax_embedded_object_behavior;
+// Tests should use ScopedAXEmbeddedObjectBehaviorSetter to change this.
+// TODO(crbug.com/1204592) Don't export this so tests can't change it.
+extern AX_EXPORT AXEmbeddedObjectBehavior g_ax_embedded_object_behavior;
+
+namespace testing {
+
+class AX_EXPORT ScopedAXEmbeddedObjectBehaviorSetter {
+ public:
+ explicit ScopedAXEmbeddedObjectBehaviorSetter(
+ AXEmbeddedObjectBehavior behavior);
+ ~ScopedAXEmbeddedObjectBehaviorSetter();
+
+ private:
+ AXEmbeddedObjectBehavior prev_behavior_;
+};
+
+} // namespace testing
// Forward declarations.
template <class AXPositionType, class AXNodeType>
@@ -2445,12 +2461,14 @@ class AXPosition {
return Clone();
}
- DCHECK_LT(text_position->text_offset_, text_position->MaxTextOffset());
+ int max_text_offset = text_position->MaxTextOffset();
+ DCHECK_LT(text_position->text_offset_, max_text_offset);
std::unique_ptr<base::i18n::BreakIterator> grapheme_iterator =
text_position->GetGraphemeIterator();
do {
++text_position->text_offset_;
- } while (!text_position->AtEndOfAnchor() && grapheme_iterator &&
+ } while (text_position->text_offset_ < max_text_offset &&
+ grapheme_iterator &&
!grapheme_iterator->IsGraphemeBoundary(
size_t{text_position->text_offset_}));
DCHECK_GT(text_position->text_offset_, 0);
@@ -3210,11 +3228,11 @@ class AXPosition {
// 0: if this position is logically equivalent to the other position
// <0: if this position is logically less than the other position
// >0: if this position is logically greater than the other position
- base::Optional<int> CompareTo(const AXPosition& other) const {
+ absl::optional<int> CompareTo(const AXPosition& other) const {
if (IsNullPosition() && other.IsNullPosition())
return 0;
if (IsNullPosition() || other.IsNullPosition())
- return base::nullopt;
+ return absl::nullopt;
if (GetAnchor() == other.GetAnchor())
return SlowCompareTo(other); // No optimization is necessary.
@@ -3288,7 +3306,7 @@ class AXPosition {
}
if (!common_anchor)
- return base::nullopt;
+ return absl::nullopt;
// If each position has an uncommon ancestor node, we can compare those
// instead of needing to compute ancestor positions. Otherwise we need to
@@ -3391,17 +3409,17 @@ class AXPosition {
// A less optimized, but much slower version of "CompareTo". Should only be
// used when optimizations cannot be applied, e.g. when comparing ignored
// positions. See "CompareTo" for an explanation of the return values.
- base::Optional<int> SlowCompareTo(const AXPosition& other) const {
+ absl::optional<int> SlowCompareTo(const AXPosition& other) const {
if (IsNullPosition() && other.IsNullPosition())
return 0;
if (IsNullPosition() || other.IsNullPosition())
- return base::nullopt;
+ return absl::nullopt;
// If both positions share an anchor and either one is a text position, or
// both are tree positions, we can do a straight comparison of text offsets
// or child indices.
if (GetAnchor() == other.GetAnchor()) {
- base::Optional<int> optional_result;
+ absl::optional<int> optional_result;
ax::mojom::TextAffinity this_affinity;
ax::mojom::TextAffinity other_affinity;
@@ -3462,14 +3480,14 @@ class AXPosition {
const AXNode* common_anchor = this->LowestCommonAnchor(other);
if (!common_anchor)
- return base::nullopt;
+ return absl::nullopt;
// If either of the two positions is a text position, and if one position is
// an ancestor of the other, we need to compare using text positions,
// because converting to tree positions will potentially lose information if
// the text offset is anything other than 0 or `MaxTextOffset()`.
if (IsTextPosition() || other.IsTextPosition()) {
- base::Optional<int> optional_result;
+ absl::optional<int> optional_result;
ax::mojom::TextAffinity this_affinity;
ax::mojom::TextAffinity other_affinity;
@@ -3701,8 +3719,8 @@ class AXPosition {
// a collapsed popup menu. The presence or the absence of accessible content
// inside a control might alter whether an "object replacement character"
// would be exposed in that control, in contrast to ordinary text such as in
- // the case of a non-empty plain text field which should only have textual
- // nodes inside it. This is because empty controls need to act as a word and
+ // the case of a non-empty text field which should only have textual nodes
+ // inside it. This is because empty controls need to act as a word and
// character boundary.
bool IsEmptyObjectReplacedByCharacter() const {
if (g_ax_embedded_object_behavior ==
@@ -4078,8 +4096,8 @@ class AXPosition {
// that are descendants of platform leaves should maintain the actual
// text of all their static text descendants, otherwise there would be
// loss of information while traversing the accessibility tree upwards.
- // An example of a platform leaf is a plain text field, because all of
- // the accessibility subtree inside the text field is hidden from
+ // An example of a platform leaf is an <input> text field, because all
+ // of the accessibility subtree inside the text field is hidden from
// platform APIs. An example of how an ignored node can affect the
// hypertext of an unignored ancestor is shown below:
// ++kTextField "Hello"
@@ -4986,42 +5004,42 @@ const int AXPosition<AXPositionType, AXNodeType>::INVALID_OFFSET;
template <class AXPositionType, class AXNodeType>
bool operator==(const AXPosition<AXPositionType, AXNodeType>& first,
const AXPosition<AXPositionType, AXNodeType>& second) {
- const base::Optional<int> compare_to_optional = first.CompareTo(second);
+ const absl::optional<int> compare_to_optional = first.CompareTo(second);
return compare_to_optional.has_value() && compare_to_optional.value() == 0;
}
template <class AXPositionType, class AXNodeType>
bool operator!=(const AXPosition<AXPositionType, AXNodeType>& first,
const AXPosition<AXPositionType, AXNodeType>& second) {
- const base::Optional<int> compare_to_optional = first.CompareTo(second);
+ const absl::optional<int> compare_to_optional = first.CompareTo(second);
return compare_to_optional.has_value() && compare_to_optional.value() != 0;
}
template <class AXPositionType, class AXNodeType>
bool operator<(const AXPosition<AXPositionType, AXNodeType>& first,
const AXPosition<AXPositionType, AXNodeType>& second) {
- const base::Optional<int> compare_to_optional = first.CompareTo(second);
+ const absl::optional<int> compare_to_optional = first.CompareTo(second);
return compare_to_optional.has_value() && compare_to_optional.value() < 0;
}
template <class AXPositionType, class AXNodeType>
bool operator<=(const AXPosition<AXPositionType, AXNodeType>& first,
const AXPosition<AXPositionType, AXNodeType>& second) {
- const base::Optional<int> compare_to_optional = first.CompareTo(second);
+ const absl::optional<int> compare_to_optional = first.CompareTo(second);
return compare_to_optional.has_value() && compare_to_optional.value() <= 0;
}
template <class AXPositionType, class AXNodeType>
bool operator>(const AXPosition<AXPositionType, AXNodeType>& first,
const AXPosition<AXPositionType, AXNodeType>& second) {
- const base::Optional<int> compare_to_optional = first.CompareTo(second);
+ const absl::optional<int> compare_to_optional = first.CompareTo(second);
return compare_to_optional.has_value() && compare_to_optional.value() > 0;
}
template <class AXPositionType, class AXNodeType>
bool operator>=(const AXPosition<AXPositionType, AXNodeType>& first,
const AXPosition<AXPositionType, AXNodeType>& second) {
- const base::Optional<int> compare_to_optional = first.CompareTo(second);
+ const absl::optional<int> compare_to_optional = first.CompareTo(second);
return compare_to_optional.has_value() && compare_to_optional.value() >= 0;
}
diff --git a/chromium/ui/accessibility/ax_range.h b/chromium/ui/accessibility/ax_range.h
index 948907beaca..7671b17bf10 100644
--- a/chromium/ui/accessibility/ax_range.h
+++ b/chromium/ui/accessibility/ax_range.h
@@ -13,7 +13,6 @@
#include "base/strings/utf_string_conversions.h"
#include "ui/accessibility/ax_clipping_behavior.h"
-#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_offscreen_result.h"
#include "ui/accessibility/ax_role_properties.h"
#include "ui/accessibility/ax_tree_manager_map.h"
@@ -114,9 +113,9 @@ class AXRange {
// <0 - If the first position would come BEFORE the second.
// >0 - If the first position would come AFTER the second.
// nullopt - If positions are not comparable (see AXPosition::CompareTo).
- static base::Optional<int> CompareEndpoints(const AXPositionType* first,
+ static absl::optional<int> CompareEndpoints(const AXPositionType* first,
const AXPositionType* second) {
- base::Optional<int> tree_position_comparison =
+ absl::optional<int> tree_position_comparison =
first->AsTreePosition()->CompareTo(*second->AsTreePosition());
// When the tree comparison is nullopt, using value_or(1) forces a default
@@ -283,7 +282,7 @@ class AXRange {
if (max_count == 0 || IsNull())
return std::u16string();
- base::Optional<int> endpoint_comparison =
+ absl::optional<int> endpoint_comparison =
CompareEndpoints(anchor(), focus());
if (!endpoint_comparison)
return std::u16string();
diff --git a/chromium/ui/accessibility/ax_range_unittest.cc b/chromium/ui/accessibility/ax_range_unittest.cc
index 466041ee6b6..6fa6cd5c485 100644
--- a/chromium/ui/accessibility/ax_range_unittest.cc
+++ b/chromium/ui/accessibility/ax_range_unittest.cc
@@ -100,7 +100,7 @@ class TestAXRangeScreenRectDelegate : public AXRangeRectDelegate {
TestAXTreeManager* const tree_manager_;
};
-class AXRangeTest : public testing::Test, public TestAXTreeManager {
+class AXRangeTest : public ::testing::Test, public TestAXTreeManager {
public:
const std::u16string EMPTY = u"";
const std::u16string NEWLINE = u"\n";
@@ -113,7 +113,7 @@ class AXRangeTest : public testing::Test, public TestAXTreeManager {
const std::u16string ALL_TEXT =
BUTTON.substr().append(TEXT_FIELD).append(AFTER_LINE);
- AXRangeTest() = default;
+ AXRangeTest();
~AXRangeTest() override = default;
protected:
@@ -140,9 +140,16 @@ class AXRangeTest : public testing::Test, public TestAXTreeManager {
AXNodeData empty_paragraph_;
private:
+ testing::ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior_;
+
DISALLOW_COPY_AND_ASSIGN(AXRangeTest);
};
+// These tests use kSuppressCharacter behavior.
+AXRangeTest::AXRangeTest()
+ : ax_embedded_object_behavior_(
+ AXEmbeddedObjectBehavior::kSuppressCharacter) {}
+
void AXRangeTest::SetUp() {
// Set up the AXTree for the following content:
// ++1 Role::kDialog
@@ -183,9 +190,6 @@ void AXRangeTest::SetUp() {
// [Empty paragraph]
// {20, 140, 700, 0}
- // Most tests use kSuppressCharacter behavior.
- g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kSuppressCharacter;
-
root_.id = ROOT_ID;
div1_.id = DIV1_ID;
div2_.id = DIV2_ID;
@@ -1312,14 +1316,14 @@ TEST_F(AXRangeTest, GetRects) {
TestPositionRange button_range(button->Clone(), button->Clone());
std::vector<gfx::Rect> expected_screen_rects = {gfx::Rect(20, 20, 100, 30)};
EXPECT_THAT(button_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Since a check box is not visible to the text representation, it spans an
// empty anchor whose start and end positions are the same.
TestPositionRange check_box1_range(check_box1->Clone(), check_box1->Clone());
expected_screen_rects = {gfx::Rect(120, 20, 30, 30)};
EXPECT_THAT(check_box1_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Retrieving bounding boxes of the button and both checkboxes.
TestPositionRange button_check_box2_range(button->Clone(),
@@ -1328,7 +1332,7 @@ TEST_F(AXRangeTest, GetRects) {
gfx::Rect(120, 20, 30, 30),
gfx::Rect(150, 20, 30, 30)};
EXPECT_THAT(button_check_box2_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Retrieving bounding box of text line 1's degenerate range at its start.
// 0 1 2 3 4 5
@@ -1338,7 +1342,7 @@ TEST_F(AXRangeTest, GetRects) {
line1_start->Clone());
expected_screen_rects = {gfx::Rect(20, 50, 1, 30)};
EXPECT_THAT(line1_degenerate_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Retrieving bounding box of text line 1, its whole range.
// 0 1 2 3 4 5
@@ -1347,7 +1351,7 @@ TEST_F(AXRangeTest, GetRects) {
TestPositionRange line1_whole_range(line1_start->Clone(), line1_end->Clone());
expected_screen_rects = {gfx::Rect(20, 50, 30, 30)};
EXPECT_THAT(line1_whole_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Retrieving bounding box of text line 1, its first half range.
// 0 1 2 3 4 5
@@ -1357,7 +1361,7 @@ TEST_F(AXRangeTest, GetRects) {
line1_middle->Clone());
expected_screen_rects = {gfx::Rect(20, 50, 15, 30)};
EXPECT_THAT(line1_first_half_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Retrieving bounding box of text line 1, its second half range.
// 0 1 2 3 4 5
@@ -1367,7 +1371,7 @@ TEST_F(AXRangeTest, GetRects) {
line1_end->Clone());
expected_screen_rects = {gfx::Rect(35, 50, 15, 30)};
EXPECT_THAT(line1_second_half_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Retrieving bounding box of text line 1, its mid range.
// 0 1 2 3 4 5
@@ -1377,7 +1381,7 @@ TEST_F(AXRangeTest, GetRects) {
line1_second_to_last_char->Clone());
expected_screen_rects = {gfx::Rect(25, 50, 20, 30)};
EXPECT_THAT(line1_mid_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Retrieving bounding box of text line 2, its whole range.
// 0 1 2 3 4 5
@@ -1386,7 +1390,7 @@ TEST_F(AXRangeTest, GetRects) {
TestPositionRange line2_whole_range(line2_start->Clone(), line2_end->Clone());
expected_screen_rects = {gfx::Rect(20, 80, 42, 30)};
EXPECT_THAT(line2_whole_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Retrieving bounding box of text line 2, its first half range.
// 0 1 2 3 4 5
@@ -1396,7 +1400,7 @@ TEST_F(AXRangeTest, GetRects) {
line2_middle->Clone());
expected_screen_rects = {gfx::Rect(20, 80, 21, 30)};
EXPECT_THAT(line2_first_half_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Retrieving bounding box of text line 2, its second half range.
// 0 1 2 3 4 5
@@ -1406,7 +1410,7 @@ TEST_F(AXRangeTest, GetRects) {
line2_end->Clone());
expected_screen_rects = {gfx::Rect(41, 80, 21, 30)};
EXPECT_THAT(line2_second_half_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Retrieving bounding box of text line 2, its mid range.
// 0 1 2 3 4 5
@@ -1416,7 +1420,7 @@ TEST_F(AXRangeTest, GetRects) {
line2_second_to_last_char->Clone());
expected_screen_rects = {gfx::Rect(27, 80, 28, 30)};
EXPECT_THAT(line2_mid_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Retrieving bounding box of degenerate range of text line 2, before its
// second character.
@@ -1427,7 +1431,7 @@ TEST_F(AXRangeTest, GetRects) {
line2_second_char->Clone());
expected_screen_rects = {gfx::Rect(27, 80, 1, 30)};
EXPECT_THAT(line2_degenerate_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Retrieving bounding boxes of text line 1 and line 2, the entire range.
// |L|i|n|e| |1|\n|L|i|n|e| |2|\n|
@@ -1437,7 +1441,7 @@ TEST_F(AXRangeTest, GetRects) {
expected_screen_rects = {gfx::Rect(20, 50, 30, 30),
gfx::Rect(20, 80, 42, 30)};
EXPECT_THAT(line1_line2_whole_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Retrieving bounding boxes of the range that spans from the middle of text
// line 1 to the middle of text line 2.
@@ -1448,7 +1452,7 @@ TEST_F(AXRangeTest, GetRects) {
expected_screen_rects = {gfx::Rect(35, 50, 15, 30),
gfx::Rect(20, 80, 21, 30)};
EXPECT_THAT(line1_line2_mid_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Retrieving bounding boxes of the range that spans from the checkbox 2
// ("invisible" in the text representation) to the middle of text line 2.
@@ -1460,7 +1464,7 @@ TEST_F(AXRangeTest, GetRects) {
gfx::Rect(20, 50, 30, 30),
gfx::Rect(20, 80, 21, 30)};
EXPECT_THAT(check_box2_line2_mid_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Retrieving bounding boxes of the range spanning the entire document.
// |[Button][Checkbox 1][Checkbox 2]L|i|n|e| |1|\n|L|i|n|e| |2|\n|A|f|t|e|r<p>
@@ -1472,7 +1476,7 @@ TEST_F(AXRangeTest, GetRects) {
gfx::Rect(150, 20, 30, 30), gfx::Rect(20, 50, 30, 30),
gfx::Rect(20, 80, 42, 30), gfx::Rect(20, 110, 50, 30)};
EXPECT_THAT(entire_test_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
}
TEST_F(AXRangeTest, GetRectsOffscreen) {
@@ -1515,7 +1519,7 @@ TEST_F(AXRangeTest, GetRectsOffscreen) {
std::vector<gfx::Rect> expected_screen_rects = {gfx::Rect(20, 50, 30, 30),
gfx::Rect(20, 80, 42, 30)};
EXPECT_THAT(entire_test_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
// Reset the root node bounds/viewport size back to {0, 0, 800x600}, and
// verify all elements should be onscreen.
@@ -1525,7 +1529,7 @@ TEST_F(AXRangeTest, GetRectsOffscreen) {
gfx::Rect(150, 20, 30, 30), gfx::Rect(20, 50, 30, 30),
gfx::Rect(20, 80, 42, 30), gfx::Rect(20, 110, 50, 30)};
EXPECT_THAT(entire_test_range.GetRects(&delegate),
- testing::ContainerEq(expected_screen_rects));
+ ::testing::ContainerEq(expected_screen_rects));
}
} // namespace ui
diff --git a/chromium/ui/accessibility/ax_relative_bounds.h b/chromium/ui/accessibility/ax_relative_bounds.h
index de780d55381..6c09bc6092f 100644
--- a/chromium/ui/accessibility/ax_relative_bounds.h
+++ b/chromium/ui/accessibility/ax_relative_bounds.h
@@ -7,8 +7,8 @@
#include <stdint.h>
+#include <iosfwd>
#include <memory>
-#include <ostream>
#include "ui/accessibility/ax_base_export.h"
#include "ui/accessibility/ax_enums.mojom-forward.h"
diff --git a/chromium/ui/accessibility/ax_role_properties.cc b/chromium/ui/accessibility/ax_role_properties.cc
index 4f28632978e..5ba1505f5c6 100644
--- a/chromium/ui/accessibility/ax_role_properties.cc
+++ b/chromium/ui/accessibility/ax_role_properties.cc
@@ -76,6 +76,19 @@ bool IsButton(const ax::mojom::Role role) {
role == ax::mojom::Role::kToggleButton;
}
+bool IsCellOrTableHeader(const ax::mojom::Role role) {
+ switch (role) {
+ case ax::mojom::Role::kCell:
+ case ax::mojom::Role::kColumnHeader:
+ case ax::mojom::Role::kRowHeader:
+ return true;
+ case ax::mojom::Role::kLayoutTableCell:
+ return kExposeLayoutTableAsDataTable;
+ default:
+ return false;
+ }
+}
+
bool IsClickable(const ax::mojom::Role role) {
switch (role) {
case ax::mojom::Role::kButton:
@@ -117,14 +130,12 @@ bool IsClickable(const ax::mojom::Role role) {
}
}
-bool IsCellOrTableHeader(const ax::mojom::Role role) {
+bool IsComboBox(const ax::mojom::Role role) {
switch (role) {
- case ax::mojom::Role::kCell:
- case ax::mojom::Role::kColumnHeader:
- case ax::mojom::Role::kRowHeader:
+ case ax::mojom::Role::kComboBoxMenuButton:
+ case ax::mojom::Role::kComboBoxGrouping:
+ case ax::mojom::Role::kTextFieldWithComboBox:
return true;
- case ax::mojom::Role::kLayoutTableCell:
- return kExposeLayoutTableAsDataTable;
default:
return false;
}
@@ -206,7 +217,6 @@ bool IsControlOnAndroid(const ax::mojom::Role role, bool isFocusable) {
case ax::mojom::Role::kDialog:
case ax::mojom::Role::kMenu:
case ax::mojom::Role::kMenuBar:
- case ax::mojom::Role::kNone:
case ax::mojom::Role::kTree:
case ax::mojom::Role::kUnknown:
return false;
@@ -408,7 +418,6 @@ bool IsPlatformDocument(const ax::mojom::Role role) {
bool IsPresentational(const ax::mojom::Role role) {
switch (role) {
case ax::mojom::Role::kNone:
- case ax::mojom::Role::kPresentational:
return true;
default:
return false;
@@ -518,73 +527,6 @@ bool IsRowContainer(const ax::mojom::Role role) {
}
}
-bool IsSection(const ax::mojom::Role role) {
- if (IsLandmark(role) || IsSelect(role))
- return true;
-
- switch (role) {
- case ax::mojom::Role::kAlert:
- case ax::mojom::Role::kAlertDialog: // Subclass of kAlert.
- case ax::mojom::Role::kCell:
- case ax::mojom::Role::kColumnHeader: // Subclass of kCell.
- case ax::mojom::Role::kDefinition:
- case ax::mojom::Role::kDirectory: // Subclass of kList.
- case ax::mojom::Role::kFeed: // Subclass of kList.
- case ax::mojom::Role::kFigure:
- case ax::mojom::Role::kGrid: // Subclass of kTable.
- case ax::mojom::Role::kGroup:
- case ax::mojom::Role::kImage:
- case ax::mojom::Role::kList:
- case ax::mojom::Role::kListItem:
- case ax::mojom::Role::kLog:
- case ax::mojom::Role::kMarquee:
- case ax::mojom::Role::kMath:
- case ax::mojom::Role::kNote:
- case ax::mojom::Role::kProgressIndicator: // Subclass of kStatus.
- case ax::mojom::Role::kRow: // Subclass of kGroup.
- case ax::mojom::Role::kRowHeader: // Subclass of kCell.
- case ax::mojom::Role::kSection:
- case ax::mojom::Role::kStatus:
- case ax::mojom::Role::kTable:
- case ax::mojom::Role::kTabPanel:
- case ax::mojom::Role::kTerm:
- case ax::mojom::Role::kTimer: // Subclass of kStatus.
- case ax::mojom::Role::kToolbar: // Subclass of kGroup.
- case ax::mojom::Role::kTooltip:
- case ax::mojom::Role::kTreeItem: // Subclass of kListItem.
- return true;
- default:
- return false;
- }
-}
-
-bool IsSectionhead(const ax::mojom::Role role) {
- switch (role) {
- case ax::mojom::Role::kColumnHeader:
- case ax::mojom::Role::kHeading:
- case ax::mojom::Role::kRowHeader:
- case ax::mojom::Role::kTab:
- return true;
- default:
- return false;
- }
-}
-
-bool IsSelect(const ax::mojom::Role role) {
- switch (role) {
- case ax::mojom::Role::kComboBoxGrouping:
- case ax::mojom::Role::kListBox:
- case ax::mojom::Role::kMenu:
- case ax::mojom::Role::kMenuBar: // Subclass of kMenu.
- case ax::mojom::Role::kRadioGroup:
- case ax::mojom::Role::kTree:
- case ax::mojom::Role::kTreeGrid: // Subclass of kTree.
- return true;
- default:
- return false;
- }
-}
-
bool IsSelectElement(const ax::mojom::Role role) {
// Depending on their "size" attribute, <select> elements come in two flavors:
// the first appears like a list box and the second like a popup menu.
@@ -630,58 +572,6 @@ bool IsStaticList(const ax::mojom::Role role) {
}
}
-bool IsStructure(const ax::mojom::Role role) {
- if (IsSection(role) || IsSectionhead(role))
- return true;
-
- switch (role) {
- case ax::mojom::Role::kApplication:
- case ax::mojom::Role::kArticle: // Subclass of kDocument.
- case ax::mojom::Role::kDocument:
- case ax::mojom::Role::kPresentational:
- case ax::mojom::Role::kRowGroup:
- case ax::mojom::Role::kSplitter:
- // Dpub roles.
- case ax::mojom::Role::kDocAbstract:
- case ax::mojom::Role::kDocAcknowledgments:
- case ax::mojom::Role::kDocAfterword:
- case ax::mojom::Role::kDocAppendix:
- case ax::mojom::Role::kDocBiblioEntry:
- case ax::mojom::Role::kDocBibliography:
- case ax::mojom::Role::kDocChapter:
- case ax::mojom::Role::kDocColophon:
- case ax::mojom::Role::kDocConclusion:
- case ax::mojom::Role::kDocCover:
- case ax::mojom::Role::kDocCredit:
- case ax::mojom::Role::kDocCredits:
- case ax::mojom::Role::kDocDedication:
- case ax::mojom::Role::kDocEndnote:
- case ax::mojom::Role::kDocEndnotes:
- case ax::mojom::Role::kDocEpigraph:
- case ax::mojom::Role::kDocEpilogue:
- case ax::mojom::Role::kDocErrata:
- case ax::mojom::Role::kDocExample:
- case ax::mojom::Role::kDocFootnote:
- case ax::mojom::Role::kDocForeword:
- case ax::mojom::Role::kDocGlossary:
- case ax::mojom::Role::kDocIndex:
- case ax::mojom::Role::kDocIntroduction:
- case ax::mojom::Role::kDocNotice:
- case ax::mojom::Role::kDocPageBreak:
- case ax::mojom::Role::kDocPageList:
- case ax::mojom::Role::kDocPart:
- case ax::mojom::Role::kDocPreface:
- case ax::mojom::Role::kDocPrologue:
- case ax::mojom::Role::kDocQna:
- case ax::mojom::Role::kDocSubtitle:
- case ax::mojom::Role::kDocTip:
- case ax::mojom::Role::kDocToc:
- return true;
- default:
- return false;
- }
-}
-
bool IsTableColumn(ax::mojom::Role role) {
return role == ax::mojom::Role::kColumn;
}
@@ -732,10 +622,10 @@ bool IsText(ax::mojom::Role role) {
}
}
-bool IsComboBox(const ax::mojom::Role role) {
+bool IsTextField(ax::mojom::Role role) {
switch (role) {
- case ax::mojom::Role::kComboBoxMenuButton:
- case ax::mojom::Role::kComboBoxGrouping:
+ case ax::mojom::Role::kSearchBox:
+ case ax::mojom::Role::kTextField:
case ax::mojom::Role::kTextFieldWithComboBox:
return true;
default:
diff --git a/chromium/ui/accessibility/ax_role_properties.h b/chromium/ui/accessibility/ax_role_properties.h
index 072c55e401b..6e496ff8806 100644
--- a/chromium/ui/accessibility/ax_role_properties.h
+++ b/chromium/ui/accessibility/ax_role_properties.h
@@ -33,6 +33,9 @@ AX_BASE_EXPORT bool IsAlert(const ax::mojom::Role role);
// Returns true if the provided role belongs to a native or an ARIA button.
AX_BASE_EXPORT bool IsButton(const ax::mojom::Role role);
+// Returns true if the provided role belongs to a cell or a table header.
+AX_BASE_EXPORT bool IsCellOrTableHeader(const ax::mojom::Role role);
+
// Returns true if the provided role belongs to an object on which a click
// handler is commonly attached, or to an object that carries out an action when
// clicked, such as activating itself, opening a dialog or closing a menu.
@@ -49,8 +52,8 @@ AX_BASE_EXPORT bool IsButton(const ax::mojom::Role role);
// so that users will know that they could activate them if they so choose.
AX_BASE_EXPORT bool IsClickable(const ax::mojom::Role role);
-// Returns true if the provided role belongs to a cell or a table header.
-AX_BASE_EXPORT bool IsCellOrTableHeader(const ax::mojom::Role role);
+// Returns true if the provided role is any of the combobox-related roles.
+AX_BASE_EXPORT bool IsComboBox(ax::mojom::Role role);
// Returns true if the provided role belongs to a container with selectable
// children.
@@ -93,9 +96,6 @@ AX_BASE_EXPORT bool IsImageOrVideo(const ax::mojom::Role role);
// pos_in_set and set_size values. Roles that are item-like are not set-like.
AX_BASE_EXPORT bool IsItemLike(const ax::mojom::Role role);
-// Returns true if the role is a subclass of the ARIA Landmark abstract role.
-AX_BASE_EXPORT bool IsLandmark(const ax::mojom::Role role);
-
// Returns true if the provided role belongs to a link.
AX_BASE_EXPORT bool IsLink(const ax::mojom::Role role);
@@ -145,15 +145,6 @@ AX_BASE_EXPORT bool IsRootLike(ax::mojom::Role role);
// table or grid row.
AX_BASE_EXPORT bool IsRowContainer(const ax::mojom::Role role);
-// Returns true if the role is a subclass of the ARIA Section abstract role.
-AX_BASE_EXPORT bool IsSection(const ax::mojom::Role role);
-
-// Returns true if the role is a subclass of the ARIA Sectionhead role.
-AX_BASE_EXPORT bool IsSectionhead(const ax::mojom::Role role);
-
-// Returns true if the role is a subclass of the ARIA Select abstract role.
-AX_BASE_EXPORT bool IsSelect(const ax::mojom::Role role);
-
// Returns true if the role is one of those exposed by the HTML <select>
// element.
AX_BASE_EXPORT bool IsSelectElement(const ax::mojom::Role role);
@@ -165,9 +156,6 @@ AX_BASE_EXPORT bool IsSetLike(const ax::mojom::Role role);
// Returns true if the provided role belongs to a non-interactive list.
AX_BASE_EXPORT bool IsStaticList(const ax::mojom::Role role);
-// Returns true if the role is a subclass of the ARIA Structure abstract role.
-AX_BASE_EXPORT bool IsStructure(const ax::mojom::Role role);
-
// Returns true if the provided role belongs to a table or grid column, and the
// table is not used for layout purposes.
AX_BASE_EXPORT bool IsTableColumn(ax::mojom::Role role);
@@ -186,8 +174,9 @@ AX_BASE_EXPORT bool IsTableRow(ax::mojom::Role role);
// break, or inline text box.
AX_BASE_EXPORT bool IsText(ax::mojom::Role role);
-// Returns true if the provided role is any of the combobox-related roles.
-AX_BASE_EXPORT bool IsComboBox(ax::mojom::Role role);
+// Returns true if the provided role belongs to a native text field, i.e.
+// <input> or <textarea>.
+AX_BASE_EXPORT bool IsTextField(ax::mojom::Role role);
// Returns true if the node should be read only by default
AX_BASE_EXPORT bool ShouldHaveReadonlyStateByDefault(
diff --git a/chromium/ui/accessibility/ax_table_fuzzer.cc b/chromium/ui/accessibility/ax_table_fuzzer.cc
index 9c921c2c991..d88153076cd 100644
--- a/chromium/ui/accessibility/ax_table_fuzzer.cc
+++ b/chromium/ui/accessibility/ax_table_fuzzer.cc
@@ -36,7 +36,7 @@ ax::mojom::Role GetInterestingTableRole(unsigned char byte) {
case 10:
return ax::mojom::Role::kGenericContainer;
case 11:
- return ax::mojom::Role::kIgnored;
+ return ax::mojom::Role::kNone;
case 12:
return ax::mojom::Role::kLayoutTable;
case 13:
diff --git a/chromium/ui/accessibility/ax_table_info.h b/chromium/ui/accessibility/ax_table_info.h
index 891a15b7027..721dead71ad 100644
--- a/chromium/ui/accessibility/ax_table_info.h
+++ b/chromium/ui/accessibility/ax_table_info.h
@@ -9,8 +9,8 @@
#include <set>
#include <vector>
-#include "base/optional.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_export.h"
#include "ui/accessibility/ax_node_data.h"
diff --git a/chromium/ui/accessibility/ax_table_info_unittest.cc b/chromium/ui/accessibility/ax_table_info_unittest.cc
index eacd8763221..fb83b21f7a5 100644
--- a/chromium/ui/accessibility/ax_table_info_unittest.cc
+++ b/chromium/ui/accessibility/ax_table_info_unittest.cc
@@ -73,7 +73,7 @@ void MakeRowHeader(AXNodeData* cell,
} // namespace
-// A macro for testing that a base::Optional has both a value and that its value
+// A macro for testing that a absl::optional has both a value and that its value
// is set to a particular expectation.
#define EXPECT_OPTIONAL_EQ(expected, actual) \
EXPECT_TRUE(actual.has_value()); \
diff --git a/chromium/ui/accessibility/ax_text_utils.cc b/chromium/ui/accessibility/ax_text_utils.cc
index 425ff7cfbe5..eef04fb6e26 100644
--- a/chromium/ui/accessibility/ax_text_utils.cc
+++ b/chromium/ui/accessibility/ax_text_utils.cc
@@ -10,9 +10,9 @@
#include "base/i18n/break_iterator.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
-#include "base/optional.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_enums.mojom.h"
namespace ui {
diff --git a/chromium/ui/accessibility/ax_text_utils_unittest.cc b/chromium/ui/accessibility/ax_text_utils_unittest.cc
index 8fd8a3f7186..8fd1b905e78 100644
--- a/chromium/ui/accessibility/ax_text_utils_unittest.cc
+++ b/chromium/ui/accessibility/ax_text_utils_unittest.cc
@@ -15,8 +15,7 @@
namespace ui {
TEST(AXTextUtils, FindAccessibleTextBoundaryWord) {
- const std::u16string text =
- base::UTF8ToUTF16("Hello there.This/is\ntesting.");
+ const std::u16string text = u"Hello there.This/is\ntesting.";
const size_t text_length = text.length();
std::vector<int> line_start_offsets;
line_start_offsets.push_back(19);
@@ -74,7 +73,7 @@ TEST(AXTextUtils, FindAccessibleTextBoundaryWord) {
}
TEST(AXTextUtils, FindAccessibleTextBoundaryLine) {
- const std::u16string text = base::UTF8ToUTF16("Line 1.\nLine 2\n\t");
+ const std::u16string text = u"Line 1.\nLine 2\n\t";
const size_t text_length = text.length();
std::vector<int> line_start_offsets;
line_start_offsets.push_back(8);
@@ -158,7 +157,7 @@ TEST(AXTextUtils, FindAccessibleTextBoundarySentence) {
};
const std::u16string text =
- base::UTF8ToUTF16("Sentence 1. Sentence 2...\n\tSentence 3! Sentence 4");
+ u"Sentence 1. Sentence 2...\n\tSentence 3! Sentence 4";
std::pair<size_t, size_t> boundaries =
find_sentence_boundaries_at_offset(text, 5);
EXPECT_EQ(0UL, boundaries.first);
@@ -190,7 +189,7 @@ TEST(AXTextUtils, FindAccessibleTextBoundarySentence) {
// The sentence should include whitespace all the way until the end of the
// string.
- const std::u16string text2 = base::UTF8ToUTF16("A sentence . \n\n\t\t\n");
+ const std::u16string text2 = u"A sentence . \n\n\t\t\n";
boundaries = find_sentence_boundaries_at_offset(text2, 10);
EXPECT_EQ(0UL, boundaries.first);
EXPECT_EQ(18UL, boundaries.second);
@@ -291,14 +290,14 @@ TEST(AXTextUtils, GetWordStartOffsetsMalformedInputTest) {
}
TEST(AXTextUtils, GetSentenceStartOffsetsBasicTest) {
- const std::u16string text = base::UTF8ToUTF16(
- "This is the first sentence. This is the second sentence");
+ const std::u16string text =
+ u"This is the first sentence. This is the second sentence";
EXPECT_THAT(GetSentenceStartOffsets(text), testing::ElementsAre(0, 28));
}
TEST(AXTextUtils, GetSentenceEndOffsetsBasicTest) {
- const std::u16string text = base::UTF8ToUTF16(
- "This is the first sentence. This is the second sentence");
+ const std::u16string text =
+ u"This is the first sentence. This is the second sentence";
EXPECT_THAT(GetSentenceEndOffsets(text), testing::ElementsAre(28, 55));
}
diff --git a/chromium/ui/accessibility/ax_tree.cc b/chromium/ui/accessibility/ax_tree.cc
index b9ac1d26551..dc01a1554ce 100644
--- a/chromium/ui/accessibility/ax_tree.cc
+++ b/chromium/ui/accessibility/ax_tree.cc
@@ -14,7 +14,9 @@
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
+#include "base/debug/activity_tracker.h"
#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/strings/stringprintf.h"
@@ -161,8 +163,8 @@ struct PendingStructureChanges {
create_node_count(0),
node_exists(!!node),
parent_node_id((node && node->parent())
- ? base::Optional<AXNodeID>{node->parent()->id()}
- : base::nullopt),
+ ? absl::optional<AXNodeID>{node->parent()->id()}
+ : absl::nullopt),
last_known_data(node ? &node->data() : nullptr) {}
// Returns true if this node has any changes remaining.
@@ -231,7 +233,7 @@ struct PendingStructureChanges {
// Keep track of the parent id for this node as of the last pending
// update that was processed.
- base::Optional<AXNodeID> parent_node_id;
+ absl::optional<AXNodeID> parent_node_id;
// Keep track of the last known node data for this node.
// This will be null either when a node does not exist in the tree, or
@@ -256,9 +258,10 @@ enum class AXTreePendingStructureStatus {
// Intermediate state to keep track of during a tree update.
struct AXTreeUpdateState {
- explicit AXTreeUpdateState(const AXTree& tree)
+ AXTreeUpdateState(const AXTree& tree, const AXTreeUpdate& pending_tree_update)
: pending_update_status(AXTreePendingStructureStatus::kNotStarted),
root_will_be_created(false),
+ pending_tree_update(pending_tree_update),
tree(tree) {}
// Returns whether this update removes |node|.
@@ -305,7 +308,7 @@ struct AXTreeUpdateState {
}
// Returns the parent node id for the pending node.
- base::Optional<AXNodeID> GetParentIdForPendingNode(AXNodeID node_id) {
+ absl::optional<AXNodeID> GetParentIdForPendingNode(AXNodeID node_id) {
DCHECK_EQ(AXTreePendingStructureStatus::kComputing, pending_update_status)
<< "This method should only be called while computing pending changes, "
"before updates are made to the tree.";
@@ -414,9 +417,9 @@ struct AXTreeUpdateState {
++data->destroy_node_count;
data->node_exists = false;
data->last_known_data = nullptr;
- data->parent_node_id = base::nullopt;
+ data->parent_node_id = absl::nullopt;
if (pending_root_id == node_id)
- pending_root_id = base::nullopt;
+ pending_root_id = absl::nullopt;
return true;
}
@@ -448,7 +451,7 @@ struct AXTreeUpdateState {
// Returns true on success, false on failure when the node will already exist.
bool IncrementPendingCreateNodeCount(
AXNodeID node_id,
- base::Optional<AXNodeID> parent_node_id) {
+ absl::optional<AXNodeID> parent_node_id) {
DCHECK_EQ(AXTreePendingStructureStatus::kComputing, pending_update_status)
<< "This method should only be called while computing pending changes, "
"before updates are made to the tree.";
@@ -486,7 +489,7 @@ struct AXTreeUpdateState {
DCHECK_EQ(AXTreePendingStructureStatus::kComputing, pending_update_status)
<< "This method should only be called while computing pending changes, "
"before updates are made to the tree.";
- base::Optional<AXNodeID> parent_node_id =
+ absl::optional<AXNodeID> parent_node_id =
GetParentIdForPendingNode(node_id);
if (parent_node_id) {
invalidate_unignored_cached_values_ids.insert(*parent_node_id);
@@ -499,7 +502,7 @@ struct AXTreeUpdateState {
// Keeps track of the root node id when calculating what changes will occur
// during an update before the update applies changes.
- base::Optional<AXNodeID> pending_root_id;
+ absl::optional<AXNodeID> pending_root_id;
// Keeps track of whether the root node will need to be created as a new node.
// This may occur either when the root node does not exist before applying
@@ -540,7 +543,12 @@ struct AXTreeUpdateState {
// Optional copy of the old tree data, only populated when the tree
// data has changed.
- base::Optional<AXTreeData> old_tree_data;
+ absl::optional<AXTreeData> old_tree_data;
+
+ // Keep track of the pending tree update to help create useful error messages.
+ // TODO(crbug.com/1156601) Revert this once we have the crash data we need
+ // (crrev.com/c/2892259).
+ const AXTreeUpdate& pending_tree_update;
private:
PendingStructureChanges* GetPendingStructureChanges(AXNodeID node_id) const {
@@ -586,7 +594,7 @@ struct AXTree::OrderedSetItemsMap {
~OrderedSetItemsMap() = default;
// Check if a particular hierarchical level exists in this map.
- bool HierarchicalLevelExists(base::Optional<int> level) {
+ bool HierarchicalLevelExists(absl::optional<int> level) {
if (items_map_.find(level) == items_map_.end())
return false;
return true;
@@ -594,7 +602,7 @@ struct AXTree::OrderedSetItemsMap {
// Add the OrderedSetContent to the corresponding hierarchical level in the
// map.
- void Add(base::Optional<int> level,
+ void Add(absl::optional<int> level,
const OrderedSetContent& ordered_set_content) {
if (!HierarchicalLevelExists(level))
items_map_[level] = std::vector<OrderedSetContent>();
@@ -609,7 +617,7 @@ struct AXTree::OrderedSetItemsMap {
// of being populated.
// - All other OrderedSetContent other than the last one on a level
// represents a complete ordered set and should not be modified.
- void AddItemToBack(base::Optional<int> level, const AXNode* item) {
+ void AddItemToBack(absl::optional<int> level, const AXNode* item) {
if (!HierarchicalLevelExists(level))
return;
@@ -636,7 +644,7 @@ struct AXTree::OrderedSetItemsMap {
void Clear() { items_map_.clear(); }
// Maps a hierarchical level to a list of OrderedSetContent.
- std::map<base::Optional<int32_t>, std::vector<OrderedSetContent>> items_map_;
+ std::map<absl::optional<int32_t>, std::vector<OrderedSetContent>> items_map_;
};
AXTree::AXTree() {
@@ -933,7 +941,7 @@ bool AXTree::Unserialize(const AXTreeUpdate& update) {
[](std::vector<AXEventIntent>* event_intents) { event_intents->clear(); },
&event_intents_));
- AXTreeUpdateState update_state(*this);
+ AXTreeUpdateState update_state(*this, update);
const AXNodeID old_root_id = root_ ? root_->id() : kInvalidAXNodeID;
// Accumulates the work that will be required to update the AXTree.
@@ -942,6 +950,9 @@ bool AXTree::Unserialize(const AXTreeUpdate& update) {
if (!ComputePendingChanges(update, &update_state))
return false;
+ // Log unserialize perf after early returns.
+ SCOPED_UMA_HISTOGRAM_TIMER("Accessibility.Performance.Tree.Unserialize");
+
// Notify observers of subtrees and nodes that are about to be destroyed or
// reparented, this must be done before applying any updates to the tree.
for (auto&& pair : update_state.node_id_to_pending_data) {
@@ -1255,9 +1266,9 @@ bool AXTree::ComputePendingChanges(const AXTreeUpdate& update,
update_state->pending_update_status =
AXTreePendingStructureStatus::kComputing;
- base::AutoReset<base::Optional<AXNodeID>> pending_root_id_resetter(
+ base::AutoReset<absl::optional<AXNodeID>> pending_root_id_resetter(
&update_state->pending_root_id,
- root_ ? base::Optional<AXNodeID>{root_->id()} : base::nullopt);
+ root_ ? absl::optional<AXNodeID>{root_->id()} : absl::nullopt);
// We distinguish between updating the root, e.g. changing its children or
// some of its attributes, or replacing the root completely. If the root is
@@ -1334,7 +1345,7 @@ bool AXTree::ComputePendingChangesToNode(const AXNodeData& new_data,
// Creation is implicit for new root nodes. If |new_data.id| is already
// pending for creation, then it must be a duplicate entry in the tree.
if (!update_state->IncrementPendingCreateNodeCount(new_data.id,
- base::nullopt)) {
+ absl::nullopt)) {
ACCESSIBILITY_TREE_UNSERIALIZE_ERROR_HISTOGRAM(
AXTreeUnserializeError::kCreationPending);
RecordError(base::StringPrintf(
@@ -1910,9 +1921,37 @@ bool AXTree::CreateNewChildVector(AXNode* node,
// This is a serious error - nodes should never be reparented.
// If this case occurs, continue so this node isn't left in an
// inconsistent state, but return failure at the end.
- RecordError(base::StringPrintf(
- "Node %d reparented from %d to %d", child->id(),
- child->parent() ? child->parent()->id() : 0, node->id()));
+ if (child->parent()) {
+ RecordError(base::StringPrintf("Node %d reparented from %d to %d",
+ child->id(), child->parent()->id(),
+ node->id()));
+ } else {
+ // --- Begin temporary change ---
+ // TODO(crbug.com/1156601) Revert this once we have the crash data we
+ // need (crrev.com/c/2892259)
+ // Diagnose strange errors "Node 1 reparented from 0 to 2", which
+ // sounds like the root node is getting the <html> element as a parent
+ // -- in the normal case, the root is 1 and <html> is 2.
+ std::ostringstream error;
+ error << "Node did not have a previous parent, but "
+ "reparenting error triggered:"
+ << "\n* Child = " << *child << "\n* New parent = " << *node
+ << "\n* root_will_be_created = "
+ << update_state->root_will_be_created
+ << "\n* pending_root_id = "
+ << (update_state->pending_root_id
+ ? *update_state->pending_root_id
+ : kInvalidAXNodeID)
+ << "\nTree update: "
+ << update_state->pending_tree_update.ToString();
+ // Add the error message to "breadcrumbs" in crash reports:
+ base::debug::ScopedActivity scoped_activity;
+ base::debug::ActivityUserData& user_data =
+ scoped_activity.user_data();
+ user_data.SetString("ax_reparenting_error", error.str());
+ CHECK(false) << error.str();
+ // --- End temporary change ---
+ }
success = false;
continue;
}
@@ -1949,13 +1988,13 @@ void AXTree::PopulateOrderedSetItemsMap(
// this, the set container (e.g. <tree>) will take on the min of the levels
// of its direct children(e.g. <treeitem>), if the children's levels are
// defined.
- base::Optional<int> ordered_set_min_level =
+ absl::optional<int> ordered_set_min_level =
ordered_set->GetHierarchicalLevel();
for (AXNode::UnignoredChildIterator child =
ordered_set->UnignoredChildrenBegin();
child != ordered_set->UnignoredChildrenEnd(); ++child) {
- base::Optional<int> child_level = child->GetHierarchicalLevel();
+ absl::optional<int> child_level = child->GetHierarchicalLevel();
if (child_level) {
ordered_set_min_level = ordered_set_min_level
? std::min(child_level, ordered_set_min_level)
@@ -1964,7 +2003,7 @@ void AXTree::PopulateOrderedSetItemsMap(
}
RecursivelyPopulateOrderedSetItemsMap(original_node, ordered_set, ordered_set,
- ordered_set_min_level, base::nullopt,
+ ordered_set_min_level, absl::nullopt,
items_map_to_be_populated);
// If after RecursivelyPopulateOrderedSetItemsMap() call, the corresponding
@@ -1986,8 +2025,8 @@ void AXTree::RecursivelyPopulateOrderedSetItemsMap(
const AXNode& original_node,
const AXNode* ordered_set,
const AXNode* local_parent,
- base::Optional<int> ordered_set_min_level,
- base::Optional<int> prev_level,
+ absl::optional<int> ordered_set_min_level,
+ absl::optional<int> prev_level,
OrderedSetItemsMap* items_map_to_be_populated) const {
// For optimization purpose, we want to only populate set items that are
// direct descendants of |ordered_set|, since we will only be calculating
@@ -2022,7 +2061,7 @@ void AXTree::RecursivelyPopulateOrderedSetItemsMap(
continue;
}
- base::Optional<int> curr_level = child->GetHierarchicalLevel();
+ absl::optional<int> curr_level = child->GetHierarchicalLevel();
// Add child to |items_map_to_be_populated| if role matches with the role of
// |ordered_set|. If role of node is kRadioButton, don't add items of other
@@ -2202,7 +2241,7 @@ void AXTree::ComputeSetSizePosInSetAndCacheHelper(
ordered_set->GetIntAttribute(ax::mojom::IntAttribute::kSetSize));
// Cache |ordered_set|'s hierarchical level.
- base::Optional<int> ordered_set_level = ordered_set->GetHierarchicalLevel();
+ absl::optional<int> ordered_set_level = ordered_set->GetHierarchicalLevel();
if (node_set_size_pos_in_set_info_map_.find(ordered_set->id()) ==
node_set_size_pos_in_set_info_map_.end()) {
node_set_size_pos_in_set_info_map_[ordered_set->id()] =
@@ -2232,7 +2271,7 @@ void AXTree::ComputeSetSizePosInSetAndCacheHelper(
} // End of iterating over each item in |ordered_set_content|.
}
-base::Optional<int> AXTree::GetPosInSet(const AXNode& node) {
+absl::optional<int> AXTree::GetPosInSet(const AXNode& node) {
if (node.data().role == ax::mojom::Role::kPopUpButton &&
node.GetUnignoredChildCount() == 0 &&
node.HasIntAttribute(ax::mojom::IntAttribute::kPosInSet)) {
@@ -2246,28 +2285,28 @@ base::Optional<int> AXTree::GetPosInSet(const AXNode& node) {
}
if (GetTreeUpdateInProgressState())
- return base::nullopt;
+ return absl::nullopt;
// Only allow this to be called on nodes that can hold PosInSet values,
// which are defined in the ARIA spec.
if (!node.IsOrderedSetItem() || node.IsIgnored())
- return base::nullopt;
+ return absl::nullopt;
const AXNode* ordered_set = node.GetOrderedSet();
if (!ordered_set)
- return base::nullopt;
+ return absl::nullopt;
// Compute, cache, then return.
ComputeSetSizePosInSetAndCache(node, ordered_set);
- base::Optional<int> pos_in_set =
+ absl::optional<int> pos_in_set =
node_set_size_pos_in_set_info_map_[node.id()].pos_in_set;
if (pos_in_set.has_value() && pos_in_set.value() < 1)
- return base::nullopt;
+ return absl::nullopt;
return pos_in_set;
}
-base::Optional<int> AXTree::GetSetSize(const AXNode& node) {
+absl::optional<int> AXTree::GetSetSize(const AXNode& node) {
if (node.data().role == ax::mojom::Role::kPopUpButton &&
node.GetUnignoredChildCount() == 0 &&
node.HasIntAttribute(ax::mojom::IntAttribute::kSetSize)) {
@@ -2281,14 +2320,14 @@ base::Optional<int> AXTree::GetSetSize(const AXNode& node) {
}
if (GetTreeUpdateInProgressState())
- return base::nullopt;
+ return absl::nullopt;
// Only allow this to be called on nodes that can hold SetSize values, which
// are defined in the ARIA spec. However, we allow set-like items to receive
// SetSize values for internal purposes.
if ((!node.IsOrderedSetItem() && !node.IsOrderedSet()) || node.IsIgnored() ||
node.IsEmbeddedGroup()) {
- return base::nullopt;
+ return absl::nullopt;
}
// If |node| is item-like, find its outerlying ordered set. Otherwise,
@@ -2297,7 +2336,7 @@ base::Optional<int> AXTree::GetSetSize(const AXNode& node) {
if (IsItemLike(node.data().role))
ordered_set = node.GetOrderedSet();
if (!ordered_set)
- return base::nullopt;
+ return absl::nullopt;
// For popup buttons that control a single element, inherit the controlled
// item's SetSize. Skip this block if the popup button controls itself.
@@ -2308,7 +2347,7 @@ base::Optional<int> AXTree::GetSetSize(const AXNode& node) {
controls_ids[0] != node.id()) {
const AXNode& controlled_item = *GetFromId(controls_ids[0]);
- base::Optional<int> controlled_item_set_size =
+ absl::optional<int> controlled_item_set_size =
GetSetSize(controlled_item);
node_set_size_pos_in_set_info_map_[node.id()].set_size =
controlled_item_set_size;
@@ -2318,10 +2357,10 @@ base::Optional<int> AXTree::GetSetSize(const AXNode& node) {
// Compute, cache, then return.
ComputeSetSizePosInSetAndCache(node, ordered_set);
- base::Optional<int> set_size =
+ absl::optional<int> set_size =
node_set_size_pos_in_set_info_map_[node.id()].set_size;
if (set_size.has_value() && set_size.value() < 0)
- return base::nullopt;
+ return absl::nullopt;
return set_size;
}
diff --git a/chromium/ui/accessibility/ax_tree.h b/chromium/ui/accessibility/ax_tree.h
index 1ff83ecd3b4..1a836fbd3fa 100644
--- a/chromium/ui/accessibility/ax_tree.h
+++ b/chromium/ui/accessibility/ax_tree.h
@@ -174,11 +174,11 @@ class AX_EXPORT AXTree : public AXNode::OwnerTree {
// Returns the PosInSet of |node|. Looks in node_set_size_pos_in_set_info_map_
// for cached value. Calls |ComputeSetSizePosInSetAndCache|if no value is
// present in the cache.
- base::Optional<int> GetPosInSet(const AXNode& node) override;
+ absl::optional<int> GetPosInSet(const AXNode& node) override;
// Returns the SetSize of |node|. Looks in node_set_size_pos_in_set_info_map_
// for cached value. Calls |ComputeSetSizePosInSetAndCache|if no value is
// present in the cache.
- base::Optional<int> GetSetSize(const AXNode& node) override;
+ absl::optional<int> GetSetSize(const AXNode& node) override;
Selection GetUnignoredSelection() const override;
@@ -362,9 +362,9 @@ class AX_EXPORT AXTree : public AXNode::OwnerTree {
NodeSetSizePosInSetInfo();
~NodeSetSizePosInSetInfo();
- base::Optional<int> pos_in_set;
- base::Optional<int> set_size;
- base::Optional<int> lowest_hierarchical_level;
+ absl::optional<int> pos_in_set;
+ absl::optional<int> set_size;
+ absl::optional<int> lowest_hierarchical_level;
};
// Represents the content of an ordered set which includes the ordered set
@@ -391,8 +391,8 @@ class AX_EXPORT AXTree : public AXNode::OwnerTree {
const AXNode& original_node,
const AXNode* ordered_set,
const AXNode* local_parent,
- base::Optional<int> ordered_set_min_level,
- base::Optional<int> prev_level,
+ absl::optional<int> ordered_set_min_level,
+ absl::optional<int> prev_level,
OrderedSetItemsMap* items_map_to_be_populated) const;
// Computes the pos_in_set and set_size values of all items in ordered_set and
diff --git a/chromium/ui/accessibility/ax_tree_data.cc b/chromium/ui/accessibility/ax_tree_data.cc
index 945ed6b69b6..f167fb3ab37 100644
--- a/chromium/ui/accessibility/ax_tree_data.cc
+++ b/chromium/ui/accessibility/ax_tree_data.cc
@@ -8,7 +8,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/accessibility/ax_enum_util.h"
#include "ui/accessibility/ax_enums.mojom.h"
diff --git a/chromium/ui/accessibility/ax_tree_data.h b/chromium/ui/accessibility/ax_tree_data.h
index 66bbaee13ac..98623e1769c 100644
--- a/chromium/ui/accessibility/ax_tree_data.h
+++ b/chromium/ui/accessibility/ax_tree_data.h
@@ -11,8 +11,8 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "base/strings/string_split.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_action_handler_registry.h"
#include "ui/accessibility/ax_base_export.h"
#include "ui/accessibility/ax_enums.mojom-forward.h"
diff --git a/chromium/ui/accessibility/ax_tree_id.cc b/chromium/ui/accessibility/ax_tree_id.cc
index d7f8877f6b3..15c4f3ee84a 100644
--- a/chromium/ui/accessibility/ax_tree_id.cc
+++ b/chromium/ui/accessibility/ax_tree_id.cc
@@ -30,7 +30,7 @@ AXTreeID::AXTreeID(const std::string& string) {
type_ = ax::mojom::AXTreeIDType::kUnknown;
} else {
type_ = ax::mojom::AXTreeIDType::kToken;
- base::Optional<base::UnguessableToken> token =
+ absl::optional<base::UnguessableToken> token =
util::ValueToUnguessableToken(base::Value(string));
CHECK(token);
token_ = *token;
diff --git a/chromium/ui/accessibility/ax_tree_id.h b/chromium/ui/accessibility/ax_tree_id.h
index 354ef7c6643..cd1fa9f374c 100644
--- a/chromium/ui/accessibility/ax_tree_id.h
+++ b/chromium/ui/accessibility/ax_tree_id.h
@@ -51,7 +51,7 @@ class AX_BASE_EXPORT AXTreeID {
std::string ToString() const;
ax::mojom::AXTreeIDType type() const { return type_; }
- const base::Optional<base::UnguessableToken>& token() const { return token_; }
+ const absl::optional<base::UnguessableToken>& token() const { return token_; }
bool operator==(const AXTreeID& rhs) const;
bool operator!=(const AXTreeID& rhs) const;
@@ -69,7 +69,7 @@ class AX_BASE_EXPORT AXTreeID {
friend void swap(AXTreeID& first, AXTreeID& second);
ax::mojom::AXTreeIDType type_;
- base::Optional<base::UnguessableToken> token_ = base::nullopt;
+ absl::optional<base::UnguessableToken> token_ = absl::nullopt;
};
// For use in std::unordered_map.
diff --git a/chromium/ui/accessibility/ax_tree_serializer.h b/chromium/ui/accessibility/ax_tree_serializer.h
index 798170787b6..f63b2cecd89 100644
--- a/chromium/ui/accessibility/ax_tree_serializer.h
+++ b/chromium/ui/accessibility/ax_tree_serializer.h
@@ -10,7 +10,6 @@
#include <ctime>
#include <ostream>
-#include <unordered_map>
#include <unordered_set>
#include <vector>
@@ -78,7 +77,7 @@ class AXTreeSerializer {
// for no maximum. This is not a hard maximum - once it hits or
// exceeds this maximum it stops walking the children of nodes, but
// it may exceed this value a bit in order to create a consistent
- // tree. This is only intended to be used for one-time tree snapshots.
+ // tree.
void set_max_node_count(size_t max_node_count) {
max_node_count_ = max_node_count;
}
@@ -96,6 +95,11 @@ class AXTreeSerializer {
// ids or changing during serialization.
bool SerializeChanges(AXSourceNode node, AXTreeUpdate* out_update);
+ // Get incompletely serialized nodes. This will only be nonempty if either
+ // set_max_node_count or set_timeout were used. This is only valid after a
+ // call to SerializeChanges, and it's reset with each call.
+ std::vector<AXNodeID> GetIncompleteNodeIds();
+
// Invalidate the subtree rooted at this node, ensuring that the whole
// subtree is re-serialized the next time any of those nodes end up
// being serialized.
@@ -212,8 +216,15 @@ class AXTreeSerializer {
// The maximum time to spend serializing before timing out, or 0
// if there's no maximum.
base::TimeDelta timeout_;
+
+ // The timer, which runs if there's a nonzero timeout and it hasn't
+ // yet expired. Once the timeout elapses, the timer is deleted.
std::unique_ptr<base::ElapsedTimer> timer_;
+ // The IDs of nodes that weren't able to be completely serialized due to
+ // max_node_count_ or timeout_.
+ std::vector<AXNodeID> incomplete_node_ids_;
+
// Keeps track of if Reset() was called. If so, we need to always
// explicitly set node_id_to_clear to ensure that the next serialized
// tree is treated as a completely new tree and not a partial update.
@@ -424,6 +435,7 @@ bool AXTreeSerializer<AXSourceNode>::SerializeChanges(
AXTreeUpdate* out_update) {
if (!timeout_.is_zero())
timer_ = std::make_unique<base::ElapsedTimer>();
+ incomplete_node_ids_.clear();
// Send the tree data if it's changed since the last update, or if
// out_update->has_tree_data is already set to true.
@@ -493,6 +505,12 @@ bool AXTreeSerializer<AXSourceNode>::SerializeChanges(
}
template <typename AXSourceNode>
+std::vector<AXNodeID> AXTreeSerializer<AXSourceNode>::GetIncompleteNodeIds() {
+ DCHECK(max_node_count_ > 0 || !timeout_.is_zero());
+ return incomplete_node_ids_;
+}
+
+template <typename AXSourceNode>
void AXTreeSerializer<AXSourceNode>::InvalidateSubtree(AXSourceNode node) {
ClientTreeNode* client_node = ClientTreeNodeById(tree_->GetId(node));
if (client_node)
@@ -573,8 +591,18 @@ bool AXTreeSerializer<AXSourceNode>::SerializeChangedNodes(
should_terminate_early = true;
// Also terminate early if a timeout is reached.
- if (!timeout_.is_zero() && timer_->Elapsed() >= timeout_)
- should_terminate_early = true;
+ if (!timeout_.is_zero()) {
+ if (timer_ && timer_->Elapsed() >= timeout_) {
+ // Terminate early and delete the timer so that we don't have to
+ // keep checking if we timed out.
+ should_terminate_early = true;
+ timer_.reset();
+ } else if (!timer_) {
+ // Already timed out; keep terminating early until the serialization
+ // is done.
+ should_terminate_early = true;
+ }
+ }
// Iterate over the ids of the children of |node|.
// Create a set of the child ids so we can quickly look
@@ -585,25 +613,10 @@ bool AXTreeSerializer<AXSourceNode>::SerializeChangedNodes(
std::set<AXNodeID> new_ignored_ids;
std::set<AXNodeID> new_child_ids;
std::vector<AXSourceNode> children;
- if (!should_terminate_early) {
- tree_->GetChildren(node, &children);
+ if (should_terminate_early) {
+ incomplete_node_ids_.push_back(id);
} else {
- static bool logged_once = false;
- if (!logged_once) {
- logged_once = true;
-
- LOG(WARNING) << "Warning: stopped serializing AX nodes before "
- << "serialization was complete.";
- if (max_node_count_) {
- LOG(WARNING) << "Nodes serialized so far: " << out_update->nodes.size()
- << ", max_node_count: " << max_node_count_;
- }
- if (!timeout_.is_zero()) {
- LOG(WARNING) << "Elapsed time in ms: "
- << timer_->Elapsed().InMilliseconds()
- << ", timeout: " << timeout_.InMilliseconds();
- }
- }
+ tree_->GetChildren(node, &children);
}
for (size_t i = 0; i < children.size(); ++i) {
AXSourceNode& child = children[i];
diff --git a/chromium/ui/accessibility/ax_tree_serializer_unittest.cc b/chromium/ui/accessibility/ax_tree_serializer_unittest.cc
index 0e7a97ad726..a693672ba7f 100644
--- a/chromium/ui/accessibility/ax_tree_serializer_unittest.cc
+++ b/chromium/ui/accessibility/ax_tree_serializer_unittest.cc
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/accessibility/ax_common.h"
@@ -618,4 +619,69 @@ TEST_F(AXTreeSerializerTest, TestClearedNodesWhenUpdatingBranch) {
serializer_.reset();
}
+TEST_F(AXTreeSerializerTest, TestPartialSerialization) {
+ // Serialize only part of the tree.
+
+ // (1)
+ treedata0_.root_id = 1;
+ treedata0_.nodes.resize(1);
+ treedata0_.nodes[0].id = 1;
+
+ // (1 (2 (3 4)) (5 (6 7)))
+ treedata1_.root_id = 1;
+ treedata1_.nodes.resize(7);
+ treedata1_.nodes[0].id = 1;
+ treedata1_.nodes[0].child_ids = {2, 5};
+ treedata1_.nodes[1].id = 2;
+ treedata1_.nodes[1].child_ids = {3, 4};
+ treedata1_.nodes[2].id = 3;
+ treedata1_.nodes[3].id = 4;
+ treedata1_.nodes[4].id = 5;
+ treedata1_.nodes[4].child_ids = {6, 7};
+ treedata1_.nodes[5].id = 6;
+ treedata1_.nodes[6].id = 7;
+
+ for (int max_node_count = 1; max_node_count <= 4; max_node_count++) {
+ SCOPED_TRACE(base::StringPrintf("Max node count: %d", max_node_count));
+ CreateTreeSerializer();
+
+ serializer_->Reset();
+ serializer_->set_max_node_count(max_node_count);
+
+ AXTreeUpdate update;
+ ASSERT_TRUE(serializer_->SerializeChanges(tree1_->GetFromId(1), &update));
+
+ // The update should unserialize without errors.
+ AXSerializableTree dst_tree(treedata0_);
+ EXPECT_TRUE(dst_tree.Unserialize(update)) << dst_tree.error();
+
+ // The tree should be incomplete; it should have too few nodes.
+ EXPECT_LT(update.nodes.size(), treedata1_.nodes.size());
+ EXPECT_LT(dst_tree.size(), static_cast<int>(treedata1_.nodes.size()));
+
+ // The serializer should give us a list of nodes that have yet to
+ // be serialized.
+ std::vector<AXNodeID> incomplete_node_ids =
+ serializer_->GetIncompleteNodeIds();
+ EXPECT_FALSE(incomplete_node_ids.empty());
+
+ // Serialize the incomplete nodes, with no more limit.
+ serializer_->set_max_node_count(0);
+ for (AXNodeID id : incomplete_node_ids) {
+ update = AXTreeUpdate();
+ ASSERT_TRUE(
+ serializer_->SerializeChanges(tree1_->GetFromId(id), &update));
+ EXPECT_TRUE(dst_tree.Unserialize(update)) << dst_tree.error();
+ }
+
+ // The result should be indistinguishable from the source tree.
+ std::unique_ptr<AXTreeSource<const AXNode*>> dst_tree_source(
+ dst_tree.CreateTreeSource());
+ AXTreeSerializer<const AXNode*> serializer(dst_tree_source.get());
+ AXTreeUpdate dst_update;
+ CHECK(serializer.SerializeChanges(dst_tree.root(), &dst_update));
+ ASSERT_EQ(treedata1_.ToString(), dst_update.ToString());
+ }
+}
+
} // namespace ui
diff --git a/chromium/ui/accessibility/ax_tree_unittest.cc b/chromium/ui/accessibility/ax_tree_unittest.cc
index e169e7d50ea..d8d4d5ede91 100644
--- a/chromium/ui/accessibility/ax_tree_unittest.cc
+++ b/chromium/ui/accessibility/ax_tree_unittest.cc
@@ -97,7 +97,7 @@ class TestAXTreeObserver : public AXTreeObserver {
tree_data_changed_ = true;
}
- base::Optional<AXNodeID> unignored_parent_id_before_node_deleted;
+ absl::optional<AXNodeID> unignored_parent_id_before_node_deleted;
void OnNodeWillBeDeleted(AXTree* tree, AXNode* node) override {
// When this observer function is called in an update, the actual node
// deletion has not happened yet. Verify that node still exists in the tree.
@@ -295,7 +295,7 @@ class TestAXTreeObserver : public AXTreeObserver {
} // namespace
-// A macro for testing that a base::Optional has both a value and that its value
+// A macro for testing that a absl::optional has both a value and that its value
// is set to a particular expectation.
#define EXPECT_OPTIONAL_EQ(expected, actual) \
EXPECT_TRUE(actual.has_value()); \
@@ -411,6 +411,9 @@ TEST(AXTreeTest, LeaveOrphanedDeletedSubtreeFails) {
initial_state.nodes[2].id = 3;
AXTree tree(initial_state);
+ histogram_tester.ExpectTotalCount(
+ "Accessibility.Performance.Tree.Unserialize", 1);
+
// This should fail because we delete a subtree rooted at id=2
// but never update it.
AXTreeUpdate update;
@@ -422,6 +425,8 @@ TEST(AXTreeTest, LeaveOrphanedDeletedSubtreeFails) {
histogram_tester.ExpectUniqueSample(
"Accessibility.Reliability.Tree.UnserializeError",
AXTreeUnserializeError::kPendingNodes, 1);
+ histogram_tester.ExpectTotalCount(
+ "Accessibility.Performance.Tree.Unserialize", 2);
}
TEST(AXTreeTest, LeaveOrphanedNewChildFails) {
@@ -432,6 +437,9 @@ TEST(AXTreeTest, LeaveOrphanedNewChildFails) {
initial_state.nodes[0].id = 1;
AXTree tree(initial_state);
+ histogram_tester.ExpectTotalCount(
+ "Accessibility.Performance.Tree.Unserialize", 1);
+
// This should fail because we add a new child to the root node
// but never update it.
AXTreeUpdate update;
@@ -443,6 +451,8 @@ TEST(AXTreeTest, LeaveOrphanedNewChildFails) {
histogram_tester.ExpectUniqueSample(
"Accessibility.Reliability.Tree.UnserializeError",
AXTreeUnserializeError::kPendingNodes, 1);
+ histogram_tester.ExpectTotalCount(
+ "Accessibility.Performance.Tree.Unserialize", 2);
}
TEST(AXTreeTest, DuplicateChildIdFails) {
@@ -453,6 +463,9 @@ TEST(AXTreeTest, DuplicateChildIdFails) {
initial_state.nodes[0].id = 1;
AXTree tree(initial_state);
+ histogram_tester.ExpectTotalCount(
+ "Accessibility.Performance.Tree.Unserialize", 1);
+
// This should fail because a child id appears twice.
AXTreeUpdate update;
update.nodes.resize(2);
@@ -465,6 +478,8 @@ TEST(AXTreeTest, DuplicateChildIdFails) {
histogram_tester.ExpectUniqueSample(
"Accessibility.Reliability.Tree.UnserializeError",
AXTreeUnserializeError::kDuplicateChild, 1);
+ histogram_tester.ExpectTotalCount(
+ "Accessibility.Performance.Tree.Unserialize", 1);
}
TEST(AXTreeTest, InvalidReparentingFails) {
@@ -480,6 +495,9 @@ TEST(AXTreeTest, InvalidReparentingFails) {
AXTree tree(initial_state);
+ histogram_tester.ExpectTotalCount(
+ "Accessibility.Performance.Tree.Unserialize", 1);
+
// This should fail because node 3 is reparented from node 2 to node 1
// without deleting node 1's subtree first.
AXTreeUpdate update;
@@ -495,6 +513,8 @@ TEST(AXTreeTest, InvalidReparentingFails) {
histogram_tester.ExpectUniqueSample(
"Accessibility.Reliability.Tree.UnserializeError",
AXTreeUnserializeError::kReparent, 1);
+ histogram_tester.ExpectTotalCount(
+ "Accessibility.Performance.Tree.Unserialize", 1);
}
TEST(AXTreeTest, NoReparentingOfRootIfNoNewRoot) {
@@ -3503,7 +3523,7 @@ TEST(AXTreeTest, SetSizePosInSetNestedContainer) {
tree_update.nodes[3].id = 4;
tree_update.nodes[3].role = ax::mojom::Role::kListItem; // 2 of 4
tree_update.nodes[4].id = 5;
- tree_update.nodes[4].role = ax::mojom::Role::kIgnored;
+ tree_update.nodes[4].role = ax::mojom::Role::kNone;
tree_update.nodes[4].child_ids = {6};
tree_update.nodes[5].id = 6;
tree_update.nodes[5].role = ax::mojom::Role::kListItem; // 3 of 4
@@ -4563,7 +4583,7 @@ TEST(AXTreeTest, OnNodeHasBeenDeleted) {
// Verify that the nodes we intend to delete in the update are actually
// absent from the tree.
for (auto id : test_observer.deleted_ids()) {
- SCOPED_TRACE(testing::Message()
+ SCOPED_TRACE(::testing::Message()
<< "Node with id=" << id << ", should not exist in the tree");
EXPECT_EQ(nullptr, tree.GetFromId(id));
}
diff --git a/chromium/ui/accessibility/ax_tree_update.h b/chromium/ui/accessibility/ax_tree_update.h
index 3c69827d17f..3b8cdcaccd7 100644
--- a/chromium/ui/accessibility/ax_tree_update.h
+++ b/chromium/ui/accessibility/ax_tree_update.h
@@ -9,7 +9,6 @@
#include <stdint.h>
#include <string>
-#include <unordered_map>
#include <vector>
#include "ui/accessibility/ax_base_export.h"
diff --git a/chromium/ui/accessibility/extensions/chromevoxclassic/BUILD.gn b/chromium/ui/accessibility/extensions/chromevoxclassic/BUILD.gn
index 8975eaecaaf..88f9d1edf07 100644
--- a/chromium/ui/accessibility/extensions/chromevoxclassic/BUILD.gn
+++ b/chromium/ui/accessibility/extensions/chromevoxclassic/BUILD.gn
@@ -505,6 +505,8 @@ test("chromevox_tests") {
"//chrome/browser/extensions/browsertest_util.h",
"//chrome/browser/ui/webui/web_ui_test_handler.cc",
"//chrome/browser/ui/webui/web_ui_test_handler.h",
+ "//chrome/test/base/devtools_listener.cc",
+ "//chrome/test/base/devtools_listener.h",
"//chrome/test/base/extension_js_browser_test.cc",
"//chrome/test/base/extension_js_browser_test.h",
"//chrome/test/base/extension_load_waiter_one_shot.cc",
diff --git a/chromium/ui/accessibility/mojom/BUILD.gn b/chromium/ui/accessibility/mojom/BUILD.gn
index b934284cf27..3302ef749a9 100644
--- a/chromium/ui/accessibility/mojom/BUILD.gn
+++ b/chromium/ui/accessibility/mojom/BUILD.gn
@@ -7,7 +7,6 @@ import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojom") {
sources = [
"ax_action_data.mojom",
- "ax_assistant_structure.mojom",
"ax_event.mojom",
"ax_event_intent.mojom",
"ax_node_data.mojom",
@@ -42,30 +41,6 @@ mojom("mojom") {
{
types = [
{
- mojom = "ax.mojom.AssistantTree"
- cpp = "::std::unique_ptr<::ui::AssistantTree>"
- move_only = true
- nullable_is_same_type = true
- },
- {
- mojom = "ax.mojom.AssistantNode"
- cpp = "::std::unique_ptr<::ui::AssistantNode>"
- move_only = true
- },
- ]
- traits_sources = [ "ax_assistant_structure_mojom_traits.cc" ]
- traits_headers = [ "ax_assistant_structure_mojom_traits.h" ]
- traits_public_deps = [
- "//ui/accessibility:ax_assistant",
- "//ui/gfx",
- "//ui/gfx/geometry/mojom",
- "//ui/gfx/geometry/mojom:mojom_traits",
- "//ui/gfx/range/mojom",
- ]
- },
- {
- types = [
- {
mojom = "ax.mojom.AXEventIntent"
cpp = "::ui::AXEventIntent"
},
@@ -147,3 +122,41 @@ mojom("mojom") {
},
]
}
+mojom("ax_assistant_mojom") {
+ sources = [ "ax_assistant_structure.mojom" ]
+
+ cpp_typemaps = [
+ {
+ types = [
+ {
+ mojom = "ax.mojom.AssistantTree"
+ cpp = "::std::unique_ptr<::ui::AssistantTree>"
+ move_only = true
+ nullable_is_same_type = true
+ },
+ {
+ mojom = "ax.mojom.AssistantNode"
+ cpp = "::std::unique_ptr<::ui::AssistantNode>"
+ move_only = true
+ },
+ ]
+ traits_sources = [ "ax_assistant_structure_mojom_traits.cc" ]
+ traits_headers = [ "ax_assistant_structure_mojom_traits.h" ]
+ traits_public_deps = [
+ "//ui/accessibility:ax_assistant",
+ "//ui/gfx",
+ "//ui/gfx/geometry/mojom",
+ "//ui/gfx/geometry/mojom:mojom_traits",
+ "//ui/gfx/range/mojom",
+ ]
+ },
+ ]
+
+ public_deps = [
+ "//mojo/public/mojom/base",
+ "//ui/gfx/geometry/mojom",
+ "//ui/gfx/mojom",
+ "//ui/gfx/range/mojom",
+ "//url/mojom:url_mojom_gurl",
+ ]
+}
diff --git a/chromium/ui/accessibility/mojom/ax_action_data.mojom b/chromium/ui/accessibility/mojom/ax_action_data.mojom
index d802f4a0700..cc835a2bf94 100644
--- a/chromium/ui/accessibility/mojom/ax_action_data.mojom
+++ b/chromium/ui/accessibility/mojom/ax_action_data.mojom
@@ -10,6 +10,8 @@ import "ui/gfx/geometry/mojom/geometry.mojom";
// A compact representation of an accessibility action and the arguments
// associated with that action. See ui::AXActionData for full documentation.
+// Next version: 1
+[Stable, Uuid="977807b3-17e0-4186-8398-deae1aeba2ec"]
struct AXActionData {
Action action;
ax.mojom.AXTreeID target_tree_id;
diff --git a/chromium/ui/accessibility/mojom/ax_assistant_structure_mojom_traits.h b/chromium/ui/accessibility/mojom/ax_assistant_structure_mojom_traits.h
index ee1814268f2..3498d8445c1 100644
--- a/chromium/ui/accessibility/mojom/ax_assistant_structure_mojom_traits.h
+++ b/chromium/ui/accessibility/mojom/ax_assistant_structure_mojom_traits.h
@@ -66,7 +66,7 @@ struct StructTraits<ax::mojom::AssistantNodeDataView,
static bool line_through(const std::unique_ptr<ui::AssistantNode>& node) {
return node->line_through;
}
- static base::Optional<gfx::Range> selection(
+ static absl::optional<gfx::Range> selection(
const std::unique_ptr<ui::AssistantNode>& node) {
return node->selection;
}
@@ -74,7 +74,7 @@ struct StructTraits<ax::mojom::AssistantNodeDataView,
const std::unique_ptr<ui::AssistantNode>& node) {
return node->class_name;
}
- static base::Optional<std::string> role(
+ static absl::optional<std::string> role(
const std::unique_ptr<ui::AssistantNode>& node) {
return node->role;
}
diff --git a/chromium/ui/accessibility/mojom/ax_tree_id.mojom b/chromium/ui/accessibility/mojom/ax_tree_id.mojom
index 0f3c79437e2..6b376213c88 100644
--- a/chromium/ui/accessibility/mojom/ax_tree_id.mojom
+++ b/chromium/ui/accessibility/mojom/ax_tree_id.mojom
@@ -7,6 +7,8 @@ module ax.mojom;
import "ui/accessibility/ax_enums.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
+// Next version: 1
+[Stable, Uuid="8bc56bf8-a206-42b2-970f-60347a23e7fa"]
union AXTreeID {
// Placeholder for an unknown AXTreeID. The value of this field is not used.
uint8 unknown;
diff --git a/chromium/ui/accessibility/platform/BUILD.gn b/chromium/ui/accessibility/platform/BUILD.gn
index 5533603bb95..277ea0b3f5b 100644
--- a/chromium/ui/accessibility/platform/BUILD.gn
+++ b/chromium/ui/accessibility/platform/BUILD.gn
@@ -65,12 +65,15 @@ source_set("platform") {
"inspect/ax_inspect.h",
"inspect/ax_inspect_scenario.cc",
"inspect/ax_inspect_scenario.h",
+ "inspect/ax_inspect_utils.cc",
+ "inspect/ax_inspect_utils.h",
"inspect/ax_property_node.cc",
"inspect/ax_property_node.h",
"inspect/ax_tree_formatter.cc",
"inspect/ax_tree_formatter.h",
"inspect/ax_tree_formatter_base.cc",
"inspect/ax_tree_formatter_base.h",
+ "inspect/ax_tree_indexer.h",
]
public_deps = [
diff --git a/chromium/ui/accessibility/platform/atk_util_auralinux_unittest.cc b/chromium/ui/accessibility/platform/atk_util_auralinux_unittest.cc
index 11342de5177..e5bcceeda09 100644
--- a/chromium/ui/accessibility/platform/atk_util_auralinux_unittest.cc
+++ b/chromium/ui/accessibility/platform/atk_util_auralinux_unittest.cc
@@ -16,8 +16,7 @@ namespace ui {
class AtkUtilAuraLinuxTest : public AXPlatformNodeTest {
public:
- AtkUtilAuraLinuxTest() {
- AXPlatformNode::NotifyAddAXModeFlags(kAXModeComplete);
+ AtkUtilAuraLinuxTest() : ax_mode_setter_(kAXModeComplete) {
// We need to create a platform node in order to install it as the root
// ATK node. The ATK bridge will complain if we try to use it without a
// root node installed.
@@ -44,6 +43,15 @@ class AtkUtilAuraLinuxTest : public AXPlatformNodeTest {
AtkUtilAuraLinuxTest(const AtkUtilAuraLinuxTest&) = delete;
AtkUtilAuraLinuxTest& operator=(const AtkUtilAuraLinuxTest&) = delete;
+
+ void TearDown() override {
+ AXPlatformNodeTest::TearDown();
+ // These tests set AtSpiReady to true. Reset to initial state.
+ AtkUtilAuraLinux::GetInstance()->SetAtSpiReady(false);
+ }
+
+ private:
+ ui::testing::ScopedAxModeSetter ax_mode_setter_;
};
TEST_F(AtkUtilAuraLinuxTest, KeySnooping) {
diff --git a/chromium/ui/accessibility/platform/ax_android_constants.h b/chromium/ui/accessibility/platform/ax_android_constants.h
index fe83123b0f1..837aab88a4f 100644
--- a/chromium/ui/accessibility/platform/ax_android_constants.h
+++ b/chromium/ui/accessibility/platform/ax_android_constants.h
@@ -5,7 +5,6 @@
#ifndef UI_ACCESSIBILITY_PLATFORM_AX_ANDROID_CONSTANTS_H_
#define UI_ACCESSIBILITY_PLATFORM_AX_ANDROID_CONSTANTS_H_
-#include <string>
#include "ui/accessibility/ax_export.h"
diff --git a/chromium/ui/accessibility/platform/ax_platform_atk_hyperlink.cc b/chromium/ui/accessibility/platform/ax_platform_atk_hyperlink.cc
index be91def6b40..889f7496405 100644
--- a/chromium/ui/accessibility/platform/ax_platform_atk_hyperlink.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_atk_hyperlink.cc
@@ -85,7 +85,7 @@ static gboolean AXPlatformAtkHyperlinkIsSelectedLink(
static int AXPlatformAtkHyperlinkGetStartIndex(AtkHyperlink* atk_hyperlink) {
g_return_val_if_fail(IS_AX_PLATFORM_ATK_HYPERLINK(atk_hyperlink), 0);
AXPlatformAtkHyperlink* link = AX_PLATFORM_ATK_HYPERLINK(atk_hyperlink);
- base::Optional<std::pair<int, int>> indices =
+ absl::optional<std::pair<int, int>> indices =
link->priv->platform_node->GetEmbeddedObjectIndices();
return indices.has_value() ? indices->first : 0;
}
@@ -93,7 +93,7 @@ static int AXPlatformAtkHyperlinkGetStartIndex(AtkHyperlink* atk_hyperlink) {
static int AXPlatformAtkHyperlinkGetEndIndex(AtkHyperlink* atk_hyperlink) {
g_return_val_if_fail(IS_AX_PLATFORM_ATK_HYPERLINK(atk_hyperlink), 0);
AXPlatformAtkHyperlink* link = AX_PLATFORM_ATK_HYPERLINK(atk_hyperlink);
- base::Optional<std::pair<int, int>> indices =
+ absl::optional<std::pair<int, int>> indices =
link->priv->platform_node->GetEmbeddedObjectIndices();
return indices.has_value() ? indices->second : 0;
}
diff --git a/chromium/ui/accessibility/platform/ax_platform_node.cc b/chromium/ui/accessibility/platform/ax_platform_node.cc
index 4f8d6305164..aa8612c332b 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node.cc
@@ -94,7 +94,7 @@ void AXPlatformNode::RemoveAXModeObserver(AXModeObserver* observer) {
// static
void AXPlatformNode::NotifyAddAXModeFlags(AXMode mode_flags) {
- // Note: this is only called on Windows.
+ // Note: this is only called on Windows, and in tests.
AXMode new_ax_mode(ax_mode_);
new_ax_mode |= mode_flags;
@@ -107,6 +107,17 @@ void AXPlatformNode::NotifyAddAXModeFlags(AXMode mode_flags) {
}
// static
+void AXPlatformNode::SetAXMode(AXMode new_mode) {
+ // Note: this is only called on Windows.
+ ax_mode_ = new_mode;
+}
+
+// static
+void AXPlatformNode::ResetAxModeForTesting() {
+ ax_mode_ = 0;
+}
+
+// static
void AXPlatformNode::SetPopupFocusOverride(
gfx::NativeViewAccessible popup_focus_override) {
popup_focus_override_ = popup_focus_override;
diff --git a/chromium/ui/accessibility/platform/ax_platform_node.h b/chromium/ui/accessibility/platform/ax_platform_node.h
index 82fe33607d3..87e5f6cbf18 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node.h
@@ -60,6 +60,15 @@ class AX_EXPORT AXPlatformNode {
// the addition of an AXMode flag.
static void NotifyAddAXModeFlags(AXMode mode_flags);
+ // Helper static function to update the AXMode. This is called when flags
+ // are removed. It doesn't currently notify global observers.
+ static void SetAXMode(AXMode new_mode);
+
+ // Since |ax_mode_| is a static, calling NotifyAddAXModeFlags in a test can
+ // cause downstream tests to be flaky. This helper function puts |ax_mode_|
+ // in the default state.
+ static void ResetAxModeForTesting();
+
// Return the focused object in any UI popup overlaying content, or null.
static gfx::NativeViewAccessible GetPopupFocusOverride();
@@ -134,6 +143,16 @@ class AX_EXPORT AXPlatformNode {
DISALLOW_COPY_AND_ASSIGN(AXPlatformNode);
};
+namespace testing {
+class ScopedAxModeSetter {
+ public:
+ explicit ScopedAxModeSetter(AXMode new_mode) {
+ AXPlatformNode::SetAXMode(new_mode);
+ }
+ ~ScopedAxModeSetter() { AXPlatformNode::ResetAxModeForTesting(); }
+};
+} // namespace testing
+
} // namespace ui
#endif // UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_H_
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc
index b68c9ca3b10..8017d30f3ea 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -20,7 +20,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/numerics/ranges.h"
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -28,6 +27,7 @@
#include "base/strings/utf_string_conversion_utils.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_enum_util.h"
#include "ui/accessibility/ax_enums.mojom.h"
@@ -915,7 +915,7 @@ AtkHyperlink* GetLink(AtkHypertext* hypertext, int index) {
if (!obj)
return nullptr;
- const AXHypertext& ax_hypertext = obj->GetAXHypertext();
+ const AXLegacyHypertext& ax_hypertext = obj->GetAXHypertext();
if (index > static_cast<int>(ax_hypertext.hyperlinks.size()) || index < 0)
return nullptr;
@@ -1203,7 +1203,7 @@ int GetNSelections(AtkText* atk_text) {
if (obj->HasSelection())
return 1;
- base::Optional<FindInPageResultInfo> result =
+ absl::optional<FindInPageResultInfo> result =
obj->GetSelectionOffsetsFromFindInPage();
if (result.has_value() && result->node == ATK_OBJECT(atk_text))
return 1;
@@ -1927,7 +1927,7 @@ GPtrArray* GetColumnHeaderCells(AtkTableCell* cell) {
if (obj->GetAtkRole() != ATK_ROLE_TABLE_CELL)
return array;
- base::Optional<int> col_index = obj->GetTableColumn();
+ absl::optional<int> col_index = obj->GetTableColumn();
if (!col_index)
return array;
@@ -1951,8 +1951,8 @@ gboolean GetCellPosition(AtkTableCell* cell, gint* row, gint* column) {
FALSE);
if (auto* obj = AXPlatformNodeAuraLinux::FromAtkObject(ATK_OBJECT(cell))) {
- base::Optional<int> row_index = obj->GetTableRow();
- base::Optional<int> col_index = obj->GetTableColumn();
+ absl::optional<int> row_index = obj->GetTableRow();
+ absl::optional<int> col_index = obj->GetTableColumn();
if (!row_index || !col_index)
return false;
@@ -1997,7 +1997,7 @@ GPtrArray* GetRowHeaderCells(AtkTableCell* cell) {
if (obj->GetAtkRole() != ATK_ROLE_TABLE_CELL)
return array;
- base::Optional<int> row_index = obj->GetTableRow();
+ absl::optional<int> row_index = obj->GetTableRow();
if (!row_index)
return array;
@@ -2373,7 +2373,7 @@ ImplementedAtkInterfaces AXPlatformNodeAuraLinux::GetGTypeInterfaceMask(
if (!IsImageOrVideo(data.role)) {
interface_mask.Add(ImplementedAtkInterfaces::Value::kText);
- if (!data.IsPlainTextField())
+ if (!data.IsAtomicTextField())
interface_mask.Add(ImplementedAtkInterfaces::Value::kHypertext);
}
@@ -2800,8 +2800,6 @@ AtkRole AXPlatformNodeAuraLinux::GetAtkRole() const {
case ax::mojom::Role::kIframe:
case ax::mojom::Role::kIframePresentational:
return ATK_ROLE_INTERNAL_FRAME;
- case ax::mojom::Role::kIgnored:
- return ATK_ROLE_REDUNDANT_OBJECT;
case ax::mojom::Role::kImage:
return IsImageWithMap() ? ATK_ROLE_IMAGE_MAP : ATK_ROLE_IMAGE;
case ax::mojom::Role::kInlineTextBox:
@@ -2923,15 +2921,8 @@ AtkRole AXPlatformNodeAuraLinux::GetAtkRole() const {
// Therefore, browser side needs to gracefully handle it if it actually
// shows up in the tree.
return kStaticRole;
- case ax::mojom::Role::kSection: {
- if (GetName().empty()) {
- // Do not use ARIA mapping for nameless <section>.
- return ATK_ROLE_SECTION;
- } else {
- // Use ARIA mapping.
- return ATK_ROLE_LANDMARK;
- }
- }
+ case ax::mojom::Role::kSection:
+ return ATK_ROLE_SECTION;
case ax::mojom::Role::kScrollBar:
return ATK_ROLE_SCROLL_BAR;
case ax::mojom::Role::kSearch:
@@ -3024,11 +3015,24 @@ AtkRole AXPlatformNodeAuraLinux::GetAtkRole() const {
case ax::mojom::Role::kImeCandidate:
case ax::mojom::Role::kKeyboard:
case ax::mojom::Role::kNone:
- case ax::mojom::Role::kPresentational:
return ATK_ROLE_REDUNDANT_OBJECT;
}
}
+// If we were compiled with a newer version of ATK than the runtime version,
+// it's possible that the state we want to expose and/or emit an event for
+// is not present. This will generate a runtime error.
+bool PlatformSupportsState(AtkStateType atk_state_type) {
+ static absl::optional<int> max_state_type = absl::nullopt;
+ if (!max_state_type.has_value()) {
+ GEnumClass* enum_class =
+ G_ENUM_CLASS(g_type_class_ref(atk_state_type_get_type()));
+ max_state_type = enum_class->maximum;
+ g_type_class_unref(enum_class);
+ }
+ return atk_state_type < max_state_type.value();
+}
+
void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) {
AXNodeData data = GetData();
@@ -3087,9 +3091,11 @@ void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) {
atk_state_set_add_state(atk_state_set, ATK_STATE_ACTIVE);
}
#if defined(ATK_216)
- if (IsPlatformCheckable())
+ // Runtime checks in case we were compiled with a newer version of ATK.
+ if (IsPlatformCheckable() && PlatformSupportsState(ATK_STATE_CHECKABLE))
atk_state_set_add_state(atk_state_set, ATK_STATE_CHECKABLE);
- if (data.HasIntAttribute(ax::mojom::IntAttribute::kHasPopup))
+ if (data.HasIntAttribute(ax::mojom::IntAttribute::kHasPopup) &&
+ PlatformSupportsState(ATK_STATE_HAS_POPUP))
atk_state_set_add_state(atk_state_set, ATK_STATE_HAS_POPUP);
#endif
if (data.GetBoolAttribute(ax::mojom::BoolAttribute::kBusy))
@@ -3101,7 +3107,7 @@ void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) {
if (data.GetBoolAttribute(ax::mojom::BoolAttribute::kSelected))
atk_state_set_add_state(atk_state_set, ATK_STATE_SELECTED);
- if (IsPlainTextField() || IsRichTextField()) {
+ if (IsTextField()) {
atk_state_set_add_state(atk_state_set, ATK_STATE_SELECTABLE_TEXT);
if (data.HasState(ax::mojom::State::kMultiline))
atk_state_set_add_state(atk_state_set, ATK_STATE_MULTI_LINE);
@@ -3123,7 +3129,9 @@ void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) {
if (data.GetRestriction() != ax::mojom::Restriction::kDisabled) {
if (IsReadOnlySupported(data.role) && data.IsReadOnlyOrDisabled()) {
#if defined(ATK_216)
- atk_state_set_add_state(atk_state_set, ATK_STATE_READ_ONLY);
+ // Runtime check in case we were compiled with a newer version of ATK.
+ if (PlatformSupportsState(ATK_STATE_READ_ONLY))
+ atk_state_set_add_state(atk_state_set, ATK_STATE_READ_ONLY);
#endif
} else {
atk_state_set_add_state(atk_state_set, ATK_STATE_ENABLED);
@@ -3150,14 +3158,14 @@ void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) {
struct AtkIntRelation {
ax::mojom::IntAttribute attribute;
AtkRelationType relation;
- base::Optional<AtkRelationType> reverse_relation;
+ absl::optional<AtkRelationType> reverse_relation;
};
static AtkIntRelation kIntRelations[] = {
{ax::mojom::IntAttribute::kMemberOfId, ATK_RELATION_MEMBER_OF,
- base::nullopt},
+ absl::nullopt},
{ax::mojom::IntAttribute::kPopupForId, ATK_RELATION_POPUP_FOR,
- base::nullopt},
+ absl::nullopt},
#if defined(ATK_226)
{ax::mojom::IntAttribute::kErrormessageId, ATK_RELATION_ERROR_MESSAGE,
ATK_RELATION_ERROR_FOR},
@@ -3167,7 +3175,7 @@ static AtkIntRelation kIntRelations[] = {
struct AtkIntListRelation {
ax::mojom::IntListAttribute attribute;
AtkRelationType relation;
- base::Optional<AtkRelationType> reverse_relation;
+ absl::optional<AtkRelationType> reverse_relation;
};
static AtkIntListRelation kIntListRelations[] = {
@@ -3198,7 +3206,7 @@ void AXPlatformNodeAuraLinux::AddRelationToSet(AtkRelationSet* relation_set,
// it's possible that we might try to add a relation that doesn't exist in
// the runtime version of the AtkRelationType enum. This will cause a runtime
// error, so return early here if we are about to do that.
- static base::Optional<int> max_relation_type = base::nullopt;
+ static absl::optional<int> max_relation_type = absl::nullopt;
if (!max_relation_type.has_value()) {
GEnumClass* enum_class =
G_ENUM_CLASS(g_type_class_ref(atk_relation_type_get_type()));
@@ -3312,7 +3320,7 @@ bool AXPlatformNodeAuraLinux::IsPlatformCheckable() const {
return AXPlatformNodeBase::IsPlatformCheckable();
}
-base::Optional<int> AXPlatformNodeAuraLinux::GetIndexInParent() {
+absl::optional<int> AXPlatformNodeAuraLinux::GetIndexInParent() {
AXPlatformNode* parent =
AXPlatformNode::FromNativeViewAccessible(GetParent());
// Even though the node doesn't have its parent, GetParent() could return the
@@ -3321,7 +3329,7 @@ base::Optional<int> AXPlatformNodeAuraLinux::GetIndexInParent() {
if (parent == AXPlatformNodeAuraLinux::application() &&
GetData().role == ax::mojom::Role::kUnknown &&
GetData().GetRestriction() == ax::mojom::Restriction::kDisabled) {
- return base::nullopt;
+ return absl::nullopt;
}
return AXPlatformNodeBase::GetIndexInParent();
@@ -3416,6 +3424,10 @@ void AXPlatformNodeAuraLinux::OnEnabledChanged() {
atk_object_notify_state_change(
obj, ATK_STATE_ENABLED,
GetData().GetRestriction() != ax::mojom::Restriction::kDisabled);
+
+ atk_object_notify_state_change(
+ obj, ATK_STATE_SENSITIVE,
+ GetData().GetRestriction() != ax::mojom::Restriction::kDisabled);
}
void AXPlatformNodeAuraLinux::OnExpandedStateChanged(bool is_expanded) {
@@ -3432,6 +3444,14 @@ void AXPlatformNodeAuraLinux::OnExpandedStateChanged(bool is_expanded) {
atk_object_notify_state_change(obj, ATK_STATE_EXPANDED, is_expanded);
}
+void AXPlatformNodeAuraLinux::OnShowingStateChanged(bool is_showing) {
+ AtkObject* obj = GetOrCreateAtkObject();
+ if (!obj)
+ return;
+
+ atk_object_notify_state_change(obj, ATK_STATE_SHOWING, is_showing);
+}
+
void AXPlatformNodeAuraLinux::OnMenuPopupStart() {
AtkObject* atk_object = GetOrCreateAtkObject();
AtkObject* parent_frame = FindAtkObjectParentFrame(atk_object);
@@ -3738,7 +3758,7 @@ void AXPlatformNodeAuraLinux::GetFullSelection(int32_t* anchor_node_id,
DCHECK(focus_node_id);
DCHECK(focus_offset);
- if (IsPlainTextField() &&
+ if (IsAtomicTextField() &&
GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart, anchor_offset) &&
GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, focus_offset)) {
int32_t node_id = GetData().id != -1 ? GetData().id : GetUniqueId();
@@ -3756,7 +3776,8 @@ void AXPlatformNodeAuraLinux::GetFullSelection(int32_t* anchor_node_id,
AXPlatformNodeAuraLinux& AXPlatformNodeAuraLinux::FindEditableRootOrDocument() {
if (GetAtkRole() == ATK_ROLE_DOCUMENT_WEB)
return *this;
- if (GetData().GetBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot))
+ if (GetData().GetBoolAttribute(
+ ax::mojom::BoolAttribute::kContentEditableRoot))
return *this;
if (auto* parent = FromAtkObject(GetParent()))
return parent->FindEditableRootOrDocument();
@@ -4008,6 +4029,22 @@ void AXPlatformNodeAuraLinux::OnParentChanged() {
g_value_unset(&property_values.new_value);
}
+void AXPlatformNodeAuraLinux::OnReadonlyChanged() {
+ AtkObject* obj = GetOrCreateAtkObject();
+ if (!obj)
+ return;
+
+#if defined(ATK_216)
+ // Runtime check in case we were compiled with a newer version of ATK.
+ if (!PlatformSupportsState(ATK_STATE_READ_ONLY))
+ return;
+
+ atk_object_notify_state_change(
+ obj, ATK_STATE_READ_ONLY,
+ GetData().GetRestriction() == ax::mojom::Restriction::kReadOnly);
+#endif
+}
+
void AXPlatformNodeAuraLinux::OnInvalidStatusChanged() {
AtkObject* atk_object = GetOrCreateAtkObject();
if (!atk_object)
@@ -4130,12 +4167,12 @@ void AXPlatformNodeAuraLinux::NotifyAccessibilityEvent(
}
}
-base::Optional<std::pair<int, int>>
+absl::optional<std::pair<int, int>>
AXPlatformNodeAuraLinux::GetEmbeddedObjectIndicesForId(int id) {
auto iterator =
std::find(hypertext_.hyperlinks.begin(), hypertext_.hyperlinks.end(), id);
if (iterator == hypertext_.hyperlinks.end())
- return base::nullopt;
+ return absl::nullopt;
int hyperlink_index = std::distance(hypertext_.hyperlinks.begin(), iterator);
auto offset = std::find_if(hypertext_.hyperlink_offset_to_index.begin(),
@@ -4144,17 +4181,17 @@ AXPlatformNodeAuraLinux::GetEmbeddedObjectIndicesForId(int id) {
return pair.second == hyperlink_index;
});
if (offset == hypertext_.hyperlink_offset_to_index.end())
- return base::nullopt;
+ return absl::nullopt;
return std::make_pair(UTF16ToUnicodeOffsetInText(offset->first),
UTF16ToUnicodeOffsetInText(offset->first + 1));
}
-base::Optional<std::pair<int, int>>
+absl::optional<std::pair<int, int>>
AXPlatformNodeAuraLinux::GetEmbeddedObjectIndices() {
auto* parent = FromAtkObject(GetParent());
if (!parent)
- return base::nullopt;
+ return absl::nullopt;
return parent->GetEmbeddedObjectIndicesForId(GetUniqueId());
}
@@ -4164,11 +4201,11 @@ void AXPlatformNodeAuraLinux::UpdateHypertext() {
if (!atk_object)
return;
- AXHypertext old_hypertext = hypertext_;
+ AXLegacyHypertext old_hypertext = hypertext_;
base::OffsetAdjuster::Adjustments old_adjustments = GetHypertextAdjustments();
UpdateComputedHypertext();
- text_unicode_adjustments_ = base::nullopt;
+ text_unicode_adjustments_ = absl::nullopt;
offset_to_text_attributes_.clear();
if ((!GetData().HasState(ax::mojom::State::kEditable) ||
@@ -4213,7 +4250,7 @@ void AXPlatformNodeAuraLinux::UpdateHypertext() {
}
}
-const AXHypertext& AXPlatformNodeAuraLinux::GetAXHypertext() {
+const AXLegacyHypertext& AXPlatformNodeAuraLinux::GetAXHypertext() {
return hypertext_;
}
@@ -4472,7 +4509,7 @@ bool AXPlatformNodeAuraLinux::
bool AXPlatformNodeAuraLinux::
GrabFocusOrSetSequentialFocusNavigationStartingPointAtOffset(int offset) {
int child_count = delegate_->GetChildCount();
- if (IsPlainTextField() || child_count == 0)
+ if (IsAtomicTextField() || child_count == 0)
return GrabFocusOrSetSequentialFocusNavigationStartingPoint();
// When this node has children, we walk through them to figure out what child
@@ -4619,7 +4656,7 @@ int AXPlatformNodeAuraLinux::GetCaretOffset() {
AXTree::Selection unignored_selection =
GetDelegate()->GetUnignoredSelection();
if (!HasCaret(&unignored_selection)) {
- base::Optional<FindInPageResultInfo> result =
+ absl::optional<FindInPageResultInfo> result =
GetSelectionOffsetsFromFindInPage();
AtkObject* atk_object = GetOrCreateAtkObject();
if (!atk_object)
@@ -4729,7 +4766,7 @@ gchar* AXPlatformNodeAuraLinux::GetSelectionWithText(int* start_offset,
if (selection_start < 0 || selection_end < 0 ||
selection_start == selection_end) {
- base::Optional<FindInPageResultInfo> find_in_page_result =
+ absl::optional<FindInPageResultInfo> find_in_page_result =
GetSelectionOffsetsFromFindInPage();
if (!find_in_page_result.has_value() ||
find_in_page_result->node != atk_object) {
@@ -4838,7 +4875,7 @@ void AXPlatformNodeAuraLinux::ScrollNodeIntoView(
#endif // defined(ATK_230)
#if defined(ATK_232)
-base::Optional<gfx::Rect>
+absl::optional<gfx::Rect>
AXPlatformNodeAuraLinux::GetUnclippedHypertextRangeBoundsRect(int start_offset,
int end_offset) {
start_offset = UnicodeToUTF16OffsetInText(start_offset);
@@ -4846,9 +4883,9 @@ AXPlatformNodeAuraLinux::GetUnclippedHypertextRangeBoundsRect(int start_offset,
std::u16string text = GetHypertext();
if (start_offset < 0 || start_offset > int{text.length()})
- return base::nullopt;
+ return absl::nullopt;
if (end_offset < 0 || end_offset > int{text.length()})
- return base::nullopt;
+ return absl::nullopt;
if (end_offset < start_offset)
std::swap(start_offset, end_offset);
@@ -4863,7 +4900,7 @@ bool AXPlatformNodeAuraLinux::ScrollSubstringIntoView(
AtkScrollType atk_scroll_type,
int start_offset,
int end_offset) {
- base::Optional<gfx::Rect> optional_rect =
+ absl::optional<gfx::Rect> optional_rect =
GetUnclippedHypertextRangeBoundsRect(start_offset, end_offset);
if (!optional_rect.has_value())
return false;
@@ -4883,7 +4920,7 @@ bool AXPlatformNodeAuraLinux::ScrollSubstringToPoint(
AtkCoordType atk_coord_type,
int x,
int y) {
- base::Optional<gfx::Rect> optional_rect =
+ absl::optional<gfx::Rect> optional_rect =
GetUnclippedHypertextRangeBoundsRect(start_offset, end_offset);
if (!optional_rect.has_value())
return false;
@@ -5004,7 +5041,7 @@ void AXPlatformNodeAuraLinux::ActivateFindInPageResult(int start_offset,
UTF16ToUnicodeOffsetInText(end_offset));
}
-base::Optional<std::pair<int, int>>
+absl::optional<std::pair<int, int>>
AXPlatformNodeAuraLinux::GetHypertextExtentsOfChild(
AXPlatformNodeAuraLinux* child_to_find) {
int current_offset = 0;
@@ -5024,7 +5061,7 @@ AXPlatformNodeAuraLinux::GetHypertextExtentsOfChild(
current_offset += size;
}
- return base::nullopt;
+ return absl::nullopt;
}
void AXPlatformNodeAuraLinux::ActivateFindInPageInParent(int start_offset,
@@ -5033,7 +5070,7 @@ void AXPlatformNodeAuraLinux::ActivateFindInPageInParent(int start_offset,
if (!parent)
return;
- base::Optional<std::pair<int, int>> extents_in_parent =
+ absl::optional<std::pair<int, int>> extents_in_parent =
parent->GetHypertextExtentsOfChild(this);
if (!extents_in_parent.has_value())
return;
@@ -5053,21 +5090,21 @@ void AXPlatformNodeAuraLinux::ForgetCurrentFindInPageResult() {
GetActiveFindInPageResults().erase(parent_doc);
}
-base::Optional<FindInPageResultInfo>
+absl::optional<FindInPageResultInfo>
AXPlatformNodeAuraLinux::GetSelectionOffsetsFromFindInPage() {
AtkObject* atk_object = GetOrCreateAtkObject();
if (!atk_object)
- return base::nullopt;
+ return absl::nullopt;
AtkObject* parent_doc = FindAtkObjectToplevelParentDocument(atk_object);
if (!parent_doc)
- return base::nullopt;
+ return absl::nullopt;
std::map<AtkObject*, FindInPageResultInfo>& active_results =
GetActiveFindInPageResults();
auto iterator = active_results.find(parent_doc);
if (iterator == active_results.end())
- return base::nullopt;
+ return absl::nullopt;
return iterator->second;
}
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h
index 431e1c77a6f..39d9786d0fa 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h
@@ -14,9 +14,9 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/strings/utf_offset_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_enums.mojom-forward.h"
#include "ui/accessibility/ax_export.h"
#include "ui/accessibility/ax_position.h"
@@ -182,7 +182,7 @@ class AX_EXPORT AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
#endif // defined(ATK_CHECK_VERSION) && ATK_CHECK_VERSION(2, 30, 0)
#if defined(ATK_CHECK_VERSION) && ATK_CHECK_VERSION(2, 32, 0)
- base::Optional<gfx::Rect> GetUnclippedHypertextRangeBoundsRect(
+ absl::optional<gfx::Rect> GetUnclippedHypertextRangeBoundsRect(
int start_offset,
int end_offset);
bool ScrollSubstringIntoView(AtkScrollType atk_scroll_type,
@@ -203,6 +203,7 @@ class AX_EXPORT AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
void OnCheckedStateChanged();
void OnEnabledChanged();
void OnExpandedStateChanged(bool is_expanded);
+ void OnShowingStateChanged(bool is_showing);
void OnFocused();
void OnWindowActivated();
void OnWindowDeactivated();
@@ -223,6 +224,7 @@ class AX_EXPORT AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
void OnSubtreeCreated();
void OnSubtreeWillBeDeleted();
void OnParentChanged();
+ void OnReadonlyChanged();
void OnWindowVisibilityChanged();
void OnScrolledToAnchor();
void OnAlertShown();
@@ -242,12 +244,12 @@ class AX_EXPORT AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
// AXPlatformNodeBase overrides.
void Init(AXPlatformNodeDelegate* delegate) override;
bool IsPlatformCheckable() const override;
- base::Optional<int> GetIndexInParent() override;
+ absl::optional<int> GetIndexInParent() override;
bool IsNameExposed();
void UpdateHypertext();
- const AXHypertext& GetAXHypertext();
+ const AXLegacyHypertext& GetAXHypertext();
const base::OffsetAdjuster::Adjustments& GetHypertextAdjustments();
size_t UTF16ToUnicodeOffsetInText(size_t utf16_offset);
size_t UnicodeToUTF16OffsetInText(int unicode_offset);
@@ -285,15 +287,15 @@ class AX_EXPORT AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
void TerminateFindInPage();
// If there is a find in page result for the toplevel document of this node,
- // return it, otherwise return base::nullopt;
- base::Optional<FindInPageResultInfo> GetSelectionOffsetsFromFindInPage();
+ // return it, otherwise return absl::nullopt;
+ absl::optional<FindInPageResultInfo> GetSelectionOffsetsFromFindInPage();
std::pair<int, int> GetSelectionOffsetsForAtk();
// Get the embedded object ("hyperlink") indices for this object in the
// parent. If this object doesn't have a parent or isn't embedded, return
// nullopt.
- base::Optional<std::pair<int, int>> GetEmbeddedObjectIndices();
+ absl::optional<std::pair<int, int>> GetEmbeddedObjectIndices();
std::string accessible_name_;
@@ -302,8 +304,8 @@ class AX_EXPORT AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
// but the ATK APIs want all offsets to be in "characters," which we
// understand to be Unicode character offsets. We keep a lazily generated set
// of Adjustments to convert between UTF-16 and Unicode character offsets.
- base::Optional<base::OffsetAdjuster::Adjustments> text_unicode_adjustments_ =
- base::nullopt;
+ absl::optional<base::OffsetAdjuster::Adjustments> text_unicode_adjustments_ =
+ absl::nullopt;
void AddAttributeToList(const char* name,
const char* value,
@@ -324,7 +326,7 @@ class AX_EXPORT AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
AtkRelationType,
AXPlatformNode* target);
bool IsInLiveRegion();
- base::Optional<std::pair<int, int>> GetEmbeddedObjectIndicesForId(int id);
+ absl::optional<std::pair<int, int>> GetEmbeddedObjectIndicesForId(int id);
void ComputeStylesIfNeeded();
int FindStartOfStyle(int start_offset, ax::mojom::MoveDirection direction);
@@ -381,8 +383,8 @@ class AX_EXPORT AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
std::pair<int32_t, int> GetCurrentCaret() const { return current_caret_; }
// If the given argument can be found as a child of this node, return its
- // hypertext extents, otherwise return base::nullopt;
- base::Optional<std::pair<int, int>> GetHypertextExtentsOfChild(
+ // hypertext extents, otherwise return absl::nullopt;
+ absl::optional<std::pair<int, int>> GetHypertextExtentsOfChild(
AXPlatformNodeAuraLinux* child);
// The AtkStateType for a checkable node can vary depending on the role.
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc b/chromium/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc
index 73080de191b..252eaa01421 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc
@@ -37,16 +37,12 @@ namespace ui {
class AXPlatformNodeAuraLinuxTest : public AXPlatformNodeTest {
public:
- AXPlatformNodeAuraLinuxTest() = default;
+ AXPlatformNodeAuraLinuxTest() : ax_mode_setter_(kAXModeComplete) {}
~AXPlatformNodeAuraLinuxTest() override = default;
AXPlatformNodeAuraLinuxTest(const AXPlatformNodeAuraLinuxTest&) = delete;
AXPlatformNodeAuraLinuxTest& operator=(const AXPlatformNodeAuraLinuxTest&) =
delete;
- void SetUp() override {
- AXPlatformNode::NotifyAddAXModeFlags(kAXModeComplete);
- }
-
protected:
AXPlatformNodeAuraLinux* GetPlatformNode(AXNode* node) {
TestAXNodeWrapper* wrapper =
@@ -73,6 +69,23 @@ class AXPlatformNodeAuraLinuxTest : public AXPlatformNodeTest {
}
AtkObject* GetRootAtkObject() { return AtkObjectFromNode(GetRootAsAXNode()); }
+
+ // If we were compiled with a newer version of ATK than the runtime version,
+ // it's possible that the state we want to expose and/or emit an event for
+ // is not present. This will generate a runtime error.
+ bool PlatformSupportsState(AtkStateType atk_state_type) {
+ static absl::optional<int> max_state_type = absl::nullopt;
+ if (!max_state_type.has_value()) {
+ GEnumClass* enum_class =
+ G_ENUM_CLASS(g_type_class_ref(atk_state_type_get_type()));
+ max_state_type = enum_class->maximum;
+ g_type_class_unref(enum_class);
+ }
+ return atk_state_type < max_state_type.value();
+ }
+
+ private:
+ ui::testing::ScopedAxModeSetter ax_mode_setter_;
};
static void EnsureAtkObjectHasAttributeWithValue(
@@ -118,7 +131,7 @@ static void SetStringAttributeOnNode(
AXNode* ax_node,
ax::mojom::StringAttribute attribute,
const char* attribute_value,
- base::Optional<ax::mojom::Role> role = base::nullopt) {
+ absl::optional<ax::mojom::Role> role = absl::nullopt) {
AXNodeData new_data = AXNodeData();
new_data.role = role.value_or(ax::mojom::Role::kApplication);
new_data.id = ax_node->data().id;
@@ -131,9 +144,10 @@ static void TestAtkObjectIntAttribute(
AtkObject* atk_object,
ax::mojom::IntAttribute mojom_attribute,
const gchar* attribute_name,
- base::Optional<ax::mojom::Role> role = base::nullopt) {
+ absl::optional<ax::mojom::Role> role = absl::nullopt) {
AXNodeData new_data = AXNodeData();
new_data.role = role.value_or(ax::mojom::Role::kApplication);
+ new_data.id = ax_node->data().id;
ax_node->SetData(new_data);
EnsureAtkObjectDoesNotHaveAttribute(atk_object, attribute_name);
@@ -143,14 +157,14 @@ static void TestAtkObjectIntAttribute(
std::make_pair(1000, "1000"),
};
- for (unsigned i = 0; i < G_N_ELEMENTS(tests); i++) {
+ for (const auto& test : tests) {
AXNodeData new_data = AXNodeData();
new_data.role = role.value_or(ax::mojom::Role::kApplication);
new_data.id = ax_node->data().id;
- new_data.AddIntAttribute(mojom_attribute, tests[i].first);
+ new_data.AddIntAttribute(mojom_attribute, test.first);
ax_node->SetData(new_data);
EnsureAtkObjectHasAttributeWithValue(atk_object, attribute_name,
- tests[i].second);
+ test.second);
}
}
@@ -159,9 +173,10 @@ static void TestAtkObjectStringAttribute(
AtkObject* atk_object,
ax::mojom::StringAttribute mojom_attribute,
const gchar* attribute_name,
- base::Optional<ax::mojom::Role> role = base::nullopt) {
+ absl::optional<ax::mojom::Role> role = absl::nullopt) {
AXNodeData new_data = AXNodeData();
new_data.role = role.value_or(ax::mojom::Role::kApplication);
+ new_data.id = ax_node->data().id;
ax_node->SetData(new_data);
EnsureAtkObjectDoesNotHaveAttribute(atk_object, attribute_name);
@@ -170,9 +185,9 @@ static void TestAtkObjectStringAttribute(
"\xE2\x98\xBA", // The smiley emoji.
};
- for (unsigned i = 0; i < G_N_ELEMENTS(tests); i++) {
- SetStringAttributeOnNode(ax_node, mojom_attribute, tests[i], role);
- EnsureAtkObjectHasAttributeWithValue(atk_object, attribute_name, tests[i]);
+ for (const char* test : tests) {
+ SetStringAttributeOnNode(ax_node, mojom_attribute, test, role);
+ EnsureAtkObjectHasAttributeWithValue(atk_object, attribute_name, test);
}
}
@@ -181,9 +196,10 @@ static void TestAtkObjectBoolAttribute(
AtkObject* atk_object,
ax::mojom::BoolAttribute mojom_attribute,
const gchar* attribute_name,
- base::Optional<ax::mojom::Role> role = base::nullopt) {
+ absl::optional<ax::mojom::Role> role = absl::nullopt) {
AXNodeData new_data = AXNodeData();
new_data.role = role.value_or(ax::mojom::Role::kApplication);
+ new_data.id = ax_node->data().id;
ax_node->SetData(new_data);
EnsureAtkObjectDoesNotHaveAttribute(atk_object, attribute_name);
@@ -366,7 +382,9 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkObjectState) {
ASSERT_TRUE(atk_state_set_contains_state(state_set, ATK_STATE_VISIBLE));
ASSERT_FALSE(atk_state_set_contains_state(state_set, ATK_STATE_BUSY));
#if defined(ATK_216)
- ASSERT_FALSE(atk_state_set_contains_state(state_set, ATK_STATE_CHECKABLE));
+ // Runtime check in case we were compiled with a newer version of ATK.
+ if (PlatformSupportsState(ATK_STATE_CHECKABLE))
+ ASSERT_FALSE(atk_state_set_contains_state(state_set, ATK_STATE_CHECKABLE));
#endif
ASSERT_FALSE(atk_state_set_contains_state(state_set, ATK_STATE_CHECKED));
ASSERT_FALSE(atk_state_set_contains_state(state_set, ATK_STATE_DEFAULT));
@@ -376,7 +394,9 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkObjectState) {
ASSERT_FALSE(atk_state_set_contains_state(state_set, ATK_STATE_FOCUSABLE));
ASSERT_FALSE(atk_state_set_contains_state(state_set, ATK_STATE_FOCUSED));
#if defined(ATK_216)
- ASSERT_FALSE(atk_state_set_contains_state(state_set, ATK_STATE_HAS_POPUP));
+ // Runtime check in case we were compiled with a newer version of ATK.
+ if (PlatformSupportsState(ATK_STATE_HAS_POPUP))
+ ASSERT_FALSE(atk_state_set_contains_state(state_set, ATK_STATE_HAS_POPUP));
#endif
ASSERT_FALSE(atk_state_set_contains_state(state_set, ATK_STATE_HORIZONTAL));
ASSERT_FALSE(
@@ -398,6 +418,7 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkObjectState) {
g_object_unref(state_set);
root = AXNodeData();
+ root.id = 1;
root.AddState(ax::mojom::State::kDefault);
root.AddState(ax::mojom::State::kEditable);
root.AddState(ax::mojom::State::kExpanded);
@@ -441,7 +462,9 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkObjectState) {
ASSERT_TRUE(ATK_IS_STATE_SET(state_set));
ASSERT_TRUE(atk_state_set_contains_state(state_set, ATK_STATE_EXPANDABLE));
#if defined(ATK_216)
- ASSERT_TRUE(atk_state_set_contains_state(state_set, ATK_STATE_HAS_POPUP));
+ // Runtime check in case we were compiled with a newer version of ATK.
+ if (PlatformSupportsState(ATK_STATE_HAS_POPUP))
+ ASSERT_TRUE(atk_state_set_contains_state(state_set, ATK_STATE_HAS_POPUP));
#endif
ASSERT_TRUE(atk_state_set_contains_state(state_set, ATK_STATE_HORIZONTAL));
ASSERT_TRUE(atk_state_set_contains_state(state_set, ATK_STATE_SELECTABLE));
@@ -452,6 +475,7 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkObjectState) {
g_object_unref(state_set);
root = AXNodeData();
+ root.id = 1;
root.AddState(ax::mojom::State::kInvisible);
root.AddBoolAttribute(ax::mojom::BoolAttribute::kModal, true);
GetRootAsAXNode()->SetData(root);
@@ -590,9 +614,9 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkObjectStringAttributes) {
"container-relevant"),
};
- for (unsigned i = 0; i < G_N_ELEMENTS(tests); i++) {
- TestAtkObjectStringAttribute(root_node, root_atk_object, tests[i].first,
- tests[i].second);
+ for (const auto& test : tests) {
+ TestAtkObjectStringAttribute(root_node, root_atk_object, test.first,
+ test.second);
}
g_object_unref(root_atk_object);
@@ -618,9 +642,9 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkObjectBoolAttributes) {
"container-busy"),
};
- for (unsigned i = 0; i < G_N_ELEMENTS(tests); i++) {
- TestAtkObjectBoolAttribute(root_node, root_atk_object, tests[i].first,
- tests[i].second);
+ for (const auto& test : tests) {
+ TestAtkObjectBoolAttribute(root_node, root_atk_object, test.first,
+ test.second);
}
g_object_unref(root_atk_object);
@@ -1190,7 +1214,7 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkTextCharacterGranularity) {
auto verify_text_at_offset = [&](const char* expected_text, int offset,
int expected_start, int expected_end) {
- testing::Message message;
+ ::testing::Message message;
message << "While checking at offset " << offset;
SCOPED_TRACE(message);
@@ -1208,7 +1232,7 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkTextCharacterGranularity) {
auto verify_text_after_offset = [&](const char* expected_text, int offset,
int expected_start, int expected_end) {
- testing::Message message;
+ ::testing::Message message;
message << "While checking after offset " << offset;
SCOPED_TRACE(message);
@@ -1228,7 +1252,7 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkTextCharacterGranularity) {
auto verify_text_before_offset = [&](const char* expected_text, int offset,
int expected_start, int expected_end) {
- testing::Message message;
+ ::testing::Message message;
message << "While checking before offset " << offset;
SCOPED_TRACE(message);
@@ -1274,38 +1298,40 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkTextWordGranularity) {
{-1, nullptr, -1, -1},
{1000, nullptr, -1, -1}};
- for (unsigned i = 0; i < G_N_ELEMENTS(tests); i++) {
- testing::Message message;
- message << "While checking at index " << tests[i].offset << " for \'"
- << tests[i].content << "\' at " << tests[i].start_offset << '-'
- << tests[i].end_offset << '.';
+ for (const auto& test : tests) {
+ ::testing::Message message;
+ message << "While checking at index " << test.offset << " for \'"
+ << test.content << "\' at " << test.start_offset << '-'
+ << test.end_offset << '.';
SCOPED_TRACE(message);
int start_offset = -1, end_offset = -1;
- char* content = atk_text_get_text_at_offset(atk_text, tests[i].offset,
+ char* content = atk_text_get_text_at_offset(atk_text, test.offset,
ATK_TEXT_BOUNDARY_WORD_START,
&start_offset, &end_offset);
- EXPECT_STREQ(content, tests[i].content);
- EXPECT_EQ(start_offset, tests[i].start_offset);
- EXPECT_EQ(end_offset, tests[i].end_offset);
+ EXPECT_STREQ(content, test.content);
+ EXPECT_EQ(start_offset, test.start_offset);
+ EXPECT_EQ(end_offset, test.end_offset);
g_free(content);
}
#if ATK_CHECK_VERSION(2, 10, 0)
- for (unsigned i = 0; i < G_N_ELEMENTS(tests); i++) {
- testing::Message message;
- message << "While checking at index " << tests[i].offset << " for \'"
- << tests[i].content << "\' at " << tests[i].start_offset << '-'
- << tests[i].end_offset << '.';
+ for (const auto& test : tests) {
+ ::testing::Message message;
+ message << "While checking at index " << test.offset << " for \'"
+ << test.content << "\' at " << test.start_offset << '-'
+ << test.end_offset << '.';
SCOPED_TRACE(message);
int start_offset = -1, end_offset = -1;
- char* content = atk_text_get_string_at_offset(atk_text, tests[i].offset,
+ char* content = atk_text_get_string_at_offset(atk_text, test.offset,
ATK_TEXT_GRANULARITY_WORD,
&start_offset, &end_offset);
- ASSERT_STREQ(content, tests[i].content) << "with test index=" << i;
- ASSERT_EQ(start_offset, tests[i].start_offset) << "with test index=" << i;
- ASSERT_EQ(end_offset, tests[i].end_offset) << "with test index=" << i;
+ ASSERT_STREQ(content, test.content) << "with test offset=" << test.offset;
+ ASSERT_EQ(start_offset, test.start_offset)
+ << "with test offset=" << test.offset;
+ ASSERT_EQ(end_offset, test.end_offset)
+ << "with test offset=" << test.offset;
g_free(content);
}
#endif
@@ -1338,38 +1364,37 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkTextSentenceGranularity) {
{1000, nullptr, -1, -1},
};
- for (unsigned i = 0; i < G_N_ELEMENTS(tests); i++) {
- testing::Message message;
- message << "While checking at index " << tests[i].offset << " for \'"
- << tests[i].content << "\' at " << tests[i].start_offset << '-'
- << tests[i].end_offset << '.';
+ for (const auto& test : tests) {
+ ::testing::Message message;
+ message << "While checking at index " << test.offset << " for \'"
+ << test.content << "\' at " << test.start_offset << '-'
+ << test.end_offset << '.';
SCOPED_TRACE(message);
int start_offset = -1, end_offset = -1;
char* content = atk_text_get_text_at_offset(
- atk_text, tests[i].offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
- &start_offset, &end_offset);
- ASSERT_STREQ(content, tests[i].content);
- ASSERT_EQ(start_offset, tests[i].start_offset);
- ASSERT_EQ(end_offset, tests[i].end_offset);
+ atk_text, test.offset, ATK_TEXT_BOUNDARY_SENTENCE_START, &start_offset,
+ &end_offset);
+ ASSERT_STREQ(content, test.content);
+ ASSERT_EQ(start_offset, test.start_offset);
+ ASSERT_EQ(end_offset, test.end_offset);
g_free(content);
}
#if ATK_CHECK_VERSION(2, 10, 0)
- for (unsigned i = 0; i < G_N_ELEMENTS(tests); i++) {
- testing::Message message;
- message << "While checking at index " << tests[i].offset << " for \'"
- << tests[i].content << "\' at " << tests[i].start_offset << '-'
- << tests[i].end_offset << '.';
- SCOPED_TRACE(message);
+ for (const auto& test : tests) {
+ ::testing::Message message;
+ message << "While checking at index " << test.offset << " for \'"
+ << test.content << "\' at " << test.start_offset << '-'
+ << test.end_offset << '.';
int start_offset = -1, end_offset = -1;
- char* content = atk_text_get_string_at_offset(atk_text, tests[i].offset,
+ char* content = atk_text_get_string_at_offset(atk_text, test.offset,
ATK_TEXT_GRANULARITY_SENTENCE,
&start_offset, &end_offset);
- ASSERT_STREQ(content, tests[i].content);
- ASSERT_EQ(start_offset, tests[i].start_offset);
- ASSERT_EQ(end_offset, tests[i].end_offset);
+ ASSERT_STREQ(content, test.content);
+ ASSERT_EQ(start_offset, test.start_offset);
+ ASSERT_EQ(end_offset, test.end_offset);
g_free(content);
}
#endif
@@ -1401,14 +1426,16 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkTextParagraphGranularity) {
{12345, nullptr, -1, -1},
};
- for (unsigned i = 0; i < G_N_ELEMENTS(tests); i++) {
+ for (const auto& test : tests) {
int start_offset = -1, end_offset = -1;
char* content = atk_text_get_string_at_offset(
- atk_text, tests[i].offset, ATK_TEXT_GRANULARITY_PARAGRAPH,
- &start_offset, &end_offset);
- ASSERT_STREQ(content, tests[i].content) << "with test index=" << i;
- ASSERT_EQ(start_offset, tests[i].start_offset) << "with test index=" << i;
- ASSERT_EQ(end_offset, tests[i].end_offset) << "with test index=" << i;
+ atk_text, test.offset, ATK_TEXT_GRANULARITY_PARAGRAPH, &start_offset,
+ &end_offset);
+ ASSERT_STREQ(content, test.content) << "with test offset=" << test.offset;
+ ASSERT_EQ(start_offset, test.start_offset)
+ << "with test offset=" << test.offset;
+ ASSERT_EQ(end_offset, test.end_offset)
+ << "with test offset=" << test.offset;
g_free(content);
}
#endif
@@ -1440,7 +1467,7 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkTextWithNonBMPCharacters) {
ASSERT_EQ(atk_text_get_character_count(atk_text), root_text_length);
for (int i = 0; i < root_text_length; i++) {
- testing::Message message;
+ ::testing::Message message;
message << "Checking character at offset " << i;
SCOPED_TRACE(message);
@@ -1475,20 +1502,20 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkTextWithNonBMPCharacters) {
static GetTextSegmentTest tests[] = {{0, "\xF0\x9F\x83\x8f ", 0, 2},
{6, "decently ", 4, 13}};
- for (unsigned i = 0; i < G_N_ELEMENTS(tests); i++) {
+ for (const auto& test : tests) {
int start_offset = -1, end_offset = -1;
- char* word = atk_text_get_text_at_offset(atk_text, tests[i].offset,
+ char* word = atk_text_get_text_at_offset(atk_text, test.offset,
ATK_TEXT_BOUNDARY_WORD_START,
&start_offset, &end_offset);
- testing::Message message;
- message << "Checking test with index=" << i << " and expected text=\'"
- << tests[i].content << "\' at " << tests[1].start_offset << '-'
- << tests[1].end_offset << '.';
+ ::testing::Message message;
+ message << "Checking test with index=" << test.offset
+ << " and expected text=\'" << test.content << "\' at "
+ << tests[1].start_offset << '-' << tests[1].end_offset << '.';
SCOPED_TRACE(message);
- ASSERT_STREQ(word, tests[i].content);
- ASSERT_EQ(start_offset, tests[i].start_offset);
- ASSERT_EQ(end_offset, tests[i].end_offset);
+ ASSERT_STREQ(word, test.content);
+ ASSERT_EQ(start_offset, test.start_offset);
+ ASSERT_EQ(end_offset, test.end_offset);
g_free(word);
}
@@ -2539,6 +2566,53 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkObjectExpandRebuildsPlatformNode) {
g_object_unref(original_atk_object);
}
+#if defined(ATK_216)
+TEST_F(AXPlatformNodeAuraLinuxTest, TestReadonlyChanged) {
+ // Runtime check in case we were compiled with a newer version of ATK.
+ if (!PlatformSupportsState(ATK_STATE_READ_ONLY))
+ return;
+
+ AXNodeData root_data;
+ root_data.id = 1;
+ root_data.role = ax::mojom::Role::kTextField;
+ Init(root_data);
+
+ AXNode* root = GetRootAsAXNode();
+ AtkObject* atk_object = AtkObjectFromNode(root);
+ AXPlatformNodeAuraLinux* node = GetPlatformNode(root);
+
+ bool is_read_only = false;
+ g_signal_connect(atk_object, "state-change",
+ G_CALLBACK(+[](AtkObject* atkobject, gchar* state_changed,
+ gboolean new_value, bool* flag) {
+ if (!g_strcmp0(state_changed, "read-only"))
+ *flag = new_value;
+ }),
+ &is_read_only);
+
+ root_data.AddIntAttribute(
+ ax::mojom::IntAttribute::kRestriction,
+ static_cast<int32_t>(ax::mojom::Restriction::kReadOnly));
+ root->SetData(root_data);
+ node->OnReadonlyChanged();
+ ASSERT_TRUE(is_read_only);
+
+ root_data.AddIntAttribute(
+ ax::mojom::IntAttribute::kRestriction,
+ static_cast<int32_t>(ax::mojom::Restriction::kNone));
+ root->SetData(root_data);
+ node->OnReadonlyChanged();
+ ASSERT_FALSE(is_read_only);
+
+ root_data.AddIntAttribute(
+ ax::mojom::IntAttribute::kRestriction,
+ static_cast<int32_t>(ax::mojom::Restriction::kReadOnly));
+ root->SetData(root_data);
+ node->OnReadonlyChanged();
+ ASSERT_TRUE(is_read_only);
+}
+#endif
+
TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkObjectParentChanged) {
AXNodeData root_data;
root_data.id = 1;
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_base.cc b/chromium/ui/accessibility/platform/ax_platform_node_base.cc
index d6000f02540..42064ce0f70 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_base.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_base.cc
@@ -37,7 +37,7 @@ base::LazyInstance<std::map<ax::mojom::Event, base::RepeatingClosure>>::
DestructorAtExit g_on_notify_event_for_testing;
// Check for descendant comment, using limited depth first search.
-bool FindDescendantRoleWithMaxDepth(AXPlatformNodeBase* node,
+bool FindDescendantRoleWithMaxDepth(const AXPlatformNodeBase* node,
ax::mojom::Role descendant_role,
int max_depth,
int max_children_to_check) {
@@ -149,24 +149,24 @@ std::string AXPlatformNodeBase::GetName() const {
return std::string();
}
-base::Optional<int> AXPlatformNodeBase::GetIndexInParent() {
+absl::optional<int> AXPlatformNodeBase::GetIndexInParent() {
AXPlatformNodeBase* parent = FromNativeViewAccessible(GetParent());
if (!parent)
- return base::nullopt;
+ return absl::nullopt;
// If this is the webview, it is not in the child in the list of its parent's
// child.
// TODO(jkim): Check if we could remove this after making WebView ignored.
if (delegate_ &&
delegate_->GetNativeViewAccessible() != GetNativeViewAccessible()) {
- return base::nullopt;
+ return absl::nullopt;
}
int child_count = parent->GetChildCount();
if (child_count == 0) {
// |child_count| could be 0 if the parent is IsLeaf.
DCHECK(parent->IsLeaf());
- return base::nullopt;
+ return absl::nullopt;
}
// Ask the delegate for the index in parent, and return it if it's plausible.
@@ -188,11 +188,11 @@ base::Optional<int> AXPlatformNodeBase::GetIndexInParent() {
// If the parent has a modal dialog, it doesn't count other children.
if (parent->delegate_ && parent->delegate_->HasModalDialog())
- return base::nullopt;
+ return absl::nullopt;
NOTREACHED()
<< "Unable to find the child in the list of its parent's children.";
- return base::nullopt;
+ return absl::nullopt;
}
base::stack<gfx::NativeViewAccessible> AXPlatformNodeBase::GetAncestors() {
@@ -206,7 +206,7 @@ base::stack<gfx::NativeViewAccessible> AXPlatformNodeBase::GetAncestors() {
return ancestors;
}
-base::Optional<int> AXPlatformNodeBase::CompareTo(AXPlatformNodeBase& other) {
+absl::optional<int> AXPlatformNodeBase::CompareTo(AXPlatformNodeBase& other) {
// We define two node's relative positions in the following way:
// 1. this->CompareTo(other) == 0:
// - |this| and |other| are the same node.
@@ -228,7 +228,7 @@ base::Optional<int> AXPlatformNodeBase::CompareTo(AXPlatformNodeBase& other) {
// be before (logically less) the node we visit later.
if (this == &other)
- return base::Optional<int>(0);
+ return absl::optional<int>(0);
// Compute the ancestor stacks of both positions and traverse them from the
// top most ancestor down, so we can discover the first uncommon ancestors.
@@ -250,26 +250,26 @@ base::Optional<int> AXPlatformNodeBase::CompareTo(AXPlatformNodeBase& other) {
// Nodes do not have a common ancestor, they are not comparable.
if (!common_ancestor)
- return base::nullopt;
+ return absl::nullopt;
// Compute the logical order when the common ancestor is |this| or |other|.
auto* common_ancestor_platform_node =
FromNativeViewAccessible(common_ancestor);
if (common_ancestor_platform_node == this)
- return base::Optional<int>(-1);
+ return absl::optional<int>(-1);
if (common_ancestor_platform_node == &other)
- return base::Optional<int>(1);
+ return absl::optional<int>(1);
// Compute the logical order of |this| and |other| by using their first
// uncommon ancestors.
if (!our_ancestors.empty() && !other_ancestors.empty()) {
- base::Optional<int> this_index_in_parent =
+ absl::optional<int> this_index_in_parent =
FromNativeViewAccessible(our_ancestors.top())->GetIndexInParent();
- base::Optional<int> other_index_in_parent =
+ absl::optional<int> other_index_in_parent =
FromNativeViewAccessible(other_ancestors.top())->GetIndexInParent();
if (!this_index_in_parent || !other_index_in_parent)
- return base::nullopt;
+ return absl::nullopt;
int this_uncommon_ancestor_index = this_index_in_parent.value();
int other_uncommon_ancestor_index = other_index_in_parent.value();
@@ -277,11 +277,11 @@ base::Optional<int> AXPlatformNodeBase::CompareTo(AXPlatformNodeBase& other) {
<< "Deepest uncommon ancestors should truly be uncommon, i.e. not "
"the same.";
- return base::Optional<int>(this_uncommon_ancestor_index -
+ return absl::optional<int>(this_uncommon_ancestor_index -
other_uncommon_ancestor_index);
}
- return base::nullopt;
+ return absl::nullopt;
}
// AXPlatformNode overrides.
@@ -596,6 +596,19 @@ bool AXPlatformNodeBase::IsPlatformDocument() const {
return ui::IsPlatformDocument(GetData().role);
}
+bool AXPlatformNodeBase::IsStructuredAnnotation() const {
+ // The node represents a structured annotation if it can trace back to a
+ // target node that is being annotated.
+ std::set<AXPlatformNode*> reverse_relations =
+ GetDelegate()->GetReverseRelations(
+ ax::mojom::IntListAttribute::kDetailsIds);
+
+ if (reverse_relations.empty())
+ return false;
+
+ return true;
+}
+
bool AXPlatformNodeBase::IsSelectionItemSupported() const {
switch (GetData().role) {
// An ARIA 1.1+ role of "cell", or a role of "row" inside
@@ -644,12 +657,12 @@ bool AXPlatformNodeBase::IsTextField() const {
return GetData().IsTextField();
}
-bool AXPlatformNodeBase::IsPlainTextField() const {
- return GetData().IsPlainTextField();
+bool AXPlatformNodeBase::IsAtomicTextField() const {
+ return GetData().IsAtomicTextField();
}
-bool AXPlatformNodeBase::IsRichTextField() const {
- return GetData().IsRichTextField();
+bool AXPlatformNodeBase::IsNonAtomicTextField() const {
+ return GetData().IsNonAtomicTextField();
}
bool AXPlatformNodeBase::IsText() const {
@@ -758,7 +771,7 @@ AXPlatformNodeBase* AXPlatformNodeBase::GetTableCell(int index) const {
return nullptr;
DCHECK(table->delegate_);
- base::Optional<int32_t> cell_id = table->delegate_->CellIndexToId(index);
+ absl::optional<int32_t> cell_id = table->delegate_->CellIndexToId(index);
if (!cell_id)
return nullptr;
@@ -781,7 +794,7 @@ AXPlatformNodeBase* AXPlatformNodeBase::GetTableCell(int row,
}
DCHECK(table->delegate_);
- base::Optional<int32_t> cell_id = table->delegate_->GetCellId(row, column);
+ absl::optional<int32_t> cell_id = table->delegate_->GetCellId(row, column);
if (!cell_id)
return nullptr;
@@ -789,89 +802,89 @@ AXPlatformNodeBase* AXPlatformNodeBase::GetTableCell(int row,
table->delegate_->GetFromNodeID(*cell_id));
}
-base::Optional<int> AXPlatformNodeBase::GetTableCellIndex() const {
+absl::optional<int> AXPlatformNodeBase::GetTableCellIndex() const {
if (!delegate_)
- return base::nullopt;
+ return absl::nullopt;
return delegate_->GetTableCellIndex();
}
-base::Optional<int> AXPlatformNodeBase::GetTableColumn() const {
+absl::optional<int> AXPlatformNodeBase::GetTableColumn() const {
if (!delegate_)
- return base::nullopt;
+ return absl::nullopt;
return delegate_->GetTableCellColIndex();
}
-base::Optional<int> AXPlatformNodeBase::GetTableColumnCount() const {
+absl::optional<int> AXPlatformNodeBase::GetTableColumnCount() const {
if (!delegate_)
- return base::nullopt;
+ return absl::nullopt;
AXPlatformNodeBase* table = GetTable();
if (!table)
- return base::nullopt;
+ return absl::nullopt;
DCHECK(table->delegate_);
return table->delegate_->GetTableColCount();
}
-base::Optional<int> AXPlatformNodeBase::GetTableAriaColumnCount() const {
+absl::optional<int> AXPlatformNodeBase::GetTableAriaColumnCount() const {
if (!delegate_)
- return base::nullopt;
+ return absl::nullopt;
AXPlatformNodeBase* table = GetTable();
if (!table)
- return base::nullopt;
+ return absl::nullopt;
DCHECK(table->delegate_);
return table->delegate_->GetTableAriaColCount();
}
-base::Optional<int> AXPlatformNodeBase::GetTableColumnSpan() const {
+absl::optional<int> AXPlatformNodeBase::GetTableColumnSpan() const {
if (!delegate_)
- return base::nullopt;
+ return absl::nullopt;
return delegate_->GetTableCellColSpan();
}
-base::Optional<int> AXPlatformNodeBase::GetTableRow() const {
+absl::optional<int> AXPlatformNodeBase::GetTableRow() const {
if (!delegate_)
- return base::nullopt;
+ return absl::nullopt;
if (delegate_->IsTableRow())
return delegate_->GetTableRowRowIndex();
if (delegate_->IsTableCellOrHeader())
return delegate_->GetTableCellRowIndex();
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<int> AXPlatformNodeBase::GetTableRowCount() const {
+absl::optional<int> AXPlatformNodeBase::GetTableRowCount() const {
if (!delegate_)
- return base::nullopt;
+ return absl::nullopt;
AXPlatformNodeBase* table = GetTable();
if (!table)
- return base::nullopt;
+ return absl::nullopt;
DCHECK(table->delegate_);
return table->delegate_->GetTableRowCount();
}
-base::Optional<int> AXPlatformNodeBase::GetTableAriaRowCount() const {
+absl::optional<int> AXPlatformNodeBase::GetTableAriaRowCount() const {
if (!delegate_)
- return base::nullopt;
+ return absl::nullopt;
AXPlatformNodeBase* table = GetTable();
if (!table)
- return base::nullopt;
+ return absl::nullopt;
DCHECK(table->delegate_);
return table->delegate_->GetTableAriaRowCount();
}
-base::Optional<int> AXPlatformNodeBase::GetTableRowSpan() const {
+absl::optional<int> AXPlatformNodeBase::GetTableRowSpan() const {
if (!delegate_)
- return base::nullopt;
+ return absl::nullopt;
return delegate_->GetTableCellRowSpan();
}
-base::Optional<float> AXPlatformNodeBase::GetFontSizeInPoints() const {
+absl::optional<float> AXPlatformNodeBase::GetFontSizeInPoints() const {
float font_size;
// Attribute has no default value.
if (GetFloatAttribute(ax::mojom::FloatAttribute::kFontSize, &font_size)) {
@@ -885,11 +898,11 @@ base::Optional<float> AXPlatformNodeBase::GetFontSizeInPoints() const {
points = std::round(points * 2.0) / 2.0;
return points;
}
- return base::nullopt;
+ return absl::nullopt;
}
bool AXPlatformNodeBase::HasCaret(const AXTree::Selection* selection) {
- if (IsPlainTextField() &&
+ if (IsAtomicTextField() &&
HasIntAttribute(ax::mojom::IntAttribute::kTextSelStart) &&
HasIntAttribute(ax::mojom::IntAttribute::kTextSelEnd)) {
return true;
@@ -999,6 +1012,46 @@ void AXPlatformNodeBase::ComputeAttributes(PlatformAttributeList* attributes) {
attributes);
}
+ // Expose description-from and description.
+ int desc_from;
+ if (GetIntAttribute(ax::mojom::IntAttribute::kDescriptionFrom, &desc_from)) {
+ std::string from;
+ switch (static_cast<ax::mojom::DescriptionFrom>(desc_from)) {
+ case ax::mojom::DescriptionFrom::kAriaDescription:
+ // Descriptions are exposed via each platform's usual description field.
+ // Also, only aria-description is exposed via tha "description" object
+ // attribute, in order to match Firefox.
+ AddAttributeToList(ax::mojom::StringAttribute::kDescription,
+ "description", attributes);
+ from = "aria-description";
+ break;
+ case ax::mojom::DescriptionFrom::kButtonLabel:
+ from = "button-label";
+ break;
+ case ax::mojom::DescriptionFrom::kRelatedElement:
+ // Both @title an aria-describedby=tooltip get "tooltip".
+ from = IsDescribedByTooltip() ? "tooltip" : "aria-describedby";
+ break;
+ case ax::mojom::DescriptionFrom::kRubyAnnotation:
+ from = "ruby-annotation";
+ break;
+ case ax::mojom::DescriptionFrom::kSummary:
+ from = "summary";
+ break;
+ case ax::mojom::DescriptionFrom::kTableCaption:
+ from = "table-caption";
+ break;
+ case ax::mojom::DescriptionFrom::kTitle:
+ // Both @title an aria-describedby=tooltip get "tooltip".
+ from = "tooltip";
+ break;
+ case ax::mojom::DescriptionFrom::kNone:
+ NOTREACHED();
+ }
+ DCHECK(!from.empty());
+ AddAttributeToList("description-from", from, attributes);
+ }
+
AddAttributeToList(ax::mojom::StringAttribute::kKeyShortcuts, "keyshortcuts",
attributes);
@@ -1103,7 +1156,7 @@ void AXPlatformNodeBase::ComputeAttributes(PlatformAttributeList* attributes) {
// Expose table cell index.
if (IsCellOrTableHeader(GetData().role)) {
- base::Optional<int> index = delegate_->GetTableCellIndex();
+ absl::optional<int> index = delegate_->GetTableCellIndex();
if (index) {
std::string str_index(base::NumberToString(*index));
AddAttributeToList("table-cell-index", str_index, attributes);
@@ -1277,7 +1330,7 @@ void AXPlatformNodeBase::ComputeAttributes(PlatformAttributeList* attributes) {
std::string type;
std::string html_tag =
GetStringAttribute(ax::mojom::StringAttribute::kHtmlTag);
- if (IsPlainTextField() && base::LowerCaseEqualsASCII(html_tag, "input") &&
+ if (IsAtomicTextField() && base::LowerCaseEqualsASCII(html_tag, "input") &&
GetData().GetHtmlAttribute("type", &type)) {
AddAttributeToList("text-input-type", type, attributes);
}
@@ -1328,16 +1381,17 @@ void AXPlatformNodeBase::AddAttributeToList(const char* name,
AddAttributeToList(name, value.c_str(), attributes);
}
-AXHypertext::AXHypertext() = default;
-AXHypertext::~AXHypertext() = default;
-AXHypertext::AXHypertext(const AXHypertext& other) = default;
-AXHypertext& AXHypertext::operator=(const AXHypertext& other) = default;
+AXLegacyHypertext::AXLegacyHypertext() = default;
+AXLegacyHypertext::~AXLegacyHypertext() = default;
+AXLegacyHypertext::AXLegacyHypertext(const AXLegacyHypertext& other) = default;
+AXLegacyHypertext& AXLegacyHypertext::operator=(
+ const AXLegacyHypertext& other) = default;
// TODO(nektar): To be able to use AXNode in Views, move this logic to AXNode.
void AXPlatformNodeBase::UpdateComputedHypertext() const {
if (!delegate_)
return;
- hypertext_ = AXHypertext();
+ hypertext_ = AXLegacyHypertext();
if (IsLeaf()) {
hypertext_.hypertext = GetInnerText();
@@ -1376,15 +1430,15 @@ void AXPlatformNodeBase::AddAttributeToList(const char* name,
PlatformAttributeList* attributes) {
}
-base::Optional<int> AXPlatformNodeBase::GetPosInSet() const {
+absl::optional<int> AXPlatformNodeBase::GetPosInSet() const {
if (!delegate_)
- return base::nullopt;
+ return absl::nullopt;
return delegate_->GetPosInSet();
}
-base::Optional<int> AXPlatformNodeBase::GetSetSize() const {
+absl::optional<int> AXPlatformNodeBase::GetSetSize() const {
if (!delegate_)
- return base::nullopt;
+ return absl::nullopt;
return delegate_->GetSetSize();
}
@@ -1574,7 +1628,7 @@ int AXPlatformNodeBase::GetHypertextOffsetFromEndpoint(
}
AXPlatformNodeBase* common_parent = this;
- base::Optional<int> index_in_common_parent = GetIndexInParent();
+ absl::optional<int> index_in_common_parent = GetIndexInParent();
while (common_parent && !endpoint_object->IsDescendantOf(common_parent)) {
index_in_common_parent = common_parent->GetIndexInParent();
common_parent = static_cast<AXPlatformNodeBase*>(
@@ -1610,7 +1664,7 @@ int AXPlatformNodeBase::GetHypertextOffsetFromEndpoint(
//
// We can safely assume that the endpoint is in another part of the tree or
// at common parent, and that this object is a descendant of common parent.
- base::Optional<int> endpoint_index_in_common_parent;
+ absl::optional<int> endpoint_index_in_common_parent;
for (auto child_iter = common_parent->AXPlatformNodeChildrenBegin();
child_iter != common_parent->AXPlatformNodeChildrenEnd(); ++child_iter) {
if (endpoint_object->IsDescendantOf(child_iter.get())) {
@@ -1663,7 +1717,7 @@ void AXPlatformNodeBase::GetSelectionOffsets(const AXTree::Selection* selection,
int* selection_end) {
DCHECK(selection_start && selection_end);
- if (IsPlainTextField() &&
+ if (IsAtomicTextField() &&
GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart,
selection_start) &&
GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, selection_end)) {
@@ -1732,7 +1786,7 @@ void AXPlatformNodeBase::GetSelectionOffsetsFromTree(
}
bool AXPlatformNodeBase::IsSameHypertextCharacter(
- const AXHypertext& old_hypertext,
+ const AXLegacyHypertext& old_hypertext,
size_t old_char_index,
size_t new_char_index) {
if (old_char_index >= old_hypertext.hypertext.size() ||
@@ -1790,7 +1844,7 @@ bool AXPlatformNodeBase::IsPlatformCheckable() const {
}
void AXPlatformNodeBase::ComputeHypertextRemovedAndInserted(
- const AXHypertext& old_hypertext,
+ const AXLegacyHypertext& old_hypertext,
size_t* start,
size_t* old_len,
size_t* new_len) {
@@ -1860,7 +1914,7 @@ int AXPlatformNodeBase::FindTextBoundary(
ax::mojom::TextAffinity affinity) const {
DCHECK_NE(boundary, ax::mojom::TextBoundary::kNone);
if (boundary != ax::mojom::TextBoundary::kSentenceStart) {
- base::Optional<int> boundary_offset =
+ absl::optional<int> boundary_offset =
GetDelegate()->FindTextBoundary(boundary, offset, direction, affinity);
if (boundary_offset.has_value())
return *boundary_offset;
@@ -2043,7 +2097,7 @@ ui::TextAttributeList AXPlatformNodeBase::ComputeTextAttributes() const {
attributes.push_back(std::make_pair("font-family", font_family));
}
- base::Optional<float> font_size_in_points = GetFontSizeInPoints();
+ absl::optional<float> font_size_in_points = GetFontSizeInPoints();
// Attribute has no default value.
if (font_size_in_points) {
attributes.push_back(std::make_pair(
@@ -2172,6 +2226,24 @@ void AXPlatformNodeBase::SanitizeTextAttributeValue(const std::string& input,
DCHECK(output);
}
+bool AXPlatformNodeBase::IsDescribedByTooltip() const {
+ const std::vector<int32_t>& description_ids =
+ GetIntListAttribute(ax::mojom::IntListAttribute::kDescribedbyIds);
+
+ std::string description_from;
+
+ for (int id : description_ids) {
+ AXPlatformNodeBase* description_object =
+ static_cast<AXPlatformNodeBase*>(delegate_->GetFromNodeID(id));
+ if (description_object &&
+ description_object->GetData().role == ax::mojom::Role::kTooltip) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
std::string AXPlatformNodeBase::ComputeDetailsRoles() const {
const std::vector<int32_t>& details_ids =
GetIntListAttribute(ax::mojom::IntListAttribute::kDetailsIds);
@@ -2200,12 +2272,7 @@ std::string AXPlatformNodeBase::ComputeDetailsRoles() const {
break;
case ax::mojom::Role::kGroup:
case ax::mojom::Role::kRegion: {
- // These should still report comment if there are comments inside them.
- constexpr int kMaxChildrenToCheck = 8;
- constexpr int kMaxDepthToCheck = 4;
- if (FindDescendantRoleWithMaxDepth(
- detail_object, ax::mojom::Role::kComment, kMaxDepthToCheck,
- kMaxChildrenToCheck)) {
+ if (DescendantHasComment(detail_object)) {
details_roles_set.insert("comment");
break;
}
@@ -2225,6 +2292,18 @@ std::string AXPlatformNodeBase::ComputeDetailsRoles() const {
return base::JoinString(details_roles_vector, " ");
}
+// static
+bool AXPlatformNodeBase::DescendantHasComment(const AXPlatformNodeBase* node) {
+ // These should still report comment if there are comments inside them.
+ constexpr int kMaxChildrenToCheck = 8;
+ constexpr int kMaxDepthToCheck = 4;
+ if (FindDescendantRoleWithMaxDepth(node, ax::mojom::Role::kComment,
+ kMaxDepthToCheck, kMaxChildrenToCheck)) {
+ return true;
+ }
+ return false;
+}
+
int AXPlatformNodeBase::GetMaxSelectableItems() const {
if (IsLeaf())
return 0;
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_base.h b/chromium/ui/accessibility/platform/ax_platform_node_base.h
index b89c1237c45..ada6e8c4496 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_base.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_base.h
@@ -30,11 +30,11 @@ struct AXNodeData;
// TODO(nektar): Move this struct over to AXNode so that it can be accessed by
// AXPosition.
-struct AX_EXPORT AXHypertext {
- AXHypertext();
- ~AXHypertext();
- AXHypertext(const AXHypertext& other);
- AXHypertext& operator=(const AXHypertext& other);
+struct AX_EXPORT AXLegacyHypertext {
+ AXLegacyHypertext();
+ ~AXLegacyHypertext();
+ AXLegacyHypertext(const AXLegacyHypertext& other);
+ AXLegacyHypertext& operator=(const AXLegacyHypertext& other);
// A flag that should be set if the hypertext information in this struct is
// out-of-date and needs to be updated. This flag should always be set upon
@@ -73,7 +73,7 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode {
// This returns nullopt if there's no parent, it's unable to find the child in
// the list of its parent's children, or its parent doesn't have children.
- virtual base::Optional<int> GetIndexInParent();
+ virtual absl::optional<int> GetIndexInParent();
// Returns a stack of ancestors of this node. The node at the top of the stack
// is the top most ancestor.
@@ -85,7 +85,7 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode {
// 0: if this position is logically equivalent to the other node
// <0: if this position is logically less than (before) the other node
// >0: if this position is logically greater than (after) the other node
- base::Optional<int> CompareTo(AXPlatformNodeBase& other);
+ absl::optional<int> CompareTo(AXPlatformNodeBase& other);
// AXPlatformNode.
void Destroy() override;
@@ -178,51 +178,51 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode {
// If inside a table or ARIA grid, returns the zero-based index of the cell.
// Indices are in row major order and each cell is counted once regardless of
- // its span. Returns base::nullopt if not a cell or if not inside a table.
- base::Optional<int> GetTableCellIndex() const;
+ // its span. Returns absl::nullopt if not a cell or if not inside a table.
+ absl::optional<int> GetTableCellIndex() const;
// If inside a table or ARIA grid, returns the physical column number for the
// current cell. In contrast to logical columns, physical columns always start
// from 0 and have no gaps in their numbering. Logical columns can be set
- // using aria-colindex. Returns base::nullopt if not a cell or if not inside a
+ // using aria-colindex. Returns absl::nullopt if not a cell or if not inside a
// table.
- base::Optional<int> GetTableColumn() const;
+ absl::optional<int> GetTableColumn() const;
// If inside a table or ARIA grid, returns the number of physical columns.
- // Returns base::nullopt if not inside a table.
- base::Optional<int> GetTableColumnCount() const;
+ // Returns absl::nullopt if not inside a table.
+ absl::optional<int> GetTableColumnCount() const;
// If inside a table or ARIA grid, returns the number of ARIA columns.
- // Returns base::nullopt if not inside a table.
- base::Optional<int> GetTableAriaColumnCount() const;
+ // Returns absl::nullopt if not inside a table.
+ absl::optional<int> GetTableAriaColumnCount() const;
// If inside a table or ARIA grid, returns the number of physical columns that
- // this cell spans. Returns base::nullopt if not a cell or if not inside a
+ // this cell spans. Returns absl::nullopt if not a cell or if not inside a
// table.
- base::Optional<int> GetTableColumnSpan() const;
+ absl::optional<int> GetTableColumnSpan() const;
// If inside a table or ARIA grid, returns the physical row number for the
// current cell. In contrast to logical rows, physical rows always start from
// 0 and have no gaps in their numbering. Logical rows can be set using
- // aria-rowindex. Returns base::nullopt if not a cell or if not inside a
+ // aria-rowindex. Returns absl::nullopt if not a cell or if not inside a
// table.
- base::Optional<int> GetTableRow() const;
+ absl::optional<int> GetTableRow() const;
// If inside a table or ARIA grid, returns the number of physical rows.
- // Returns base::nullopt if not inside a table.
- base::Optional<int> GetTableRowCount() const;
+ // Returns absl::nullopt if not inside a table.
+ absl::optional<int> GetTableRowCount() const;
// If inside a table or ARIA grid, returns the number of ARIA rows.
- // Returns base::nullopt if not inside a table.
- base::Optional<int> GetTableAriaRowCount() const;
+ // Returns absl::nullopt if not inside a table.
+ absl::optional<int> GetTableAriaRowCount() const;
// If inside a table or ARIA grid, returns the number of physical rows that
- // this cell spans. Returns base::nullopt if not a cell or if not inside a
+ // this cell spans. Returns absl::nullopt if not a cell or if not inside a
// table.
- base::Optional<int> GetTableRowSpan() const;
+ absl::optional<int> GetTableRowSpan() const;
// Returns the font size converted to points, if available.
- base::Optional<float> GetFontSizeInPoints() const;
+ absl::optional<float> GetFontSizeInPoints() const;
// Returns true if either a descendant has selection (sel_focus_object_id) or
// if this node is a simple text element and has text selection attributes.
@@ -257,11 +257,11 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode {
// See AXNodeData::IsTextField().
bool IsTextField() const;
- // See AXNodeData::IsPlainTextField().
- bool IsPlainTextField() const;
+ // See AXNodeData::IsAtomicTextField().
+ bool IsAtomicTextField() const;
- // See AXNodeData::IsRichTextField().
- bool IsRichTextField() const;
+ // See AXNodeData::IsNonAtomicTextField().
+ bool IsNonAtomicTextField() const;
// See AXNode::IsText().
bool IsText() const;
@@ -371,10 +371,10 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode {
AXPlatformNodeDelegate* delegate_ = nullptr;
// Uses the delegate to calculate this node's PosInSet.
- base::Optional<int> GetPosInSet() const;
+ absl::optional<int> GetPosInSet() const;
// Uses the delegate to calculate this node's SetSize.
- base::Optional<int> GetSetSize() const;
+ absl::optional<int> GetSetSize() const;
// Returns true if this object is at the root of what most accessibility APIs
// consider to be a document, such as the root of a webpage, an iframe, or a
@@ -382,6 +382,7 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode {
bool IsPlatformDocument() const;
protected:
+ bool IsStructuredAnnotation() const;
bool IsSelectionItemSupported() const;
// Get the role description from the node data or from the image annotation
@@ -394,6 +395,9 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode {
// Cannot be called on nodes with a role other than kImage.
bool IsImageWithMap() const;
+ // Return true if a descendant of this has a kComment.
+ static bool DescendantHasComment(const AXPlatformNodeBase* node);
+
// Cast a gfx::NativeViewAccessible to an AXPlatformNodeBase if it is one,
// or return NULL if it's not an instance of this class.
static AXPlatformNodeBase* FromNativeViewAccessible(
@@ -502,13 +506,14 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode {
int GetHypertextOffsetFromEndpoint(AXPlatformNodeBase* endpoint_object,
int endpoint_offset);
- bool IsSameHypertextCharacter(const AXHypertext& old_hypertext,
+ bool IsSameHypertextCharacter(const AXLegacyHypertext& old_hypertext,
size_t old_char_index,
size_t new_char_index);
- void ComputeHypertextRemovedAndInserted(const AXHypertext& old_hypertext,
- size_t* start,
- size_t* old_len,
- size_t* new_len);
+ void ComputeHypertextRemovedAndInserted(
+ const AXLegacyHypertext& old_hypertext,
+ size_t* start,
+ size_t* old_len,
+ size_t* new_len);
std::string GetInvalidValue() const;
@@ -517,7 +522,7 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode {
// selectable children that this object could potentially contain.
int GetMaxSelectableItems() const;
- mutable AXHypertext hypertext_;
+ mutable AXLegacyHypertext hypertext_;
private:
// Returns true if the index represents a text character.
@@ -528,6 +533,9 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode {
// Compute value for object attribute details-roles on aria-details nodes.
std::string ComputeDetailsRoles() const;
+ // Is there an aria-describedby that points to a role="tooltip".
+ bool IsDescribedByTooltip() const;
+
DISALLOW_COPY_AND_ASSIGN(AXPlatformNodeBase);
};
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_base_unittest.cc b/chromium/ui/accessibility/platform/ax_platform_node_base_unittest.cc
index 37683517a09..0c1e594bd9f 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_base_unittest.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_base_unittest.cc
@@ -66,7 +66,7 @@ TEST(AXPlatformNodeBaseTest, GetHypertext) {
// Set an AXMode on the AXPlatformNode as some platforms (auralinux) use it to
// determine if it should enable accessibility.
- AXPlatformNodeBase::NotifyAddAXModeFlags(kAXModeComplete);
+ testing::ScopedAxModeSetter ax_mode_setter(kAXModeComplete);
AXPlatformNodeBase* root = static_cast<AXPlatformNodeBase*>(
TestAXNodeWrapper::GetOrCreate(&tree, tree.root())->ax_platform_node());
@@ -125,7 +125,7 @@ TEST(AXPlatformNodeBaseTest, GetHypertextIgnoredContainerSiblings) {
AXTree tree(update);
// Set an AXMode on the AXPlatformNode as some platforms (auralinux) use it to
// determine if it should enable accessibility.
- AXPlatformNodeBase::NotifyAddAXModeFlags(kAXModeComplete);
+ ui::testing::ScopedAxModeSetter ax_mode_setter(kAXModeComplete);
AXPlatformNodeBase* root = static_cast<AXPlatformNodeBase*>(
TestAXNodeWrapper::GetOrCreate(&tree, tree.root())->ax_platform_node());
@@ -170,7 +170,7 @@ TEST(AXPlatformNodeBaseTest, InnerTextIgnoresInvisibleAndIgnored) {
// Set an AXMode on the AXPlatformNode as some platforms (auralinux) use it to
// determine if it should enable accessibility.
- AXPlatformNodeBase::NotifyAddAXModeFlags(kAXModeComplete);
+ ui::testing::ScopedAxModeSetter ax_mode_setter(kAXModeComplete);
EXPECT_EQ(root->GetInnerText(), u"abde");
@@ -183,7 +183,7 @@ TEST(AXPlatformNodeBaseTest, InnerTextIgnoresInvisibleAndIgnored) {
SetIsInvisible(&tree, 2, false);
EXPECT_EQ(root->GetInnerText(), u"abde");
- SetRole(&tree, 2, ax::mojom::Role::kIgnored);
+ SetRole(&tree, 2, ax::mojom::Role::kNone);
EXPECT_EQ(root->GetInnerText(), u"bde");
SetRole(&tree, 2, ax::mojom::Role::kStaticText);
@@ -196,13 +196,13 @@ TEST(AXPlatformNodeBaseTest, InnerTextIgnoresInvisibleAndIgnored) {
SetIsInvisible(&tree, 4, true);
EXPECT_EQ(root->GetInnerText(), u"abde");
- SetRole(&tree, 4, ax::mojom::Role::kIgnored);
+ SetRole(&tree, 4, ax::mojom::Role::kNone);
EXPECT_EQ(root->GetInnerText(), u"abde");
}
}
TEST(AXPlatformNodeBaseTest, TestMenuSelectedItems) {
- AXPlatformNode::NotifyAddAXModeFlags(kAXModeComplete);
+ ui::testing::ScopedAxModeSetter ax_mode_setter(kAXModeComplete);
AXNodeData root_data;
root_data.id = 1;
@@ -237,7 +237,7 @@ TEST(AXPlatformNodeBaseTest, TestMenuSelectedItems) {
}
TEST(AXPlatformNodeBaseTest, TestSelectedChildren) {
- AXPlatformNode::NotifyAddAXModeFlags(kAXModeComplete);
+ ui::testing::ScopedAxModeSetter ax_mode_setter(kAXModeComplete);
AXNodeData root_data;
root_data.id = 1;
@@ -272,7 +272,7 @@ TEST(AXPlatformNodeBaseTest, TestSelectedChildren) {
}
TEST(AXPlatformNodeBaseTest, TestSelectedChildrenWithGroup) {
- AXPlatformNode::NotifyAddAXModeFlags(kAXModeComplete);
+ ui::testing::ScopedAxModeSetter ax_mode_setter(kAXModeComplete);
AXNodeData root_data;
root_data.id = 1;
@@ -338,7 +338,7 @@ TEST(AXPlatformNodeBaseTest, TestSelectedChildrenWithGroup) {
}
TEST(AXPlatformNodeBaseTest, TestSelectedChildrenMixed) {
- AXPlatformNode::NotifyAddAXModeFlags(kAXModeComplete);
+ ui::testing::ScopedAxModeSetter ax_mode_setter(kAXModeComplete);
// Build the below tree which is mixed with listBoxOption and group.
// id=1 listBox FOCUSABLE MULTISELECTABLE (0, 0)-(0, 0) child_ids=2,3,4,9
@@ -446,7 +446,7 @@ TEST(AXPlatformNodeBaseTest, CompareTo) {
// n4 n5 n6 n10
// /
// n7
- AXPlatformNode::NotifyAddAXModeFlags(kAXModeComplete);
+ ui::testing::ScopedAxModeSetter ax_mode_setter(kAXModeComplete);
AXNodeData node1;
node1.id = 1;
node1.role = ax::mojom::Role::kRootWebArea;
@@ -524,7 +524,7 @@ TEST(AXPlatformNodeBaseTest, CompareTo) {
// Test for two nodes that do not share the same root. They should not be
// comparable.
AXPlatformNodeBase detached_node;
- EXPECT_EQ(base::nullopt, n1->CompareTo(detached_node));
+ EXPECT_EQ(absl::nullopt, n1->CompareTo(detached_node));
// Create a test vector of all the tree nodes arranged in a pre-order
// traversal way. The node that has a smaller index in the vector should also
@@ -541,14 +541,14 @@ TEST(AXPlatformNodeBaseTest, CompareTo) {
else if (lhs->GetData().id > rhs->GetData().id)
expected_result = 1;
- EXPECT_NE(base::nullopt, lhs->CompareTo(*rhs));
+ EXPECT_NE(absl::nullopt, lhs->CompareTo(*rhs));
int actual_result = 0;
if (lhs->CompareTo(*rhs) < 0)
actual_result = -1;
else if (lhs->CompareTo(*rhs) > 0)
actual_result = 1;
- SCOPED_TRACE(testing::Message()
+ SCOPED_TRACE(::testing::Message()
<< "lhs.id=" << base::NumberToString(lhs->GetData().id)
<< ", rhs.id=" << base::NumberToString(rhs->GetData().id)
<< ", lhs->CompareTo(*rhs)={actual:"
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_delegate.h b/chromium/ui/accessibility/platform/ax_platform_node_delegate.h
index bde4bc4dcc7..1ccb2cc23b7 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_delegate.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_delegate.h
@@ -16,7 +16,7 @@
#include <utility>
#include <vector>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/accessibility/ax_clipping_behavior.h"
#include "ui/accessibility/ax_coordinate_system.h"
@@ -157,9 +157,12 @@ class AX_EXPORT AXPlatformNodeDelegate {
// platform's accessibility layer.
virtual bool IsChildOfLeaf() const = 0;
- // Returns true if this node is either a plain text field , or one of its
- // ancestors is.
- virtual bool IsDescendantOfPlainTextField() const = 0;
+ // Returns true if this node is either an atomic text field , or one of its
+ // ancestors is. An atomic text field does not expose its internal
+ // implementation to assistive software, appearing as a single leaf node in
+ // the accessibility tree. It includes <input>, <textarea> and Views-based
+ // text fields.
+ virtual bool IsDescendantOfAtomicTextField() const = 0;
// Returns true if this is a leaf node, meaning all its
// children should not be exposed to any platform's native accessibility
@@ -186,6 +189,12 @@ class AX_EXPORT AXPlatformNodeDelegate {
// APIs: See `IsInvisibleOrIgnored`.)
virtual gfx::NativeViewAccessible GetLowestPlatformAncestor() const = 0;
+ // If this node is within an editable region, returns the node that is at the
+ // root of that editable region, otherwise returns nullptr. In accessibility,
+ // an editable region is synonymous to a node with the kTextField role, or a
+ // contenteditable without the role, (see `AXNodeData::IsTextField()`).
+ virtual gfx::NativeViewAccessible GetTextFieldAncestor() const = 0;
+
class ChildIterator {
public:
virtual ~ChildIterator() = default;
@@ -351,7 +360,7 @@ class AX_EXPORT AXPlatformNodeDelegate {
// that the delegate does not have all the information required to calculate
// this value and it is the responsibility of the AXPlatformNode itself to
// to calculate it.
- virtual base::Optional<int> FindTextBoundary(
+ virtual absl::optional<int> FindTextBoundary(
ax::mojom::TextBoundary boundary,
int offset,
ax::mojom::MoveDirection direction,
@@ -378,12 +387,12 @@ class AX_EXPORT AXPlatformNodeDelegate {
// role, otherwise they return nullopt.
//
virtual bool IsTable() const = 0;
- virtual base::Optional<int> GetTableColCount() const = 0;
- virtual base::Optional<int> GetTableRowCount() const = 0;
- virtual base::Optional<int> GetTableAriaColCount() const = 0;
- virtual base::Optional<int> GetTableAriaRowCount() const = 0;
- virtual base::Optional<int> GetTableCellCount() const = 0;
- virtual base::Optional<bool> GetTableHasColumnOrRowHeaderNode() const = 0;
+ virtual absl::optional<int> GetTableColCount() const = 0;
+ virtual absl::optional<int> GetTableRowCount() const = 0;
+ virtual absl::optional<int> GetTableAriaColCount() const = 0;
+ virtual absl::optional<int> GetTableAriaRowCount() const = 0;
+ virtual absl::optional<int> GetTableCellCount() const = 0;
+ virtual absl::optional<bool> GetTableHasColumnOrRowHeaderNode() const = 0;
virtual std::vector<int32_t> GetColHeaderNodeIds() const = 0;
virtual std::vector<int32_t> GetColHeaderNodeIds(int col_index) const = 0;
virtual std::vector<int32_t> GetRowHeaderNodeIds() const = 0;
@@ -392,20 +401,20 @@ class AX_EXPORT AXPlatformNodeDelegate {
// Table row-like nodes.
virtual bool IsTableRow() const = 0;
- virtual base::Optional<int> GetTableRowRowIndex() const = 0;
+ virtual absl::optional<int> GetTableRowRowIndex() const = 0;
// Table cell-like nodes.
virtual bool IsTableCellOrHeader() const = 0;
- virtual base::Optional<int> GetTableCellIndex() const = 0;
- virtual base::Optional<int> GetTableCellColIndex() const = 0;
- virtual base::Optional<int> GetTableCellRowIndex() const = 0;
- virtual base::Optional<int> GetTableCellColSpan() const = 0;
- virtual base::Optional<int> GetTableCellRowSpan() const = 0;
- virtual base::Optional<int> GetTableCellAriaColIndex() const = 0;
- virtual base::Optional<int> GetTableCellAriaRowIndex() const = 0;
- virtual base::Optional<int32_t> GetCellId(int row_index,
+ virtual absl::optional<int> GetTableCellIndex() const = 0;
+ virtual absl::optional<int> GetTableCellColIndex() const = 0;
+ virtual absl::optional<int> GetTableCellRowIndex() const = 0;
+ virtual absl::optional<int> GetTableCellColSpan() const = 0;
+ virtual absl::optional<int> GetTableCellRowSpan() const = 0;
+ virtual absl::optional<int> GetTableCellAriaColIndex() const = 0;
+ virtual absl::optional<int> GetTableCellAriaRowIndex() const = 0;
+ virtual absl::optional<int32_t> GetCellId(int row_index,
int col_index) const = 0;
- virtual base::Optional<int32_t> CellIndexToId(int cell_index) const = 0;
+ virtual absl::optional<int32_t> CellIndexToId(int cell_index) const = 0;
// Helper methods to check if a cell is an ARIA-1.1+ 'cell' or 'gridcell'
virtual bool IsCellOrHeaderOfARIATable() const = 0;
@@ -414,8 +423,8 @@ class AX_EXPORT AXPlatformNodeDelegate {
// Ordered-set-like and item-like nodes.
virtual bool IsOrderedSetItem() const = 0;
virtual bool IsOrderedSet() const = 0;
- virtual base::Optional<int> GetPosInSet() const = 0;
- virtual base::Optional<int> GetSetSize() const = 0;
+ virtual absl::optional<int> GetPosInSet() const = 0;
+ virtual absl::optional<int> GetSetSize() const = 0;
// Computed colors, taking blending into account.
virtual SkColor GetColor() const = 0;
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_delegate_base.cc b/chromium/ui/accessibility/platform/ax_platform_node_delegate_base.cc
index 0a1a0c1759b..3198084626d 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_delegate_base.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_delegate_base.cc
@@ -172,7 +172,17 @@ bool AXPlatformNodeDelegateBase::IsToplevelBrowserWindow() {
return false;
}
-bool AXPlatformNodeDelegateBase::IsDescendantOfPlainTextField() const {
+bool AXPlatformNodeDelegateBase::IsDescendantOfAtomicTextField() const {
+ // TODO(nektar): Add const to all tree traversal methods and remove
+ // const_cast.
+ for (AXPlatformNodeDelegateBase* ancestor_delegate =
+ const_cast<AXPlatformNodeDelegateBase*>(this);
+ ancestor_delegate;
+ ancestor_delegate = static_cast<AXPlatformNodeDelegateBase*>(
+ ancestor_delegate->GetParentDelegate())) {
+ if (ancestor_delegate->GetData().IsAtomicTextField())
+ return true;
+ }
return false;
}
@@ -210,6 +220,21 @@ AXPlatformNodeDelegateBase::GetLowestPlatformAncestor() const {
return current_delegate->GetNativeViewAccessible();
}
+gfx::NativeViewAccessible AXPlatformNodeDelegateBase::GetTextFieldAncestor()
+ const {
+ // TODO(nektar): Add const to all tree traversal methods and remove
+ // const_cast.
+ for (AXPlatformNodeDelegateBase* ancestor_delegate =
+ const_cast<AXPlatformNodeDelegateBase*>(this);
+ ancestor_delegate;
+ ancestor_delegate = static_cast<AXPlatformNodeDelegateBase*>(
+ ancestor_delegate->GetParentDelegate())) {
+ if (ancestor_delegate->GetData().IsTextField())
+ return ancestor_delegate->GetNativeViewAccessible();
+ }
+ return nullptr;
+}
+
AXPlatformNodeDelegateBase::ChildIteratorBase::ChildIteratorBase(
AXPlatformNodeDelegateBase* parent,
int index)
@@ -387,39 +412,39 @@ bool AXPlatformNodeDelegateBase::IsTable() const {
return ui::IsTableLike(GetData().role);
}
-base::Optional<int> AXPlatformNodeDelegateBase::GetTableRowCount() const {
+absl::optional<int> AXPlatformNodeDelegateBase::GetTableRowCount() const {
return GetData().GetIntAttribute(ax::mojom::IntAttribute::kTableRowCount);
}
-base::Optional<int> AXPlatformNodeDelegateBase::GetTableColCount() const {
+absl::optional<int> AXPlatformNodeDelegateBase::GetTableColCount() const {
return GetData().GetIntAttribute(ax::mojom::IntAttribute::kTableColumnCount);
}
-base::Optional<int> AXPlatformNodeDelegateBase::GetTableAriaColCount() const {
+absl::optional<int> AXPlatformNodeDelegateBase::GetTableAriaColCount() const {
int aria_column_count;
if (!GetData().GetIntAttribute(ax::mojom::IntAttribute::kAriaColumnCount,
&aria_column_count)) {
- return base::nullopt;
+ return absl::nullopt;
}
return aria_column_count;
}
-base::Optional<int> AXPlatformNodeDelegateBase::GetTableAriaRowCount() const {
+absl::optional<int> AXPlatformNodeDelegateBase::GetTableAriaRowCount() const {
int aria_row_count;
if (!GetData().GetIntAttribute(ax::mojom::IntAttribute::kAriaRowCount,
&aria_row_count)) {
- return base::nullopt;
+ return absl::nullopt;
}
return aria_row_count;
}
-base::Optional<int> AXPlatformNodeDelegateBase::GetTableCellCount() const {
- return base::nullopt;
+absl::optional<int> AXPlatformNodeDelegateBase::GetTableCellCount() const {
+ return absl::nullopt;
}
-base::Optional<bool>
+absl::optional<bool>
AXPlatformNodeDelegateBase::GetTableHasColumnOrRowHeaderNode() const {
- return base::nullopt;
+ return absl::nullopt;
}
std::vector<int32_t> AXPlatformNodeDelegateBase::GetColHeaderNodeIds() const {
@@ -448,7 +473,7 @@ bool AXPlatformNodeDelegateBase::IsTableRow() const {
return ui::IsTableRow(GetData().role);
}
-base::Optional<int> AXPlatformNodeDelegateBase::GetTableRowRowIndex() const {
+absl::optional<int> AXPlatformNodeDelegateBase::GetTableRowRowIndex() const {
return GetData().GetIntAttribute(ax::mojom::IntAttribute::kTableRowIndex);
}
@@ -456,25 +481,25 @@ bool AXPlatformNodeDelegateBase::IsTableCellOrHeader() const {
return ui::IsCellOrTableHeader(GetData().role);
}
-base::Optional<int> AXPlatformNodeDelegateBase::GetTableCellColIndex() const {
+absl::optional<int> AXPlatformNodeDelegateBase::GetTableCellColIndex() const {
return GetData().GetIntAttribute(
ax::mojom::IntAttribute::kTableCellColumnIndex);
}
-base::Optional<int> AXPlatformNodeDelegateBase::GetTableCellRowIndex() const {
+absl::optional<int> AXPlatformNodeDelegateBase::GetTableCellRowIndex() const {
return GetData().GetIntAttribute(ax::mojom::IntAttribute::kTableCellRowIndex);
}
-base::Optional<int> AXPlatformNodeDelegateBase::GetTableCellColSpan() const {
+absl::optional<int> AXPlatformNodeDelegateBase::GetTableCellColSpan() const {
return GetData().GetIntAttribute(
ax::mojom::IntAttribute::kTableCellColumnSpan);
}
-base::Optional<int> AXPlatformNodeDelegateBase::GetTableCellRowSpan() const {
+absl::optional<int> AXPlatformNodeDelegateBase::GetTableCellRowSpan() const {
return GetData().GetIntAttribute(ax::mojom::IntAttribute::kTableCellRowSpan);
}
-base::Optional<int> AXPlatformNodeDelegateBase::GetTableCellAriaColIndex()
+absl::optional<int> AXPlatformNodeDelegateBase::GetTableCellAriaColIndex()
const {
if (GetData().HasIntAttribute(
ax::mojom::IntAttribute::kAriaCellColumnIndex)) {
@@ -482,32 +507,32 @@ base::Optional<int> AXPlatformNodeDelegateBase::GetTableCellAriaColIndex()
ax::mojom::IntAttribute::kAriaCellColumnIndex);
}
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<int> AXPlatformNodeDelegateBase::GetTableCellAriaRowIndex()
+absl::optional<int> AXPlatformNodeDelegateBase::GetTableCellAriaRowIndex()
const {
if (GetData().HasIntAttribute(ax::mojom::IntAttribute::kAriaCellRowIndex)) {
return GetData().GetIntAttribute(
ax::mojom::IntAttribute::kAriaCellRowIndex);
}
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<int32_t> AXPlatformNodeDelegateBase::GetCellId(
+absl::optional<int32_t> AXPlatformNodeDelegateBase::GetCellId(
int row_index,
int col_index) const {
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<int> AXPlatformNodeDelegateBase::GetTableCellIndex() const {
- return base::nullopt;
+absl::optional<int> AXPlatformNodeDelegateBase::GetTableCellIndex() const {
+ return absl::nullopt;
}
-base::Optional<int32_t> AXPlatformNodeDelegateBase::CellIndexToId(
+absl::optional<int32_t> AXPlatformNodeDelegateBase::CellIndexToId(
int cell_index) const {
- return base::nullopt;
+ return absl::nullopt;
}
bool AXPlatformNodeDelegateBase::IsCellOrHeaderOfARIATable() const {
@@ -526,12 +551,12 @@ bool AXPlatformNodeDelegateBase::IsOrderedSet() const {
return false;
}
-base::Optional<int> AXPlatformNodeDelegateBase::GetPosInSet() const {
- return base::nullopt;
+absl::optional<int> AXPlatformNodeDelegateBase::GetPosInSet() const {
+ return absl::nullopt;
}
-base::Optional<int> AXPlatformNodeDelegateBase::GetSetSize() const {
- return base::nullopt;
+absl::optional<int> AXPlatformNodeDelegateBase::GetSetSize() const {
+ return absl::nullopt;
}
SkColor AXPlatformNodeDelegateBase::GetColor() const {
@@ -608,7 +633,7 @@ bool AXPlatformNodeDelegateBase::IsWebContent() const {
}
bool AXPlatformNodeDelegateBase::HasVisibleCaretOrSelection() const {
- return IsDescendantOfPlainTextField();
+ return IsDescendantOfAtomicTextField();
}
AXPlatformNode* AXPlatformNodeDelegateBase::GetTargetNodeForRelation(
@@ -680,12 +705,12 @@ const AXUniqueId& AXPlatformNodeDelegateBase::GetUniqueId() const {
return *dummy_unique_id;
}
-base::Optional<int> AXPlatformNodeDelegateBase::FindTextBoundary(
+absl::optional<int> AXPlatformNodeDelegateBase::FindTextBoundary(
ax::mojom::TextBoundary boundary,
int offset,
ax::mojom::MoveDirection direction,
ax::mojom::TextAffinity affinity) const {
- return base::nullopt;
+ return absl::nullopt;
}
const std::vector<gfx::NativeViewAccessible>
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_delegate_base.h b/chromium/ui/accessibility/platform/ax_platform_node_delegate_base.h
index c15e3eb2cd0..ca4a279d56d 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_delegate_base.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_delegate_base.h
@@ -12,7 +12,7 @@
#include <string>
#include <vector>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/platform/ax_platform_node_delegate.h"
namespace ui {
@@ -72,11 +72,12 @@ class AX_EXPORT AXPlatformNodeDelegateBase : public AXPlatformNodeDelegate {
gfx::NativeViewAccessible GetPreviousSibling() override;
bool IsChildOfLeaf() const override;
- bool IsDescendantOfPlainTextField() const override;
+ bool IsDescendantOfAtomicTextField() const override;
bool IsLeaf() const override;
bool IsFocused() const override;
bool IsToplevelBrowserWindow() override;
gfx::NativeViewAccessible GetLowestPlatformAncestor() const override;
+ gfx::NativeViewAccessible GetTextFieldAncestor() const override;
class ChildIteratorBase : public ChildIterator {
public:
@@ -205,7 +206,7 @@ class AX_EXPORT AXPlatformNodeDelegateBase : public AXPlatformNodeDelegate {
const AXUniqueId& GetUniqueId() const override;
- base::Optional<int> FindTextBoundary(
+ absl::optional<int> FindTextBoundary(
ax::mojom::TextBoundary boundary,
int offset,
ax::mojom::MoveDirection direction,
@@ -221,12 +222,12 @@ class AX_EXPORT AXPlatformNodeDelegateBase : public AXPlatformNodeDelegate {
// role, otherwise they return nullopt.
//
bool IsTable() const override;
- base::Optional<int> GetTableColCount() const override;
- base::Optional<int> GetTableRowCount() const override;
- base::Optional<int> GetTableAriaColCount() const override;
- base::Optional<int> GetTableAriaRowCount() const override;
- base::Optional<int> GetTableCellCount() const override;
- base::Optional<bool> GetTableHasColumnOrRowHeaderNode() const override;
+ absl::optional<int> GetTableColCount() const override;
+ absl::optional<int> GetTableRowCount() const override;
+ absl::optional<int> GetTableAriaColCount() const override;
+ absl::optional<int> GetTableAriaRowCount() const override;
+ absl::optional<int> GetTableCellCount() const override;
+ absl::optional<bool> GetTableHasColumnOrRowHeaderNode() const override;
std::vector<int32_t> GetColHeaderNodeIds() const override;
std::vector<int32_t> GetColHeaderNodeIds(int col_index) const override;
std::vector<int32_t> GetRowHeaderNodeIds() const override;
@@ -235,20 +236,20 @@ class AX_EXPORT AXPlatformNodeDelegateBase : public AXPlatformNodeDelegate {
// Table row-like nodes.
bool IsTableRow() const override;
- base::Optional<int> GetTableRowRowIndex() const override;
+ absl::optional<int> GetTableRowRowIndex() const override;
// Table cell-like nodes.
bool IsTableCellOrHeader() const override;
- base::Optional<int> GetTableCellIndex() const override;
- base::Optional<int> GetTableCellColIndex() const override;
- base::Optional<int> GetTableCellRowIndex() const override;
- base::Optional<int> GetTableCellColSpan() const override;
- base::Optional<int> GetTableCellRowSpan() const override;
- base::Optional<int> GetTableCellAriaColIndex() const override;
- base::Optional<int> GetTableCellAriaRowIndex() const override;
- base::Optional<int32_t> GetCellId(int row_index,
+ absl::optional<int> GetTableCellIndex() const override;
+ absl::optional<int> GetTableCellColIndex() const override;
+ absl::optional<int> GetTableCellRowIndex() const override;
+ absl::optional<int> GetTableCellColSpan() const override;
+ absl::optional<int> GetTableCellRowSpan() const override;
+ absl::optional<int> GetTableCellAriaColIndex() const override;
+ absl::optional<int> GetTableCellAriaRowIndex() const override;
+ absl::optional<int32_t> GetCellId(int row_index,
int col_index) const override;
- base::Optional<int32_t> CellIndexToId(int cell_index) const override;
+ absl::optional<int32_t> CellIndexToId(int cell_index) const override;
// Helper methods to check if a cell is an ARIA-1.1+ 'cell' or 'gridcell'
bool IsCellOrHeaderOfARIATable() const override;
@@ -257,8 +258,8 @@ class AX_EXPORT AXPlatformNodeDelegateBase : public AXPlatformNodeDelegate {
// Ordered-set-like and item-like nodes.
bool IsOrderedSetItem() const override;
bool IsOrderedSet() const override;
- base::Optional<int> GetPosInSet() const override;
- base::Optional<int> GetSetSize() const override;
+ absl::optional<int> GetPosInSet() const override;
+ absl::optional<int> GetSetSize() const override;
// Computed colors, taking blending into account.
SkColor GetColor() const override;
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_mac.mm b/chromium/ui/accessibility/platform/ax_platform_node_mac.mm
index 3fabf9995c8..e8600ea3b8c 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_mac.mm
+++ b/chromium/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -140,7 +140,6 @@ RoleMap BuildRoleMap() {
{ax::mojom::Role::kHeading, @"AXHeading"},
{ax::mojom::Role::kIframe, NSAccessibilityGroupRole},
{ax::mojom::Role::kIframePresentational, NSAccessibilityGroupRole},
- {ax::mojom::Role::kIgnored, NSAccessibilityUnknownRole},
{ax::mojom::Role::kImage, NSAccessibilityImageRole},
{ax::mojom::Role::kInputTime, @"AXTimeField"},
{ax::mojom::Role::kLabelText, NSAccessibilityGroupRole},
@@ -178,7 +177,6 @@ RoleMap BuildRoleMap() {
{ax::mojom::Role::kPopUpButton, NSAccessibilityPopUpButtonRole},
{ax::mojom::Role::kPortal, NSAccessibilityButtonRole},
{ax::mojom::Role::kPre, NSAccessibilityGroupRole},
- {ax::mojom::Role::kPresentational, NSAccessibilityGroupRole},
{ax::mojom::Role::kProgressIndicator,
NSAccessibilityProgressIndicatorRole},
{ax::mojom::Role::kRadioButton, NSAccessibilityRadioButtonRole},
@@ -262,7 +260,6 @@ RoleMap BuildSubroleMap() {
{ax::mojom::Role::kRegion, @"AXLandmarkRegion"},
{ax::mojom::Role::kSearch, @"AXLandmarkSearch"},
{ax::mojom::Role::kSearchBox, @"AXSearchField"},
- {ax::mojom::Role::kSection, @"AXLandmarkRegion"},
{ax::mojom::Role::kStatus, @"AXApplicationStatus"},
{ax::mojom::Role::kStrong, @"AXStrongStyleGroup"},
{ax::mojom::Role::kSwitch, @"AXSwitch"},
@@ -286,10 +283,10 @@ EventMap BuildEventMap() {
NSAccessibilityFocusedUIElementChangedNotification},
{ax::mojom::Event::kFocusContext,
NSAccessibilityFocusedUIElementChangedNotification},
- {ax::mojom::Event::kMenuStart, (id)kAXMenuOpenedNotification},
- {ax::mojom::Event::kMenuEnd, (id)kAXMenuClosedNotification},
- {ax::mojom::Event::kMenuPopupStart, (id)kAXMenuOpenedNotification},
- {ax::mojom::Event::kMenuPopupEnd, (id)kAXMenuClosedNotification},
+ {ax::mojom::Event::kMenuStart, (NSString*)kAXMenuOpenedNotification},
+ {ax::mojom::Event::kMenuEnd, (NSString*)kAXMenuClosedNotification},
+ {ax::mojom::Event::kMenuPopupStart, (NSString*)kAXMenuOpenedNotification},
+ {ax::mojom::Event::kMenuPopupEnd, (NSString*)kAXMenuClosedNotification},
{ax::mojom::Event::kTextChanged, NSAccessibilityTitleChangedNotification},
{ax::mojom::Event::kValueChanged,
NSAccessibilityValueChangedNotification},
@@ -333,6 +330,16 @@ void PostAnnouncementNotification(NSString* announcement,
notification_info);
}
void NotifyMacEvent(AXPlatformNodeCocoa* target, ax::mojom::Event event_type) {
+ // When this is fired and VoiceOver is running, a blocking AppKit call will
+ // attempt to ascend the hierarchy. Don't fire AXMenuOpened if we don't yet
+ // have a window.
+ if (event_type == ax::mojom::Event::kMenuPopupStart) {
+ if (auto* node = ui::AXPlatformNode::FromNativeViewAccessible(target)) {
+ if (!node->GetDelegate()->GetNSWindow())
+ return;
+ }
+ }
+
NSString* notification =
[AXPlatformNodeCocoa nativeNotificationFromAXEvent:event_type];
if (notification)
@@ -850,14 +857,14 @@ bool IsAXSetter(SEL selector) {
}
- (NSNumber*)AXARIAPosInSet {
- base::Optional<int> posInSet = _node->GetPosInSet();
+ absl::optional<int> posInSet = _node->GetPosInSet();
if (!posInSet)
return nil;
return @(*posInSet);
}
- (NSNumber*)AXARIASetSize {
- base::Optional<int> setSize = _node->GetSetSize();
+ absl::optional<int> setSize = _node->GetSetSize();
if (!setSize)
return nil;
return @(*setSize);
@@ -872,15 +879,15 @@ bool IsAXSetter(SEL selector) {
}
- (NSValue*)AXSelectedTextRange {
- // Selection might not be supported. Return (NSRange){0,0} in that case.
int start = 0, end = 0;
- if (_node->IsPlainTextField()) {
- start = _node->GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart);
- end = _node->GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd);
+ if (_node->IsAtomicTextField() &&
+ _node->GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart, &start) &&
+ _node->GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, &end)) {
+ // NSRange cannot represent the direction the text was selected in.
+ return [NSValue valueWithRange:{std::min(start, end), abs(end - start)}];
}
- // NSRange cannot represent the direction the text was selected in.
- return [NSValue valueWithRange:{std::min(start, end), abs(end - start)}];
+ return [NSValue valueWithRange:NSMakeRange(0, 0)];
}
- (NSNumber*)AXNumberOfCharacters {
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_textchildprovider_win_unittest.cc b/chromium/ui/accessibility/platform/ax_platform_node_textchildprovider_win_unittest.cc
index 4e0c8742d09..b621d94d583 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_textchildprovider_win_unittest.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_textchildprovider_win_unittest.cc
@@ -105,6 +105,7 @@ class AXPlatformNodeTextChildProviderTest : public AXPlatformNodeWinTest {
InitITextChildProvider(text_child_of_text_node,
text_child_of_text_text_provider_raw_,
text_child_of_text_text_child_provider_);
+ AXPlatformNodeWinTest::SetUp();
}
void InitITextChildProvider(
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_textprovider_win.h b/chromium/ui/accessibility/platform/ax_platform_node_textprovider_win.h
index 74984eb2a87..b8c2c61776c 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_textprovider_win.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_textprovider_win.h
@@ -7,7 +7,6 @@
#include <wrl/client.h>
-#include <string>
#include "ui/accessibility/platform/ax_platform_node_win.h"
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc b/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
index ebe60bd8008..5b7d8f413ff 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
@@ -161,7 +161,7 @@ HRESULT AXPlatformNodeTextRangeProviderWin::CompareEndpoints(
? other_provider->start()
: other_provider->end();
- base::Optional<int> comparison =
+ absl::optional<int> comparison =
this_provider_endpoint->CompareTo(*other_provider_endpoint);
if (!comparison)
return UIA_E_INVALIDOPERATION;
@@ -532,13 +532,13 @@ HRESULT AXPlatformNodeTextRangeProviderWin::GetAttributeValue(
const bool at_end_leaf_text_anchor =
it->anchor_id() == end_leaf_text_position->anchor_id() &&
it->tree_id() == end_leaf_text_position->tree_id();
- const base::Optional<int> start_offset =
- it->IsTextPosition() ? base::make_optional(it->text_offset())
- : base::nullopt;
- const base::Optional<int> end_offset =
+ const absl::optional<int> start_offset =
+ it->IsTextPosition() ? absl::make_optional(it->text_offset())
+ : absl::nullopt;
+ const absl::optional<int> end_offset =
at_end_leaf_text_anchor
- ? base::make_optional(end_leaf_text_position->text_offset())
- : base::nullopt;
+ ? absl::make_optional(end_leaf_text_position->text_offset())
+ : absl::nullopt;
HRESULT hr = platform_node->GetTextAttributeValue(
attribute_id, start_offset, end_offset, &current_value);
if (FAILED(hr))
@@ -788,7 +788,7 @@ HRESULT AXPlatformNodeTextRangeProviderWin::MoveEndpointByUnitImpl(
// If the start was moved past the end, create a degenerate range with the end
// equal to the start; do the equivalent if the end moved past the start.
- base::Optional<int> endpoint_comparison =
+ absl::optional<int> endpoint_comparison =
AXNodeRange::CompareEndpoints(start().get(), end().get());
DCHECK(endpoint_comparison.has_value());
@@ -1243,8 +1243,8 @@ void AXPlatformNodeTextRangeProviderWin::NormalizeTextRange(
// the TextPattern must be preserved so that the UIA client can handle
// scenarios such as determining which characters were deleted. So
// normalization must be bypassed.
- if (HasCaretOrSelectionInPlainTextField(start) ||
- HasCaretOrSelectionInPlainTextField(end)) {
+ if (HasCaretOrSelectionInAtomicTextField(start) ||
+ HasCaretOrSelectionInAtomicTextField(end)) {
return;
}
@@ -1395,28 +1395,36 @@ AXPlatformNodeTextRangeProviderWin::GetLowestAccessibleCommonPlatformNode()
return platform_node->GetLowestAccessibleElement();
}
-bool AXPlatformNodeTextRangeProviderWin::HasCaretOrSelectionInPlainTextField(
+bool AXPlatformNodeTextRangeProviderWin::HasCaretOrSelectionInAtomicTextField(
const AXPositionInstance& position) const {
- // This condition fixes issues when the caret is inside a plain text field,
- // but causes more issues when used inside of a rich text field. For this
- // reason, if we have a caret or a selection inside of an editable node,
- // restrict this to a plain text field as we gain nothing from using it in a
- // rich text field.
+ // This condition fixes issues when the caret is inside an atomic text field,
+ // but causes more issues when used inside of a non-atomic text field. An
+ // atomic text field does not expose its internal implementation to assistive
+ // software, appearing as a single leaf node in the accessibility tree. It
+ // includes <input>, <textarea> and Views-based text fields.
//
- // Note that "AXPlatformNodeDelegate::IsDescendantOfPlainTextField()" also
- // returns true when this node is at the root of a plain text field, i.e. the
- // node could either be a descendant or it could be equivalent to the field's
- // root node.
+ // For this reason, if we have a caret or a selection inside of an editable
+ // node, restrict this to an atomic text field as we gain nothing from using
+ // it in a non-atomic text field.
+ //
+ // Note that "AXPlatformNodeDelegate::IsDescendantOfAtomicTextField()" also
+ // returns true when this node is at the root of an atomic text field, i.e.
+ // the node could either be a descendant or it could be equivalent to the
+ // field's root node. An atomic text field does not expose its internal
+ // implementation to assistive software, appearing as a single leaf node in
+ // the accessibility tree. It includes <input>, <textarea> and Views-based
+ // text fields.
AXPlatformNodeDelegate* delegate = GetDelegate(position.get());
return delegate && delegate->HasVisibleCaretOrSelection() &&
- delegate->IsDescendantOfPlainTextField();
+ delegate->IsDescendantOfAtomicTextField();
}
// static
bool AXPlatformNodeTextRangeProviderWin::TextAttributeIsArrayType(
TEXTATTRIBUTEID attribute_id) {
// https://docs.microsoft.com/en-us/windows/win32/winauto/uiauto-textattribute-ids
- return attribute_id == UIA_AnnotationTypesAttributeId ||
+ return attribute_id == UIA_AnnotationObjectsAttributeId ||
+ attribute_id == UIA_AnnotationTypesAttributeId ||
attribute_id == UIA_TabsAttributeId;
}
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h b/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h
index 35e1096afaf..b814aed95bb 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h
@@ -178,7 +178,7 @@ class AX_EXPORT __declspec(uuid("3071e40d-a10d-45ff-a59f-6e8e1138e2c1"))
void RemoveFocusFromPreviousSelectionIfNeeded(
const AXNodeRange& new_selection);
AXPlatformNodeWin* GetLowestAccessibleCommonPlatformNode() const;
- bool HasCaretOrSelectionInPlainTextField(
+ bool HasCaretOrSelectionInAtomicTextField(
const AXPositionInstance& position) const;
void SetStart(AXPositionInstance start);
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc b/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
index 4224b793ead..ffe744e913e 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
@@ -39,6 +39,44 @@ namespace ui {
#define ASSERT_UIA_NOTSUPPORTED(expr) \
ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED), (expr))
+#define EXPECT_UIA_GETPROPERTYVALUE_EQ(node, property_id, expected) \
+ { \
+ base::win::ScopedVariant expectedVariant(expected); \
+ ASSERT_EQ(VT_BSTR, expectedVariant.type()); \
+ ASSERT_NE(nullptr, expectedVariant.ptr()->bstrVal); \
+ base::win::ScopedVariant actual; \
+ ASSERT_HRESULT_SUCCEEDED( \
+ node->GetPropertyValue(property_id, actual.Receive())); \
+ ASSERT_EQ(VT_BSTR, actual.type()); \
+ ASSERT_NE(nullptr, actual.ptr()->bstrVal); \
+ EXPECT_STREQ(expectedVariant.ptr()->bstrVal, actual.ptr()->bstrVal); \
+ }
+
+#define EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(array, element_test_property_id, \
+ expected_property_values) \
+ { \
+ ASSERT_EQ(1u, SafeArrayGetDim(array)); \
+ LONG array_lower_bound; \
+ ASSERT_HRESULT_SUCCEEDED( \
+ SafeArrayGetLBound(array, 1, &array_lower_bound)); \
+ LONG array_upper_bound; \
+ ASSERT_HRESULT_SUCCEEDED( \
+ SafeArrayGetUBound(array, 1, &array_upper_bound)); \
+ IUnknown** array_data; \
+ ASSERT_HRESULT_SUCCEEDED( \
+ ::SafeArrayAccessData(array, reinterpret_cast<void**>(&array_data))); \
+ size_t count = array_upper_bound - array_lower_bound + 1; \
+ ASSERT_EQ(expected_property_values.size(), count); \
+ for (size_t i = 0; i < count; ++i) { \
+ ComPtr<IRawElementProviderSimple> element; \
+ ASSERT_HRESULT_SUCCEEDED( \
+ array_data[i]->QueryInterface(IID_PPV_ARGS(&element))); \
+ EXPECT_UIA_GETPROPERTYVALUE_EQ(element, element_test_property_id, \
+ expected_property_values[i].c_str()); \
+ } \
+ ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(array)); \
+ }
+
#define EXPECT_UIA_SAFEARRAY_EQ(safearray, expected_property_values) \
{ \
using T = typename decltype(expected_property_values)::value_type; \
@@ -379,7 +417,8 @@ class AXPlatformNodeTextRangeProviderTest : public ui::AXPlatformNodeWinTest {
text_field.role = ax::mojom::Role::kTextField;
text_field.AddState(ax::mojom::State::kEditable);
- text_field.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot, true);
+ text_field.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag,
+ "input");
text_field.SetValue(ALL_TEXT);
text_field.AddIntListAttribute(
ax::mojom::IntListAttribute::kCachedLineStarts,
@@ -2863,6 +2902,9 @@ TEST_F(AXPlatformNodeTextRangeProviderTest,
ui::AXNodeData text_input_data;
text_input_data.id = 4;
text_input_data.role = ax::mojom::Role::kTextField;
+ text_input_data.AddState(ax::mojom::State::kEditable);
+ text_input_data.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag,
+ "input");
ui::AXNodeData group2_data;
group2_data.id = 5;
@@ -2883,6 +2925,7 @@ TEST_F(AXPlatformNodeTextRangeProviderTest,
ui::AXNodeData empty_text_data;
empty_text_data.id = 7;
empty_text_data.role = ax::mojom::Role::kStaticText;
+ empty_text_data.AddState(ax::mojom::State::kEditable);
text_content = "";
empty_text_data.SetName(text_content);
ComputeWordBoundariesOffsets(text_content, word_start_offsets,
@@ -3240,11 +3283,14 @@ TEST_F(AXPlatformNodeTextRangeProviderTest,
ui::AXNodeData search_box;
search_box.id = 13;
search_box.role = ax::mojom::Role::kSearchBox;
+ search_box.AddState(ax::mojom::State::kEditable);
+ search_box.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag, "input");
paragraph_data.child_ids.push_back(search_box.id);
ui::AXNodeData search_text;
search_text.id = 14;
search_text.role = ax::mojom::Role::kStaticText;
+ search_text.AddState(ax::mojom::State::kEditable);
search_text.SetName("placeholder");
search_box.child_ids.push_back(search_text.id);
@@ -3634,8 +3680,8 @@ TEST_F(AXPlatformNodeTextRangeProviderTest, TestITextRangeProviderGetChildren) {
generic_container_2.role = ax::mojom::Role::kGenericContainer;
generic_container_2.AddState(ax::mojom::State::kEditable);
generic_container_2.AddState(ax::mojom::State::kRichlyEditable);
- generic_container_2.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot,
- true);
+ generic_container_2.AddBoolAttribute(
+ ax::mojom::BoolAttribute::kContentEditableRoot, true);
generic_container_2.child_ids = {static_text_3.id, static_text_6.id,
static_text_7.id, button_8.id};
@@ -3654,7 +3700,8 @@ TEST_F(AXPlatformNodeTextRangeProviderTest, TestITextRangeProviderGetChildren) {
button_8.role = ax::mojom::Role::kButton;
// Hack: The kEditableRoot attribute is needed to get a text range provider
// located on this element (see AXPlatformNodeWin::GetPatternProvider).
- button_8.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot, true);
+ button_8.AddBoolAttribute(ax::mojom::BoolAttribute::kContentEditableRoot,
+ true);
// When kEditableRoot is set, kEditable is also expected.
button_8.AddState(ax::mojom::State::kEditable);
button_8.child_ids = {image_9.id, static_text_10.id};
@@ -3930,8 +3977,8 @@ TEST_F(AXPlatformNodeTextRangeProviderTest,
input_text_data.AddIntAttribute(ax::mojom::IntAttribute::kBackgroundColor,
0xFFADBEEFU);
input_text_data.AddIntAttribute(ax::mojom::IntAttribute::kColor, 0xFFADC0DEU);
- input_text_data.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot,
- true);
+ input_text_data.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag,
+ "input");
input_text_data.SetName("placeholder");
input_text_data.child_ids = {13};
@@ -3948,14 +3995,15 @@ TEST_F(AXPlatformNodeTextRangeProviderTest,
input_text_data2.id = 14;
input_text_data2.role = ax::mojom::Role::kTextField;
input_text_data2.AddState(ax::mojom::State::kEditable);
+ input_text_data2.SetRestriction(ax::mojom::Restriction::kDisabled);
input_text_data2.AddStringAttribute(ax::mojom::StringAttribute::kPlaceholder,
"placeholder2");
input_text_data2.AddIntAttribute(ax::mojom::IntAttribute::kBackgroundColor,
0xFFADBEEFU);
input_text_data2.AddIntAttribute(ax::mojom::IntAttribute::kColor,
0xFFADC0DEU);
- input_text_data2.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot,
- true);
+ input_text_data2.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag,
+ "input");
input_text_data2.SetName("foo");
input_text_data2.child_ids = {15};
@@ -4151,7 +4199,7 @@ TEST_F(AXPlatformNodeTextRangeProviderTest,
UIA_IsReadOnlyAttributeId, expected_variant);
expected_variant.Reset();
- expected_variant.Set(false);
+ expected_variant.Set(true);
EXPECT_UIA_TEXTATTRIBUTE_EQ(placeholder_text_range_provider2,
UIA_IsReadOnlyAttributeId, expected_variant);
expected_variant.Reset();
@@ -4352,6 +4400,289 @@ TEST_F(AXPlatformNodeTextRangeProviderTest,
}
TEST_F(AXPlatformNodeTextRangeProviderTest,
+ TestITextRangeProviderGetAttributeValueAnnotationObjects) {
+ // rootWebArea id=1
+ // ++mark id=2 detailsIds=comment1 comment2 highlighted
+ // ++++staticText id=3 name="some text"
+ // ++comment id=4 name="comment 1"
+ // ++++staticText id=5 name="comment 1"
+ // ++comment id=6 name="comment 2"
+ // ++++staticText id=7 name="comment 2"
+ // ++mark id=8 name="highlighted"
+ // ++++staticText id=9 name="highlighted"
+
+ AXNodeData root;
+ AXNodeData annotation_target;
+ AXNodeData some_text;
+ AXNodeData comment1;
+ AXNodeData comment1_text;
+ AXNodeData comment2;
+ AXNodeData comment2_text;
+ AXNodeData highlighted;
+ AXNodeData highlighted_text;
+
+ root.id = 1;
+ annotation_target.id = 2;
+ some_text.id = 3;
+ comment1.id = 4;
+ comment1_text.id = 5;
+ comment2.id = 6;
+ comment2_text.id = 7;
+ highlighted.id = 8;
+ highlighted_text.id = 9;
+
+ root.role = ax::mojom::Role::kRootWebArea;
+ root.SetName("root");
+ root.child_ids = {annotation_target.id, comment1.id, comment2.id,
+ highlighted.id};
+
+ annotation_target.role = ax::mojom::Role::kMark;
+ annotation_target.child_ids = {some_text.id};
+ annotation_target.AddIntListAttribute(
+ ax::mojom::IntListAttribute::kDetailsIds,
+ {comment1.id, comment2.id, highlighted.id});
+
+ some_text.role = ax::mojom::Role::kStaticText;
+ some_text.SetName("some text");
+
+ comment1.role = ax::mojom::Role::kComment;
+ comment1.SetName("comment 1");
+ comment1.child_ids = {comment1_text.id};
+
+ comment1_text.role = ax::mojom::Role::kStaticText;
+ comment1_text.SetName("comment 1");
+
+ comment2.role = ax::mojom::Role::kComment;
+ comment2.SetName("comment 2");
+ comment2.child_ids = {comment2_text.id};
+
+ comment2_text.role = ax::mojom::Role::kStaticText;
+ comment2_text.SetName("comment 2");
+
+ highlighted.role = ax::mojom::Role::kMark;
+ highlighted.SetName("highlighted");
+ highlighted.child_ids = {highlighted_text.id};
+
+ highlighted_text.role = ax::mojom::Role::kStaticText;
+ highlighted_text.SetName("highlighted");
+
+ ui::AXTreeUpdate update;
+ update.has_tree_data = true;
+ update.root_id = root.id;
+ update.nodes = {root, annotation_target, some_text,
+ comment1, comment1_text, comment2,
+ comment2_text, highlighted, highlighted_text};
+ update.tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID();
+
+ Init(update);
+
+ AXNode* root_node = GetRootAsAXNode();
+ AXNode* annotation_target_node = root_node->children()[0];
+ AXNode* comment1_node = root_node->children()[1];
+ AXNode* comment2_node = root_node->children()[2];
+ AXNode* highlighted_node = root_node->children()[3];
+
+ ComPtr<AXPlatformNodeTextRangeProviderWin> some_text_range_provider;
+
+ // Create a text range encapsulates |annotation_target_node| with content
+ // "some text".
+ // start: TextPosition, anchor_id=2, text_offset=0, annotated_text=<s>ome text
+ // end : TextPosition, anchor_id=2, text_offset=9, annotated_text=some text<>
+ AXPlatformNodeWin* owner = static_cast<AXPlatformNodeWin*>(
+ AXPlatformNodeFromNode(annotation_target_node));
+ CreateTextRangeProviderWin(
+ some_text_range_provider, owner, update.tree_data.tree_id,
+ /*start_anchor_id=*/annotation_target.id, /*start_offset=*/0,
+ /*start_affinity*/ ax::mojom::TextAffinity::kDownstream,
+ /*end_anchor_id=*/annotation_target.id, /*end_offset=*/9,
+ /*end_affinity*/ ax::mojom::TextAffinity::kDownstream);
+ ASSERT_NE(nullptr, some_text_range_provider.Get());
+ EXPECT_UIA_TEXTRANGE_EQ(some_text_range_provider, L"some text");
+
+ ComPtr<IRawElementProviderSimple> comment1_provider =
+ QueryInterfaceFromNode<IRawElementProviderSimple>(comment1_node);
+ ASSERT_NE(nullptr, comment1_provider.Get());
+ ComPtr<IRawElementProviderSimple> comment2_provider =
+ QueryInterfaceFromNode<IRawElementProviderSimple>(comment2_node);
+ ASSERT_NE(nullptr, comment2_provider.Get());
+ ComPtr<IRawElementProviderSimple> highlighted_provider =
+ QueryInterfaceFromNode<IRawElementProviderSimple>(highlighted_node);
+ ASSERT_NE(nullptr, highlighted_provider.Get());
+
+ ComPtr<IAnnotationProvider> annotation_provider;
+ int annotation_type;
+
+ // Validate |comment1_node| with Role::kComment supports IAnnotationProvider.
+ EXPECT_HRESULT_SUCCEEDED(comment1_provider->GetPatternProvider(
+ UIA_AnnotationPatternId, &annotation_provider));
+ ASSERT_NE(nullptr, annotation_provider.Get());
+ EXPECT_HRESULT_SUCCEEDED(
+ annotation_provider->get_AnnotationTypeId(&annotation_type));
+ EXPECT_EQ(AnnotationType_Comment, annotation_type);
+ annotation_provider.Reset();
+
+ // Validate |comment2_node| with Role::kComment supports IAnnotationProvider.
+ EXPECT_HRESULT_SUCCEEDED(comment2_provider->GetPatternProvider(
+ UIA_AnnotationPatternId, &annotation_provider));
+ ASSERT_NE(nullptr, annotation_provider.Get());
+ EXPECT_HRESULT_SUCCEEDED(
+ annotation_provider->get_AnnotationTypeId(&annotation_type));
+ EXPECT_EQ(AnnotationType_Comment, annotation_type);
+ annotation_provider.Reset();
+
+ // Validate |highlighted_node| with Role::kMark supports
+ // IAnnotationProvider.
+ EXPECT_HRESULT_SUCCEEDED(highlighted_provider->GetPatternProvider(
+ UIA_AnnotationPatternId, &annotation_provider));
+ ASSERT_NE(nullptr, annotation_provider.Get());
+ EXPECT_HRESULT_SUCCEEDED(
+ annotation_provider->get_AnnotationTypeId(&annotation_type));
+ EXPECT_EQ(AnnotationType_Highlighted, annotation_type);
+ annotation_provider.Reset();
+
+ base::win::ScopedVariant annotation_objects_variant;
+ EXPECT_HRESULT_SUCCEEDED(some_text_range_provider->GetAttributeValue(
+ UIA_AnnotationObjectsAttributeId, annotation_objects_variant.Receive()));
+ EXPECT_EQ(VT_UNKNOWN | VT_ARRAY, annotation_objects_variant.type());
+
+ std::vector<std::wstring> expected_names = {L"comment 1", L"comment 2",
+ L"highlighted"};
+ EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(V_ARRAY(annotation_objects_variant.ptr()),
+ UIA_NamePropertyId, expected_names);
+}
+
+TEST_F(AXPlatformNodeTextRangeProviderTest,
+ TestITextRangeProviderGetAttributeValueAnnotationObjectsMixed) {
+ // rootWebArea id=1
+ // ++mark id=2 detailsIds=comment
+ // ++++staticText id=3 name="some text"
+ // ++staticText id=4 name="read only" restriction=readOnly
+ // ++comment id=5 name="comment 1"
+ // ++++staticText id=6 name="comment 1"
+
+ AXNodeData root;
+ AXNodeData highlighted;
+ AXNodeData some_text;
+ AXNodeData readonly_text;
+ AXNodeData comment1;
+ AXNodeData comment1_text;
+
+ root.id = 1;
+ highlighted.id = 2;
+ some_text.id = 3;
+ readonly_text.id = 4;
+ comment1.id = 5;
+ comment1_text.id = 6;
+
+ root.role = ax::mojom::Role::kRootWebArea;
+ root.SetName("root");
+ root.child_ids = {highlighted.id, readonly_text.id, comment1.id};
+
+ highlighted.role = ax::mojom::Role::kMark;
+ highlighted.child_ids = {some_text.id};
+ highlighted.AddIntListAttribute(ax::mojom::IntListAttribute::kDetailsIds,
+ {comment1.id});
+
+ some_text.role = ax::mojom::Role::kStaticText;
+ some_text.SetName("some text");
+
+ readonly_text.role = ax::mojom::Role::kStaticText;
+ readonly_text.SetRestriction(ax::mojom::Restriction::kReadOnly);
+ readonly_text.SetName("read only");
+
+ comment1.role = ax::mojom::Role::kComment;
+ comment1.SetName("comment 1");
+ comment1.child_ids = {comment1_text.id};
+
+ comment1_text.role = ax::mojom::Role::kStaticText;
+ comment1_text.SetName("comment 1");
+
+ ui::AXTreeUpdate update;
+ update.has_tree_data = true;
+ update.root_id = root.id;
+ update.nodes = {root, highlighted, some_text,
+ readonly_text, comment1, comment1_text};
+ update.tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID();
+
+ Init(update);
+
+ AXNode* root_node = GetRootAsAXNode();
+ AXNode* highlighted_node = root_node->children()[0];
+ AXNode* readonly_text_node = root_node->children()[1];
+ AXNode* comment1_node = root_node->children()[2];
+
+ // Create a text range encapsulates |highlighted_node| with content
+ // "some text".
+ // start: TextPosition, anchor_id=2, text_offset=0, annotated_text=<s>ome text
+ // end : TextPosition, anchor_id=2, text_offset=9, annotated_text=some text<>
+ ComPtr<AXPlatformNodeTextRangeProviderWin> some_text_range_provider;
+ AXPlatformNodeWin* owner =
+ static_cast<AXPlatformNodeWin*>(AXPlatformNodeFromNode(highlighted_node));
+ CreateTextRangeProviderWin(
+ some_text_range_provider, owner, update.tree_data.tree_id,
+ /*start_anchor_id=*/highlighted.id, /*start_offset=*/0,
+ /*start_affinity*/ ax::mojom::TextAffinity::kDownstream,
+ /*end_anchor_id=*/highlighted.id, /*end_offset=*/9,
+ /*end_affinity*/ ax::mojom::TextAffinity::kDownstream);
+ ASSERT_NE(nullptr, some_text_range_provider.Get());
+ EXPECT_UIA_TEXTRANGE_EQ(some_text_range_provider, L"some text");
+
+ ComPtr<ITextRangeProvider> readonly_text_range_provider;
+ GetTextRangeProviderFromTextNode(readonly_text_range_provider,
+ readonly_text_node);
+ ASSERT_NE(nullptr, readonly_text_range_provider.Get());
+
+ ComPtr<IRawElementProviderSimple> comment1_provider =
+ QueryInterfaceFromNode<IRawElementProviderSimple>(comment1_node);
+ ASSERT_NE(nullptr, comment1_provider.Get());
+
+ ComPtr<IAnnotationProvider> annotation_provider;
+ int annotation_type;
+ base::win::ScopedVariant expected_variant;
+
+ // Validate |comment1_node| with Role::kComment supports IAnnotationProvider.
+ EXPECT_HRESULT_SUCCEEDED(comment1_provider->GetPatternProvider(
+ UIA_AnnotationPatternId, &annotation_provider));
+ ASSERT_NE(nullptr, annotation_provider.Get());
+ EXPECT_HRESULT_SUCCEEDED(
+ annotation_provider->get_AnnotationTypeId(&annotation_type));
+ EXPECT_EQ(AnnotationType_Comment, annotation_type);
+ annotation_provider.Reset();
+
+ // Validate text range "some text" supports AnnotationObjectsAttribute.
+ EXPECT_HRESULT_SUCCEEDED(some_text_range_provider->GetAttributeValue(
+ UIA_AnnotationObjectsAttributeId, expected_variant.Receive()));
+ EXPECT_EQ(VT_UNKNOWN | VT_ARRAY, expected_variant.type());
+
+ std::vector<std::wstring> expected_names = {L"comment 1"};
+ EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(V_ARRAY(expected_variant.ptr()),
+ UIA_NamePropertyId, expected_names);
+ expected_variant.Reset();
+
+ // Validate text range "read only" supports IsReadOnlyAttribute.
+ // Use IsReadOnly on text range "read only" as a second property in order to
+ // test the "mixed" property in the following section.
+ expected_variant.Set(true);
+ EXPECT_UIA_TEXTATTRIBUTE_EQ(readonly_text_range_provider,
+ UIA_IsReadOnlyAttributeId, expected_variant);
+
+ // Validate text range "some textread only" returns mixed attribute.
+ // start: TextPosition, anchor_id=2, text_offset=0, annotated_text=<s>ome text
+ // end : TextPosition, anchor_id=3, text_offset=9, annotated_text=read only<>
+ ComPtr<AXPlatformNodeTextRangeProviderWin> mixed_text_range_provider;
+ CreateTextRangeProviderWin(
+ mixed_text_range_provider, owner, update.tree_data.tree_id,
+ /*start_anchor_id=*/some_text.id, /*start_offset=*/0,
+ /*start_affinity*/ ax::mojom::TextAffinity::kDownstream,
+ /*end_anchor_id=*/readonly_text.id, /*end_offset=*/9,
+ /*end_affinity*/ ax::mojom::TextAffinity::kDownstream);
+
+ EXPECT_UIA_TEXTRANGE_EQ(mixed_text_range_provider, L"some textread only");
+ EXPECT_UIA_TEXTATTRIBUTE_MIXED(mixed_text_range_provider,
+ UIA_AnnotationObjectsAttributeId);
+}
+
+TEST_F(AXPlatformNodeTextRangeProviderTest,
TestITextRangeProviderGetAttributeValueNotSupported) {
ui::AXNodeData root_data;
root_data.id = 1;
@@ -4389,8 +4720,6 @@ TEST_F(AXPlatformNodeTextRangeProviderTest,
EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider,
UIA_AnimationStyleAttributeId);
EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider,
- UIA_AnnotationObjectsAttributeId);
- EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider,
UIA_BeforeParagraphSpacingAttributeId);
EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider,
UIA_CapStyleAttributeId);
@@ -5336,8 +5665,8 @@ TEST_F(AXPlatformNodeTextRangeProviderTest,
tree_update.nodes[1].AddState(ax::mojom::State::kIgnored);
tree_update.nodes[1].AddState(ax::mojom::State::kEditable);
tree_update.nodes[1].AddState(ax::mojom::State::kRichlyEditable);
- tree_update.nodes[1].AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot,
- true);
+ tree_update.nodes[1].AddBoolAttribute(
+ ax::mojom::BoolAttribute::kContentEditableRoot, true);
tree_update.nodes[1].role = ax::mojom::Role::kGenericContainer;
tree_update.nodes[2].id = 3;
@@ -5784,7 +6113,6 @@ TEST_F(AXPlatformNodeTextRangeProviderTest,
text_field_4.role = ax::mojom::Role::kTextField;
text_field_4.AddState(ax::mojom::State::kEditable);
- text_field_4.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot, true);
text_field_4.child_ids = {generic_container_5.id};
text_field_4.SetValue("3.14");
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_unittest.cc b/chromium/ui/accessibility/platform/ax_platform_node_unittest.cc
index 1cc881f5af8..99b9dd5c35d 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_unittest.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_unittest.cc
@@ -65,6 +65,8 @@ AXTreeUpdate AXPlatformNodeTest::BuildTextField() {
text_field_node.id = 1;
text_field_node.role = ax::mojom::Role::kTextField;
text_field_node.AddState(ax::mojom::State::kEditable);
+ text_field_node.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag,
+ "input");
text_field_node.SetValue("How now brown cow.");
AXTreeUpdate update;
@@ -80,6 +82,8 @@ AXTreeUpdate AXPlatformNodeTest::BuildTextFieldWithSelectionRange(
text_field_node.id = 1;
text_field_node.role = ax::mojom::Role::kTextField;
text_field_node.AddState(ax::mojom::State::kEditable);
+ text_field_node.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag,
+ "input");
text_field_node.AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, true);
text_field_node.AddIntAttribute(ax::mojom::IntAttribute::kTextSelStart,
start);
@@ -96,9 +100,10 @@ AXTreeUpdate AXPlatformNodeTest::BuildContentEditable() {
AXNodeData content_editable_node;
content_editable_node.id = 1;
content_editable_node.role = ax::mojom::Role::kGroup;
+ content_editable_node.AddState(ax::mojom::State::kEditable);
content_editable_node.AddState(ax::mojom::State::kRichlyEditable);
content_editable_node.AddBoolAttribute(
- ax::mojom::BoolAttribute::kEditableRoot, true);
+ ax::mojom::BoolAttribute::kContentEditableRoot, true);
content_editable_node.SetValue("How now brown cow.");
AXTreeUpdate update;
@@ -113,11 +118,12 @@ AXTreeUpdate AXPlatformNodeTest::BuildContentEditableWithSelectionRange(
AXNodeData content_editable_node;
content_editable_node.id = 1;
content_editable_node.role = ax::mojom::Role::kGroup;
+ content_editable_node.AddState(ax::mojom::State::kEditable);
content_editable_node.AddState(ax::mojom::State::kRichlyEditable);
content_editable_node.AddBoolAttribute(ax::mojom::BoolAttribute::kSelected,
true);
content_editable_node.AddBoolAttribute(
- ax::mojom::BoolAttribute::kEditableRoot, true);
+ ax::mojom::BoolAttribute::kContentEditableRoot, true);
content_editable_node.SetValue("How now brown cow.");
AXTreeUpdate update;
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_unittest.h b/chromium/ui/accessibility/platform/ax_platform_node_unittest.h
index d004a0585eb..b71bc5a5732 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_unittest.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_unittest.h
@@ -15,7 +15,7 @@
namespace ui {
-class AXPlatformNodeTest : public testing::Test, public TestAXTreeManager {
+class AXPlatformNodeTest : public ::testing::Test, public TestAXTreeManager {
public:
AXPlatformNodeTest();
~AXPlatformNodeTest() override;
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_win.cc b/chromium/ui/accessibility/platform/ax_platform_node_win.cc
index 62680090cd7..d62db41ef6d 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_win.cc
@@ -283,6 +283,22 @@ GetWinAccessibilityAPIUsageObserverList() {
return g_win_accessibility_api_usage_observer_list.Get();
}
+// Used to simplify calling StartFiringUIAEvents and EndFiringEvents
+WinAccessibilityAPIUsageScopedUIAEventsNotifier::
+ WinAccessibilityAPIUsageScopedUIAEventsNotifier() {
+ for (ui::WinAccessibilityAPIUsageObserver& observer :
+ ui::GetWinAccessibilityAPIUsageObserverList()) {
+ observer.StartFiringUIAEvents();
+ }
+}
+WinAccessibilityAPIUsageScopedUIAEventsNotifier::
+ ~WinAccessibilityAPIUsageScopedUIAEventsNotifier() {
+ for (ui::WinAccessibilityAPIUsageObserver& observer :
+ ui::GetWinAccessibilityAPIUsageObserverList()) {
+ observer.EndFiringUIAEvents();
+ }
+}
+
//
// AXPlatformNode::Create
//
@@ -457,7 +473,7 @@ SAFEARRAY* AXPlatformNodeWin::CreateUIAControllerForArray() {
std::vector<AXPlatformNodeWin*> platform_node_list =
CreatePlatformNodeVectorFromRelationIdVector(relation_id_list);
- if (GetActivePopupAxUniqueId() != base::nullopt) {
+ if (GetActivePopupAxUniqueId() != absl::nullopt) {
AXPlatformNodeWin* view_popup_node_win = static_cast<AXPlatformNodeWin*>(
GetFromUniqueId(GetActivePopupAxUniqueId().value()));
@@ -644,7 +660,7 @@ void AXPlatformNodeWin::NotifyAccessibilityEvent(ax::mojom::Event event_type) {
UpdateComputedHypertext();
}
- if (base::Optional<DWORD> native_event = MojoEventToMSAAEvent(event_type)) {
+ if (absl::optional<DWORD> native_event = MojoEventToMSAAEvent(event_type)) {
HWND hwnd = GetDelegate()->GetTargetForNativeAccessibilityEvent();
if (!hwnd)
return;
@@ -652,7 +668,7 @@ void AXPlatformNodeWin::NotifyAccessibilityEvent(ax::mojom::Event event_type) {
::NotifyWinEvent((*native_event), hwnd, OBJID_CLIENT, -GetUniqueId());
}
- if (base::Optional<PROPERTYID> uia_property =
+ if (absl::optional<PROPERTYID> uia_property =
MojoEventToUIAProperty(event_type)) {
// For this event, we're not concerned with the old value.
base::win::ScopedVariant old_value;
@@ -664,7 +680,7 @@ void AXPlatformNodeWin::NotifyAccessibilityEvent(ax::mojom::Event event_type) {
new_value);
}
- if (base::Optional<EVENTID> uia_event = MojoEventToUIAEvent(event_type))
+ if (absl::optional<EVENTID> uia_event = MojoEventToUIAEvent(event_type))
::UiaRaiseAutomationEvent(this, (*uia_event));
// Keep track of objects that are a target of an alert event.
@@ -1396,7 +1412,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_attributes(BSTR* attributes) {
IFACEMETHODIMP AXPlatformNodeWin::get_indexInParent(LONG* index_in_parent) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_INDEX_IN_PARENT);
COM_OBJECT_VALIDATE_1_ARG(index_in_parent);
- base::Optional<int> index = GetIndexInParent();
+ absl::optional<int> index = GetIndexInParent();
if (!index.has_value())
return E_FAIL;
@@ -1760,6 +1776,104 @@ IFACEMETHODIMP AXPlatformNodeWin::GetIAccessiblePair(IAccessible** accessible,
}
//
+// IAnnotationProvider methods.
+//
+
+IFACEMETHODIMP AXPlatformNodeWin::get_AnnotationTypeId(int* type_id) {
+ WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_ANNOTATION_GET_ANNOTATIONTYPEID);
+ UIA_VALIDATE_CALL_1_ARG(type_id);
+
+ *type_id = GetAnnotationTypeImpl();
+ return S_OK;
+}
+
+IFACEMETHODIMP AXPlatformNodeWin::get_AnnotationTypeName(BSTR* type_name) {
+ WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_ANNOTATION_GET_ANNOTATIONTYPENAME);
+ UIA_VALIDATE_CALL_1_ARG(type_name);
+
+ // According to UIA spec, for well known AnnotationType, we do not need to
+ // implement the type name, since UI Automation can provide a default name, so
+ // we do not set |type_name|.
+ // But for unknown type, we should provide a name, so we set |type_name| to
+ // the localized role description.
+ // https://docs.microsoft.com/en-us/windows/win32/winauto/uiauto-implementingannotation
+ if (AnnotationType_Unknown == GetAnnotationTypeImpl())
+ *type_name = SysAllocString(base::as_wcstr(GetRoleDescription()));
+
+ return S_OK;
+}
+
+IFACEMETHODIMP AXPlatformNodeWin::get_Author(BSTR* author) {
+ WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_ANNOTATION_GET_AUTHOR);
+ UIA_VALIDATE_CALL_1_ARG(author);
+ // This method is optional, and currently does not have a mapping. So we
+ // return S_OK with empty string.
+ *author = SysAllocString(L"");
+ return S_OK;
+}
+
+IFACEMETHODIMP AXPlatformNodeWin::get_DateTime(BSTR* date_time) {
+ WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_ANNOTATION_GET_DATETIME);
+ UIA_VALIDATE_CALL_1_ARG(date_time);
+ // This method is optional, and currently does not have a mapping. So we
+ // return S_OK with empty string.
+ *date_time = SysAllocString(L"");
+ return S_OK;
+}
+
+IFACEMETHODIMP AXPlatformNodeWin::get_Target(
+ IRawElementProviderSimple** target) {
+ WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_ANNOTATION_GET_TARGET);
+ UIA_VALIDATE_CALL_1_ARG(target);
+ std::set<AXPlatformNode*> reverse_relations =
+ GetDelegate()->GetReverseRelations(
+ ax::mojom::IntListAttribute::kDetailsIds);
+
+ // If there is no reverse relation target, IAnnotationProvider
+ // should not be exposed in the first place.
+ DCHECK(reverse_relations.size() > 0);
+ AXPlatformNodeWin* target_node;
+ auto iter = reverse_relations.begin();
+ target_node = static_cast<AXPlatformNodeWin*>(*iter);
+
+ // Since this method is expected to return only one target, if the node has
+ // multiple targets, we default to return the first one.
+ // Since |reverse_relations| does not guarantee the order of the nodes. We
+ // have to compare the nodes to find the first target node.
+ ++iter;
+ while (iter != reverse_relations.end()) {
+ AXPlatformNodeWin* lhs = static_cast<AXPlatformNodeWin*>(*iter);
+ if (lhs->CompareTo(*target_node) < 0)
+ target_node = lhs;
+ ++iter;
+ }
+
+ return target_node->QueryInterface(IID_PPV_ARGS(target));
+}
+
+int AXPlatformNodeWin::GetAnnotationTypeImpl() const {
+ switch (GetData().role) {
+ case ax::mojom::Role::kComment:
+ return AnnotationType_Comment;
+ case ax::mojom::Role::kDocEndnote:
+ return AnnotationType_Endnote;
+ case ax::mojom::Role::kDocFootnote:
+ return AnnotationType_Footnote;
+ case ax::mojom::Role::kMark:
+ return AnnotationType_Highlighted;
+ case ax::mojom::Role::kGroup:
+ case ax::mojom::Role::kRegion: {
+ if (DescendantHasComment(this))
+ return AnnotationType_Comment;
+
+ FALLTHROUGH;
+ }
+ default:
+ return AnnotationType_Unknown;
+ }
+}
+
+//
// IExpandCollapseProvider implementation.
//
@@ -1835,7 +1949,13 @@ IFACEMETHODIMP AXPlatformNodeWin::get_ExpandCollapseState(
IFACEMETHODIMP AXPlatformNodeWin::get_Column(int* result) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GRIDITEM_GET_COLUMN);
UIA_VALIDATE_CALL_1_ARG(result);
- base::Optional<int> column = GetTableColumn();
+
+ absl::optional<int> column;
+ if (HasIntAttribute(ax::mojom::IntAttribute::kAriaCellColumnIndex))
+ column = GetDelegate()->GetTableCellAriaColIndex();
+ else
+ column = GetTableColumn();
+
if (!column)
return E_FAIL;
*result = *column;
@@ -1845,7 +1965,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_Column(int* result) {
IFACEMETHODIMP AXPlatformNodeWin::get_ColumnSpan(int* result) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GRIDITEM_GET_COLUMNSPAN);
UIA_VALIDATE_CALL_1_ARG(result);
- base::Optional<int> column_span = GetTableColumnSpan();
+ absl::optional<int> column_span = GetTableColumnSpan();
if (!column_span)
return E_FAIL;
*result = *column_span;
@@ -1870,7 +1990,13 @@ IFACEMETHODIMP AXPlatformNodeWin::get_ContainingGrid(
IFACEMETHODIMP AXPlatformNodeWin::get_Row(int* result) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GRIDITEM_GET_ROW);
UIA_VALIDATE_CALL_1_ARG(result);
- base::Optional<int> row = GetTableRow();
+
+ absl::optional<int> row;
+ if (HasIntAttribute(ax::mojom::IntAttribute::kAriaCellRowIndex))
+ row = GetDelegate()->GetTableCellAriaRowIndex();
+ else
+ row = GetTableRow();
+
if (!row)
return E_FAIL;
*result = *row;
@@ -1880,7 +2006,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_Row(int* result) {
IFACEMETHODIMP AXPlatformNodeWin::get_RowSpan(int* result) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GRIDITEM_GET_ROWSPAN);
UIA_VALIDATE_CALL_1_ARG(result);
- base::Optional<int> row_span = GetTableRowSpan();
+ absl::optional<int> row_span = GetTableRowSpan();
if (!row_span)
return E_FAIL;
*result = *row_span;
@@ -1911,7 +2037,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_RowCount(int* result) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GRID_GET_ROWCOUNT);
UIA_VALIDATE_CALL_1_ARG(result);
- base::Optional<int> row_count = GetTableAriaRowCount();
+ absl::optional<int> row_count = GetTableAriaRowCount();
if (!row_count)
row_count = GetTableRowCount();
@@ -1925,7 +2051,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_ColumnCount(int* result) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GRID_GET_COLUMNCOUNT);
UIA_VALIDATE_CALL_1_ARG(result);
- base::Optional<int> column_count = GetTableAriaColumnCount();
+ absl::optional<int> column_count = GetTableAriaColumnCount();
if (!column_count)
column_count = GetTableColumnCount();
@@ -2234,7 +2360,7 @@ IFACEMETHODIMP AXPlatformNodeWin::GetColumnHeaderItems(SAFEARRAY** result) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TABLEITEM_GETCOLUMNHEADERITEMS);
UIA_VALIDATE_CALL_1_ARG(result);
- base::Optional<int> column = GetTableColumn();
+ absl::optional<int> column = GetTableColumn();
if (!column)
return E_FAIL;
@@ -2252,7 +2378,7 @@ IFACEMETHODIMP AXPlatformNodeWin::GetRowHeaderItems(SAFEARRAY** result) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TABLEITEM_GETROWHEADERITEMS);
UIA_VALIDATE_CALL_1_ARG(result);
- base::Optional<int> row = GetTableRow();
+ absl::optional<int> row = GetTableRow();
if (!row)
return E_FAIL;
@@ -2582,7 +2708,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_childIndex(LONG row,
if (!cell)
return E_INVALIDARG;
- base::Optional<int> index = cell->GetTableCellIndex();
+ absl::optional<int> index = cell->GetTableCellIndex();
if (!index)
return E_FAIL;
@@ -2596,7 +2722,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_columnDescription(LONG column,
COM_OBJECT_VALIDATE_1_ARG(description);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> columns = GetTableColumnCount();
+ absl::optional<int> columns = GetTableColumnCount();
if (!columns)
return E_FAIL;
@@ -2639,7 +2765,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_columnExtentAt(LONG row,
if (!cell)
return E_INVALIDARG;
- base::Optional<int> column_span = cell->GetTableColumnSpan();
+ absl::optional<int> column_span = cell->GetTableColumnSpan();
if (!column_span)
return E_FAIL;
*n_columns_spanned = LONG{*column_span};
@@ -2667,7 +2793,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_columnIndex(LONG cell_index,
if (!cell)
return E_INVALIDARG;
- base::Optional<int> cell_column = cell->GetTableColumn();
+ absl::optional<int> cell_column = cell->GetTableColumn();
if (!cell_column)
return E_FAIL;
*column_index = LONG{*cell_column};
@@ -2678,7 +2804,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_nColumns(LONG* column_count) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_N_COLUMNS);
COM_OBJECT_VALIDATE_1_ARG(column_count);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> columns = GetTableColumnCount();
+ absl::optional<int> columns = GetTableColumnCount();
if (!columns)
return E_FAIL;
*column_count = LONG{*columns};
@@ -2689,7 +2815,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_nRows(LONG* row_count) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_N_ROWS);
COM_OBJECT_VALIDATE_1_ARG(row_count);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> rows = GetTableRowCount();
+ absl::optional<int> rows = GetTableRowCount();
if (!rows)
return E_FAIL;
*row_count = LONG{*rows};
@@ -2701,8 +2827,8 @@ IFACEMETHODIMP AXPlatformNodeWin::get_nSelectedChildren(LONG* cell_count) {
COM_OBJECT_VALIDATE_1_ARG(cell_count);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> columns = GetTableColumnCount();
- base::Optional<int> rows = GetTableRowCount();
+ absl::optional<int> columns = GetTableColumnCount();
+ absl::optional<int> rows = GetTableRowCount();
if (!columns || !rows)
return E_FAIL;
@@ -2724,8 +2850,8 @@ IFACEMETHODIMP AXPlatformNodeWin::get_nSelectedColumns(LONG* column_count) {
COM_OBJECT_VALIDATE_1_ARG(column_count);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> columns = GetTableColumnCount();
- base::Optional<int> rows = GetTableRowCount();
+ absl::optional<int> columns = GetTableColumnCount();
+ absl::optional<int> rows = GetTableRowCount();
if (!columns || !rows)
return E_FAIL;
@@ -2752,8 +2878,8 @@ IFACEMETHODIMP AXPlatformNodeWin::get_nSelectedRows(LONG* row_count) {
COM_OBJECT_VALIDATE_1_ARG(row_count);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> columns = GetTableColumnCount();
- base::Optional<int> rows = GetTableRowCount();
+ absl::optional<int> columns = GetTableColumnCount();
+ absl::optional<int> rows = GetTableRowCount();
if (!columns || !rows)
return E_FAIL;
@@ -2781,7 +2907,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_rowDescription(LONG row,
COM_OBJECT_VALIDATE_1_ARG(description);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> rows = GetTableRowCount();
+ absl::optional<int> rows = GetTableRowCount();
if (!rows)
return E_FAIL;
@@ -2824,7 +2950,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_rowExtentAt(LONG row,
if (!cell)
return E_INVALIDARG;
- base::Optional<int> cell_row_span = cell->GetTableRowSpan();
+ absl::optional<int> cell_row_span = cell->GetTableRowSpan();
if (!cell_row_span)
return E_FAIL;
*n_rows_spanned = LONG{*cell_row_span};
@@ -2852,7 +2978,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_rowIndex(LONG cell_index,
if (!cell)
return E_INVALIDARG;
- base::Optional<int> cell_row = cell->GetTableRow();
+ absl::optional<int> cell_row = cell->GetTableRow();
if (!cell_row)
return E_FAIL;
*row_index = LONG{*cell_row};
@@ -2869,8 +2995,8 @@ IFACEMETHODIMP AXPlatformNodeWin::get_selectedChildren(LONG max_children,
if (max_children <= 0)
return E_INVALIDARG;
- base::Optional<int> columns = GetTableColumnCount();
- base::Optional<int> rows = GetTableRowCount();
+ absl::optional<int> columns = GetTableColumnCount();
+ absl::optional<int> rows = GetTableRowCount();
if (!columns || !rows)
return E_FAIL;
@@ -2880,7 +3006,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_selectedChildren(LONG max_children,
const AXPlatformNodeBase* cell = GetTableCell(r, c);
if (cell && cell->GetData().GetBoolAttribute(
ax::mojom::BoolAttribute::kSelected)) {
- base::Optional<int> cell_index = cell->GetTableCellIndex();
+ absl::optional<int> cell_index = cell->GetTableCellIndex();
if (!cell_index)
return E_FAIL;
@@ -2903,8 +3029,8 @@ IFACEMETHODIMP AXPlatformNodeWin::get_selectedColumns(LONG max_columns,
if (max_columns <= 0)
return E_INVALIDARG;
- base::Optional<int> column_count = GetTableColumnCount();
- base::Optional<int> row_count = GetTableRowCount();
+ absl::optional<int> column_count = GetTableColumnCount();
+ absl::optional<int> row_count = GetTableRowCount();
if (!column_count || !row_count)
return E_FAIL;
@@ -2934,8 +3060,8 @@ IFACEMETHODIMP AXPlatformNodeWin::get_selectedRows(LONG max_rows,
if (max_rows <= 0)
return E_INVALIDARG;
- base::Optional<int> column_count = GetTableColumnCount();
- base::Optional<int> row_count = GetTableRowCount();
+ absl::optional<int> column_count = GetTableColumnCount();
+ absl::optional<int> row_count = GetTableRowCount();
if (!column_count || !row_count)
return E_FAIL;
@@ -2970,8 +3096,8 @@ IFACEMETHODIMP AXPlatformNodeWin::get_isColumnSelected(LONG column,
COM_OBJECT_VALIDATE_1_ARG(is_selected);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> columns = GetTableColumnCount();
- base::Optional<int> rows = GetTableRowCount();
+ absl::optional<int> columns = GetTableColumnCount();
+ absl::optional<int> rows = GetTableRowCount();
if (!columns || !rows)
return E_FAIL;
@@ -2995,8 +3121,8 @@ IFACEMETHODIMP AXPlatformNodeWin::get_isRowSelected(LONG row,
COM_OBJECT_VALIDATE_1_ARG(is_selected);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> columns = GetTableColumnCount();
- base::Optional<int> rows = GetTableRowCount();
+ absl::optional<int> columns = GetTableColumnCount();
+ absl::optional<int> rows = GetTableRowCount();
if (!columns || !rows)
return E_FAIL;
@@ -3021,8 +3147,8 @@ IFACEMETHODIMP AXPlatformNodeWin::get_isSelected(LONG row,
COM_OBJECT_VALIDATE_1_ARG(is_selected);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> columns = GetTableColumnCount();
- base::Optional<int> rows = GetTableRowCount();
+ absl::optional<int> columns = GetTableColumnCount();
+ absl::optional<int> rows = GetTableRowCount();
if (!columns || !rows)
return E_FAIL;
@@ -3052,10 +3178,10 @@ IFACEMETHODIMP AXPlatformNodeWin::get_rowColumnExtentsAtIndex(
if (!cell)
return E_INVALIDARG;
- base::Optional<int> row_index = cell->GetTableRow();
- base::Optional<int> column_index = cell->GetTableColumn();
- base::Optional<int> row_span = cell->GetTableRowSpan();
- base::Optional<int> column_span = cell->GetTableColumnSpan();
+ absl::optional<int> row_index = cell->GetTableRow();
+ absl::optional<int> column_index = cell->GetTableColumn();
+ absl::optional<int> row_span = cell->GetTableRowSpan();
+ absl::optional<int> column_span = cell->GetTableColumnSpan();
if (!row_index || !column_index || !row_span || !column_span)
return E_FAIL;
@@ -3072,7 +3198,7 @@ IFACEMETHODIMP AXPlatformNodeWin::selectRow(LONG row) {
// TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> rows = GetTableRowCount();
+ absl::optional<int> rows = GetTableRowCount();
if (!rows)
return E_FAIL;
@@ -3086,7 +3212,7 @@ IFACEMETHODIMP AXPlatformNodeWin::selectColumn(LONG column) {
// TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> columns = GetTableColumnCount();
+ absl::optional<int> columns = GetTableColumnCount();
if (!columns)
return E_FAIL;
@@ -3100,7 +3226,7 @@ IFACEMETHODIMP AXPlatformNodeWin::unselectRow(LONG row) {
// TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> rows = GetTableRowCount();
+ absl::optional<int> rows = GetTableRowCount();
if (!rows)
return E_FAIL;
@@ -3114,7 +3240,7 @@ IFACEMETHODIMP AXPlatformNodeWin::unselectColumn(LONG column) {
// TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> columns = GetTableColumnCount();
+ absl::optional<int> columns = GetTableColumnCount();
if (!columns)
return E_FAIL;
@@ -3163,8 +3289,8 @@ IFACEMETHODIMP AXPlatformNodeWin::get_selectedCells(IUnknown*** cells,
COM_OBJECT_VALIDATE_2_ARGS(cells, n_selected_cells);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> columns = GetTableColumnCount();
- base::Optional<int> rows = GetTableRowCount();
+ absl::optional<int> columns = GetTableColumnCount();
+ absl::optional<int> rows = GetTableRowCount();
if (!columns || !rows)
return E_FAIL;
@@ -3209,7 +3335,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_columnExtent(LONG* n_columns_spanned) {
COM_OBJECT_VALIDATE_1_ARG(n_columns_spanned);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> column_span = GetTableColumnSpan();
+ absl::optional<int> column_span = GetTableColumnSpan();
if (!column_span)
return E_FAIL;
*n_columns_spanned = LONG{*column_span};
@@ -3223,7 +3349,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_columnHeaderCells(
COM_OBJECT_VALIDATE_2_ARGS(cell_accessibles, n_column_header_cells);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> column = GetTableColumn();
+ absl::optional<int> column = GetTableColumn();
if (!column)
return E_FAIL;
@@ -3250,7 +3376,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_columnIndex(LONG* column_index) {
COM_OBJECT_VALIDATE_1_ARG(column_index);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> column = GetTableColumn();
+ absl::optional<int> column = GetTableColumn();
if (!column)
return E_FAIL;
*column_index = LONG{*column};
@@ -3262,7 +3388,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_rowExtent(LONG* n_rows_spanned) {
COM_OBJECT_VALIDATE_1_ARG(n_rows_spanned);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> row_span = GetTableRowSpan();
+ absl::optional<int> row_span = GetTableRowSpan();
if (!row_span)
return E_FAIL;
*n_rows_spanned = LONG{*row_span};
@@ -3276,7 +3402,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_rowHeaderCells(
COM_OBJECT_VALIDATE_2_ARGS(cell_accessibles, n_row_header_cells);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> row = GetTableRow();
+ absl::optional<int> row = GetTableRow();
if (!row)
return E_FAIL;
@@ -3303,7 +3429,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_rowIndex(LONG* row_index) {
COM_OBJECT_VALIDATE_1_ARG(row_index);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> row = GetTableRow();
+ absl::optional<int> row = GetTableRow();
if (!row)
return E_FAIL;
*row_index = LONG{*row};
@@ -3330,10 +3456,10 @@ IFACEMETHODIMP AXPlatformNodeWin::get_rowColumnExtents(LONG* row_index,
column_extents, is_selected);
AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- base::Optional<int> row = GetTableRow();
- base::Optional<int> column = GetTableColumn();
- base::Optional<int> row_span = GetTableRowSpan();
- base::Optional<int> column_span = GetTableColumnSpan();
+ absl::optional<int> row = GetTableRow();
+ absl::optional<int> column = GetTableColumn();
+ absl::optional<int> row_span = GetTableRowSpan();
+ absl::optional<int> column_span = GetTableColumnSpan();
if (!row || !column || !row_span || !column_span)
return E_FAIL;
@@ -4104,6 +4230,12 @@ HRESULT AXPlatformNodeWin::GetPropertyValueImpl(PROPERTYID property_id,
// Default UIA Property Ids.
switch (property_id) {
+ case UIA_AnnotationObjectsPropertyId: {
+ result->vt = VT_ARRAY | VT_UNKNOWN;
+ result->parray = CreateUIAElementsArrayForRelation(
+ ax::mojom::IntListAttribute::kDetailsIds);
+ break;
+ }
case UIA_AriaPropertiesPropertyId:
result->vt = VT_BSTR;
result->bstrVal = SysAllocString(ComputeUIAProperties().c_str());
@@ -4142,7 +4274,7 @@ HRESULT AXPlatformNodeWin::GetPropertyValueImpl(PROPERTYID property_id,
break;
case UIA_CulturePropertyId: {
- base::Optional<LCID> lcid = GetCultureAttributeAsLCID();
+ absl::optional<LCID> lcid = GetCultureAttributeAsLCID();
if (!lcid)
return E_FAIL;
result->vt = VT_I4;
@@ -4402,7 +4534,7 @@ HRESULT AXPlatformNodeWin::GetPropertyValueImpl(PROPERTYID property_id,
break;
case UIA_PositionInSetPropertyId: {
- base::Optional<int> pos_in_set = GetPosInSet();
+ absl::optional<int> pos_in_set = GetPosInSet();
if (pos_in_set) {
result->vt = VT_I4;
result->intVal = *pos_in_set;
@@ -4422,7 +4554,7 @@ HRESULT AXPlatformNodeWin::GetPropertyValueImpl(PROPERTYID property_id,
}
case UIA_SizeOfSetPropertyId: {
- base::Optional<int> set_size = GetSetSize();
+ absl::optional<int> set_size = GetSetSize();
if (set_size) {
result->vt = VT_I4;
result->intVal = *set_size;
@@ -4431,7 +4563,7 @@ HRESULT AXPlatformNodeWin::GetPropertyValueImpl(PROPERTYID property_id,
}
case UIA_LandmarkTypePropertyId: {
- base::Optional<LONG> landmark_type = ComputeUIALandmarkType();
+ absl::optional<LONG> landmark_type = ComputeUIALandmarkType();
if (landmark_type) {
result->vt = VT_I4;
result->intVal = landmark_type.value();
@@ -4456,7 +4588,6 @@ HRESULT AXPlatformNodeWin::GetPropertyValueImpl(PROPERTYID property_id,
break;
// Not currently implemented.
- case UIA_AnnotationObjectsPropertyId:
case UIA_AnnotationTypesPropertyId:
case UIA_CenterPointPropertyId:
case UIA_FillColorPropertyId:
@@ -4690,13 +4821,15 @@ STDMETHODIMP AXPlatformNodeWin::InternalQueryInterface(
HRESULT AXPlatformNodeWin::GetTextAttributeValue(
TEXTATTRIBUTEID attribute_id,
- const base::Optional<int>& start_offset,
- const base::Optional<int>& end_offset,
+ const absl::optional<int>& start_offset,
+ const absl::optional<int>& end_offset,
base::win::VariantVector* result) {
DCHECK(!start_offset || start_offset.value() >= 0);
DCHECK(!end_offset || end_offset.value() >= 0);
-
switch (attribute_id) {
+ case UIA_AnnotationObjectsAttributeId:
+ GetAnnotationObjectsAttribute(result);
+ break;
case UIA_AnnotationTypesAttributeId:
return GetAnnotationTypesAttribute(start_offset, end_offset, result);
case UIA_BackgroundColorAttributeId:
@@ -4707,7 +4840,7 @@ HRESULT AXPlatformNodeWin::GetTextAttributeValue(
result->Insert<VT_I4>(ComputeUIABulletStyle());
break;
case UIA_CultureAttributeId: {
- base::Optional<LCID> lcid = GetCultureAttributeAsLCID();
+ absl::optional<LCID> lcid = GetCultureAttributeAsLCID();
if (!lcid)
return E_FAIL;
result->Insert<VT_I4>(lcid.value());
@@ -4717,7 +4850,7 @@ HRESULT AXPlatformNodeWin::GetTextAttributeValue(
result->Insert<VT_BSTR>(GetFontNameAttributeAsBSTR());
break;
case UIA_FontSizeAttributeId: {
- base::Optional<float> font_size_in_points = GetFontSizeInPoints();
+ absl::optional<float> font_size_in_points = GetFontSizeInPoints();
if (font_size_in_points) {
result->Insert<VT_R8>(*font_size_in_points);
}
@@ -4738,17 +4871,17 @@ HRESULT AXPlatformNodeWin::GetTextAttributeValue(
result->Insert<VT_BOOL>(
GetData().HasTextStyle(ax::mojom::TextStyle::kItalic));
break;
- case UIA_IsReadOnlyAttributeId:
- // Placeholder text should return the enclosing element's read-only value.
- if (IsPlaceholderText()) {
- AXPlatformNodeWin* parent_platform_node =
- static_cast<AXPlatformNodeWin*>(
- FromNativeViewAccessible(GetParent()));
- return parent_platform_node->GetTextAttributeValue(
- attribute_id, start_offset, end_offset, result);
+ case UIA_IsReadOnlyAttributeId: {
+ // If inside a text field, the text field's readonly state rules.
+ const AXPlatformNodeWin* text_field = static_cast<AXPlatformNodeWin*>(
+ FromNativeViewAccessible(GetDelegate()->GetTextFieldAncestor()));
+ if (text_field) {
+ result->Insert<VT_BOOL>(text_field->GetData().IsReadOnlyOrDisabled());
+ } else {
+ result->Insert<VT_BOOL>(GetData().IsReadOnlyOrDisabled());
}
- result->Insert<VT_BOOL>(GetData().IsReadOnlyOrDisabled());
break;
+ }
case UIA_IsSubscriptAttributeId:
result->Insert<VT_BOOL>(GetData().GetTextPosition() ==
ax::mojom::TextPosition::kSubscript);
@@ -4772,7 +4905,7 @@ HRESULT AXPlatformNodeWin::GetTextAttributeValue(
result->Insert<VT_I4>(ComputeUIAStyleId());
break;
case UIA_HorizontalTextAlignmentAttributeId: {
- base::Optional<HorizontalTextAlignment> horizontal_text_alignment =
+ absl::optional<HorizontalTextAlignment> horizontal_text_alignment =
AXTextAlignToUIAHorizontalTextAlignment(GetData().GetTextAlign());
if (horizontal_text_alignment)
result->Insert<VT_I4>(*horizontal_text_alignment);
@@ -4798,16 +4931,44 @@ HRESULT AXPlatformNodeWin::GetTextAttributeValue(
return S_OK;
}
+void AXPlatformNodeWin::GetAnnotationObjectsAttribute(
+ base::win::VariantVector* result) {
+ // Most times AnnotationObject attribute is set on the container (immediate
+ // parent) of the text node, but it can be on any ancestor of the text node.
+ // TODO(vicfei): Need to find an efficient algorithm to walk up current node's
+ // ancestors to find the attribute. https://crbug.com/1201327
+ AXPlatformNodeWin* parent_platform_node =
+ static_cast<AXPlatformNodeWin*>(FromNativeViewAccessible(GetParent()));
+
+ if (!parent_platform_node || !IsText())
+ return;
+
+ std::vector<int32_t> relation_id_list =
+ parent_platform_node->GetIntListAttribute(
+ ax::mojom::IntListAttribute::kDetailsIds);
+
+ std::vector<AXPlatformNodeWin*> platform_node_list =
+ CreatePlatformNodeVectorFromRelationIdVector(relation_id_list);
+
+ for (AXPlatformNodeWin* platform_node : platform_node_list) {
+ Microsoft::WRL::ComPtr<IUnknown> annotation_object;
+ if (SUCCEEDED(
+ platform_node->QueryInterface(IID_PPV_ARGS(&annotation_object)))) {
+ result->Insert<VT_UNKNOWN>(annotation_object.Get());
+ }
+ }
+}
+
HRESULT AXPlatformNodeWin::GetAnnotationTypesAttribute(
- const base::Optional<int>& start_offset,
- const base::Optional<int>& end_offset,
+ const absl::optional<int>& start_offset,
+ const absl::optional<int>& end_offset,
base::win::VariantVector* result) {
base::win::VariantVector variant_vector;
MarkerTypeRangeResult grammar_result = MarkerTypeRangeResult::kNone;
MarkerTypeRangeResult spelling_result = MarkerTypeRangeResult::kNone;
- if (IsText() || IsPlainTextField()) {
+ if (IsText() || IsAtomicTextField()) {
grammar_result = GetMarkerTypeFromRange(start_offset, end_offset,
ax::mojom::MarkerType::kGrammar);
spelling_result = GetMarkerTypeFromRange(start_offset, end_offset,
@@ -4831,13 +4992,13 @@ HRESULT AXPlatformNodeWin::GetAnnotationTypesAttribute(
return S_OK;
}
-base::Optional<LCID> AXPlatformNodeWin::GetCultureAttributeAsLCID() const {
+absl::optional<LCID> AXPlatformNodeWin::GetCultureAttributeAsLCID() const {
const std::u16string language =
GetInheritedString16Attribute(ax::mojom::StringAttribute::kLanguage);
const LCID lcid =
LocaleNameToLCID(base::as_wcstr(language), LOCALE_ALLOW_NEUTRAL_NAMES);
if (!lcid)
- return base::nullopt;
+ return absl::nullopt;
return lcid;
}
@@ -4908,12 +5069,12 @@ LONG AXPlatformNodeWin::ComputeUIAStyleId() const {
}
// static
-base::Optional<HorizontalTextAlignment>
+absl::optional<HorizontalTextAlignment>
AXPlatformNodeWin::AXTextAlignToUIAHorizontalTextAlignment(
ax::mojom::TextAlign text_align) {
switch (text_align) {
case ax::mojom::TextAlign::kNone:
- return base::nullopt;
+ return absl::nullopt;
case ax::mojom::TextAlign::kLeft:
return HorizontalTextAlignment_Left;
case ax::mojom::TextAlign::kRight:
@@ -5014,16 +5175,16 @@ void AXPlatformNodeWin::AggregateRangesForMarkerType(
AXPlatformNodeWin::MarkerTypeRangeResult
AXPlatformNodeWin::GetMarkerTypeFromRange(
- const base::Optional<int>& start_offset,
- const base::Optional<int>& end_offset,
+ const absl::optional<int>& start_offset,
+ const absl::optional<int>& end_offset,
ax::mojom::MarkerType marker_type) {
- DCHECK(IsText() || IsPlainTextField());
+ DCHECK(IsText() || IsAtomicTextField());
std::vector<std::pair<int, int>> relevant_ranges;
if (IsText()) {
AggregateRangesForMarkerType(this, marker_type, /*offset_ranges_amount=*/0,
&relevant_ranges);
- } else if (IsPlainTextField()) {
+ } else if (IsAtomicTextField()) {
int offset_ranges_amount = 0;
for (AXPlatformNodeBase* static_text = GetFirstTextOnlyDescendant();
static_text; static_text = static_text->GetNextSibling()) {
@@ -5054,7 +5215,7 @@ AXPlatformNodeWin::GetMarkerTypeFromRange(
sort_ranges_by_start_offset);
// Validate that the desired range has a contiguous MarkerType.
- base::Optional<std::pair<int, int>> contiguous_range;
+ absl::optional<std::pair<int, int>> contiguous_range;
for (const std::pair<int, int>& range : relevant_ranges) {
if (end_offset && range.first > end_offset.value())
break;
@@ -5486,14 +5647,8 @@ int AXPlatformNodeWin::MSAARole() {
// shows up in the tree.
return ROLE_SYSTEM_STATICTEXT;
- case ax::mojom::Role::kSection: {
- if (GetName().empty()) {
- // Do not use ARIA mapping for nameless <section>.
- return ROLE_SYSTEM_GROUPING;
- }
- // Use ARIA mapping.
- return ROLE_SYSTEM_PANE;
- }
+ case ax::mojom::Role::kSection:
+ return ROLE_SYSTEM_GROUPING;
case ax::mojom::Role::kScrollBar:
return ROLE_SYSTEM_SCROLLBAR;
@@ -5599,10 +5754,8 @@ int AXPlatformNodeWin::MSAARole() {
return ROLE_SYSTEM_PANE;
case ax::mojom::Role::kImeCandidate:
- case ax::mojom::Role::kIgnored:
case ax::mojom::Role::kKeyboard:
case ax::mojom::Role::kNone:
- case ax::mojom::Role::kPresentational:
case ax::mojom::Role::kUnknown:
return ROLE_SYSTEM_PANE;
}
@@ -5677,7 +5830,7 @@ int32_t AXPlatformNodeWin::ComputeIA2State() {
// enable paste operations. Eventually this need should go away once IE11
// support is no longer needed and Slides instead relies on paste events.
if (!data.HasState(ax::mojom::State::kFocusable) ||
- GetBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot))
+ GetBoolAttribute(ax::mojom::BoolAttribute::kContentEditableRoot))
break; // Not used with activedescendant, so preserve editable state.
FALLTHROUGH; // Will clear editable state.
case ax::mojom::Role::kMenuListPopup:
@@ -5896,16 +6049,9 @@ int32_t AXPlatformNodeWin::ComputeIA2Role() {
case ax::mojom::Role::kSearch:
ia2_role = IA2_ROLE_LANDMARK;
break;
- case ax::mojom::Role::kSection: {
- if (GetName().empty()) {
- // Do not use ARIA mapping for nameless <section>.
- ia2_role = IA2_ROLE_SECTION;
- } else {
- // Use ARIA mapping.
- ia2_role = IA2_ROLE_LANDMARK;
- }
+ case ax::mojom::Role::kSection:
+ ia2_role = IA2_ROLE_SECTION;
break;
- }
case ax::mojom::Role::kSwitch:
ia2_role = IA2_ROLE_TOGGLE_BUTTON;
break;
@@ -6329,14 +6475,8 @@ std::wstring AXPlatformNodeWin::UIAAriaRole() {
// shows up in the tree.
return L"description";
- case ax::mojom::Role::kSection: {
- if (GetName().empty()) {
- // Do not use ARIA mapping for nameless <section>.
- return L"group";
- }
- // Use ARIA mapping.
- return L"region";
- }
+ case ax::mojom::Role::kSection:
+ return L"group";
case ax::mojom::Role::kScrollBar:
return L"scrollbar";
@@ -6439,9 +6579,7 @@ std::wstring AXPlatformNodeWin::UIAAriaRole() {
case ax::mojom::Role::kPane:
case ax::mojom::Role::kWindow:
- case ax::mojom::Role::kIgnored:
case ax::mojom::Role::kNone:
- case ax::mojom::Role::kPresentational:
case ax::mojom::Role::kUnknown:
return L"region";
}
@@ -6635,7 +6773,7 @@ LONG AXPlatformNodeWin::ComputeUIAControlType() { // NOLINT(runtime/int)
case ax::mojom::Role::kComment:
case ax::mojom::Role::kSuggestion:
- return ROLE_SYSTEM_GROUPING;
+ return UIA_GroupControlTypeId;
case ax::mojom::Role::kApplication:
return UIA_PaneControlTypeId;
@@ -7098,11 +7236,9 @@ LONG AXPlatformNodeWin::ComputeUIAControlType() { // NOLINT(runtime/int)
case ax::mojom::Role::kPane:
case ax::mojom::Role::kWindow:
- case ax::mojom::Role::kIgnored:
case ax::mojom::Role::kImeCandidate:
case ax::mojom::Role::kKeyboard:
case ax::mojom::Role::kNone:
- case ax::mojom::Role::kPresentational:
case ax::mojom::Role::kUnknown:
return UIA_PaneControlTypeId;
}
@@ -7278,7 +7414,8 @@ bool AXPlatformNodeWin::IsUIAControl() const {
// content as not controls.
// Doing so helps Narrator find all the content of live regions.
if (!data.GetBoolAttribute(ax::mojom::BoolAttribute::kHasAriaAttribute) &&
- !data.GetBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot) &&
+ !data.GetBoolAttribute(
+ ax::mojom::BoolAttribute::kContentEditableRoot) &&
GetName().empty() &&
data.GetStringAttribute(ax::mojom::StringAttribute::kDescription)
.empty() &&
@@ -7294,7 +7431,7 @@ bool AXPlatformNodeWin::IsUIAControl() const {
!data.HasState(ax::mojom::State::kFocusable));
}
-base::Optional<LONG> AXPlatformNodeWin::ComputeUIALandmarkType() const {
+absl::optional<LONG> AXPlatformNodeWin::ComputeUIALandmarkType() const {
const AXNodeData& data = GetData();
switch (data.role) {
case ax::mojom::Role::kBanner:
@@ -7329,10 +7466,7 @@ base::Optional<LONG> AXPlatformNodeWin::ComputeUIALandmarkType() const {
return UIA_SearchLandmarkTypeId;
case ax::mojom::Role::kRegion:
- case ax::mojom::Role::kSection:
- if (data.HasStringAttribute(ax::mojom::StringAttribute::kName))
- return UIA_CustomLandmarkTypeId;
- FALLTHROUGH;
+ return UIA_CustomLandmarkTypeId;
default:
return {};
@@ -7352,7 +7486,7 @@ bool AXPlatformNodeWin::IsInaccessibleDueToAncestor() const {
}
bool AXPlatformNodeWin::ShouldHideChildrenForUIA() const {
- if (IsPlainTextField())
+ if (IsAtomicTextField())
return true;
auto role = GetData().role;
@@ -7580,7 +7714,7 @@ int AXPlatformNodeWin::MSAAState() const {
}
// static
-base::Optional<DWORD> AXPlatformNodeWin::MojoEventToMSAAEvent(
+absl::optional<DWORD> AXPlatformNodeWin::MojoEventToMSAAEvent(
ax::mojom::Event event) {
switch (event) {
case ax::mojom::Event::kAlert:
@@ -7621,15 +7755,15 @@ base::Optional<DWORD> AXPlatformNodeWin::MojoEventToMSAAEvent(
case ax::mojom::Event::kValueChanged:
return EVENT_OBJECT_VALUECHANGE;
default:
- return base::nullopt;
+ return absl::nullopt;
}
}
// static
-base::Optional<EVENTID> AXPlatformNodeWin::MojoEventToUIAEvent(
+absl::optional<EVENTID> AXPlatformNodeWin::MojoEventToUIAEvent(
ax::mojom::Event event) {
if (!::switches::IsExperimentalAccessibilityPlatformUIAEnabled())
- return base::nullopt;
+ return absl::nullopt;
switch (event) {
case ax::mojom::Event::kAlert:
@@ -7651,15 +7785,15 @@ base::Optional<EVENTID> AXPlatformNodeWin::MojoEventToUIAEvent(
case ax::mojom::Event::kTooltipOpened:
return UIA_ToolTipOpenedEventId;
default:
- return base::nullopt;
+ return absl::nullopt;
}
}
// static
-base::Optional<PROPERTYID> AXPlatformNodeWin::MojoEventToUIAProperty(
+absl::optional<PROPERTYID> AXPlatformNodeWin::MojoEventToUIAProperty(
ax::mojom::Event event) {
if (!::switches::IsExperimentalAccessibilityPlatformUIAEnabled())
- return base::nullopt;
+ return absl::nullopt;
switch (event) {
case ax::mojom::Event::kControlsChanged:
@@ -7674,7 +7808,7 @@ base::Optional<PROPERTYID> AXPlatformNodeWin::MojoEventToUIAProperty(
case ax::mojom::Event::kSelectionRemove:
return UIA_SelectionItemIsSelectedPropertyId;
default:
- return base::nullopt;
+ return absl::nullopt;
}
}
@@ -7845,17 +7979,6 @@ HRESULT AXPlatformNodeWin::AllocateComArrayFromVector(
return S_OK;
}
-bool AXPlatformNodeWin::IsPlaceholderText() const {
- if (GetData().role != ax::mojom::Role::kStaticText)
- return false;
- AXPlatformNodeWin* parent =
- static_cast<AXPlatformNodeWin*>(FromNativeViewAccessible(GetParent()));
- // Static text nodes are always expected to have a parent.
- DCHECK(parent);
- return parent->IsTextField() &&
- parent->HasStringAttribute(ax::mojom::StringAttribute::kPlaceholder);
-}
-
bool AXPlatformNodeWin::IsHyperlink() {
int32_t hyperlink_index = -1;
AXPlatformNodeWin* parent =
@@ -7939,6 +8062,11 @@ AXPlatformNodeWin::GetPatternProviderFactoryMethod(PATTERNID pattern_id) {
const AXNodeData& data = GetData();
switch (pattern_id) {
+ case UIA_AnnotationPatternId:
+ if (IsStructuredAnnotation()) {
+ return &PatternProvider<IAnnotationProvider>;
+ }
+ break;
case UIA_ExpandCollapsePatternId:
if (data.SupportsExpandCollapse()) {
return &PatternProvider<IExpandCollapseProvider>;
@@ -7997,7 +8125,7 @@ AXPlatformNodeWin::GetPatternProviderFactoryMethod(PATTERNID pattern_id) {
// that any control implementing ITableProvider must also expose a column
// and/or row header relationship for each child element.
if (IsTableLike(data.role)) {
- base::Optional<bool> table_has_headers =
+ absl::optional<bool> table_has_headers =
GetDelegate()->GetTableHasColumnOrRowHeaderNode();
if (table_has_headers.has_value() && table_has_headers.value()) {
return &PatternProvider<ITableProvider>;
@@ -8012,7 +8140,7 @@ AXPlatformNodeWin::GetPatternProviderFactoryMethod(PATTERNID pattern_id) {
// expose the relationship between the individual cell and its row and
// column information.
if (IsCellOrTableHeader(data.role)) {
- base::Optional<bool> table_has_headers =
+ absl::optional<bool> table_has_headers =
GetDelegate()->GetTableHasColumnOrRowHeaderNode();
if (table_has_headers.has_value() && table_has_headers.value()) {
return &PatternProvider<ITableItemProvider>;
@@ -8051,7 +8179,6 @@ AXPlatformNodeWin::GetPatternProviderFactoryMethod(PATTERNID pattern_id) {
break;
// Not currently implemented.
- case UIA_AnnotationPatternId:
case UIA_CustomNavigationPatternId:
case UIA_DockPatternId:
case UIA_DragPatternId:
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_win.h b/chromium/ui/accessibility/platform/ax_platform_node_win.h
index 3d0cd23e480..481adddc898 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_win.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_win.h
@@ -286,6 +286,11 @@ enum {
UMA_API_ADVISE_EVENT_ADDED = 248,
UMA_API_ADVISE_EVENT_REMOVED = 249,
UMA_API_ITEMCONTAINER_FINDITEMBYPROPERTY = 250,
+ UMA_API_ANNOTATION_GET_ANNOTATIONTYPEID = 251,
+ UMA_API_ANNOTATION_GET_ANNOTATIONTYPENAME = 252,
+ UMA_API_ANNOTATION_GET_AUTHOR = 253,
+ UMA_API_ANNOTATION_GET_DATETIME = 254,
+ UMA_API_ANNOTATION_GET_TARGET = 255,
// This must always be the last enum. It's okay for its value to
// increase, but none of the other enum values may change.
@@ -337,6 +342,8 @@ class AX_EXPORT WinAccessibilityAPIUsageObserver {
virtual void OnScreenReaderHoneyPotQueried() = 0;
virtual void OnAccNameCalled() = 0;
virtual void OnUIAutomationUsed() = 0;
+ virtual void StartFiringUIAEvents() = 0;
+ virtual void EndFiringUIAEvents() = 0;
};
// Get an observer list that allows modules across the codebase to
@@ -345,6 +352,13 @@ extern AX_EXPORT
base::ObserverList<WinAccessibilityAPIUsageObserver>::Unchecked&
GetWinAccessibilityAPIUsageObserverList();
+// Used to simplify calling StartFiringUIAEvents and EndFiringEvents
+class AX_EXPORT WinAccessibilityAPIUsageScopedUIAEventsNotifier {
+ public:
+ WinAccessibilityAPIUsageScopedUIAEventsNotifier();
+ ~WinAccessibilityAPIUsageScopedUIAEventsNotifier();
+};
+
// TODO(nektar): Remove multithread superclass since we don't support it.
class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
AXPlatformNodeWin : public CComObjectRootEx<CComMultiThreadModel>,
@@ -357,6 +371,7 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
public IAccessibleTable2,
public IAccessibleTableCell,
public IAccessibleValue,
+ public IAnnotationProvider,
public IExpandCollapseProvider,
public IGridItemProvider,
public IGridProvider,
@@ -399,6 +414,7 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
COM_INTERFACE_ENTRY(IAccessibleTableCell)
COM_INTERFACE_ENTRY(IAccessibleValue)
COM_INTERFACE_ENTRY(IChromeAccessible)
+ COM_INTERFACE_ENTRY(IAnnotationProvider)
COM_INTERFACE_ENTRY(IExpandCollapseProvider)
COM_INTERFACE_ENTRY(IGridItemProvider)
COM_INTERFACE_ENTRY(IGridProvider)
@@ -584,6 +600,20 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
LONG* child_id) override;
//
+ // IAnnotationProvider methods.
+ //
+
+ IFACEMETHODIMP get_AnnotationTypeId(int* type_id) override;
+
+ IFACEMETHODIMP get_AnnotationTypeName(BSTR* type_name) override;
+
+ IFACEMETHODIMP get_Author(BSTR* author) override;
+
+ IFACEMETHODIMP get_DateTime(BSTR* date_time) override;
+
+ IFACEMETHODIMP get_Target(IRawElementProviderSimple** target) override;
+
+ //
// IExpandCollapseProvider methods.
//
@@ -1073,8 +1103,8 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
// If either |start_offset| or |end_offset| are not provided then the
// endpoint is treated as the start or end of the node respectively.
HRESULT GetTextAttributeValue(TEXTATTRIBUTEID attribute_id,
- const base::Optional<int>& start_offset,
- const base::Optional<int>& end_offset,
+ const absl::optional<int>& start_offset,
+ const absl::optional<int>& end_offset,
base::win::VariantVector* result);
// IRawElementProviderSimple support method.
@@ -1115,13 +1145,13 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
AXPlatformNodeWin* GetFirstTextOnlyDescendant();
// Convert a mojo event to an MSAA event. Exposed for testing.
- static base::Optional<DWORD> MojoEventToMSAAEvent(ax::mojom::Event event);
+ static absl::optional<DWORD> MojoEventToMSAAEvent(ax::mojom::Event event);
// Convert a mojo event to a UIA event. Exposed for testing.
- static base::Optional<EVENTID> MojoEventToUIAEvent(ax::mojom::Event event);
+ static absl::optional<EVENTID> MojoEventToUIAEvent(ax::mojom::Event event);
// Convert a mojo event to a UIA property id. Exposed for testing.
- static base::Optional<PROPERTYID> MojoEventToUIAProperty(
+ static absl::optional<PROPERTYID> MojoEventToUIAProperty(
ax::mojom::Event event);
protected:
@@ -1156,7 +1186,7 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
bool IsUIAControl() const;
- base::Optional<LONG> ComputeUIALandmarkType() const;
+ absl::optional<LONG> ComputeUIALandmarkType() const;
bool IsInaccessibleDueToAncestor() const;
@@ -1170,7 +1200,7 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
// Relationships between this node and other nodes.
std::vector<Microsoft::WRL::ComPtr<AXPlatformRelationWin>> relations_;
- AXHypertext old_hypertext_;
+ AXLegacyHypertext old_hypertext_;
// These protected methods are still used by BrowserAccessibilityComWin. At
// some point post conversion, we can probably move these to be private
@@ -1210,7 +1240,7 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
private:
bool IsWebAreaForPresentationalIframe();
bool ShouldNodeHaveFocusableState(const AXNodeData& data) const;
-
+ int GetAnnotationTypeImpl() const;
// Get the value attribute as a Bstr, this means something different depending
// on the type of element being queried. (e.g. kColorWell uses kColorValue).
static BSTR GetValueAttributeAsBstr(AXPlatformNodeWin* target);
@@ -1359,13 +1389,15 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
// Getters for UIA GetTextAttributeValue
//
+ // Computes the AnnotationObjects Attribute for the current node.
+ void GetAnnotationObjectsAttribute(base::win::VariantVector* result);
// Computes the AnnotationTypes Attribute for the current node.
- HRESULT GetAnnotationTypesAttribute(const base::Optional<int>& start_offset,
- const base::Optional<int>& end_offset,
+ HRESULT GetAnnotationTypesAttribute(const absl::optional<int>& start_offset,
+ const absl::optional<int>& end_offset,
base::win::VariantVector* result);
// Lookup the LCID for the language this node is using.
- // Returns base::nullopt if there was an error.
- base::Optional<LCID> GetCultureAttributeAsLCID() const;
+ // Returns absl::nullopt if there was an error.
+ absl::optional<LCID> GetCultureAttributeAsLCID() const;
// Converts an int attribute to a COLORREF
COLORREF GetIntAttributeAsCOLORREF(ax::mojom::IntAttribute attribute) const;
// Converts the ListStyle to UIA BulletStyle
@@ -1373,7 +1405,7 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
// Helper to get the UIA StyleId enumeration for this node
LONG ComputeUIAStyleId() const;
// Convert mojom TextAlign to UIA HorizontalTextAlignment enumeration
- static base::Optional<HorizontalTextAlignment>
+ static absl::optional<HorizontalTextAlignment>
AXTextAlignToUIAHorizontalTextAlignment(ax::mojom::TextAlign text_align);
// Converts IntAttribute::kHierarchicalLevel to UIA StyleId enumeration
static LONG AXHierarchicalLevelToUIAStyleId(int32_t hierarchical_level);
@@ -1403,14 +1435,12 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
// Determine if a text range overlaps a |marker_type|, and whether
// the overlap is a partial or or complete match.
MarkerTypeRangeResult GetMarkerTypeFromRange(
- const base::Optional<int>& start_offset,
- const base::Optional<int>& end_offset,
+ const absl::optional<int>& start_offset,
+ const absl::optional<int>& end_offset,
ax::mojom::MarkerType marker_type);
bool IsAncestorComboBox();
- bool IsPlaceholderText() const;
-
// Helper method for getting the horizontal scroll percent.
double GetHorizontalScrollPercent();
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc
index 41fe2fdf6a9..f235aad766b 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -185,42 +185,42 @@ ScopedVariant SELF(CHILDID_SELF);
expected_property_values); \
}
-#define EXPECT_UIA_PROPERTY_UNORDERED_ELEMENT_ARRAY_BSTR_EQ( \
- node, array_property_id, element_test_property_id, \
- expected_property_values) \
- { \
- ScopedVariant array; \
- ASSERT_HRESULT_SUCCEEDED( \
- node->GetPropertyValue(array_property_id, array.Receive())); \
- ASSERT_EQ(VT_ARRAY | VT_UNKNOWN, array.type()); \
- ASSERT_EQ(1u, SafeArrayGetDim(array.ptr()->parray)); \
- LONG array_lower_bound; \
- ASSERT_HRESULT_SUCCEEDED( \
- SafeArrayGetLBound(array.ptr()->parray, 1, &array_lower_bound)); \
- LONG array_upper_bound; \
- ASSERT_HRESULT_SUCCEEDED( \
- SafeArrayGetUBound(array.ptr()->parray, 1, &array_upper_bound)); \
- IUnknown** array_data; \
- ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData( \
- array.ptr()->parray, reinterpret_cast<void**>(&array_data))); \
- size_t count = array_upper_bound - array_lower_bound + 1; \
- ASSERT_EQ(expected_property_values.size(), count); \
- std::vector<std::wstring> property_values; \
- for (size_t i = 0; i < count; ++i) { \
- ComPtr<IRawElementProviderSimple> element; \
- ASSERT_HRESULT_SUCCEEDED( \
- array_data[i]->QueryInterface(IID_PPV_ARGS(&element))); \
- ScopedVariant actual; \
- ASSERT_HRESULT_SUCCEEDED(element->GetPropertyValue( \
- element_test_property_id, actual.Receive())); \
- ASSERT_EQ(VT_BSTR, actual.type()); \
- ASSERT_NE(nullptr, actual.ptr()->bstrVal); \
- property_values.push_back(std::wstring( \
- V_BSTR(actual.ptr()), SysStringLen(V_BSTR(actual.ptr())))); \
- } \
- ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(array.ptr()->parray)); \
- EXPECT_THAT(property_values, \
- testing::UnorderedElementsAreArray(expected_property_values)); \
+#define EXPECT_UIA_PROPERTY_UNORDERED_ELEMENT_ARRAY_BSTR_EQ( \
+ node, array_property_id, element_test_property_id, \
+ expected_property_values) \
+ { \
+ ScopedVariant array; \
+ ASSERT_HRESULT_SUCCEEDED( \
+ node->GetPropertyValue(array_property_id, array.Receive())); \
+ ASSERT_EQ(VT_ARRAY | VT_UNKNOWN, array.type()); \
+ ASSERT_EQ(1u, SafeArrayGetDim(array.ptr()->parray)); \
+ LONG array_lower_bound; \
+ ASSERT_HRESULT_SUCCEEDED( \
+ SafeArrayGetLBound(array.ptr()->parray, 1, &array_lower_bound)); \
+ LONG array_upper_bound; \
+ ASSERT_HRESULT_SUCCEEDED( \
+ SafeArrayGetUBound(array.ptr()->parray, 1, &array_upper_bound)); \
+ IUnknown** array_data; \
+ ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData( \
+ array.ptr()->parray, reinterpret_cast<void**>(&array_data))); \
+ size_t count = array_upper_bound - array_lower_bound + 1; \
+ ASSERT_EQ(expected_property_values.size(), count); \
+ std::vector<std::wstring> property_values; \
+ for (size_t i = 0; i < count; ++i) { \
+ ComPtr<IRawElementProviderSimple> element; \
+ ASSERT_HRESULT_SUCCEEDED( \
+ array_data[i]->QueryInterface(IID_PPV_ARGS(&element))); \
+ ScopedVariant actual; \
+ ASSERT_HRESULT_SUCCEEDED(element->GetPropertyValue( \
+ element_test_property_id, actual.Receive())); \
+ ASSERT_EQ(VT_BSTR, actual.type()); \
+ ASSERT_NE(nullptr, actual.ptr()->bstrVal); \
+ property_values.push_back(std::wstring( \
+ V_BSTR(actual.ptr()), SysStringLen(V_BSTR(actual.ptr())))); \
+ } \
+ ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(array.ptr()->parray)); \
+ EXPECT_THAT(property_values, ::testing::UnorderedElementsAreArray( \
+ expected_property_values)); \
}
MockIRawElementProviderSimple::MockIRawElementProviderSimple() = default;
@@ -264,7 +264,8 @@ IFACEMETHODIMP MockIRawElementProviderSimple::get_HostRawElementProvider(
return E_NOTIMPL;
}
-AXPlatformNodeWinTest::AXPlatformNodeWinTest() {
+AXPlatformNodeWinTest::AXPlatformNodeWinTest()
+ : ax_embedded_object_behavior_(AXEmbeddedObjectBehavior::kExposeCharacter) {
scoped_feature_list_.InitAndEnableFeature(features::kIChromeAccessible);
}
@@ -279,6 +280,7 @@ void AXPlatformNodeWinTest::TearDown() {
ax_fragment_root_.reset(nullptr);
DestroyTree();
TestAXNodeWrapper::SetGlobalIsWebContent(false);
+ TestAXNodeWrapper::ResetGlobalState();
ASSERT_EQ(0U, AXPlatformNodeBase::GetInstanceCountForTesting());
}
@@ -627,6 +629,7 @@ TEST_F(AXPlatformNodeWinTest, IAccessibleAccValue) {
AXNodeData root;
root.id = 1;
root.role = ax::mojom::Role::kTextField;
+ root.AddState(ax::mojom::State::kEditable);
root.AddStringAttribute(ax::mojom::StringAttribute::kValue, "Value");
Init(root);
@@ -1968,6 +1971,7 @@ TEST_F(AXPlatformNodeWinTest,
AXNodeData child1;
child1.id = 2;
child1.role = ax::mojom::Role::kTextField;
+ child1.AddState(ax::mojom::State::kEditable);
child1.AddIntListAttribute(ax::mojom::IntListAttribute::kControlsIds, {3});
root.child_ids.push_back(2);
@@ -4149,6 +4153,38 @@ TEST_F(AXPlatformNodeWinTest,
UIA_IsControlElementPropertyId, false);
}
+TEST_F(AXPlatformNodeWinTest, UIAGetAnnotationObjectsPropertyId) {
+ AXNodeData root;
+ root.id = 1;
+ root.role = ax::mojom::Role::kRootWebArea;
+ root.SetName("root");
+ root.AddIntListAttribute(ax::mojom::IntListAttribute::kDetailsIds, {2, 3});
+
+ AXNodeData highlighted;
+ highlighted.id = 2;
+ highlighted.role = ax::mojom::Role::kMark;
+ highlighted.SetName("highlighted");
+ root.child_ids.push_back(highlighted.id);
+
+ AXNodeData comment;
+ comment.id = 3;
+ comment.role = ax::mojom::Role::kComment;
+ comment.SetName("comment");
+ root.child_ids.push_back(comment.id);
+
+ Init(root, highlighted, comment);
+ ComPtr<IRawElementProviderSimple> root_node =
+ QueryInterfaceFromNode<IRawElementProviderSimple>(GetRootAsAXNode());
+
+ ScopedVariant array;
+ ASSERT_HRESULT_SUCCEEDED(root_node->GetPropertyValue(
+ UIA_AnnotationObjectsPropertyId, array.Receive()));
+ ASSERT_EQ(VT_ARRAY | VT_UNKNOWN, array.type());
+ std::vector<std::wstring> expected_names = {L"highlighted", L"comment"};
+ EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(array.ptr()->parray, UIA_NamePropertyId,
+ expected_names);
+}
+
TEST_F(AXPlatformNodeWinTest, UIAGetControllerForPropertyId) {
AXNodeData root;
root.id = 1;
@@ -4562,6 +4598,7 @@ TEST_F(AXPlatformNodeWinTest, GetPropertyValue_HelpText) {
AXNodeData input1;
input1.id = 2;
input1.role = ax::mojom::Role::kTextField;
+ input1.AddState(ax::mojom::State::kEditable);
input1.SetName("name-from-title");
input1.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
static_cast<int>(ax::mojom::NameFrom::kTitle));
@@ -4573,6 +4610,7 @@ TEST_F(AXPlatformNodeWinTest, GetPropertyValue_HelpText) {
AXNodeData input2;
input2.id = 3;
input2.role = ax::mojom::Role::kTextField;
+ input2.AddState(ax::mojom::State::kEditable);
input2.SetName("name-from-title");
input2.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
static_cast<int>(ax::mojom::NameFrom::kTitle));
@@ -4582,6 +4620,7 @@ TEST_F(AXPlatformNodeWinTest, GetPropertyValue_HelpText) {
AXNodeData input3;
input3.id = 4;
input3.role = ax::mojom::Role::kTextField;
+ input3.AddState(ax::mojom::State::kEditable);
input3.SetName("name-from-placeholder");
input3.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
static_cast<int>(ax::mojom::NameFrom::kPlaceholder));
@@ -4591,6 +4630,7 @@ TEST_F(AXPlatformNodeWinTest, GetPropertyValue_HelpText) {
AXNodeData input4;
input4.id = 5;
input4.role = ax::mojom::Role::kTextField;
+ input4.AddState(ax::mojom::State::kEditable);
input4.SetName("name-from-attribute");
input4.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
static_cast<int>(ax::mojom::NameFrom::kAttribute));
@@ -4602,6 +4642,7 @@ TEST_F(AXPlatformNodeWinTest, GetPropertyValue_HelpText) {
AXNodeData input5;
input5.id = 6;
input5.role = ax::mojom::Role::kTextField;
+ input5.AddState(ax::mojom::State::kEditable);
input5.SetName("name-from-attribute");
input5.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
static_cast<int>(ax::mojom::NameFrom::kAttribute));
@@ -4703,8 +4744,10 @@ TEST_F(AXPlatformNodeWinTest, GetPropertyValue_IsControlElement) {
true);
update.nodes[12].id = 13;
update.nodes[12].role = ax::mojom::Role::kGenericContainer;
- update.nodes[12].AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot,
- true);
+ update.nodes[12].AddState(ax::mojom::State::kEditable);
+ update.nodes[12].AddState(ax::mojom::State::kRichlyEditable);
+ update.nodes[12].AddBoolAttribute(
+ ax::mojom::BoolAttribute::kContentEditableRoot, true);
update.nodes[13].id = 14;
update.nodes[13].role = ax::mojom::Role::kGenericContainer;
update.nodes[13].SetName("name");
@@ -5074,6 +5117,273 @@ TEST_F(AXPlatformNodeWinTest, UIANavigate) {
nullptr);
}
+TEST_F(AXPlatformNodeWinTest, IAnnotationProvider) {
+ // rootWebArea
+ // ++mark detailsIds=comment, footnote, definition
+ // ++++staticText name='highlighted 1'
+ // ++comment
+ // ++++staticText name='comment 1'
+ // ++docFootnote
+ // ++++staticText name="footnote"
+ // ++definition
+ // ++button
+
+ AXNodeData root;
+ AXNodeData highlighted1;
+ AXNodeData highlighted1_text;
+ AXNodeData comment1;
+ AXNodeData comment1_text;
+ AXNodeData footnote;
+ AXNodeData footnote_text;
+ AXNodeData definition;
+ AXNodeData button;
+
+ root.id = 1;
+ highlighted1.id = 2;
+ highlighted1_text.id = 3;
+ comment1.id = 4;
+ comment1_text.id = 5;
+ footnote.id = 6;
+ footnote_text.id = 7;
+ definition.id = 8;
+ button.id = 9;
+
+ root.role = ax::mojom::Role::kRootWebArea;
+ root.SetName("root");
+ root.child_ids = {highlighted1.id, comment1.id, footnote.id, definition.id,
+ button.id};
+
+ highlighted1.role = ax::mojom::Role::kMark;
+ highlighted1.AddIntListAttribute(ax::mojom::IntListAttribute::kDetailsIds,
+ {comment1.id, footnote.id, definition.id});
+ highlighted1.child_ids = {highlighted1_text.id};
+
+ highlighted1_text.role = ax::mojom::Role::kStaticText;
+ highlighted1_text.SetName("highlighted 1");
+
+ comment1.role = ax::mojom::Role::kComment;
+ comment1.child_ids = {comment1_text.id};
+
+ comment1_text.role = ax::mojom::Role::kStaticText;
+ comment1_text.SetName("comment 1");
+
+ footnote.role = ax::mojom::Role::kDocFootnote;
+ footnote.child_ids = {footnote_text.id};
+
+ footnote_text.role = ax::mojom::Role::kStaticText;
+ footnote_text.SetName("highligthed 2");
+
+ definition.role = ax::mojom::Role::kDefinition;
+ button.role = ax::mojom::Role::kButton;
+
+ Init(root, highlighted1, highlighted1_text, comment1, comment1_text, footnote,
+ footnote_text, definition, button);
+
+ ComPtr<IRawElementProviderSimple> highlighted1_node =
+ QueryInterfaceFromNode<IRawElementProviderSimple>(
+ GetRootAsAXNode()->children()[0]);
+ ComPtr<IRawElementProviderSimple> comment1_node =
+ QueryInterfaceFromNode<IRawElementProviderSimple>(
+ GetRootAsAXNode()->children()[1]);
+ ComPtr<IRawElementProviderSimple> footnote_node =
+ QueryInterfaceFromNode<IRawElementProviderSimple>(
+ GetRootAsAXNode()->children()[2]);
+ ComPtr<IRawElementProviderSimple> definition_node =
+ QueryInterfaceFromNode<IRawElementProviderSimple>(
+ GetRootAsAXNode()->children()[3]);
+ ComPtr<IRawElementProviderSimple> button_node =
+ QueryInterfaceFromNode<IRawElementProviderSimple>(
+ GetRootAsAXNode()->children()[4]);
+ ComPtr<IAnnotationProvider> annotation_provider;
+ ComPtr<IRawElementProviderSimple> target;
+ int annotation_type;
+ ScopedBstr name;
+
+ {
+ // |highlighted1_node| with Role::kMark should not support
+ // IAnnotationProvider, since it does not have a relation back to the
+ // target.
+ EXPECT_HRESULT_SUCCEEDED(highlighted1_node->GetPatternProvider(
+ UIA_AnnotationPatternId, &annotation_provider));
+ ASSERT_EQ(nullptr, annotation_provider.Get());
+ annotation_provider.Reset();
+ }
+
+ {
+ // |comment1_node| with Role::kComment should support IAnnotationProvider.
+ EXPECT_HRESULT_SUCCEEDED(comment1_node->GetPatternProvider(
+ UIA_AnnotationPatternId, &annotation_provider));
+ ASSERT_NE(nullptr, annotation_provider.Get());
+ EXPECT_HRESULT_SUCCEEDED(
+ annotation_provider->get_AnnotationTypeId(&annotation_type));
+ EXPECT_EQ(AnnotationType_Comment, annotation_type);
+ EXPECT_HRESULT_SUCCEEDED(
+ annotation_provider->get_AnnotationTypeName(name.Receive()));
+ // For common annotation type such as Comment, we return empty string for
+ // the type name, since UIA will provide a default name.
+ EXPECT_EQ(nullptr, name.Get());
+
+ // Retrieve the target from |comment1_node| and verify that it is
+ // |highlighted1_node|.
+ EXPECT_HRESULT_SUCCEEDED(annotation_provider->get_Target(&target));
+ EXPECT_EQ(highlighted1_node.Get(), target.Get());
+ annotation_provider.Reset();
+ target.Reset();
+ name.Release();
+ }
+
+ {
+ // |footnote_node| with Role::kDocFootnote should support
+ // IAnnotationProvider.
+ EXPECT_HRESULT_SUCCEEDED(footnote_node->GetPatternProvider(
+ UIA_AnnotationPatternId, &annotation_provider));
+ ASSERT_NE(nullptr, annotation_provider.Get());
+ EXPECT_HRESULT_SUCCEEDED(
+ annotation_provider->get_AnnotationTypeId(&annotation_type));
+ EXPECT_EQ(AnnotationType_Footnote, annotation_type);
+ EXPECT_HRESULT_SUCCEEDED(
+ annotation_provider->get_AnnotationTypeName(name.Receive()));
+ // For common annotation type such as Footnote, we return empty string for
+ // the type name, since UIA will provide a default name.
+ EXPECT_EQ(nullptr, name.Get());
+
+ // Retrieve the target from |footnote_node| and verify that it is
+ // |highlighted1_node|.
+ EXPECT_HRESULT_SUCCEEDED(annotation_provider->get_Target(&target));
+ EXPECT_EQ(highlighted1_node.Get(), target.Get());
+ annotation_provider.Reset();
+ target.Reset();
+ name.Release();
+ }
+
+ {
+ // |definition_node| with Role::kDefinition should support
+ // IAnnotationProvider.
+ EXPECT_HRESULT_SUCCEEDED(definition_node->GetPatternProvider(
+ UIA_AnnotationPatternId, &annotation_provider));
+ ASSERT_NE(nullptr, annotation_provider.Get());
+ // AnnotationType for Role::kDefinition is currently not implemented, so map
+ // it to AnnotationType_Unknown.
+ EXPECT_HRESULT_SUCCEEDED(
+ annotation_provider->get_AnnotationTypeId(&annotation_type));
+ EXPECT_EQ(AnnotationType_Unknown, annotation_type);
+ EXPECT_HRESULT_SUCCEEDED(
+ annotation_provider->get_AnnotationTypeName(name.Receive()));
+ // Role::kDefinition has AnnotationType_Unknown, we explicitly return the
+ // type name and should be "definition".
+ EXPECT_STREQ(L"definition", name.Get());
+
+ // Retrieve the target from |definition_node| and verify that it is
+ // |highlighted_node|.
+ EXPECT_HRESULT_SUCCEEDED(annotation_provider->get_Target(&target));
+ EXPECT_EQ(highlighted1_node.Get(), target.Get());
+ annotation_provider.Reset();
+ target.Reset();
+ name.Release();
+ }
+
+ {
+ // |button_node| with Role::kButton should not support IAnnotationProvider.
+ EXPECT_HRESULT_SUCCEEDED(button_node->GetPatternProvider(
+ UIA_AnnotationPatternId, &annotation_provider));
+ ASSERT_EQ(nullptr, annotation_provider.Get());
+ }
+}
+
+TEST_F(AXPlatformNodeWinTest, IAnnotationProviderMultipleTargets) {
+ // rootWebArea
+ // ++mark detailsIds=comment
+ // ++++staticText name='highlighted 1'
+ // ++mark detailsIds=comment
+ // ++++staticText name="highlighted 2"
+ // ++docEndnote detailsIds=comment
+ // ++++staticText name="endnote"
+ // ++comment
+ // ++++staticText name='comment 1'
+
+ AXNodeData root;
+ AXNodeData highlighted1;
+ AXNodeData highlighted1_text;
+ AXNodeData highlighted2;
+ AXNodeData highlighted2_text;
+ AXNodeData endnote;
+ AXNodeData endnote_text;
+ AXNodeData comment1;
+ AXNodeData comment1_text;
+
+ root.id = 1;
+ highlighted1.id = 2;
+ highlighted1_text.id = 3;
+ highlighted2.id = 4;
+ highlighted2_text.id = 5;
+ endnote.id = 6;
+ endnote_text.id = 7;
+ comment1.id = 8;
+ comment1_text.id = 9;
+
+ root.role = ax::mojom::Role::kRootWebArea;
+ root.SetName("root");
+ root.child_ids = {highlighted1.id, highlighted2.id, endnote.id, comment1.id};
+
+ highlighted1.role = ax::mojom::Role::kMark;
+ highlighted1.AddIntListAttribute(ax::mojom::IntListAttribute::kDetailsIds,
+ {comment1.id});
+ highlighted1.child_ids = {highlighted1_text.id};
+
+ highlighted1_text.role = ax::mojom::Role::kStaticText;
+ highlighted1_text.SetName("highlighted 1");
+
+ highlighted2.role = ax::mojom::Role::kMark;
+ highlighted2.AddIntListAttribute(ax::mojom::IntListAttribute::kDetailsIds,
+ {comment1.id});
+ highlighted2.child_ids = {highlighted2_text.id};
+
+ highlighted2_text.role = ax::mojom::Role::kStaticText;
+ highlighted2_text.SetName("highlighted 2");
+
+ endnote.role = ax::mojom::Role::kDocEndnote;
+ endnote.AddIntListAttribute(ax::mojom::IntListAttribute::kDetailsIds,
+ {comment1.id});
+ endnote.child_ids = {endnote_text.id};
+
+ endnote_text.role = ax::mojom::Role::kStaticText;
+ endnote_text.SetName("endnote");
+
+ comment1.role = ax::mojom::Role::kComment;
+ comment1.child_ids = {comment1_text.id};
+
+ comment1_text.role = ax::mojom::Role::kStaticText;
+ comment1_text.SetName("comment 1");
+
+ Init(root, highlighted1, highlighted1_text, highlighted2, highlighted2_text,
+ endnote, endnote_text, comment1, comment1_text);
+
+ ComPtr<IRawElementProviderSimple> highlighted1_node =
+ QueryInterfaceFromNode<IRawElementProviderSimple>(
+ GetRootAsAXNode()->children()[0]);
+ ComPtr<IRawElementProviderSimple> comment1_node =
+ QueryInterfaceFromNode<IRawElementProviderSimple>(
+ GetRootAsAXNode()->children()[3]);
+
+ ComPtr<IAnnotationProvider> annotation_provider;
+ ComPtr<IRawElementProviderSimple> target;
+ int annotation_type;
+
+ // |comment1_node| with Role::kComment should support IAnnotationProvider.
+ EXPECT_HRESULT_SUCCEEDED(comment1_node->GetPatternProvider(
+ UIA_AnnotationPatternId, &annotation_provider));
+ ASSERT_NE(nullptr, annotation_provider.Get());
+ EXPECT_HRESULT_SUCCEEDED(
+ annotation_provider->get_AnnotationTypeId(&annotation_type));
+ EXPECT_EQ(AnnotationType_Comment, annotation_type);
+
+ // |comment1_node| is set up as the annotation for both |highlighted1_node|
+ // and |highlighted2_node|, which means it has two targets. Since get_Target
+ // only returns one target, verify that it is |highlighted1_node|.
+ EXPECT_HRESULT_SUCCEEDED(annotation_provider->get_Target(&target));
+ EXPECT_EQ(highlighted1_node.Get(), target.Get());
+}
+
TEST_F(AXPlatformNodeWinTest, ISelectionProviderCanSelectMultipleDefault) {
Init(BuildListBox(/*option_1_is_selected*/ false,
/*option_2_is_selected*/ false,
@@ -5262,6 +5572,7 @@ TEST_F(AXPlatformNodeWinTest, ComputeUIAControlType) {
AXNodeID child3_id = 4;
child3.id = child3_id;
child3.role = ax::mojom::Role::kTextField;
+ child3.AddState(ax::mojom::State::kEditable);
root.child_ids.push_back(child3_id);
AXNodeData child4;
@@ -5297,7 +5608,7 @@ TEST_F(AXPlatformNodeWinTest, ComputeUIAControlType) {
TEST_F(AXPlatformNodeWinTest, UIALandmarkType) {
auto TestLandmarkType = [this](ax::mojom::Role node_role,
- base::Optional<LONG> expected_landmark_type,
+ absl::optional<LONG> expected_landmark_type,
const std::string& node_name = {}) {
AXNodeData root_data;
root_data.id = 1;
@@ -5330,7 +5641,7 @@ TEST_F(AXPlatformNodeWinTest, UIALandmarkType) {
TestLandmarkType(ax::mojom::Role::kForm, UIA_FormLandmarkTypeId, "name");
// Only named regions should be exposed as landmarks.
- TestLandmarkType(ax::mojom::Role::kRegion, {});
+ // Blink handles this, and will not pass a nameless region as a Role::kRegion.
TestLandmarkType(ax::mojom::Role::kRegion, UIA_CustomLandmarkTypeId, "name");
TestLandmarkType(ax::mojom::Role::kGroup, {});
@@ -5676,8 +5987,6 @@ TEST_F(AXPlatformNodeWinTest, GetPatternProviderSupportedPatterns) {
update.nodes[1].id = text_field_with_combo_box_id;
update.nodes[1].role = ax::mojom::Role::kTextFieldWithComboBox;
update.nodes[1].AddState(ax::mojom::State::kEditable);
- update.nodes[1].AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot,
- true);
update.nodes[2].id = meter_id;
update.nodes[2].role = ax::mojom::Role::kMeter;
update.nodes[3].id = group_with_scroll_id;
@@ -6255,10 +6564,10 @@ TEST_F(AXPlatformNodeWinTest,
EXPECT_NE(expandcollapse_provider.Get(), nullptr);
EXPECT_HRESULT_SUCCEEDED(
expandcollapse_provider->get_ExpandCollapseState(&state));
- SCOPED_TRACE(testing::Message()
- << "node index: " << i << ", Actual Expanded/Collapsed State: "
- << state << ", Expected Expanded/Collapsed State: "
- << node_expected_state[i]);
+ SCOPED_TRACE(
+ ::testing::Message()
+ << "node index: " << i << ", Actual Expanded/Collapsed State: " << state
+ << ", Expected Expanded/Collapsed State: " << node_expected_state[i]);
EXPECT_EQ(node_expected_state[i], state);
}
}
@@ -6800,6 +7109,7 @@ TEST_F(AXPlatformNodeWinTest, IValueProvider_GetValue) {
AXNodeData child3;
child3.id = 4;
child3.role = ax::mojom::Role::kTextField;
+ child3.AddState(ax::mojom::State::kEditable);
child3.AddStringAttribute(ax::mojom::StringAttribute::kValue, "test");
child3.AddIntAttribute(ax::mojom::IntAttribute::kRestriction,
static_cast<int>(ax::mojom::Restriction::kReadOnly));
@@ -6865,12 +7175,14 @@ TEST_F(AXPlatformNodeWinTest, IValueProvider_SetValue) {
AXNodeData child2;
child2.id = 3;
child2.role = ax::mojom::Role::kTextField;
+ child2.AddState(ax::mojom::State::kEditable);
child2.AddStringAttribute(ax::mojom::StringAttribute::kValue, "test");
root.child_ids.push_back(child2.id);
AXNodeData child3;
child3.id = 4;
child3.role = ax::mojom::Role::kTextField;
+ child3.AddState(ax::mojom::State::kEditable);
child3.AddStringAttribute(ax::mojom::StringAttribute::kValue, "test");
child3.AddIntAttribute(ax::mojom::IntAttribute::kRestriction,
static_cast<int>(ax::mojom::Restriction::kReadOnly));
@@ -6922,6 +7234,7 @@ TEST_F(AXPlatformNodeWinTest, IValueProvider_IsReadOnly) {
AXNodeData child2;
child2.id = 3;
child2.role = ax::mojom::Role::kTextField;
+ child2.AddState(ax::mojom::State::kEditable);
child2.AddIntAttribute(ax::mojom::IntAttribute::kRestriction,
static_cast<int>(ax::mojom::Restriction::kReadOnly));
root.child_ids.push_back(child2.id);
@@ -6929,6 +7242,7 @@ TEST_F(AXPlatformNodeWinTest, IValueProvider_IsReadOnly) {
AXNodeData child3;
child3.id = 4;
child3.role = ax::mojom::Role::kTextField;
+ child3.AddState(ax::mojom::State::kEditable);
child3.AddIntAttribute(ax::mojom::IntAttribute::kRestriction,
static_cast<int>(ax::mojom::Restriction::kDisabled));
root.child_ids.push_back(child3.id);
@@ -7121,7 +7435,7 @@ TEST_F(AXPlatformNodeWinTest, DISABLED_BulkFetch) {
// Note: base::JSONReader is fine for unit tests, but production code
// that parses untrusted JSON should always use DataDecoder instead.
- base::Optional<base::Value> result =
+ absl::optional<base::Value> result =
base::JSONReader::Read(response, base::JSON_ALLOW_TRAILING_COMMAS);
ASSERT_TRUE(result);
ASSERT_TRUE(result->FindKey("role"));
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.h b/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.h
index f1a31e5fe3c..41b1a1d9c72 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.h
@@ -11,6 +11,7 @@
#include <unordered_set>
#include "base/test/scoped_feature_list.h"
+#include "ui/accessibility/ax_position.h"
#include "ui/accessibility/platform/ax_fragment_root_delegate_win.h"
#include "ui/base/win/accessibility_misc_utils.h"
@@ -129,7 +130,7 @@ class AXPlatformNodeWinTest : public AXPlatformNodeTest {
std::unique_ptr<AXFragmentRootWin> ax_fragment_root_;
std::unique_ptr<TestFragmentRootDelegate> test_fragment_root_delegate_;
-
+ testing::ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior_;
base::test::ScopedFeatureList scoped_feature_list_;
};
diff --git a/chromium/ui/accessibility/platform/compute_attributes.cc b/chromium/ui/accessibility/platform/compute_attributes.cc
index 63280ae9445..ed50874bac8 100644
--- a/chromium/ui/accessibility/platform/compute_attributes.cc
+++ b/chromium/ui/accessibility/platform/compute_attributes.cc
@@ -6,7 +6,7 @@
#include <cstddef>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/platform/ax_platform_node_delegate.h"
@@ -14,7 +14,7 @@
namespace ui {
namespace {
-base::Optional<int32_t> GetCellAttribute(
+absl::optional<int32_t> GetCellAttribute(
const ui::AXPlatformNodeDelegate* delegate,
ax::mojom::IntAttribute attribute) {
switch (attribute) {
@@ -31,20 +31,20 @@ base::Optional<int32_t> GetCellAttribute(
case ax::mojom::IntAttribute::kTableCellRowSpan:
return delegate->GetTableCellRowSpan();
default:
- return base::nullopt;
+ return absl::nullopt;
}
}
-base::Optional<int32_t> GetRowAttribute(
+absl::optional<int32_t> GetRowAttribute(
const ui::AXPlatformNodeDelegate* delegate,
ax::mojom::IntAttribute attribute) {
if (attribute == ax::mojom::IntAttribute::kTableRowIndex) {
return delegate->GetTableRowRowIndex();
}
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<int32_t> GetTableAttribute(
+absl::optional<int32_t> GetTableAttribute(
const ui::AXPlatformNodeDelegate* delegate,
ax::mojom::IntAttribute attribute) {
switch (attribute) {
@@ -57,11 +57,11 @@ base::Optional<int32_t> GetTableAttribute(
case ax::mojom::IntAttribute::kAriaRowCount:
return delegate->GetTableAriaRowCount();
default:
- return base::nullopt;
+ return absl::nullopt;
}
}
-base::Optional<int> GetOrderedSetItemAttribute(
+absl::optional<int> GetOrderedSetItemAttribute(
const ui::AXPlatformNodeDelegate* delegate,
ax::mojom::IntAttribute attribute) {
switch (attribute) {
@@ -70,36 +70,36 @@ base::Optional<int> GetOrderedSetItemAttribute(
case ax::mojom::IntAttribute::kSetSize:
return delegate->GetSetSize();
default:
- return base::nullopt;
+ return absl::nullopt;
}
}
-base::Optional<int> GetOrderedSetAttribute(
+absl::optional<int> GetOrderedSetAttribute(
const ui::AXPlatformNodeDelegate* delegate,
ax::mojom::IntAttribute attribute) {
switch (attribute) {
case ax::mojom::IntAttribute::kSetSize:
return delegate->GetSetSize();
default:
- return base::nullopt;
+ return absl::nullopt;
}
}
-base::Optional<int32_t> GetFromData(const ui::AXPlatformNodeDelegate* delegate,
+absl::optional<int32_t> GetFromData(const ui::AXPlatformNodeDelegate* delegate,
ax::mojom::IntAttribute attribute) {
int32_t value;
if (delegate->GetData().GetIntAttribute(attribute, &value)) {
return value;
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace
-base::Optional<int32_t> ComputeAttribute(
+absl::optional<int32_t> ComputeAttribute(
const ui::AXPlatformNodeDelegate* delegate,
ax::mojom::IntAttribute attribute) {
- base::Optional<int32_t> maybe_value = base::nullopt;
+ absl::optional<int32_t> maybe_value = absl::nullopt;
// Color-related attributes.
if (attribute == ax::mojom::IntAttribute::kColor)
diff --git a/chromium/ui/accessibility/platform/compute_attributes.h b/chromium/ui/accessibility/platform/compute_attributes.h
index f0e82a0a0b3..436d5d6306d 100644
--- a/chromium/ui/accessibility/platform/compute_attributes.h
+++ b/chromium/ui/accessibility/platform/compute_attributes.h
@@ -7,7 +7,7 @@
#include <cstddef>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_enums.mojom-forward.h"
#include "ui/accessibility/ax_export.h"
@@ -17,7 +17,7 @@ class AXPlatformNodeDelegate;
// Compute the attribute value instead of returning the "raw" attribute value
// for those attributes that have computation methods.
-AX_EXPORT base::Optional<int32_t> ComputeAttribute(
+AX_EXPORT absl::optional<int32_t> ComputeAttribute(
const ui::AXPlatformNodeDelegate* delegate,
ax::mojom::IntAttribute attribute);
diff --git a/chromium/ui/accessibility/platform/inspect/ax_inspect.h b/chromium/ui/accessibility/platform/inspect/ax_inspect.h
index a7550792c56..d3def966d95 100644
--- a/chromium/ui/accessibility/platform/inspect/ax_inspect.h
+++ b/chromium/ui/accessibility/platform/inspect/ax_inspect.h
@@ -52,9 +52,7 @@ struct AX_EXPORT AXTreeSelector {
// For example, :1,:3;AXDOMClassList=*
// will query a AXDOMClassList attribute on accessible objects placed at 1st
// and 3rd lines in the output accessible tree.
-// Also see
-// DumpAccessibilityTestBase::ParseHtmlForExtraDirectives() for more
-// information.
+// Also see AXInspectScenario::From() for more information.
struct AX_EXPORT AXPropertyFilter {
enum Type { ALLOW, ALLOW_EMPTY, DENY, SCRIPT };
diff --git a/chromium/ui/accessibility/platform/inspect/ax_inspect_scenario.cc b/chromium/ui/accessibility/platform/inspect/ax_inspect_scenario.cc
index 6a6210e6013..1ea150f5221 100644
--- a/chromium/ui/accessibility/platform/inspect/ax_inspect_scenario.cc
+++ b/chromium/ui/accessibility/platform/inspect/ax_inspect_scenario.cc
@@ -25,24 +25,37 @@ AXInspectScenario AXInspectScenario::From(
const std::vector<std::string>& lines,
const std::vector<ui::AXPropertyFilter>& default_filters) {
AXInspectScenario scenario(default_filters);
+ Directive directive = kNone;
+ // Directives have format of @directive:value[..value], value per line.
for (const std::string& line : lines) {
- // Directives have format of @directive:value.
+ // Treat empty line the multiline directive end.
+ if (line.empty()) {
+ directive = kNone;
+ }
+
+ // Implicit directive case: use the most recent directive.
if (!base::StartsWith(line, "@")) {
+ if (directive != kNone) {
+ std::string value(base::TrimWhitespaceASCII(line, base::TRIM_ALL));
+ if (!value.empty())
+ scenario.ProcessDirective(directive, value);
+ }
continue;
}
+ // Parse directive.
auto directive_end_pos = line.find_first_of(':');
- if (directive_end_pos == std::string::npos) {
+ if (directive_end_pos == std::string::npos)
continue;
- }
- Directive directive =
+ directive =
ParseDirective(directive_prefix, line.substr(0, directive_end_pos));
if (directive == kNone)
continue;
std::string value = line.substr(directive_end_pos + 1);
- scenario.ProcessDirective(directive, value);
+ if (!value.empty())
+ scenario.ProcessDirective(directive, value);
}
return scenario;
}
diff --git a/chromium/ui/accessibility/platform/inspect/ax_inspect_scenario_unittest.cc b/chromium/ui/accessibility/platform/inspect/ax_inspect_scenario_unittest.cc
new file mode 100644
index 00000000000..e6e79b41a24
--- /dev/null
+++ b/chromium/ui/accessibility/platform/inspect/ax_inspect_scenario_unittest.cc
@@ -0,0 +1,84 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/platform/inspect/ax_inspect_scenario.h"
+
+#include "testing/gmock/include/gmock/gmock-matchers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/platform/inspect/ax_inspect.h"
+
+namespace ui {
+
+class AXInspectScenarioTest : public testing::Test {
+ public:
+ AXInspectScenarioTest() = default;
+ ~AXInspectScenarioTest() override = default;
+
+ AXInspectScenarioTest(const AXInspectScenarioTest&) = delete;
+ AXInspectScenarioTest& operator=(const AXInspectScenarioTest&) = delete;
+};
+
+TEST_F(AXInspectScenarioTest, NoLoadExpected) {
+ AXInspectScenario scenario =
+ AXInspectScenario::From("@MAC", {"@NO-LOAD-EXPECTED:broken.jpg"});
+ EXPECT_THAT(scenario.no_load_expected, testing::ElementsAre("broken.jpg"));
+}
+
+TEST_F(AXInspectScenarioTest, WaitFor) {
+ AXInspectScenario scenario =
+ AXInspectScenario::From("@MAC", {"@WAIT-FOR:(0, 50"});
+ EXPECT_THAT(scenario.wait_for, testing::ElementsAre("(0, 50"));
+}
+
+TEST_F(AXInspectScenarioTest, DefaultActionOn) {
+ AXInspectScenario scenario =
+ AXInspectScenario::From("@MAC", {"@DEFAULT-ACTION-ON:Show time picker"});
+ EXPECT_THAT(scenario.default_action_on,
+ testing::ElementsAre("Show time picker"));
+}
+
+TEST_F(AXInspectScenarioTest, ExecuteAndWaitFor) {
+ AXInspectScenario scenario =
+ AXInspectScenario::From("@MAC", {"@EXECUTE-AND-WAIT-FOR:open_modal()"});
+ EXPECT_THAT(scenario.execute, testing::ElementsAre("open_modal()"));
+}
+
+TEST_F(AXInspectScenarioTest, RunUntil) {
+ AXInspectScenario scenario =
+ AXInspectScenario::From("@MAC", {"@MAC-RUN-UNTIL-EVENT:AXRowCollapsed"});
+ EXPECT_THAT(scenario.run_until, testing::ElementsAre("AXRowCollapsed"));
+}
+
+TEST_F(AXInspectScenarioTest, PropertyFilters) {
+ AXInspectScenario scenario = AXInspectScenario::From(
+ "@MAC", {"@MAC-ALLOW:AXRoleDescription", "@MAC-ALLOW-EMPTY:AXARIALive",
+ "@MAC-DENY:AXTitle"});
+ EXPECT_EQ(scenario.property_filters.size(), 3U);
+ EXPECT_EQ(scenario.property_filters[0].type, AXPropertyFilter::ALLOW);
+ EXPECT_EQ(scenario.property_filters[0].match_str, "AXRoleDescription");
+ EXPECT_EQ(scenario.property_filters[1].type, AXPropertyFilter::ALLOW_EMPTY);
+ EXPECT_EQ(scenario.property_filters[1].match_str, "AXARIALive");
+ EXPECT_EQ(scenario.property_filters[2].type, AXPropertyFilter::DENY);
+ EXPECT_EQ(scenario.property_filters[2].match_str, "AXTitle");
+}
+
+TEST_F(AXInspectScenarioTest, PropertyFilters_Multiline) {
+ AXInspectScenario scenario = AXInspectScenario::From(
+ "@MAC", {"@MAC-ALLOW:", " AXRoleDescription", " AXARIALive"});
+ EXPECT_EQ(scenario.property_filters.size(), 2U);
+ EXPECT_EQ(scenario.property_filters[0].type, AXPropertyFilter::ALLOW);
+ EXPECT_EQ(scenario.property_filters[0].match_str, "AXRoleDescription");
+ EXPECT_EQ(scenario.property_filters[1].type, AXPropertyFilter::ALLOW);
+ EXPECT_EQ(scenario.property_filters[1].match_str, "AXARIALive");
+}
+
+TEST_F(AXInspectScenarioTest, NodeFilters) {
+ AXInspectScenario scenario =
+ AXInspectScenario::From("@MAC", {"@MAC-DENY-NODE:AXRole=AXCheckBox"});
+ EXPECT_EQ(scenario.node_filters.size(), 1U);
+ EXPECT_EQ(scenario.node_filters[0].property, "AXRole");
+ EXPECT_EQ(scenario.node_filters[0].pattern, "AXCheckBox");
+}
+
+} // namespace ui
diff --git a/chromium/ui/accessibility/platform/inspect/ax_inspect_utils.cc b/chromium/ui/accessibility/platform/inspect/ax_inspect_utils.cc
new file mode 100644
index 00000000000..401cc293a34
--- /dev/null
+++ b/chromium/ui/accessibility/platform/inspect/ax_inspect_utils.cc
@@ -0,0 +1,98 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/platform/inspect/ax_inspect_utils.h"
+
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/values.h"
+
+namespace ui {
+
+constexpr char kConstValuePrefix[] = "_const_";
+constexpr char kSetKeyPrefixDictAttr[] = "_setkey_";
+constexpr char kOrderedKeyPrefixDictAttr[] = "_index_";
+
+std::string AXMakeConst(const std::string& value) {
+ return kConstValuePrefix + value;
+}
+
+std::string AXMakeSetKey(const std::string& key_name) {
+ return kSetKeyPrefixDictAttr + key_name;
+}
+
+std::string AXMakeOrderedKey(const std::string& key_name, int position) {
+ // Works for single-diget orders.
+ return kOrderedKeyPrefixDictAttr + base::NumberToString(position) + key_name;
+}
+
+std::string AXFormatValue(const base::Value& value) {
+ // String.
+ if (value.is_string()) {
+ // Special handling for constants which are exposed as is, i.e. with no
+ // quotation marks.
+ std::string const_prefix = kConstValuePrefix;
+ if (base::StartsWith(value.GetString(), const_prefix,
+ base::CompareCase::SENSITIVE)) {
+ return value.GetString().substr(const_prefix.length());
+ }
+ return "'" + value.GetString() + "'";
+ }
+
+ // Integer.
+ if (value.is_int()) {
+ return base::NumberToString(value.GetInt());
+ }
+
+ // Double.
+ if (value.is_double()) {
+ return base::NumberToString(value.GetDouble());
+ }
+
+ // List: exposed as [value1, ..., valueN];
+ if (value.is_list()) {
+ std::string output;
+ for (const auto& item : value.GetList()) {
+ if (!output.empty()) {
+ output += ", ";
+ }
+ output += AXFormatValue(item);
+ }
+ return "[" + output + "]";
+ }
+
+ // Dictionary. Exposed as {key1: value1, ..., keyN: valueN}. Set-like
+ // dictionary is exposed as {value1, ..., valueN}.
+ if (value.is_dict()) {
+ const std::string setkey_prefix(kSetKeyPrefixDictAttr);
+ const std::string orderedkey_prefix(kOrderedKeyPrefixDictAttr);
+
+ std::string output;
+ for (const auto& item : value.DictItems()) {
+ if (!output.empty()) {
+ output += ", ";
+ }
+ if (base::StartsWith(item.first, setkey_prefix,
+ base::CompareCase::SENSITIVE)) {
+ // Some of the dictionary's keys should not be appended to the output,
+ // so that the dictionary can also be used as a set. Such keys start
+ // with the _setkey_ prefix.
+ output += AXFormatValue(item.second);
+ } else if (base::StartsWith(item.first, orderedkey_prefix,
+ base::CompareCase::SENSITIVE)) {
+ // Process ordered dictionaries. Remove order number from keys before
+ // formatting.
+ std::string key = item.first;
+ key.erase(0, orderedkey_prefix.length() + 1);
+ output += key + ": " + AXFormatValue(item.second);
+ } else {
+ output += item.first + ": " + AXFormatValue(item.second);
+ }
+ }
+ return "{" + output + "}";
+ }
+ return "";
+}
+
+} // namespace ui
diff --git a/chromium/ui/accessibility/platform/inspect/ax_inspect_utils.h b/chromium/ui/accessibility/platform/inspect/ax_inspect_utils.h
new file mode 100644
index 00000000000..bd1b81796df
--- /dev/null
+++ b/chromium/ui/accessibility/platform/inspect/ax_inspect_utils.h
@@ -0,0 +1,45 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ACCESSIBILITY_PLATFORM_INSPECT_AX_INSPECT_UTILS_H_
+#define UI_ACCESSIBILITY_PLATFORM_INSPECT_AX_INSPECT_UTILS_H_
+
+#include <string>
+
+#include "ui/accessibility/ax_export.h"
+
+namespace base {
+class Value;
+} // namespace base
+
+namespace ui {
+
+/**
+ * Constructs a const formattable value. Refers to FormatValue.
+ */
+std::string AX_EXPORT AXMakeConst(const std::string& value);
+
+/**
+ * Constructs a key for a formattable set represented by dictionary. It adds
+ * the _setkey_ prefix to a string key. Refers to FormatValue.
+ */
+std::string AX_EXPORT AXMakeSetKey(const std::string& key_name);
+
+/**
+ * Constructs an ordered key for a formattable dictionary by appending position
+ * number to a string key for sorting. It makes the keys to be traversed
+ * according to their position when the dictionary is formatted. Refers to
+ * FormatValue.
+ */
+std::string AX_EXPORT AXMakeOrderedKey(const std::string& key_name,
+ int position);
+
+/**
+ * Formats a value.
+ */
+std::string AX_EXPORT AXFormatValue(const base::Value& value);
+
+} // namespace ui
+
+#endif // UI_ACCESSIBILITY_PLATFORM_INSPECT_AX_INSPECT_UTILS_H_
diff --git a/chromium/ui/accessibility/platform/inspect/ax_inspect_utils_unittest.cc b/chromium/ui/accessibility/platform/inspect/ax_inspect_utils_unittest.cc
new file mode 100644
index 00000000000..2e1d57199c1
--- /dev/null
+++ b/chromium/ui/accessibility/platform/inspect/ax_inspect_utils_unittest.cc
@@ -0,0 +1,65 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/platform/inspect/ax_inspect_utils.h"
+
+#include <string>
+
+#include "base/values.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ui {
+
+TEST(AXInspectUtilsTest, FormatString) {
+ base::Value value("hey");
+ EXPECT_EQ(AXFormatValue(value), std::string("'hey'"));
+}
+
+TEST(AXInspectUtilsTest, FormatConst) {
+ base::Value value(AXMakeConst("hey"));
+ EXPECT_EQ(AXFormatValue(value), std::string("hey"));
+}
+
+TEST(AXInspectUtilsTest, FormatInteger) {
+ base::Value value(3);
+ EXPECT_EQ(AXFormatValue(value), std::string("3"));
+}
+
+TEST(AXInspectUtilsTest, FormatDouble) {
+ base::Value value(3.3);
+ EXPECT_EQ(AXFormatValue(value), std::string("3.3"));
+}
+
+TEST(AXInspectUtilsTest, FormatList) {
+ base::Value list(base::Value::Type::LIST);
+ list.Append("item1");
+ list.Append("item2");
+ EXPECT_EQ(AXFormatValue(list), std::string("['item1', 'item2']"));
+}
+
+TEST(AXInspectUtilsTest, FormatDict) {
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetStringPath("anchor", AXMakeConst("textbox"));
+ dict.SetIntPath("offset", 2);
+ dict.SetStringPath("affinity", AXMakeConst("down"));
+ EXPECT_EQ(AXFormatValue(dict),
+ std::string("{affinity: down, anchor: textbox, offset: 2}"));
+}
+
+TEST(AXInspectUtilsTest, FormatSet) {
+ base::Value set(base::Value::Type::DICTIONARY);
+ set.SetStringPath(AXMakeSetKey("index1_anchor"), AXMakeConst(":1"));
+ set.SetIntPath(AXMakeSetKey("index2_offset"), 2);
+ set.SetStringPath(AXMakeSetKey("index3_affinity"), AXMakeConst("down"));
+ EXPECT_EQ(AXFormatValue(set), std::string("{:1, 2, down}"));
+}
+
+TEST(AXInspectUtilsTest, FormatOrderedDict) {
+ base::Value ordered_dict(base::Value::Type::DICTIONARY);
+ ordered_dict.SetIntPath(AXMakeOrderedKey("w", 0), 40);
+ ordered_dict.SetIntPath(AXMakeOrderedKey("h", 1), 30);
+ EXPECT_EQ(AXFormatValue(ordered_dict), std::string("{w: 40, h: 30}"));
+}
+
+} // namespace ui
diff --git a/chromium/ui/accessibility/platform/inspect/ax_inspect_utils_win.cc b/chromium/ui/accessibility/platform/inspect/ax_inspect_utils_win.cc
index 651f582d7ee..c98ad2741e8 100644
--- a/chromium/ui/accessibility/platform/inspect/ax_inspect_utils_win.cc
+++ b/chromium/ui/accessibility/platform/inspect/ax_inspect_utils_win.cc
@@ -9,6 +9,7 @@
#include <map>
#include <string>
+#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/stl_util.h"
#include "base/strings/pattern.h"
diff --git a/chromium/ui/accessibility/platform/inspect/ax_property_node.cc b/chromium/ui/accessibility/platform/inspect/ax_property_node.cc
index 74b10a1b4d5..d21a595e775 100644
--- a/chromium/ui/accessibility/platform/inspect/ax_property_node.cc
+++ b/chromium/ui/accessibility/platform/inspect/ax_property_node.cc
@@ -4,9 +4,9 @@
#include "ui/accessibility/platform/inspect/ax_property_node.h"
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/platform/inspect/ax_inspect.h"
namespace ui {
@@ -78,10 +78,10 @@ bool AXPropertyNode::IsDict() const {
return name_or_value == "{}";
}
-base::Optional<int> AXPropertyNode::AsInt() const {
+absl::optional<int> AXPropertyNode::AsInt() const {
int value = 0;
if (!base::StringToInt(name_or_value, &value)) {
- return base::nullopt;
+ return absl::nullopt;
}
return value;
}
@@ -95,23 +95,23 @@ const AXPropertyNode* AXPropertyNode::FindKey(const char* refkey) const {
return nullptr;
}
-base::Optional<std::string> AXPropertyNode::FindStringKey(
+absl::optional<std::string> AXPropertyNode::FindStringKey(
const char* refkey) const {
for (const auto& param : parameters) {
if (param.key == refkey) {
return param.name_or_value;
}
}
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<int> AXPropertyNode::FindIntKey(const char* refkey) const {
+absl::optional<int> AXPropertyNode::FindIntKey(const char* refkey) const {
for (const auto& param : parameters) {
if (param.key == refkey) {
return param.AsInt();
}
}
- return base::nullopt;
+ return absl::nullopt;
}
std::string AXPropertyNode::ToString() const {
diff --git a/chromium/ui/accessibility/platform/inspect/ax_property_node.h b/chromium/ui/accessibility/platform/inspect/ax_property_node.h
index e9033b8fdda..42e058eaa91 100644
--- a/chromium/ui/accessibility/platform/inspect/ax_property_node.h
+++ b/chromium/ui/accessibility/platform/inspect/ax_property_node.h
@@ -8,13 +8,9 @@
#include <string>
#include <vector>
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_export.h"
-namespace base {
-template <typename T>
-class Optional;
-}
-
namespace ui {
struct AXPropertyFilter;
@@ -66,10 +62,10 @@ class AX_EXPORT AXPropertyNode final {
// Argument conversion methods.
bool IsArray() const;
bool IsDict() const;
- base::Optional<int> AsInt() const;
+ absl::optional<int> AsInt() const;
const AXPropertyNode* FindKey(const char* refkey) const;
- base::Optional<std::string> FindStringKey(const char* refkey) const;
- base::Optional<int> FindIntKey(const char* key) const;
+ absl::optional<std::string> FindStringKey(const char* refkey) const;
+ absl::optional<int> FindIntKey(const char* key) const;
std::string ToString() const;
diff --git a/chromium/ui/accessibility/platform/inspect/ax_property_node_unittest.cc b/chromium/ui/accessibility/platform/inspect/ax_property_node_unittest.cc
index 17cde27a2df..198167dd660 100644
--- a/chromium/ui/accessibility/platform/inspect/ax_property_node_unittest.cc
+++ b/chromium/ui/accessibility/platform/inspect/ax_property_node_unittest.cc
@@ -4,8 +4,9 @@
#include "ui/accessibility/platform/inspect/ax_property_node.h"
+#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/accessibility/ax_enums.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/platform/inspect/ax_inspect.h"
using ui::AXPropertyFilter;
@@ -119,13 +120,13 @@ TEST_F(AXPropertyNodeTest, ParseProperty) {
"forward");
EXPECT_EQ(GetArgumentNode("Text({start: :1, dir: forward})")
.FindStringKey("notexists"),
- base::nullopt);
+ absl::nullopt);
// Dict: FindIntKey
EXPECT_EQ(GetArgumentNode("Text({loc: 3, len: 2})").FindIntKey("loc"), 3);
EXPECT_EQ(GetArgumentNode("Text({loc: 3, len: 2})").FindIntKey("len"), 2);
EXPECT_EQ(GetArgumentNode("Text({loc: 3, len: 2})").FindIntKey("notexists"),
- base::nullopt);
+ absl::nullopt);
// Dict: FindKey
EXPECT_EQ(GetArgumentNode("Text({anchor: {:1, 0, up}})")
diff --git a/chromium/ui/accessibility/platform/inspect/ax_tree_formatter_base.cc b/chromium/ui/accessibility/platform/inspect/ax_tree_formatter_base.cc
index 6090b835340..c0496a893e5 100644
--- a/chromium/ui/accessibility/platform/inspect/ax_tree_formatter_base.cc
+++ b/chromium/ui/accessibility/platform/inspect/ax_tree_formatter_base.cc
@@ -8,6 +8,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "ui/accessibility/ax_tree_id.h"
+#include "ui/accessibility/platform/ax_platform_node_delegate.h"
#include "ui/accessibility/platform/inspect/ax_property_node.h"
namespace ui {
@@ -29,6 +30,26 @@ AXTreeFormatterBase::~AXTreeFormatterBase() = default;
const char AXTreeFormatterBase::kChildrenDictAttr[] = "children";
const char AXTreeFormatterBase::kScriptsDictAttr[] = "scripts";
+bool AXTreeFormatterBase::ShouldDumpNode(
+ const AXPlatformNodeDelegate& node) const {
+ for (const std::pair<ax::mojom::StringAttribute, std::string>&
+ string_attribute : node.GetData().string_attributes) {
+ if (string_attribute.second.find(kSkipString) != std::string::npos)
+ return false;
+ }
+ return true;
+}
+
+bool AXTreeFormatterBase::ShouldDumpChildren(
+ const AXPlatformNodeDelegate& node) const {
+ for (const std::pair<ax::mojom::StringAttribute, std::string>&
+ string_attribute : node.GetData().string_attributes) {
+ if (string_attribute.second.find(kSkipChildren) != std::string::npos)
+ return false;
+ }
+ return true;
+}
+
std::string AXTreeFormatterBase::Format(AXPlatformNodeDelegate* root) const {
DCHECK(root);
return FormatTree(BuildTree(root));
@@ -76,9 +97,15 @@ void AXTreeFormatterBase::RecursiveFormatTree(const base::Value& dict,
if (MatchesNodeFilters(dict))
return;
+ if (dict.DictEmpty())
+ return;
+
std::string indent = std::string(depth * kIndentSymbolCount, kIndentSymbol);
std::string line =
indent + ProcessTreeForOutput(base::Value::AsDictionaryValue(dict));
+
+ // TODO(accessibility): This can be removed once the UIA tree formatter
+ // can call ShouldDumpNode().
if (line.find(kSkipString) != std::string::npos)
return;
@@ -89,6 +116,9 @@ void AXTreeFormatterBase::RecursiveFormatTree(const base::Value& dict,
base::ReplaceChars(line, "\n", "<newline>", &line);
*contents += line + "\n";
+
+ // TODO(accessibility): This can be removed once the UIA tree formatter
+ // can call ShouldDumpChildren().
if (line.find(kSkipChildren) != std::string::npos)
return;
diff --git a/chromium/ui/accessibility/platform/inspect/ax_tree_formatter_base.h b/chromium/ui/accessibility/platform/inspect/ax_tree_formatter_base.h
index 45e80bfb231..b53da126acd 100644
--- a/chromium/ui/accessibility/platform/inspect/ax_tree_formatter_base.h
+++ b/chromium/ui/accessibility/platform/inspect/ax_tree_formatter_base.h
@@ -23,6 +23,9 @@ class AX_EXPORT AXTreeFormatterBase : public AXTreeFormatter {
AXTreeFormatterBase();
~AXTreeFormatterBase() override;
+ bool ShouldDumpNode(const AXPlatformNodeDelegate& node) const;
+ bool ShouldDumpChildren(const AXPlatformNodeDelegate& node) const;
+
// Dumps formatted the given accessibility tree into a string.
std::string Format(AXPlatformNodeDelegate* root) const override;
diff --git a/chromium/ui/accessibility/platform/inspect/ax_tree_indexer.h b/chromium/ui/accessibility/platform/inspect/ax_tree_indexer.h
new file mode 100644
index 00000000000..e188614da04
--- /dev/null
+++ b/chromium/ui/accessibility/platform/inspect/ax_tree_indexer.h
@@ -0,0 +1,86 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ACCESSIBILITY_PLATFORM_INSPECT_AX_TREE_INDEXER_H_
+#define UI_ACCESSIBILITY_PLATFORM_INSPECT_AX_TREE_INDEXER_H_
+
+#include <string>
+
+#include "base/strings/string_number_conversions.h"
+#include "ui/accessibility/ax_export.h"
+
+namespace ui {
+
+/**
+ * Indexes an accessible tree: associates each accessible node of the tree
+ * with its DOM id (if any) and to a line index in the formatted accessible
+ * tree the node is placed at.
+ *
+ * GetDOMId returns DOM id by an accessible node;
+ * ChildrenContainer returns accessible children for an accessible node;
+ * Compare is the Compare named requirements, used to compare two nodes.
+ */
+template <std::string (*GetDOMId)(const gfx::NativeViewAccessible),
+ typename ChildrenContainer,
+ ChildrenContainer (*GetChildren)(const gfx::NativeViewAccessible),
+ typename Compare = std::less<gfx::NativeViewAccessible>>
+class AX_EXPORT AXTreeIndexer final {
+ public:
+ explicit AXTreeIndexer(const gfx::NativeViewAccessible node) {
+ int counter = 0;
+ Build(node, &counter);
+ }
+ virtual ~AXTreeIndexer() {}
+
+ // Returns a line index in the formatted tree the node is placed at.
+ std::string IndexBy(const gfx::NativeViewAccessible node) const {
+ std::string line_index = ":unknown";
+ auto iter = node_to_identifier_.find(node);
+ if (iter != node_to_identifier_.end()) {
+ line_index = iter->second.line_index;
+ }
+ return line_index;
+ }
+
+ // Finds a first match either by a line number in :LINE_NUM format or by DOM
+ // id.
+ gfx::NativeViewAccessible NodeBy(const std::string& identifier) const {
+ for (auto& item : node_to_identifier_) {
+ if (item.second.line_index == identifier ||
+ item.second.DOMid == identifier) {
+ return item.first;
+ }
+ }
+ return nullptr;
+ }
+
+ private:
+ void Build(const gfx::NativeViewAccessible node, int* counter) {
+ const std::string line_index =
+ std::string(1, ':') + base::NumberToString(++(*counter));
+ const std::string domid = GetDOMId(node);
+
+ node_to_identifier_.insert({node, {line_index, domid}});
+
+ auto children = GetChildren(node);
+ for (gfx::NativeViewAccessible child in children) {
+ Build(child, counter);
+ }
+ }
+
+ struct NodeIdentifier {
+ std::string line_index;
+ std::string DOMid;
+ };
+
+ // Map between accessible objects and their identificators which can be a line
+ // index the object is placed at in an accessible tree or its DOM id
+ // attribute.
+ std::map<const gfx::NativeViewAccessible, NodeIdentifier, Compare>
+ node_to_identifier_;
+};
+
+} // namespace ui
+
+#endif // UI_ACCESSIBILITY_PLATFORM_INSPECT_AX_TREE_INDEXER_H_
diff --git a/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc b/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc
index 14f827c5072..cbe632fbd41 100644
--- a/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc
+++ b/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc
@@ -120,6 +120,18 @@ void TestAXNodeWrapper::SetHitTestResult(AXNodeID src_node_id,
g_hit_test_result[src_node_id] = dst_node_id;
}
+// static
+void TestAXNodeWrapper::ResetGlobalState() {
+ g_node_id_to_wrapper_map.clear();
+ g_focused_node_in_tree.clear();
+ g_hit_test_result.clear();
+ g_node_from_last_show_context_menu = nullptr;
+ g_node_from_last_default_action = nullptr;
+ g_scale_factor = 1.0;
+ g_offset.set_x(0);
+ g_offset.set_y(0);
+}
+
TestAXNodeWrapper::~TestAXNodeWrapper() {
platform_node_->Destroy();
}
@@ -439,27 +451,27 @@ bool TestAXNodeWrapper::IsTable() const {
return node_->IsTable();
}
-base::Optional<int> TestAXNodeWrapper::GetTableRowCount() const {
+absl::optional<int> TestAXNodeWrapper::GetTableRowCount() const {
return node_->GetTableRowCount();
}
-base::Optional<int> TestAXNodeWrapper::GetTableColCount() const {
+absl::optional<int> TestAXNodeWrapper::GetTableColCount() const {
return node_->GetTableColCount();
}
-base::Optional<int> TestAXNodeWrapper::GetTableAriaRowCount() const {
+absl::optional<int> TestAXNodeWrapper::GetTableAriaRowCount() const {
return node_->GetTableAriaRowCount();
}
-base::Optional<int> TestAXNodeWrapper::GetTableAriaColCount() const {
+absl::optional<int> TestAXNodeWrapper::GetTableAriaColCount() const {
return node_->GetTableAriaColCount();
}
-base::Optional<int> TestAXNodeWrapper::GetTableCellCount() const {
+absl::optional<int> TestAXNodeWrapper::GetTableCellCount() const {
return node_->GetTableCellCount();
}
-base::Optional<bool> TestAXNodeWrapper::GetTableHasColumnOrRowHeaderNode()
+absl::optional<bool> TestAXNodeWrapper::GetTableHasColumnOrRowHeaderNode()
const {
return node_->GetTableHasColumnOrRowHeaderNode();
}
@@ -486,7 +498,7 @@ bool TestAXNodeWrapper::IsTableRow() const {
return node_->IsTableRow();
}
-base::Optional<int> TestAXNodeWrapper::GetTableRowRowIndex() const {
+absl::optional<int> TestAXNodeWrapper::GetTableRowRowIndex() const {
return node_->GetTableRowRowIndex();
}
@@ -494,39 +506,39 @@ bool TestAXNodeWrapper::IsTableCellOrHeader() const {
return node_->IsTableCellOrHeader();
}
-base::Optional<int> TestAXNodeWrapper::GetTableCellIndex() const {
+absl::optional<int> TestAXNodeWrapper::GetTableCellIndex() const {
return node_->GetTableCellIndex();
}
-base::Optional<int> TestAXNodeWrapper::GetTableCellColIndex() const {
+absl::optional<int> TestAXNodeWrapper::GetTableCellColIndex() const {
return node_->GetTableCellColIndex();
}
-base::Optional<int> TestAXNodeWrapper::GetTableCellRowIndex() const {
+absl::optional<int> TestAXNodeWrapper::GetTableCellRowIndex() const {
return node_->GetTableCellRowIndex();
}
-base::Optional<int> TestAXNodeWrapper::GetTableCellColSpan() const {
+absl::optional<int> TestAXNodeWrapper::GetTableCellColSpan() const {
return node_->GetTableCellColSpan();
}
-base::Optional<int> TestAXNodeWrapper::GetTableCellRowSpan() const {
+absl::optional<int> TestAXNodeWrapper::GetTableCellRowSpan() const {
return node_->GetTableCellRowSpan();
}
-base::Optional<int> TestAXNodeWrapper::GetTableCellAriaColIndex() const {
+absl::optional<int> TestAXNodeWrapper::GetTableCellAriaColIndex() const {
return node_->GetTableCellAriaColIndex();
}
-base::Optional<int> TestAXNodeWrapper::GetTableCellAriaRowIndex() const {
+absl::optional<int> TestAXNodeWrapper::GetTableCellAriaRowIndex() const {
return node_->GetTableCellAriaRowIndex();
}
-base::Optional<int32_t> TestAXNodeWrapper::GetCellId(int row_index,
+absl::optional<int32_t> TestAXNodeWrapper::GetCellId(int row_index,
int col_index) const {
AXNode* cell = node_->GetTableCellFromCoords(row_index, col_index);
if (!cell)
- return base::nullopt;
+ return absl::nullopt;
return cell->id();
}
@@ -535,10 +547,10 @@ TestAXNodeWrapper::GetTargetForNativeAccessibilityEvent() {
return native_event_target_;
}
-base::Optional<int32_t> TestAXNodeWrapper::CellIndexToId(int cell_index) const {
+absl::optional<int32_t> TestAXNodeWrapper::CellIndexToId(int cell_index) const {
AXNode* cell = node_->GetTableCellFromIndex(cell_index);
if (!cell)
- return base::nullopt;
+ return absl::nullopt;
return cell->id();
}
@@ -713,6 +725,9 @@ std::u16string TestAXNodeWrapper::GetLocalizedStringForRoleDescription() const {
case ax::mojom::Role::kColorWell:
return u"color picker";
+ case ax::mojom::Role::kComment:
+ return u"comment";
+
case ax::mojom::Role::kContentInfo:
return u"content information";
@@ -732,9 +747,18 @@ std::u16string TestAXNodeWrapper::GetLocalizedStringForRoleDescription() const {
return {};
}
+ case ax::mojom::Role::kDefinition:
+ return u"definition";
+
case ax::mojom::Role::kDetails:
return u"details";
+ case ax::mojom::Role::kDocEndnote:
+ return u"endnote";
+
+ case ax::mojom::Role::kDocFootnote:
+ return u"footnote";
+
case ax::mojom::Role::kEmphasis:
return u"emphasis";
@@ -798,13 +822,11 @@ std::u16string TestAXNodeWrapper::GetLocalizedStringForImageAnnotationStatus(
ax::mojom::ImageAnnotationStatus status) const {
switch (status) {
case ax::mojom::ImageAnnotationStatus::kEligibleForAnnotation:
- return base::ASCIIToUTF16(
- "To get missing image descriptions, open the context menu.");
+ return u"To get missing image descriptions, open the context menu.";
case ax::mojom::ImageAnnotationStatus::kAnnotationPending:
return u"Getting description...";
case ax::mojom::ImageAnnotationStatus::kAnnotationAdult:
- return base::ASCIIToUTF16(
- "Appears to contain adult content. No description available.");
+ return u"Appears to contain adult content. No description available.";
case ax::mojom::ImageAnnotationStatus::kAnnotationEmpty:
case ax::mojom::ImageAnnotationStatus::kAnnotationProcessFailed:
return u"No description available.";
@@ -844,8 +866,8 @@ bool TestAXNodeWrapper::HasVisibleCaretOrSelection() const {
// Selection or caret will be visible in a focused editable area.
if (GetData().HasState(ax::mojom::State::kEditable)) {
- return GetData().IsPlainTextField() ? focus_object == node_
- : focus_object->IsDescendantOf(node_);
+ return GetData().IsAtomicTextField() ? focus_object == node_
+ : focus_object->IsDescendantOf(node_);
}
// The selection will be visible in non-editable content only if it is not
@@ -891,11 +913,11 @@ bool TestAXNodeWrapper::IsOrderedSet() const {
return node_->IsOrderedSet();
}
-base::Optional<int> TestAXNodeWrapper::GetPosInSet() const {
+absl::optional<int> TestAXNodeWrapper::GetPosInSet() const {
return node_->GetPosInSet();
}
-base::Optional<int> TestAXNodeWrapper::GetSetSize() const {
+absl::optional<int> TestAXNodeWrapper::GetSetSize() const {
return node_->GetSetSize();
}
diff --git a/chromium/ui/accessibility/platform/test_ax_node_wrapper.h b/chromium/ui/accessibility/platform/test_ax_node_wrapper.h
index b46628b22a2..7064c8bea2a 100644
--- a/chromium/ui/accessibility/platform/test_ax_node_wrapper.h
+++ b/chromium/ui/accessibility/platform/test_ax_node_wrapper.h
@@ -55,6 +55,9 @@ class TestAXNodeWrapper : public AXPlatformNodeDelegateBase {
// the result.
static void SetHitTestResult(AXNodeID src_node_id, AXNodeID dst_node_id);
+ // This is used to make sure global state doesn't persist across tests.
+ static void ResetGlobalState();
+
~TestAXNodeWrapper() override;
AXPlatformNode* ax_platform_node() const { return platform_node_; }
@@ -100,29 +103,29 @@ class TestAXNodeWrapper : public AXPlatformNodeDelegateBase {
int32_t id) override;
int GetIndexInParent() override;
bool IsTable() const override;
- base::Optional<int> GetTableRowCount() const override;
- base::Optional<int> GetTableColCount() const override;
- base::Optional<int> GetTableAriaColCount() const override;
- base::Optional<int> GetTableAriaRowCount() const override;
- base::Optional<int> GetTableCellCount() const override;
- base::Optional<bool> GetTableHasColumnOrRowHeaderNode() const override;
+ absl::optional<int> GetTableRowCount() const override;
+ absl::optional<int> GetTableColCount() const override;
+ absl::optional<int> GetTableAriaColCount() const override;
+ absl::optional<int> GetTableAriaRowCount() const override;
+ absl::optional<int> GetTableCellCount() const override;
+ absl::optional<bool> GetTableHasColumnOrRowHeaderNode() const override;
std::vector<int32_t> GetColHeaderNodeIds() const override;
std::vector<int32_t> GetColHeaderNodeIds(int col_index) const override;
std::vector<int32_t> GetRowHeaderNodeIds() const override;
std::vector<int32_t> GetRowHeaderNodeIds(int row_index) const override;
bool IsTableRow() const override;
- base::Optional<int> GetTableRowRowIndex() const override;
+ absl::optional<int> GetTableRowRowIndex() const override;
bool IsTableCellOrHeader() const override;
- base::Optional<int> GetTableCellIndex() const override;
- base::Optional<int> GetTableCellColIndex() const override;
- base::Optional<int> GetTableCellRowIndex() const override;
- base::Optional<int> GetTableCellColSpan() const override;
- base::Optional<int> GetTableCellRowSpan() const override;
- base::Optional<int> GetTableCellAriaColIndex() const override;
- base::Optional<int> GetTableCellAriaRowIndex() const override;
- base::Optional<int32_t> GetCellId(int row_index,
+ absl::optional<int> GetTableCellIndex() const override;
+ absl::optional<int> GetTableCellColIndex() const override;
+ absl::optional<int> GetTableCellRowIndex() const override;
+ absl::optional<int> GetTableCellColSpan() const override;
+ absl::optional<int> GetTableCellRowSpan() const override;
+ absl::optional<int> GetTableCellAriaColIndex() const override;
+ absl::optional<int> GetTableCellAriaRowIndex() const override;
+ absl::optional<int32_t> GetCellId(int row_index,
int col_index) const override;
- base::Optional<int32_t> CellIndexToId(int cell_index) const override;
+ absl::optional<int32_t> CellIndexToId(int cell_index) const override;
bool IsCellOrHeaderOfARIATable() const override;
bool IsCellOrHeaderOfARIAGrid() const override;
gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
@@ -142,8 +145,8 @@ class TestAXNodeWrapper : public AXPlatformNodeDelegateBase {
ax::mojom::IntListAttribute attr) override;
bool IsOrderedSetItem() const override;
bool IsOrderedSet() const override;
- base::Optional<int> GetPosInSet() const override;
- base::Optional<int> GetSetSize() const override;
+ absl::optional<int> GetPosInSet() const override;
+ absl::optional<int> GetSetSize() const override;
SkColor GetColor() const override;
SkColor GetBackgroundColor() const override;
diff --git a/chromium/ui/android/BUILD.gn b/chromium/ui/android/BUILD.gn
index 5358a597b15..257868f4eae 100644
--- a/chromium/ui/android/BUILD.gn
+++ b/chromium/ui/android/BUILD.gn
@@ -482,6 +482,7 @@ junit_binary("ui_junit_tests") {
"//third_party/androidx:androidx_appcompat_appcompat_java",
"//third_party/androidx:androidx_appcompat_appcompat_resources_java",
"//third_party/androidx:androidx_asynclayoutinflater_asynclayoutinflater_java",
+ "//third_party/androidx:androidx_core_core_java",
"//third_party/androidx:androidx_test_core_java",
"//third_party/androidx:androidx_test_ext_junit_java",
"//third_party/androidx:androidx_test_runner_java",
diff --git a/chromium/ui/android/DIR_METADATA b/chromium/ui/android/DIR_METADATA
index fdda50b12d1..048a7e50e8d 100644
--- a/chromium/ui/android/DIR_METADATA
+++ b/chromium/ui/android/DIR_METADATA
@@ -6,7 +6,4 @@
# For the schema of this file, see Metadata message:
# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
-monorail {
- component: "UI"
-}
os: ANDROID \ No newline at end of file
diff --git a/chromium/ui/android/color_helpers.cc b/chromium/ui/android/color_helpers.cc
index e110e6a8389..af2bb719d8d 100644
--- a/chromium/ui/android/color_helpers.cc
+++ b/chromium/ui/android/color_helpers.cc
@@ -10,21 +10,21 @@
namespace ui {
-std::string OptionalSkColorToString(const base::Optional<SkColor>& color) {
+std::string OptionalSkColorToString(const absl::optional<SkColor>& color) {
if (!color)
return std::string();
return color_utils::SkColorToRgbaString(*color);
}
-int64_t OptionalSkColorToJavaColor(const base::Optional<SkColor>& skcolor) {
+int64_t OptionalSkColorToJavaColor(const absl::optional<SkColor>& skcolor) {
if (!skcolor)
return kInvalidJavaColor;
return static_cast<int32_t>(*skcolor);
}
-base::Optional<SkColor> JavaColorToOptionalSkColor(int64_t java_color) {
+absl::optional<SkColor> JavaColorToOptionalSkColor(int64_t java_color) {
if (java_color == kInvalidJavaColor)
- return base::nullopt;
+ return absl::nullopt;
DCHECK(base::IsValueInRangeForNumericType<int32_t>(java_color));
return static_cast<SkColor>(java_color);
}
diff --git a/chromium/ui/android/color_helpers.h b/chromium/ui/android/color_helpers.h
index 6b12d90abf6..4dadc228cb2 100644
--- a/chromium/ui/android/color_helpers.h
+++ b/chromium/ui/android/color_helpers.h
@@ -10,7 +10,7 @@
#include <limits>
#include <string>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/android/ui_android_export.h"
@@ -22,15 +22,15 @@ UI_ANDROID_EXPORT constexpr int64_t kInvalidJavaColor =
// Converts |color| to a CSS color string. If |color| is null, the empty string
// is returned.
UI_ANDROID_EXPORT std::string OptionalSkColorToString(
- const base::Optional<SkColor>& color);
+ const absl::optional<SkColor>& color);
// Conversions between a Java color and an Optional<SkColor>. Java colors are
// represented as 64-bit signed integers. Valid colors are in the range
// [std::numeric_limits<int32_t>::min(), std::numeric_limits<int32_t>::max()].
// while |kInvalidJavaColor| is reserved for representing a null/unset color.
UI_ANDROID_EXPORT int64_t
-OptionalSkColorToJavaColor(const base::Optional<SkColor>& skcolor);
-UI_ANDROID_EXPORT base::Optional<SkColor> JavaColorToOptionalSkColor(
+OptionalSkColorToJavaColor(const absl::optional<SkColor>& skcolor);
+UI_ANDROID_EXPORT absl::optional<SkColor> JavaColorToOptionalSkColor(
int64_t java_color);
} // namespace ui
diff --git a/chromium/ui/android/color_helpers_unittest.cc b/chromium/ui/android/color_helpers_unittest.cc
index 4ad4e1e69c3..5acf395353d 100644
--- a/chromium/ui/android/color_helpers_unittest.cc
+++ b/chromium/ui/android/color_helpers_unittest.cc
@@ -8,8 +8,8 @@
#include <limits>
-#include "base/optional.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
namespace ui {
@@ -32,7 +32,7 @@ constexpr int kAndroidTransparent = 0;
} // namespace
TEST(ColorHelpersTest, Null) {
- EXPECT_EQ(kAndroidInvalidColor, OptionalSkColorToJavaColor(base::nullopt));
+ EXPECT_EQ(kAndroidInvalidColor, OptionalSkColorToJavaColor(absl::nullopt));
EXPECT_FALSE(JavaColorToOptionalSkColor(kAndroidInvalidColor).has_value());
}
diff --git a/chromium/ui/android/delegated_frame_host_android.cc b/chromium/ui/android/delegated_frame_host_android.cc
index a1ed0d9158d..5412ecf55ff 100644
--- a/chromium/ui/android/delegated_frame_host_android.cc
+++ b/chromium/ui/android/delegated_frame_host_android.cc
@@ -374,7 +374,7 @@ void DelegatedFrameHostAndroid::TakeFallbackContentFrom(
return;
const viz::SurfaceId& other_primary = other->content_layer_->surface_id();
- const base::Optional<viz::SurfaceId>& other_fallback =
+ const absl::optional<viz::SurfaceId>& other_fallback =
other->content_layer_->oldest_acceptable_fallback();
viz::SurfaceId desired_fallback;
if (!other->HasFallbackSurface() ||
diff --git a/chromium/ui/android/dummy_screen_android.h b/chromium/ui/android/dummy_screen_android.h
index 3e61475e9d0..b4af87e5722 100644
--- a/chromium/ui/android/dummy_screen_android.h
+++ b/chromium/ui/android/dummy_screen_android.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_ANDROID_SCREEN_DUMMY_SCREEN_ANDROID_H_
-#define UI_ANDROID_SCREEN_DUMMY_SCREEN_ANDROID_H_
+#ifndef UI_ANDROID_DUMMY_SCREEN_ANDROID_H_
+#define UI_ANDROID_DUMMY_SCREEN_ANDROID_H_
#include "ui/android/ui_android_export.h"
@@ -19,4 +19,4 @@ UI_ANDROID_EXPORT display::Screen* CreateDummyScreenAndroid();
} // namespace display
-#endif // UI_ANDROID_SCREEN_DUMMY_SCREEN_ANDROID_H_
+#endif // UI_ANDROID_DUMMY_SCREEN_ANDROID_H_
diff --git a/chromium/ui/android/edge_effect.h b/chromium/ui/android/edge_effect.h
index 2e0039eb0ed..21fa329141f 100644
--- a/chromium/ui/android/edge_effect.h
+++ b/chromium/ui/android/edge_effect.h
@@ -5,7 +5,6 @@
#ifndef UI_ANDROID_EDGE_EFFECT_H_
#define UI_ANDROID_EDGE_EFFECT_H_
-#include <memory>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
diff --git a/chromium/ui/android/junit/src/org/chromium/ui/base/DIR_METADATA b/chromium/ui/android/junit/src/org/chromium/ui/base/DIR_METADATA
deleted file mode 100644
index 2769d07edc7..00000000000
--- a/chromium/ui/android/junit/src/org/chromium/ui/base/DIR_METADATA
+++ /dev/null
@@ -1,11 +0,0 @@
-# Metadata information for this directory.
-#
-# For more information on DIR_METADATA files, see:
-# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
-#
-# For the schema of this file, see Metadata message:
-# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
-
-monorail {
- component: "UI"
-} \ No newline at end of file
diff --git a/chromium/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java b/chromium/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java
index 12f07aa2d87..c0786286333 100644
--- a/chromium/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java
+++ b/chromium/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java
@@ -11,6 +11,8 @@ import static org.junit.Assert.assertTrue;
import android.net.Uri;
import android.webkit.MimeTypeMap;
+import androidx.core.content.ContextCompat;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Shadows;
@@ -18,7 +20,6 @@ import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowMimeTypeMap;
import org.chromium.base.ContextUtils;
-import org.chromium.base.PathUtils;
import org.chromium.base.test.BaseRobolectricTestRunner;
import java.io.File;
@@ -161,42 +162,51 @@ public class SelectFileDialogTest {
"///storage/emulated/0/DCIM/Camera/IMG_1.jpg");
}
- @Test
- public void testFilePathSelected() throws IOException {
- SelectFileDialog selectFileDialog = new SelectFileDialog(0);
- PathUtils.setPrivateDataDirectorySuffix("test");
- String dataDir = new File(PathUtils.getDataDirectory()).getCanonicalPath();
+ private void testFilePath(
+ String path, SelectFileDialog selectFileDialog, boolean expectedPass) {
+ Uri[] uris = new Uri[1];
+ uris[0] = Uri.fromFile(new File(path));
SelectFileDialog.FilePathSelectedTask task = selectFileDialog.new FilePathSelectedTask(
- ContextUtils.getApplicationContext(), dataDir, null);
- assertFalse(task.doInBackground());
-
- task = selectFileDialog.new FilePathSelectedTask(
- ContextUtils.getApplicationContext(), dataDir + "/tmp/xyz.jpg", null);
- assertFalse(task.doInBackground());
-
- task = selectFileDialog.new FilePathSelectedTask(
- ContextUtils.getApplicationContext(), dataDir + "/../xyz.jpg", null);
- assertTrue(task.doInBackground());
+ ContextUtils.getApplicationContext(), path, null);
+ SelectFileDialog.GetDisplayNameTask task2 =
+ selectFileDialog.new GetDisplayNameTask(ContextUtils.getApplicationContext(),
+ /* isMultiple = */ false, uris);
+ assertEquals(expectedPass, task.doInBackground());
+ assertEquals(expectedPass, null != task2.doInBackground());
+ }
- task = selectFileDialog.new FilePathSelectedTask(
- ContextUtils.getApplicationContext(), dataDir + "/tmp/../xyz.jpg", null);
- assertFalse(task.doInBackground());
+ @Test
+ public void testFilePathTasks() throws IOException {
+ SelectFileDialog selectFileDialog = new SelectFileDialog(0);
- task = selectFileDialog.new FilePathSelectedTask(
- ContextUtils.getApplicationContext(), "/data/local/tmp.jpg", null);
- assertTrue(task.doInBackground());
+ // Obtain the data directory for RoboElectric. It should look something like:
+ // /tmp/robolectric-Method_[testName][number]/org.chromium.test.ui-dataDir
+ // ... where [testName] is the name of this test function and [number] is a unique id.
+ String dataDir =
+ ContextCompat.getDataDir(ContextUtils.getApplicationContext()).getCanonicalPath();
+
+ // Passing in the data directory itself should fail.
+ testFilePath(dataDir, selectFileDialog, /* expectedPass= */ false);
+ // Passing in a subdirectory of the data directory should also fail.
+ testFilePath(dataDir + "/tmp/xyz.jpg", selectFileDialog, /* expectedPass= */ false);
+ // The parent directory of the data directory should, however, succeed.
+ testFilePath(dataDir + "/../xyz.jpg", selectFileDialog, /* expectedPass= */ true);
+ // Another way of specifying the data directory (should fail).
+ testFilePath(dataDir + "/tmp/../xyz.jpg", selectFileDialog, /* expectedPass= */ false);
+ // The directory outside the data directory should succeed.
+ testFilePath("/data/local/tmp.jpg", selectFileDialog, /* expectedPass= */ true);
Path path = new File(dataDir).toPath();
String parent = path.getParent().toString();
String lastComponent = path.getName(path.getNameCount() - 1).toString();
- task = selectFileDialog.new FilePathSelectedTask(ContextUtils.getApplicationContext(),
- parent + "/./" + lastComponent + "/xyz.jpg", null);
- assertFalse(task.doInBackground());
- task = selectFileDialog.new FilePathSelectedTask(ContextUtils.getApplicationContext(),
- dataDir + "/../" + lastComponent + "/xyz.jpg", null);
- assertFalse(task.doInBackground());
+ // Make sure that base/./dataDir is treated the same as base/dataDir (and fail the request).
+ testFilePath(parent + "/./" + lastComponent + "/xyz.jpg", selectFileDialog,
+ /* expectedPass= */ false);
+ // Make sure that dataDir/../dataDir is treated the same as dataDir (and fail the request).
+ testFilePath(dataDir + "/../" + lastComponent + "/xyz.jpg", selectFileDialog,
+ /* expectedPass= */ false);
}
@Test
diff --git a/chromium/ui/android/junit/src/org/chromium/ui/modaldialog/DIR_METADATA b/chromium/ui/android/junit/src/org/chromium/ui/modaldialog/DIR_METADATA
index 94bd7e259da..263fe7da091 100644
--- a/chromium/ui/android/junit/src/org/chromium/ui/modaldialog/DIR_METADATA
+++ b/chromium/ui/android/junit/src/org/chromium/ui/modaldialog/DIR_METADATA
@@ -9,4 +9,3 @@
monorail {
component: "UI>Browser>Mobile"
}
-os: ANDROID \ No newline at end of file
diff --git a/chromium/ui/android/resources/resource_manager.h b/chromium/ui/android/resources/resource_manager.h
index 27b2e28d014..0506161e202 100644
--- a/chromium/ui/android/resources/resource_manager.h
+++ b/chromium/ui/android/resources/resource_manager.h
@@ -5,10 +5,6 @@
#ifndef UI_ANDROID_RESOURCES_RESOURCE_MANAGER_H_
#define UI_ANDROID_RESOURCES_RESOURCE_MANAGER_H_
-#include <memory>
-#include <unordered_map>
-#include <unordered_set>
-
#include "base/android/jni_android.h"
#include "cc/resources/scoped_ui_resource.h"
#include "third_party/skia/include/core/SkColor.h"
diff --git a/chromium/ui/android/resources/resource_manager_impl.h b/chromium/ui/android/resources/resource_manager_impl.h
index a737d566d9a..c0d266f1db7 100644
--- a/chromium/ui/android/resources/resource_manager_impl.h
+++ b/chromium/ui/android/resources/resource_manager_impl.h
@@ -6,6 +6,8 @@
#define UI_ANDROID_RESOURCES_RESOURCE_MANAGER_IMPL_H_
#include <memory>
+#include <unordered_map>
+#include <unordered_set>
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
diff --git a/chromium/ui/android/view_android.cc b/chromium/ui/android/view_android.cc
index e89265babbf..2a24accc6c1 100644
--- a/chromium/ui/android/view_android.cc
+++ b/chromium/ui/android/view_android.cc
@@ -114,10 +114,10 @@ float ViewAndroid::GetDipScale() {
return ui::GetScaleFactorForNativeView(this);
}
-base::Optional<gfx::Rect> ViewAndroid::GetDisplayFeature() {
+absl::optional<gfx::Rect> ViewAndroid::GetDisplayFeature() {
ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
if (delegate.is_null())
- return base::nullopt;
+ return absl::nullopt;
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jintArray> jni_display_feature =
@@ -137,7 +137,7 @@ base::Optional<gfx::Rect> ViewAndroid::GetDisplayFeature() {
return display_feature;
}
- return base::nullopt;
+ return absl::nullopt;
}
ScopedJavaLocalRef<jobject> ViewAndroid::GetEventForwarder() {
@@ -539,7 +539,7 @@ void ViewAndroid::DispatchOnSizeChanged() {
void ViewAndroid::OnPhysicalBackingSizeChanged(
const gfx::Size& size,
- base::Optional<base::TimeDelta> deadline_override) {
+ absl::optional<base::TimeDelta> deadline_override) {
if (physical_size_ == size)
return;
physical_size_ = size;
@@ -561,10 +561,6 @@ void ViewAndroid::OnControlsResizeViewChanged(bool controls_resize_view) {
child->OnControlsResizeViewChanged(controls_resize_view);
}
-bool ViewAndroid::ControlsResizeView() {
- return controls_resize_view_;
-}
-
gfx::Size ViewAndroid::GetPhysicalBackingSize() const {
return physical_size_;
}
diff --git a/chromium/ui/android/view_android.h b/chromium/ui/android/view_android.h
index 5114fbce214..35a572d43f7 100644
--- a/chromium/ui/android/view_android.h
+++ b/chromium/ui/android/view_android.h
@@ -14,8 +14,8 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/android/ui_android_export.h"
#include "ui/android/view_android_observer.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -158,7 +158,7 @@ class UI_ANDROID_EXPORT ViewAndroid {
// timeout for this resize.
void OnPhysicalBackingSizeChanged(
const gfx::Size& size,
- base::Optional<base::TimeDelta> deadline_override = base::nullopt);
+ absl::optional<base::TimeDelta> deadline_override = absl::nullopt);
void OnCursorChanged(const Cursor& cursor);
void OnBackgroundColorChanged(unsigned int color);
void OnTopControlsChanged(float top_controls_offset,
@@ -173,7 +173,6 @@ class UI_ANDROID_EXPORT ViewAndroid {
void OnVerticalScrollDirectionChanged(bool direction_up,
float current_scroll_ratio);
void OnControlsResizeViewChanged(bool controls_resize_view);
- bool ControlsResizeView();
// Gets the Visual Viewport inset to apply in physical pixels.
int GetViewportInsetBottom();
@@ -209,7 +208,7 @@ class UI_ANDROID_EXPORT ViewAndroid {
ViewAndroid* parent() const { return parent_; }
- base::Optional<gfx::Rect> GetDisplayFeature();
+ absl::optional<gfx::Rect> GetDisplayFeature();
bool OnTouchEventForTesting(const MotionEventAndroid& event) {
return OnTouchEvent(event);
diff --git a/chromium/ui/aura/BUILD.gn b/chromium/ui/aura/BUILD.gn
index f638d50067f..92de86a947a 100644
--- a/chromium/ui/aura/BUILD.gn
+++ b/chromium/ui/aura/BUILD.gn
@@ -123,6 +123,7 @@ component("aura") {
"//ui/events",
"//ui/events:dom_keyboard_layout",
"//ui/events:events_base",
+ "//ui/events:keyboard_hook",
"//ui/events/platform",
"//ui/gfx",
"//ui/gfx:gfx_switches",
diff --git a/chromium/ui/aura/client/aura_constants.cc b/chromium/ui/aura/client/aura_constants.cc
index e1d88b353f8..e63df4e16d9 100644
--- a/chromium/ui/aura/client/aura_constants.cc
+++ b/chromium/ui/aura/client/aura_constants.cc
@@ -6,6 +6,7 @@
#include "ui/base/class_property.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/image/image_skia.h"
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, bool)
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, base::TimeDelta)
diff --git a/chromium/ui/aura/client/aura_constants.h b/chromium/ui/aura/client/aura_constants.h
index c81a0263bee..7c486507e99 100644
--- a/chromium/ui/aura/client/aura_constants.h
+++ b/chromium/ui/aura/client/aura_constants.h
@@ -13,6 +13,10 @@
#include "ui/aura/window.h"
#include "ui/base/ui_base_types.h"
+namespace gfx {
+class ImageSkia;
+}
+
namespace ws {
namespace mojom {
enum class WindowType;
diff --git a/chromium/ui/aura/client/cursor_client.h b/chromium/ui/aura/client/cursor_client.h
index a39aeff5870..4d7c6361cf2 100644
--- a/chromium/ui/aura/client/cursor_client.h
+++ b/chromium/ui/aura/client/cursor_client.h
@@ -5,7 +5,6 @@
#ifndef UI_AURA_CLIENT_CURSOR_CLIENT_H_
#define UI_AURA_CLIENT_CURSOR_CLIENT_H_
-#include <string>
#include "ui/aura/aura_export.h"
#include "ui/base/cursor/cursor.h"
diff --git a/chromium/ui/aura/client/drag_drop_client.h b/chromium/ui/aura/client/drag_drop_client.h
index a6fa5efeb1d..14f959b948b 100644
--- a/chromium/ui/aura/client/drag_drop_client.h
+++ b/chromium/ui/aura/client/drag_drop_client.h
@@ -34,12 +34,13 @@ class AURA_EXPORT DragDropClient {
// applied at the end of the drag drop session. |screen_location| is in
// screen coordinates. At most one drag and drop operation is allowed.
// It must not start drag operation while |IsDragDropInProgress| returns true.
- virtual int StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data,
- aura::Window* root_window,
- aura::Window* source_window,
- const gfx::Point& screen_location,
- int operation,
- ui::mojom::DragEventSource source) = 0;
+ virtual ui::mojom::DragOperation StartDragAndDrop(
+ std::unique_ptr<ui::OSExchangeData> data,
+ aura::Window* root_window,
+ aura::Window* source_window,
+ const gfx::Point& screen_location,
+ int allowed_operations,
+ ui::mojom::DragEventSource source) = 0;
// Called when a drag and drop session is cancelled.
virtual void DragCancel() = 0;
diff --git a/chromium/ui/aura/client/drag_drop_delegate.h b/chromium/ui/aura/client/drag_drop_delegate.h
index 009f91445bc..717ff6ed693 100644
--- a/chromium/ui/aura/client/drag_drop_delegate.h
+++ b/chromium/ui/aura/client/drag_drop_delegate.h
@@ -7,6 +7,7 @@
#include <memory>
+#include "base/callback.h"
#include "ui/aura/aura_export.h"
#include "ui/aura/window.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
@@ -37,9 +38,15 @@ struct AURA_EXPORT DragUpdateInfo {
// Delegate interface for drag and drop actions on aura::Window.
class AURA_EXPORT DragDropDelegate {
public:
+ using DropCallback =
+ base::OnceCallback<void(const ui::DropTargetEvent& event,
+ std::unique_ptr<ui::OSExchangeData> data,
+ ui::mojom::DragOperation& output_drag_op)>;
+
// OnDragEntered is invoked when the mouse enters this window during a drag &
// drop session. This is immediately followed by an invocation of
- // OnDragUpdated, and eventually one of OnDragExited or OnPerformDrop.
+ // OnDragUpdated, and eventually one of OnDragExited, OnPerformDrop, or
+ // GetDropCallback.
virtual void OnDragEntered(const ui::DropTargetEvent& event) = 0;
// Invoked during a drag and drop session while the mouse is over the window.
@@ -57,10 +64,16 @@ class AURA_EXPORT DragDropDelegate {
// also stored in the DropTargetEvent. Implementor of this function should be
// aware of keeping the OSExchageData alive until it wants to access it
// through the parameter or the stored reference in DropTargetEvent.
+ // TODO(crbug.com/1175682): Remove OnPerformDrop and switch to GetDropCallback
+ // instead.
virtual ui::mojom::DragOperation OnPerformDrop(
const ui::DropTargetEvent& event,
std::unique_ptr<ui::OSExchangeData> data) = 0;
+ // Invoked during a drag and drop session when the user release the mouse, but
+ // the drop is held because of the DataTransferPolicyController.
+ virtual DropCallback GetDropCallback(const ui::DropTargetEvent& event) = 0;
+
protected:
virtual ~DragDropDelegate() {}
};
diff --git a/chromium/ui/aura/client/screen_position_client.h b/chromium/ui/aura/client/screen_position_client.h
index f2d7a44a155..3db26868037 100644
--- a/chromium/ui/aura/client/screen_position_client.h
+++ b/chromium/ui/aura/client/screen_position_client.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_AURA_SCREEN_POSITION_CLIENT_H_
-#define UI_AURA_SCREEN_POSITION_CLIENT_H_
+#ifndef UI_AURA_CLIENT_SCREEN_POSITION_CLIENT_H_
+#define UI_AURA_CLIENT_SCREEN_POSITION_CLIENT_H_
#include "ui/aura/aura_export.h"
#include "ui/aura/window.h"
@@ -68,4 +68,4 @@ AURA_EXPORT ScreenPositionClient* GetScreenPositionClient(
} // namespace client
} // namespace aura
-#endif // UI_AURA_SCREEN_POSITION_CLIENT_H_
+#endif // UI_AURA_CLIENT_SCREEN_POSITION_CLIENT_H_
diff --git a/chromium/ui/aura/client/window_stacking_client.h b/chromium/ui/aura/client/window_stacking_client.h
index 657e5997147..151efdd902e 100644
--- a/chromium/ui/aura/client/window_stacking_client.h
+++ b/chromium/ui/aura/client/window_stacking_client.h
@@ -5,7 +5,6 @@
#ifndef UI_AURA_CLIENT_WINDOW_STACKING_CLIENT_H_
#define UI_AURA_CLIENT_WINDOW_STACKING_CLIENT_H_
-#include <memory>
#include "ui/aura/aura_export.h"
#include "ui/aura/window.h"
diff --git a/chromium/ui/aura/demo/demo_main.cc b/chromium/ui/aura/demo/demo_main.cc
index 235f635a06e..eb0f97df230 100644
--- a/chromium/ui/aura/demo/demo_main.cc
+++ b/chromium/ui/aura/demo/demo_main.cc
@@ -116,8 +116,8 @@ class DemoWindowParentingClient : public aura::client::WindowParentingClient {
aura::Window* GetDefaultParent(aura::Window* window,
const gfx::Rect& bounds) override {
if (!capture_client_) {
- capture_client_.reset(
- new aura::client::DefaultCaptureClient(window_->GetRootWindow()));
+ capture_client_ = std::make_unique<aura::client::DefaultCaptureClient>(
+ window_->GetRootWindow());
}
return window_;
}
@@ -192,7 +192,7 @@ int DemoMain() {
gfx::Rect window1_bounds(100, 100, 400, 400);
DemoWindowDelegate window_delegate1(SK_ColorBLUE);
aura::Window window1(&window_delegate1);
- window1.set_id(1);
+ window1.SetId(1);
window1.Init(ui::LAYER_TEXTURED);
window1.SetBounds(window1_bounds);
window1.Show();
@@ -201,7 +201,7 @@ int DemoMain() {
gfx::Rect window2_bounds(200, 200, 350, 350);
DemoWindowDelegate window_delegate2(SK_ColorRED);
aura::Window window2(&window_delegate2);
- window2.set_id(2);
+ window2.SetId(2);
window2.Init(ui::LAYER_TEXTURED);
window2.SetBounds(window2_bounds);
window2.Show();
@@ -210,7 +210,7 @@ int DemoMain() {
gfx::Rect window3_bounds(10, 10, 50, 50);
DemoWindowDelegate window_delegate3(SK_ColorGREEN);
aura::Window window3(&window_delegate3);
- window3.set_id(3);
+ window3.SetId(3);
window3.Init(ui::LAYER_TEXTURED);
window3.SetBounds(window3_bounds);
window3.Show();
diff --git a/chromium/ui/aura/env.cc b/chromium/ui/aura/env.cc
index 043a669ebea..12de7c4f947 100644
--- a/chromium/ui/aura/env.cc
+++ b/chromium/ui/aura/env.cc
@@ -34,10 +34,6 @@
#include "ui/base/x/x11_cursor_factory.h"
#endif
-#if defined(OS_WIN) || defined(USE_X11)
-#include "ui/gfx/switches.h"
-#endif
-
namespace aura {
namespace {
@@ -210,17 +206,13 @@ Env::Env()
: env_controller_(std::make_unique<EnvInputStateController>(this)),
gesture_recognizer_(std::make_unique<ui::GestureRecognizerImpl>()),
input_state_lookup_(InputStateLookup::Create()) {
-#if defined(OS_WIN) || defined(USE_X11)
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless)) {
#if defined(USE_X11)
- // In Ozone/X11, the cursor factory is initialized by the platform
- // initialization code.
- if (!features::IsUsingOzonePlatform())
- cursor_factory_ = std::make_unique<ui::X11CursorFactory>();
-#else
- cursor_factory_ = std::make_unique<ui::WinCursorFactory>();
-#endif
- }
+ // In Ozone/X11, the cursor factory is initialized by the platform
+ // initialization code.
+ if (!features::IsUsingOzonePlatform())
+ cursor_factory_ = std::make_unique<ui::X11CursorFactory>();
+#elif defined(OS_WIN)
+ cursor_factory_ = std::make_unique<ui::WinCursorFactory>();
#endif
}
diff --git a/chromium/ui/aura/env.h b/chromium/ui/aura/env.h
index 2baf5a54175..ff912bbe9f8 100644
--- a/chromium/ui/aura/env.h
+++ b/chromium/ui/aura/env.h
@@ -8,7 +8,6 @@
#include <memory>
#include <set>
-#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/supports_user_data.h"
diff --git a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc
index 40ad0466075..50e6c3177c2 100644
--- a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc
+++ b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc
@@ -41,8 +41,9 @@ namespace test {
namespace {
std::string WindowIDAsString(ui::GestureConsumer* consumer) {
- return consumer ? base::NumberToString(static_cast<Window*>(consumer)->id())
- : "?";
+ return consumer
+ ? base::NumberToString(static_cast<Window*>(consumer)->GetId())
+ : "?";
}
#define EXPECT_0_EVENTS(events) \
@@ -2214,7 +2215,7 @@ TEST_F(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) {
delegates[i] = new GestureEventConsumeDelegate();
windows[i] = CreateTestWindowWithDelegate(
delegates[i], i, window_bounds[i], root_window());
- windows[i]->set_id(i);
+ windows[i]->SetId(i);
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, window_bounds[i].origin(),
tes.Now(),
ui::PointerDetails(ui::EventPointerType::kTouch, i));
diff --git a/chromium/ui/aura/native_window_occlusion_tracker_win.cc b/chromium/ui/aura/native_window_occlusion_tracker_win.cc
index 57f85d3699f..70f7b9ccb50 100644
--- a/chromium/ui/aura/native_window_occlusion_tracker_win.cc
+++ b/chromium/ui/aura/native_window_occlusion_tracker_win.cc
@@ -799,7 +799,7 @@ bool NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
(IsWindowOnCurrentVirtualDesktop(hwnd) == true);
}
-base::Optional<bool> NativeWindowOcclusionTrackerWin::
+absl::optional<bool> NativeWindowOcclusionTrackerWin::
WindowOcclusionCalculator::IsWindowOnCurrentVirtualDesktop(HWND hwnd) {
if (!virtual_desktop_manager_)
return true;
@@ -809,7 +809,7 @@ base::Optional<bool> NativeWindowOcclusionTrackerWin::
hwnd, &on_current_desktop))) {
return on_current_desktop;
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace aura
diff --git a/chromium/ui/aura/native_window_occlusion_tracker_win.h b/chromium/ui/aura/native_window_occlusion_tracker_win.h
index b1a44a9989b..dc00150dbc8 100644
--- a/chromium/ui/aura/native_window_occlusion_tracker_win.h
+++ b/chromium/ui/aura/native_window_occlusion_tracker_win.h
@@ -18,7 +18,6 @@
#include "base/containers/flat_set.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
-#include "base/time/time.h"
#include "base/timer/timer.h"
#include "ui/aura/aura_export.h"
#include "ui/aura/window.h"
@@ -184,7 +183,7 @@ class AURA_EXPORT NativeWindowOcclusionTrackerWin
// Returns true if |hwnd| is definitely on the current virtual desktop,
// false if it's definitely not on the current virtual desktop, and nullopt
// if we we can't tell for sure.
- base::Optional<bool> IsWindowOnCurrentVirtualDesktop(HWND hwnd);
+ absl::optional<bool> IsWindowOnCurrentVirtualDesktop(HWND hwnd);
static WindowOcclusionCalculator* instance_;
diff --git a/chromium/ui/aura/scoped_simple_keyboard_hook.cc b/chromium/ui/aura/scoped_simple_keyboard_hook.cc
index c39f0a1cf4c..2591d8701c0 100644
--- a/chromium/ui/aura/scoped_simple_keyboard_hook.cc
+++ b/chromium/ui/aura/scoped_simple_keyboard_hook.cc
@@ -12,7 +12,7 @@
namespace aura {
ScopedSimpleKeyboardHook::ScopedSimpleKeyboardHook(
- base::Optional<base::flat_set<ui::DomCode>> dom_codes)
+ absl::optional<base::flat_set<ui::DomCode>> dom_codes)
: dom_codes_(std::move(dom_codes)) {}
ScopedSimpleKeyboardHook::~ScopedSimpleKeyboardHook() = default;
diff --git a/chromium/ui/aura/scoped_simple_keyboard_hook.h b/chromium/ui/aura/scoped_simple_keyboard_hook.h
index 18d3c512265..f68499bfbd7 100644
--- a/chromium/ui/aura/scoped_simple_keyboard_hook.h
+++ b/chromium/ui/aura/scoped_simple_keyboard_hook.h
@@ -7,7 +7,7 @@
#include "base/containers/flat_set.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/aura/scoped_keyboard_hook.h"
namespace ui {
@@ -24,14 +24,14 @@ namespace aura {
class ScopedSimpleKeyboardHook : public ScopedKeyboardHook {
public:
explicit ScopedSimpleKeyboardHook(
- base::Optional<base::flat_set<ui::DomCode>> dom_codes);
+ absl::optional<base::flat_set<ui::DomCode>> dom_codes);
~ScopedSimpleKeyboardHook() override;
// ScopedKeyboardHook override.
bool IsKeyLocked(ui::DomCode dom_code) override;
private:
- base::Optional<base::flat_set<ui::DomCode>> dom_codes_;
+ absl::optional<base::flat_set<ui::DomCode>> dom_codes_;
DISALLOW_COPY_AND_ASSIGN(ScopedSimpleKeyboardHook);
};
diff --git a/chromium/ui/aura/window.cc b/chromium/ui/aura/window.cc
index 303a0290b53..aca9f1e5838 100644
--- a/chromium/ui/aura/window.cc
+++ b/chromium/ui/aura/window.cc
@@ -46,6 +46,8 @@
#include "ui/aura/window_tracker.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/layout.h"
+#include "ui/base/metadata/base_type_conversion.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/ui_base_features.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
@@ -57,6 +59,66 @@
#include "ui/gfx/canvas.h"
#include "ui/gfx/scoped_canvas.h"
+DEFINE_ENUM_CONVERTERS(
+ aura::client::WindowType,
+ {aura::client::WINDOW_TYPE_UNKNOWN, u"WINDOW_TYPE_UNKNOWN"},
+ {aura::client::WINDOW_TYPE_NORMAL, u"WINDOW_TYPE_NORMAL"},
+ {aura::client::WINDOW_TYPE_POPUP, u"WINDOW_TYPE_POPUP"},
+ {aura::client::WINDOW_TYPE_CONTROL, u"WINDOW_TYPE_CONTROL"},
+ {aura::client::WINDOW_TYPE_MENU, u"WINDOW_TYPE_MENU"},
+ {aura::client::WINDOW_TYPE_TOOLTIP, u"WINDOW_TYPE_TOOLTIP"})
+
+DEFINE_ENUM_CONVERTERS(aura::Window::OcclusionState,
+ {aura::Window::OcclusionState::UNKNOWN, u"UNKNOWN"},
+ {aura::Window::OcclusionState::VISIBLE, u"VISIBLE"},
+ {aura::Window::OcclusionState::OCCLUDED, u"OCCLUDED"},
+ {aura::Window::OcclusionState::HIDDEN, u"HIDDEN"})
+
+namespace ui {
+namespace metadata {
+
+template <>
+struct TypeConverter<viz::SurfaceId> : public BaseTypeConverter<true> {
+ static std::u16string ToString(const viz::SurfaceId& source_value);
+ static absl::optional<viz::SurfaceId> FromString(
+ const std::u16string& source_value);
+ static ValidStrings GetValidStrings();
+};
+
+// static
+std::u16string TypeConverter<viz::SurfaceId>::ToString(
+ const viz::SurfaceId& source_value) {
+ return source_value.is_valid() ? base::UTF8ToUTF16(source_value.ToString())
+ : u"<none>";
+}
+
+// static
+absl::optional<viz::SurfaceId> TypeConverter<viz::SurfaceId>::FromString(
+ const std::u16string& source_value) {
+ return absl::nullopt;
+}
+
+// static
+ValidStrings TypeConverter<viz::SurfaceId>::GetValidStrings() {
+ return ValidStrings();
+}
+
+} // namespace metadata
+} // namespace ui
+
+namespace {
+
+// This enum is used to construct a unique property changed callback key from
+// the address of the `bounds_` field by using these values as an offset.
+enum BoundsCallbackIndex : int {
+ kBoundsX,
+ kBoundsY,
+ kBoundsWidth,
+ kBoundsHeight,
+};
+
+} // namespace
+
namespace aura {
namespace {
static const char* kExo = "Exo";
@@ -198,10 +260,28 @@ void Window::Init(ui::LayerType layer_type) {
Env::GetInstance()->NotifyWindowInitialized(this);
}
+int Window::GetId() const {
+ return id_;
+}
+
+void Window::SetId(int id) {
+ if (id == id_)
+ return;
+ id_ = id;
+ TriggerChangedCallback(&id_);
+}
+
+client::WindowType Window::GetType() const {
+ return type_;
+}
+
void Window::SetType(client::WindowType type) {
// Cannot change type after the window is initialized.
DCHECK(!layer());
+ if (type == type_)
+ return;
type_ = type;
+ TriggerChangedCallback(&type_);
}
const std::string& Window::GetName() const {
@@ -215,6 +295,7 @@ void Window::SetName(const std::string& name) {
SetProperty(client::kNameKey, name);
if (layer())
UpdateLayerName();
+ TriggerChangedCallback(client::kNameKey);
}
const std::u16string& Window::GetTitle() const {
@@ -230,12 +311,17 @@ void Window::SetTitle(const std::u16string& title) {
observer.OnWindowTitleChanged(this);
}
+bool Window::GetTransparent() const {
+ return transparent_;
+}
+
void Window::SetTransparent(bool transparent) {
if (transparent == transparent_)
return;
transparent_ = transparent;
if (layer())
layer()->SetFillsBoundsOpaquely(!transparent_);
+ TriggerChangedCallback(&transparent_);
}
void Window::SetFillsBoundsCompletely(bool fills_bounds) {
@@ -267,12 +353,12 @@ void Window::Show() {
// transparent since the window would still be considered to be active but
// could not be seen.
DCHECK(!visible_ || layer()->GetTargetOpacity() > 0.0f);
- SetVisible(true);
+ SetVisibleInternal(true);
}
void Window::Hide() {
// RootWindow::OnVisibilityChanged will call ReleaseCapture.
- SetVisible(false);
+ SetVisibleInternal(false);
}
bool Window::IsVisible() const {
@@ -283,6 +369,10 @@ bool Window::IsVisible() const {
return visible_ ? layer()->IsDrawn() : false;
}
+Window::OcclusionState Window::GetOcclusionState() const {
+ return occlusion_state_;
+}
+
ScopedWindowCaptureRequest Window::MakeWindowCapturable() {
DCHECK(!IsRootWindow()) << "Root windows can already be captured using their "
"FrameSinkId; no need to call this.";
@@ -291,9 +381,6 @@ ScopedWindowCaptureRequest Window::MakeWindowCapturable() {
}
gfx::Rect Window::GetBoundsInRootWindow() const {
- // TODO(beng): There may be a better way to handle this, and the existing code
- // is likely wrong anyway in a multi-display world, but this will
- // do for now.
if (!GetRootWindow())
return bounds();
gfx::Rect bounds_in_root(bounds().size());
@@ -301,6 +388,21 @@ gfx::Rect Window::GetBoundsInRootWindow() const {
return bounds_in_root;
}
+gfx::Rect Window::GetActualBoundsInRootWindow() const {
+ if (!GetRootWindow())
+ return bounds();
+ gfx::Rect bounds_in_root(bounds().size());
+ gfx::PointF origin_f = gfx::PointF(bounds_in_root.origin());
+ ui::Layer::ConvertPointToLayer(layer(), GetRootWindow()->layer(),
+ /*use_target_transform=*/false, &origin_f);
+ bounds_in_root.set_origin(gfx::ToFlooredPoint(origin_f));
+ return bounds_in_root;
+}
+
+const gfx::Transform& Window::transform() const {
+ return layer()->transform();
+}
+
gfx::Rect Window::GetBoundsInScreen() const {
gfx::Rect bounds(GetBoundsInRootWindow());
const Window* root = GetRootWindow();
@@ -316,6 +418,17 @@ gfx::Rect Window::GetBoundsInScreen() const {
return bounds;
}
+gfx::Rect Window::GetActualBoundsInScreen() const {
+ gfx::Rect bounds(GetActualBoundsInRootWindow());
+ const Window* root = GetRootWindow();
+ if (root) {
+ gfx::Point origin_in_screen = root->GetBoundsInScreen().origin();
+ origin_in_screen += bounds.OffsetFromOrigin();
+ bounds.set_origin(origin_in_screen);
+ }
+ return bounds;
+}
+
void Window::SetTransform(const gfx::Transform& transform) {
WindowOcclusionTracker::ScopedPause pause_occlusion_tracking;
for (WindowObserver& observer : observers_)
@@ -477,7 +590,7 @@ Window* Window::GetChildById(int id) {
const Window* Window::GetChildById(int id) const {
Windows::const_iterator i;
for (i = children_.begin(); i != children_.end(); ++i) {
- if ((*i)->id() == id)
+ if ((*i)->GetId() == id)
return *i;
const Window* result = (*i)->GetChildById(id);
if (result)
@@ -505,7 +618,8 @@ void Window::ConvertPointToTarget(const Window* source,
if (target_client)
target_client->ConvertPointFromScreen(target, point);
} else {
- ui::Layer::ConvertPointToLayer(source->layer(), target->layer(), point);
+ ui::Layer::ConvertPointToLayer(source->layer(), target->layer(),
+ /*use_target_transform=*/true, point);
}
}
@@ -738,7 +852,7 @@ bool Window::HasCapture() {
}
std::unique_ptr<ScopedKeyboardHook> Window::CaptureSystemKeyEvents(
- base::Optional<base::flat_set<ui::DomCode>> dom_codes) {
+ absl::optional<base::flat_set<ui::DomCode>> dom_codes) {
Window* root_window = GetRootWindow();
if (!root_window)
return nullptr;
@@ -795,9 +909,10 @@ std::string Window::GetDebugInfo() const {
layer()->opacity());
}
return base::StringPrintf(
- "%s<%d> bounds=%s %s %s occlusion_state=%s", name.c_str(), id(),
+ "%s<%d> bounds=%s %s %s occlusion_state=%s", name.c_str(), GetId(),
bounds().ToString().c_str(), visible_ ? "WindowVisible" : "WindowHidden",
- layer_state.c_str(), OcclusionStateToString(occlusion_state_));
+ layer_state.c_str(),
+ base::UTF16ToUTF8(OcclusionStateToString(occlusion_state_)).c_str());
}
std::string Window::GetWindowHierarchy(int depth) const {
@@ -877,7 +992,7 @@ void Window::SetBoundsInternal(const gfx::Rect& new_bounds) {
}
}
-void Window::SetVisible(bool visible) {
+void Window::SetVisibleInternal(bool visible) {
if (visible == layer()->GetTargetVisibility())
return; // No change.
@@ -1201,6 +1316,10 @@ viz::SurfaceId Window::GetSurfaceId() {
return viz::SurfaceId(GetFrameSinkId(), GetLocalSurfaceId());
}
+viz::SurfaceId Window::GetSurfaceId() const {
+ return const_cast<Window*>(this)->GetSurfaceId();
+}
+
void Window::AllocateLocalSurfaceId() {
if (!parent_local_surface_id_allocator_) {
parent_local_surface_id_allocator_ =
@@ -1229,7 +1348,7 @@ void Window::InvalidateLocalSurfaceId() {
}
void Window::UpdateLocalSurfaceIdFromEmbeddedClient(
- const base::Optional<viz::LocalSurfaceId>&
+ const absl::optional<viz::LocalSurfaceId>&
embedded_client_local_surface_id) {
if (embedded_client_local_surface_id) {
parent_local_surface_id_allocator_->UpdateFromChild(
@@ -1264,27 +1383,14 @@ bool Window::RequiresDoubleTapGestureEvents() const {
}
// static
-const char* Window::OcclusionStateToString(OcclusionState state) {
-#define CASE_TYPE(t) \
- case t: \
- return #t
-
- switch (state) {
- CASE_TYPE(OcclusionState::UNKNOWN);
- CASE_TYPE(OcclusionState::VISIBLE);
- CASE_TYPE(OcclusionState::OCCLUDED);
- CASE_TYPE(OcclusionState::HIDDEN);
- }
-#undef CASE_TYPE
-
- NOTREACHED();
- return "";
+const std::u16string Window::OcclusionStateToString(OcclusionState state) {
+ return ui::metadata::TypeConverter<OcclusionState>::ToString(state);
}
void Window::SetOpaqueRegionsForOcclusion(
const std::vector<gfx::Rect>& opaque_regions_for_occlusion) {
// Only transparent windows should try to set opaque regions for occlusion.
- DCHECK(transparent() || opaque_regions_for_occlusion.empty());
+ DCHECK(GetTransparent() || opaque_regions_for_occlusion.empty());
if (opaque_regions_for_occlusion == opaque_regions_for_occlusion_)
return;
opaque_regions_for_occlusion_ = opaque_regions_for_occlusion;
@@ -1326,6 +1432,16 @@ void Window::OnLayerBoundsChanged(const gfx::Rect& old_bounds,
delegate_->OnBoundsChanged(old_bounds, bounds_);
for (auto& observer : observers_)
observer.OnWindowBoundsChanged(this, old_bounds, bounds_, reason);
+
+ // Trigger the changed notification for each of the bounds "properties".
+ if (old_bounds.x() != bounds_.x())
+ TriggerChangedCallback(&bounds_ + kBoundsX);
+ if (old_bounds.y() != bounds_.y())
+ TriggerChangedCallback(&bounds_ + kBoundsY);
+ if (old_bounds.width() != bounds_.width())
+ TriggerChangedCallback(&bounds_ + kBoundsWidth);
+ if (old_bounds.height() != bounds_.height())
+ TriggerChangedCallback(&bounds_ + kBoundsHeight);
}
void Window::OnLayerOpacityChanged(ui::PropertyChangeReason reason) {
@@ -1347,7 +1463,7 @@ void Window::OnLayerFillsBoundsOpaquelyChanged(
WindowOcclusionTracker::ScopedPause pause_occlusion_tracking;
// Non-transparent windows should not have opaque regions for occlusion set.
- if (!transparent())
+ if (!GetTransparent())
DCHECK(opaque_regions_for_occlusion_.empty());
for (WindowObserver& observer : observers_)
@@ -1573,4 +1689,87 @@ void Window::OnScopedWindowCaptureRequestRemoved() {
}
}
+int Window::GetHeight() const {
+ return bounds().height();
+}
+
+int Window::GetWidth() const {
+ return bounds().width();
+}
+
+int Window::GetX() const {
+ return bounds().x();
+}
+
+int Window::GetY() const {
+ return bounds().y();
+}
+
+void Window::SetHeight(int height) {
+ if (height == bounds().height())
+ return;
+ // Bounds changed notification is done within OnLayerBoundsChanged.
+ // Here and below.
+ SetBounds({bounds().x(), bounds().y(), bounds().width(), height});
+}
+
+void Window::SetWidth(int width) {
+ if (width == bounds().width())
+ return;
+ SetBounds({bounds().x(), bounds().y(), width, bounds().height()});
+}
+
+void Window::SetX(int x) {
+ if (x == bounds().x())
+ return;
+ SetBounds({x, bounds().y(), bounds().width(), bounds().height()});
+}
+
+void Window::SetY(int y) {
+ if (y == bounds().y())
+ return;
+ SetBounds({bounds().x(), y, bounds().width(), bounds().height()});
+}
+
+bool Window::GetCapture() const {
+ return const_cast<Window*>(this)->HasCapture();
+}
+
+bool Window::GetVisible() const {
+ return IsVisible();
+}
+
+void Window::SetVisible(bool visible) {
+ if (visible == IsVisible())
+ return;
+ if (visible)
+ Show();
+ else
+ Hide();
+ // Changed notification is handled in SetVisibleInternal().
+}
+
+// Under Windows this macro is defined.
+#undef GetClassName
+
+BEGIN_METADATA_BASE(Window)
+ADD_READONLY_PROPERTY_METADATA(gfx::Rect, ActualBoundsInRootWindow)
+ADD_READONLY_PROPERTY_METADATA(gfx::Rect, ActualBoundsInScreen)
+ADD_READONLY_PROPERTY_METADATA(gfx::Rect, BoundsInRootWindow)
+ADD_READONLY_PROPERTY_METADATA(gfx::Rect, BoundsInScreen)
+ADD_READONLY_PROPERTY_METADATA(bool, Capture)
+ADD_PROPERTY_METADATA(int, Height)
+ADD_PROPERTY_METADATA(int, Width)
+ADD_PROPERTY_METADATA(int, X)
+ADD_PROPERTY_METADATA(int, Y)
+ADD_READONLY_PROPERTY_METADATA(Window::OcclusionState, OcclusionState)
+ADD_READONLY_PROPERTY_METADATA(viz::SurfaceId, SurfaceId)
+ADD_PROPERTY_METADATA(int, Id)
+ADD_PROPERTY_METADATA(std::string, Name)
+ADD_PROPERTY_METADATA(std::u16string, Title)
+ADD_PROPERTY_METADATA(bool, Transparent)
+ADD_PROPERTY_METADATA(client::WindowType, Type)
+ADD_PROPERTY_METADATA(bool, Visible)
+END_METADATA
+
} // namespace aura
diff --git a/chromium/ui/aura/window.h b/chromium/ui/aura/window.h
index d3034469851..b79b13298f6 100644
--- a/chromium/ui/aura/window.h
+++ b/chromium/ui/aura/window.h
@@ -19,7 +19,6 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
@@ -27,14 +26,18 @@
#include "components/viz/common/surfaces/scoped_surface_id_allocator.h"
#include "components/viz/common/surfaces/subtree_capture_id.h"
#include "components/viz/host/host_frame_sink_client.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/skia/include/core/SkRegion.h"
#include "ui/aura/aura_export.h"
#include "ui/aura/client/window_types.h"
#include "ui/aura/scoped_window_capture_request.h"
#include "ui/aura/window_observer.h"
#include "ui/base/class_property.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/layer_delegate.h"
#include "ui/compositor/layer_owner.h"
+#include "ui/compositor/layer_type.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_target.h"
#include "ui/events/event_targeter.h"
@@ -65,6 +68,7 @@ class Layer;
namespace viz {
class ParentLocalSurfaceIdAllocator;
+class SurfaceId;
}
namespace aura {
@@ -106,8 +110,11 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
public ui::EventTarget,
public ui::GestureConsumer,
public ui::PropertyHandler,
+ public ui::metadata::MetaDataProvider,
public viz::HostFrameSinkClient {
public:
+ METADATA_HEADER_BASE(Window);
+
// Initial value of id() for newly created windows.
static constexpr int kInitialId = -1;
@@ -163,11 +170,11 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// A type is used to identify a class of Windows and customize behavior such
// as event handling and parenting. This field should only be consumed by the
// shell -- Aura itself shouldn't contain type-specific logic.
- client::WindowType type() const { return type_; }
+ client::WindowType GetType() const;
void SetType(client::WindowType type);
- int id() const { return id_; }
- void set_id(int id) { id_ = id; }
+ int GetId() const;
+ void SetId(int id);
const std::string& GetName() const;
void SetName(const std::string& name);
@@ -175,7 +182,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
const std::u16string& GetTitle() const;
void SetTitle(const std::u16string& title);
- bool transparent() const { return transparent_; }
+ bool GetTransparent() const;
// Note: Setting a window transparent has significant performance impact,
// especially on low-end Chrome OS devices. Please ensure you are not
@@ -218,7 +225,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// state of this window isn't tracked (Window::TrackOcclusionState) or
// hasn't been computed yet. Is stale if called within the scope of a
// WindowOcclusionTracker::ScopedPause.
- OcclusionState occlusion_state() const { return occlusion_state_; }
+ OcclusionState GetOcclusionState() const;
// Returns the currently occluded region in the root Window coordinates. This
// will be empty unless the window is tracked and has a VISIBLE occlusion
@@ -256,17 +263,33 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
return subtree_capture_id_;
}
- // Returns the window's bounds in root window's coordinates.
+ // Returns the window's bounds in root window's coordinates. The returned
+ // value is calculated using the target transform. The target transform is the
+ // end value of a transform animation. If there is no animation ongoing, the
+ // target transform is the same as the current transform.
gfx::Rect GetBoundsInRootWindow() const;
- // Returns the window's bounds in screen coordinates.
+ // Similar to `GetBoundsInRootWindow()` except that the returned value is
+ // calculated using the current transform. If there is no animation ongoing,
+ // this function returns the same value as `GetBoundsInRootWindow()`.
+ gfx::Rect GetActualBoundsInRootWindow() const;
+
+ // Returns the window's bounds in screen coordinates. The returned
+ // value is calculated using the target transform. The target transform is the
+ // end value of a transform animation. If there is no animation ongoing, the
+ // target transform is the same as the current transform.
// How the root window's coordinates is mapped to screen's coordinates
// is platform dependent and defined in the implementation of the
// |aura::client::ScreenPositionClient| interface.
gfx::Rect GetBoundsInScreen() const;
+ // Similar to `GetBoundsInScreen()` except that the returned value is
+ // calculated using the current transform. If there is no animation ongoing,
+ // this function returns the same value as `GetBoundsInScreen()`.
+ gfx::Rect GetActualBoundsInScreen() const;
+
void SetTransform(const gfx::Transform& transform);
- const gfx::Transform& transform() const { return layer()->transform(); }
+ const gfx::Transform& transform() const;
// Assigns a LayoutManager to size and place child windows.
// The Window takes ownership of the LayoutManager.
@@ -330,7 +353,10 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Converts |point| from |source|'s coordinates to |target|'s. If |source| is
// nullptr, the function returns without modifying |point|. |target| cannot be
- // nullptr.
+ // nullptr. Use layers' target transform in coordinate conversions. The target
+ // transform is the end value of a transform animation. If there is no
+ // animation ongoing, the target transform is the same as the current
+ // transform.
static void ConvertPointToTarget(const Window* source,
const Window* target,
gfx::PointF* point);
@@ -407,7 +433,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// intercepted. Returns a ScopedKeyboardHook instance which stops capturing
// system key events when destroyed.
std::unique_ptr<ScopedKeyboardHook> CaptureSystemKeyEvents(
- base::Optional<base::flat_set<ui::DomCode>> codes);
+ absl::optional<base::flat_set<ui::DomCode>> codes);
// NativeWidget::[GS]etNativeWindowProperty use strings as keys, and this is
// difficult to change while retaining compatibility with other platforms.
@@ -462,7 +488,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// has allocated one. Also sets child sequence number component of the
// viz::LocalSurfaceId allocator.
void UpdateLocalSurfaceIdFromEmbeddedClient(
- const base::Optional<viz::LocalSurfaceId>& local_surface_id);
+ const absl::optional<viz::LocalSurfaceId>& local_surface_id);
// Returns the FrameSinkId. In LOCAL mode, this returns a valid FrameSinkId
// only if a LayerTreeFrameSink has been created. In MUS mode, this always
@@ -489,7 +515,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
bool RequiresDoubleTapGestureEvents() const override;
// Returns |state| as a string. This is generally only useful for debugging.
- static const char* OcclusionStateToString(OcclusionState state);
+ static const std::u16string OcclusionStateToString(OcclusionState state);
// Sets the regions of this window to consider opaque when computing the
// occlusion of underneath windows. Opaque regions can only be set for a
@@ -552,9 +578,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Changes the bounds of the window without condition.
void SetBoundsInternal(const gfx::Rect& new_bounds);
- // Updates the visible state of the layer, but does not make visible-state
- // specific changes. Called from Show()/Hide().
- void SetVisible(bool visible);
+ // Updates the visible state of the layer and the Window, but does not make
+ // visible-state specific changes. Called from Show()/Hide().
+ void SetVisibleInternal(bool visible);
// Updates the occlusion info of the window.
void SetOcclusionInfo(OcclusionState occlusion_state,
@@ -663,6 +689,27 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// to make this non-root window capturable by the FrameSinkVideoCapturer.
void OnScopedWindowCaptureRequestRemoved();
+ // The following are intended for use by the metadata to access the internals
+ // of instances of this class. At some point they should be moved to the
+ // public section and code refactored to use them.
+
+ // Break out the separate elements of the Window bounds.
+ int GetHeight() const;
+ int GetWidth() const;
+ int GetX() const;
+ int GetY() const;
+ void SetHeight(int height);
+ void SetWidth(int width);
+ void SetX(int x);
+ void SetY(int y);
+
+ bool GetCapture() const;
+
+ viz::SurfaceId GetSurfaceId() const;
+
+ bool GetVisible() const;
+ void SetVisible(bool visible);
+
// Bounds of this window relative to the parent. This is cached as the bounds
// of the Layer and Window are not necessarily the same. In particular bounds
// of the Layer are relative to the first ancestor with a Layer, where as this
diff --git a/chromium/ui/aura/window_event_dispatcher.cc b/chromium/ui/aura/window_event_dispatcher.cc
index 9eddddd0499..11e99e357df 100644
--- a/chromium/ui/aura/window_event_dispatcher.cc
+++ b/chromium/ui/aura/window_event_dispatcher.cc
@@ -60,6 +60,8 @@ bool IsEventCandidateForHold(const ui::Event& event) {
return true;
if (event.type() == ui::ET_MOUSE_DRAGGED)
return true;
+ if (event.type() == ui::ET_MOUSE_EXITED)
+ return false;
if (event.IsMouseEvent() && (event.flags() & ui::EF_IS_SYNTHESIZED))
return true;
return false;
diff --git a/chromium/ui/aura/window_event_dispatcher_unittest.cc b/chromium/ui/aura/window_event_dispatcher_unittest.cc
index 8b05ebc4c55..43445b5c0fa 100644
--- a/chromium/ui/aura/window_event_dispatcher_unittest.cc
+++ b/chromium/ui/aura/window_event_dispatcher_unittest.cc
@@ -296,10 +296,10 @@ class TestEventClient : public client::EventClient {
client::SetEventClient(root_window_, this);
Window* lock_window =
test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_);
- lock_window->set_id(kLockWindowId);
+ lock_window->SetId(kLockWindowId);
Window* non_lock_window =
test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_);
- non_lock_window->set_id(kNonLockWindowId);
+ non_lock_window->SetId(kNonLockWindowId);
}
~TestEventClient() override { client::SetEventClient(root_window_, NULL); }
@@ -348,10 +348,10 @@ TEST_F(WindowEventDispatcherTest, GetCanProcessEventsWithinSubtree) {
Window* w1 = test::CreateTestWindowWithBounds(gfx::Rect(10, 10, 20, 20),
client.GetNonLockWindow());
- w1->set_id(1);
+ w1->SetId(1);
Window* w2 = test::CreateTestWindowWithBounds(gfx::Rect(30, 30, 20, 20),
client.GetNonLockWindow());
- w2->set_id(2);
+ w2->SetId(2);
std::unique_ptr<Window> w3(test::CreateTestWindowWithDelegate(
&d, 3, gfx::Rect(30, 30, 20, 20), client.GetLockWindow()));
@@ -975,6 +975,35 @@ TEST_F(WindowEventDispatcherTest, DispatchMouseExitWhenHidingWindow) {
window->RemovePreTargetHandler(&recorder);
}
+TEST_F(WindowEventDispatcherTest, HeldMovesDispatchMouseExitWhenHidingWindow) {
+ EventFilterRecorder recorder;
+
+ test::TestWindowDelegate delegate;
+ std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ &delegate, 1, gfx::Rect(10, 10, 50, 50), root_window()));
+ window->Show();
+ window->AddPreTargetHandler(&recorder);
+
+ // Dispatch a mouse move event into the window.
+ const gfx::Point event_location(22, 33);
+ ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
+ ui::EventTimeForNow(), 0, 0);
+ DispatchEventUsingWindowDispatcher(&mouse);
+ EXPECT_FALSE(recorder.events().empty());
+ recorder.Reset();
+
+ // Hide the window and verify a mouse exit event's location.
+ host()->dispatcher()->HoldPointerMoves();
+ window->Hide();
+ host()->dispatcher()->ReleasePointerMoves();
+ EXPECT_FALSE(recorder.events().empty());
+ EXPECT_EQ("MOUSE_EXITED", EventTypesToString(recorder.events()));
+ ASSERT_EQ(1u, recorder.mouse_locations().size());
+ EXPECT_EQ(gfx::Point(12, 23).ToString(),
+ recorder.mouse_locations()[0].ToString());
+ window->RemovePreTargetHandler(&recorder);
+}
+
// Tests that a mouse-exit event is not synthesized during shutdown.
TEST_F(WindowEventDispatcherTest, NoMouseExitInShutdown) {
EventFilterRecorder recorder;
diff --git a/chromium/ui/aura/window_observer.h b/chromium/ui/aura/window_observer.h
index c2ce7a6d141..d893c9345b1 100644
--- a/chromium/ui/aura/window_observer.h
+++ b/chromium/ui/aura/window_observer.h
@@ -5,7 +5,6 @@
#ifndef UI_AURA_WINDOW_OBSERVER_H_
#define UI_AURA_WINDOW_OBSERVER_H_
-#include <string>
#include "base/observer_list_types.h"
#include "ui/aura/aura_export.h"
diff --git a/chromium/ui/aura/window_occlusion_tracker.cc b/chromium/ui/aura/window_occlusion_tracker.cc
index 07a1f10402a..c4c5f71dff7 100644
--- a/chromium/ui/aura/window_occlusion_tracker.cc
+++ b/chromium/ui/aura/window_occlusion_tracker.cc
@@ -14,6 +14,7 @@
#include "ui/aura/env.h"
#include "ui/aura/window_occlusion_change_builder.h"
#include "ui/aura/window_tree_host.h"
+#include "ui/compositor/layer.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/transform.h"
@@ -260,7 +261,7 @@ bool WindowOcclusionTracker::OcclusionStatesMatch(
const base::flat_map<Window*, OcclusionData>& tracked_windows) {
for (const auto& tracked_window : tracked_windows) {
if (tracked_window.second.occlusion_state !=
- tracked_window.first->occlusion_state())
+ tracked_window.first->GetOcclusionState())
return false;
}
return true;
@@ -345,7 +346,7 @@ void WindowOcclusionTracker::MaybeComputeOcclusion() {
}
// Sanity check: Occlusion states in |tracked_windows_| should match those
- // returned by Window::occlusion_state().
+ // returned by Window::GetOcclusionState().
DCHECK(OcclusionStatesMatch(tracked_windows_));
}
@@ -449,7 +450,7 @@ bool WindowOcclusionTracker::VisibleWindowCanOccludeOtherWindows(
: window->layer()->background_color();
combined_opacity *= SkColorGetA(color) / 255.f;
}
- return (!window->transparent() && WindowHasContent(window) &&
+ return (!window->GetTransparent() && WindowHasContent(window) &&
combined_opacity == 1.0f &&
// For simplicity, a shaped window is not considered opaque.
!WindowOrParentHasShape(window)) ||
@@ -655,7 +656,7 @@ bool WindowOcclusionTracker::WindowOrDescendantCanOccludeOtherWindows(
WindowIsAnimated(window)) {
return false;
}
- if ((!window->transparent() && WindowHasContent(window)) ||
+ if ((!window->GetTransparent() && WindowHasContent(window)) ||
WindowHasOpaqueRegionsForOcclusion(window)) {
return true;
}
diff --git a/chromium/ui/aura/window_occlusion_tracker.h b/chromium/ui/aura/window_occlusion_tracker.h
index 70a6477489a..19bdb1d2a49 100644
--- a/chromium/ui/aura/window_occlusion_tracker.h
+++ b/chromium/ui/aura/window_occlusion_tracker.h
@@ -174,7 +174,7 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver,
~WindowOcclusionTracker() override;
// Returns true iff the occlusion states in |tracked_windows| match those
- // returned by Window::occlusion_state().
+ // returned by Window::GetOcclusionState().
static bool OcclusionStatesMatch(
const base::flat_map<Window*, OcclusionData>& tracked_windows);
diff --git a/chromium/ui/aura/window_occlusion_tracker_unittest.cc b/chromium/ui/aura/window_occlusion_tracker_unittest.cc
index a8ecbcf2a62..63607894c63 100644
--- a/chromium/ui/aura/window_occlusion_tracker_unittest.cc
+++ b/chromium/ui/aura/window_occlusion_tracker_unittest.cc
@@ -19,6 +19,7 @@
#include "ui/aura/test/window_occlusion_tracker_test_api.h"
#include "ui/aura/window_observer.h"
#include "ui/base/ui_base_features.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
@@ -2411,7 +2412,7 @@ TEST_F(WindowOcclusionTrackerTest, ScopedForceVisibleHiddenContainer) {
EXPECT_FALSE(browser_delegate->is_expecting_call());
EXPECT_FALSE(webcontents_delegate->is_expecting_call());
- EXPECT_EQ(Window::OcclusionState::VISIBLE, webcontents->occlusion_state());
+ EXPECT_EQ(Window::OcclusionState::VISIBLE, webcontents->GetOcclusionState());
EXPECT_TRUE(webcontents->TargetVisibility());
container_delegate->set_expectation(Window::OcclusionState::VISIBLE);
diff --git a/chromium/ui/aura/window_targeter.cc b/chromium/ui/aura/window_targeter.cc
index 46e718a7943..facae72bf56 100644
--- a/chromium/ui/aura/window_targeter.cc
+++ b/chromium/ui/aura/window_targeter.cc
@@ -14,6 +14,7 @@
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
+#include "ui/compositor/layer.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/event_target.h"
diff --git a/chromium/ui/aura/window_targeter_unittest.cc b/chromium/ui/aura/window_targeter_unittest.cc
index f4e6b465f59..6dc411c5b95 100644
--- a/chromium/ui/aura/window_targeter_unittest.cc
+++ b/chromium/ui/aura/window_targeter_unittest.cc
@@ -11,6 +11,7 @@
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
+#include "ui/compositor/layer.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/event_utils.h"
@@ -217,7 +218,7 @@ class IdCheckingEventTargeter : public WindowTargeter {
// WindowTargeter:
bool SubtreeShouldBeExploredForEvent(Window* window,
const ui::LocatedEvent& event) override {
- return (window->id() == id_ &&
+ return (window->GetId() == id_ &&
WindowTargeter::SubtreeShouldBeExploredForEvent(window, event));
}
diff --git a/chromium/ui/aura/window_tree_host.cc b/chromium/ui/aura/window_tree_host.cc
index 6faeee8d7eb..bcb66b25eb8 100644
--- a/chromium/ui/aura/window_tree_host.cc
+++ b/chromium/ui/aura/window_tree_host.cc
@@ -310,7 +310,7 @@ void WindowTreeHost::Hide() {
}
std::unique_ptr<ScopedKeyboardHook> WindowTreeHost::CaptureSystemKeyEvents(
- base::Optional<base::flat_set<ui::DomCode>> dom_codes) {
+ absl::optional<base::flat_set<ui::DomCode>> dom_codes) {
// TODO(joedow): Remove the simple hook class/logic once this flag is removed.
if (!base::FeatureList::IsEnabled(features::kSystemKeyboardLock))
return std::make_unique<ScopedSimpleKeyboardHook>(std::move(dom_codes));
diff --git a/chromium/ui/aura/window_tree_host.h b/chromium/ui/aura/window_tree_host.h
index 93c56f7ffbc..65644909583 100644
--- a/chromium/ui/aura/window_tree_host.h
+++ b/chromium/ui/aura/window_tree_host.h
@@ -15,9 +15,9 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "build/build_config.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/aura/aura_export.h"
#include "ui/aura/scoped_enable_unadjusted_mouse_events.h"
#include "ui/aura/window.h"
@@ -220,7 +220,7 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate,
// intercepted. Returns a ScopedKeyboardHook instance which stops capturing
// system key events when destroyed.
std::unique_ptr<ScopedKeyboardHook> CaptureSystemKeyEvents(
- base::Optional<base::flat_set<ui::DomCode>> codes);
+ absl::optional<base::flat_set<ui::DomCode>> codes);
// Returns a map of KeyboardEvent code to KeyboardEvent key values.
virtual base::flat_map<std::string, std::string> GetKeyboardLayoutMap() = 0;
@@ -307,7 +307,7 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate,
// Begins capturing system key events. Returns true if successful.
virtual bool CaptureSystemKeyEventsImpl(
- base::Optional<base::flat_set<ui::DomCode>> dom_codes) = 0;
+ absl::optional<base::flat_set<ui::DomCode>> dom_codes) = 0;
// Stops capturing system keyboard events.
virtual void ReleaseSystemKeyEventCapture() = 0;
diff --git a/chromium/ui/aura/window_tree_host_platform.cc b/chromium/ui/aura/window_tree_host_platform.cc
index 6025626d122..9b9a303a750 100644
--- a/chromium/ui/aura/window_tree_host_platform.cc
+++ b/chromium/ui/aura/window_tree_host_platform.cc
@@ -4,6 +4,7 @@
#include "ui/aura/window_tree_host_platform.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -92,7 +93,7 @@ void WindowTreeHostPlatform::CreateAndSetPlatformWindow(
#endif
NOTREACHED();
#elif defined(OS_WIN)
- platform_window_.reset(new ui::WinWindow(this, properties.bounds));
+ platform_window_ = std::make_unique<ui::WinWindow>(this, properties.bounds);
#else
NOTIMPLEMENTED();
#endif
@@ -150,7 +151,7 @@ void WindowTreeHostPlatform::ReleaseCapture() {
}
bool WindowTreeHostPlatform::CaptureSystemKeyEventsImpl(
- base::Optional<base::flat_set<ui::DomCode>> dom_codes) {
+ absl::optional<base::flat_set<ui::DomCode>> dom_codes) {
// Only one KeyboardHook should be active at a time, otherwise there will be
// problems with event routing (i.e. which Hook takes precedence) and
// destruction ordering.
diff --git a/chromium/ui/aura/window_tree_host_platform.h b/chromium/ui/aura/window_tree_host_platform.h
index 60d5129bdb9..dd2a8f40076 100644
--- a/chromium/ui/aura/window_tree_host_platform.h
+++ b/chromium/ui/aura/window_tree_host_platform.h
@@ -81,7 +81,7 @@ class AURA_EXPORT WindowTreeHostPlatform : public WindowTreeHost,
// Overridden from aura::WindowTreeHost:
bool CaptureSystemKeyEventsImpl(
- base::Optional<base::flat_set<ui::DomCode>> dom_codes) override;
+ absl::optional<base::flat_set<ui::DomCode>> dom_codes) override;
void ReleaseSystemKeyEventCapture() override;
bool IsKeyLocked(ui::DomCode dom_code) override;
base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
diff --git a/chromium/ui/aura/window_unittest.cc b/chromium/ui/aura/window_unittest.cc
index a30c5ee18b0..69af357e341 100644
--- a/chromium/ui/aura/window_unittest.cc
+++ b/chromium/ui/aura/window_unittest.cc
@@ -39,6 +39,7 @@
#include "ui/aura/window_tree_host.h"
#include "ui/base/class_property.h"
#include "ui/base/hit_test.h"
+#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animator.h"
@@ -96,6 +97,72 @@ class DeletionTracker {
DISALLOW_COPY_AND_ASSIGN(DeletionTracker);
};
+// The helper class to wait for the animation completion and run callbacks.
+class LayerTranslationAnimationNotifier : public ui::CompositorObserver {
+ public:
+ using AnimationCallback =
+ base::RepeatingCallback<void(const gfx::Transform&)>;
+
+ LayerTranslationAnimationNotifier(
+ ui::Layer* animation_layer,
+ const gfx::Transform& initial_transform_,
+ const gfx::Transform& target_transform,
+ AnimationCallback animation_start_callback,
+ AnimationCallback animation_end_callback,
+ AnimationCallback animation_progress_callback)
+ : animation_layer_(animation_layer),
+ initial_transform_(initial_transform_),
+ target_transform_(target_transform),
+ animation_start_callback_(animation_start_callback),
+ animation_end_callback_(animation_end_callback),
+ animation_progress_callback_(animation_progress_callback) {
+ animation_layer_->GetCompositor()->AddObserver(this);
+ }
+ LayerTranslationAnimationNotifier(const LayerTranslationAnimationNotifier&) =
+ delete;
+ LayerTranslationAnimationNotifier& operator=(
+ const LayerTranslationAnimationNotifier&) = delete;
+ ~LayerTranslationAnimationNotifier() override {
+ animation_layer_->GetCompositor()->RemoveObserver(this);
+ }
+
+ void WaitForAnimationCompletion() { run_loop_.Run(); }
+
+ // ui::CompositorObserver:
+ void OnCompositingDidCommit(ui::Compositor* compositor) override {
+ const gfx::Transform current_transform = animation_layer_->transform();
+ if (current_transform == initial_transform_) {
+ animation_start_callback_.Run(current_transform);
+ } else if (current_transform == target_transform_) {
+ animation_end_callback_.Run(current_transform);
+ run_loop_.Quit();
+ } else {
+ animation_progress_callback_.Run(current_transform);
+ }
+ }
+
+ private:
+ // The layer to be animated.
+ ui::Layer* const animation_layer_;
+
+ // The initial transform.
+ gfx::Transform initial_transform_;
+
+ // The target transform.
+ gfx::Transform target_transform_;
+
+ // The callback to run at the start of the animation.
+ AnimationCallback animation_start_callback_;
+
+ // The callback to run at the end of the animation.
+ AnimationCallback animation_end_callback_;
+
+ // The callback to run during the progress of the animation.
+ AnimationCallback animation_progress_callback_;
+
+ base::RunLoop run_loop_;
+};
+
class DeletionTestProperty {
public:
explicit DeletionTestProperty(DeletionTracker* tracker) : tracker_(tracker) {}
@@ -793,13 +860,13 @@ TEST_F(WindowTest, StackChildBelow) {
parent.Init(ui::LAYER_NOT_DRAWN);
Window child1(nullptr);
child1.Init(ui::LAYER_NOT_DRAWN);
- child1.set_id(1);
+ child1.SetId(1);
Window child2(nullptr);
child2.Init(ui::LAYER_NOT_DRAWN);
- child2.set_id(2);
+ child2.SetId(2);
Window child3(nullptr);
child3.Init(ui::LAYER_NOT_DRAWN);
- child3.set_id(3);
+ child3.SetId(3);
parent.AddChild(&child1);
parent.AddChild(&child2);
@@ -1968,7 +2035,7 @@ class WindowObserverTest : public WindowTest,
void OnWindowVisibilityChanged(Window* window, bool visible) override {
if (!visibility_info_) {
- visibility_info_.reset(new VisibilityInfo);
+ visibility_info_ = std::make_unique<VisibilityInfo>();
visibility_info_->changed_count = 0;
}
visibility_info_->window_visible = window->IsVisible();
@@ -2425,7 +2492,7 @@ TEST_F(WindowTest, RecreateLayer) {
// Set properties to non default values.
gfx::Rect window_bounds(100, 100);
Window w(new ColorTestWindowDelegate(SK_ColorWHITE));
- w.set_id(1);
+ w.SetId(1);
w.Init(ui::LAYER_SOLID_COLOR);
w.SetBounds(window_bounds);
@@ -2699,7 +2766,7 @@ TEST_F(WindowTest, RootWindowAttachment) {
observer.Clear();
// Test an indirect add/remove from the RootWindow.
- w1.reset(new Window(nullptr));
+ w1 = std::make_unique<Window>(nullptr);
w1->Init(ui::LAYER_NOT_DRAWN);
Window* w11 = new Window(nullptr);
w11->Init(ui::LAYER_NOT_DRAWN);
@@ -2720,7 +2787,7 @@ TEST_F(WindowTest, RootWindowAttachment) {
observer.Clear();
// Test an indirect add/remove with nested observers.
- w1.reset(new Window(nullptr));
+ w1 = std::make_unique<Window>(nullptr);
w1->Init(ui::LAYER_NOT_DRAWN);
w11 = new Window(nullptr);
w11->Init(ui::LAYER_NOT_DRAWN);
@@ -3511,6 +3578,113 @@ TEST_F(WindowTest, CleanupGestureStateDeleteOtherWindows) {
child2.reset();
}
+class WindowActualScreenBoundsTest
+ : public WindowTest,
+ public testing::WithParamInterface<
+ /*is_target_transform_identical*/ bool> {
+ public:
+ WindowActualScreenBoundsTest() = default;
+ WindowActualScreenBoundsTest(const WindowActualScreenBoundsTest&) = delete;
+ WindowActualScreenBoundsTest& operator=(const WindowActualScreenBoundsTest&) =
+ delete;
+ ~WindowActualScreenBoundsTest() override = default;
+
+ // WindowTest:
+ void SetUp() override {
+ WindowTest::SetUp();
+ viewport_ = std::unique_ptr<Window>(CreateTestWindowWithBounds(
+ gfx::Rect(/*x=*/100, /*y=*/50, /*width=*/200, /*height=*/200),
+ root_window()));
+ child_ = std::unique_ptr<Window>(CreateTestWindowWithBounds(
+ gfx::Rect(/*x=*/0, /*y=*/0, /*width=*/100, /*height*/ 100),
+ viewport_.get()));
+ }
+
+ void TearDown() override {
+ child_.reset();
+ viewport_.reset();
+ WindowTest::TearDown();
+ }
+
+ void OnTranslationAnimationStarted(const gfx::Transform& transform) const {
+ EXPECT_EQ("100,50 100x100", child_->GetActualBoundsInScreen().ToString());
+ EXPECT_EQ("50,0 100x100", child_->GetBoundsInScreen().ToString());
+ }
+
+ void OnTranslationAnimationEnded(const gfx::Transform& transform) const {
+ EXPECT_EQ("50,0 100x100", child_->GetActualBoundsInScreen().ToString());
+ EXPECT_EQ("50,0 100x100", child_->GetBoundsInScreen().ToString());
+ }
+
+ void OnTranslationAnimationProgressed(const gfx::Rect& child_initial_bounds,
+ const gfx::Transform& transform) const {
+ gfx::RectF current_screen_bounds(child_initial_bounds);
+ transform.TransformRect(&current_screen_bounds);
+ EXPECT_EQ(gfx::ToEnclosedRect(current_screen_bounds),
+ child_->GetActualBoundsInScreen());
+ }
+
+ std::unique_ptr<Window> viewport_;
+ std::unique_ptr<Window> child_;
+};
+
+INSTANTIATE_TEST_SUITE_P(All, WindowActualScreenBoundsTest, testing::Bool());
+
+// Verifies that the function to get the window's screen bounds works as
+// expected during layer animation.
+TEST_P(WindowActualScreenBoundsTest, VerifyWindowActualBoundsDuringAnimation) {
+ ui::ScopedAnimationDurationScaleMode test_duration_mode(
+ ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
+
+ auto* viewport_layer = viewport_->layer();
+ gfx::Transform initial_transform;
+ gfx::Transform target_transform;
+ gfx::Rect child_initial_bounds;
+ if (GetParam()) {
+ // Test in the scenario where the target transform is identical.
+
+ // Set the target bounds.
+ viewport_->SetBounds(
+ gfx::Rect(/*x=*/50, /*y=*/0, /*width=*/200, /*height=*/200));
+
+ // Set the transform to reverse the effect brought by bounds setting.
+ initial_transform.Translate(50, 50);
+ viewport_->layer()->SetTransform(initial_transform);
+
+ // Trigger the translation animation.
+ ui::ScopedLayerAnimationSettings settings(viewport_layer->GetAnimator());
+ viewport_layer->SetTransform(target_transform);
+
+ // Calculate the child's initial screen bounds manually.
+ child_initial_bounds =
+ gfx::Rect(/*x=*/50, /*y=*/0, /*width=*/100, /*height=*/100);
+ } else {
+ // Test in the scenario where the target transform is non-identical.
+
+ // Trigger the translation animation.
+ ui::ScopedLayerAnimationSettings settings(viewport_layer->GetAnimator());
+ target_transform.Translate(-50, -50);
+ viewport_layer->SetTransform(target_transform);
+
+ // Calculate the child's initial screen bounds manually.
+ child_initial_bounds =
+ gfx::Rect(/*x=*/100, /*y=*/50, /*width=*/100, /*height=*/100);
+ }
+
+ LayerTranslationAnimationNotifier bounds_checker(
+ viewport_layer, initial_transform, target_transform,
+ base::BindRepeating(
+ &WindowActualScreenBoundsTest::OnTranslationAnimationStarted,
+ base::Unretained(this)),
+ base::BindRepeating(
+ &WindowActualScreenBoundsTest::OnTranslationAnimationEnded,
+ base::Unretained(this)),
+ base::BindRepeating(
+ &WindowActualScreenBoundsTest::OnTranslationAnimationProgressed,
+ base::Unretained(this), child_initial_bounds));
+ bounds_checker.WaitForAnimationCompletion();
+}
+
} // namespace
} // namespace test
} // namespace aura
diff --git a/chromium/ui/aura_extra/aura_extra_export.h b/chromium/ui/aura_extra/aura_extra_export.h
index 6e89721071a..6e408f3377b 100644
--- a/chromium/ui/aura_extra/aura_extra_export.h
+++ b/chromium/ui/aura_extra/aura_extra_export.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_AURA_EXTRA_EXPORT_H_
-#define UI_AURA_EXTRA_EXPORT_H_
+#ifndef UI_AURA_EXTRA_AURA_EXTRA_EXPORT_H_
+#define UI_AURA_EXTRA_AURA_EXTRA_EXPORT_H_
// Defines AURA_EXTRA_EXPORT so that functionality implemented by the aura-extra
// module can be exported to consumers.
@@ -29,4 +29,4 @@
#define AURA_EXTRA_EXPORT
#endif
-#endif // UI_AURA_EXTRA_EXPORT_H_
+#endif // UI_AURA_EXTRA_AURA_EXTRA_EXPORT_H_
diff --git a/chromium/ui/aura_extra/window_occlusion_win.h b/chromium/ui/aura_extra/window_occlusion_win.h
index 9e009690757..b98b719ca63 100644
--- a/chromium/ui/aura_extra/window_occlusion_win.h
+++ b/chromium/ui/aura_extra/window_occlusion_win.h
@@ -23,4 +23,4 @@ ComputeNativeWindowOcclusionStatus(
} // namespace aura_extra
-#endif // UI_AURA_EXTRA_WINDOW_OCCLUSION_WIN_H
+#endif // UI_AURA_EXTRA_WINDOW_OCCLUSION_WIN_H_
diff --git a/chromium/ui/base/BUILD.gn b/chromium/ui/base/BUILD.gn
index d26e454c8ed..2939b20ceb0 100644
--- a/chromium/ui/base/BUILD.gn
+++ b/chromium/ui/base/BUILD.gn
@@ -102,6 +102,12 @@ component("base") {
"dragdrop/os_exchange_data_provider_factory.h",
"ime/utf_offset.cc",
"ime/utf_offset.h",
+ "interaction/element_identifier.cc",
+ "interaction/element_identifier.h",
+ "interaction/element_tracker.cc",
+ "interaction/element_tracker.h",
+ "interaction/interaction_sequence.cc",
+ "interaction/interaction_sequence.h",
"l10n/formatter.cc",
"l10n/formatter.h",
"l10n/l10n_font_util.cc",
@@ -113,6 +119,16 @@ component("base") {
"l10n/time_format.h",
"layout.cc",
"layout.h",
+ "metadata/base_type_conversion.cc",
+ "metadata/base_type_conversion.h",
+ "metadata/metadata_cache.cc",
+ "metadata/metadata_cache.h",
+ "metadata/metadata_header_macros.h",
+ "metadata/metadata_impl_macros.h",
+ "metadata/metadata_macros_internal.h",
+ "metadata/metadata_types.cc",
+ "metadata/metadata_types.h",
+ "metadata/property_metadata.h",
"models/button_menu_item_model.cc",
"models/button_menu_item_model.h",
"models/combobox_model.cc",
@@ -274,8 +290,6 @@ component("base") {
"cocoa/flipped_view.mm",
"cocoa/focus_tracker.h",
"cocoa/focus_tracker.mm",
- "cocoa/focus_window_set.h",
- "cocoa/focus_window_set.mm",
"cocoa/menu_controller.h",
"cocoa/menu_controller.mm",
"cocoa/nsmenuitem_additions.h",
@@ -329,6 +343,7 @@ component("base") {
"accelerators/accelerator.h",
"accelerators/accelerator_manager.cc",
"accelerators/accelerator_manager.h",
+ "accelerators/accelerator_map.h",
"accelerators/media_keys_listener.cc",
"accelerators/media_keys_listener.h",
"accelerators/media_keys_util.cc",
@@ -357,6 +372,8 @@ component("base") {
"accelerators/menu_label_accelerator_util_linux.h",
"linux/linux_desktop.cc",
"linux/linux_desktop.h",
+ "linux/linux_ui_delegate.cc",
+ "linux/linux_ui_delegate.h",
]
}
@@ -417,6 +434,10 @@ component("base") {
defines = [ "IS_UI_BASE_IMPL" ]
+ if (enable_pseudolocales) {
+ defines += [ "ENABLE_PSEUDOLOCALES" ]
+ }
+
public_deps = [
":buildflags",
":features",
@@ -462,6 +483,7 @@ component("base") {
# iOS does not use Chromium-specific code for event handling.
public_deps += [
"//ui/base/clipboard:file_info",
+ "//ui/events:dom_keycode_converter",
"//ui/events:events_base",
"//ui/events/platform",
]
@@ -676,6 +698,9 @@ if (!is_ios) {
static_library("test_support") {
testonly = true
sources = [
+ "interaction/element_test_util.cc",
+ "interaction/element_test_util.h",
+ "interaction/expect_call_in_scope.h",
"resource/mock_resource_bundle_delegate.cc",
"resource/mock_resource_bundle_delegate.h",
]
@@ -797,7 +822,10 @@ static_library("test_support") {
"ime/chromeos/mock_input_method_manager.cc",
"ime/chromeos/mock_input_method_manager.h",
]
- deps += [ "//ui/base/ime/chromeos" ]
+ deps += [
+ "//ui/base/ime/chromeos",
+ "//ui/base/ime/chromeos:typing_session_manager",
+ ]
}
}
@@ -866,10 +894,15 @@ test("ui_base_unittests") {
"class_property_unittest.cc",
"clipboard/file_info_unittest.cc",
"ime/utf_offset_unittest.cc",
+ "interaction/element_tracker_unittest.cc",
+ "interaction/interaction_sequence_unittest.cc",
"l10n/l10n_util_unittest.cc",
"l10n/time_format_unittest.cc",
"layout_unittest.cc",
+ "metadata/base_type_conversion_unittest.cc",
+ "metadata/metadata_unittest.cc",
"models/image_model_unittest.cc",
+ "models/simple_combobox_model_unittest.cc",
"models/simple_menu_model_unittest.cc",
"models/tree_node_iterator_unittest.cc",
"pointer/touch_ui_controller_unittest.cc",
@@ -914,7 +947,7 @@ test("ui_base_unittests") {
}
data = []
- data_deps = [ "//testing/buildbot/filters:ui_base_unittests_filters" ]
+ data_deps = []
deps = [
":ui_base_test_resources_grit",
":ui_base_unittests_bundle_data",
@@ -966,6 +999,7 @@ test("ui_base_unittests") {
} else { # !is_ios
sources += [
"accelerators/accelerator_manager_unittest.cc",
+ "accelerators/accelerator_map_unittest.cc",
"accelerators/accelerator_unittest.cc",
"accelerators/menu_label_accelerator_util_unittest.cc",
"models/dialog_model_unittest.cc",
@@ -1030,10 +1064,12 @@ test("ui_base_unittests") {
"ime/chromeos/input_method_chromeos_unittest.cc",
"ime/chromeos/input_method_descriptor_unittest.cc",
"ime/chromeos/input_method_util_unittest.cc",
+ "ime/chromeos/typing_session_manager_unittest.cc",
]
deps += [
"//build:branding_buildflags",
"//ui/base/ime/chromeos",
+ "//ui/base/ime/chromeos:typing_session_manager",
]
}
if ((is_linux || is_chromeos_lacros) && use_aura) {
@@ -1128,11 +1164,6 @@ test("ui_base_unittests") {
]
}
- if (use_x11) {
- sources += [ "dragdrop/os_exchange_data_provider_x11_unittest.cc" ]
- deps += [ "//ui/gfx/x:unit_test" ]
- }
-
if (is_chromeos_ash) {
deps += [ "//ui/events:dom_keycode_converter" ]
}
diff --git a/chromium/ui/base/DEPS b/chromium/ui/base/DEPS
index 42711119b4c..32d921670d7 100644
--- a/chromium/ui/base/DEPS
+++ b/chromium/ui/base/DEPS
@@ -1,5 +1,4 @@
include_rules = [
- "+components/system_media_controls",
"+media/media_buildflags.h",
"+net",
"+skia/ext",
diff --git a/chromium/ui/base/accelerators/OWNERS b/chromium/ui/base/accelerators/OWNERS
new file mode 100644
index 00000000000..1bef084970c
--- /dev/null
+++ b/chromium/ui/base/accelerators/OWNERS
@@ -0,0 +1 @@
+zentaro@chromium.org
diff --git a/chromium/ui/base/accelerators/accelerator.cc b/chromium/ui/base/accelerators/accelerator.cc
index c44f3d37520..d6913b15149 100644
--- a/chromium/ui/base/accelerators/accelerator.cc
+++ b/chromium/ui/base/accelerators/accelerator.cc
@@ -31,7 +31,7 @@
#include "ui/events/keycodes/keyboard_code_conversion.h"
#endif
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
#include "ui/base/ui_base_features.h"
#endif
@@ -108,6 +108,20 @@ Accelerator::Accelerator(KeyboardCode key_code,
time_stamp_(time_stamp),
interrupted_by_mouse_event_(false) {}
+#if defined(OS_CHROMEOS)
+Accelerator::Accelerator(KeyboardCode key_code,
+ DomCode code,
+ int modifiers,
+ KeyState key_state,
+ base::TimeTicks time_stamp)
+ : key_code_(key_code),
+ code_(code),
+ key_state_(key_state),
+ modifiers_(modifiers & kInterestingFlagsMask),
+ time_stamp_(time_stamp),
+ interrupted_by_mouse_event_(false) {}
+#endif
+
Accelerator::Accelerator(const KeyEvent& key_event)
: key_code_(key_event.key_code()),
key_state_(key_event.type() == ET_KEY_PRESSED ? KeyState::PRESSED
@@ -117,8 +131,15 @@ Accelerator::Accelerator(const KeyEvent& key_event)
time_stamp_(key_event.time_stamp()),
interrupted_by_mouse_event_(false),
source_device_id_(key_event.source_device_id()) {
+#if defined(OS_CHROMEOS)
+ if (features::IsImprovedKeyboardShortcutsEnabled()) {
+ code_ = key_event.code();
+ }
+#endif
+
#if BUILDFLAG(IS_CHROMEOS_ASH)
if (features::IsNewShortcutMappingEnabled()) {
+ DCHECK(!features::IsImprovedKeyboardShortcutsEnabled());
DomKey dom_key = key_event.GetDomKey();
if (!dom_key.IsCharacter())
return;
@@ -154,7 +175,11 @@ KeyEvent Accelerator::ToKeyEvent() const {
return KeyEvent(key_state() == Accelerator::KeyState::PRESSED
? ET_KEY_PRESSED
: ET_KEY_RELEASED,
- key_code(), modifiers(), time_stamp());
+ key_code(),
+#if defined(OS_CHROMEOS)
+ code(),
+#endif
+ modifiers(), time_stamp());
}
bool Accelerator::operator<(const Accelerator& rhs) const {
diff --git a/chromium/ui/base/accelerators/accelerator.h b/chromium/ui/base/accelerators/accelerator.h
index 62eacbe23f9..780a45f9ca2 100644
--- a/chromium/ui/base/accelerators/accelerator.h
+++ b/chromium/ui/base/accelerators/accelerator.h
@@ -21,6 +21,10 @@
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/keyboard_codes.h"
+#if defined(OS_CHROMEOS)
+#include "ui/events/keycodes/dom/dom_code.h"
+#endif
+
namespace ui {
class KeyEvent;
@@ -46,6 +50,26 @@ class COMPONENT_EXPORT(UI_BASE) Accelerator {
int modifiers,
KeyState key_state = KeyState::PRESSED,
base::TimeTicks time_stamp = base::TimeTicks());
+
+#if defined(OS_CHROMEOS)
+ // Additional constructor that takes a |DomCode| in order to implement
+ // layout independent fixed position shortcuts. This is only used for
+ // shortcuts in Chrome OS. One such example is Alt ']'. In the US layout ']'
+ // is VKEY_OEM_6, in the DE layout it is VKEY_OEM_PLUS. However the key in
+ // that position is always DomCode::BRACKET_RIGHT regardless of what the key
+ // generates when pressed. When the DE layout is used and the accelerator
+ // is created with { VKEY_OEM_PLUS, DomCode::BRACKET_RIGHT } the custom
+ // accelerator map will map BRACKET_RIGHT to VKEY_OEM_6 as if in the US
+ // layout in order to lookup the accelerator.
+ //
+ // See accelerator_map.h for more information.
+ Accelerator(KeyboardCode key_code,
+ DomCode code,
+ int modifiers,
+ KeyState key_state = KeyState::PRESSED,
+ base::TimeTicks time_stamp = base::TimeTicks());
+#endif
+
explicit Accelerator(const KeyEvent& key_event);
Accelerator(const Accelerator& accelerator);
Accelerator& operator=(const Accelerator& accelerator);
@@ -67,6 +91,11 @@ class COMPONENT_EXPORT(UI_BASE) Accelerator {
KeyboardCode key_code() const { return key_code_; }
+#if defined(OS_CHROMEOS)
+ DomCode code() const { return code_; }
+ void reset_code() { code_ = DomCode::NONE; }
+#endif
+
// Sets the key state that triggers the accelerator. Default is PRESSED.
void set_key_state(KeyState state) { key_state_ = state; }
KeyState key_state() const { return key_state_; }
@@ -107,6 +136,11 @@ class COMPONENT_EXPORT(UI_BASE) Accelerator {
// The keycode (VK_...).
KeyboardCode key_code_;
+#if defined(OS_CHROMEOS)
+ // The DomCode representing a key's physical position.
+ DomCode code_ = DomCode::NONE;
+#endif
+
KeyState key_state_;
// The state of the Shift/Ctrl/Alt keys. This corresponds to Event::flags().
diff --git a/chromium/ui/base/accelerators/accelerator_manager.cc b/chromium/ui/base/accelerators/accelerator_manager.cc
index 695f378c067..01d842d9716 100644
--- a/chromium/ui/base/accelerators/accelerator_manager.cc
+++ b/chromium/ui/base/accelerators/accelerator_manager.cc
@@ -20,25 +20,24 @@ void AcceleratorManager::Register(
DCHECK(target);
for (const ui::Accelerator& accelerator : accelerators) {
- accelerators_[accelerator].RegisterWithPriority(target, priority);
+ accelerators_.GetOrInsertDefault(accelerator)
+ .RegisterWithPriority(target, priority);
}
}
void AcceleratorManager::Unregister(const Accelerator& accelerator,
AcceleratorTarget* target) {
DCHECK(target);
- auto map_iter = accelerators_.find(accelerator);
- DCHECK(map_iter != accelerators_.end())
- << "Unregistering non-existing accelerator";
+ AcceleratorTargetInfo* target_info = accelerators_.Find(accelerator);
+ DCHECK(target_info) << "Unregistering non-existing accelerator";
- AcceleratorTargetInfo& target_info = map_iter->second;
- const bool was_registered = target_info.Unregister(target);
+ const bool was_registered = target_info->Unregister(target);
DCHECK(was_registered) << "Unregistering accelerator for wrong target";
// If the last target for the accelerator is removed, then erase the
// entry from the map.
- if (!target_info.HasTargets())
- accelerators_.erase(map_iter);
+ if (!target_info->HasTargets())
+ accelerators_.Erase(accelerator);
}
void AcceleratorManager::UnregisterAll(AcceleratorTarget* target) {
@@ -49,7 +48,9 @@ void AcceleratorManager::UnregisterAll(AcceleratorTarget* target) {
// Unregister the target and remove the entry if it was the last target.
const bool was_registered = target_info.Unregister(target);
if (was_registered && !target_info.HasTargets()) {
- map_iter = accelerators_.erase(map_iter);
+ Accelerator key_to_remove = map_iter->first;
+ ++map_iter;
+ accelerators_.Erase(key_to_remove);
continue;
}
@@ -59,35 +60,31 @@ void AcceleratorManager::UnregisterAll(AcceleratorTarget* target) {
}
bool AcceleratorManager::IsRegistered(const Accelerator& accelerator) const {
- auto map_iter = accelerators_.find(accelerator);
+ const AcceleratorTargetInfo* target_info = accelerators_.Find(accelerator);
// If the accelerator is in the map, the target list should not be empty.
- DCHECK(map_iter == accelerators_.end() || map_iter->second.HasTargets());
- return map_iter != accelerators_.end();
+ DCHECK(!target_info || target_info->HasTargets());
+ return target_info != nullptr;
}
bool AcceleratorManager::Process(const Accelerator& accelerator) {
- auto map_iter = accelerators_.find(accelerator);
- if (map_iter == accelerators_.end())
+ const AcceleratorTargetInfo* target_info = accelerators_.Find(accelerator);
+ if (!target_info)
return false;
// If the accelerator is in the map, the target list should not be empty.
- AcceleratorTargetInfo& target_info = map_iter->second;
- DCHECK(target_info.HasTargets());
+ DCHECK(target_info->HasTargets());
// We have to copy the target list here, because processing the accelerator
// event handler may modify the list.
- AcceleratorTargetInfo target_info_copy(target_info);
+ AcceleratorTargetInfo target_info_copy(*target_info);
return target_info_copy.TryProcess(accelerator);
}
bool AcceleratorManager::HasPriorityHandler(
const Accelerator& accelerator) const {
- auto map_iter = accelerators_.find(accelerator);
- if (map_iter == accelerators_.end())
- return false;
-
- return map_iter->second.HasPriorityHandler();
+ const AcceleratorTargetInfo* target_info = accelerators_.Find(accelerator);
+ return target_info && target_info->HasPriorityHandler();
}
AcceleratorManager::AcceleratorTargetInfo::AcceleratorTargetInfo() = default;
diff --git a/chromium/ui/base/accelerators/accelerator_manager.h b/chromium/ui/base/accelerators/accelerator_manager.h
index 0586b8cd204..af354b1cd70 100644
--- a/chromium/ui/base/accelerators/accelerator_manager.h
+++ b/chromium/ui/base/accelerators/accelerator_manager.h
@@ -11,6 +11,11 @@
#include "base/component_export.h"
#include "ui/base/accelerators/accelerator.h"
+#include "ui/base/accelerators/accelerator_map.h"
+
+#if defined(OS_CHROMEOS)
+#include "ui/base/ui_base_features.h"
+#endif
namespace ui {
@@ -79,6 +84,13 @@ class COMPONENT_EXPORT(UI_BASE) AcceleratorManager {
// Whether the given |accelerator| has a priority handler associated with it.
bool HasPriorityHandler(const Accelerator& accelerator) const;
+#if defined(OS_CHROMEOS)
+ void SetUsePositionalLookup(bool use_positional_lookup) {
+ DCHECK(::features::IsImprovedKeyboardShortcutsEnabled());
+ accelerators_.set_use_positional_lookup(use_positional_lookup);
+ }
+#endif // defined(OS_CHROMEOS)
+
private:
// Private helper class to manage the accelerator targets and priority. Each
// set of targets for a given accelerator can only have 0 or 1 priority
@@ -112,13 +124,16 @@ class COMPONENT_EXPORT(UI_BASE) AcceleratorManager {
// Returns true if there are registered targets.
bool HasTargets() const { return !targets_.empty(); }
+ // Returns the number of targets for this accelerator.
+ size_t size() const { return targets_.size(); }
+
private:
std::list<AcceleratorTarget*> targets_;
bool has_priority_handler_ = false;
};
// The accelerators and associated targets.
- std::map<Accelerator, AcceleratorTargetInfo> accelerators_;
+ AcceleratorMap<AcceleratorTargetInfo> accelerators_;
};
} // namespace ui
diff --git a/chromium/ui/base/accelerators/accelerator_manager_unittest.cc b/chromium/ui/base/accelerators/accelerator_manager_unittest.cc
index 502d45aa40d..701c651ce14 100644
--- a/chromium/ui/base/accelerators/accelerator_manager_unittest.cc
+++ b/chromium/ui/base/accelerators/accelerator_manager_unittest.cc
@@ -168,9 +168,12 @@ TEST_F(AcceleratorManagerTest, Process) {
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
-TEST_F(AcceleratorManagerTest, NewMapping) {
+// TODO(crbug.com/1179893): Remove once the feature is enabled permanently.
+TEST_F(AcceleratorManagerTest, NewMappingWithImprovedShortcutsDisabled) {
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(features::kNewShortcutMapping);
+ scoped_feature_list.InitWithFeatures(
+ /*enabled_features=*/{features::kNewShortcutMapping},
+ /*disabled_features=*/{::features::kImprovedKeyboardShortcuts});
// Test new mapping with a ASCII punctuation shortcut that doesn't involve
// shift.
@@ -202,7 +205,140 @@ TEST_F(AcceleratorManagerTest, NewMapping) {
EXPECT_TRUE(manager_.Process(trigger));
}
}
-#endif
+
+// TODO(crbug.com/1179893): Remove once the feature is enabled permanently.
+TEST_F(AcceleratorManagerTest, NewMappingSuperseded) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kNewShortcutMapping);
+
+ // When kImprovedKeyboardShortcuts is enabled, it takes precedence
+ // over kNewShortcutMapping. Remove this test when kImprovedShortcutMapping
+ // is made permanent.
+ EXPECT_TRUE(::features::IsImprovedKeyboardShortcutsEnabled());
+ EXPECT_FALSE(::features::IsNewShortcutMappingEnabled());
+}
+
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+
+#if defined(OS_CHROMEOS)
+
+TEST_F(AcceleratorManagerTest, PositionalShortcuts_AllEqual) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kImprovedKeyboardShortcuts);
+
+ // Use a local instance so that the feature is enabled during construction.
+ AcceleratorManager manager;
+ manager.SetUsePositionalLookup(true);
+
+ // Test what would be ctrl + ']' (VKEY_OEM_6) on a US keyboard. This
+ // should match.
+ TestAcceleratorTarget target;
+ const Accelerator accelerator(VKEY_OEM_6, EF_CONTROL_DOWN);
+ manager.Register({accelerator}, AcceleratorManager::kNormalPriority, &target);
+ KeyEvent event(ui::ET_KEY_PRESSED, VKEY_OEM_6, ui::DomCode::BRACKET_RIGHT,
+ ui::EF_CONTROL_DOWN, ui::DomKey::Constant<']'>::Character,
+ base::TimeTicks());
+ const Accelerator trigger(event);
+ EXPECT_TRUE(manager.IsRegistered(trigger));
+ EXPECT_TRUE(manager.Process(trigger));
+}
+
+TEST_F(AcceleratorManagerTest, PositionalShortcuts_MatchingDomCode) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kImprovedKeyboardShortcuts);
+
+ // Use a local instance so that the feature is enabled during construction.
+ AcceleratorManager manager;
+ manager.SetUsePositionalLookup(true);
+
+ // Test what would be ctrl + ']' on a US keyboard with matching DomCode
+ // and different VKEY (eg. '+'). This is the use case of a positional key
+ // on the German keyboard. Since the DomCode matches, this should match.
+ TestAcceleratorTarget target;
+ const Accelerator accelerator(VKEY_OEM_6, EF_CONTROL_DOWN);
+ manager.Register({accelerator}, AcceleratorManager::kNormalPriority, &target);
+ KeyEvent event(ui::ET_KEY_PRESSED, VKEY_OEM_PLUS, ui::DomCode::BRACKET_RIGHT,
+ ui::EF_CONTROL_DOWN, ui::DomKey::Constant<']'>::Character,
+ base::TimeTicks());
+ const Accelerator trigger(event);
+ EXPECT_TRUE(manager.IsRegistered(trigger));
+ EXPECT_TRUE(manager.Process(trigger));
+}
+
+TEST_F(AcceleratorManagerTest, PositionalShortcuts_NotMatchingDomCode) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kImprovedKeyboardShortcuts);
+
+ // Use a local instance so that the feature is enabled during construction.
+ AcceleratorManager manager;
+ manager.SetUsePositionalLookup(true);
+
+ // Test what would be ctrl + ']' on a US keyboard using positional mapping
+ // for a German layout. The accelerator is registered using the US VKEY and
+ // triggered with a KeyEvent with the US VKEY but a mismatched DomCode. This
+ // should not match. This prevents ghost shortcuts on non-US layouts.
+ TestAcceleratorTarget target;
+ const Accelerator accelerator(VKEY_OEM_6, EF_CONTROL_DOWN);
+ manager.Register({accelerator}, AcceleratorManager::kNormalPriority, &target);
+ KeyEvent event(ui::ET_KEY_PRESSED, VKEY_OEM_6, ui::DomCode::BRACKET_LEFT,
+ ui::EF_CONTROL_DOWN, ui::DomKey::Constant<']'>::Character,
+ base::TimeTicks());
+ const Accelerator trigger(event);
+ EXPECT_FALSE(manager.IsRegistered(trigger));
+ EXPECT_FALSE(manager.Process(trigger));
+}
+
+TEST_F(AcceleratorManagerTest, PositionalShortcuts_NonPositionalMatch) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kImprovedKeyboardShortcuts);
+
+ // Use a local instance so that the feature is enabled during construction.
+ AcceleratorManager manager;
+ manager.SetUsePositionalLookup(true);
+
+ // Test ctrl + 'Z' for the German layout. Since 'Z' is not a positional
+ // key it should match based on the VKEY, regardless of the DomCode. In this
+ // case the 'Z' has DomCode US_Y (ie. QWERTZ keyboard), but it should still
+ // match.
+ TestAcceleratorTarget target;
+ const Accelerator accelerator(VKEY_Z, EF_CONTROL_DOWN);
+ manager.Register({accelerator}, AcceleratorManager::kNormalPriority, &target);
+ KeyEvent event(ui::ET_KEY_PRESSED, VKEY_Z, ui::DomCode::US_Y,
+ ui::EF_CONTROL_DOWN, ui::DomKey::Constant<']'>::Character,
+ base::TimeTicks());
+ const Accelerator trigger(event);
+ EXPECT_TRUE(manager.IsRegistered(trigger));
+ EXPECT_TRUE(manager.Process(trigger));
+}
+
+TEST_F(AcceleratorManagerTest, PositionalShortcuts_NonPositionalNonMatch) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kImprovedKeyboardShortcuts);
+
+ // Use a local instance so that the feature is enabled during construction.
+ AcceleratorManager manager;
+ manager.SetUsePositionalLookup(true);
+
+ // Test ctrl + 'Z' for the German layout. The 'Y' key (in the US_Z position),
+ // should not match. Alphanumeric keys are not positional, and pressing the
+ // key with DomCode::US_Z should not match when it's mapped to VKEY_Y.
+ TestAcceleratorTarget target;
+ const Accelerator accelerator(VKEY_Z, EF_CONTROL_DOWN);
+ manager.Register({accelerator}, AcceleratorManager::kNormalPriority, &target);
+ KeyEvent event(ui::ET_KEY_PRESSED, VKEY_Y, ui::DomCode::US_Z,
+ ui::EF_CONTROL_DOWN, ui::DomKey::Constant<']'>::Character,
+ base::TimeTicks());
+ const Accelerator trigger(event);
+ EXPECT_FALSE(manager.IsRegistered(trigger));
+ EXPECT_FALSE(manager.Process(trigger));
+}
+
+#endif // defined(OS_CHROMEOS)
} // namespace
} // namespace test
diff --git a/chromium/ui/base/accelerators/accelerator_map.h b/chromium/ui/base/accelerators/accelerator_map.h
new file mode 100644
index 00000000000..e64eb5fc086
--- /dev/null
+++ b/chromium/ui/base/accelerators/accelerator_map.h
@@ -0,0 +1,191 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_ACCELERATORS_ACCELERATOR_MAP_H_
+#define UI_BASE_ACCELERATORS_ACCELERATOR_MAP_H_
+
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "base/component_export.h"
+#include "ui/base/accelerators/accelerator.h"
+
+#if defined(OS_CHROMEOS)
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
+#endif
+
+namespace ui {
+
+// This is a wrapper around an internal std::map of type
+// |std::map<Accelerator, V>| where |V| is the mapped value.
+//
+// Accelerators in Chrome on all platforms are specified with the |key_code|,
+// aka VKEY, however certain keys (eg. brackets, comma, period, plus, minus),
+// are in different places based on the keyboard layout. In some cases the
+// VKEYs don't exist, in some cases they now conflict with other shortcuts.
+//
+// Chrome OS uses a positional mapping for this subset of keys. Shortcuts
+// based on these keys are determined by the position of the key on a US
+// keyboard. This was already the case for all non-latin alphabet keyboards
+// (Chinese, Japanese, Arabic, Russian, etc.).
+//
+// To achieve this on Chrome OS for the remaining layouts, an additional
+// remapping may happen to the accelerator used for lookup based on the state
+// of |use_positional_lookup_|. When false no remapping occurs. When true,
+// the |code| aka DomCode (which is by definition fixed position), is used to
+// find the US layout VKEY, and that VKEY is used to lookup in the map.
+//
+// Other non-positional keys, eg. alphanumeric, F-keys, and special keys are
+// all not remapped. Alphanumeric keys always continue to follow the
+// |code|/VKEY defined by the current layout as is existing behavior.
+template <typename V>
+class COMPONENT_EXPORT(UI_BASE) AcceleratorMap {
+ public:
+ AcceleratorMap() = default;
+ ~AcceleratorMap() = default;
+
+ using iterator = typename std::map<Accelerator, V>::iterator;
+ using const_iterator = typename std::map<Accelerator, V>::const_iterator;
+
+ // Lookup an accelerator and return a pointer to the value. If the
+ // accelerator is not in the map, this returns nullptr.
+ const V* Find(const Accelerator& accelerator) const {
+ auto iter = FindImpl(accelerator);
+ return iter == map_.end() ? nullptr : &iter->second;
+ }
+
+ V* Find(const Accelerator& accelerator) {
+ // Call the const implementation to avoid duplicating code.
+ return const_cast<V*>(
+ const_cast<const AcceleratorMap*>(this)->Find(accelerator));
+ }
+
+ // Lookup an accelerator and return a reference to the value. If the
+ // accelerator is not present this function will DCHECK.
+ const V& Get(const Accelerator& accelerator) const {
+ auto iter = FindImpl(accelerator);
+ DCHECK(iter != map_.end());
+ return iter->second;
+ }
+
+ V& Get(const Accelerator& accelerator) {
+ // Call the const implementation to avoid duplicating code.
+ return const_cast<V&>(
+ const_cast<const AcceleratorMap*>(this)->Get(accelerator));
+ }
+
+ V& GetOrInsertDefault(const Accelerator& accelerator) {
+#if defined(OS_CHROMEOS)
+ // Ensure the DomCode is NONE before registering. The DomCode is only
+ // used during lookup to select the correct VKEY.
+ if (accelerator.code() != DomCode::NONE) {
+ Accelerator accelerator_copy = accelerator;
+ accelerator_copy.reset_code();
+ return map_[accelerator_copy];
+ }
+#endif
+ return map_[accelerator];
+ }
+
+ // Erase an accelerator from the map.
+ bool Erase(const Accelerator& accelerator) {
+ return map_.erase(accelerator) > 0;
+ }
+
+ // Inserts a new accelerator and value into the map. DCHECKs if the
+ // accelerator was already in the map.
+ void InsertNew(const std::pair<const Accelerator, V>& value) {
+#if defined(OS_CHROMEOS)
+ // Ensure the DomCode is NONE before registering. The DomCode is only
+ // used during lookup to select the correct VKEY.
+ if (value.first.code() != DomCode::NONE) {
+ Accelerator accelerator_copy = value.first;
+ accelerator_copy.reset_code();
+ auto value_copy = std::make_pair(accelerator_copy, value.second);
+ auto result = map_.insert(value_copy);
+ DCHECK(result.second);
+ return;
+ }
+#endif
+ auto result = map_.insert(value);
+ DCHECK(result.second);
+ }
+
+ // Iterators for the internal map.
+ iterator begin() { return map_.begin(); }
+ iterator end() { return map_.end(); }
+
+ // Returns the number of items in the map.
+ size_t size() const { return map_.size(); }
+
+ // Returns true if the map is empty.
+ bool empty() const { return map_.empty(); }
+
+#if defined(OS_CHROMEOS)
+ // When true, lookup operators on the map will remap the |key_code| of
+ // position-based keys based on the |code|.
+ void set_use_positional_lookup(bool use_positional_lookup) {
+ use_positional_lookup_ = use_positional_lookup;
+ }
+#endif
+
+ private:
+ std::map<Accelerator, V> map_;
+
+#if defined(OS_CHROMEOS)
+ bool use_positional_lookup_ = false;
+
+ // For the shortcuts that use positional mapping, the lookup is done based
+ // on the |key_code| in the US layout. The supplied |code| (DomCode) is used
+ // to remap the layout specific |key_code| with the US layout equivalent,
+ // which effectively pins the location of these keys in place regardless of
+ // the actual key mapping. Note that this only happens for a subset of keys
+ // and has no overlap with alphanumeric characters or the language equivalent
+ // keys that map to the alphanumeric set of VKEYS.
+ //
+ // One such example is Alt ']'. In the US layout ']' is VKEY_OEM_6, in the
+ // DE layout it is VKEY_OEM_PLUS. However the key in that position is always
+ // DomCode::BRACKET_RIGHT regardless of what the key generates when pressed.
+ // This function uses the DomCode to remap the VKEY back to it's US layout
+ // equivalent.
+ //
+ // See the design doc in crbug.com/1174326 for more information.
+ Accelerator RemapAcceleratorForLookup(const Accelerator& accelerator) const {
+ KeyboardCode lookup_key_code = accelerator.key_code();
+ if (use_positional_lookup_) {
+ // If there's a valid remapping, use that |KeyboardCode| instead.
+ KeyboardCode remapped_key_code =
+ KeycodeConverter::MapPositionalDomCodeToUSShortcutKey(
+ accelerator.code());
+ lookup_key_code = remapped_key_code != VKEY_UNKNOWN ? remapped_key_code
+ : lookup_key_code;
+ }
+
+ return Accelerator(lookup_key_code, DomCode::NONE, accelerator.modifiers(),
+ accelerator.key_state());
+ }
+#endif // defined(OS_CHROMEOS)
+
+ const_iterator FindImpl(const Accelerator& accelerator) const {
+#if defined(OS_CHROMEOS)
+ auto iter = map_.find(RemapAcceleratorForLookup(accelerator));
+ // Sanity check that a DomCode was never inserted into the map.
+ DCHECK(iter == map_.end() || iter->first.code() == DomCode::NONE);
+ return iter;
+#endif // defined(OS_CHROMEOS)
+
+ return map_.find(accelerator);
+ }
+
+ iterator FindImpl(const Accelerator& accelerator) {
+ return const_cast<V*>(
+ const_cast<const AcceleratorMap*>(this)->FindImpl(accelerator));
+ }
+};
+
+} // namespace ui
+
+#endif // UI_BASE_ACCELERATORS_ACCELERATOR_MAP_H_
diff --git a/chromium/ui/base/accelerators/accelerator_map_unittest.cc b/chromium/ui/base/accelerators/accelerator_map_unittest.cc
new file mode 100644
index 00000000000..a89715d4bb9
--- /dev/null
+++ b/chromium/ui/base/accelerators/accelerator_map_unittest.cc
@@ -0,0 +1,235 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/accelerators/accelerator_map.h"
+
+#include <utility>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/accelerators/accelerator.h"
+#include "ui/events/event.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+
+namespace ui {
+
+namespace {
+
+bool IsValidMatch(AcceleratorMap<int>* map,
+ const Accelerator& pressed,
+ int expected) {
+ return nullptr != map->Find(pressed) && expected == *map->Find(pressed) &&
+ expected == map->Get(pressed);
+}
+
+TEST(AcceleratorMapTest, MapIsEmpty) {
+ AcceleratorMap<int> m;
+ EXPECT_EQ(0U, m.size());
+ EXPECT_TRUE(m.empty());
+}
+
+TEST(AcceleratorMapTest, EmptyFind) {
+ AcceleratorMap<int> m;
+ Accelerator accelerator(VKEY_Z, EF_SHIFT_DOWN);
+ EXPECT_EQ(nullptr, m.Find(accelerator));
+
+ // Still empty after lookup.
+ EXPECT_TRUE(m.empty());
+}
+
+TEST(AcceleratorMapTest, FindExists) {
+ AcceleratorMap<int> m;
+ Accelerator accelerator(VKEY_Z, EF_SHIFT_DOWN);
+
+ const int expected = 77;
+ m.InsertNew(std::make_pair(accelerator, expected));
+ EXPECT_TRUE(IsValidMatch(&m, accelerator, expected));
+
+ // Still single entry.
+ EXPECT_EQ(1U, m.size());
+}
+
+TEST(AcceleratorMapTest, FindDoesNotExist) {
+ AcceleratorMap<int> m;
+ Accelerator accelerator(VKEY_Z, EF_SHIFT_DOWN);
+ Accelerator other(VKEY_Y, EF_SHIFT_DOWN);
+
+ const int expected = 77;
+ m.InsertNew(std::make_pair(accelerator, expected));
+ EXPECT_EQ(nullptr, m.Find(other));
+
+ // Still single entry.
+ EXPECT_EQ(1U, m.size());
+}
+
+TEST(AcceleratorMapTest, InsertDefaultCreatedNew) {
+ AcceleratorMap<int> m;
+ Accelerator accelerator(VKEY_Z, EF_SHIFT_DOWN);
+ int& value_ref = m.GetOrInsertDefault(accelerator);
+ EXPECT_EQ(int(), value_ref);
+ EXPECT_EQ(1U, m.size());
+}
+
+TEST(AcceleratorMapTest, ChangeValueViaReturnedRef) {
+ AcceleratorMap<int> m;
+ Accelerator accelerator(VKEY_Z, EF_SHIFT_DOWN);
+ int& value_ref = m.GetOrInsertDefault(accelerator);
+
+ const int expected = 77;
+ value_ref = expected;
+ EXPECT_EQ(expected, m.Get(accelerator));
+}
+
+TEST(AcceleratorMapTest, SetValueDirect) {
+ AcceleratorMap<int> m;
+ Accelerator accelerator(VKEY_Z, EF_SHIFT_DOWN);
+
+ const int expected = 77;
+ m.InsertNew(std::make_pair(accelerator, expected));
+ EXPECT_EQ(expected, m.Get(accelerator));
+}
+
+TEST(AcceleratorMapTest, Iterate) {
+ AcceleratorMap<int> m;
+ Accelerator accelerator(VKEY_Z, EF_SHIFT_DOWN);
+ const int expected = 77;
+ m.InsertNew(std::make_pair(accelerator, expected));
+
+ auto iter = m.begin();
+ EXPECT_NE(m.end(), iter);
+ EXPECT_EQ(accelerator, iter->first);
+ EXPECT_EQ(expected, iter->second);
+ ++iter;
+ EXPECT_EQ(m.end(), iter);
+}
+
+// Chrome OS specific tests.
+// Only Chrome OS supports positional shortcuts.
+#if defined(OS_CHROMEOS)
+
+// Even with positional lookup enabled, if both the stored and lookup
+// accelerator have no DomCode then the behavior is as if there was no
+// positional lookup.
+TEST(AcceleratorMapTest, PositionalLookupExistsVkeyOnly) {
+ AcceleratorMap<int> m;
+ m.set_use_positional_lookup(true);
+ Accelerator accelerator(VKEY_Z, EF_SHIFT_DOWN);
+ EXPECT_EQ(DomCode::NONE, accelerator.code());
+
+ const int expected = 77;
+ m.InsertNew(std::make_pair(accelerator, expected));
+ EXPECT_TRUE(IsValidMatch(&m, accelerator, expected));
+}
+
+// Both the VKEY and DomCode match, so this is always a match. This scenario
+// happens when positional shortcuts are enabled, and the layout has a VKEY
+// mapping consistent with the US layout.
+TEST(AcceleratorMapTest, PositionalLookupExistsFullMatch) {
+ AcceleratorMap<int> m;
+ m.set_use_positional_lookup(true);
+
+ Accelerator registered(VKEY_OEM_6, EF_SHIFT_DOWN);
+ const int expected = 77;
+ m.InsertNew(std::make_pair(registered, expected));
+
+ Accelerator pressed(VKEY_OEM_6, DomCode::BRACKET_RIGHT, EF_SHIFT_DOWN);
+ EXPECT_TRUE(IsValidMatch(&m, pressed, expected));
+}
+
+// The DomCode matches, but the VKEY does not - this is a positional match.
+// This scenario happens on eg. German and Spanish keyboards.
+TEST(AcceleratorMapTest, PositionalLookupDomCodeMatchOnly) {
+ AcceleratorMap<int> m;
+ m.set_use_positional_lookup(true);
+
+ Accelerator registered(VKEY_OEM_6, EF_SHIFT_DOWN);
+ const int expected = 77;
+ m.InsertNew(std::make_pair(registered, expected));
+
+ Accelerator pressed(VKEY_OEM_PLUS, DomCode::BRACKET_RIGHT, EF_SHIFT_DOWN);
+ EXPECT_TRUE(IsValidMatch(&m, pressed, expected));
+}
+
+// With positional mapping enabled this first press is like the ']' key
+// on a German keyboard, and it matches. When positional mapping is disabled
+// it no longer matches because the VKEYs are different.
+//
+// Disabling positional lookup also used for special layouts like Dvorak which
+// are designed to intentionally reposition certain punctuation keys. These
+// layouts already work with US-like VKEY mapping, albeit to keys in different
+// positions.
+TEST(AcceleratorMapTest, PositionalLookupDisabled) {
+ AcceleratorMap<int> m;
+
+ // NOTE: The state of use_positional_lookup_ has no effect on insertion.
+ Accelerator registered(VKEY_OEM_6, EF_SHIFT_DOWN);
+ const int expected = 77;
+ m.InsertNew(std::make_pair(registered, expected));
+
+ // This lookup with succeed with positional lookup enabled.
+ m.set_use_positional_lookup(true);
+ Accelerator pressed(VKEY_OEM_PLUS, DomCode::BRACKET_RIGHT, EF_SHIFT_DOWN);
+ EXPECT_TRUE(IsValidMatch(&m, pressed, expected));
+
+ // Switch to a non-positional layout before testing the pressed keys and
+ // this lookup with fail.
+ m.set_use_positional_lookup(false);
+ EXPECT_FALSE(IsValidMatch(&m, pressed, expected));
+}
+
+// The VKEY matches, and both the registered and pressed accelerator supply a
+// positional DomCode - this is not a match. This prevents ghost or conflicting
+// shortcuts on the key that has the matching VKEY. This is a scenario on a
+// Spanish keyboard.
+TEST(AcceleratorMapTest, PositionalLookupVkeyMatchOnlyBothDomCodesSpecified) {
+ AcceleratorMap<int> m;
+ m.set_use_positional_lookup(true);
+ Accelerator registered(VKEY_OEM_6, EF_SHIFT_DOWN);
+ const int expected = 77;
+ m.InsertNew(std::make_pair(registered, expected));
+
+ Accelerator pressed(VKEY_OEM_6, DomCode::EQUAL, EF_SHIFT_DOWN);
+ EXPECT_FALSE(IsValidMatch(&m, pressed, expected));
+}
+
+// The VKEY matches, and the registered accelerator has no DomCode (ie. it's
+// non-positional) - this is a match. This scenario is to allow non-positional
+// shortcuts to continue to work regardless of the DomCode. This is a scenario
+// for the Z key on a German or other QWERTZ layout.
+TEST(AcceleratorMapTest, PositionalLookupVkeyMatchOnlyRegisteredDomCodeIsNone) {
+ AcceleratorMap<int> m;
+ m.set_use_positional_lookup(true);
+ Accelerator registered(VKEY_Z, EF_SHIFT_DOWN);
+ const int expected = 77;
+ m.InsertNew(std::make_pair(registered, expected));
+
+ Accelerator pressed(VKEY_Z, DomCode::US_Y, EF_SHIFT_DOWN);
+ EXPECT_TRUE(IsValidMatch(&m, pressed, expected));
+}
+
+// When an accelerator is inserted to the map, if it contains a DomCode it
+// should be stripped out.
+TEST(AcceleratorMapTest, DomCodesStrippedWhenInserted) {
+ AcceleratorMap<int> m;
+ m.set_use_positional_lookup(true);
+
+ // Verify the accelerator has a DomCode and insert it.
+ Accelerator accelerator(ui::VKEY_F, DomCode::US_F,
+ ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN);
+ EXPECT_EQ(accelerator.code(), DomCode::US_F);
+ const int expected = 77;
+ m.InsertNew(std::make_pair(accelerator, expected));
+
+ // Reset the DomCode on the accelerator and perform a lookup and verify
+ // that it can still be found.
+ accelerator.reset_code();
+ auto* value = m.Find(accelerator);
+ ASSERT_TRUE(value);
+ EXPECT_EQ(*value, expected);
+}
+
+#endif // defined(OS_CHROMEOS)
+
+} // namespace
+
+} // namespace ui \ No newline at end of file
diff --git a/chromium/ui/base/accelerators/accelerator_unittest.cc b/chromium/ui/base/accelerators/accelerator_unittest.cc
index 74282004e8e..e2e8e6ebfce 100644
--- a/chromium/ui/base/accelerators/accelerator_unittest.cc
+++ b/chromium/ui/base/accelerators/accelerator_unittest.cc
@@ -7,8 +7,10 @@
#include <string>
#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/ui_base_features.h"
#include "ui/events/event.h"
namespace ui {
@@ -74,4 +76,35 @@ TEST(AcceleratorTest, ShortcutTextForUnknownKey) {
EXPECT_EQ(std::u16string(), accelerator.GetShortcutText());
}
+TEST(AcceleratorTest, ConversionFromKeyEvent) {
+ ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_F,
+ ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN);
+ Accelerator accelerator(key_event);
+
+ EXPECT_EQ(accelerator.key_code(), ui::VKEY_F);
+ EXPECT_EQ(accelerator.modifiers(), ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN);
+}
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+TEST(AcceleratorTest, ConversionFromKeyEvent_Ash) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ ::features::kImprovedKeyboardShortcuts);
+
+ ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_F,
+ ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN);
+ Accelerator accelerator(key_event);
+
+ EXPECT_EQ(accelerator.key_code(), ui::VKEY_F);
+ EXPECT_EQ(accelerator.modifiers(), ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN);
+
+ // Code is set when converting from a KeyEvent.
+ EXPECT_EQ(accelerator.code(), DomCode::US_F);
+
+ // Test resetting code.
+ accelerator.reset_code();
+ EXPECT_EQ(accelerator.code(), DomCode::NONE);
+}
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+
} // namespace ui
diff --git a/chromium/ui/base/class_property.h b/chromium/ui/base/class_property.h
index 4af52aef43d..25c00e7d064 100644
--- a/chromium/ui/base/class_property.h
+++ b/chromium/ui/base/class_property.h
@@ -137,8 +137,6 @@ class COMPONENT_EXPORT(UI_BASE) PropertyHandler {
std::map<const void*, Value> prop_map_;
};
-namespace {
-
// No single new-style cast works for every conversion to/from int64_t, so we
// need this helper class.
template<typename T>
@@ -162,8 +160,6 @@ class ClassPropertyCaster<base::TimeDelta> {
}
};
-} // namespace
-
namespace subtle {
class COMPONENT_EXPORT(UI_BASE) PropertyHelper {
diff --git a/chromium/ui/base/clipboard/BUILD.gn b/chromium/ui/base/clipboard/BUILD.gn
index e710361b70b..42d2fb48145 100644
--- a/chromium/ui/base/clipboard/BUILD.gn
+++ b/chromium/ui/base/clipboard/BUILD.gn
@@ -159,6 +159,14 @@ component("clipboard") {
# TODO(crbug.com/1096425): Cleanup when non-Ozone path gets dropped.
if (use_ozone || use_x11) {
sources += [ "clipboard_factory_ozone.cc" ]
+ if (!use_ozone) {
+ sources += [
+ "clipboard_data.cc",
+ "clipboard_data.h",
+ "clipboard_non_backed.cc",
+ "clipboard_non_backed.h",
+ ]
+ }
deps += [ "//ui/base" ]
}
}
@@ -203,6 +211,7 @@ source_set("clipboard_test_support") {
"//build:chromecast_buildflags",
"//build:chromeos_buildflags",
"//ui/base:features",
+ "//ui/gfx",
]
if (is_android) {
diff --git a/chromium/ui/base/clipboard/clipboard.cc b/chromium/ui/base/clipboard/clipboard.cc
index 83fd6aa2e71..e5aa1deb231 100644
--- a/chromium/ui/base/clipboard/clipboard.cc
+++ b/chromium/ui/base/clipboard/clipboard.cc
@@ -12,7 +12,6 @@
#include "base/containers/contains.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
-#include "build/chromeos_buildflags.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/size.h"
#include "url/gurl.h"
@@ -25,22 +24,30 @@ namespace ui {
// static
bool Clipboard::IsSupportedClipboardBuffer(ClipboardBuffer buffer) {
+ // Use lambda instead of local helper function in order to access private
+ // member IsSelectionBufferAvailable().
+ static auto IsSupportedSelectionClipboard = []() -> bool {
+#if defined(USE_OZONE) && !defined(OS_CHROMEOS)
+ if (features::IsUsingOzonePlatform()) {
+ ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
+ CHECK(clipboard);
+ return clipboard->IsSelectionBufferAvailable();
+ }
+#endif
+#if !defined(OS_WIN) && !defined(OS_APPLE) && !defined(OS_CHROMEOS)
+ return true;
+#else
+ return false;
+#endif
+ };
+
switch (buffer) {
case ClipboardBuffer::kCopyPaste:
return true;
case ClipboardBuffer::kSelection:
-#if defined(USE_OZONE) && !BUILDFLAG(IS_CHROMEOS_ASH)
- if (features::IsUsingOzonePlatform()) {
- ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
- CHECK(clipboard);
- return clipboard->IsSelectionBufferAvailable();
- }
-#endif
-#if !defined(OS_WIN) && !defined(OS_APPLE) && !BUILDFLAG(IS_CHROMEOS_ASH)
- return true;
-#else
- return false;
-#endif
+ // Cache the result to make this function cheap.
+ static bool selection_result = IsSupportedSelectionClipboard();
+ return selection_result;
case ClipboardBuffer::kDrag:
return false;
}
diff --git a/chromium/ui/base/clipboard/clipboard.h b/chromium/ui/base/clipboard/clipboard.h
index 82d35fe8f88..11ce126c3d8 100644
--- a/chromium/ui/base/clipboard/clipboard.h
+++ b/chromium/ui/base/clipboard/clipboard.h
@@ -58,6 +58,8 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
uint32_t fragment_end)>;
using ReadSvgCallback = base::OnceCallback<void(std::u16string result)>;
using ReadRTFCallback = base::OnceCallback<void(std::string result)>;
+ using ReadPngCallback =
+ base::OnceCallback<void(const std::vector<uint8_t>& result)>;
using ReadImageCallback = base::OnceCallback<void(const SkBitmap& result)>;
using ReadCustomDataCallback =
base::OnceCallback<void(std::u16string result)>;
@@ -180,6 +182,11 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
const DataTransferEndpoint* data_dst,
ReadRTFCallback callback) const;
+ // Reads a png from the clipboard, if available.
+ virtual void ReadPng(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ ReadPngCallback callback) const = 0;
+
// Reads an image from the clipboard, if available.
virtual void ReadImage(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
diff --git a/chromium/ui/base/clipboard/clipboard_android.cc b/chromium/ui/base/clipboard/clipboard_android.cc
index dd32059ebab..62e6ef76ac2 100644
--- a/chromium/ui/base/clipboard/clipboard_android.cc
+++ b/chromium/ui/base/clipboard/clipboard_android.cc
@@ -18,6 +18,7 @@
#include "base/containers/contains.h"
#include "base/lazy_instance.h"
#include "base/no_destructor.h"
+#include "base/notreached.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "base/task/post_task.h"
@@ -63,6 +64,7 @@ namespace {
constexpr char kPngExtension[] = ".png";
+using ReadPngCallback = ClipboardAndroid::ReadPngCallback;
using ReadImageCallback = ClipboardAndroid::ReadImageCallback;
// Fetching image data from Java.
@@ -478,13 +480,13 @@ void ClipboardAndroid::ReadAvailableTypes(
types->push_back(base::UTF8ToUTF16(kMimeTypeText));
if (IsFormatAvailable(ClipboardFormatType::GetHtmlType(), buffer, data_dst))
types->push_back(base::UTF8ToUTF16(kMimeTypeHTML));
+ if (IsFormatAvailable(ClipboardFormatType::GetBitmapType(), buffer, data_dst))
+ types->push_back(base::UTF8ToUTF16(kMimeTypePNG));
// these formats aren't supported by the ClipboardMap currently, but might
// be one day?
if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer, data_dst))
types->push_back(base::UTF8ToUTF16(kMimeTypeRTF));
- if (IsFormatAvailable(ClipboardFormatType::GetBitmapType(), buffer, data_dst))
- types->push_back(base::UTF8ToUTF16(kMimeTypePNG));
}
// |data_dst| is not used. It's only passed to be consistent with other
@@ -571,6 +573,16 @@ void ClipboardAndroid::ReadRTF(ClipboardBuffer buffer,
// |data_dst| is not used. It's only passed to be consistent with other
// platforms.
+void ClipboardAndroid::ReadPng(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ ReadPngCallback callback) const {
+ DCHECK(CalledOnValidThread());
+ // TODO(crbug.com/1201018): Implement this.
+ NOTIMPLEMENTED();
+}
+
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
void ClipboardAndroid::ReadImage(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadImageCallback callback) const {
diff --git a/chromium/ui/base/clipboard/clipboard_android.h b/chromium/ui/base/clipboard/clipboard_android.h
index c8e23a49527..870ee348b14 100644
--- a/chromium/ui/base/clipboard/clipboard_android.h
+++ b/chromium/ui/base/clipboard/clipboard_android.h
@@ -88,6 +88,9 @@ class ClipboardAndroid : public Clipboard {
void ReadRTF(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
std::string* result) const override;
+ void ReadPng(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ ReadPngCallback callback) const override;
void ReadImage(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadImageCallback callback) const override;
diff --git a/chromium/ui/base/clipboard/clipboard_constants.cc b/chromium/ui/base/clipboard/clipboard_constants.cc
index df542333f6b..690a8b555e5 100644
--- a/chromium/ui/base/clipboard/clipboard_constants.cc
+++ b/chromium/ui/base/clipboard/clipboard_constants.cc
@@ -17,6 +17,8 @@ const char kMimeTypeHTML[] = "text/html";
const char kMimeTypeSvg[] = "image/svg+xml";
const char kMimeTypeRTF[] = "text/rtf";
const char kMimeTypePNG[] = "image/png";
+// Used for image drag & drop from LaCrOS.
+const char kMimeTypeOctetStream[] = "application/octet-stream";
#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA)
const char kMimeTypeLinuxUtf8String[] = "UTF8_STRING";
diff --git a/chromium/ui/base/clipboard/clipboard_constants.h b/chromium/ui/base/clipboard/clipboard_constants.h
index d0eea2208fb..5bfe4e6f4e5 100644
--- a/chromium/ui/base/clipboard/clipboard_constants.h
+++ b/chromium/ui/base/clipboard/clipboard_constants.h
@@ -5,7 +5,6 @@
#ifndef UI_BASE_CLIPBOARD_CLIPBOARD_CONSTANTS_H_
#define UI_BASE_CLIPBOARD_CLIPBOARD_CONSTANTS_H_
-#include <string>
#include "base/component_export.h"
#include "build/build_config.h"
@@ -35,6 +34,8 @@ COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypeHTML[];
COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypeSvg[];
COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypeRTF[];
COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypePNG[];
+COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
+extern const char kMimeTypeOctetStream[];
// Linux-specific MIME type constants (also used in Fuchsia).
#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA)
diff --git a/chromium/ui/base/clipboard/clipboard_data.cc b/chromium/ui/base/clipboard/clipboard_data.cc
index 0f93ad7484c..0bc1e93ec74 100644
--- a/chromium/ui/base/clipboard/clipboard_data.cc
+++ b/chromium/ui/base/clipboard/clipboard_data.cc
@@ -10,6 +10,7 @@
#include "base/notreached.h"
#include "skia/ext/skia_utils_base.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
+#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/skia_util.h"
namespace ui {
@@ -22,7 +23,7 @@ ClipboardData::ClipboardData(const ClipboardData& other) {
markup_data_ = other.markup_data_;
url_ = other.url_;
rtf_data_ = other.rtf_data_;
- bitmap_ = other.bitmap();
+ png_ = other.png_;
bookmark_title_ = other.bookmark_title_;
bookmark_url_ = other.bookmark_url_;
custom_data_format_ = other.custom_data_format_;
@@ -48,7 +49,7 @@ bool ClipboardData::operator==(const ClipboardData& that) const {
custom_data_data_ == that.custom_data_data() &&
web_smart_paste_ == that.web_smart_paste() &&
svg_data_ == that.svg_data() && filenames_ == that.filenames() &&
- gfx::BitmapsAreEqual(bitmap_, that.bitmap()) &&
+ png_ == that.png() &&
(src_.get() ? (that.source() && *src_.get() == *that.source())
: !that.source());
}
@@ -57,10 +58,22 @@ bool ClipboardData::operator!=(const ClipboardData& that) const {
return !(*this == that);
}
+void ClipboardData::SetPngData(std::vector<uint8_t> png) {
+ png_ = std::move(png);
+ format_ |= static_cast<int>(ClipboardInternalFormat::kPng);
+}
+
+SkBitmap ClipboardData::bitmap() const {
+ SkBitmap bitmap;
+ gfx::PNGCodec::Decode(png_.data(), png_.size(), &bitmap);
+ return bitmap;
+}
+
void ClipboardData::SetBitmapData(const SkBitmap& bitmap) {
DCHECK_EQ(bitmap.colorType(), kN32_SkColorType);
- bitmap_ = bitmap;
- format_ |= static_cast<int>(ClipboardInternalFormat::kBitmap);
+ gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, /*discard_transparency=*/false,
+ &png_);
+ format_ |= static_cast<int>(ClipboardInternalFormat::kPng);
}
void ClipboardData::SetCustomData(const std::string& data_format,
diff --git a/chromium/ui/base/clipboard/clipboard_data.h b/chromium/ui/base/clipboard/clipboard_data.h
index 3c60c1f797b..3f4a550655a 100644
--- a/chromium/ui/base/clipboard/clipboard_data.h
+++ b/chromium/ui/base/clipboard/clipboard_data.h
@@ -24,7 +24,7 @@ enum class ClipboardInternalFormat {
kSvg = 1 << 2,
kRtf = 1 << 3,
kBookmark = 1 << 4,
- kBitmap = 1 << 5,
+ kPng = 1 << 5,
kCustom = 1 << 6,
kWeb = 1 << 7,
kFilenames = 1 << 8,
@@ -88,7 +88,12 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardData {
format_ |= static_cast<int>(ClipboardInternalFormat::kBookmark);
}
- const SkBitmap& bitmap() const { return bitmap_; }
+ const std::vector<uint8_t>& png() const { return png_; }
+ void SetPngData(std::vector<uint8_t> png);
+
+ // Bitmaps are stored as encoded bytes in the `png_` member. This means we
+ // cannot return a const reference, since the bitmap is created on request.
+ SkBitmap bitmap() const;
void SetBitmapData(const SkBitmap& bitmap);
const std::string& custom_data_format() const { return custom_data_format_; }
@@ -130,8 +135,8 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardData {
std::string bookmark_title_;
std::string bookmark_url_;
- // Bitmap images.
- SkBitmap bitmap_;
+ // PNG image data. Bitmaps are encoded into and decoded from this member.
+ std::vector<uint8_t> png_;
// Data with custom format.
std::string custom_data_format_;
@@ -149,7 +154,7 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardData {
int format_;
// The source of the data.
- std::unique_ptr<DataTransferEndpoint> src_ = nullptr;
+ std::unique_ptr<DataTransferEndpoint> src_;
};
} // namespace ui
diff --git a/chromium/ui/base/clipboard/clipboard_data_endpoint.cc b/chromium/ui/base/clipboard/clipboard_data_endpoint.cc
index 10aed991bcb..1ce15996c69 100644
--- a/chromium/ui/base/clipboard/clipboard_data_endpoint.cc
+++ b/chromium/ui/base/clipboard/clipboard_data_endpoint.cc
@@ -5,7 +5,7 @@
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "base/check_op.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
namespace ui {
@@ -19,7 +19,7 @@ DataTransferEndpoint::DataTransferEndpoint(const url::Origin& origin,
DataTransferEndpoint::DataTransferEndpoint(EndpointType type,
bool notify_if_restricted)
: type_(type),
- origin_(base::nullopt),
+ origin_(absl::nullopt),
notify_if_restricted_(notify_if_restricted) {
DCHECK_NE(type, EndpointType::kUrl);
}
diff --git a/chromium/ui/base/clipboard/clipboard_data_unittest.cc b/chromium/ui/base/clipboard/clipboard_data_unittest.cc
index 627793fd3c1..35baa44f0d2 100644
--- a/chromium/ui/base/clipboard/clipboard_data_unittest.cc
+++ b/chromium/ui/base/clipboard/clipboard_data_unittest.cc
@@ -9,13 +9,14 @@
#include "base/strings/string_piece_forward.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
+#include "ui/gfx/skia_util.h"
#include "url/gurl.h"
namespace ui {
// Tests that two ClipboardData objects won't be equal if they don't have the
// same bitmap.
-TEST(ClipboardDataTest, BitMapTest) {
+TEST(ClipboardDataTest, BitmapTest) {
ClipboardData data1;
SkBitmap test_bitmap;
test_bitmap.allocN32Pixels(3, 2);
@@ -43,4 +44,15 @@ TEST(ClipboardDataTest, DataSrcTest) {
EXPECT_EQ(data1, data2);
}
+// Tests that encoding/decoding bitmaps as PNG bytes works as intended.
+TEST(ClipboardDataTest, BitmapAsBytesTest) {
+ ClipboardData data1;
+ SkBitmap test_bitmap;
+ test_bitmap.allocN32Pixels(3, 2);
+ test_bitmap.eraseARGB(255, 0, 255, 0);
+ EXPECT_FALSE(gfx::BitmapsAreEqual(data1.bitmap(), test_bitmap));
+ data1.SetBitmapData(test_bitmap);
+ EXPECT_TRUE(gfx::BitmapsAreEqual(data1.bitmap(), test_bitmap));
+}
+
} // namespace ui \ No newline at end of file
diff --git a/chromium/ui/base/clipboard/clipboard_format_type.h b/chromium/ui/base/clipboard/clipboard_format_type.h
index 982ea528952..03451964918 100644
--- a/chromium/ui/base/clipboard/clipboard_format_type.h
+++ b/chromium/ui/base/clipboard/clipboard_format_type.h
@@ -62,6 +62,8 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) ClipboardFormatType {
static const ClipboardFormatType& GetHtmlType();
static const ClipboardFormatType& GetSvgType();
static const ClipboardFormatType& GetRtfType();
+ static const ClipboardFormatType& GetPngType();
+ // TODO(crbug.com/1201018): Remove this type.
static const ClipboardFormatType& GetBitmapType();
static const ClipboardFormatType& GetWebCustomDataType();
diff --git a/chromium/ui/base/clipboard/clipboard_format_type_android.cc b/chromium/ui/base/clipboard/clipboard_format_type_android.cc
index 2e1b66e0fbb..ded6f0c1d1a 100644
--- a/chromium/ui/base/clipboard/clipboard_format_type_android.cc
+++ b/chromium/ui/base/clipboard/clipboard_format_type_android.cc
@@ -90,12 +90,17 @@ const ClipboardFormatType& ClipboardFormatType::GetRtfType() {
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetBitmapType() {
+const ClipboardFormatType& ClipboardFormatType::GetPngType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypePNG);
return *type;
}
// static
+const ClipboardFormatType& ClipboardFormatType::GetBitmapType() {
+ return ClipboardFormatType::GetPngType();
+}
+
+// static
const ClipboardFormatType& ClipboardFormatType::GetWebCustomDataType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypeWebCustomData);
return *type;
diff --git a/chromium/ui/base/clipboard/clipboard_format_type_aura.cc b/chromium/ui/base/clipboard/clipboard_format_type_aura.cc
index 0e182341f49..a47fd9ae246 100644
--- a/chromium/ui/base/clipboard/clipboard_format_type_aura.cc
+++ b/chromium/ui/base/clipboard/clipboard_format_type_aura.cc
@@ -86,12 +86,17 @@ const ClipboardFormatType& ClipboardFormatType::GetRtfType() {
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetBitmapType() {
+const ClipboardFormatType& ClipboardFormatType::GetPngType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypePNG);
return *type;
}
// static
+const ClipboardFormatType& ClipboardFormatType::GetBitmapType() {
+ return ClipboardFormatType::GetPngType();
+}
+
+// static
const ClipboardFormatType& ClipboardFormatType::GetWebKitSmartPasteType() {
static base::NoDestructor<ClipboardFormatType> type(
kMimeTypeWebkitSmartPaste);
diff --git a/chromium/ui/base/clipboard/clipboard_format_type_mac.mm b/chromium/ui/base/clipboard/clipboard_format_type_mac.mm
index c87c9bc4cb6..719582aa1da 100644
--- a/chromium/ui/base/clipboard/clipboard_format_type_mac.mm
+++ b/chromium/ui/base/clipboard/clipboard_format_type_mac.mm
@@ -99,6 +99,12 @@ const ClipboardFormatType& ClipboardFormatType::GetRtfType() {
}
// static
+const ClipboardFormatType& ClipboardFormatType::GetPngType() {
+ static base::NoDestructor<ClipboardFormatType> type(NSPasteboardTypePNG);
+ return *type;
+}
+
+// static
const ClipboardFormatType& ClipboardFormatType::GetBitmapType() {
static base::NoDestructor<ClipboardFormatType> type(NSTIFFPboardType);
return *type;
diff --git a/chromium/ui/base/clipboard/clipboard_format_type_win.cc b/chromium/ui/base/clipboard/clipboard_format_type_win.cc
index 74b273b4de1..8834346f7ae 100644
--- a/chromium/ui/base/clipboard/clipboard_format_type_win.cc
+++ b/chromium/ui/base/clipboard/clipboard_format_type_win.cc
@@ -212,8 +212,15 @@ const ClipboardFormatType& ClipboardFormatType::GetRtfType() {
}
// static
+const ClipboardFormatType& ClipboardFormatType::GetPngType() {
+ static base::NoDestructor<ClipboardFormatType> format(
+ ::RegisterClipboardFormat(L"PNG"));
+ return *format;
+}
+
+// static
const ClipboardFormatType& ClipboardFormatType::GetBitmapType() {
- static base::NoDestructor<ClipboardFormatType> format(CF_BITMAP);
+ static base::NoDestructor<ClipboardFormatType> format(CF_DIBV5);
return *format;
}
diff --git a/chromium/ui/base/clipboard/clipboard_mac.h b/chromium/ui/base/clipboard/clipboard_mac.h
index e517301e047..f45d165368a 100644
--- a/chromium/ui/base/clipboard/clipboard_mac.h
+++ b/chromium/ui/base/clipboard/clipboard_mac.h
@@ -62,6 +62,9 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardMac : public Clipboard {
void ReadRTF(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
std::string* result) const override;
+ void ReadPng(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ ReadPngCallback callback) const override;
void ReadImage(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadImageCallback callback) const override;
diff --git a/chromium/ui/base/clipboard/clipboard_mac.mm b/chromium/ui/base/clipboard/clipboard_mac.mm
index 5dedaf79e22..76b08ef78e5 100644
--- a/chromium/ui/base/clipboard/clipboard_mac.mm
+++ b/chromium/ui/base/clipboard/clipboard_mac.mm
@@ -17,6 +17,7 @@
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_nsobject.h"
#include "base/no_destructor.h"
+#include "base/notreached.h"
#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -279,6 +280,15 @@ void ClipboardMac::ReadRTF(ClipboardBuffer buffer,
// |data_dst| is not used. It's only passed to be consistent with other
// platforms.
+void ClipboardMac::ReadPng(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ ReadPngCallback callback) const {
+ // TODO(crbug.com/1201018): Implement this.
+ NOTIMPLEMENTED();
+}
+
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
void ClipboardMac::ReadImage(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadImageCallback callback) const {
diff --git a/chromium/ui/base/clipboard/clipboard_metrics.h b/chromium/ui/base/clipboard/clipboard_metrics.h
index 3683dd3e27d..044655a9be7 100644
--- a/chromium/ui/base/clipboard/clipboard_metrics.h
+++ b/chromium/ui/base/clipboard/clipboard_metrics.h
@@ -14,14 +14,15 @@ enum class ClipboardFormatMetric {
kText = 0, // On applicable platforms, includes both UNICODE and ANSI text.
kHtml = 1,
kRtf = 2,
- kImage = 3,
+ kImage = 3, // Bitmap data.
kBookmark = 4,
kData = 5,
kCustomData = 6,
kWebSmartPaste = 7, // Only used on write.
kSvg = 8,
kFilenames = 9,
- kMaxValue = kFilenames,
+ kPng = 10,
+ kMaxValue = kPng,
};
void RecordRead(ClipboardFormatMetric metric);
@@ -29,4 +30,4 @@ void RecordWrite(ClipboardFormatMetric metric);
} // namespace ui
-#endif // UI_BASE_CLIPBOARD_CLIPBOARD_MONITOR_H_
+#endif // UI_BASE_CLIPBOARD_CLIPBOARD_METRICS_H_
diff --git a/chromium/ui/base/clipboard/clipboard_monitor.cc b/chromium/ui/base/clipboard/clipboard_monitor.cc
index 9defbce91fb..493040618e2 100644
--- a/chromium/ui/base/clipboard/clipboard_monitor.cc
+++ b/chromium/ui/base/clipboard/clipboard_monitor.cc
@@ -5,7 +5,6 @@
#include "ui/base/clipboard/clipboard_monitor.h"
#include "build/chromeos_buildflags.h"
-#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/clipboard_observer.h"
namespace ui {
diff --git a/chromium/ui/base/clipboard/clipboard_non_backed.cc b/chromium/ui/base/clipboard/clipboard_non_backed.cc
index fcf249c6b32..3cacd71de81 100644
--- a/chromium/ui/base/clipboard/clipboard_non_backed.cc
+++ b/chromium/ui/base/clipboard/clipboard_non_backed.cc
@@ -183,7 +183,7 @@ class ClipboardInternal {
// Reads image from the ClipboardData.
SkBitmap ReadImage() const {
SkBitmap img;
- if (!HasFormat(ClipboardInternalFormat::kBitmap))
+ if (!HasFormat(ClipboardInternalFormat::kPng))
return img;
// A shallow copy should be fine here, but just to be safe...
@@ -435,9 +435,10 @@ bool ClipboardNonBacked::IsFormatAvailable(
if (format == ClipboardFormatType::GetRtfType())
return clipboard_internal_->IsFormatAvailable(
ClipboardInternalFormat::kRtf);
- if (format == ClipboardFormatType::GetBitmapType())
+ if (format == ClipboardFormatType::GetPngType() ||
+ format == ClipboardFormatType::GetBitmapType())
return clipboard_internal_->IsFormatAvailable(
- ClipboardInternalFormat::kBitmap);
+ ClipboardInternalFormat::kPng);
if (format == ClipboardFormatType::GetWebKitSmartPasteType())
return clipboard_internal_->IsFormatAvailable(
ClipboardInternalFormat::kWeb);
@@ -604,6 +605,14 @@ void ClipboardNonBacked::ReadRTF(ClipboardBuffer buffer,
#endif
}
+void ClipboardNonBacked::ReadPng(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ ReadPngCallback callback) const {
+ DCHECK(CalledOnValidThread());
+ // TODO(crbug.com/1201018): Implement this.
+ NOTIMPLEMENTED();
+}
+
void ClipboardNonBacked::ReadImage(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadImageCallback callback) const {
@@ -688,6 +697,7 @@ void ClipboardNonBacked::ReadData(const ClipboardFormatType& format,
#endif
}
+#if defined(USE_OZONE)
bool ClipboardNonBacked::IsSelectionBufferAvailable() const {
#if BUILDFLAG(IS_CHROMEOS_ASH)
return false;
@@ -695,6 +705,7 @@ bool ClipboardNonBacked::IsSelectionBufferAvailable() const {
return true;
#endif
}
+#endif // defined(USE_OZONE)
void ClipboardNonBacked::WritePortableRepresentations(
ClipboardBuffer buffer,
diff --git a/chromium/ui/base/clipboard/clipboard_non_backed.h b/chromium/ui/base/clipboard/clipboard_non_backed.h
index 6194d63d2ad..17403e75391 100644
--- a/chromium/ui/base/clipboard/clipboard_non_backed.h
+++ b/chromium/ui/base/clipboard/clipboard_non_backed.h
@@ -81,6 +81,9 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardNonBacked
void ReadRTF(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
std::string* result) const override;
+ void ReadPng(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ ReadPngCallback callback) const override;
void ReadImage(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadImageCallback callback) const override;
@@ -97,7 +100,9 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardNonBacked
void ReadData(const ClipboardFormatType& format,
const DataTransferEndpoint* data_dst,
std::string* result) const override;
+#if defined(USE_OZONE)
bool IsSelectionBufferAvailable() const override;
+#endif // defined(USE_OZONE)
void WritePortableRepresentations(
ClipboardBuffer buffer,
const ObjectMap& objects,
diff --git a/chromium/ui/base/clipboard/clipboard_ozone.cc b/chromium/ui/base/clipboard/clipboard_ozone.cc
index cc838a70a2f..12e3371b4ee 100644
--- a/chromium/ui/base/clipboard/clipboard_ozone.cc
+++ b/chromium/ui/base/clipboard/clipboard_ozone.cc
@@ -10,17 +10,17 @@
#include <vector>
#include "base/bind.h"
-#include "base/callback_forward.h"
#include "base/containers/contains.h"
#include "base/containers/flat_map.h"
#include "base/containers/span.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
+#include "base/notreached.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard_buffer.h"
#include "ui/base/clipboard/clipboard_constants.h"
@@ -72,8 +72,8 @@ class StubPlatformClipboard : public PlatformClipboard {
bool IsSelectionOwner(ClipboardBuffer buffer) override {
return is_owner_[buffer];
}
- void SetSequenceNumberUpdateCb(
- PlatformClipboard::SequenceNumberUpdateCb cb) override {}
+ void SetClipboardDataChangedCallback(
+ PlatformClipboard::ClipboardDataChangedCallback cb) override {}
bool IsSelectionBufferAvailable() const override { return false; }
private:
@@ -94,9 +94,9 @@ class ClipboardOzone::AsyncClipboardOzone {
// Set a callback to listen to requests to increase the clipboard sequence
// number.
auto update_sequence_cb =
- base::BindRepeating(&AsyncClipboardOzone::UpdateClipboardSequenceNumber,
+ base::BindRepeating(&AsyncClipboardOzone::OnClipboardDataChanged,
weak_factory_.GetWeakPtr());
- platform_clipboard_->SetSequenceNumberUpdateCb(
+ platform_clipboard_->SetClipboardDataChangedCallback(
std::move(update_sequence_cb));
}
@@ -108,6 +108,9 @@ class ClipboardOzone::AsyncClipboardOzone {
base::span<uint8_t> ReadClipboardDataAndWait(ClipboardBuffer buffer,
const std::string& mime_type) {
+ if (buffer == ClipboardBuffer::kSelection && !IsSelectionBufferAvailable())
+ return {};
+
// We can use a fastpath if we are the owner of the selection.
if (platform_clipboard_->IsSelectionOwner(buffer)) {
auto it = offered_data_[buffer].find(mime_type);
@@ -122,6 +125,9 @@ class ClipboardOzone::AsyncClipboardOzone {
}
std::vector<std::string> RequestMimeTypes(ClipboardBuffer buffer) {
+ if (buffer == ClipboardBuffer::kSelection && !IsSelectionBufferAvailable())
+ return {};
+
// We can use a fastpath if we are the owner of the selection.
if (platform_clipboard_->IsSelectionOwner(buffer)) {
std::vector<std::string> mime_types;
@@ -133,15 +139,19 @@ class ClipboardOzone::AsyncClipboardOzone {
return GetMimeTypes(buffer);
}
+ void PrepareForWriting() { data_to_offer_.clear(); }
+
void OfferData(ClipboardBuffer buffer) {
+ if (buffer == ClipboardBuffer::kSelection && !IsSelectionBufferAvailable())
+ return;
Offer(buffer, std::move(data_to_offer_));
- UpdateClipboardSequenceNumber(buffer);
}
void Clear(ClipboardBuffer buffer) {
+ if (buffer == ClipboardBuffer::kSelection && !IsSelectionBufferAvailable())
+ return;
data_to_offer_.clear();
OfferData(buffer);
- ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged();
}
void InsertData(std::vector<uint8_t> data,
@@ -152,11 +162,11 @@ class ClipboardOzone::AsyncClipboardOzone {
DCHECK_EQ(data_to_offer_.count(mime_type), 0U);
data_to_offer_[mime_type] = wrapped_data;
}
- ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged();
}
uint64_t GetSequenceNumber(ClipboardBuffer buffer) {
- return clipboard_sequence_number_[buffer];
+ return buffer == ClipboardBuffer::kCopyPaste ? clipboard_sequence_number_
+ : selection_sequence_number_;
}
private:
@@ -261,8 +271,19 @@ class ClipboardOzone::AsyncClipboardOzone {
request.TakeResultSync();
}
- void UpdateClipboardSequenceNumber(ClipboardBuffer buffer) {
- ++clipboard_sequence_number_[buffer];
+ void OnClipboardDataChanged(ClipboardBuffer buffer) {
+ DCHECK(buffer == ClipboardBuffer::kCopyPaste ||
+ platform_clipboard_->IsSelectionBufferAvailable());
+ if (buffer == ClipboardBuffer::kCopyPaste)
+ clipboard_sequence_number_++;
+ else
+ selection_sequence_number_++;
+ ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged();
+ }
+
+ bool IsBufferSupported(ClipboardBuffer buffer) const {
+ return buffer == ClipboardBuffer::kCopyPaste ||
+ platform_clipboard_->IsSelectionBufferAvailable();
}
// Clipboard data accumulated for writing.
@@ -275,7 +296,8 @@ class ClipboardOzone::AsyncClipboardOzone {
// Provides communication to a system clipboard under ozone level.
PlatformClipboard* const platform_clipboard_ = nullptr;
- base::flat_map<ClipboardBuffer, uint64_t> clipboard_sequence_number_;
+ uint64_t clipboard_sequence_number_ = 0;
+ uint64_t selection_sequence_number_ = 0;
base::WeakPtrFactory<AsyncClipboardOzone> weak_factory_;
@@ -443,6 +465,14 @@ void ClipboardOzone::ReadRTF(ClipboardBuffer buffer,
}
// TODO(crbug.com/1103194): |data_dst| should be supported.
+void ClipboardOzone::ReadPng(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ ReadPngCallback callback) const {
+ // TODO(crbug.com/1201018): Implement this.
+ NOTIMPLEMENTED();
+}
+
+// TODO(crbug.com/1103194): |data_dst| should be supported.
void ClipboardOzone::ReadImage(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadImageCallback callback) const {
@@ -508,22 +538,20 @@ void ClipboardOzone::WritePortableRepresentations(
std::unique_ptr<DataTransferEndpoint> data_src) {
DCHECK(CalledOnValidThread());
+ async_clipboard_ozone_->PrepareForWriting();
for (const auto& object : objects)
DispatchPortableRepresentation(object.first, object.second);
-
async_clipboard_ozone_->OfferData(buffer);
// Just like Non-Backed/X11 implementation does, copy text data from the
// copy/paste selection to the primary selection.
- if (buffer == ClipboardBuffer::kCopyPaste) {
+ if (buffer == ClipboardBuffer::kCopyPaste && IsSelectionBufferAvailable()) {
auto text_iter = objects.find(PortableFormat::kText);
- if (text_iter != objects.end()) {
- const ObjectMapParams& params_vector = text_iter->second;
- if (!params_vector.empty()) {
- const ObjectMapParam& char_vector = params_vector[0];
- if (!char_vector.empty())
- WriteText(&char_vector.front(), char_vector.size());
- }
+ if (text_iter != objects.end() && !text_iter->second.empty()) {
+ const auto& char_vector = text_iter->second[0];
+ async_clipboard_ozone_->PrepareForWriting();
+ if (!char_vector.empty())
+ WriteText(&char_vector.front(), char_vector.size());
async_clipboard_ozone_->OfferData(ClipboardBuffer::kSelection);
}
}
@@ -537,8 +565,9 @@ void ClipboardOzone::WritePlatformRepresentations(
std::vector<Clipboard::PlatformRepresentation> platform_representations,
std::unique_ptr<DataTransferEndpoint> data_src) {
DCHECK(CalledOnValidThread());
- DispatchPlatformRepresentations(std::move(platform_representations));
+ async_clipboard_ozone_->PrepareForWriting();
+ DispatchPlatformRepresentations(std::move(platform_representations));
async_clipboard_ozone_->OfferData(buffer);
data_src_[buffer] = std::move(data_src);
diff --git a/chromium/ui/base/clipboard/clipboard_ozone.h b/chromium/ui/base/clipboard/clipboard_ozone.h
index fda6985b219..730cf5d318c 100644
--- a/chromium/ui/base/clipboard/clipboard_ozone.h
+++ b/chromium/ui/base/clipboard/clipboard_ozone.h
@@ -55,6 +55,9 @@ class ClipboardOzone : public Clipboard {
void ReadRTF(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
std::string* result) const override;
+ void ReadPng(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ ReadPngCallback callback) const override;
void ReadImage(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadImageCallback callback) const override;
diff --git a/chromium/ui/base/clipboard/clipboard_test_template.h b/chromium/ui/base/clipboard/clipboard_test_template.h
index d8f709df759..e89e6263a52 100644
--- a/chromium/ui/base/clipboard/clipboard_test_template.h
+++ b/chromium/ui/base/clipboard/clipboard_test_template.h
@@ -63,7 +63,6 @@
using base::ASCIIToUTF16;
using base::UTF16ToUTF8;
-using base::UTF8ToUTF16;
using testing::Contains;
@@ -274,9 +273,9 @@ TYPED_TEST(ClipboardTest, RTFTest) {
}
#endif // !defined(OS_ANDROID)
-// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
-// of lacros-chrome is complete.
-#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
+// MultipleBufferTest only ran on Linux because Linux is the only platform that
+// supports the selection buffer by default.
+#if defined(OS_LINUX)
TYPED_TEST(ClipboardTest, MultipleBufferTest) {
if (!ui::Clipboard::IsSupportedClipboardBuffer(
ui::ClipboardBuffer::kSelection)) {
@@ -330,7 +329,7 @@ TYPED_TEST(ClipboardTest, MultipleBufferTest) {
EXPECT_EQ(markup,
markup_result.substr(fragment_end - markup.size(), markup.size()));
}
-#endif
+#endif // defined(OS_LINUX)
TYPED_TEST(ClipboardTest, TrickyHTMLTest) {
std::u16string markup(u"<em>Bye!<!--EndFragment --></em>"), markup_result;
@@ -366,8 +365,7 @@ TYPED_TEST(ClipboardTest, TrickyHTMLTest) {
// Some platforms store HTML as UTF-8 internally. Make sure fragment indices are
// adjusted appropriately when converting back to UTF-16.
TYPED_TEST(ClipboardTest, UnicodeHTMLTest) {
- std::u16string markup(UTF8ToUTF16("<div>A \xc3\xb8 \xe6\xb0\xb4</div>")),
- markup_result;
+ std::u16string markup(u"<div>A ø 水</div>"), markup_result;
std::string url, url_result;
{
@@ -443,7 +441,7 @@ TYPED_TEST(ClipboardTest, FilenamesTest) {
this->clipboard().ReadAvailableTypes(ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr, &types);
EXPECT_EQ(1u, types.size());
- EXPECT_EQ("text/uri-list", base::UTF16ToUTF8(types[0]));
+ EXPECT_EQ(u"text/uri-list", types[0]);
std::vector<ui::FileInfo> filenames;
this->clipboard().ReadFilenames(ClipboardBuffer::kCopyPaste,
@@ -708,6 +706,7 @@ TYPED_TEST(ClipboardTest, MultiplePickleTest) {
TYPED_TEST(ClipboardTest, DataTest) {
const std::string kFormatString = "chromium/x-test-format";
+ const std::u16string kFormatString16 = u"chromium/x-test-format";
const ClipboardFormatType kFormat =
ClipboardFormatType::GetType(kFormatString);
const std::string payload = "test string";
@@ -716,7 +715,7 @@ TYPED_TEST(ClipboardTest, DataTest) {
{
ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste);
- clipboard_writer.WriteData(UTF8ToUTF16(kFormatString),
+ clipboard_writer.WriteData(kFormatString16,
mojo_base::BigBuffer(payload_span));
}
@@ -736,6 +735,7 @@ TYPED_TEST(ClipboardTest, DataTest) {
!BUILDFLAG(IS_CHROMEOS_ASH)
TYPED_TEST(ClipboardTest, MultipleDataTest) {
const std::string kFormatString1 = "chromium/x-test-format1";
+ const std::u16string kFormatString116 = u"chromium/x-test-format1";
const ClipboardFormatType kFormat1 =
ClipboardFormatType::GetType(kFormatString1);
const std::string payload1("test string1");
@@ -743,6 +743,7 @@ TYPED_TEST(ClipboardTest, MultipleDataTest) {
reinterpret_cast<const uint8_t*>(payload1.data()), payload1.size());
const std::string kFormatString2 = "chromium/x-test-format2";
+ const std::u16string kFormatString216 = u"chromium/x-test-format2";
const ClipboardFormatType kFormat2 =
ClipboardFormatType::GetType(kFormatString2);
const std::string payload2("test string2");
@@ -752,16 +753,16 @@ TYPED_TEST(ClipboardTest, MultipleDataTest) {
{
ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste);
// Both payloads should write successfully and not overwrite one another.
- clipboard_writer.WriteData(UTF8ToUTF16(kFormatString1),
+ clipboard_writer.WriteData(kFormatString116,
mojo_base::BigBuffer(payload_span1));
- clipboard_writer.WriteData(UTF8ToUTF16(kFormatString2),
+ clipboard_writer.WriteData(kFormatString216,
mojo_base::BigBuffer(payload_span2));
}
// Check format 1.
EXPECT_THAT(this->clipboard().ReadAvailablePlatformSpecificFormatNames(
ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr),
- Contains(ASCIIToUTF16(kFormatString1)));
+ Contains(kFormatString116));
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
kFormat1, ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
std::string output1;
@@ -771,7 +772,7 @@ TYPED_TEST(ClipboardTest, MultipleDataTest) {
// Check format 2.
EXPECT_THAT(this->clipboard().ReadAvailablePlatformSpecificFormatNames(
ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr),
- Contains(ASCIIToUTF16(kFormatString2)));
+ Contains(kFormatString216));
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
kFormat2, ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
std::string output2;
@@ -904,9 +905,9 @@ TYPED_TEST(ClipboardTest, PlatformSpecificDataTest) {
TYPED_TEST(ClipboardTest, HyperlinkTest) {
const std::string kTitle("The <Example> Company's \"home page\"");
const std::string kUrl("http://www.example.com?x=3&lt=3#\"'<>");
- const std::u16string kExpectedHtml(UTF8ToUTF16(
- "<a href=\"http://www.example.com?x=3&amp;lt=3#&quot;&#39;&lt;&gt;\">"
- "The &lt;Example&gt; Company&#39;s &quot;home page&quot;</a>"));
+ const std::u16string kExpectedHtml(
+ u"<a href=\"http://www.example.com?x=3&amp;lt=3#&quot;&#39;&lt;&gt;\">"
+ u"The &lt;Example&gt; Company&#39;s &quot;home page&quot;</a>");
std::string url_result;
std::u16string html_result;
diff --git a/chromium/ui/base/clipboard/clipboard_win.cc b/chromium/ui/base/clipboard/clipboard_win.cc
index 751f40e1d79..868de231d10 100644
--- a/chromium/ui/base/clipboard/clipboard_win.cc
+++ b/chromium/ui/base/clipboard/clipboard_win.cc
@@ -42,6 +42,7 @@
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/base/ui_base_features.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/geometry/size.h"
#include "url/gurl.h"
@@ -213,13 +214,6 @@ void ParseBookmarkClipboardFormat(const std::u16string& bookmark,
}
}
-void FreeData(unsigned int format, HANDLE data) {
- if (format == CF_BITMAP)
- ::DeleteObject(static_cast<HBITMAP>(data));
- else
- ::GlobalFree(data);
-}
-
template <typename StringType>
void TrimAfterNull(StringType* result) {
// Text copied to the clipboard may explicitly contain null characters that
@@ -508,6 +502,15 @@ void ClipboardWin::ReadRTF(ClipboardBuffer buffer,
// |data_dst| is not used. It's only passed to be consistent with other
// platforms.
+void ClipboardWin::ReadPng(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ ReadPngCallback callback) const {
+ // TODO(crbug.com/1201018): Implement this.
+ NOTIMPLEMENTED();
+}
+
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
void ClipboardWin::ReadImage(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadImageCallback callback) const {
@@ -761,15 +764,26 @@ void ClipboardWin::WriteWebSmartPaste() {
}
void ClipboardWin::WriteBitmap(const SkBitmap& bitmap) {
- // This doesn't actually cost us a memcpy when the bitmap comes from the
- // renderer as we load it into the bitmap using setPixels which just sets a
- // pointer. Someone has to memcpy it into GDI, it might as well be us here.
- base::win::ScopedBitmap hbitmap = skia::CreateHBitmapFromN32SkBitmap(bitmap);
- if (hbitmap.is_valid()) {
- // Now we have an HBITMAP, we can write it to the clipboard
- WriteBitmapFromHandle(hbitmap.get(),
- gfx::Size(bitmap.width(), bitmap.height()));
+ CHECK_EQ(bitmap.colorType(), kN32_SkColorType);
+
+ // On Windows there are 2 ways of writing a transparent image to the
+ // clipboard: Using the DIBV5 format with correct header and format or using
+ // the PNG format. Some programs only support one or the other. In particular,
+ // Word support for DIBV5 is buggy and PNG format is needed for it. Writing
+ // order is also important as some programs will use the first compatible
+ // format that is available on the clipboard, and we want Word to choose the
+ // PNG format.
+
+ std::vector<unsigned char> png_encoded_bitmap;
+ if (gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, /*discard_transparency=*/false,
+ &png_encoded_bitmap)) {
+ HGLOBAL png_hglobal = skia::CreateHGlobalForByteArray(png_encoded_bitmap);
+ if (png_hglobal)
+ WriteToClipboard(ClipboardFormatType::GetPngType(), png_hglobal);
}
+ HGLOBAL dibv5_hglobal = skia::CreateDIBV5ImageDataFromN32SkBitmap(bitmap);
+ if (dibv5_hglobal)
+ WriteToClipboard(ClipboardFormatType::GetBitmapType(), dibv5_hglobal);
}
void ClipboardWin::WriteData(const ClipboardFormatType& format,
@@ -785,55 +799,6 @@ void ClipboardWin::WriteData(const ClipboardFormatType& format,
WriteToClipboard(format, hdata);
}
-void ClipboardWin::WriteBitmapFromHandle(HBITMAP source_hbitmap,
- const gfx::Size& size) {
- // We would like to just call ::SetClipboardData on the source_hbitmap,
- // but that bitmap might not be of a sort we can write to the clipboard.
- // For this reason, we create a new bitmap, copy the bits over, and then
- // write that to the clipboard.
-
- HDC dc = ::GetDC(nullptr);
- HDC compatible_dc = ::CreateCompatibleDC(nullptr);
- HDC source_dc = ::CreateCompatibleDC(nullptr);
-
- // This is the HBITMAP we will eventually write to the clipboard
- HBITMAP hbitmap = ::CreateCompatibleBitmap(dc, size.width(), size.height());
- if (!hbitmap) {
- // Failed to create the bitmap
- ::DeleteDC(compatible_dc);
- ::DeleteDC(source_dc);
- ::ReleaseDC(nullptr, dc);
- return;
- }
-
- HBITMAP old_hbitmap = (HBITMAP)SelectObject(compatible_dc, hbitmap);
- HBITMAP old_source = (HBITMAP)SelectObject(source_dc, source_hbitmap);
-
- // Now we need to blend it into an HBITMAP we can place on the clipboard
- BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
- ::GdiAlphaBlend(compatible_dc,
- 0,
- 0,
- size.width(),
- size.height(),
- source_dc,
- 0,
- 0,
- size.width(),
- size.height(),
- bf);
-
- // Clean up all the handles we just opened
- ::SelectObject(compatible_dc, old_hbitmap);
- ::SelectObject(source_dc, old_source);
- ::DeleteObject(old_hbitmap);
- ::DeleteObject(old_source);
- ::DeleteDC(compatible_dc);
- ::DeleteDC(source_dc);
- ::ReleaseDC(nullptr, dc);
-
- WriteToClipboard(ClipboardFormatType::GetBitmapType(), hbitmap);
-}
SkBitmap ClipboardWin::ReadImageInternal(ClipboardBuffer buffer) const {
DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
@@ -928,7 +893,7 @@ void ClipboardWin::WriteToClipboard(ClipboardFormatType format, HANDLE handle) {
if (handle && !::SetClipboardData(cf_format, handle)) {
DCHECK_NE(GetLastError(),
static_cast<unsigned long>(ERROR_CLIPBOARD_NOT_OPEN));
- FreeData(cf_format, handle);
+ ::GlobalFree(handle);
}
}
diff --git a/chromium/ui/base/clipboard/clipboard_win.h b/chromium/ui/base/clipboard/clipboard_win.h
index e5d613250c0..33b6abca99d 100644
--- a/chromium/ui/base/clipboard/clipboard_win.h
+++ b/chromium/ui/base/clipboard/clipboard_win.h
@@ -20,10 +20,6 @@ class MessageWindow;
}
}
-namespace gfx {
-class Size;
-}
-
namespace ui {
class ClipboardWin : public Clipboard {
@@ -65,6 +61,9 @@ class ClipboardWin : public Clipboard {
void ReadRTF(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
std::string* result) const override;
+ void ReadPng(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ ReadPngCallback callback) const override;
void ReadImage(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadImageCallback callback) const override;
@@ -106,10 +105,10 @@ class ClipboardWin : public Clipboard {
void WriteData(const ClipboardFormatType& format,
const char* data_data,
size_t data_len) override;
- void WriteBitmapFromHandle(HBITMAP source_hbitmap, const gfx::Size& size);
SkBitmap ReadImageInternal(ClipboardBuffer buffer) const;
// Safely write to system clipboard. Free |handle| on failure.
+ // This function takes ownership of the given handle's memory.
void WriteToClipboard(ClipboardFormatType format, HANDLE handle);
// Return the window that should be the clipboard owner, creating it
diff --git a/chromium/ui/base/clipboard/clipboard_x11.cc b/chromium/ui/base/clipboard/clipboard_x11.cc
index 3c83fe820b7..2807d6e8ddc 100644
--- a/chromium/ui/base/clipboard/clipboard_x11.cc
+++ b/chromium/ui/base/clipboard/clipboard_x11.cc
@@ -14,6 +14,7 @@
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/notreached.h"
#include "base/strings/utf_string_conversions.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard_buffer.h"
@@ -207,6 +208,15 @@ void ClipboardX11::ReadRTF(ClipboardBuffer buffer,
// |data_dst| is not used. It's only passed to be consistent with other
// platforms.
+void ClipboardX11::ReadPng(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ ReadPngCallback callback) const {
+ // TODO(crbug.com/1201018): Implement this.
+ NOTIMPLEMENTED();
+}
+
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
void ClipboardX11::ReadImage(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadImageCallback callback) const {
diff --git a/chromium/ui/base/clipboard/clipboard_x11.h b/chromium/ui/base/clipboard/clipboard_x11.h
index 286c15e4560..88a5ed96273 100644
--- a/chromium/ui/base/clipboard/clipboard_x11.h
+++ b/chromium/ui/base/clipboard/clipboard_x11.h
@@ -55,6 +55,9 @@ class ClipboardX11 : public Clipboard {
void ReadRTF(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
std::string* result) const override;
+ void ReadPng(ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst,
+ ReadPngCallback callback) const override;
void ReadImage(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadImageCallback callback) const override;
diff --git a/chromium/ui/base/clipboard/custom_data_helper.h b/chromium/ui/base/clipboard/custom_data_helper.h
index c2fc581234e..b31b3e4a7da 100644
--- a/chromium/ui/base/clipboard/custom_data_helper.h
+++ b/chromium/ui/base/clipboard/custom_data_helper.h
@@ -52,4 +52,4 @@ void WriteCustomDataToPickle(
} // namespace ui
-#endif // UI_BASE_CLIPBOARD_CLIPBOARD_H_
+#endif // UI_BASE_CLIPBOARD_CUSTOM_DATA_HELPER_H_
diff --git a/chromium/ui/base/clipboard/file_info_unittest.cc b/chromium/ui/base/clipboard/file_info_unittest.cc
index fa17e4a3d8d..998b6e624da 100644
--- a/chromium/ui/base/clipboard/file_info_unittest.cc
+++ b/chromium/ui/base/clipboard/file_info_unittest.cc
@@ -20,7 +20,7 @@ TEST(FileInfoTest, Roundtrip) {
struct TestCase {
std::string uri_list;
std::vector<base::FilePath::StringType> paths;
- base::Optional<std::string> uri_list_roundtrip;
+ absl::optional<std::string> uri_list_roundtrip;
};
const TestCase tests[] = {
// Empty text/uri-list should give empty list.
@@ -82,7 +82,7 @@ TEST(FileInfoTest, Backslashes) {
struct TestCase {
base::FilePath::StringType path;
std::string uri_list;
- base::Optional<base::FilePath::StringType> path_roundtrip;
+ absl::optional<base::FilePath::StringType> path_roundtrip;
};
const TestCase tests[] = {
#if defined(OS_WIN)
diff --git a/chromium/ui/base/clipboard/scoped_clipboard_writer.h b/chromium/ui/base/clipboard/scoped_clipboard_writer.h
index dfe6fbab6bf..4d5122026dd 100644
--- a/chromium/ui/base/clipboard/scoped_clipboard_writer.h
+++ b/chromium/ui/base/clipboard/scoped_clipboard_writer.h
@@ -104,7 +104,7 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter {
// The source of the data written in ScopedClipboardWriter, nullptr means it's
// not set, or the source of the data can't be represented by
// DataTransferEndpoint.
- std::unique_ptr<DataTransferEndpoint> data_src_ = nullptr;
+ std::unique_ptr<DataTransferEndpoint> data_src_;
DISALLOW_COPY_AND_ASSIGN(ScopedClipboardWriter);
};
diff --git a/chromium/ui/base/cocoa/DIR_METADATA b/chromium/ui/base/cocoa/DIR_METADATA
deleted file mode 100644
index 2769d07edc7..00000000000
--- a/chromium/ui/base/cocoa/DIR_METADATA
+++ /dev/null
@@ -1,11 +0,0 @@
-# Metadata information for this directory.
-#
-# For more information on DIR_METADATA files, see:
-# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
-#
-# For the schema of this file, see Metadata message:
-# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
-
-monorail {
- component: "UI"
-} \ No newline at end of file
diff --git a/chromium/ui/base/cocoa/animation_utils.h b/chromium/ui/base/cocoa/animation_utils.h
index 89e8fff8e02..2e08ce609c8 100644
--- a/chromium/ui/base/cocoa/animation_utils.h
+++ b/chromium/ui/base/cocoa/animation_utils.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_BASE_COCOA_ANIMATION_UTILS_H
-#define UI_BASE_COCOA_ANIMATION_UTILS_H
+#ifndef UI_BASE_COCOA_ANIMATION_UTILS_H_
+#define UI_BASE_COCOA_ANIMATION_UTILS_H_
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
@@ -59,4 +59,4 @@ class ScopedCAActionSetDuration {
}
};
-#endif // UI_BASE_COCOA_ANIMATION_UTILS_H
+#endif // UI_BASE_COCOA_ANIMATION_UTILS_H_
diff --git a/chromium/ui/base/cocoa/appkit_utils.h b/chromium/ui/base/cocoa/appkit_utils.h
index a3b46d13329..6d28aeedba4 100644
--- a/chromium/ui/base/cocoa/appkit_utils.h
+++ b/chromium/ui/base/cocoa/appkit_utils.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_BASE_COCOA_APPKIT_UTILS_H
-#define UI_BASE_COCOA_APPKIT_UTILS_H
+#ifndef UI_BASE_COCOA_APPKIT_UTILS_H_
+#define UI_BASE_COCOA_APPKIT_UTILS_H_
#import <Cocoa/Cocoa.h>
@@ -19,4 +19,4 @@ COMPONENT_EXPORT(UI_BASE) bool IsCGFloatEqual(CGFloat a, CGFloat b);
} // namespace ui
-#endif // UI_BASE_COCOA_APPKIT_UTILS_H
+#endif // UI_BASE_COCOA_APPKIT_UTILS_H_
diff --git a/chromium/ui/base/cocoa/defaults_utils.h b/chromium/ui/base/cocoa/defaults_utils.h
index 7845045d5c4..0c2e078c3c0 100644
--- a/chromium/ui/base/cocoa/defaults_utils.h
+++ b/chromium/ui/base/cocoa/defaults_utils.h
@@ -16,4 +16,4 @@ COMPONENT_EXPORT(UI_BASE)
bool TextInsertionCaretBlinkPeriod(base::TimeDelta* period);
}
-#endif
+#endif // UI_BASE_COCOA_DEFAULTS_UTILS_H_
diff --git a/chromium/ui/base/cocoa/focus_window_set.h b/chromium/ui/base/cocoa/focus_window_set.h
deleted file mode 100644
index 820195f6978..00000000000
--- a/chromium/ui/base/cocoa/focus_window_set.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_BASE_COCOA_FOCUS_WINDOW_SET_H_
-#define UI_BASE_COCOA_FOCUS_WINDOW_SET_H_
-
-#include <set>
-
-#include "base/component_export.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace ui {
-
-// Brings a group of windows to the front without changing their order, and
-// makes the frontmost one key and main. If none are visible, the frontmost
-// miniaturized window is deminiaturized.
-COMPONENT_EXPORT(UI_BASE)
-void FocusWindowSet(const std::set<gfx::NativeWindow>& windows);
-
-// Brings a group of windows to the front without changing their
-// order, and makes the frontmost one key and main. If none are
-// visible, the frontmost miniaturized window is deminiaturized. This
-// variant is meant to clean up after the system-default Dock icon
-// behavior. Unlike FocusWindowSet, only windows on the current space
-// are considered. It also ignores the hidden state of windows; the
-// window system may be in the middle of unhiding the application.
-COMPONENT_EXPORT(UI_BASE)
-void FocusWindowSetOnCurrentSpace(const std::set<gfx::NativeWindow>& windows);
-
-} // namespace ui
-
-#endif // UI_BASE_COCOA_FOCUS_WINDOW_SET_H_
diff --git a/chromium/ui/base/cocoa/focus_window_set.mm b/chromium/ui/base/cocoa/focus_window_set.mm
deleted file mode 100644
index 06e7223ded8..00000000000
--- a/chromium/ui/base/cocoa/focus_window_set.mm
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/check.h"
-#include "ui/base/cocoa/focus_window_set.h"
-
-namespace ui {
-
-namespace {
-
-// This attempts to match OS X's native behavior, namely that a window
-// is only ever deminiaturized if ALL windows on ALL workspaces are
-// miniaturized.
-void FocusWindowSetHelper(const std::set<gfx::NativeWindow>& windows,
- bool allow_workspace_switch,
- bool visible_windows_only) {
- NSArray* ordered_windows = [NSApp orderedWindows];
- NSWindow* frontmost_window = nil;
- NSWindow* frontmost_window_all_spaces = nil;
- NSWindow* frontmost_miniaturized_window = nil;
- bool all_miniaturized = true;
- for (int i = [ordered_windows count] - 1; i >= 0; i--) {
- NSWindow* win = ordered_windows[i];
- if (windows.find(win) == windows.end())
- continue;
- if ([win isMiniaturized]) {
- frontmost_miniaturized_window = win;
- } else if (!visible_windows_only || [win isVisible]) {
- all_miniaturized = false;
- frontmost_window_all_spaces = win;
- if ([win isOnActiveSpace]) {
- // Raise the old |frontmost_window| (if any). The topmost |win| will be
- // raised with makeKeyAndOrderFront: below.
- [frontmost_window orderFront:nil];
- frontmost_window = win;
- }
- }
- }
- if (all_miniaturized && frontmost_miniaturized_window) {
- DCHECK(!frontmost_window);
- // Note the call to makeKeyAndOrderFront: will deminiaturize the window.
- frontmost_window = frontmost_miniaturized_window;
- }
- // If we couldn't find one on the active space, consider all spaces.
- if (allow_workspace_switch && !frontmost_window)
- frontmost_window = frontmost_window_all_spaces;
-
- if (frontmost_window) {
- [frontmost_window makeKeyAndOrderFront:nil];
- [NSApp activateIgnoringOtherApps:YES];
- }
-}
-
-} // namespace
-
-void FocusWindowSet(const std::set<gfx::NativeWindow>& windows) {
- FocusWindowSetHelper(windows, true, true);
-}
-
-void FocusWindowSetOnCurrentSpace(const std::set<gfx::NativeWindow>& windows) {
- // This callback runs before AppKit picks its own window to
- // deminiaturize, so we get to pick one from the right set. Limit to
- // the windows on the current workspace. Otherwise we jump spaces
- // haphazardly.
- //
- // Also consider both visible and hidden windows; this call races
- // with the system unhiding the application. http://crbug.com/368238
- //
- // NOTE: If this is called in the
- // applicationShouldHandleReopen:hasVisibleWindows: hook when
- // clicking the dock icon, and that caused OS X to begin switch
- // spaces, isOnActiveSpace gives the answer for the PREVIOUS
- // space. This means that we actually raise and focus the wrong
- // space's windows, leaving the new key window off-screen. To detect
- // this, check if the key window is on the active space prior to
- // calling.
- //
- // Also, if we decide to deminiaturize a window during a space switch,
- // that can switch spaces and then switch back. Fortunately, this only
- // happens if, say, space 1 contains an app, space 2 contains a
- // miniaturized browser. We click the icon, OS X switches to space 1,
- // we deminiaturize the browser, and that triggers switching back.
- //
- // TODO(davidben): To limit those cases, consider preferentially
- // deminiaturizing a window on the current space.
- FocusWindowSetHelper(windows, false, false);
-}
-
-} // namespace ui
diff --git a/chromium/ui/base/cocoa/menu_controller.h b/chromium/ui/base/cocoa/menu_controller.h
index ace28e03577..5a42c79cc5a 100644
--- a/chromium/ui/base/cocoa/menu_controller.h
+++ b/chromium/ui/base/cocoa/menu_controller.h
@@ -7,7 +7,6 @@
#import <Cocoa/Cocoa.h>
-#include <string>
#include "base/component_export.h"
#include "base/mac/scoped_nsobject.h"
diff --git a/chromium/ui/base/cocoa/secure_password_input.mm b/chromium/ui/base/cocoa/secure_password_input.mm
index c9d003216ec..b3283a4c85e 100644
--- a/chromium/ui/base/cocoa/secure_password_input.mm
+++ b/chromium/ui/base/cocoa/secure_password_input.mm
@@ -41,7 +41,7 @@ void SetPasswordInputEnabled(bool enabled) {
namespace ui {
ScopedPasswordInputEnabler::ScopedPasswordInputEnabler() {
- if (!g_password_input_counter) {
+ if (!g_password_input_counter && !IsSecureEventInputEnabled()) {
SetPasswordInputEnabled(true);
}
++g_password_input_counter;
diff --git a/chromium/ui/base/cocoa/touch_bar_util.h b/chromium/ui/base/cocoa/touch_bar_util.h
index 19293c6f93a..965f50cc119 100644
--- a/chromium/ui/base/cocoa/touch_bar_util.h
+++ b/chromium/ui/base/cocoa/touch_bar_util.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_BASE_COCOA_TOUCH_BAR_UTIL_H
-#define UI_BASE_COCOA_TOUCH_BAR_UTIL_H
+#ifndef UI_BASE_COCOA_TOUCH_BAR_UTIL_H_
+#define UI_BASE_COCOA_TOUCH_BAR_UTIL_H_
#import <Cocoa/Cocoa.h>
#include <os/availability.h>
@@ -40,4 +40,4 @@ NSString* GetTouchBarItemId(NSString* touch_bar_id, NSString* item_id);
} // namespace ui
-#endif // UI_BASE_COCOA_TOUCH_BAR_UTIL_H
+#endif // UI_BASE_COCOA_TOUCH_BAR_UTIL_H_
diff --git a/chromium/ui/base/cursor/BUILD.gn b/chromium/ui/base/cursor/BUILD.gn
index 23ebb70fbf3..53672acdf46 100644
--- a/chromium/ui/base/cursor/BUILD.gn
+++ b/chromium/ui/base/cursor/BUILD.gn
@@ -14,6 +14,7 @@ component("cursor_base") {
"cursor_factory.cc",
"cursor_factory.h",
"cursor_size.h",
+ "platform_cursor.h",
]
defines = [ "IS_UI_BASE_CURSOR_BASE_IMPL" ]
public_deps = [
@@ -23,10 +24,6 @@ component("cursor_base") {
"//ui/gfx/geometry",
]
deps = [ "//ui/gfx:geometry_skia" ]
-
- if (use_aura) {
- sources += [ "cursor_aura.cc" ]
- }
}
component("theme_manager") {
diff --git a/chromium/ui/base/cursor/cursor.cc b/chromium/ui/base/cursor/cursor.cc
index 6b19377f80c..cdeb19d6eff 100644
--- a/chromium/ui/base/cursor/cursor.cc
+++ b/chromium/ui/base/cursor/cursor.cc
@@ -13,39 +13,14 @@ Cursor::Cursor() = default;
Cursor::Cursor(mojom::CursorType type) : type_(type) {}
-Cursor::Cursor(const Cursor& cursor)
- : type_(cursor.type_),
- platform_cursor_(cursor.platform_cursor_),
- image_scale_factor_(cursor.image_scale_factor_) {
- if (type_ == mojom::CursorType::kCustom) {
- custom_hotspot_ = cursor.custom_hotspot_;
- custom_bitmap_ = cursor.custom_bitmap_;
- RefCustomCursor();
- }
-}
+Cursor::Cursor(const Cursor& cursor) = default;
-Cursor::~Cursor() {
- if (type_ == mojom::CursorType::kCustom)
- UnrefCustomCursor();
-}
+Cursor::~Cursor() = default;
-void Cursor::SetPlatformCursor(const PlatformCursor& platform) {
- if (type_ == mojom::CursorType::kCustom)
- UnrefCustomCursor();
- platform_cursor_ = platform;
- if (type_ == mojom::CursorType::kCustom)
- RefCustomCursor();
+void Cursor::SetPlatformCursor(scoped_refptr<PlatformCursor> platform_cursor) {
+ platform_cursor_ = platform_cursor;
}
-#if !defined(USE_AURA)
-void Cursor::RefCustomCursor() {
- NOTIMPLEMENTED();
-}
-void Cursor::UnrefCustomCursor() {
- NOTIMPLEMENTED();
-}
-#endif
-
bool Cursor::operator==(const Cursor& cursor) const {
return type_ == cursor.type_ && platform_cursor_ == cursor.platform_cursor_ &&
image_scale_factor_ == cursor.image_scale_factor_ &&
@@ -54,19 +29,4 @@ bool Cursor::operator==(const Cursor& cursor) const {
gfx::BitmapsAreEqual(custom_bitmap_, cursor.custom_bitmap_)));
}
-void Cursor::operator=(const Cursor& cursor) {
- if (*this == cursor)
- return;
- if (type_ == mojom::CursorType::kCustom)
- UnrefCustomCursor();
- type_ = cursor.type_;
- platform_cursor_ = cursor.platform_cursor_;
- if (type_ == mojom::CursorType::kCustom) {
- RefCustomCursor();
- custom_hotspot_ = cursor.custom_hotspot_;
- custom_bitmap_ = cursor.custom_bitmap_;
- }
- image_scale_factor_ = cursor.image_scale_factor_;
-}
-
} // namespace ui
diff --git a/chromium/ui/base/cursor/cursor.h b/chromium/ui/base/cursor/cursor.h
index e5ffd67ffa3..b73cec8a9c6 100644
--- a/chromium/ui/base/cursor/cursor.h
+++ b/chromium/ui/base/cursor/cursor.h
@@ -6,42 +6,26 @@
#define UI_BASE_CURSOR_CURSOR_H_
#include "base/component_export.h"
-#include "build/build_config.h"
+#include "base/memory/scoped_refptr.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/gfx/geometry/point.h"
-#if defined(OS_WIN)
-#include "base/win/windows_types.h"
-#endif
-
namespace ui {
-// NOTE: On Ozone platforms, the type is chosen at runtime, and is either
-// X11Cursor* or BitmapCursorOzone*.
-// On Windows, it's WinCursor*.
-using PlatformCursor = void*;
-
// Ref-counted cursor that supports both default and custom cursors.
class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) Cursor {
public:
Cursor();
-
- // Implicit constructor.
Cursor(mojom::CursorType type);
-
- // Allow copy.
Cursor(const Cursor& cursor);
-
~Cursor();
- void SetPlatformCursor(const PlatformCursor& platform);
-
- void RefCustomCursor();
- void UnrefCustomCursor();
+ void SetPlatformCursor(scoped_refptr<PlatformCursor> platform_cursor);
mojom::CursorType type() const { return type_; }
- PlatformCursor platform() const { return platform_cursor_; }
+ scoped_refptr<PlatformCursor> platform() const { return platform_cursor_; }
float image_scale_factor() const { return image_scale_factor_; }
void set_image_scale_factor(float scale) { image_scale_factor_ = scale; }
@@ -60,14 +44,12 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) Cursor {
bool operator==(mojom::CursorType type) const { return type_ == type; }
bool operator!=(mojom::CursorType type) const { return type_ != type; }
- void operator=(const Cursor& cursor);
-
private:
// The basic cursor type.
mojom::CursorType type_ = mojom::CursorType::kNull;
// The native platform cursor.
- PlatformCursor platform_cursor_ = 0;
+ scoped_refptr<PlatformCursor> platform_cursor_;
// The scale factor for the cursor bitmap.
float image_scale_factor_ = 1.0f;
diff --git a/chromium/ui/base/cursor/cursor_aura.cc b/chromium/ui/base/cursor/cursor_aura.cc
deleted file mode 100644
index b41f4ca3b67..00000000000
--- a/chromium/ui/base/cursor/cursor_aura.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/base/cursor/cursor.h"
-
-#include "ui/base/cursor/cursor_factory.h"
-
-namespace ui {
-
-void Cursor::RefCustomCursor() {
- if (platform_cursor_)
- CursorFactory::GetInstance()->RefImageCursor(platform_cursor_);
-}
-
-void Cursor::UnrefCustomCursor() {
- if (platform_cursor_)
- CursorFactory::GetInstance()->UnrefImageCursor(platform_cursor_);
-}
-
-} // namespace ui
diff --git a/chromium/ui/base/cursor/cursor_factory.cc b/chromium/ui/base/cursor/cursor_factory.cc
index 3d757428531..1b727571dfd 100644
--- a/chromium/ui/base/cursor/cursor_factory.cc
+++ b/chromium/ui/base/cursor/cursor_factory.cc
@@ -8,8 +8,10 @@
#include "base/check.h"
#include "base/check_op.h"
+#include "base/memory/scoped_refptr.h"
#include "base/notreached.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
+#include "ui/base/cursor/platform_cursor.h"
namespace ui {
@@ -19,6 +21,8 @@ CursorFactory* g_instance = nullptr;
} // namespace
+CursorFactoryObserver::~CursorFactoryObserver() = default;
+
CursorFactory::CursorFactory() {
DCHECK(!g_instance) << "There should only be a single CursorFactory.";
g_instance = this;
@@ -34,33 +38,40 @@ CursorFactory* CursorFactory::GetInstance() {
return g_instance;
}
-PlatformCursor CursorFactory::GetDefaultCursor(mojom::CursorType type) {
+void CursorFactory::AddObserver(CursorFactoryObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void CursorFactory::RemoveObserver(CursorFactoryObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void CursorFactory::NotifyObserversOnThemeLoaded() {
+ for (auto& observer : observers_)
+ observer.OnThemeLoaded();
+}
+
+scoped_refptr<PlatformCursor> CursorFactory::GetDefaultCursor(
+ mojom::CursorType type) {
NOTIMPLEMENTED();
return nullptr;
}
-PlatformCursor CursorFactory::CreateImageCursor(mojom::CursorType type,
- const SkBitmap& bitmap,
- const gfx::Point& hotspot) {
+scoped_refptr<PlatformCursor> CursorFactory::CreateImageCursor(
+ mojom::CursorType type,
+ const SkBitmap& bitmap,
+ const gfx::Point& hotspot) {
NOTIMPLEMENTED();
- return 0;
+ return nullptr;
}
-PlatformCursor CursorFactory::CreateAnimatedCursor(
+scoped_refptr<PlatformCursor> CursorFactory::CreateAnimatedCursor(
mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot,
base::TimeDelta frame_delay) {
NOTIMPLEMENTED();
- return 0;
-}
-
-void CursorFactory::RefImageCursor(PlatformCursor cursor) {
- NOTIMPLEMENTED();
-}
-
-void CursorFactory::UnrefImageCursor(PlatformCursor cursor) {
- NOTIMPLEMENTED();
+ return nullptr;
}
void CursorFactory::ObserveThemeChanges() {
diff --git a/chromium/ui/base/cursor/cursor_factory.h b/chromium/ui/base/cursor/cursor_factory.h
index a4b25f9f56c..1423293daba 100644
--- a/chromium/ui/base/cursor/cursor_factory.h
+++ b/chromium/ui/base/cursor/cursor_factory.h
@@ -9,11 +9,15 @@
#include <vector>
#include "base/component_export.h"
+#include "base/observer_list.h"
#include "build/build_config.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
class SkBitmap;
+template <class T>
+class scoped_refptr;
+
namespace base {
class TimeDelta;
}
@@ -23,7 +27,15 @@ class Point;
}
namespace ui {
-using PlatformCursor = void*;
+class PlatformCursor;
+
+class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) CursorFactoryObserver {
+ public:
+ // Called by the factory after it has loaded the cursor theme.
+ virtual void OnThemeLoaded() = 0;
+
+ virtual ~CursorFactoryObserver();
+};
class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) CursorFactory {
public:
@@ -33,37 +45,30 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) CursorFactory {
// Returns the thread-local instance.
static CursorFactory* GetInstance();
- // Return the default cursor of the specified type. The types are listed in
- // ui/base/cursor/cursor.h. Default cursors are managed by the implementation
- // and must live indefinitely; there's no way to know when to free them.
- // When a default cursor is not available, nullptr is returned.
- virtual PlatformCursor GetDefaultCursor(mojom::CursorType type);
-
- // Return an image cursor for the specified |type| with a |bitmap| and
- // |hotspot|. Image cursors are referenced counted and have an initial
- // refcount of 1. Therefore, each CreateImageCursor call must be matched with
- // a call to UnrefImageCursor.
- virtual PlatformCursor CreateImageCursor(mojom::CursorType type,
- const SkBitmap& bitmap,
- const gfx::Point& hotspot);
-
- // Return a animated cursor from the specified image & hotspot. Animated
- // cursors are referenced counted and have an initial refcount of 1.
- // Therefore, each CreateAnimatedCursor call must be matched with a call to
- // UnrefImageCursor.
- // |frame_delay| is the delay between frames.
- virtual PlatformCursor CreateAnimatedCursor(
+ void AddObserver(CursorFactoryObserver* observer);
+ void RemoveObserver(CursorFactoryObserver* observer);
+ void NotifyObserversOnThemeLoaded();
+
+ // Return the default cursor of the specified type. When a default cursor is
+ // not available, nullptr is returned.
+ virtual scoped_refptr<PlatformCursor> GetDefaultCursor(
+ mojom::CursorType type);
+
+ // Return an image cursor for the specified `type` with a `bitmap` and
+ // `hotspot`.
+ virtual scoped_refptr<PlatformCursor> CreateImageCursor(
+ mojom::CursorType type,
+ const SkBitmap& bitmap,
+ const gfx::Point& hotspot);
+
+ // Return a animated cursor from the specified `bitmaps` and `hotspot`.
+ // `frame_delay` is the delay between frames.
+ virtual scoped_refptr<PlatformCursor> CreateAnimatedCursor(
mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot,
base::TimeDelta frame_delay);
- // Increment platform image cursor refcount.
- virtual void RefImageCursor(PlatformCursor cursor);
-
- // Decrement platform image cursor refcount.
- virtual void UnrefImageCursor(PlatformCursor cursor);
-
// Called after CursorThemeManager is initialized, to be able to track
// cursor theme and size changes.
virtual void ObserveThemeChanges();
@@ -71,6 +76,9 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) CursorFactory {
// Sets the device scale factor that CursorFactory may use when creating
// cursors.
virtual void SetDeviceScaleFactor(float scale);
+
+ private:
+ base::ObserverList<CursorFactoryObserver>::Unchecked observers_;
};
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
diff --git a/chromium/ui/base/cursor/cursor_loader.cc b/chromium/ui/base/cursor/cursor_loader.cc
index cdd82eb8a21..7529e8e9a58 100644
--- a/chromium/ui/base/cursor/cursor_loader.cc
+++ b/chromium/ui/base/cursor/cursor_loader.cc
@@ -8,6 +8,7 @@
#include <vector>
#include "base/check.h"
+#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/cursor_factory.h"
@@ -15,6 +16,7 @@
#include "ui/base/cursor/cursor_util.h"
#include "ui/base/cursor/cursors_aura.h"
#include "ui/base/cursor/mojom/cursor_type.mojom.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/gfx/geometry/point.h"
namespace ui {
@@ -31,15 +33,20 @@ constexpr base::TimeDelta kAnimatedCursorFrameDelay =
CursorLoader::CursorLoader(bool use_platform_cursors)
: use_platform_cursors_(use_platform_cursors),
- factory_(CursorFactory::GetInstance()) {}
+ factory_(CursorFactory::GetInstance()) {
+ factory_->AddObserver(this);
+}
CursorLoader::~CursorLoader() {
+ factory_->RemoveObserver(this);
+ UnloadCursors();
+}
+
+void CursorLoader::OnThemeLoaded() {
UnloadCursors();
}
void CursorLoader::UnloadCursors() {
- for (const auto& image_cursor : image_cursors_)
- factory_->UnrefImageCursor(image_cursor.second);
image_cursors_.clear();
}
@@ -91,7 +98,8 @@ void CursorLoader::LoadImageCursor(mojom::CursorType type,
}
}
-PlatformCursor CursorLoader::CursorFromType(mojom::CursorType type) {
+scoped_refptr<PlatformCursor> CursorLoader::CursorFromType(
+ mojom::CursorType type) {
// An image cursor is loaded for this type.
if (image_cursors_.count(type))
return image_cursors_[type];
@@ -99,7 +107,7 @@ PlatformCursor CursorLoader::CursorFromType(mojom::CursorType type) {
// Check if there's a default platform cursor available.
// For the none cursor, we also need to use the platform factory to take
// into account the different ways of creating an invisible cursor.
- PlatformCursor cursor;
+ scoped_refptr<PlatformCursor> cursor;
if (use_platform_cursors_ || type == mojom::CursorType::kNone) {
cursor = factory_->GetDefaultCursor(type);
if (cursor)
@@ -112,14 +120,14 @@ PlatformCursor CursorLoader::CursorFromType(mojom::CursorType type) {
cursor = LoadCursorFromAsset(type);
if (!cursor && type != mojom::CursorType::kPointer) {
cursor = CursorFromType(mojom::CursorType::kPointer);
- factory_->RefImageCursor(cursor);
image_cursors_[type] = cursor;
}
DCHECK(cursor) << "Failed to load a bitmap for the pointer cursor.";
return cursor;
}
-PlatformCursor CursorLoader::LoadCursorFromAsset(mojom::CursorType type) {
+scoped_refptr<PlatformCursor> CursorLoader::LoadCursorFromAsset(
+ mojom::CursorType type) {
int resource_id;
gfx::Point hotspot;
if (GetCursorDataFor(size(), type, scale(), &resource_id, &hotspot)) {
diff --git a/chromium/ui/base/cursor/cursor_loader.h b/chromium/ui/base/cursor/cursor_loader.h
index 767758e1619..39e0320eccf 100644
--- a/chromium/ui/base/cursor/cursor_loader.h
+++ b/chromium/ui/base/cursor/cursor_loader.h
@@ -9,7 +9,9 @@
#include <memory>
#include "base/component_export.h"
+#include "base/memory/scoped_refptr.h"
#include "ui/base/cursor/cursor.h"
+#include "ui/base/cursor/cursor_factory.h"
#include "ui/base/cursor/cursor_size.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
#include "ui/display/display.h"
@@ -19,14 +21,18 @@ class Point;
}
namespace ui {
-class CursorFactory;
+class PlatformCursor;
-class COMPONENT_EXPORT(UI_BASE_CURSOR) CursorLoader {
+class COMPONENT_EXPORT(UI_BASE_CURSOR) CursorLoader
+ : public CursorFactoryObserver {
public:
explicit CursorLoader(bool use_platform_cursors = true);
CursorLoader(const CursorLoader&) = delete;
CursorLoader& operator=(const CursorLoader&) = delete;
- ~CursorLoader();
+ ~CursorLoader() override;
+
+ // CursorFactoryObserver:
+ void OnThemeLoaded() override;
// Returns the rotation and scale of the currently loaded cursor.
display::Display::Rotation rotation() const { return rotation_; }
@@ -51,15 +57,15 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) CursorLoader {
void LoadImageCursor(mojom::CursorType id,
int resource_id,
const gfx::Point& hot);
- PlatformCursor CursorFromType(mojom::CursorType type);
- PlatformCursor LoadCursorFromAsset(mojom::CursorType type);
+ scoped_refptr<PlatformCursor> CursorFromType(mojom::CursorType type);
+ scoped_refptr<PlatformCursor> LoadCursorFromAsset(mojom::CursorType type);
// Whether to use cursors provided by the underlying platform (e.g. X11
// cursors). If false or in the case of a failure, Chromium assets will be
// used instead.
const bool use_platform_cursors_;
- std::map<mojom::CursorType, PlatformCursor> image_cursors_;
+ std::map<mojom::CursorType, scoped_refptr<PlatformCursor>> image_cursors_;
CursorFactory* factory_ = nullptr;
// The current scale of the mouse cursor icon.
diff --git a/chromium/ui/base/cursor/cursor_loader_unittest.cc b/chromium/ui/base/cursor/cursor_loader_unittest.cc
index c50a3f2c53f..dcccc48508e 100644
--- a/chromium/ui/base/cursor/cursor_loader_unittest.cc
+++ b/chromium/ui/base/cursor/cursor_loader_unittest.cc
@@ -4,10 +4,12 @@
#include "ui/base/cursor/cursor_loader.h"
+#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
+#include "ui/base/cursor/platform_cursor.h"
#if defined(OS_WIN)
#include "ui/base/cursor/win/win_cursor.h"
@@ -25,12 +27,13 @@
#endif
namespace ui {
-
namespace {
-PlatformCursor LoadInvisibleCursor() {
+using mojom::CursorType;
+
+scoped_refptr<PlatformCursor> LoadInvisibleCursor() {
CursorLoader cursor_loader;
- Cursor cursor(mojom::CursorType::kNone);
+ Cursor cursor(CursorType::kNone);
cursor_loader.SetPlatformCursor(&cursor);
return cursor.platform();
}
@@ -40,19 +43,20 @@ PlatformCursor LoadInvisibleCursor() {
#if defined(OS_WIN)
TEST(CursorLoaderTest, InvisibleCursor) {
WinCursorFactory cursor_factory;
- auto* invisible_cursor = static_cast<WinCursor*>(LoadInvisibleCursor());
+ auto invisible_cursor = LoadInvisibleCursor();
ASSERT_NE(invisible_cursor, nullptr);
- EXPECT_EQ(invisible_cursor->hcursor(), nullptr);
+ EXPECT_EQ(WinCursor::FromPlatformCursor(invisible_cursor)->hcursor(),
+ nullptr);
}
#endif
#if defined(USE_OZONE) && !defined(USE_X11)
TEST(CursorLoaderTest, InvisibleCursor) {
BitmapCursorFactoryOzone cursor_factory;
- auto* invisible_cursor =
- static_cast<BitmapCursorOzone*>(LoadInvisibleCursor());
+ auto invisible_cursor = LoadInvisibleCursor();
ASSERT_NE(invisible_cursor, nullptr);
- EXPECT_EQ(invisible_cursor->type(), mojom::CursorType::kNone);
+ EXPECT_EQ(BitmapCursorOzone::FromPlatformCursor(invisible_cursor)->type(),
+ CursorType::kNone);
}
#endif
@@ -61,13 +65,10 @@ TEST(CursorLoaderTest, InvisibleCursor) {
X11CursorFactory cursor_factory;
// Building an image cursor with an invalid SkBitmap should return the
// invisible cursor in X11.
- auto* invisible_cursor =
+ auto invisible_cursor =
cursor_factory.CreateImageCursor({}, SkBitmap(), gfx::Point());
ASSERT_NE(invisible_cursor, nullptr);
EXPECT_EQ(invisible_cursor, LoadInvisibleCursor());
-
- // Release our refcount on the cursor
- cursor_factory.UnrefImageCursor(invisible_cursor);
}
#endif
diff --git a/chromium/ui/base/cursor/cursors_aura.cc b/chromium/ui/base/cursor/cursors_aura.cc
index 2a63023f112..3633161ec32 100644
--- a/chromium/ui/base/cursor/cursors_aura.cc
+++ b/chromium/ui/base/cursor/cursors_aura.cc
@@ -333,7 +333,7 @@ SkBitmap GetDefaultBitmap(const Cursor& cursor) {
CursorLoader cursor_loader;
cursor_loader.SetPlatformCursor(&cursor_copy);
return IconUtil::CreateSkBitmapFromHICON(
- static_cast<WinCursor*>(cursor_copy.platform())->hcursor());
+ WinCursor::FromPlatformCursor(cursor_copy.platform())->hcursor());
#else
int resource_id;
gfx::Point hotspot;
@@ -354,7 +354,7 @@ gfx::Point GetDefaultHotspot(const Cursor& cursor) {
CursorLoader cursor_loader;
cursor_loader.SetPlatformCursor(&cursor_copy);
return IconUtil::GetHotSpotFromHICON(
- static_cast<WinCursor*>(cursor_copy.platform())->hcursor());
+ WinCursor::FromPlatformCursor(cursor_copy.platform())->hcursor());
#else
int resource_id;
gfx::Point hotspot;
diff --git a/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc b/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc
index 189a61bd851..2f3d4bb0190 100644
--- a/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc
+++ b/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc
@@ -85,16 +85,15 @@ bool UseDefaultCursorForType(mojom::CursorType type) {
}
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
-BitmapCursorOzone* ToBitmapCursorOzone(PlatformCursor cursor) {
- return static_cast<BitmapCursorOzone*>(cursor);
-}
+} // namespace
-PlatformCursor ToPlatformCursor(BitmapCursorOzone* cursor) {
- return static_cast<PlatformCursor>(cursor);
+// static
+scoped_refptr<BitmapCursorOzone> BitmapCursorOzone::FromPlatformCursor(
+ scoped_refptr<PlatformCursor> platform_cursor) {
+ return base::WrapRefCounted(
+ static_cast<BitmapCursorOzone*>(platform_cursor.get()));
}
-} // namespace
-
BitmapCursorOzone::BitmapCursorOzone(mojom::CursorType type) : type_(type) {}
BitmapCursorOzone::BitmapCursorOzone(mojom::CursorType type,
@@ -148,13 +147,7 @@ BitmapCursorFactoryOzone::BitmapCursorFactoryOzone() {}
BitmapCursorFactoryOzone::~BitmapCursorFactoryOzone() {}
-// static
-scoped_refptr<BitmapCursorOzone> BitmapCursorFactoryOzone::GetBitmapCursor(
- PlatformCursor platform_cursor) {
- return base::WrapRefCounted(ToBitmapCursorOzone(platform_cursor));
-}
-
-PlatformCursor BitmapCursorFactoryOzone::GetDefaultCursor(
+scoped_refptr<PlatformCursor> BitmapCursorFactoryOzone::GetDefaultCursor(
mojom::CursorType type) {
if (!default_cursors_.count(type)) {
if (type == mojom::CursorType::kNone
@@ -171,37 +164,24 @@ PlatformCursor BitmapCursorFactoryOzone::GetDefaultCursor(
}
}
- // Returns owned default cursor for this type.
- return default_cursors_[type].get();
+ return default_cursors_[type];
}
-PlatformCursor BitmapCursorFactoryOzone::CreateImageCursor(
+scoped_refptr<PlatformCursor> BitmapCursorFactoryOzone::CreateImageCursor(
mojom::CursorType type,
const SkBitmap& bitmap,
const gfx::Point& hotspot) {
- BitmapCursorOzone* cursor = new BitmapCursorOzone(type, bitmap, hotspot);
- cursor->AddRef(); // Balanced by UnrefImageCursor.
- return ToPlatformCursor(cursor);
+ return base::MakeRefCounted<BitmapCursorOzone>(type, bitmap, hotspot);
}
-PlatformCursor BitmapCursorFactoryOzone::CreateAnimatedCursor(
+scoped_refptr<PlatformCursor> BitmapCursorFactoryOzone::CreateAnimatedCursor(
mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot,
base::TimeDelta frame_delay) {
DCHECK_LT(0U, bitmaps.size());
- auto cursor = base::MakeRefCounted<BitmapCursorOzone>(type, bitmaps, hotspot,
- frame_delay);
- cursor->AddRef(); // Balanced by UnrefImageCursor.
- return ToPlatformCursor(cursor.get());
-}
-
-void BitmapCursorFactoryOzone::RefImageCursor(PlatformCursor cursor) {
- ToBitmapCursorOzone(cursor)->AddRef();
-}
-
-void BitmapCursorFactoryOzone::UnrefImageCursor(PlatformCursor cursor) {
- ToBitmapCursorOzone(cursor)->Release();
+ return base::MakeRefCounted<BitmapCursorOzone>(type, bitmaps, hotspot,
+ frame_delay);
}
} // namespace ui
diff --git a/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h b/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h
index e59398136b0..b217791adc0 100644
--- a/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h
+++ b/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h
@@ -10,21 +10,24 @@
#include "base/component_export.h"
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/cursor_factory.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/gfx/geometry/point.h"
namespace ui {
// A cursor that is an SkBitmap combined with a gfx::Point hotspot.
class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorOzone
- : public base::RefCounted<BitmapCursorOzone> {
+ : public PlatformCursor {
public:
+ static scoped_refptr<BitmapCursorOzone> FromPlatformCursor(
+ scoped_refptr<PlatformCursor> platform_cursor);
+
// Creates a cursor that doesn't need backing bitmaps (for example, a
// server-side cursor for Lacros).
explicit BitmapCursorOzone(mojom::CursorType type);
@@ -55,8 +58,8 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorOzone
void* platform_data() { return platform_data_; }
private:
- friend class base::RefCounted<BitmapCursorOzone>;
- ~BitmapCursorOzone();
+ friend class base::RefCounted<PlatformCursor>;
+ ~BitmapCursorOzone() override;
const mojom::CursorType type_;
std::vector<SkBitmap> bitmaps_;
@@ -80,21 +83,18 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorFactoryOzone
BitmapCursorFactoryOzone();
~BitmapCursorFactoryOzone() override;
- // Convert PlatformCursor to BitmapCursorOzone.
- static scoped_refptr<BitmapCursorOzone> GetBitmapCursor(
- PlatformCursor platform_cursor);
-
// CursorFactory:
- PlatformCursor GetDefaultCursor(mojom::CursorType type) override;
- PlatformCursor CreateImageCursor(mojom::CursorType type,
- const SkBitmap& bitmap,
- const gfx::Point& hotspot) override;
- PlatformCursor CreateAnimatedCursor(mojom::CursorType type,
- const std::vector<SkBitmap>& bitmaps,
- const gfx::Point& hotspot,
- base::TimeDelta frame_delay) override;
- void RefImageCursor(PlatformCursor cursor) override;
- void UnrefImageCursor(PlatformCursor cursor) override;
+ scoped_refptr<PlatformCursor> GetDefaultCursor(
+ mojom::CursorType type) override;
+ scoped_refptr<PlatformCursor> CreateImageCursor(
+ mojom::CursorType type,
+ const SkBitmap& bitmap,
+ const gfx::Point& hotspot) override;
+ scoped_refptr<PlatformCursor> CreateAnimatedCursor(
+ mojom::CursorType type,
+ const std::vector<SkBitmap>& bitmaps,
+ const gfx::Point& hotspot,
+ base::TimeDelta frame_delay) override;
private:
std::map<mojom::CursorType, scoped_refptr<BitmapCursorOzone>>
diff --git a/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone_unittest.cc b/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone_unittest.cc
index 21e2984c3d7..8a190ecdc65 100644
--- a/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone_unittest.cc
+++ b/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone_unittest.cc
@@ -6,8 +6,8 @@
#include "build/chromeos_buildflags.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
+#include "ui/base/cursor/platform_cursor.h"
namespace ui {
@@ -16,11 +16,12 @@ using mojom::CursorType;
TEST(BitmapCursorFactoryOzoneTest, InvisibleCursor) {
BitmapCursorFactoryOzone cursor_factory;
- PlatformCursor cursor = cursor_factory.GetDefaultCursor(CursorType::kNone);
+ auto cursor = cursor_factory.GetDefaultCursor(CursorType::kNone);
// The invisible cursor should be a BitmapCursorOzone of type kNone, not
// nullptr.
ASSERT_NE(cursor, nullptr);
- EXPECT_EQ(static_cast<BitmapCursorOzone*>(cursor)->type(), CursorType::kNone);
+ EXPECT_EQ(BitmapCursorOzone::FromPlatformCursor(cursor)->type(),
+ CursorType::kNone);
}
#if BUILDFLAG(IS_CHROMEOS_LACROS)
@@ -28,24 +29,25 @@ TEST(BitmapCursorFactoryOzoneTest, LacrosUsesDefaultCursorsForCommonTypes) {
BitmapCursorFactoryOzone factory;
// Verify some common cursor types.
- PlatformCursor cursor = factory.GetDefaultCursor(CursorType::kPointer);
+ auto cursor = factory.GetDefaultCursor(CursorType::kPointer);
EXPECT_NE(cursor, nullptr);
- EXPECT_EQ(static_cast<BitmapCursorOzone*>(cursor)->type(),
+ EXPECT_EQ(BitmapCursorOzone::FromPlatformCursor(cursor)->type(),
CursorType::kPointer);
cursor = factory.GetDefaultCursor(CursorType::kHand);
EXPECT_NE(cursor, nullptr);
- EXPECT_EQ(static_cast<BitmapCursorOzone*>(cursor)->type(), CursorType::kHand);
+ EXPECT_EQ(BitmapCursorOzone::FromPlatformCursor(cursor)->type(),
+ CursorType::kHand);
cursor = factory.GetDefaultCursor(CursorType::kIBeam);
EXPECT_NE(cursor, nullptr);
- EXPECT_EQ(static_cast<BitmapCursorOzone*>(cursor)->type(),
+ EXPECT_EQ(BitmapCursorOzone::FromPlatformCursor(cursor)->type(),
CursorType::kIBeam);
}
TEST(BitmapCursorFactoryOzoneTest, LacrosCustomCursor) {
BitmapCursorFactoryOzone factory;
- PlatformCursor cursor = factory.GetDefaultCursor(CursorType::kCustom);
+ auto cursor = factory.GetDefaultCursor(CursorType::kCustom);
// Custom cursors don't have a default platform cursor.
EXPECT_EQ(cursor, nullptr);
}
diff --git a/chromium/ui/base/cursor/platform_cursor.h b/chromium/ui/base/cursor/platform_cursor.h
new file mode 100644
index 00000000000..6a547096c65
--- /dev/null
+++ b/chromium/ui/base/cursor/platform_cursor.h
@@ -0,0 +1,36 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_CURSOR_PLATFORM_CURSOR_H_
+#define UI_BASE_CURSOR_PLATFORM_CURSOR_H_
+
+#include "base/component_export.h"
+#include "base/memory/ref_counted.h"
+
+namespace ui {
+
+// Ref-counted base class for platform-specific cursors.
+//
+// Sub-classes of PlatformCursor are expected to wrap platform-specific cursor
+// resources (e.g. HCURSOR on Windows). Those resources also have
+// platform-specific deletion methods that must only be called once the last
+// cursor is destroyed, thus requiring a ref-counted type.
+// While default cursors (all other than kCustom in
+// ui/base/cursor/cursor_type.mojom) are used often during any Chrome session
+// and could perhaps be kept alive for the duration of the program, custom
+// cursors might incur in high memory usage. Because of this, all types of
+// cursors are expected to be ref-counted.
+class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) PlatformCursor
+ : public base::RefCounted<PlatformCursor> {
+ public:
+ REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
+
+ protected:
+ friend class base::RefCounted<PlatformCursor>;
+ virtual ~PlatformCursor() = default;
+};
+
+} // namespace ui
+
+#endif // UI_BASE_CURSOR_PLATFORM_CURSOR_H_
diff --git a/chromium/ui/base/cursor/win/win_cursor.cc b/chromium/ui/base/cursor/win/win_cursor.cc
index afa707faffd..c37c3527b8b 100644
--- a/chromium/ui/base/cursor/win/win_cursor.cc
+++ b/chromium/ui/base/cursor/win/win_cursor.cc
@@ -6,14 +6,24 @@
#include <windows.h>
+#include "base/memory/scoped_refptr.h"
+
namespace ui {
-WinCursor::WinCursor(HCURSOR hcursor) {
- hcursor_ = hcursor;
+// static
+scoped_refptr<WinCursor> WinCursor::FromPlatformCursor(
+ scoped_refptr<PlatformCursor> platform_cursor) {
+ return base::WrapRefCounted(static_cast<WinCursor*>(platform_cursor.get()));
}
+WinCursor::WinCursor(HCURSOR hcursor, bool should_destroy)
+ : should_destroy_(should_destroy), hcursor_(hcursor) {}
+
WinCursor::~WinCursor() {
- DestroyIcon(hcursor_);
+ // DestroyIcon shouldn't be used to destroy a shared icon:
+ // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-destroyicon#remarks
+ if (should_destroy_)
+ DestroyIcon(hcursor_);
}
} // namespace ui
diff --git a/chromium/ui/base/cursor/win/win_cursor.h b/chromium/ui/base/cursor/win/win_cursor.h
index e1f787f7710..8acd1062afb 100644
--- a/chromium/ui/base/cursor/win/win_cursor.h
+++ b/chromium/ui/base/cursor/win/win_cursor.h
@@ -6,17 +6,22 @@
#define UI_BASE_CURSOR_WIN_WIN_CURSOR_H_
#include "base/component_export.h"
-#include "base/memory/ref_counted.h"
#include "base/win/windows_types.h"
+#include "ui/base/cursor/platform_cursor.h"
+
+template <class T>
+class scoped_refptr;
namespace ui {
-// Ref counted class to hold a Windows cursor, i.e. an HCURSOR. Clears the
+// Ref counted class to hold a Windows cursor, i.e. an HCURSOR. Clears the
// resources on destruction.
-class COMPONENT_EXPORT(UI_BASE_CURSOR) WinCursor
- : public base::RefCounted<WinCursor> {
+class COMPONENT_EXPORT(UI_BASE_CURSOR) WinCursor : public PlatformCursor {
public:
- explicit WinCursor(HCURSOR hcursor = nullptr);
+ static scoped_refptr<WinCursor> FromPlatformCursor(
+ scoped_refptr<PlatformCursor> platform_cursor);
+
+ explicit WinCursor(HCURSOR hcursor = nullptr, bool should_destroy = false);
WinCursor(const WinCursor&) = delete;
WinCursor& operator=(const WinCursor&) = delete;
@@ -24,9 +29,10 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) WinCursor
private:
friend class base::RefCounted<WinCursor>;
+ ~WinCursor() override;
- ~WinCursor();
-
+ // Release the cursor on deletion. To be used by custom image cursors.
+ bool should_destroy_;
HCURSOR hcursor_;
};
diff --git a/chromium/ui/base/cursor/win/win_cursor_factory.cc b/chromium/ui/base/cursor/win/win_cursor_factory.cc
index abe5223eabb..fb53c731ab2 100644
--- a/chromium/ui/base/cursor/win/win_cursor_factory.cc
+++ b/chromium/ui/base/cursor/win/win_cursor_factory.cc
@@ -12,8 +12,8 @@
#include "base/notreached.h"
#include "base/win/scoped_gdi_object.h"
#include "base/win/windows_types.h"
-#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/resource/resource_bundle_win.h"
#include "ui/gfx/icon_util.h"
#include "ui/resources/grit/ui_unscaled_resources.h"
@@ -21,14 +21,6 @@
namespace ui {
namespace {
-WinCursor* ToWinCursor(PlatformCursor cursor) {
- return static_cast<WinCursor*>(cursor);
-}
-
-PlatformCursor ToPlatformCursor(WinCursor* cursor) {
- return static_cast<PlatformCursor>(cursor);
-}
-
const wchar_t* GetCursorId(mojom::CursorType type) {
switch (type) {
case mojom::CursorType::kNull:
@@ -135,7 +127,8 @@ WinCursorFactory::WinCursorFactory() = default;
WinCursorFactory::~WinCursorFactory() = default;
-PlatformCursor WinCursorFactory::GetDefaultCursor(mojom::CursorType type) {
+scoped_refptr<PlatformCursor> WinCursorFactory::GetDefaultCursor(
+ mojom::CursorType type) {
if (!default_cursors_.count(type)) {
// Using a dark 1x1 bit bmp for the kNone cursor may still cause DWM to do
// composition work unnecessarily. Better to totally remove it from the
@@ -153,25 +146,16 @@ PlatformCursor WinCursorFactory::GetDefaultCursor(mojom::CursorType type) {
default_cursors_[type] = base::MakeRefCounted<WinCursor>(hcursor);
}
- auto cursor = default_cursors_[type];
- return ToPlatformCursor(cursor.get());
-}
-
-PlatformCursor WinCursorFactory::CreateImageCursor(mojom::CursorType type,
- const SkBitmap& bitmap,
- const gfx::Point& hotspot) {
- auto cursor = base::MakeRefCounted<WinCursor>(
- IconUtil::CreateCursorFromSkBitmap(bitmap, hotspot).release());
- cursor->AddRef();
- return ToPlatformCursor(cursor.get());
-}
-
-void WinCursorFactory::RefImageCursor(PlatformCursor cursor) {
- ToWinCursor(cursor)->AddRef();
+ return default_cursors_[type];
}
-void WinCursorFactory::UnrefImageCursor(PlatformCursor cursor) {
- ToWinCursor(cursor)->Release();
+scoped_refptr<PlatformCursor> WinCursorFactory::CreateImageCursor(
+ mojom::CursorType type,
+ const SkBitmap& bitmap,
+ const gfx::Point& hotspot) {
+ return base::MakeRefCounted<WinCursor>(
+ IconUtil::CreateCursorFromSkBitmap(bitmap, hotspot).release(),
+ /*should_destroy=*/true);
}
} // namespace ui
diff --git a/chromium/ui/base/cursor/win/win_cursor_factory.h b/chromium/ui/base/cursor/win/win_cursor_factory.h
index ff8534532cd..9a684359850 100644
--- a/chromium/ui/base/cursor/win/win_cursor_factory.h
+++ b/chromium/ui/base/cursor/win/win_cursor_factory.h
@@ -29,12 +29,12 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) WinCursorFactory : public CursorFactory {
~WinCursorFactory() override;
// CursorFactory:
- PlatformCursor GetDefaultCursor(mojom::CursorType type) override;
- PlatformCursor CreateImageCursor(mojom::CursorType type,
- const SkBitmap& bitmap,
- const gfx::Point& hotspot) override;
- void RefImageCursor(PlatformCursor cursor) override;
- void UnrefImageCursor(PlatformCursor cursor) override;
+ scoped_refptr<PlatformCursor> GetDefaultCursor(
+ mojom::CursorType type) override;
+ scoped_refptr<PlatformCursor> CreateImageCursor(
+ mojom::CursorType type,
+ const SkBitmap& bitmap,
+ const gfx::Point& hotspot) override;
private:
std::map<mojom::CursorType, scoped_refptr<WinCursor>> default_cursors_;
diff --git a/chromium/ui/base/data_transfer_policy/OWNERS b/chromium/ui/base/data_transfer_policy/OWNERS
index 11249b99d52..ed5b6d0a1dd 100644
--- a/chromium/ui/base/data_transfer_policy/OWNERS
+++ b/chromium/ui/base/data_transfer_policy/OWNERS
@@ -2,4 +2,4 @@
ayaelattar@chromium.org
# Secondary:
-huangdarwin@chromium.org \ No newline at end of file
+huangdarwin@chromium.org
diff --git a/chromium/ui/base/data_transfer_policy/data_transfer_endpoint.cc b/chromium/ui/base/data_transfer_policy/data_transfer_endpoint.cc
index 5f12aca7450..3d8c18e69e3 100644
--- a/chromium/ui/base/data_transfer_policy/data_transfer_endpoint.cc
+++ b/chromium/ui/base/data_transfer_policy/data_transfer_endpoint.cc
@@ -5,7 +5,7 @@
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "base/check_op.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
namespace ui {
@@ -19,7 +19,7 @@ DataTransferEndpoint::DataTransferEndpoint(const url::Origin& origin,
DataTransferEndpoint::DataTransferEndpoint(EndpointType type,
bool notify_if_restricted)
: type_(type),
- origin_(base::nullopt),
+ origin_(absl::nullopt),
notify_if_restricted_(notify_if_restricted) {
DCHECK_NE(type, EndpointType::kUrl);
}
diff --git a/chromium/ui/base/data_transfer_policy/data_transfer_endpoint.h b/chromium/ui/base/data_transfer_policy/data_transfer_endpoint.h
index d3a9d2f3c85..a79c8c68f8a 100644
--- a/chromium/ui/base/data_transfer_policy/data_transfer_endpoint.h
+++ b/chromium/ui/base/data_transfer_policy/data_transfer_endpoint.h
@@ -5,9 +5,9 @@
#ifndef UI_BASE_DATA_TRANSFER_POLICY_DATA_TRANSFER_ENDPOINT_H_
#define UI_BASE_DATA_TRANSFER_POLICY_DATA_TRANSFER_ENDPOINT_H_
-#include "base/optional.h"
#include "base/stl_util.h"
#include "build/chromeos_buildflags.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
namespace ui {
@@ -77,7 +77,7 @@ class COMPONENT_EXPORT(UI_BASE_DATA_TRANSFER_POLICY) DataTransferEndpoint {
EndpointType type_;
// The url::Origin of the data endpoint. It always has a value if `type_` ==
// EndpointType::kUrl, otherwise it's empty.
- base::Optional<url::Origin> origin_;
+ absl::optional<url::Origin> origin_;
// This variable should be set to true, if paste is initiated by the user.
// Otherwise it should be set to false, so the user won't see a notification
// when the data is restricted by the rules of data leak prevention policy
diff --git a/chromium/ui/base/dragdrop/BUILD.gn b/chromium/ui/base/dragdrop/BUILD.gn
index 82c9295dbcd..9c7c90b1456 100644
--- a/chromium/ui/base/dragdrop/BUILD.gn
+++ b/chromium/ui/base/dragdrop/BUILD.gn
@@ -9,7 +9,10 @@ component("types") {
"drag_drop_types.h",
]
defines = [ "IS_UI_BASE_DRAGDROP_TYPES_IMPL" ]
- public_deps = [ "//base" ]
+ public_deps = [
+ "//base",
+ "//ui/base/dragdrop/mojom:mojom_headers",
+ ]
deps = [ "//ui/base/dragdrop/mojom" ]
if (is_mac) {
diff --git a/chromium/ui/base/dragdrop/cocoa_dnd_util.h b/chromium/ui/base/dragdrop/cocoa_dnd_util.h
index 52c3b7b210c..876297770b9 100644
--- a/chromium/ui/base/dragdrop/cocoa_dnd_util.h
+++ b/chromium/ui/base/dragdrop/cocoa_dnd_util.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_BASE_DRAGDROP_MAC_DND_UTIL_H_
-#define UI_BASE_DRAGDROP_MAC_DND_UTIL_H_
+#ifndef UI_BASE_DRAGDROP_COCOA_DND_UTIL_H_
+#define UI_BASE_DRAGDROP_COCOA_DND_UTIL_H_
#import <Cocoa/Cocoa.h>
@@ -42,4 +42,4 @@ BOOL PopulateURLAndTitleFromPasteboard(GURL* url,
} // namespace ui
-#endif // UI_BASE_DRAGDROP_MAC_DND_UTIL_H_
+#endif // UI_BASE_DRAGDROP_COCOA_DND_UTIL_H_
diff --git a/chromium/ui/base/dragdrop/drag_drop_types.cc b/chromium/ui/base/dragdrop/drag_drop_types.cc
index 96ea4c33e2f..693316ad61b 100644
--- a/chromium/ui/base/dragdrop/drag_drop_types.cc
+++ b/chromium/ui/base/dragdrop/drag_drop_types.cc
@@ -20,4 +20,14 @@ STATIC_ASSERT_ENUM(DragDropTypes::DRAG_COPY, DragOperation::kCopy);
STATIC_ASSERT_ENUM(DragDropTypes::DRAG_LINK, DragOperation::kLink);
STATIC_ASSERT_ENUM(DragDropTypes::DRAG_MOVE, DragOperation::kMove);
+DragOperation PreferredDragOperation(int operations) {
+ if (operations & DragDropTypes::DRAG_COPY)
+ return DragOperation::kCopy;
+ if (operations & DragDropTypes::DRAG_MOVE)
+ return DragOperation::kMove;
+ if (operations & DragDropTypes::DRAG_LINK)
+ return DragOperation::kLink;
+ return DragOperation::kNone;
+}
+
} // namespace ui
diff --git a/chromium/ui/base/dragdrop/drag_drop_types.h b/chromium/ui/base/dragdrop/drag_drop_types.h
index 8f7fbbaccc4..e84d5468848 100644
--- a/chromium/ui/base/dragdrop/drag_drop_types.h
+++ b/chromium/ui/base/dragdrop/drag_drop_types.h
@@ -9,6 +9,7 @@
#include "base/component_export.h"
#include "build/build_config.h"
+#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h"
namespace ui {
@@ -36,6 +37,9 @@ class COMPONENT_EXPORT(UI_BASE_DRAGDROP_TYPES) DragDropTypes {
#endif
};
+COMPONENT_EXPORT(UI_BASE_DRAGDROP_TYPES)
+ui::mojom::DragOperation PreferredDragOperation(int operations);
+
} // namespace ui
#endif // UI_BASE_DRAGDROP_DRAG_DROP_TYPES_H_
diff --git a/chromium/ui/base/dragdrop/os_exchange_data.cc b/chromium/ui/base/dragdrop/os_exchange_data.cc
index 30d06ec5b14..6f066b8e4d1 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data.cc
+++ b/chromium/ui/base/dragdrop/os_exchange_data.cc
@@ -91,6 +91,10 @@ bool OSExchangeData::HasFile() const {
return provider_->HasFile();
}
+bool OSExchangeData::HasFileContents() const {
+ return provider_->HasFileContents();
+}
+
bool OSExchangeData::HasCustomFormat(const ClipboardFormatType& format) const {
return provider_->HasCustomFormat(format);
}
@@ -102,10 +106,8 @@ bool OSExchangeData::HasAnyFormat(
return true;
if ((formats & URL) != 0 && HasURL(FilenameToURLPolicy::CONVERT_FILENAMES))
return true;
-#if defined(OS_WIN)
if ((formats & FILE_CONTENTS) != 0 && provider_->HasFileContents())
return true;
-#endif
#if defined(USE_AURA)
if ((formats & HTML) != 0 && provider_->HasHtml())
return true;
@@ -119,7 +121,6 @@ bool OSExchangeData::HasAnyFormat(
return false;
}
-#if defined(OS_WIN)
void OSExchangeData::SetFileContents(const base::FilePath& filename,
const std::string& file_contents) {
provider_->SetFileContents(filename, file_contents);
@@ -130,6 +131,7 @@ bool OSExchangeData::GetFileContents(base::FilePath* filename,
return provider_->GetFileContents(filename, file_contents);
}
+#if defined(OS_WIN)
bool OSExchangeData::HasVirtualFilenames() const {
return provider_->HasVirtualFilenames();
}
diff --git a/chromium/ui/base/dragdrop/os_exchange_data.h b/chromium/ui/base/dragdrop/os_exchange_data.h
index abaaf8a28f3..d04b8188a5f 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data.h
+++ b/chromium/ui/base/dragdrop/os_exchange_data.h
@@ -57,9 +57,7 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeData {
URL = 1 << 1,
FILE_NAME = 1 << 2,
PICKLED_DATA = 1 << 3,
-#if defined(OS_WIN)
FILE_CONTENTS = 1 << 4,
-#endif
#if defined(USE_AURA)
HTML = 1 << 5,
#endif
@@ -125,6 +123,7 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeData {
bool HasString() const;
bool HasURL(FilenameToURLPolicy policy) const;
bool HasFile() const;
+ bool HasFileContents() const;
bool HasCustomFormat(const ClipboardFormatType& format) const;
// Returns true if this OSExchangeData has data in any of the formats in
@@ -132,7 +131,6 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeData {
bool HasAnyFormat(int formats,
const std::set<ClipboardFormatType>& types) const;
-#if defined(OS_WIN)
// Adds the bytes of a file (CFSTR_FILECONTENTS and CFSTR_FILEDESCRIPTOR on
// Windows).
void SetFileContents(const base::FilePath& filename,
@@ -140,6 +138,7 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeData {
bool GetFileContents(base::FilePath* filename,
std::string* file_contents) const;
+#if defined(OS_WIN)
// Methods used to query and retrieve file data from a drag source
// IDataObject implementation packaging the data with the
// CFSTR_FILEDESCRIPTOR/CFSTR_FILECONTENTS clipboard formats instead of the
diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed_unittest.cc b/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed_unittest.cc
index 3030bd9bb77..8ff37d05d0d 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed_unittest.cc
+++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed_unittest.cc
@@ -18,14 +18,14 @@
namespace ui {
namespace {
-const char kTestString[] = "Hello World!";
+const char16_t kTestString[] = u"Hello World!";
const char kUrl[] = "https://example.com";
-const char kUrlTitle[] = "example";
+const char16_t kUrlTitle[] = u"example";
const char kFileName[] = "file.pdf";
const base::FilePath::CharType kFileContentsFileName[] =
FILE_PATH_LITERAL("file.jpg");
const char kFileContents[] = "test data";
-const char kHtml[] = "<h1>Random Title</h1>";
+const char16_t kHtml[] = u"<h1>Random Title</h1>";
const char kBaseUrl[] = "www.example2.com";
} // namespace
@@ -34,16 +34,16 @@ const char kBaseUrl[] = "www.example2.com";
TEST(OSExchangeDataProviderNonBackedTest, CloneTest) {
OSExchangeDataProviderNonBacked original;
- original.SetString(base::UTF8ToUTF16(kTestString));
- original.SetURL(GURL(kUrl), base::UTF8ToUTF16(kUrlTitle));
+ original.SetString(kTestString);
+ original.SetURL(GURL(kUrl), kUrlTitle);
base::Pickle original_pickle;
- original_pickle.WriteString16(base::UTF8ToUTF16(kTestString));
+ original_pickle.WriteString16(kTestString);
original.SetPickledData(ClipboardFormatType::GetPlainTextType(),
original_pickle);
original.SetFileContents(base::FilePath(kFileContentsFileName),
std::string(kFileContents));
- original.SetHtml(base::UTF8ToUTF16(kHtml), GURL(kBaseUrl));
+ original.SetHtml(kHtml, GURL(kBaseUrl));
#if !BUILDFLAG(IS_CHROMEOS_ASH)
original.MarkOriginatedFromRenderer();
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
@@ -53,21 +53,21 @@ TEST(OSExchangeDataProviderNonBackedTest, CloneTest) {
std::unique_ptr<OSExchangeDataProvider> copy = original.Clone();
std::u16string copy_string;
EXPECT_TRUE(copy->GetString(&copy_string));
- EXPECT_EQ(base::UTF8ToUTF16(kTestString), copy_string);
+ EXPECT_EQ(kTestString, copy_string);
GURL copy_url;
std::u16string copy_title;
EXPECT_TRUE(copy->GetURLAndTitle(
FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &copy_url, &copy_title));
EXPECT_EQ(GURL(kUrl), copy_url);
- EXPECT_EQ(base::UTF8ToUTF16(kUrlTitle), copy_title);
+ EXPECT_EQ(kUrlTitle, copy_title);
base::Pickle copy_pickle;
copy->GetPickledData(ClipboardFormatType::GetPlainTextType(), &copy_pickle);
base::PickleIterator pickle_itr(copy_pickle);
std::u16string copy_pickle_string;
EXPECT_TRUE(pickle_itr.ReadString16(&copy_pickle_string));
- EXPECT_EQ(base::UTF8ToUTF16(kTestString), copy_pickle_string);
+ EXPECT_EQ(kTestString, copy_pickle_string);
base::FilePath copy_file_contents_filename;
std::string copy_file_contents;
@@ -78,7 +78,7 @@ TEST(OSExchangeDataProviderNonBackedTest, CloneTest) {
std::u16string copy_html;
GURL copy_base_url;
EXPECT_TRUE(copy->GetHtml(&copy_html, &copy_base_url));
- EXPECT_EQ(base::UTF8ToUTF16(kHtml), copy_html);
+ EXPECT_EQ(kHtml, copy_html);
EXPECT_EQ(GURL(kBaseUrl), copy_base_url);
#if !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_win.h b/chromium/ui/base/dragdrop/os_exchange_data_provider_win.h
index 6b19f7152d2..899311cda81 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data_provider_win.h
+++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_win.h
@@ -16,6 +16,7 @@
#include <vector>
#include "base/component_export.h"
+#include "base/containers/span.h"
#include "base/macros.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/dragdrop/os_exchange_data_provider.h"
diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_x11_unittest.cc b/chromium/ui/base/dragdrop/os_exchange_data_provider_x11_unittest.cc
deleted file mode 100644
index f8453a22649..00000000000
--- a/chromium/ui/base/dragdrop/os_exchange_data_provider_x11_unittest.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/base/dragdrop/os_exchange_data_provider_x11.h"
-
-#include <string>
-
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/task_environment.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/clipboard/clipboard_constants.h"
-#include "ui/base/clipboard/file_info.h"
-#include "ui/events/platform/x11/x11_event_source.h"
-#include "ui/gfx/x/connection.h"
-#include "ui/gfx/x/x11_atom_cache.h"
-#include "url/gurl.h"
-
-const char kFileURL[] = "file:///home/user/file.txt";
-const char kFileName[] = "/home/user/file.txt";
-const char kGoogleTitle[] = "Google";
-const char kGoogleURL[] = "http://www.google.com/";
-
-namespace ui {
-
-class OSExchangeDataProviderX11Test : public testing::Test {
- public:
- OSExchangeDataProviderX11Test()
- : task_environment_(base::test::TaskEnvironment::MainThreadType::UI),
- event_source(x11::Connection::Get()) {}
-
- void AddURLList(const std::string& list_contents) {
- std::string contents_copy = list_contents;
- scoped_refptr<base::RefCountedMemory> mem(
- base::RefCountedString::TakeString(&contents_copy));
-
- provider.format_map_.Insert(x11::GetAtom(kMimeTypeURIList), mem);
- }
-
- protected:
- base::test::TaskEnvironment task_environment_;
- X11EventSource event_source;
- OSExchangeDataProviderX11 provider;
-};
-
-TEST_F(OSExchangeDataProviderX11Test, MozillaURL) {
- // Check that we can get titled entries.
- provider.SetURL(GURL(kGoogleURL), base::ASCIIToUTF16(kGoogleTitle));
- {
- GURL out_gurl;
- std::u16string out_str;
- EXPECT_TRUE(provider.GetURLAndTitle(
- FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &out_gurl, &out_str));
- EXPECT_EQ(base::ASCIIToUTF16(kGoogleTitle), out_str);
- EXPECT_EQ(kGoogleURL, out_gurl.spec());
- }
-
- // Check that we can get non-titled entries.
- provider.SetURL(GURL(kGoogleURL), std::u16string());
- {
- GURL out_gurl;
- std::u16string out_str;
- EXPECT_TRUE(provider.GetURLAndTitle(
- FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &out_gurl, &out_str));
- EXPECT_EQ(std::u16string(), out_str);
- EXPECT_EQ(kGoogleURL, out_gurl.spec());
- }
-}
-
-TEST_F(OSExchangeDataProviderX11Test, FilesArentURLs) {
- AddURLList(kFileURL);
-
- EXPECT_TRUE(provider.HasFile());
- EXPECT_TRUE(provider.HasURL(FilenameToURLPolicy::CONVERT_FILENAMES));
- EXPECT_FALSE(provider.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES));
-}
-
-TEST_F(OSExchangeDataProviderX11Test, HTTPURLsArentFiles) {
- AddURLList(kGoogleURL);
-
- EXPECT_FALSE(provider.HasFile());
- EXPECT_TRUE(provider.HasURL(FilenameToURLPolicy::CONVERT_FILENAMES));
- EXPECT_TRUE(provider.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES));
-}
-
-TEST_F(OSExchangeDataProviderX11Test, URIListWithBoth) {
- AddURLList("file:///home/user/file.txt\nhttp://www.google.com");
-
- EXPECT_TRUE(provider.HasFile());
- EXPECT_TRUE(provider.HasURL(FilenameToURLPolicy::CONVERT_FILENAMES));
- EXPECT_TRUE(provider.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES));
-
- // We should only receive the file from GetFilenames().
- std::vector<FileInfo> filenames;
- EXPECT_TRUE(provider.GetFilenames(&filenames));
- ASSERT_EQ(1u, filenames.size());
- EXPECT_EQ(kFileName, filenames[0].path.value());
-
- // We should only receive the URL here.
- GURL out_gurl;
- std::u16string out_str;
- EXPECT_TRUE(provider.GetURLAndTitle(
- FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &out_gurl, &out_str));
- EXPECT_EQ(std::u16string(), out_str);
- EXPECT_EQ(kGoogleURL, out_gurl.spec());
-}
-
-TEST_F(OSExchangeDataProviderX11Test, OnlyStringURLIsUnfiltered) {
- const std::u16string file_url = base::UTF8ToUTF16(kFileURL);
- provider.SetString(file_url);
-
- EXPECT_TRUE(provider.HasString());
- EXPECT_FALSE(provider.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES));
-}
-
-TEST_F(OSExchangeDataProviderX11Test, StringAndURIListFilterString) {
- const std::u16string file_url = base::UTF8ToUTF16(kFileURL);
- provider.SetString(file_url);
- AddURLList(kFileURL);
-
- EXPECT_FALSE(provider.HasString());
- std::u16string out_str;
- EXPECT_FALSE(provider.GetString(&out_str));
-
- EXPECT_TRUE(provider.HasFile());
-}
-
-} // namespace ui
diff --git a/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc b/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc
index 954c93f98cc..d4156e85d79 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc
+++ b/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc
@@ -196,10 +196,10 @@ TEST_F(OSExchangeDataTest, TestFilenames) {
TEST_F(OSExchangeDataTest, TestHTML) {
OSExchangeData data;
GURL url("http://www.google.com/");
- std::u16string html = base::ASCIIToUTF16(
- "<HTML>\n<BODY>\n"
- "<b>bold.</b> <i><b>This is bold italic.</b></i>\n"
- "</BODY>\n</HTML>");
+ std::u16string html =
+ u"<HTML>\n<BODY>\n"
+ u"<b>bold.</b> <i><b>This is bold italic.</b></i>\n"
+ u"</BODY>\n</HTML>";
data.SetHtml(html, url);
OSExchangeData copy(
diff --git a/chromium/ui/base/glib/glib_cast.h b/chromium/ui/base/glib/glib_cast.h
index 5ecf9dd46cc..da550e017f5 100644
--- a/chromium/ui/base/glib/glib_cast.h
+++ b/chromium/ui/base/glib/glib_cast.h
@@ -11,6 +11,9 @@
template <typename T, typename U>
T* GlibCast(U* instance, GType g_type) {
+ // Ensure |g_type| is used so the compiler doesn't optimize it away
+ // in release builds.
+ g_type_class_unref(g_type_class_ref(g_type));
DCHECK(G_TYPE_CHECK_INSTANCE_TYPE(instance, g_type));
return reinterpret_cast<T*>(instance);
}
diff --git a/chromium/ui/base/glib/glib_signal.h b/chromium/ui/base/glib/glib_signal.h
index a0eec52c720..9bd736f8ffe 100644
--- a/chromium/ui/base/glib/glib_signal.h
+++ b/chromium/ui/base/glib/glib_signal.h
@@ -145,4 +145,4 @@ typedef void* gpointer;
\
virtual RETURN METHOD(SENDER, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6)
-#endif
+#endif // UI_BASE_GLIB_GLIB_SIGNAL_H_
diff --git a/chromium/ui/base/idle/BUILD.gn b/chromium/ui/base/idle/BUILD.gn
index 73f2aebff65..0e428cf697e 100644
--- a/chromium/ui/base/idle/BUILD.gn
+++ b/chromium/ui/base/idle/BUILD.gn
@@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//build/config/chromeos/ui_mode.gni")
+import("//build/config/features.gni")
import("//build/config/ui.gni")
if (is_mac) {
@@ -57,7 +58,12 @@ component("idle") {
}
if (is_linux) {
- sources += [ "idle_linux.cc" ]
+ if (use_dbus) {
+ sources += [ "idle_linux.cc" ]
+ deps += [ "//dbus" ]
+ } else {
+ sources += [ "idle_stub.cc" ]
+ }
}
if (use_x11 && !is_chromeos_ash) {
diff --git a/chromium/ui/base/idle/DEPS b/chromium/ui/base/idle/DEPS
index c0b3407624a..50cec1b8c00 100644
--- a/chromium/ui/base/idle/DEPS
+++ b/chromium/ui/base/idle/DEPS
@@ -2,5 +2,6 @@ include_rules = [
"+chromeos/dbus/dbus_thread_manager.h",
"+chromeos/dbus/session_manager",
"+chromeos/lacros",
+ "+dbus",
"+ui/base/ui_base_jni_headers",
]
diff --git a/chromium/ui/base/idle/idle_internal.cc b/chromium/ui/base/idle/idle_internal.cc
index ac62882ee5f..968d800b74c 100644
--- a/chromium/ui/base/idle/idle_internal.cc
+++ b/chromium/ui/base/idle/idle_internal.cc
@@ -8,8 +8,8 @@
namespace ui {
-base::Optional<IdleState>& IdleStateForTesting() {
- static base::NoDestructor<base::Optional<IdleState>> idle_state;
+absl::optional<IdleState>& IdleStateForTesting() {
+ static base::NoDestructor<absl::optional<IdleState>> idle_state;
return *idle_state;
}
diff --git a/chromium/ui/base/idle/idle_internal.h b/chromium/ui/base/idle/idle_internal.h
index 01e959854f9..d32affa3577 100644
--- a/chromium/ui/base/idle/idle_internal.h
+++ b/chromium/ui/base/idle/idle_internal.h
@@ -6,14 +6,14 @@
#define UI_BASE_IDLE_IDLE_INTERNAL_H_
#include "base/component_export.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/idle/idle.h"
namespace ui {
// An optional idle state set by tests via a ScopedSetIdleState to override the
// actual idle state of the system.
-COMPONENT_EXPORT(UI_BASE_IDLE) base::Optional<IdleState>& IdleStateForTesting();
+COMPONENT_EXPORT(UI_BASE_IDLE) absl::optional<IdleState>& IdleStateForTesting();
} // namespace ui
diff --git a/chromium/ui/base/idle/idle_linux.cc b/chromium/ui/base/idle/idle_linux.cc
index 3b97a45618c..a9c1fafe9cf 100644
--- a/chromium/ui/base/idle/idle_linux.cc
+++ b/chromium/ui/base/idle/idle_linux.cc
@@ -2,13 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/bind.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/no_destructor.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "base/task_runner.h"
#include "ui/base/idle/idle.h"
+#include "dbus/bus.h"
+#include "dbus/message.h"
+#include "dbus/object_path.h"
+#include "dbus/object_proxy.h"
#include "ui/base/idle/idle_internal.h"
#if defined(USE_X11)
#include "ui/base/x/x11_idle_query.h"
-#include "ui/base/x/x11_screensaver_window_finder.h"
+#include "ui/base/x/x11_screensaver.h"
#else
#include "base/notreached.h"
#endif
@@ -20,6 +30,140 @@
namespace ui {
+namespace {
+
+const char kMethodName[] = "GetActive";
+const char kSignalName[] = "ActiveChanged";
+
+struct {
+ const char* service_name;
+ const char* object_path;
+ const char* interface;
+} constexpr kInterfaces[] = {
+ // ksmserver, light-locker, etc.
+ {"org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver",
+ "org.freedesktop.ScreenSaver"},
+ // cinnamon-screensaver
+ {"org.cinnamon.ScreenSaver", "/org/cinnamon/ScreenSaver",
+ "org.cinnamon.ScreenSaver"},
+ // gnome-screensaver
+ {"org.gnome.ScreenSaver", "/", "org.gnome.ScreenSaver"},
+ // mate-screensaver
+ {"org.mate.ScreenSaver", "/", "org.mate.ScreenSaver"},
+ // xfce4-screensaver
+ {"org.xfce.ScreenSaver", "/", "org.xfce.ScreenSaver"},
+};
+
+bool ServiceNameHasOwner(dbus::Bus* bus, const char* service_name) {
+ dbus::ObjectProxy* dbus_proxy =
+ bus->GetObjectProxy(DBUS_SERVICE_DBUS, dbus::ObjectPath(DBUS_PATH_DBUS));
+ dbus::MethodCall name_has_owner_call(DBUS_INTERFACE_DBUS, "NameHasOwner");
+ dbus::MessageWriter writer(&name_has_owner_call);
+ writer.AppendString(service_name);
+ std::unique_ptr<dbus::Response> name_has_owner_response =
+ dbus_proxy->CallMethodAndBlock(&name_has_owner_call,
+ dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
+ dbus::MessageReader reader(name_has_owner_response.get());
+ bool owned = false;
+ return name_has_owner_response && reader.PopBool(&owned) && owned;
+}
+
+// This class checks for availability of various DBus screensaver interfaces
+// and listens for screensaver events on the first one found.
+class IdleLinuxImpl {
+ public:
+ enum class LockState {
+ kUnknown,
+ kLocked,
+ kUnlocked,
+ };
+
+ IdleLinuxImpl()
+ : task_runner_(
+ base::ThreadPool::CreateSequencedTaskRunner(base::TaskTraits(
+ base::MayBlock(),
+ base::TaskPriority::USER_VISIBLE,
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN))) {}
+
+ void Init() {
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(&IdleLinuxImpl::InitOnTaskRunner,
+ base::Unretained(this)));
+ }
+
+ LockState lock_state() const { return lock_state_; }
+
+ private:
+ ~IdleLinuxImpl() = default;
+
+ void InitOnTaskRunner() {
+ dbus::Bus::Options options;
+ options.bus_type = dbus::Bus::SESSION;
+ options.connection_type = dbus::Bus::PRIVATE;
+ options.dbus_task_runner = task_runner_;
+ bus_ = base::MakeRefCounted<dbus::Bus>(options);
+
+ for (const auto& interface : kInterfaces) {
+ // Calling methods on a non-existent service will lead to a timeout rather
+ // than an immediate error, so check for service existence first.
+ if (!ServiceNameHasOwner(bus_.get(), interface.service_name))
+ continue;
+
+ // To avoid a race condition, start listenting for state changes before
+ // querying the state.
+ auto* proxy = bus_->GetObjectProxy(
+ interface.service_name, dbus::ObjectPath(interface.object_path));
+ if (!proxy->ConnectToSignalAndBlock(
+ interface.interface, kSignalName,
+ base::BindRepeating(&IdleLinuxImpl::OnActiveChanged,
+ base::Unretained(this)))) {
+ continue;
+ }
+
+ // Some service owners (eg. gsd-screensaver-proxy) advertise the correct
+ // methods on org.freedesktop.ScreenSaver, but calling them will result in
+ // a NotImplemented DBus error. To ensure the service owner will send
+ // state change events, make an explicit method call and check that no
+ // error is returned.
+ dbus::MethodCall method_call(interface.interface, kMethodName);
+ auto response = proxy->CallMethodAndBlock(
+ &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
+ if (response && UpdateLockState(response.get()))
+ return;
+
+ // Try the next interface.
+ proxy->Detach();
+ }
+ }
+
+ void OnActiveChanged(dbus::Signal* signal) { UpdateLockState(signal); }
+
+ bool UpdateLockState(dbus::Message* message) {
+ dbus::MessageReader reader(message);
+ bool active;
+ if (!reader.PopBool(&active) || reader.HasMoreData())
+ return false;
+ lock_state_ = active ? LockState::kLocked : LockState::kUnlocked;
+ return true;
+ }
+
+ // Only accessed on the task runner.
+ scoped_refptr<dbus::Bus> bus_;
+
+ // Only accessed on the main thread.
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+ // Read on the main thread and written on the task runner.
+ std::atomic<LockState> lock_state_{LockState::kUnknown};
+};
+
+IdleLinuxImpl* GetIdleLinuxImpl() {
+ static base::NoDestructor<IdleLinuxImpl> impl;
+ return impl.get();
+}
+
+} // namespace
+
int CalculateIdleTime() {
#if defined(USE_OZONE)
if (features::IsUsingOzonePlatform()) {
@@ -43,6 +187,10 @@ bool CheckIdleStateIsLocked() {
if (IdleStateForTesting().has_value())
return IdleStateForTesting().value() == IDLE_STATE_LOCKED;
+ auto lock_state = GetIdleLinuxImpl()->lock_state();
+ if (lock_state != IdleLinuxImpl::LockState::kUnknown)
+ return lock_state == IdleLinuxImpl::LockState::kLocked;
+
#if defined(USE_OZONE)
if (features::IsUsingOzonePlatform()) {
auto* const screen = display::Screen::GetScreen();
@@ -54,7 +202,7 @@ bool CheckIdleStateIsLocked() {
#endif
#if defined(USE_X11)
// Usually the screensaver is used to lock the screen.
- return ScreensaverWindowFinder::ScreensaverWindowExists();
+ return IsXScreensaverActive();
#else
NOTIMPLEMENTED_LOG_ONCE();
return false;
diff --git a/chromium/ui/base/idle/idle_stub.cc b/chromium/ui/base/idle/idle_stub.cc
new file mode 100644
index 00000000000..77ca1dd9638
--- /dev/null
+++ b/chromium/ui/base/idle/idle_stub.cc
@@ -0,0 +1,21 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/idle/idle.h"
+
+#include "base/notreached.h"
+
+namespace ui {
+
+int CalculateIdleTime() {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+bool CheckIdleStateIsLocked() {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/idle/scoped_set_idle_state.h b/chromium/ui/base/idle/scoped_set_idle_state.h
index 7309095d37b..db8eafa06a7 100644
--- a/chromium/ui/base/idle/scoped_set_idle_state.h
+++ b/chromium/ui/base/idle/scoped_set_idle_state.h
@@ -6,7 +6,7 @@
#define UI_BASE_IDLE_SCOPED_SET_IDLE_STATE_H_
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/idle/idle.h"
namespace ui {
@@ -17,7 +17,7 @@ class ScopedSetIdleState {
~ScopedSetIdleState();
private:
- base::Optional<IdleState> previous_state_;
+ absl::optional<IdleState> previous_state_;
DISALLOW_COPY_AND_ASSIGN(ScopedSetIdleState);
};
diff --git a/chromium/ui/base/ime/BUILD.gn b/chromium/ui/base/ime/BUILD.gn
index 194c8383e2d..3a18c6bf896 100644
--- a/chromium/ui/base/ime/BUILD.gn
+++ b/chromium/ui/base/ime/BUILD.gn
@@ -21,6 +21,8 @@ component("ime_types") {
"candidate_window.h",
"composition_text.cc",
"composition_text.h",
+ "grammar_fragment.cc",
+ "grammar_fragment.h",
"ime_text_span.cc",
"ime_text_span.h",
"infolist_entry.cc",
diff --git a/chromium/ui/base/ime/OWNERS b/chromium/ui/base/ime/OWNERS
index 3bf3a83c1a8..65b2c66cb9b 100644
--- a/chromium/ui/base/ime/OWNERS
+++ b/chromium/ui/base/ime/OWNERS
@@ -8,4 +8,4 @@ shend@chromium.org
yukishiino@chromium.org
# For Windows.
-yukawa@chromium.org \ No newline at end of file
+yukawa@chromium.org
diff --git a/chromium/ui/base/ime/chromeos/BUILD.gn b/chromium/ui/base/ime/chromeos/BUILD.gn
index f68783743db..76365cbeb06 100644
--- a/chromium/ui/base/ime/chromeos/BUILD.gn
+++ b/chromium/ui/base/ime/chromeos/BUILD.gn
@@ -10,6 +10,18 @@ source_set("ime_types") {
sources = [ "ime_keyset.h" ]
}
+source_set("typing_session_manager") {
+ sources = [
+ "typing_session_manager.cc",
+ "typing_session_manager.h",
+ ]
+
+ public_deps = [
+ "//base:base",
+ "//third_party/abseil-cpp:absl",
+ ]
+}
+
component("chromeos") {
output_name = "ui_base_ime_chromeos"
@@ -42,6 +54,8 @@ component("chromeos") {
"input_method_descriptor.h",
"input_method_manager.cc",
"input_method_manager.h",
+ "input_method_ukm.cc",
+ "input_method_ukm.h",
"input_method_util.cc",
"input_method_util.h",
]
@@ -55,11 +69,14 @@ component("chromeos") {
deps = [
":ime_types",
+ ":typing_session_manager",
"//build:branding_buildflags",
"//chromeos/services/ime/public/mojom",
"//chromeos/system",
+ "//services/metrics/public/cpp:ukm_builders",
"//third_party/icu",
"//ui/base",
+ "//ui/base",
"//ui/chromeos/strings",
"//ui/ozone:ozone_base",
]
diff --git a/chromium/ui/base/ime/dummy_text_input_client.cc b/chromium/ui/base/ime/dummy_text_input_client.cc
index d063f39d801..4507c8f52a6 100644
--- a/chromium/ui/base/ime/dummy_text_input_client.cc
+++ b/chromium/ui/base/ime/dummy_text_input_client.cc
@@ -8,6 +8,7 @@
#include <vector>
#endif
+#include "base/notreached.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
@@ -79,6 +80,11 @@ gfx::Rect DummyTextInputClient::GetCaretBounds() const {
return gfx::Rect();
}
+gfx::Rect DummyTextInputClient::GetSelectionBoundingBox() const {
+ NOTIMPLEMENTED_LOG_ONCE();
+ return gfx::Rect();
+}
+
bool DummyTextInputClient::GetCompositionCharacterBounds(
uint32_t index,
gfx::Rect* rect) const {
@@ -171,12 +177,23 @@ bool DummyTextInputClient::SetAutocorrectRange(
return true;
}
+bool DummyTextInputClient::ClearGrammarFragments(const gfx::Range& range) {
+ grammar_fragments_.clear();
+ return true;
+}
+
+bool DummyTextInputClient::AddGrammarFragments(
+ const std::vector<GrammarFragment>& fragments) {
+ grammar_fragments_.insert(grammar_fragments_.end(), fragments.begin(),
+ fragments.end());
+ return true;
+}
#endif
#if defined(OS_WIN)
void DummyTextInputClient::GetActiveTextInputControlLayoutBounds(
- base::Optional<gfx::Rect>* control_bounds,
- base::Optional<gfx::Rect>* selection_bounds) {}
+ absl::optional<gfx::Rect>* control_bounds,
+ absl::optional<gfx::Rect>* selection_bounds) {}
void DummyTextInputClient::SetActiveCompositionForAccessibility(
const gfx::Range& range,
diff --git a/chromium/ui/base/ime/dummy_text_input_client.h b/chromium/ui/base/ime/dummy_text_input_client.h
index 7908a32d38c..114f91da393 100644
--- a/chromium/ui/base/ime/dummy_text_input_client.h
+++ b/chromium/ui/base/ime/dummy_text_input_client.h
@@ -38,6 +38,7 @@ class DummyTextInputClient : public TextInputClient {
int GetTextInputFlags() const override;
bool CanComposeInline() const override;
gfx::Rect GetCaretBounds() const override;
+ gfx::Rect GetSelectionBoundingBox() const override;
bool GetCompositionCharacterBounds(uint32_t index,
gfx::Rect* rect) const override;
bool HasCompositionText() const override;
@@ -69,12 +70,15 @@ class DummyTextInputClient : public TextInputClient {
gfx::Range GetAutocorrectRange() const override;
gfx::Rect GetAutocorrectCharacterBounds() const override;
bool SetAutocorrectRange(const gfx::Range& range) override;
+ bool ClearGrammarFragments(const gfx::Range& range) override;
+ bool AddGrammarFragments(
+ const std::vector<GrammarFragment>& fragments) override;
#endif
#if defined(OS_WIN)
void GetActiveTextInputControlLayoutBounds(
- base::Optional<gfx::Rect>* control_bounds,
- base::Optional<gfx::Rect>* selection_bounds) override;
+ absl::optional<gfx::Rect>* control_bounds,
+ absl::optional<gfx::Rect>* selection_bounds) override;
void SetActiveCompositionForAccessibility(
const gfx::Range& range,
const std::u16string& active_composition_text,
@@ -93,6 +97,10 @@ class DummyTextInputClient : public TextInputClient {
return selection_history_;
}
+ std::vector<GrammarFragment> get_grammar_fragments() const {
+ return grammar_fragments_;
+ }
+
TextInputType text_input_type_;
TextInputMode text_input_mode_;
@@ -105,6 +113,7 @@ class DummyTextInputClient : public TextInputClient {
std::vector<CompositionText> composition_history_;
std::vector<gfx::Range> selection_history_;
gfx::Range autocorrect_range_;
+ std::vector<GrammarFragment> grammar_fragments_;
};
} // namespace ui
diff --git a/chromium/ui/base/ime/fake_text_input_client.cc b/chromium/ui/base/ime/fake_text_input_client.cc
index 4932bc8d6e2..1e3b7a4347b 100644
--- a/chromium/ui/base/ime/fake_text_input_client.cc
+++ b/chromium/ui/base/ime/fake_text_input_client.cc
@@ -20,6 +20,10 @@ void FakeTextInputClient::set_text_input_type(TextInputType text_input_type) {
text_input_type_ = text_input_type;
}
+void FakeTextInputClient::set_source_id(ukm::SourceId source_id) {
+ source_id_ = source_id;
+}
+
void FakeTextInputClient::SetTextAndSelection(const std::u16string& text,
gfx::Range selection) {
DCHECK_LE(selection_.end(), text.length());
@@ -79,6 +83,10 @@ gfx::Rect FakeTextInputClient::GetCaretBounds() const {
return {};
}
+gfx::Rect FakeTextInputClient::GetSelectionBoundingBox() const {
+ return {};
+}
+
bool FakeTextInputClient::GetCompositionCharacterBounds(uint32_t index,
gfx::Rect* rect) const {
return false;
@@ -140,7 +148,7 @@ void FakeTextInputClient::SetTextEditCommandForNextKeyEvent(
TextEditCommand command) {}
ukm::SourceId FakeTextInputClient::GetClientSourceForMetrics() const {
- return {};
+ return source_id_;
}
bool FakeTextInputClient::ShouldDoLearning() {
@@ -177,8 +185,8 @@ bool FakeTextInputClient::SetAutocorrectRange(const gfx::Range& range) {
#if defined(OS_WIN)
void FakeTextInputClient::GetActiveTextInputControlLayoutBounds(
- base::Optional<gfx::Rect>* control_bounds,
- base::Optional<gfx::Rect>* selection_bounds) {}
+ absl::optional<gfx::Rect>* control_bounds,
+ absl::optional<gfx::Rect>* selection_bounds) {}
void FakeTextInputClient::SetActiveCompositionForAccessibility(
const gfx::Range& range,
diff --git a/chromium/ui/base/ime/fake_text_input_client.h b/chromium/ui/base/ime/fake_text_input_client.h
index d282ea58760..ffd35c6853c 100644
--- a/chromium/ui/base/ime/fake_text_input_client.h
+++ b/chromium/ui/base/ime/fake_text_input_client.h
@@ -25,6 +25,7 @@ class FakeTextInputClient : public TextInputClient {
~FakeTextInputClient() override;
void set_text_input_type(TextInputType text_input_type);
+ void set_source_id(ukm::SourceId source_id);
void SetTextAndSelection(const std::u16string& text, gfx::Range selection);
const std::u16string& text() const { return text_; }
@@ -48,6 +49,7 @@ class FakeTextInputClient : public TextInputClient {
int GetTextInputFlags() const override;
bool CanComposeInline() const override;
gfx::Rect GetCaretBounds() const override;
+ gfx::Rect GetSelectionBoundingBox() const override;
bool GetCompositionCharacterBounds(uint32_t index,
gfx::Rect* rect) const override;
bool HasCompositionText() const override;
@@ -80,8 +82,8 @@ class FakeTextInputClient : public TextInputClient {
#endif
#if defined(OS_WIN)
void GetActiveTextInputControlLayoutBounds(
- base::Optional<gfx::Rect>* control_bounds,
- base::Optional<gfx::Rect>* selection_bounds) override;
+ absl::optional<gfx::Rect>* control_bounds,
+ absl::optional<gfx::Rect>* selection_bounds) override;
void SetActiveCompositionForAccessibility(
const gfx::Range& range,
const std::u16string& active_composition_text,
@@ -95,6 +97,7 @@ class FakeTextInputClient : public TextInputClient {
gfx::Range composition_range_;
std::vector<ui::ImeTextSpan> ime_text_spans_;
gfx::Range autocorrect_range_;
+ ukm::SourceId source_id_;
};
} // namespace ui
diff --git a/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc b/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc
index aaa5a1e142c..4d88241eecd 100644
--- a/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc
+++ b/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc
@@ -49,9 +49,19 @@ ui::EventDispatchDetails InputMethodFuchsia::DispatchKeyEvent(
return dispatch_details;
}
-void InputMethodFuchsia::OnCaretBoundsChanged(const TextInputClient* client) {}
+void InputMethodFuchsia::CancelComposition(const TextInputClient* client) {
+ // FIDL asynchronicity makes it impossible to know whether a recent
+ // visibility update might be in flight, so always call Dismiss.
+ virtual_keyboard_controller_.DismissVirtualKeyboard();
+}
+
+void InputMethodFuchsia::OnTextInputTypeChanged(const TextInputClient* client) {
+ InputMethodBase::OnTextInputTypeChanged(client);
-void InputMethodFuchsia::CancelComposition(const TextInputClient* client) {}
+ virtual_keyboard_controller_.UpdateTextType();
+}
+
+void InputMethodFuchsia::OnCaretBoundsChanged(const TextInputClient* client) {}
bool InputMethodFuchsia::IsCandidatePopupOpen() const {
return false;
diff --git a/chromium/ui/base/ime/fuchsia/input_method_fuchsia.h b/chromium/ui/base/ime/fuchsia/input_method_fuchsia.h
index 511f2c9ea7f..52b2b6b0eb2 100644
--- a/chromium/ui/base/ime/fuchsia/input_method_fuchsia.h
+++ b/chromium/ui/base/ime/fuchsia/input_method_fuchsia.h
@@ -8,7 +8,6 @@
#include <fuchsia/ui/input/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/ui/scenic/cpp/view_ref_pair.h>
-#include <memory>
#include "base/component_export.h"
#include "base/macros.h"
@@ -35,8 +34,9 @@ class COMPONENT_EXPORT(UI_BASE_IME_FUCHSIA) InputMethodFuchsia
// InputMethodBase interface implementation.
VirtualKeyboardController* GetVirtualKeyboardController() final;
ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) final;
- void OnCaretBoundsChanged(const TextInputClient* client) final;
void CancelComposition(const TextInputClient* client) final;
+ void OnTextInputTypeChanged(const TextInputClient* client) final;
+ void OnCaretBoundsChanged(const TextInputClient* client) final;
bool IsCandidatePopupOpen() const final;
private:
diff --git a/chromium/ui/base/ime/fuchsia/keyboard_client.h b/chromium/ui/base/ime/fuchsia/keyboard_client.h
index d74aeb07309..3c213077e83 100644
--- a/chromium/ui/base/ime/fuchsia/keyboard_client.h
+++ b/chromium/ui/base/ime/fuchsia/keyboard_client.h
@@ -7,7 +7,6 @@
#include <fuchsia/ui/input3/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
-#include <memory>
#include "base/component_export.h"
#include "ui/events/event.h"
diff --git a/chromium/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.cc b/chromium/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.cc
index 70031994afe..25de7d0c6a0 100644
--- a/chromium/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.cc
+++ b/chromium/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.cc
@@ -15,27 +15,6 @@
namespace ui {
namespace {
-// Returns the FIDL enum representation of the current InputMode.
-fuchsia::input::virtualkeyboard::TextType ConvertTextInputMode(
- ui::TextInputMode mode) {
- switch (mode) {
- case TEXT_INPUT_MODE_NUMERIC:
- case TEXT_INPUT_MODE_DECIMAL:
- return fuchsia::input::virtualkeyboard::TextType::NUMERIC;
-
- case TEXT_INPUT_MODE_TEL:
- return fuchsia::input::virtualkeyboard::TextType::PHONE;
-
- case TEXT_INPUT_MODE_DEFAULT:
- case TEXT_INPUT_MODE_NONE:
- case TEXT_INPUT_MODE_TEXT:
- case TEXT_INPUT_MODE_URL:
- case TEXT_INPUT_MODE_EMAIL:
- case TEXT_INPUT_MODE_SEARCH:
- return fuchsia::input::virtualkeyboard::TextType::ALPHANUMERIC;
- }
-}
-
} // namespace
VirtualKeyboardControllerFuchsia::VirtualKeyboardControllerFuchsia(
@@ -47,13 +26,11 @@ VirtualKeyboardControllerFuchsia::VirtualKeyboardControllerFuchsia(
base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::input::virtualkeyboard::ControllerCreator>()
- ->Create(std::move(view_ref),
- ConvertTextInputMode(input_method_->GetTextInputMode()),
+ ->Create(std::move(view_ref), requested_type_,
controller_service_.NewRequest());
- controller_service_.set_error_handler([this](zx_status_t status) {
+ controller_service_.set_error_handler([](zx_status_t status) {
ZX_LOG(ERROR, status) << "virtualkeyboard::Controller disconnected";
- keyboard_visible_ = false;
});
WatchVisibility();
@@ -62,22 +39,29 @@ VirtualKeyboardControllerFuchsia::VirtualKeyboardControllerFuchsia(
VirtualKeyboardControllerFuchsia::~VirtualKeyboardControllerFuchsia() = default;
bool VirtualKeyboardControllerFuchsia::DisplayVirtualKeyboard() {
+ DVLOG(1) << "DisplayVirtualKeyboard (visible= " << keyboard_visible_ << ")";
+
if (!controller_service_)
return false;
- controller_service_->SetTextType(
- ConvertTextInputMode(input_method_->GetTextInputMode()));
+ UpdateTextType();
- if (!keyboard_visible_)
- controller_service_->RequestShow();
+ requested_visible_ = true;
+ controller_service_->RequestShow();
return true;
}
void VirtualKeyboardControllerFuchsia::DismissVirtualKeyboard() {
+ DVLOG(1) << "DismissVirtualKeyboard (visible= " << keyboard_visible_ << ")";
+
if (!controller_service_)
return;
+ if (!requested_visible_ && !keyboard_visible_)
+ return;
+
+ requested_visible_ = false;
controller_service_->RequestHide();
}
@@ -100,8 +84,40 @@ void VirtualKeyboardControllerFuchsia::WatchVisibility() {
}
void VirtualKeyboardControllerFuchsia::OnVisibilityChange(bool is_visible) {
+ DVLOG(1) << "OnVisibilityChange " << is_visible;
keyboard_visible_ = is_visible;
WatchVisibility();
}
+// Returns the FIDL enum representation of the current InputMode.
+fuchsia::input::virtualkeyboard::TextType
+VirtualKeyboardControllerFuchsia::GetFocusedTextType() const {
+ switch (input_method_->GetTextInputMode()) {
+ case TEXT_INPUT_MODE_NUMERIC:
+ case TEXT_INPUT_MODE_DECIMAL:
+ return fuchsia::input::virtualkeyboard::TextType::NUMERIC;
+
+ case TEXT_INPUT_MODE_TEL:
+ return fuchsia::input::virtualkeyboard::TextType::PHONE;
+
+ case TEXT_INPUT_MODE_DEFAULT:
+ case TEXT_INPUT_MODE_NONE:
+ case TEXT_INPUT_MODE_TEXT:
+ case TEXT_INPUT_MODE_URL:
+ case TEXT_INPUT_MODE_EMAIL:
+ case TEXT_INPUT_MODE_SEARCH:
+ return fuchsia::input::virtualkeyboard::TextType::ALPHANUMERIC;
+ }
+}
+
+void VirtualKeyboardControllerFuchsia::UpdateTextType() {
+ // Only send updates if the type has changed.
+ auto new_type = GetFocusedTextType();
+ if (new_type != requested_type_) {
+ DVLOG(1) << "SetTextType " << static_cast<int>(new_type);
+ controller_service_->SetTextType(new_type);
+ requested_type_ = new_type;
+ }
+}
+
} // namespace ui
diff --git a/chromium/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.h b/chromium/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.h
index 1adc5692e23..4f960033764 100644
--- a/chromium/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.h
+++ b/chromium/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.h
@@ -29,6 +29,8 @@ class COMPONENT_EXPORT(UI_BASE_IME) VirtualKeyboardControllerFuchsia
VirtualKeyboardControllerFuchsia operator=(
VirtualKeyboardControllerFuchsia&) = delete;
+ void UpdateTextType();
+
// VirtualKeyboardController implementation.
bool DisplayVirtualKeyboard() override;
void DismissVirtualKeyboard() override;
@@ -43,9 +45,15 @@ class COMPONENT_EXPORT(UI_BASE_IME) VirtualKeyboardControllerFuchsia
// Handles the visibility change response from the service.
void OnVisibilityChange(bool is_visible);
+ // Gets the Fuchsia TextType corresponding to the currently focused field.
+ fuchsia::input::virtualkeyboard::TextType GetFocusedTextType() const;
+
ui::InputMethodBase* const input_method_;
+ fuchsia::input::virtualkeyboard::TextType requested_type_ =
+ fuchsia::input::virtualkeyboard::TextType::ALPHANUMERIC;
fuchsia::input::virtualkeyboard::ControllerPtr controller_service_;
bool keyboard_visible_ = false;
+ bool requested_visible_ = false;
};
} // namespace ui
diff --git a/chromium/ui/base/ime/grammar_fragment.cc b/chromium/ui/base/ime/grammar_fragment.cc
new file mode 100644
index 00000000000..36a005e1390
--- /dev/null
+++ b/chromium/ui/base/ime/grammar_fragment.cc
@@ -0,0 +1,25 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/ime/grammar_fragment.h"
+
+namespace ui {
+
+GrammarFragment::GrammarFragment(const gfx::Range& range,
+ const std::string& suggestion)
+ : range(range), suggestion(suggestion) {}
+
+GrammarFragment::GrammarFragment(const GrammarFragment& other) = default;
+
+GrammarFragment::~GrammarFragment() = default;
+
+bool GrammarFragment::operator==(const GrammarFragment& other) const {
+ return range == other.range && suggestion == other.suggestion;
+}
+
+bool GrammarFragment::operator!=(const GrammarFragment& other) const {
+ return !(*this == other);
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/ime/grammar_fragment.h b/chromium/ui/base/ime/grammar_fragment.h
new file mode 100644
index 00000000000..b97cadc162d
--- /dev/null
+++ b/chromium/ui/base/ime/grammar_fragment.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_IME_GRAMMAR_FRAGMENT_H_
+#define UI_BASE_IME_GRAMMAR_FRAGMENT_H_
+
+#include <string>
+
+#include "base/component_export.h"
+#include "ui/gfx/range/range.h"
+
+namespace ui {
+
+// A struct represents a fragment of grammar edit suggestion.
+struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) GrammarFragment {
+ GrammarFragment(const gfx::Range& range, const std::string& suggestion);
+ GrammarFragment(const GrammarFragment& other);
+ ~GrammarFragment();
+
+ bool operator==(const GrammarFragment& other) const;
+ bool operator!=(const GrammarFragment& other) const;
+
+ // The range of the marker, visual indications such as underlining are
+ // expected to show in this range.
+ gfx::Range range;
+
+ // The replacement text suggested by the grammar model.
+ std::string suggestion;
+};
+
+} // namespace ui
+
+#endif // UI_BASE_IME_GRAMMAR_FRAGMENT_H_
diff --git a/chromium/ui/base/ime/ime_text_span.h b/chromium/ui/base/ime/ime_text_span.h
index 62bdfb8cbac..2d373da4350 100644
--- a/chromium/ui/base/ime/ime_text_span.h
+++ b/chromium/ui/base/ime/ime_text_span.h
@@ -28,6 +28,8 @@ struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) ImeTextSpan {
kMisspellingSuggestion,
// Creates an autocorrect marker that isn't cleared by itself.
kAutocorrect,
+ // Creates a grammar marker that isn't cleared by itself.
+ kGrammarSuggestion,
};
enum class Thickness {
diff --git a/chromium/ui/base/ime/input_method.h b/chromium/ui/base/ime/input_method.h
index a93dc25d794..6e411aa2e5e 100644
--- a/chromium/ui/base/ime/input_method.h
+++ b/chromium/ui/base/ime/input_method.h
@@ -7,9 +7,6 @@
#include <stdint.h>
-#include <memory>
-#include <string>
-#include <vector>
#include "build/build_config.h"
#include "ui/base/ime/text_input_mode.h"
diff --git a/chromium/ui/base/ime/linux/BUILD.gn b/chromium/ui/base/ime/linux/BUILD.gn
index 672a47ae34b..77452cf14f9 100644
--- a/chromium/ui/base/ime/linux/BUILD.gn
+++ b/chromium/ui/base/ime/linux/BUILD.gn
@@ -36,4 +36,8 @@ component("linux") {
"composition_text_util_pango.h",
]
}
+
+ # TODO(crbug.com/1199385): Remove this on unifying lacros and linux desktop
+ # behavior again.
+ deps = [ "//build:chromeos_buildflags" ]
}
diff --git a/chromium/ui/base/ime/linux/input_method_auralinux.cc b/chromium/ui/base/ime/linux/input_method_auralinux.cc
index 9388feaff2e..3bff237d309 100644
--- a/chromium/ui/base/ime/linux/input_method_auralinux.cc
+++ b/chromium/ui/base/ime/linux/input_method_auralinux.cc
@@ -7,6 +7,7 @@
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/environment.h"
+#include "build/chromeos_buildflags.h"
#include "ui/base/ime/constants.h"
#include "ui/base/ime/linux/linux_input_method_context_factory.h"
#include "ui/base/ime/text_input_client.h"
@@ -26,6 +27,16 @@ bool IsEventFromVK(const ui::KeyEvent& event) {
properties->find(ui::kPropertyFromVK) != properties->end();
}
+bool IsSameKeyEvent(const ui::KeyEvent& lhs, const ui::KeyEvent& rhs) {
+ // Note that we do not check timestamp here in order to support wayland's
+ // text_input::keysym, which does not have timestamp.
+ // Ignore EF_IS_REPEAT here, because they may be calculated in KeyEvent's
+ // ctor, so we cannot rely on it to detect whether key events come from
+ // the same native event.
+ return lhs.type() == rhs.type() && lhs.code() == rhs.code() &&
+ (lhs.flags() & ~ui::EF_IS_REPEAT) == (rhs.flags() & ~ui::EF_IS_REPEAT);
+}
+
} // namespace
namespace ui {
@@ -59,6 +70,43 @@ LinuxInputMethodContext* InputMethodAuraLinux::GetContextForTesting(
ui::EventDispatchDetails InputMethodAuraLinux::DispatchKeyEvent(
ui::KeyEvent* event) {
DCHECK(event->type() == ET_KEY_PRESSED || event->type() == ET_KEY_RELEASED);
+ // If there's pending deadkey event, i.e. a key event which is expected to
+ // trigger input method actions (like OnCommit, OnPreedit* invocation)
+ // and to be dispatched from there, but not yet, dispatch the pending event
+ // first.
+ // Dead keys are considered to be consumed by IME. Actually, it updates
+ // input method's internal state. However, it makes no input method actions,
+ // so the event won't be dispatched without this handling.
+ // Note that this is the earliest timing to find the pending deadkey event
+ // needs to be dispatched. It is because InputMethodAuraLinux cannot find
+ // whether input method actions will be followed or not on holding the event.
+ //
+ // Note that we do not apply this for non-deadkey events intentionally.
+ // It is because some input framework sends key events twice to fill the gap
+ // of synchronous API v.s. asynchronous operations.
+ // Specifically:
+ // - The first key event is passed to input method via |context_| below.
+ // - Inside the function, it triggers asynchronous input method operation.
+ // However, the function needs to return whether the event is filtered
+ // or not synchronously, it returns "filtered" regardless of the event
+ // will be actually filtered or not.
+ // - On completion of the input method action, specifically if the input
+ // method does not consume the event, the framework internally re-generates
+ // the same key event, and post it back again to the application.
+ // This happens some common input method framework, such as iBus/fcitx and
+ // GTK-IMmodule. Also, wayland extension implemented by exosphere in
+ // ash-chrome for Lacros behaves in the same way from InputMethodAuraLinux's
+ // point of view.
+ // To avoid dispatching twice, do not dispatch it here. Following code
+ // will handle the second (i.e. fallback) key event, including event
+ // dispatching.
+ // Importantly, the second key press event may be arrived after the first
+ // key release event, because everything is working in asynchronous ways.
+ if (ime_filtered_key_event_.has_value() &&
+ !IsSameKeyEvent(*ime_filtered_key_event_, *event) &&
+ ime_filtered_key_event_->GetDomKey().IsDeadKey()) {
+ std::ignore = DispatchKeyEventPostIME(&*ime_filtered_key_event_);
+ }
ime_filtered_key_event_.reset();
// If no text input client, do nothing.
@@ -112,7 +160,17 @@ ui::EventDispatchDetails InputMethodAuraLinux::DispatchKeyEvent(
// consumed by IME and commit/preedit string update will happen
// asynchronously. The remaining case is covered in OnCommit and
// OnPreeditChanged/End.
- if (filtered && !HasInputMethodResult() && !IsTextInputTypeNone()) {
+ // TODO(crbug.com/1199385): On Lacros CTRL+TAB events are sent twice if
+ // user types it on loading page, because the connected client is considered
+ // None type, and so the peek key event is not held here.
+ // To derisk the regression in other platform, and to prioritize the fix
+ // on Lacros, we conditionally do not check whether the connected client
+ // is None type for Lacros only. We should remove this soon.
+ if (filtered && !HasInputMethodResult()
+#if !BUILDFLAG(IS_CHROMEOS_LACROS)
+ && !IsTextInputTypeNone()
+#endif
+ ) {
ime_filtered_key_event_ = std::move(*event);
return ui::EventDispatchDetails();
}
@@ -376,8 +434,9 @@ void InputMethodAuraLinux::OnCommit(const std::u16string& text) {
if (!is_sync_mode_ && !IsTextInputTypeNone()) {
ui::KeyEvent event =
ime_filtered_key_event_.has_value()
- ? *ime_filtered_key_event_
+ ? std::move(*ime_filtered_key_event_)
: ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, 0);
+ ime_filtered_key_event_.reset();
ui::EventDispatchDetails details = DispatchImeFilteredKeyPressEvent(&event);
if (details.target_destroyed || details.dispatcher_destroyed ||
event.stopped_propagation()) {
@@ -443,8 +502,9 @@ void InputMethodAuraLinux::OnPreeditUpdate(
return;
ui::KeyEvent event =
ime_filtered_key_event_.has_value()
- ? *ime_filtered_key_event_
+ ? std::move(*ime_filtered_key_event_)
: ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, 0);
+ ime_filtered_key_event_.reset();
ui::EventDispatchDetails details = DispatchImeFilteredKeyPressEvent(&event);
if (details.target_destroyed || details.dispatcher_destroyed ||
event.stopped_propagation()) {
diff --git a/chromium/ui/base/ime/linux/input_method_auralinux.h b/chromium/ui/base/ime/linux/input_method_auralinux.h
index 5118102b902..9aa424dc7dc 100644
--- a/chromium/ui/base/ime/linux/input_method_auralinux.h
+++ b/chromium/ui/base/ime/linux/input_method_auralinux.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/component_export.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/input_method_base.h"
#include "ui/base/ime/linux/linux_input_method_context.h"
@@ -83,7 +83,7 @@ class COMPONENT_EXPORT(UI_BASE_IME_LINUX) InputMethodAuraLinux
// The last key event that IME is probably in process in
// async-mode.
- base::Optional<ui::KeyEvent> ime_filtered_key_event_;
+ absl::optional<ui::KeyEvent> ime_filtered_key_event_;
std::u16string result_text_;
diff --git a/chromium/ui/base/ime/linux/input_method_auralinux_unittest.cc b/chromium/ui/base/ime/linux/input_method_auralinux_unittest.cc
index f62edbede72..52d57c5d0b5 100644
--- a/chromium/ui/base/ime/linux/input_method_auralinux_unittest.cc
+++ b/chromium/ui/base/ime/linux/input_method_auralinux_unittest.cc
@@ -17,6 +17,7 @@
#include "ui/base/ime/linux/fake_input_method_context.h"
#include "ui/base/ime/linux/linux_input_method_context_factory.h"
#include "ui/events/event.h"
+#include "ui/events/keycodes/dom/dom_code.h"
namespace ui {
namespace {
@@ -68,11 +69,11 @@ class LinuxInputMethodContextForTesting : public LinuxInputMethodContext {
void SetEatKey(bool eat_key) { eat_key_ = eat_key; }
void AddCommitAction(const std::string& text) {
- actions_.push_back(base::ASCIIToUTF16("C:" + text));
+ actions_.push_back(u"C:" + base::ASCIIToUTF16(text));
}
void AddCompositionUpdateAction(const std::string& text) {
- actions_.push_back(base::ASCIIToUTF16("U:" + text));
+ actions_.push_back(u"U:" + base::ASCIIToUTF16(text));
}
void AddCompositionStartAction() { actions_.push_back(u"S"); }
@@ -467,32 +468,65 @@ TEST_F(InputMethodAuraLinuxTest, IBusPinyinTest) {
}
// crbug.com/463491
-TEST_F(InputMethodAuraLinuxTest, DeadKeyTest) {
- context_simple_->SetSyncMode(true);
- context_simple_->SetEatKey(true);
-
- std::unique_ptr<TextInputClientForTesting> client(
- new TextInputClientForTesting(TEXT_INPUT_TYPE_NONE));
- input_method_auralinux_->SetFocusedTextInputClient(client.get());
- input_method_auralinux_->OnTextInputTypeChanged(client.get());
+void DeadKeyTest(TextInputType text_input_type,
+ InputMethodAuraLinux* input_method_auralinux,
+ LinuxInputMethodContextForTesting* context,
+ TestResult* test_result) {
+ context->SetSyncMode(true);
+ context->SetEatKey(true);
+
+ auto client = std::make_unique<TextInputClientForTesting>(text_input_type);
+ input_method_auralinux->SetFocusedTextInputClient(client.get());
+ input_method_auralinux->OnTextInputTypeChanged(client.get());
+
+ constexpr int32_t kCombiningGraveAccent = 0x0300;
+ {
+ KeyEvent dead_key(
+ ET_KEY_PRESSED, VKEY_OEM_4, ui::DomCode::BRACKET_LEFT,
+ /* flags= */ 0,
+ DomKey::DeadKeyFromCombiningCharacter(kCombiningGraveAccent),
+ base::TimeTicks());
+ input_method_auralinux->DispatchKeyEvent(&dead_key);
+ }
- KeyEvent dead_key(ET_KEY_PRESSED, VKEY_OEM_7, 0);
- dead_key.set_character(L'\'');
- input_method_auralinux_->DispatchKeyEvent(&dead_key);
+ // Do not filter release key event.
+ context->SetEatKey(false);
+ {
+ KeyEvent dead_key(
+ ET_KEY_RELEASED, VKEY_OEM_4, ui::DomCode::BRACKET_LEFT,
+ /* flags= */ 0,
+ DomKey::DeadKeyFromCombiningCharacter(kCombiningGraveAccent),
+ base::TimeTicks());
+ input_method_auralinux->DispatchKeyEvent(&dead_key);
+ }
// The single quote key is muted.
- test_result_->ExpectAction("keydown:222");
- test_result_->Verify();
+ test_result->ExpectAction("keydown:219");
+ test_result->ExpectAction("keyup:219");
+ test_result->Verify();
- context_simple_->AddCommitAction("X");
+ // Reset to filter press key again.
+ context->SetEatKey(true);
+
+ context->AddCommitAction("X");
KeyEvent key(ET_KEY_PRESSED, VKEY_A, 0);
key.set_character(L'a');
- input_method_auralinux_->DispatchKeyEvent(&key);
+ input_method_auralinux->DispatchKeyEvent(&key);
// The following A key generates the accent key: á.
- test_result_->ExpectAction("keydown:65");
- test_result_->ExpectAction("keypress:88");
- test_result_->Verify();
+ test_result->ExpectAction("keydown:65");
+ test_result->ExpectAction("keypress:88");
+ test_result->Verify();
+}
+
+TEST_F(InputMethodAuraLinuxTest, DeadKeyTest) {
+ DeadKeyTest(TEXT_INPUT_TYPE_TEXT, input_method_auralinux_, context_,
+ test_result_);
+}
+
+TEST_F(InputMethodAuraLinuxTest, DeadKeySimpleContextTest) {
+ DeadKeyTest(TEXT_INPUT_TYPE_NONE, input_method_auralinux_, context_simple_,
+ test_result_);
}
TEST_F(InputMethodAuraLinuxTest, MultiCommitsTest) {
diff --git a/chromium/ui/base/ime/mock_input_method.h b/chromium/ui/base/ime/mock_input_method.h
index 6fdd6306826..0ed0143661e 100644
--- a/chromium/ui/base/ime/mock_input_method.h
+++ b/chromium/ui/base/ime/mock_input_method.h
@@ -5,7 +5,6 @@
#ifndef UI_BASE_IME_MOCK_INPUT_METHOD_H_
#define UI_BASE_IME_MOCK_INPUT_METHOD_H_
-#include <string>
#include "base/compiler_specific.h"
#include "base/component_export.h"
diff --git a/chromium/ui/base/ime/mojom/ime_types.mojom b/chromium/ui/base/ime/mojom/ime_types.mojom
index 0c04bbfa900..8c6c22ed137 100644
--- a/chromium/ui/base/ime/mojom/ime_types.mojom
+++ b/chromium/ui/base/ime/mojom/ime_types.mojom
@@ -58,6 +58,7 @@ enum ImeTextSpanType {
kSuggestion,
kMisspellingSuggestion,
kAutocorrect,
+ kGrammarSuggestion,
};
// This enum represents the thickness of an underline segment of text,
diff --git a/chromium/ui/base/ime/mojom/ime_types_mojom_traits.cc b/chromium/ui/base/ime/mojom/ime_types_mojom_traits.cc
index e09781c80e8..36a77cd74f6 100644
--- a/chromium/ui/base/ime/mojom/ime_types_mojom_traits.cc
+++ b/chromium/ui/base/ime/mojom/ime_types_mojom_traits.cc
@@ -209,6 +209,8 @@ EnumTraits<ui::mojom::ImeTextSpanType, ui::ImeTextSpan::Type>::ToMojom(
return ui::mojom::ImeTextSpanType::kMisspellingSuggestion;
case ui::ImeTextSpan::Type::kAutocorrect:
return ui::mojom::ImeTextSpanType::kAutocorrect;
+ case ui::ImeTextSpan::Type::kGrammarSuggestion:
+ return ui::mojom::ImeTextSpanType::kGrammarSuggestion;
}
NOTREACHED();
@@ -232,6 +234,9 @@ bool EnumTraits<ui::mojom::ImeTextSpanType, ui::ImeTextSpan::Type>::FromMojom(
case ui::mojom::ImeTextSpanType::kAutocorrect:
*out = ui::ImeTextSpan::Type::kAutocorrect;
return true;
+ case ui::mojom::ImeTextSpanType::kGrammarSuggestion:
+ *out = ui::ImeTextSpan::Type::kGrammarSuggestion;
+ return true;
}
NOTREACHED();
diff --git a/chromium/ui/base/ime/mojom/text_input_state.mojom b/chromium/ui/base/ime/mojom/text_input_state.mojom
index cba3427a944..1e847b6e562 100644
--- a/chromium/ui/base/ime/mojom/text_input_state.mojom
+++ b/chromium/ui/base/ime/mojom/text_input_state.mojom
@@ -19,6 +19,10 @@ struct ImeTextSpanInfo {
// This structure represents the current editing state.
struct TextInputState {
+ // Identifier for the currently focused input field, or 0 if there is no
+ // focus. This identifier is unique for nodes within the same document.
+ int32 node_id = 0;
+
// Type of the input field.
ui.mojom.TextInputType type = ui.mojom.TextInputType.NONE;
diff --git a/chromium/ui/base/ime/text_input_client.cc b/chromium/ui/base/ime/text_input_client.cc
index 2fb370e85e7..bbdd0dce461 100644
--- a/chromium/ui/base/ime/text_input_client.cc
+++ b/chromium/ui/base/ime/text_input_client.cc
@@ -9,4 +9,20 @@ namespace ui {
TextInputClient::~TextInputClient() {
}
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+absl::optional<GrammarFragment> TextInputClient::GetGrammarFragment(
+ const gfx::Range& range) {
+ return absl::nullopt;
+}
+
+bool TextInputClient::ClearGrammarFragments(const gfx::Range& range) {
+ return false;
+}
+
+bool TextInputClient::AddGrammarFragments(
+ const std::vector<GrammarFragment>& fragments) {
+ return false;
+}
+#endif
+
} // namespace ui
diff --git a/chromium/ui/base/ime/text_input_client.h b/chromium/ui/base/ime/text_input_client.h
index e9a5e3724b9..62252d73c33 100644
--- a/chromium/ui/base/ime/text_input_client.h
+++ b/chromium/ui/base/ime/text_input_client.h
@@ -15,11 +15,12 @@
#include "base/component_export.h"
#include "base/i18n/rtl.h"
-#include "base/optional.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/ime/composition_text.h"
+#include "ui/base/ime/grammar_fragment.h"
#include "ui/base/ime/input_method_delegate.h"
#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
@@ -136,6 +137,11 @@ class COMPONENT_EXPORT(UI_BASE_IME) TextInputClient {
// If there is selection, then the selection bounds will be returned.
virtual gfx::Rect GetCaretBounds() const = 0;
+ // Returns the bounds of the rectangle which encloses the selection region.
+ // Bounds are in the screen coordinates. An empty value should be returned if
+ // there is not any selection or this function is not implemented.
+ virtual gfx::Rect GetSelectionBoundingBox() const = 0;
+
// Retrieves the composition character boundary rectangle in the universal
// screen coordinates in DIP (Density Independent Pixel).
// The |index| is zero-based index of character position in composition text.
@@ -260,6 +266,21 @@ class COMPONENT_EXPORT(UI_BASE_IME) TextInputClient {
// Returns true if the operation was successful. If |range| is invalid, then
// no modifications are made and this function returns false.
virtual bool SetAutocorrectRange(const gfx::Range& range) = 0;
+
+ // Returns the grammar fragment which contains |range|. If non-existent,
+ // returns an empty Fragment.
+ virtual absl::optional<GrammarFragment> GetGrammarFragment(
+ const gfx::Range& range);
+
+ // Clears all the grammar fragments in |range|, returns whether the operation
+ // is successful. Should return true if the there is no fragment in the range.
+ virtual bool ClearGrammarFragments(const gfx::Range& range);
+
+ // Adds new grammar markers according to |fragments|. Clients should show
+ // some visual indications such as underlining. Returns whether the operation
+ // is successful.
+ virtual bool AddGrammarFragments(
+ const std::vector<GrammarFragment>& fragments);
#endif
#if defined(OS_WIN)
@@ -269,8 +290,8 @@ class COMPONENT_EXPORT(UI_BASE_IME) TextInputClient {
// editable element. This is used to report the layout bounds of the text
// input control to TSF on Windows.
virtual void GetActiveTextInputControlLayoutBounds(
- base::Optional<gfx::Rect>* control_bounds,
- base::Optional<gfx::Rect>* selection_bounds) = 0;
+ absl::optional<gfx::Rect>* control_bounds,
+ absl::optional<gfx::Rect>* selection_bounds) = 0;
// Notifies accessibility about active composition. This API is currently
// only defined for TSF which is available only on Windows
// https://docs.microsoft.com/en-us/windows/desktop/api/UIAutomationCore/
diff --git a/chromium/ui/base/ime/text_input_mode.h b/chromium/ui/base/ime/text_input_mode.h
index 742c5713645..e547112abfa 100644
--- a/chromium/ui/base/ime/text_input_mode.h
+++ b/chromium/ui/base/ime/text_input_mode.h
@@ -25,4 +25,4 @@ enum TextInputMode {
} // namespace ui
-#endif // UI_BASE_IME_TEXT_INPUT_TYPE_H_
+#endif // UI_BASE_IME_TEXT_INPUT_MODE_H_
diff --git a/chromium/ui/base/ime/utf_offset.cc b/chromium/ui/base/ime/utf_offset.cc
index 7991f6bf21f..873b3f6305b 100644
--- a/chromium/ui/base/ime/utf_offset.cc
+++ b/chromium/ui/base/ime/utf_offset.cc
@@ -11,29 +11,29 @@
namespace ui {
-base::Optional<size_t> Utf16OffsetFromUtf8Offset(base::StringPiece text,
+absl::optional<size_t> Utf16OffsetFromUtf8Offset(base::StringPiece text,
size_t utf8_offset) {
if (utf8_offset > text.length())
- return base::nullopt;
+ return absl::nullopt;
// TODO(hidehiko): Update not to depend on UTF8ToUTF16 to avoid
// unnecessary memory allocation.
std::u16string converted;
if (!base::UTF8ToUTF16(text.data(), utf8_offset, &converted))
- return base::nullopt;
+ return absl::nullopt;
return converted.length();
}
-base::Optional<size_t> Utf8OffsetFromUtf16Offset(base::StringPiece16 text,
+absl::optional<size_t> Utf8OffsetFromUtf16Offset(base::StringPiece16 text,
size_t utf16_offset) {
if (utf16_offset > text.length())
- return base::nullopt;
+ return absl::nullopt;
// TODO(hidehiko): Update not to depend on UTF16ToUTF8 to avoid
// unnecessary memory allocation.
std::string converted;
if (!base::UTF16ToUTF8(text.data(), utf16_offset, &converted))
- return base::nullopt;
+ return absl::nullopt;
return converted.length();
}
diff --git a/chromium/ui/base/ime/utf_offset.h b/chromium/ui/base/ime/utf_offset.h
index fc2ce21d4bc..7e5fbd53884 100644
--- a/chromium/ui/base/ime/utf_offset.h
+++ b/chromium/ui/base/ime/utf_offset.h
@@ -6,8 +6,8 @@
#define UI_BASE_IME_UTF_OFFSET_H_
#include "base/component_export.h"
-#include "base/optional.h"
#include "base/strings/string_piece_forward.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace ui {
@@ -15,14 +15,14 @@ namespace ui {
// Returns nullopt if the given offset is invalid (not at a valid boundary
// or out of range).
COMPONENT_EXPORT(UI_BASE)
-base::Optional<size_t> Utf16OffsetFromUtf8Offset(base::StringPiece text,
+absl::optional<size_t> Utf16OffsetFromUtf8Offset(base::StringPiece text,
size_t utf8_offset);
// Given UTF16 string and its valid offset, returns the offset in UTF8.
// Returns nullopt if the given offset is invalid (not at a valid boundary
// or out of range).
COMPONENT_EXPORT(UI_BASE)
-base::Optional<size_t> Utf8OffsetFromUtf16Offset(base::StringPiece16 text,
+absl::optional<size_t> Utf8OffsetFromUtf16Offset(base::StringPiece16 text,
size_t utf16_offset);
} // namespace ui
diff --git a/chromium/ui/base/ime/utf_offset_unittest.cc b/chromium/ui/base/ime/utf_offset_unittest.cc
index cf0a6aeb03f..6b67e6689dd 100644
--- a/chromium/ui/base/ime/utf_offset_unittest.cc
+++ b/chromium/ui/base/ime/utf_offset_unittest.cc
@@ -7,9 +7,9 @@
#include <string>
#include "base/logging.h"
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace ui {
namespace {
@@ -18,61 +18,61 @@ TEST(UtfOffsetTest, Utf16OffsetFromUtf8Offset) {
constexpr struct {
const char* str;
size_t offset;
- base::Optional<size_t> expect;
+ absl::optional<size_t> expect;
} kTestCases[] = {
// 1 byte letters.
{u8"ab", 0, 0},
{u8"ab", 1, 1},
{u8"ab", 2, 2},
- {u8"ab", 3, base::nullopt},
+ {u8"ab", 3, absl::nullopt},
// 2 byte letters. \u03A9=\xCE\xA9 is greek OMEGA.
{u8"\u03A9\u03A9", 0, 0},
- {u8"\u03A9\u03A9", 1, base::nullopt},
+ {u8"\u03A9\u03A9", 1, absl::nullopt},
{u8"\u03A9\u03A9", 2, 1},
- {u8"\u03A9\u03A9", 3, base::nullopt},
+ {u8"\u03A9\u03A9", 3, absl::nullopt},
{u8"\u03A9\u03A9", 4, 2},
- {u8"\u03A9\u03A9", 5, base::nullopt},
+ {u8"\u03A9\u03A9", 5, absl::nullopt},
// 3 byte letters. \u3042=\xE3\x81\x82 is Japanese "A".
{u8"\u3042\u3042", 0, 0},
- {u8"\u3042\u3042", 1, base::nullopt},
- {u8"\u3042\u3042", 2, base::nullopt},
+ {u8"\u3042\u3042", 1, absl::nullopt},
+ {u8"\u3042\u3042", 2, absl::nullopt},
{u8"\u3042\u3042", 3, 1},
- {u8"\u3042\u3042", 4, base::nullopt},
- {u8"\u3042\u3042", 5, base::nullopt},
+ {u8"\u3042\u3042", 4, absl::nullopt},
+ {u8"\u3042\u3042", 5, absl::nullopt},
{u8"\u3042\u3042", 6, 2},
- {u8"\u3042\u3042", 7, base::nullopt},
+ {u8"\u3042\u3042", 7, absl::nullopt},
// 4 byte letters. \U0001F3B7=\xF0\x9F\x8E\xB7 is "SAXOPHONE" emoji.
// Note that a surrogate pair advances by 2 in UTF16.
{u8"\U0001F3B7\U0001F3B7", 0, 0},
- {u8"\U0001F3B7\U0001F3B7", 1, base::nullopt},
- {u8"\U0001F3B7\U0001F3B7", 2, base::nullopt},
- {u8"\U0001F3B7\U0001F3B7", 3, base::nullopt},
+ {u8"\U0001F3B7\U0001F3B7", 1, absl::nullopt},
+ {u8"\U0001F3B7\U0001F3B7", 2, absl::nullopt},
+ {u8"\U0001F3B7\U0001F3B7", 3, absl::nullopt},
{u8"\U0001F3B7\U0001F3B7", 4, 2},
- {u8"\U0001F3B7\U0001F3B7", 5, base::nullopt},
- {u8"\U0001F3B7\U0001F3B7", 6, base::nullopt},
- {u8"\U0001F3B7\U0001F3B7", 7, base::nullopt},
+ {u8"\U0001F3B7\U0001F3B7", 5, absl::nullopt},
+ {u8"\U0001F3B7\U0001F3B7", 6, absl::nullopt},
+ {u8"\U0001F3B7\U0001F3B7", 7, absl::nullopt},
{u8"\U0001F3B7\U0001F3B7", 8, 4},
- {u8"\U0001F3B7\U0001F3B7", 9, base::nullopt},
+ {u8"\U0001F3B7\U0001F3B7", 9, absl::nullopt},
// Mix case.
{u8"a\u03A9b\u3042c\U0001F3B7d", 0, 0},
{u8"a\u03A9b\u3042c\U0001F3B7d", 1, 1},
- {u8"a\u03A9b\u3042c\U0001F3B7d", 2, base::nullopt},
+ {u8"a\u03A9b\u3042c\U0001F3B7d", 2, absl::nullopt},
{u8"a\u03A9b\u3042c\U0001F3B7d", 3, 2},
{u8"a\u03A9b\u3042c\U0001F3B7d", 4, 3},
- {u8"a\u03A9b\u3042c\U0001F3B7d", 5, base::nullopt},
- {u8"a\u03A9b\u3042c\U0001F3B7d", 6, base::nullopt},
+ {u8"a\u03A9b\u3042c\U0001F3B7d", 5, absl::nullopt},
+ {u8"a\u03A9b\u3042c\U0001F3B7d", 6, absl::nullopt},
{u8"a\u03A9b\u3042c\U0001F3B7d", 7, 4},
{u8"a\u03A9b\u3042c\U0001F3B7d", 8, 5},
- {u8"a\u03A9b\u3042c\U0001F3B7d", 9, base::nullopt},
- {u8"a\u03A9b\u3042c\U0001F3B7d", 10, base::nullopt},
- {u8"a\u03A9b\u3042c\U0001F3B7d", 11, base::nullopt},
+ {u8"a\u03A9b\u3042c\U0001F3B7d", 9, absl::nullopt},
+ {u8"a\u03A9b\u3042c\U0001F3B7d", 10, absl::nullopt},
+ {u8"a\u03A9b\u3042c\U0001F3B7d", 11, absl::nullopt},
{u8"a\u03A9b\u3042c\U0001F3B7d", 12, 7},
{u8"a\u03A9b\u3042c\U0001F3B7d", 13, 8},
- {u8"a\u03A9b\u3042c\U0001F3B7d", 14, base::nullopt},
+ {u8"a\u03A9b\u3042c\U0001F3B7d", 14, absl::nullopt},
};
for (const auto& test_case : kTestCases) {
@@ -86,34 +86,34 @@ TEST(UtfOffsetTest, Utf8OffsetFromUtf16Offset) {
constexpr struct {
const char16_t* str;
size_t offset;
- base::Optional<size_t> expect;
+ absl::optional<size_t> expect;
} kTestCases[] = {
// 1 byte letters.
{u"ab", 0, 0},
{u"ab", 1, 1},
{u"ab", 2, 2},
- {u"ab", 3, base::nullopt},
+ {u"ab", 3, absl::nullopt},
// 2 byte letters.
{u"\u03A9\u03A9", 0, 0},
{u"\u03A9\u03A9", 1, 2},
{u"\u03A9\u03A9", 2, 4},
- {u"\u03A9\u03A9", 3, base::nullopt},
+ {u"\u03A9\u03A9", 3, absl::nullopt},
// 3 byte letters.
{u"\u3042\u3042", 0, 0},
{u"\u3042\u3042", 1, 3},
{u"\u3042\u3042", 2, 6},
- {u"\u3042\u3042", 3, base::nullopt},
+ {u"\u3042\u3042", 3, absl::nullopt},
// 4 byte letters = surrogate pairs.
{u"\U0001F3B7\U0001F3B7", 0, 0},
- {u"\U0001F3B7\U0001F3B7", 1, base::nullopt},
+ {u"\U0001F3B7\U0001F3B7", 1, absl::nullopt},
{u"\U0001F3B7\U0001F3B7", 2, 4},
- {u"\U0001F3B7\U0001F3B7", 3, base::nullopt},
+ {u"\U0001F3B7\U0001F3B7", 3, absl::nullopt},
{u"\U0001F3B7\U0001F3B7", 4, 8},
- {u"\U0001F3B7\U0001F3B7", 5, base::nullopt},
- {u"\U0001F3B7\U0001F3B7", 6, base::nullopt},
+ {u"\U0001F3B7\U0001F3B7", 5, absl::nullopt},
+ {u"\U0001F3B7\U0001F3B7", 6, absl::nullopt},
// Mix case.
{u"a\u03A9b\u3042c\U0001F3B7d", 0, 0},
@@ -122,10 +122,10 @@ TEST(UtfOffsetTest, Utf8OffsetFromUtf16Offset) {
{u"a\u03A9b\u3042c\U0001F3B7d", 3, 4},
{u"a\u03A9b\u3042c\U0001F3B7d", 4, 7},
{u"a\u03A9b\u3042c\U0001F3B7d", 5, 8},
- {u"a\u03A9b\u3042c\U0001F3B7d", 6, base::nullopt},
+ {u"a\u03A9b\u3042c\U0001F3B7d", 6, absl::nullopt},
{u"a\u03A9b\u3042c\U0001F3B7d", 7, 12},
{u"a\u03A9b\u3042c\U0001F3B7d", 8, 13},
- {u"a\u03A9b\u3042c\U0001F3B7d", 9, base::nullopt},
+ {u"a\u03A9b\u3042c\U0001F3B7d", 9, absl::nullopt},
};
for (const auto& test_case : kTestCases) {
diff --git a/chromium/ui/base/ime/win/imm32_manager.h b/chromium/ui/base/ime/win/imm32_manager.h
index d876eca1ec3..d1069bf34c5 100644
--- a/chromium/ui/base/ime/win/imm32_manager.h
+++ b/chromium/ui/base/ime/win/imm32_manager.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_BASE_IME_WIN_IMM32_MANAGER_H
-#define UI_BASE_IME_WIN_IMM32_MANAGER_H
+#ifndef UI_BASE_IME_WIN_IMM32_MANAGER_H_
+#define UI_BASE_IME_WIN_IMM32_MANAGER_H_
#include <windows.h>
@@ -307,4 +307,4 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) IMM32Manager {
} // namespace ui
-#endif // UI_BASE_IME_WIN_IMM32_MANAGER_H
+#endif // UI_BASE_IME_WIN_IMM32_MANAGER_H_
diff --git a/chromium/ui/base/ime/win/input_method_win_imm32.h b/chromium/ui/base/ime/win/input_method_win_imm32.h
index b9ec2f5ddbb..cd2334758bd 100644
--- a/chromium/ui/base/ime/win/input_method_win_imm32.h
+++ b/chromium/ui/base/ime/win/input_method_win_imm32.h
@@ -7,7 +7,6 @@
#include <windows.h>
-#include <string>
#include "base/compiler_specific.h"
#include "base/component_export.h"
diff --git a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h
index 68521961907..9fd1207d78d 100644
--- a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h
+++ b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_BASE_IME_WIN_ON_SCREEN_KEYBOARD_DISPLAY_MANAGER_TAP_TIP_H_
-#define UI_BASE_IME_WIN_ON_SCREEN_KEYBOARD_DISPLAY_MANAGER_TAP_TIP_H_
+#ifndef UI_BASE_IME_WIN_ON_SCREEN_KEYBOARD_DISPLAY_MANAGER_TAB_TIP_H_
+#define UI_BASE_IME_WIN_ON_SCREEN_KEYBOARD_DISPLAY_MANAGER_TAB_TIP_H_
#include <string>
@@ -60,4 +60,4 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN)
} // namespace ui
-#endif // UI_BASE_IME_WIN_ON_SCREEN_KEYBOARD_DISPLAY_MANAGER_TAP_TIP_H_
+#endif // UI_BASE_IME_WIN_ON_SCREEN_KEYBOARD_DISPLAY_MANAGER_TAB_TIP_H_
diff --git a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_unittest.cc b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_unittest.cc
index 6a4a9a6dc77..2416843b487 100644
--- a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_unittest.cc
+++ b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_unittest.cc
@@ -4,6 +4,7 @@
#include <wrl/event.h>
+#include <memory>
#include <string>
#include "base/files/file_path.h"
@@ -112,13 +113,11 @@ class OnScreenKeyboardTest : public ::testing::Test {
: task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {}
std::unique_ptr<OnScreenKeyboardDisplayManagerTabTip> CreateTabTip() {
- return std::unique_ptr<OnScreenKeyboardDisplayManagerTabTip>(
- new OnScreenKeyboardDisplayManagerTabTip(nullptr));
+ return std::make_unique<OnScreenKeyboardDisplayManagerTabTip>(nullptr);
}
std::unique_ptr<OnScreenKeyboardDisplayManagerInputPane> CreateInputPane() {
- return std::unique_ptr<OnScreenKeyboardDisplayManagerInputPane>(
- new OnScreenKeyboardDisplayManagerInputPane(nullptr));
+ return std::make_unique<OnScreenKeyboardDisplayManagerInputPane>(nullptr);
}
void WaitForEventsWithTimeDelay(int64_t time_delta_ms = 10) {
diff --git a/chromium/ui/base/ime/win/tsf_bridge.cc b/chromium/ui/base/ime/win/tsf_bridge.cc
index 73e528641e8..a4d9ab04d1a 100644
--- a/chromium/ui/base/ime/win/tsf_bridge.cc
+++ b/chromium/ui/base/ime/win/tsf_bridge.cc
@@ -112,6 +112,10 @@ class TSFBridgeImpl : public TSFBridge {
// An ITfThreadMgr object to be used in focus and document management.
Microsoft::WRL::ComPtr<ITfThreadMgr> thread_manager_;
+ // An ITfInputProcessorProfiles object to be used to get current language
+ // locale profile.
+ Microsoft::WRL::ComPtr<ITfInputProcessorProfiles> input_processor_profiles_;
+
// A map from TextInputType to an editable document for TSF. We use multiple
// TSF documents that have different InputScopes and TSF attributes based on
// the TextInputType associated with the target document. For a TextInputType
@@ -138,6 +142,9 @@ class TSFBridgeImpl : public TSFBridge {
// Handle to ITfKeyTraceEventSink.
DWORD key_trace_sink_cookie_ = 0;
+ // Handle to ITfLanguageProfileNotifySink
+ DWORD language_profile_cookie_ = 0;
+
DISALLOW_COPY_AND_ASSIGN(TSFBridgeImpl);
};
@@ -153,6 +160,11 @@ TSFBridgeImpl::~TSFBridgeImpl() {
if (SUCCEEDED(thread_manager_->QueryInterface(IID_PPV_ARGS(&source)))) {
source->UnadviseSink(key_trace_sink_cookie_);
}
+ Microsoft::WRL::ComPtr<ITfSource> language_source;
+ if (SUCCEEDED(input_processor_profiles_->QueryInterface(
+ IID_PPV_ARGS(&language_source)))) {
+ language_source->UnadviseSink(language_profile_cookie_);
+ }
}
for (TSFDocumentMap::iterator it = tsf_document_map_.begin();
@@ -177,8 +189,16 @@ HRESULT TSFBridgeImpl::Initialize() {
return S_OK; // shouldn't return error code in this case.
}
- HRESULT hr = ::CoCreateInstance(CLSID_TF_ThreadMgr, nullptr, CLSCTX_ALL,
- IID_PPV_ARGS(&thread_manager_));
+ HRESULT hr =
+ ::CoCreateInstance(CLSID_TF_InputProcessorProfiles, nullptr, CLSCTX_ALL,
+ IID_PPV_ARGS(&input_processor_profiles_));
+ if (FAILED(hr)) {
+ DVLOG(1) << "Failed to create InputProcessorProfiles instance.";
+ return hr;
+ }
+
+ hr = ::CoCreateInstance(CLSID_TF_ThreadMgr, nullptr, CLSCTX_ALL,
+ IID_PPV_ARGS(&thread_manager_));
if (FAILED(hr)) {
DVLOG(1) << "Failed to create ThreadManager instance.";
return hr;
@@ -432,6 +452,22 @@ HRESULT TSFBridgeImpl::CreateDocumentManager(TSFTextStore* text_store,
return hr;
}
+ Microsoft::WRL::ComPtr<ITfSource> language_source;
+ hr =
+ input_processor_profiles_->QueryInterface(IID_PPV_ARGS(&language_source));
+ if (FAILED(hr)) {
+ DVLOG(1) << "Failed to get source_ITfInputProcessorProfiles.";
+ return hr;
+ }
+
+ hr = language_source->AdviseSink(IID_ITfLanguageProfileNotifySink,
+ static_cast<ITfTextEditSink*>(text_store),
+ &language_profile_cookie_);
+ if (FAILED(hr)) {
+ DVLOG(1) << "AdviseSink for language profile notify sink failed.";
+ return hr;
+ }
+
if (*source_cookie == TF_INVALID_COOKIE) {
DVLOG(1) << "The result of cookie is invalid.";
return E_FAIL;
diff --git a/chromium/ui/base/ime/win/tsf_event_router.h b/chromium/ui/base/ime/win/tsf_event_router.h
index 6107c59994d..7b822898759 100644
--- a/chromium/ui/base/ime/win/tsf_event_router.h
+++ b/chromium/ui/base/ime/win/tsf_event_router.h
@@ -8,7 +8,6 @@
#include <msctf.h>
#include <wrl/client.h>
-#include <set>
#include "base/callback.h"
#include "base/compiler_specific.h"
diff --git a/chromium/ui/base/ime/win/tsf_text_store.cc b/chromium/ui/base/ime/win/tsf_text_store.cc
index b0968cc0d12..5e152181451 100644
--- a/chromium/ui/base/ime/win/tsf_text_store.cc
+++ b/chromium/ui/base/ime/win/tsf_text_store.cc
@@ -90,6 +90,8 @@ HRESULT TSFTextStore::QueryInterface(REFIID iid, void** result) {
*result = static_cast<ITextStoreACP*>(this);
} else if (iid == IID_ITfContextOwnerCompositionSink) {
*result = static_cast<ITfContextOwnerCompositionSink*>(this);
+ } else if (iid == IID_ITfLanguageProfileNotifySink) {
+ *result = static_cast<ITfLanguageProfileNotifySink*>(this);
} else if (iid == IID_ITfTextEditSink) {
*result = static_cast<ITfTextEditSink*>(this);
} else if (iid == IID_ITfKeyTraceEventSink) {
@@ -194,8 +196,8 @@ HRESULT TSFTextStore::GetScreenExt(TsViewCookie view_cookie, RECT* rect) {
// {0, 0, 0, 0} means that the document rect is not currently displayed.
SetRect(rect, 0, 0, 0, 0);
- base::Optional<gfx::Rect> result_rect;
- base::Optional<gfx::Rect> tmp_rect;
+ absl::optional<gfx::Rect> result_rect;
+ absl::optional<gfx::Rect> tmp_rect;
// If the EditContext is active, then fetch the layout bounds from
// the active EditContext, else get it from the focused element's
// bounding client rect.
@@ -328,8 +330,8 @@ HRESULT TSFTextStore::GetTextExt(TsViewCookie view_cookie,
// indicates a last character's one.
// TODO(IME): add tests for scenario that left position is bigger than right
// position.
- base::Optional<gfx::Rect> result_rect;
- base::Optional<gfx::Rect> tmp_opt_rect;
+ absl::optional<gfx::Rect> result_rect;
+ absl::optional<gfx::Rect> tmp_opt_rect;
const uint32_t start_pos = acp_start - composition_start_;
const uint32_t end_pos = acp_end - composition_start_;
// If there is an active EditContext, then fetch the layout bounds from it.
@@ -864,6 +866,17 @@ HRESULT TSFTextStore::OnEndComposition(ITfCompositionView* composition_view) {
return S_OK;
}
+HRESULT TSFTextStore::OnLanguageChange(LANGID langid, BOOL* pfAccept) {
+ *pfAccept = TRUE;
+ return S_OK;
+}
+
+HRESULT TSFTextStore::OnLanguageChanged() {
+ if (text_input_client_)
+ text_input_client_->OnInputMethodChanged();
+ return S_OK;
+}
+
HRESULT TSFTextStore::OnKeyTraceDown(WPARAM wParam, LPARAM lParam) {
// fire the event right away if we're in composition
if (has_composition_range_) {
diff --git a/chromium/ui/base/ime/win/tsf_text_store.h b/chromium/ui/base/ime/win/tsf_text_store.h
index e0f0219e31f..7a700692c2f 100644
--- a/chromium/ui/base/ime/win/tsf_text_store.h
+++ b/chromium/ui/base/ime/win/tsf_text_store.h
@@ -102,6 +102,7 @@ class TextInputClient;
class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFTextStore
: public ITextStoreACP,
public ITfContextOwnerCompositionSink,
+ public ITfLanguageProfileNotifySink,
public ITfKeyTraceEventSink,
public ITfTextEditSink {
public:
@@ -217,6 +218,10 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFTextStore
IFACEMETHODIMP OnEndComposition(
ITfCompositionView* composition_view) override;
+ // ITfLanguageProfileNotifySink:
+ IFACEMETHODIMP OnLanguageChange(LANGID langid, BOOL* pfAccept) override;
+ IFACEMETHODIMP OnLanguageChanged() override;
+
// ITfTextEditSink:
IFACEMETHODIMP OnEndEdit(ITfContext* context,
TfEditCookie read_only_edit_cookie,
diff --git a/chromium/ui/base/ime/win/tsf_text_store_unittest.cc b/chromium/ui/base/ime/win/tsf_text_store_unittest.cc
index ef9b1fa3510..77132609652 100644
--- a/chromium/ui/base/ime/win/tsf_text_store_unittest.cc
+++ b/chromium/ui/base/ime/win/tsf_text_store_unittest.cc
@@ -48,6 +48,7 @@ class MockTextInputClient : public TextInputClient {
MOCK_CONST_METHOD0(GetTextInputFlags, int());
MOCK_CONST_METHOD0(CanComposeInline, bool());
MOCK_CONST_METHOD0(GetCaretBounds, gfx::Rect());
+ MOCK_CONST_METHOD0(GetSelectionBoundingBox, gfx::Rect());
MOCK_CONST_METHOD2(GetCompositionCharacterBounds, bool(uint32_t, gfx::Rect*));
MOCK_CONST_METHOD0(HasCompositionText, bool());
MOCK_CONST_METHOD0(GetFocusReason, ui::TextInputClient::FocusReason());
@@ -72,8 +73,8 @@ class MockTextInputClient : public TextInputClient {
MOCK_METHOD3(SetActiveCompositionForAccessibility,
void(const gfx::Range&, const std::u16string&, bool));
MOCK_METHOD2(GetActiveTextInputControlLayoutBounds,
- void(base::Optional<gfx::Rect>* control_bounds,
- base::Optional<gfx::Rect>* selection_bounds));
+ void(absl::optional<gfx::Rect>* control_bounds,
+ absl::optional<gfx::Rect>* selection_bounds));
};
class MockInputMethodDelegate : public internal::InputMethodDelegate {
diff --git a/chromium/ui/base/interaction/OWNERS b/chromium/ui/base/interaction/OWNERS
new file mode 100644
index 00000000000..f8cdc78782f
--- /dev/null
+++ b/chromium/ui/base/interaction/OWNERS
@@ -0,0 +1,2 @@
+dfried@chromium.org
+collinbaker@chromium.org
diff --git a/chromium/ui/base/interaction/README.md b/chromium/ui/base/interaction/README.md
new file mode 100644
index 00000000000..26d96148063
--- /dev/null
+++ b/chromium/ui/base/interaction/README.md
@@ -0,0 +1,401 @@
+# Elements and Interaction Sequences
+
+This folder contains primitives for locating named elements in different
+application windows as well as following specific sequences of user interactions
+with the UI. It is designed to support things like User Education Tutorials and
+interactive UI testing, and to work with multiple UI presentation frameworks.
+
+See the [Supported Frameworks](#Supported%20Frameworks) section for a list of
+currently-supported frameworks.
+
+[TOC]
+
+## Named elements
+
+Named elements are the fundamental building blocks of these systems. Each
+supported framework must define how a UI element can be assigned an
+[ElementIdentifier](/ui/base/interaction/element_identifier.h) which its
+[framework implementation](#Framework%20implementation) must be able to read.
+A UI element with a non-null `ElementIdentifier` assigned to it is known as a
+*named element*.
+
+Each `ElementIdentifier` contains a globally unique opaque handle, with its
+underlying value based on the address of a block of memory allocated at compile
+time.
+
+Two named elements with the same identifier are not necessarily equivalent. In
+an application with multiple primary windows (such as a browser with several
+windows and a PWA open), each primary window and all of its secondary UI - menus,
+dialogs, bubbles, etc. - are represented by a single `ElementContext`. Like
+identifiers, contexts are opaque handles that are unique to each primary window.
+To get the context associated with a UI element or window, you will need to call
+a method specific to your framework; see
+[the relevant section](#2.%20Define%20how%20`ElementContext`%20works%20in%20your%20framework)
+below.
+
+`ElementIdentifier` and `ElementContext` both support the methods one might
+expect from a handle or opaque pointer:
+* Assignment (`=`)
+* Equality (`==`, `!=`)
+* Ordering (`<`) - for use in `std::set` and `std::map`
+* Boolean value (`!` and ```explicit operator bool```)
+* Conversion to and from an integer type (`intptr_t`) - for platforms written in
+ languages that don't support pointers
+
+The only falsy/null/zero value is the default-constructed value. No guarantees
+are made about the ordering produced by the `<` operator; only that there is
+one.
+
+### Creating `ElementIdentifier` values for your application
+
+You will want to create named constants representing each identifier you want to
+use in your code. These constants are defined using macros found in
+[element_identifier.h](/ui/base/interaction/element_identifier.h).
+
+Each declaration creates a compile-time constant that can be copied and used
+anywhere in your application - they are valid from the time your application
+starts up until it exits.
+
+Furthermore, every `ElementIdentifier` you declare in code will either be
+default-constructed (and therefore null), or be assigned a copy of one of these
+compile-time constants. You should _never_ construct an `ElementIdentifier` or
+assign a value from anything other than another `ElementIdentifier`.
+
+To create a public, unique `ElementIdentifier` value in a global scope:
+``` cpp
+// This goes in the .h file:
+DECLARE_ELEMENT_IDENTIFIER_VALUE(kMyIdentifierName);
+
+// This goes in the .cc file:
+DEFINE_ELEMENT_IDENTIFIER_VALUE(kMyIdentifierName);
+```
+To create a class member that is a unique identifier, use:
+``` cpp
+// This declares a unique identifier, MyClass::kClassMemberIdentifier. You could
+// also make the identifier protected or private if you wanted.
+class MyClass {
+ public:
+ DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kClassMemberIdentifier);
+};
+
+// This goes in the .cc file:
+DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(MyClass, kClassMemberIdentifier);
+```
+And finally, if you want to create an identifier that's local to a .cc file or
+class method, there is a single-line declaration available, as shown in these
+examples:
+``` cpp
+// This declares a module-local identifier. The anonymous namespace is optional
+// (though recommended) as kModuleLocalIdentifier will also be marked 'static'.
+namespace {
+DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kModuleLocalIdentifier);
+}
+
+// This declares a method-local identifier.
+/* static */ ui::ElementIdentifier MyClass::GetIdentifier() {
+ DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kMethodLocalIdentifier);
+ return kMethodLocalIdentifier;
+}
+```
+Please note that since all `ElementIdentifier`s created using these macros are
+constexpr/compile-time constants, copies of these values can be used outside of
+their originating classes or modules - the value of the `ElementIdentifier` is
+valid anywhere in the application.
+
+## UI Elements and element events
+
+[`ElementTracker`](/ui/base/interaction/element_tracker.h) is a global singleton
+object that allows you to:
+* Retrieve a visible element or elements from a particular context by identifier
+* Register for callbacks when elements with a given identifier and context
+ become visible
+* Register for callbacks when elements with a given identifier and context
+ become hidden or are destroyed
+* Register for callbacks when the user interacts with an element with a given
+ identifier and context (known as _activation_)
+
+`TrackedElement`, a polymorphic class defined in
+[`element_tracker.h`](/ui/base/interaction/element_tracker.h), represents a
+platform-agnostic UI element with an identifier and context. There must be a 1:1
+correspondence between a visible named UI element and an
+`TrackedElement`; the `TrackedElement` is what is passed to
+callbacks when the UI element is shown, hidden, or activated.
+
+Each framework has its own derived version of `TrackedElement` that may
+provide additional information about the element. If you know what platform the
+element is from you may use the `AsA()` template method to dynamically downcast
+to the platform-specific element type. If you are working in an environment with
+multiple presentation frameworks, you can use the `IsA()` method to determine if
+the element is of the expected type.
+
+Here is an example that shows some of the functionality of `ElementTracker` and
+`TrackedElement`. Note that you must specify the `ElementContext` in
+which you are listening:
+``` cpp
+void ListenForShowEvent(ui::ElementIdentifier id, ui::ElementContext context) {
+ auto callback =
+ base::BindRepeating(&MyClass::OnElementShown, base::Unretained(this)));
+ subscription_ = ui::ElementTracker::GetElementTracker()
+ ->AddElementShownCallback(id, context, callback);
+}
+
+void OnElementShown(ui::TrackedElement* element) {
+// Technically you don't need the IsA() call here, since AsA() returns null if
+// the object is the wrong type.
+if (element->IsA<views::TrackedElementViews>()) {
+ views::View* const view =
+ element->AsA<views::TrackedElementViews>()->view();
+ // Do something with the view that was shown here.
+}
+```
+## Defining and following user interaction sequences
+
+The `InteractionSequence` class provides a way to describe a sequence of
+interactions between the application and the user (real or simulated). Sequences
+are useful for e.g. creating user education tutorials guiding the user through
+the steps of using a new feature, or for simulating user input during
+interaction testing.
+
+Each sequence consists of a series of steps of the following types:
+* **Shown** - a UI element becomes visible to the user
+* **Activated** - the user clics on or otherwise interacts with the UI element
+* **Hidden** - a UI element stops being visible to the user
+
+These are equivalent to the corresponding events provided by `ElementTracker`.
+All of the steps must be followed in order, or the sequence is _aborted_.
+Callbacks may be registered at the start and end of each step, and for when the
+sequence completes or aborts.
+
+Events not in the sequence (other UI elements appearing, focus changes, mouse
+hover, scroll) are ignored unless they result in a required UI element being
+dismissed (such as if a dialog or menu is closed).
+
+To create an interaction sequence, use a `InteractionSequence::Builder`. To add
+steps to the builder, use an `InteractionSequence::StepBuilder`, or call a
+convenience method like `InitialElement()`. Here is an example that expects the
+user to interact with a feature entry point and then displays a help bubble on
+the resulting dialog:
+
+``` cpp
+initial_element =
+ ElementTracker::GetFirstMatchingElement(kFeatureEntryPointID, context());
+sequence_ = InteractionSequence::Builder()
+ .SetCompletedCallback(base::BindOnce(
+ &MyClass::OnSequenceComplete,
+ base::Unretained(this)))
+ .AddStep(InteractionSequence::InitialElement(initial_element))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(initial_element->identifier())
+ .SetType(StepType::kActivated)
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(kFeatureDialogID)
+ .SetType(StepType::kShown)
+ .SetStartCallback(&MyClass::ShowHelpBubble, base::Unretained(this))
+ .Build())
+ .Build();
+sequence_->Start();
+```
+
+### Interaction steps
+
+Each `Step` has properties that can be set via its `StepBuilder`:
+* **Type** - whether this is a show, activate, or hide step
+* **Element ID** - the identifier of the element involved in the step
+* **Must be visible at start** - the element must be visible at the start of the
+ step or else the sequence is aborted
+* **Must remain visible** - the element must remain visible until the next step
+ begins; not compatible with **hidden** steps
+* **Start callback** - called as soon as the step is started
+* **End callback** - called as soon as the next step is started, or the sequence
+ aborts or completes
+
+Of these, only **Type** and **Element ID** are required. If you do not specify
+whether the element must be visible at start or remain visible, default values
+will be assigned according to the type of step. All callbacks are optional.
+
+Instead of using `StepBuilder`, for the initial step you can call
+`InteractionSequence::InitialElement()`. This creates a default **shown** step
+for an element that is already visible; it expects the element to be visible
+when `Start()` is called or the sequence will abort. You may pass optional
+step start and end callbacks to `InitialElement()`; these are useful for
+displaying an initial prompt to the user (in the case of a tutorial).
+
+There is an additional method on `StepBuilder`, `SetContext()`, but it is only
+used by helper methods and for testing. You should instead use
+`Builder::SetContext()` or `InteractionSequence::InitialElement()`. There is
+currently no support for cross-context sequences and setting conflicting
+contexts in a sequence is an error and will crash if DCHECK is enabled.
+
+### Step callbacks
+
+Each step callback (start or end) has three parameters:
+* **Element** - the element involved in the step; null if the element is not
+ available (i.e. was hidden before the callback could be called)
+* **Identifier** - the `ElementIdentifier` associated with the step, which is
+ always valid even if the element is null
+* **Type** - the step type; **shown**, **activated**, or **hidden**
+
+The **element** can be used to retrieve the UI element in your framework by
+downcasting via `AsA()` - see
+[UI Elements and element events](#UI%20Elements%20and%20element%20events) above.
+
+Typically, when using a sequence to run a tutorial, this will be the code that
+shows or hides a tutorial dialog or prompt. When using the sequence for
+interaction testing, the callback will contain the code to simulate the next
+input to the UI.
+
+### Best practices
+
+In general, it will be pretty obvious how to construct your sequence, because
+you know the steps you need to perform in the UI to get where you want to go.
+However, keep the following in mind:
+* Try to start the sequence with a step generated by `InitialElement()`, keyed
+ to a UI element you know will be visible when the sequence starts.
+* Do not assume the order in which elements will become visible when a surface
+ is shown.
+* Do not assume that interacting with a button or menu item will bring up a
+ resulting surface (another menu, a dialog) _before_ the initial button or
+ menu item disappears.
+
+To elaborate on the third point: it is better to have the following steps in the
+case where a menu item brings up a dialog:
+1. Menu item shown
+2. Menu item activated (does not need to remain visible; default)
+3. Dialog element shown (does not need to be visible at start; default)
+
+If you specify that the menu item must stay visible or that the dialog element
+must be visible at step start, the sequence could fail depending on the order in
+which the presentation framework dismisses the menu and displays the dialog.
+
+However, in the case where you want the user to navigate a series of submenus,
+if the platform supports menu-open-via-hover you may not receive the
+**activated** signal and a sequence like the following might work better:
+1. Menu item shown
+2. Submenu item shown (triggers as soon as the submenu is opened, regardless of
+ how)
+3. Submenu item activated
+4. ...
+
+### Known limitations
+
+* Cannot nest sequences (might be able to in some cases via callbacks)
+* Cannot provide alternate sets of steps in the same sequence
+* Cannot skip ahead (e.g. if the user uses a shortcut key to bypass a menu)
+* Cannot restart steps (e.g. if the user hovers a submenu containing the next
+ element, then un-hovers it, then hovers it again)
+
+All of these can be addressed if a relevant, concrete need is found.
+
+## Supporting additional UI frameworks
+
+If you want to use ElementTracker with a framework that isn't supported yet, you
+must at minimum do the following:
+1. Derive a class from `TrackedElement` representing visual elements in
+ your framework.
+2. Determine how `ElementContext`s are defined in your framework.
+3. Implement code to create and register your derived element objects with
+ `ElementTracker` when UI elements become visible to the user, send events
+ when they are activated by the user (however you choose to define
+ "activation"), and to unregister them when the element is no longer visible.
+
+See [`ElementTrackerViews`](/ui/views/interaction/element_tracker_views.h) for
+an example implementation.
+
+When you are done, please add the folder containing the implementation code to
+the [Supported Frameworks](#Supported%20Frameworks) section below.
+
+### 1. Derive a class from `TrackedElement`
+
+When you derive a class from `TrackedElement` to use for your UI
+framework, you are obliged to declare specific metadata in order to support
+`IsA()` and `AsA()`. To do this, add the following to the class definition:
+``` cpp
+class TrackedElementMyPlatform {
+ public:
+ // This provides the required TrackedElement metadata support.
+ DECLARE_ELEMENT_TRACKER_METADATA();
+}
+
+// In the corresponding .cc file:
+DEFINE_ELEMENT_TRACKER_METADATA(TrackedElementMyPlatform)
+```
+You will also be expected to pass an immutable identifier and context into the
+constructor, and if the element object stores a pointer or handle to the
+associated UI element in your framework, that reference should not change for
+the life of the element (and the element should not outlive the corresponding
+framework object).
+
+### 2. Define how `ElementContext` works in your framework
+
+You will need a method to generate an `ElementContext` from a window or UI
+element. The context identifies the primary window associated with the UI, such
+as a browser or PWA window, the taskbar of an operating system's GUI, a file
+browser window, etc. Good candidates are the handle of the primary window or the
+address of the framework object that represents it. The value of the handle must
+not change over the lifetime of that window.
+
+If you do not already have one, you will probably want a helper method that
+finds the primary window given a UI element that might be in secondary UI (such
+as a dialog or menu).
+
+In Views, we use the address of the primary window's `Widget` to construct the
+`ElementContext` and we provide the `ElementTrackerViews::GetContextForView()`
+method to fetch it. We also added the `Widget::GetPrimaryWindowWidget()` helper
+method for finding the primary window.
+
+### 3. Managing the lifetime of your elements and sending events
+
+How your platform manages the lifetime of elements is entirely up to you. You
+could create an `TrackedElement` whenever a named UI element in your
+framework becomes visible to the user, or you could have every UI element
+with an associated `ElementIdentifier` hold a permanent `TrackedElement`.
+
+The one requirement is that a single `TrackedElement` must be associated
+with any named UI element, and must remain associated with that implementation
+as long as the element remains visible.
+
+To register or unregister an element or send activation events, get the
+`ElementTrackerFrameworkDelegate` from the `ElementTracker` class and call the
+appropriate method:
+``` cpp
+auto* const delegate = ui::ElementTracker::GetFrameworkDelegate();
+
+// Register a visible element:
+delegate->NotifyElementShown(my_element);
+
+// Notify that the element was activated by the user:
+delegate->NotifyElementActivated(my_element);
+
+// Unregister the element on hide:
+delegate->NotifyElementHidden(my_element);
+```
+"Activation" requires some special discussion here, as what it means to be
+activated is extremely context-specific. For example:
+* A button is activated when the user clicks it
+* A menu item is activated when the user performs the item's action
+* A browser tab is activated when the user selects the tab with the mouse or
+ keyboard
+
+Activation should be the **default** action that occurs when the user directly
+interacts with that UI element. So for example, the _Back_ button in a browser
+can be clicked to return to the previous page, or long-pressed/dragged to open a
+menu containing a list of previous pages. The single-click is the default
+action, and therefore should be the action that results in
+`NotifyElementActivated()` being called.
+
+How you proxy events from UI elements to calls to
+`ElementTrackerFrameworkDelegate` is entirely up to you. In Views we go through
+a mediator object -
+[`ElementTrackerViews`](ui/views/interaction/element_tracker_views.h) - which
+first maps the `Button`, `MenuItem`, etc. to an `TrackedElementViews`
+before passing that object to the appropriate delegate method.
+
+## Supported Frameworks
+
+The following UI frameworks support `ElementTracker` and `InteractionSequence`.
+Please add additional frameworks to this list as they become supported.
+
+* Views:
+ * [`ElementTrackerViews`](/ui/views/interaction/element_tracker_views.h)
+ * [`InteractionSequenceViews`](/ui/views/interaction/interaction_sequence_views.h)
diff --git a/chromium/ui/base/interaction/element_identifier.cc b/chromium/ui/base/interaction/element_identifier.cc
new file mode 100644
index 00000000000..79c7f755c16
--- /dev/null
+++ b/chromium/ui/base/interaction/element_identifier.cc
@@ -0,0 +1,21 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/interaction/element_identifier.h"
+
+namespace ui {
+
+void PrintTo(ElementIdentifier element_identifier, std::ostream* os) {
+ const internal::ElementIdentifierImpl* impl =
+ reinterpret_cast<const internal::ElementIdentifierImpl*>(
+ element_identifier.raw_value());
+ *os << "ElementIdentifier " << impl << " [" << (impl ? impl->name : "")
+ << "]";
+}
+
+void PrintTo(ElementContext element_context, std::ostream* os) {
+ *os << "ElementContext " << static_cast<const void*>(element_context);
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/interaction/element_identifier.h b/chromium/ui/base/interaction/element_identifier.h
new file mode 100644
index 00000000000..3ff3d581266
--- /dev/null
+++ b/chromium/ui/base/interaction/element_identifier.h
@@ -0,0 +1,258 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_INTERACTION_ELEMENT_IDENTIFIER_H_
+#define UI_BASE_INTERACTION_ELEMENT_IDENTIFIER_H_
+
+#include <stdint.h>
+
+#include <ostream>
+
+#include "base/component_export.h"
+#include "ui/base/class_property.h"
+
+// Overview:
+// ElementIdentifier provides a named opaque value that can be used to identify
+// individual (or potentially groups of) elements in the UI.
+//
+// Unique identifier constants must be both declared and defined. To create a
+// publicly-visible identifier, declare a new unique value in your .h file,
+// with:
+//
+// DECLARE_ELEMENT_IDENTIFIER_VALUE(kMyIdentifierName);
+//
+// In the corresponding .cc file, make sure it is defined:
+//
+// DEFINE_ELEMENT_IDENTIFIER_VALUE(kMyIdentifierName);
+//
+// If you want to add an identifier as a class member, use the following:
+//
+// class MyClass {
+// DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(MyClass, kMyIdentifierName);
+// };
+//
+// Then in the corresponding .cc file, add the following:
+//
+// DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(MyClass, kMyIdentifierValue);
+//
+// If you want to create an identifier local to a .cc file or to a method, you
+// can instead use the following all-in-one declaration:
+//
+// DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kMyIdentifierName);
+//
+// That's it! You can now initialize an ElementIdentifier using this value, or
+// pass it directly to a method:
+//
+// ElementIdentifier my_id = kMyIdentifierName;
+// ElementIdentifier my_id2 = my_id;
+// MyFuncThatTakesAnIdentifier(kMyIdentifierName);
+// MyFuncThatTakesAnIdentifier(my_id2);
+//
+// ElementIdentifier behaves more or less like other mutable primitive types; it
+// is default-constructable (producing a null value) and supports the ==, !=, <,
+// !, and (bool) operators as well as assignment and copy [1]. This means you
+// can use ElementIdentifier as a key in std::set and std::map, and it is safe
+// to use in both DCHECK and test assertions:
+//
+// ElementIdentifier id1;
+// ElementIdentifier id2 = kMyIdentifierName;
+// std::map<ElementIdentifier, int> map;
+// map.emplace(id2, 4);
+// DCHECK(!id1);
+// EXPECT_TRUE(static_cast<bool>(id2));
+// DCHECK_NE(id1, id2);
+// EXPECT_FALSE(base::Contains(map, id1));
+// ASSERT_EQ(4, map[id2]);
+//
+// -----
+//
+// [1] Please note that while operator < will provide a strict ordering, the
+// specific order of two ElementIdentifier constants may vary by build and
+// should not be relied upon; operator < is only provided for compatibility
+// with sorted STL containers.
+
+namespace ui {
+
+namespace internal {
+
+// Defines the underlying value that an ElementIdentifier holds (namely, the
+// address of an instance of this class). Because these objects are only
+// declared statically, the value of an ElementIdentifier is always valid and
+// two ElementIdentifiers are equal if and only if they hold the address of the
+// same instance of this class.
+//
+// Instances of this object are named for debugging/logging purposes only, the
+// value of name() should never be used for any other purpose.
+struct ElementIdentifierImpl {
+ // The name of the identifier; only used in testing via PrintTo().
+ const char* const name;
+};
+
+} // namespace internal
+
+// Holds a globally-unqiue, value-typed identifier from a set of identifiers
+// which can be declared in any static scope using
+// DECLARE_UNIQUE_ELEMENT_VALUE().
+//
+// This type is comparable and supports operator bool and negation, where
+// default-constructed instances have false value and all other values evaluate
+// as true. It can also be used as the key in std::set, std::map, and similar
+// collections.
+class COMPONENT_EXPORT(UI_BASE) ElementIdentifier final {
+ public:
+ // Creates a null identifier.
+ constexpr ElementIdentifier() = default;
+
+ // Avoid this constructor - it is used internally by the
+ // DECLARE_ELEMENT_IDENTIFIER_VALUE() macro.
+ explicit constexpr ElementIdentifier(
+ const internal::ElementIdentifierImpl* provider)
+ : handle_(provider) {}
+
+ constexpr explicit operator bool() const { return handle_ != nullptr; }
+
+ constexpr bool operator!() const { return !handle_; }
+
+ constexpr bool operator==(const ElementIdentifier& other) const {
+ return handle_ == other.handle_;
+ }
+
+ constexpr bool operator!=(const ElementIdentifier& other) const {
+ return handle_ != other.handle_;
+ }
+
+ constexpr bool operator<(const ElementIdentifier& other) const {
+ return handle_ < other.handle_;
+ }
+
+ // Included for interoperability with PropertyHandler. Only works because this
+ // class contains a single pointer, has a trivial destructor, and has no
+ // virtual methods.
+ intptr_t raw_value() const { return reinterpret_cast<intptr_t>(handle_); }
+
+ // Included for interoperability with PropertyHandler. Can be used when
+ // overriding PropertyHandler::AfterPropertyChange() to recover the old
+ // identifier value.
+ static ElementIdentifier FromRawValue(intptr_t value) {
+ return ElementIdentifier(
+ reinterpret_cast<const internal::ElementIdentifierImpl*>(value));
+ }
+
+ private:
+ // The value of the identifier. Because all non-null values point to static
+ // ElementIdentifierImpl objects this can be treated as a value from a set of
+ // unique, opaque handles.
+ const void* handle_ = nullptr;
+};
+
+// The context of an element is unique to the top-level, primary window that the
+// element is associated with. Elements in secondary UI (bubbles, menus,
+// drop-downs, etc.) will be associated with the same context as elements in the
+// primary window itself.
+//
+// The value used should be consistent across a toolkit and unique between
+// primary windows; a memory address or handle of the window object can
+// typically be used (e.g. in Views, we use the address of the primary window's
+// Widget). A zero or null value should always correspond to "no context".
+//
+// Please note that you must consistently use the same pointer or handle type
+// across your framework when creating contexts; because of the vagaries of C++
+// up- and down-casting (especially with multiple inheritance) constructing an
+// ElementContext from different pointer types can produce different results,
+// even for the same underlying object.
+//
+// ElementContext objects are assignable, have boolean value based on whether
+// the underlying value is null, and support operator < for use in maps and
+// sets.
+class COMPONENT_EXPORT(UI_BASE) ElementContext {
+ public:
+ ElementContext() = default;
+
+ template <class T>
+ explicit ElementContext(T* value)
+ : value_(reinterpret_cast<uintptr_t>(value)) {}
+
+ template <class T>
+ explicit ElementContext(T value) : value_(static_cast<uintptr_t>(value)) {}
+
+ explicit operator const void*() const {
+ return reinterpret_cast<const void*>(value_);
+ }
+ explicit operator uintptr_t() const { return value_; }
+ explicit operator intptr_t() const { return static_cast<intptr_t>(value_); }
+ explicit operator bool() const { return value_ != 0; }
+ bool operator!() const { return !value_; }
+ bool operator==(const ElementContext& other) const {
+ return value_ == other.value_;
+ }
+ bool operator!=(const ElementContext& other) const {
+ return value_ != other.value_;
+ }
+ bool operator<(const ElementContext& other) const {
+ return value_ < other.value_;
+ }
+
+ private:
+ uintptr_t value_ = 0;
+};
+
+COMPONENT_EXPORT(UI_BASE)
+extern void PrintTo(ElementIdentifier element_identifier, std::ostream* os);
+
+COMPONENT_EXPORT(UI_BASE)
+extern void PrintTo(ElementContext element_context, std::ostream* os);
+
+// Required for interoperability with PropertyHandler.
+template <>
+class ClassPropertyCaster<ui::ElementIdentifier> {
+ public:
+ static int64_t ToInt64(ui::ElementIdentifier x) { return x.raw_value(); }
+ static ui::ElementIdentifier FromInt64(int64_t x) {
+ return ui::ElementIdentifier::FromRawValue(x);
+ }
+};
+
+} // namespace ui
+
+// Declaring identifiers outside a scope:
+
+// Use this code in the .h file to declare a new identifier.
+#define DECLARE_ELEMENT_IDENTIFIER_VALUE(IdentifierName) \
+ extern const ui::internal::ElementIdentifierImpl IdentifierName##Provider; \
+ constexpr ui::ElementIdentifier IdentifierName(&IdentifierName##Provider)
+
+// Use this code in the .cc file to define a new identifier.
+#define DEFINE_ELEMENT_IDENTIFIER_VALUE(IdentifierName) \
+ constexpr ui::internal::ElementIdentifierImpl IdentifierName##Provider { \
+#IdentifierName \
+ }
+
+// Declaring identifiers in a class:
+
+// Use this code in your class declaration in its .h file to declare an
+// identifier that is scoped to your class.
+#define DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(ClassName, IdentifierName) \
+ static constexpr ui::internal::ElementIdentifierImpl \
+ IdentifierName##Provider{#ClassName "::" #IdentifierName}; \
+ static constexpr ui::ElementIdentifier IdentifierName { \
+ &IdentifierName##Provider \
+ }
+
+// Use this code in your class definition .cc file to define the member
+// variables
+#define DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(ClassName, IdentifierName) \
+ constexpr ui::internal::ElementIdentifierImpl \
+ ClassName::IdentifierName##Provider; \
+ constexpr ui::ElementIdentifier ClassName::IdentifierName
+
+// Declaring local identifiers in functions, class methods, or local to a .cc
+// file:
+
+// Use this code to declare a local identifier in a function body.
+#define DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(IdentifierName) \
+ static constexpr ui::internal::ElementIdentifierImpl \
+ IdentifierName##Provider{#IdentifierName}; \
+ constexpr ui::ElementIdentifier IdentifierName(&IdentifierName##Provider)
+
+#endif // UI_BASE_INTERACTION_ELEMENT_IDENTIFIER_H_
diff --git a/chromium/ui/base/interaction/element_test_util.cc b/chromium/ui/base/interaction/element_test_util.cc
new file mode 100644
index 00000000000..2670056fcba
--- /dev/null
+++ b/chromium/ui/base/interaction/element_test_util.cc
@@ -0,0 +1,68 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/interaction/element_test_util.h"
+
+#include "base/test/bind.h"
+
+namespace ui {
+
+DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTestFrameworkIdentifier);
+DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kOtherFrameworkIdentifier);
+
+TestElementBase::TestElementBase(ElementIdentifier id, ElementContext context)
+ : TrackedElement(id, context) {}
+
+TestElementBase::~TestElementBase() {
+ Hide();
+}
+
+TestElement::TestElement(ElementIdentifier id, ElementContext context)
+ : TestElementBase(id, context) {}
+
+TestElementOtherFramework::TestElementOtherFramework(ElementIdentifier id,
+ ElementContext context)
+ : TestElementBase(id, context) {}
+
+void TestElementBase::Show() {
+ if (visible_)
+ return;
+ visible_ = true;
+ ElementTracker::GetFrameworkDelegate()->NotifyElementShown(this);
+}
+
+void TestElementBase::Activate() {
+ DCHECK(visible_);
+ ElementTracker::GetFrameworkDelegate()->NotifyElementActivated(this);
+}
+
+void TestElementBase::Hide() {
+ if (!visible_)
+ return;
+ visible_ = false;
+ ElementTracker::GetFrameworkDelegate()->NotifyElementHidden(this);
+}
+
+// static
+TrackedElement::FrameworkIdentifier TestElement::GetFrameworkIdentifier() {
+ return kTestFrameworkIdentifier;
+}
+
+TrackedElement::FrameworkIdentifier
+TestElement::GetInstanceFrameworkIdentifier() const {
+ return kTestFrameworkIdentifier;
+}
+
+// static
+TrackedElement::FrameworkIdentifier
+TestElementOtherFramework::GetFrameworkIdentifier() {
+ return kOtherFrameworkIdentifier;
+}
+
+TrackedElement::FrameworkIdentifier
+TestElementOtherFramework::GetInstanceFrameworkIdentifier() const {
+ return kOtherFrameworkIdentifier;
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/interaction/element_test_util.h b/chromium/ui/base/interaction/element_test_util.h
new file mode 100644
index 00000000000..389d6057ff8
--- /dev/null
+++ b/chromium/ui/base/interaction/element_test_util.h
@@ -0,0 +1,55 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_INTERACTION_ELEMENT_TEST_UTIL_H_
+#define UI_BASE_INTERACTION_ELEMENT_TEST_UTIL_H_
+
+#include "ui/base/interaction/element_identifier.h"
+#include "ui/base/interaction/element_tracker.h"
+
+namespace ui {
+
+// Provides a platform-less pseudoelement for use in ElementTracker and
+// InteractionSequence tests.
+class TestElementBase : public TrackedElement {
+ public:
+ TestElementBase(ElementIdentifier id, ElementContext context);
+ ~TestElementBase() override;
+
+ // Simulate the element shown event.
+ void Show();
+
+ // Simulate the element activated event.
+ void Activate();
+
+ // Simulate the element hidden event.
+ void Hide();
+
+ private:
+ bool visible_ = false;
+};
+
+// Provides a platform-less test element in a fictional UI framework.
+class TestElement : public TestElementBase {
+ public:
+ TestElement(ElementIdentifier id, ElementContext context);
+ static FrameworkIdentifier GetFrameworkIdentifier();
+ FrameworkIdentifier GetInstanceFrameworkIdentifier() const override;
+};
+
+// Provides a platform-less test element in a fictional UI framework distinct
+// from `TestElement`.
+class TestElementOtherFramework : public TestElementBase {
+ public:
+ TestElementOtherFramework(ElementIdentifier id, ElementContext context);
+ static FrameworkIdentifier GetFrameworkIdentifier();
+ FrameworkIdentifier GetInstanceFrameworkIdentifier() const override;
+};
+
+// Convenience typedef for unique pointers to test elements.
+using TestElementPtr = std::unique_ptr<TestElementBase>;
+
+} // namespace ui
+
+#endif // UI_BASE_INTERACTION_ELEMENT_TEST_UTIL_H_
diff --git a/chromium/ui/base/interaction/element_tracker.cc b/chromium/ui/base/interaction/element_tracker.cc
new file mode 100644
index 00000000000..d32d7de3098
--- /dev/null
+++ b/chromium/ui/base/interaction/element_tracker.cc
@@ -0,0 +1,333 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/interaction/element_tracker.h"
+
+#include <algorithm>
+#include <iterator>
+#include <list>
+#include <map>
+
+#include "base/auto_reset.h"
+#include "base/bind.h"
+#include "base/containers/contains.h"
+#include "ui/base/interaction/element_identifier.h"
+
+namespace ui {
+
+class ElementTracker::ElementData {
+ public:
+ ElementData(ElementTracker* tracker,
+ ElementIdentifier id,
+ ElementContext context)
+ : identifier_(id), context_(context) {
+ auto removal_callback =
+ base::BindRepeating(&ElementTracker::MaybeCleanup,
+ base::Unretained(tracker), base::Unretained(this));
+ shown_callbacks_.set_removal_callback(removal_callback);
+ activated_callbacks_.set_removal_callback(removal_callback);
+ hidden_callbacks_.set_removal_callback(removal_callback);
+ }
+
+ ~ElementData() = default;
+
+ ElementIdentifier identifier() const { return identifier_; }
+ ElementContext context() const { return context_; }
+
+ bool empty() const {
+ return elements_.empty() && shown_callbacks_.empty() &&
+ activated_callbacks_.empty() && hidden_callbacks_.empty();
+ }
+
+ size_t num_elements() const {
+ // Guaranteed O(1) in C++11 and later.
+ return elements_.size();
+ }
+
+ const std::list<TrackedElement*>& elements() const { return elements_; }
+
+ Subscription AddElementShownCallback(Callback callback) {
+ return shown_callbacks_.Add(callback);
+ }
+
+ Subscription AddElementActivatedCallback(Callback callback) {
+ return activated_callbacks_.Add(callback);
+ }
+
+ Subscription AddElementHiddenCallback(Callback callback) {
+ return hidden_callbacks_.Add(callback);
+ }
+
+ void NotifyElementShown(TrackedElement* element) {
+ DCHECK_EQ(identifier().raw_value(), element->identifier().raw_value());
+ DCHECK_EQ(static_cast<intptr_t>(context()),
+ static_cast<intptr_t>(element->context()));
+ const auto it = elements_.insert(elements_.end(), element);
+ const bool success = element_lookup_.emplace(element, it).second;
+ DCHECK(success);
+ shown_callbacks_.Notify(element);
+ }
+
+ void NotifyElementActivated(TrackedElement* element) {
+ DCHECK(base::Contains(element_lookup_, element));
+ activated_callbacks_.Notify(element);
+ }
+
+ void NotifyElementHidden(TrackedElement* element) {
+ const auto it = element_lookup_.find(element);
+ DCHECK(it != element_lookup_.end());
+ elements_.erase(it->second);
+ element_lookup_.erase(it);
+ hidden_callbacks_.Notify(element);
+ }
+
+ private:
+ const ElementIdentifier identifier_;
+ const ElementContext context_;
+
+ // Holds elements in the order they were added to this data block, so that the
+ // first element or the first element that matches some criterion can be
+ // easily found.
+ std::list<TrackedElement*> elements_;
+
+ // Provides a fast lookup into `elements_` by element for checking and
+ // removal. Since there could be many elements (e.g. tabs in a browser) we
+ // don't want removing a series of them to turn into an O(n^2) operation.
+ std::map<TrackedElement*, std::list<TrackedElement*>::iterator>
+ element_lookup_;
+
+ base::RepeatingCallbackList<void(TrackedElement*)> shown_callbacks_;
+ base::RepeatingCallbackList<void(TrackedElement*)> activated_callbacks_;
+ base::RepeatingCallbackList<void(TrackedElement*)> hidden_callbacks_;
+};
+
+// Ensures that ElementData objects get cleaned up, but only after all callbacks
+// have returned. Otherwise a subscription could be canceled during a callback,
+// resulting in the ElementData and the callback list being deleted before the
+// callback has returned.
+class ElementTracker::GarbageCollector {
+ public:
+ // Represents a call stack frame in which garbage collection can happen.
+ // Garbage collection doesn't actually occur until all nested Frames are
+ // destructed.
+ class Frame {
+ public:
+ explicit Frame(GarbageCollector* gc) : gc_(gc) {
+ gc_->IncrementFrameCount();
+ }
+
+ ~Frame() { gc_->DecrementFrameCount(); }
+
+ void Add(ElementData* data) { gc_->AddCandidate(data); }
+
+ private:
+ GarbageCollector* const gc_;
+ };
+
+ explicit GarbageCollector(ElementTracker* tracker) : tracker_(tracker) {}
+
+ private:
+ void AddCandidate(ElementData* data) {
+ DCHECK_GE(frame_count_, 0);
+ candidates_.insert(data);
+ }
+
+ void IncrementFrameCount() { ++frame_count_; }
+
+ void DecrementFrameCount() {
+ DCHECK_GE(frame_count_, 0);
+ if (--frame_count_ > 0)
+ return;
+
+ for (ElementData* data : candidates_) {
+ if (data->empty()) {
+ const auto result = tracker_->element_data_.erase(
+ LookupKey(data->identifier(), data->context()));
+ DCHECK(result);
+ }
+ }
+ candidates_.clear();
+ }
+
+ ElementTracker* const tracker_;
+ std::set<ElementData*> candidates_;
+ int frame_count_ = 0;
+};
+
+TrackedElement::TrackedElement(ElementIdentifier id, ElementContext context)
+ : identifier_(id), context_(context) {}
+
+TrackedElement::~TrackedElement() = default;
+
+// static
+ElementTracker* ElementTracker::GetElementTracker() {
+ static base::NoDestructor<ElementTracker> instance;
+ return instance.get();
+}
+
+// static
+ElementTrackerFrameworkDelegate* ElementTracker::GetFrameworkDelegate() {
+ return static_cast<ElementTrackerFrameworkDelegate*>(GetElementTracker());
+}
+
+TrackedElement* ElementTracker::GetUniqueElement(ElementIdentifier id,
+ ElementContext context) {
+ const auto it = element_data_.find(LookupKey(id, context));
+ if (it == element_data_.end() || it->second->num_elements() == 0)
+ return nullptr;
+ DCHECK_EQ(1U, it->second->num_elements());
+ return it->second->elements().front();
+}
+
+TrackedElement* ElementTracker::GetFirstMatchingElement(
+ ElementIdentifier id,
+ ElementContext context) {
+ const auto it = element_data_.find(LookupKey(id, context));
+ if (it == element_data_.end() || it->second->num_elements() == 0)
+ return nullptr;
+ return it->second->elements().front();
+}
+
+ElementTracker::ElementList ElementTracker::GetAllMatchingElements(
+ ElementIdentifier id,
+ ElementContext context) {
+ const auto it = element_data_.find(LookupKey(id, context));
+ ElementList result;
+ if (it != element_data_.end()) {
+ std::copy(it->second->elements().begin(), it->second->elements().end(),
+ std::back_inserter(result));
+ }
+ return result;
+}
+
+bool ElementTracker::IsElementVisible(ElementIdentifier id,
+ ElementContext context) {
+ const auto it = element_data_.find(LookupKey(id, context));
+ return it != element_data_.end() && it->second->num_elements() > 0;
+}
+
+ElementTracker::Subscription ElementTracker::AddElementShownCallback(
+ ElementIdentifier id,
+ ElementContext context,
+ Callback callback) {
+ return GetOrAddElementData(id, context)->AddElementShownCallback(callback);
+}
+
+ElementTracker::Subscription ElementTracker::AddElementActivatedCallback(
+ ElementIdentifier id,
+ ElementContext context,
+ Callback callback) {
+ return GetOrAddElementData(id, context)
+ ->AddElementActivatedCallback(callback);
+}
+
+ElementTracker::Subscription ElementTracker::AddElementHiddenCallback(
+ ElementIdentifier id,
+ ElementContext context,
+ Callback callback) {
+ return GetOrAddElementData(id, context)->AddElementHiddenCallback(callback);
+}
+
+ElementTracker::ElementTracker()
+ : gc_(std::make_unique<GarbageCollector>(this)) {}
+
+ElementTracker::~ElementTracker() {
+ NOTREACHED();
+}
+
+void ElementTracker::NotifyElementShown(TrackedElement* element) {
+ GarbageCollector::Frame gc_frame(gc_.get());
+ DCHECK(!base::Contains(element_to_data_lookup_, element));
+ ElementData* const element_data =
+ GetOrAddElementData(element->identifier(), element->context());
+ element_to_data_lookup_.emplace(element, element_data);
+ element_data->NotifyElementShown(element);
+}
+
+void ElementTracker::NotifyElementActivated(TrackedElement* element) {
+ GarbageCollector::Frame gc_frame(gc_.get());
+ const auto it = element_to_data_lookup_.find(element);
+ DCHECK(it != element_to_data_lookup_.end());
+ it->second->NotifyElementActivated(element);
+}
+
+void ElementTracker::NotifyElementHidden(TrackedElement* element) {
+ GarbageCollector::Frame gc_frame(gc_.get());
+ const auto it = element_to_data_lookup_.find(element);
+ DCHECK(it != element_to_data_lookup_.end());
+ ElementData* const data = it->second;
+ element_to_data_lookup_.erase(it);
+ data->NotifyElementHidden(element);
+ gc_frame.Add(data);
+}
+
+ElementTracker::ElementData* ElementTracker::GetOrAddElementData(
+ ElementIdentifier id,
+ ElementContext context) {
+ const LookupKey key(id, context);
+ auto it = element_data_.find(key);
+ if (it == element_data_.end()) {
+ const auto result = element_data_.emplace(
+ key, std::make_unique<ElementData>(this, id, context));
+ DCHECK(result.second);
+ it = result.first;
+ }
+ return it->second.get();
+}
+
+void ElementTracker::MaybeCleanup(ElementData* data) {
+ GarbageCollector::Frame gc_frame(gc_.get());
+ gc_frame.Add(data);
+}
+
+SafeElementReference::SafeElementReference() = default;
+
+SafeElementReference::SafeElementReference(TrackedElement* element)
+ : element_(element) {
+ Subscribe();
+}
+
+SafeElementReference::SafeElementReference(SafeElementReference&& other)
+ : element_(other.element_) {
+ // Have to rebind instead of moving the subscription since the other
+ // reference's this pointer is bound.
+ Subscribe();
+ other.subscription_ = ElementTracker::Subscription();
+ other.element_ = nullptr;
+}
+
+SafeElementReference& SafeElementReference::operator=(
+ SafeElementReference&& other) {
+ if (&other != this) {
+ element_ = other.element_;
+ // Have to rebind instead of moving the subscription since the other
+ // reference's this pointer is bound.
+ Subscribe();
+ other.subscription_ = ElementTracker::Subscription();
+ other.element_ = nullptr;
+ }
+ return *this;
+}
+
+SafeElementReference::~SafeElementReference() = default;
+
+void SafeElementReference::Subscribe() {
+ if (!element_)
+ return;
+
+ subscription_ = ElementTracker::GetElementTracker()->AddElementHiddenCallback(
+ element_->identifier(), element_->context(),
+ base::BindRepeating(&SafeElementReference::OnElementHidden,
+ base::Unretained(this)));
+}
+
+void SafeElementReference::OnElementHidden(TrackedElement* element) {
+ if (element != element_)
+ return;
+
+ subscription_ = ElementTracker::Subscription();
+ element_ = nullptr;
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/interaction/element_tracker.h b/chromium/ui/base/interaction/element_tracker.h
new file mode 100644
index 00000000000..9be36263248
--- /dev/null
+++ b/chromium/ui/base/interaction/element_tracker.h
@@ -0,0 +1,235 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_INTERACTION_ELEMENT_TRACKER_H_
+#define UI_BASE_INTERACTION_ELEMENT_TRACKER_H_
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "base/callback_list.h"
+#include "base/component_export.h"
+#include "base/gtest_prod_util.h"
+#include "base/no_destructor.h"
+#include "base/notreached.h"
+#include "base/observer_list.h"
+#include "base/observer_list_types.h"
+#include "ui/base/interaction/element_identifier.h"
+
+namespace ui {
+
+// Represents a visible UI element in a platform-agnostic manner.
+//
+// A pointer to this object may be stored after the element becomes visible, but
+// is only valid until the "element hidden" event is called for this element;
+// see `ElementTracker` below. If you want to hold a pointer that will be valid
+// only as long as the element is visible, use a SafeElementReference.
+//
+// You should derive a class for each UI framework whose elements you wish to
+// track. See README.md for information on how to create your own framework
+// implementations.
+class COMPONENT_EXPORT(UI_BASE) TrackedElement {
+ public:
+ // Used by IsA() and AsA() methods to do runtime type-checking.
+ using FrameworkIdentifier = ElementIdentifier;
+
+ virtual ~TrackedElement();
+
+ ElementIdentifier identifier() const { return identifier_; }
+ ElementContext context() const { return context_; }
+
+ // Returns whether this element is a specific subtype - for example, a
+ // views::ViewsTrackedElement.
+ template <typename T>
+ bool IsA() const {
+ return AsA<T>();
+ }
+
+ // Dynamically casts this element to a specific subtype, such as a
+ // views::ViewsTrackedElement, returning null if the element is the
+ // wrong type.
+ template <typename T>
+ T* AsA() {
+ return GetInstanceFrameworkIdentifier() == T::GetFrameworkIdentifier()
+ ? static_cast<T*>(this)
+ : nullptr;
+ }
+
+ // Dynamically casts this element to a specific subtype, such as a
+ // views::ViewsTrackedElement, returning null if the element is the
+ // wrong type. This version converts const objects.
+ template <typename T>
+ const T* AsA() const {
+ return GetInstanceFrameworkIdentifier() == T::GetFrameworkIdentifier()
+ ? static_cast<const T*>(this)
+ : nullptr;
+ }
+
+ protected:
+ TrackedElement(ElementIdentifier identifier, ElementContext context);
+
+ // Override this in derived classes with a unique FrameworkIdentifier.
+ // You must also define a static GetFrameworkIdentifier() method that returns
+ // the same value.
+ virtual FrameworkIdentifier GetInstanceFrameworkIdentifier() const = 0;
+
+ private:
+ // The identifier for this element that will be used by ElementTracker to
+ // retrieve it.
+ const ElementIdentifier identifier_;
+
+ // The context of the element, corresponding to the main window the element is
+ // associated with. See the ElementContext documentation in
+ // element_identifier.h for more information on how to create appropriate
+ // contexts for each UI framework.
+ const ElementContext context_;
+};
+
+// These macros can be used to help define platform-specific subclasses of
+// `TrackedElement`.
+#define DECLARE_ELEMENT_TRACKER_METADATA() \
+ static FrameworkIdentifier GetFrameworkIdentifier(); \
+ FrameworkIdentifier GetInstanceFrameworkIdentifier() const override;
+#define DEFINE_ELEMENT_TRACKER_METADATA(ClassName) \
+ ui::TrackedElement::FrameworkIdentifier \
+ ClassName::GetFrameworkIdentifier() { \
+ DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(k##ClassName##Identifier); \
+ return k##ClassName##Identifier; \
+ } \
+ ui::TrackedElement::FrameworkIdentifier \
+ ClassName::GetInstanceFrameworkIdentifier() const { \
+ return GetFrameworkIdentifier(); \
+ }
+
+// Provides a delegate for UI framework-specific implementations to notify of
+// element tracker events.
+//
+// An element must be visible before events can be sent for that element;
+// NotifyElementHidden() must be called before the element is destroyed or
+// changes context or identifier.
+class COMPONENT_EXPORT(UI_BASE) ElementTrackerFrameworkDelegate {
+ public:
+ virtual void NotifyElementShown(TrackedElement* element) = 0;
+ virtual void NotifyElementActivated(TrackedElement* element) = 0;
+ virtual void NotifyElementHidden(TrackedElement* element) = 0;
+};
+
+// Tracks elements as they become visible, are activated by the user, and
+// eventually become hidden. Tracks only visible elements.
+//
+// NOT THREAD SAFE. Should only be accessed from the main UI thread.
+class COMPONENT_EXPORT(UI_BASE) ElementTracker
+ : ElementTrackerFrameworkDelegate {
+ public:
+ using Callback = base::RepeatingCallback<void(TrackedElement*)>;
+ using Subscription = base::CallbackListSubscription;
+ using ElementList = std::vector<TrackedElement*>;
+
+ // Gets the element tracker to be used by clients to subscribe to and receive
+ // events.
+ static ElementTracker* GetElementTracker();
+
+ // Gets the delegate to be used by specific UI frameworks to send events.
+ static ElementTrackerFrameworkDelegate* GetFrameworkDelegate();
+
+ // Returns either the one element matching the given `id` and `context`, or
+ // null if there are none. Will generate an error if there is more than one
+ // element with `id|`in `context`. Only visible elements are returned.
+ //
+ // Use when you want to verify that there's only one matching element in the
+ // given context.
+ TrackedElement* GetUniqueElement(ElementIdentifier id,
+ ElementContext context);
+
+ // Returns the same result as GetUniqueElement() except that no error is
+ // generated if there is more than one matching element.
+ //
+ // Use when you just need *an* element in the given context, and don't care if
+ // there's more than one.
+ TrackedElement* GetFirstMatchingElement(ElementIdentifier id,
+ ElementContext context);
+
+ // Returns a list of all visible elements with identifier `id` in `context`.
+ // The list may be empty.
+ ElementList GetAllMatchingElements(ElementIdentifier id,
+ ElementContext context);
+
+ // Returns whether an element with identifier `id` in `context` is visible.
+ bool IsElementVisible(ElementIdentifier id, ElementContext context);
+
+ // Adds a callback that will be called whenever an element with identifier
+ // `id` in `context` becomes visible.
+ Subscription AddElementShownCallback(ElementIdentifier id,
+ ElementContext context,
+ Callback callback);
+
+ // Adds a callback that will be called whenever an element with identifier
+ // `id` in `context` is activated by the user.
+ Subscription AddElementActivatedCallback(ElementIdentifier id,
+ ElementContext context,
+ Callback callback);
+
+ // Adds a callback that will be called whenever an element with identifier
+ // `id` in `context` is hidden.
+ //
+ // Note: the TrackedElement* passed to the callback may not remain
+ // valid after the call, even if the same element object in its UI framework
+ // is re-shown (a new TrackedElement may be generated).
+ Subscription AddElementHiddenCallback(ElementIdentifier id,
+ ElementContext context,
+ Callback callback);
+
+ private:
+ friend class base::NoDestructor<ElementTracker>;
+ class ElementData;
+ class GarbageCollector;
+ using LookupKey = std::pair<ElementIdentifier, ElementContext>;
+ FRIEND_TEST_ALL_PREFIXES(ElementTrackerTest, CleanupAfterElementHidden);
+ FRIEND_TEST_ALL_PREFIXES(ElementTrackerTest, CleanupAfterCallbacksRemoved);
+ FRIEND_TEST_ALL_PREFIXES(ElementTrackerTest, HideDuringShowCallback);
+
+ ElementTracker();
+ ~ElementTracker();
+
+ // ElementTrackerFrameworkDelegate:
+ void NotifyElementShown(TrackedElement* element) override;
+ void NotifyElementActivated(TrackedElement* element) override;
+ void NotifyElementHidden(TrackedElement* element) override;
+
+ ElementData* GetOrAddElementData(ElementIdentifier id,
+ ElementContext context);
+
+ void MaybeCleanup(ElementData* data);
+
+ std::map<LookupKey, std::unique_ptr<ElementData>> element_data_;
+ std::map<TrackedElement*, ElementData*> element_to_data_lookup_;
+ std::unique_ptr<GarbageCollector> gc_;
+};
+
+// Holds an TrackedElement reference and nulls it out if the element goes
+// away. In other words, acts as a weak reference for TrackedElements.
+class COMPONENT_EXPORT(UI_BASE) SafeElementReference {
+ public:
+ SafeElementReference();
+ explicit SafeElementReference(TrackedElement* element);
+ SafeElementReference(SafeElementReference&& other);
+ SafeElementReference& operator=(SafeElementReference&& other);
+ ~SafeElementReference();
+
+ TrackedElement* get() { return element_; }
+ explicit operator bool() const { return element_; }
+ bool operator!() const { return !element_; }
+
+ private:
+ void Subscribe();
+ void OnElementHidden(TrackedElement* element);
+
+ ElementTracker::Subscription subscription_;
+ TrackedElement* element_ = nullptr;
+};
+
+} // namespace ui
+
+#endif // UI_BASE_INTERACTION_ELEMENT_TRACKER_H_
diff --git a/chromium/ui/base/interaction/element_tracker_unittest.cc b/chromium/ui/base/interaction/element_tracker_unittest.cc
new file mode 100644
index 00000000000..412b69ae38b
--- /dev/null
+++ b/chromium/ui/base/interaction/element_tracker_unittest.cc
@@ -0,0 +1,554 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/interaction/element_tracker.h"
+
+#include "base/callback_forward.h"
+#include "base/logging.h"
+#include "base/test/bind.h"
+#include "base/test/mock_callback.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/interaction/element_identifier.h"
+#include "ui/base/interaction/element_test_util.h"
+#include "ui/base/interaction/expect_call_in_scope.h"
+
+namespace ui {
+
+namespace {
+
+DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kElementIdentifier1);
+DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kElementIdentifier2);
+const ElementContext kElementContext1(1);
+const ElementContext kElementContext2(2);
+
+} // namespace
+
+TEST(TrackedElementTest, IsATest) {
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ TestElementPtr e2 = std::make_unique<TestElementOtherFramework>(
+ kElementIdentifier1, kElementContext1);
+
+ EXPECT_TRUE(e1->IsA<TestElement>());
+ EXPECT_FALSE(e1->IsA<TestElementOtherFramework>());
+ EXPECT_FALSE(e2->IsA<TestElement>());
+ EXPECT_TRUE(e2->IsA<TestElementOtherFramework>());
+}
+
+TEST(TrackedElementTest, AsATest) {
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier2, kElementContext2);
+ TestElementPtr e2 = std::make_unique<TestElementOtherFramework>(
+ kElementIdentifier2, kElementContext2);
+
+ EXPECT_EQ(e1.get(), e1->AsA<TestElement>());
+ EXPECT_EQ(nullptr, e1->AsA<TestElementOtherFramework>());
+ EXPECT_EQ(nullptr, e2->AsA<TestElement>());
+ EXPECT_EQ(e2.get(), e2->AsA<TestElementOtherFramework>());
+}
+
+TEST(ElementTrackerTest, GetUniqueElement) {
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ TestElementPtr e2 = std::make_unique<TestElementOtherFramework>(
+ kElementIdentifier2, kElementContext1);
+ EXPECT_EQ(nullptr, ElementTracker::GetElementTracker()->GetUniqueElement(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_EQ(nullptr, ElementTracker::GetElementTracker()->GetUniqueElement(
+ kElementIdentifier2, kElementContext1));
+ e1->Show();
+ EXPECT_EQ(e1.get(), ElementTracker::GetElementTracker()->GetUniqueElement(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_EQ(nullptr, ElementTracker::GetElementTracker()->GetUniqueElement(
+ kElementIdentifier2, kElementContext1));
+ e2->Show();
+ EXPECT_EQ(e1.get(), ElementTracker::GetElementTracker()->GetUniqueElement(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_EQ(e2.get(), ElementTracker::GetElementTracker()->GetUniqueElement(
+ kElementIdentifier2, kElementContext1));
+ e1->Hide();
+ EXPECT_EQ(nullptr, ElementTracker::GetElementTracker()->GetUniqueElement(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_EQ(e2.get(), ElementTracker::GetElementTracker()->GetUniqueElement(
+ kElementIdentifier2, kElementContext1));
+ e2->Hide();
+ EXPECT_EQ(nullptr, ElementTracker::GetElementTracker()->GetUniqueElement(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_EQ(nullptr, ElementTracker::GetElementTracker()->GetUniqueElement(
+ kElementIdentifier2, kElementContext1));
+}
+
+TEST(ElementTrackerTest, GetFirstMatchingElement) {
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ TestElementPtr e2 = std::make_unique<TestElementOtherFramework>(
+ kElementIdentifier2, kElementContext1);
+ EXPECT_EQ(nullptr,
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_EQ(nullptr,
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier2, kElementContext1));
+ e1->Show();
+ EXPECT_EQ(e1.get(),
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_EQ(nullptr,
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier2, kElementContext1));
+ e2->Show();
+ EXPECT_EQ(e1.get(),
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_EQ(e2.get(),
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier2, kElementContext1));
+ e1->Hide();
+ EXPECT_EQ(nullptr,
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_EQ(e2.get(),
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier2, kElementContext1));
+ e2->Hide();
+ EXPECT_EQ(nullptr,
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_EQ(nullptr,
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier2, kElementContext1));
+}
+
+TEST(ElementTrackerTest, GetFirstMatchingElementWithMultipleElements) {
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ TestElementPtr e2 = std::make_unique<TestElementOtherFramework>(
+ kElementIdentifier1, kElementContext1);
+ EXPECT_EQ(nullptr,
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier1, kElementContext1));
+ e1->Show();
+ EXPECT_EQ(e1.get(),
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier1, kElementContext1));
+ e2->Show();
+ EXPECT_EQ(e1.get(),
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier1, kElementContext1));
+ e1->Hide();
+ EXPECT_EQ(e2.get(),
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier1, kElementContext1));
+ e1->Show();
+ EXPECT_EQ(e2.get(),
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier1, kElementContext1));
+ e2->Hide();
+ EXPECT_EQ(e1.get(),
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier1, kElementContext1));
+ e1->Hide();
+ EXPECT_EQ(nullptr,
+ ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kElementIdentifier1, kElementContext1));
+}
+
+TEST(ElementTrackerTest, GetAllMatchingElements) {
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ TestElementPtr e2 = std::make_unique<TestElementOtherFramework>(
+ kElementIdentifier1, kElementContext1);
+ ElementTracker::ElementList expected;
+ EXPECT_EQ(expected,
+ ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kElementIdentifier1, kElementContext1));
+ e1->Show();
+ expected = ElementTracker::ElementList{e1.get()};
+ EXPECT_EQ(expected,
+ ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kElementIdentifier1, kElementContext1));
+ e2->Show();
+ expected = ElementTracker::ElementList{e1.get(), e2.get()};
+ EXPECT_EQ(expected,
+ ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kElementIdentifier1, kElementContext1));
+ e1->Hide();
+ expected = ElementTracker::ElementList{e2.get()};
+ EXPECT_EQ(expected,
+ ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kElementIdentifier1, kElementContext1));
+ e1->Show();
+ expected = ElementTracker::ElementList{e2.get(), e1.get()};
+ EXPECT_EQ(expected,
+ ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kElementIdentifier1, kElementContext1));
+ e2->Hide();
+ expected = ElementTracker::ElementList{e1.get()};
+ EXPECT_EQ(expected,
+ ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kElementIdentifier1, kElementContext1));
+ e1->Hide();
+ expected = ElementTracker::ElementList{};
+ EXPECT_EQ(expected,
+ ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kElementIdentifier1, kElementContext1));
+}
+
+TEST(ElementTrackerTest, IsElementVisible) {
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ TestElementPtr e2 = std::make_unique<TestElementOtherFramework>(
+ kElementIdentifier2, kElementContext1);
+ TestElementPtr e3 = std::make_unique<TestElementOtherFramework>(
+ kElementIdentifier1, kElementContext2);
+ EXPECT_FALSE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_FALSE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier2, kElementContext1));
+ EXPECT_FALSE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier1, kElementContext2));
+ e1->Show();
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_FALSE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier2, kElementContext1));
+ EXPECT_FALSE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier1, kElementContext2));
+ e2->Show();
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier2, kElementContext1));
+ EXPECT_FALSE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier1, kElementContext2));
+ e3->Show();
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier2, kElementContext1));
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier1, kElementContext2));
+ e2->Hide();
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_FALSE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier2, kElementContext1));
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier1, kElementContext2));
+ e1->Hide();
+ EXPECT_FALSE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_FALSE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier2, kElementContext1));
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier1, kElementContext2));
+ e3->Hide();
+ EXPECT_FALSE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier1, kElementContext1));
+ EXPECT_FALSE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier2, kElementContext1));
+ EXPECT_FALSE(ElementTracker::GetElementTracker()->IsElementVisible(
+ kElementIdentifier1, kElementContext2));
+}
+
+TEST(ElementTrackerTest, AddElementShownCallback) {
+ UNCALLED_MOCK_CALLBACK(ElementTracker::Callback, callback);
+ auto subscription =
+ ElementTracker::GetElementTracker()->AddElementShownCallback(
+ kElementIdentifier1, kElementContext1, callback.Get());
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ TestElementPtr e2 = std::make_unique<TestElementOtherFramework>(
+ kElementIdentifier2, kElementContext1);
+ TestElementPtr e3 = std::make_unique<TestElementOtherFramework>(
+ kElementIdentifier1, kElementContext2);
+ TestElementPtr e4 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ EXPECT_CALL_IN_SCOPE(callback, Run(e1.get()), e1->Show());
+ e2->Show();
+ e3->Show();
+ e1->Activate();
+ e1->Hide();
+ EXPECT_CALL_IN_SCOPE(callback, Run(e4.get()), e4->Show());
+}
+
+TEST(ElementTrackerTest, AddElementActivatedCallback) {
+ UNCALLED_MOCK_CALLBACK(ElementTracker::Callback, callback);
+ auto subscription =
+ ElementTracker::GetElementTracker()->AddElementActivatedCallback(
+ kElementIdentifier1, kElementContext1, callback.Get());
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ TestElementPtr e2 = std::make_unique<TestElementOtherFramework>(
+ kElementIdentifier2, kElementContext1);
+ TestElementPtr e3 = std::make_unique<TestElementOtherFramework>(
+ kElementIdentifier1, kElementContext2);
+ TestElementPtr e4 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ e1->Show();
+ e2->Show();
+ e3->Show();
+ e4->Show();
+ EXPECT_CALL_IN_SCOPE(callback, Run(e1.get()), e1->Activate());
+ EXPECT_CALL_IN_SCOPE(callback, Run(e4.get()), e4->Activate());
+ EXPECT_CALL_IN_SCOPE(callback, Run(e1.get()), e1->Activate());
+ e2->Activate();
+ e3->Activate();
+}
+
+TEST(ElementTrackerTest, AddElementHiddenCallback) {
+ UNCALLED_MOCK_CALLBACK(ElementTracker::Callback, callback);
+ auto subscription =
+ ElementTracker::GetElementTracker()->AddElementHiddenCallback(
+ kElementIdentifier1, kElementContext1, callback.Get());
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ TestElementPtr e2 = std::make_unique<TestElementOtherFramework>(
+ kElementIdentifier2, kElementContext1);
+ TestElementPtr e3 = std::make_unique<TestElementOtherFramework>(
+ kElementIdentifier1, kElementContext2);
+ TestElementPtr e4 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ e1->Show();
+ e2->Show();
+ e3->Show();
+ e4->Show();
+ e1->Activate();
+ e4->Activate();
+ e2->Hide();
+ EXPECT_CALL_IN_SCOPE(callback, Run(e1.get()), e1->Hide());
+ e3->Hide();
+ EXPECT_CALL_IN_SCOPE(callback, Run(e4.get()), e4->Hide());
+ e1->Show();
+ EXPECT_CALL_IN_SCOPE(callback, Run(e1.get()), e1->Hide());
+}
+
+TEST(ElementTrackerTest, CleanupAfterElementHidden) {
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty());
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ e1->Show();
+ EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size());
+ {
+ UNCALLED_MOCK_CALLBACK(ElementTracker::Callback, callback);
+ auto subscription =
+ ElementTracker::GetElementTracker()->AddElementShownCallback(
+ kElementIdentifier1, kElementContext1, callback.Get());
+ EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size());
+ }
+ e1->Hide();
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty());
+}
+
+TEST(ElementTrackerTest, CleanupAfterCallbacksRemoved) {
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty());
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+
+ // Add element shown callback. An element will be shown transiently during the
+ // subscription.
+ {
+ base::MockCallback<ElementTracker::Callback> callback;
+ EXPECT_CALL(callback, Run).Times(testing::AnyNumber());
+ auto subscription =
+ ElementTracker::GetElementTracker()->AddElementShownCallback(
+ kElementIdentifier1, kElementContext1, callback.Get());
+ EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size());
+ e1->Show();
+ EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size());
+ e1->Hide();
+ EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size());
+ }
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty());
+
+ // Add element activated callback.
+ {
+ base::MockCallback<ElementTracker::Callback> callback;
+ EXPECT_CALL(callback, Run).Times(testing::AnyNumber());
+ auto subscription =
+ ElementTracker::GetElementTracker()->AddElementActivatedCallback(
+ kElementIdentifier1, kElementContext1, callback.Get());
+ EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size());
+ }
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty());
+
+ // Add element hidden callback.
+ {
+ base::MockCallback<ElementTracker::Callback> callback;
+ EXPECT_CALL(callback, Run).Times(testing::AnyNumber());
+ auto subscription =
+ ElementTracker::GetElementTracker()->AddElementHiddenCallback(
+ kElementIdentifier1, kElementContext1, callback.Get());
+ EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size());
+ }
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty());
+
+ // Add and remove multiple callbacks.
+ {
+ base::MockCallback<ElementTracker::Callback> callback;
+ EXPECT_CALL(callback, Run).Times(testing::AnyNumber());
+ auto sub1 = ElementTracker::GetElementTracker()->AddElementShownCallback(
+ kElementIdentifier1, kElementContext1, callback.Get());
+ auto sub2 =
+ ElementTracker::GetElementTracker()->AddElementActivatedCallback(
+ kElementIdentifier1, kElementContext1, callback.Get());
+ auto sub3 = ElementTracker::GetElementTracker()->AddElementHiddenCallback(
+ kElementIdentifier1, kElementContext1, callback.Get());
+ EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size());
+ }
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty());
+}
+
+// The following test specific conditions that could trigger a UAF or cause
+// similar instability due to changing callback lists during callbacks. These
+// tests may fail all or some builds (specifically asan/msan) if the logic is
+// implemented incorrectly.
+
+TEST(ElementTrackerTest, RemoveCallbackDuringRemove) {
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ UNCALLED_MOCK_CALLBACK(ElementTracker::Callback, callback);
+ ElementTracker::Subscription subscription =
+ ElementTracker::GetElementTracker()->AddElementHiddenCallback(
+ e1->identifier(), e1->context(), callback.Get());
+
+ ON_CALL(callback, Run).WillByDefault([&](TrackedElement*) {
+ subscription = ElementTracker::Subscription();
+ });
+
+ e1->Show();
+ EXPECT_CALL_IN_SCOPE(callback, Run(e1.get()), e1->Hide());
+ e1->Show();
+ e1->Hide();
+}
+
+TEST(ElementTrackerTest, RemoveAndThenAddCallbackDuringRemove) {
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ UNCALLED_MOCK_CALLBACK(ElementTracker::Callback, callback);
+ ElementTracker::Subscription subscription =
+ ElementTracker::GetElementTracker()->AddElementHiddenCallback(
+ e1->identifier(), e1->context(), callback.Get());
+
+ ON_CALL(callback, Run).WillByDefault([&](TrackedElement*) {
+ subscription = ElementTracker::Subscription();
+ subscription =
+ ElementTracker::GetElementTracker()->AddElementHiddenCallback(
+ e1->identifier(), e1->context(), callback.Get());
+ });
+ e1->Show();
+ EXPECT_CALL_IN_SCOPE(callback, Run(e1.get()), e1->Hide());
+ e1->Show();
+ EXPECT_CALL_IN_SCOPE(callback, Run(e1.get()), e1->Hide());
+}
+
+TEST(ElementTrackerTest, RemoveAndThenAddDifferentCallbackDuringRemove) {
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ UNCALLED_MOCK_CALLBACK(ElementTracker::Callback, callback);
+ ElementTracker::Subscription subscription =
+ ElementTracker::GetElementTracker()->AddElementHiddenCallback(
+ e1->identifier(), e1->context(), callback.Get());
+
+ ON_CALL(callback, Run).WillByDefault([&](TrackedElement*) {
+ subscription = ElementTracker::Subscription();
+ subscription = ElementTracker::GetElementTracker()->AddElementShownCallback(
+ e1->identifier(), e1->context(), callback.Get());
+ });
+
+ e1->Show();
+ EXPECT_CALL_IN_SCOPE(callback, Run(e1.get()), e1->Hide());
+ EXPECT_CALL_IN_SCOPE(callback, Run(e1.get()), e1->Show());
+ e1->Hide();
+}
+
+TEST(ElementTrackerTest, MultipleCallbacksForSameEvent) {
+ TestElementPtr e1 =
+ std::make_unique<TestElement>(kElementIdentifier1, kElementContext1);
+ UNCALLED_MOCK_CALLBACK(ElementTracker::Callback, callback);
+ UNCALLED_MOCK_CALLBACK(ElementTracker::Callback, callback2);
+ ElementTracker::Subscription subscription =
+ ElementTracker::GetElementTracker()->AddElementHiddenCallback(
+ e1->identifier(), e1->context(), callback.Get());
+ ElementTracker::Subscription subscription2 =
+ ElementTracker::GetElementTracker()->AddElementHiddenCallback(
+ e1->identifier(), e1->context(), callback2.Get());
+
+ e1->Show();
+
+ // Note: these calls are not ordered.
+ EXPECT_CALL(callback, Run(e1.get())).Times(1);
+ EXPECT_CALL(callback2, Run(e1.get())).Times(1);
+ e1->Hide();
+}
+
+TEST(ElementTrackerTest, HideDuringShowCallback) {
+ TestElement e1(kElementIdentifier1, kElementContext1);
+ ElementTracker::Subscription subscription;
+ auto callback = base::BindLambdaForTesting([&](TrackedElement* element) {
+ subscription = ElementTracker::Subscription();
+ e1.Hide();
+ });
+ subscription = ElementTracker::GetElementTracker()->AddElementShownCallback(
+ e1.identifier(), e1.context(), callback);
+ e1.Show();
+
+ // Verify that cleanup still happens after all callbacks return.
+ EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty());
+}
+
+TEST(SafeElementReferenceTest, ElementRemainsVisible) {
+ TestElement e1(kElementIdentifier1, kElementContext1);
+ e1.Show();
+ SafeElementReference ref(&e1);
+ EXPECT_TRUE(ref);
+ EXPECT_FALSE(!ref);
+ EXPECT_EQ(&e1, ref.get());
+ e1.Activate();
+ EXPECT_TRUE(ref);
+ EXPECT_FALSE(!ref);
+ EXPECT_EQ(&e1, ref.get());
+}
+
+TEST(SafeElementReferenceTest, ElementHidden) {
+ TestElement e1(kElementIdentifier1, kElementContext1);
+ e1.Show();
+ SafeElementReference ref(&e1);
+ EXPECT_TRUE(ref);
+ EXPECT_FALSE(!ref);
+ EXPECT_EQ(&e1, ref.get());
+ e1.Hide();
+ EXPECT_FALSE(ref);
+ EXPECT_TRUE(!ref);
+ EXPECT_EQ(nullptr, ref.get());
+}
+
+TEST(SafeElementReferenceTest, MoveConstructor) {
+ TestElement e1(kElementIdentifier1, kElementContext1);
+ e1.Show();
+ std::unique_ptr<SafeElementReference> ref;
+ {
+ SafeElementReference ref2(&e1);
+ ref = std::make_unique<SafeElementReference>(std::move(ref2));
+ }
+ EXPECT_EQ(&e1, ref->get());
+ e1.Hide();
+ EXPECT_EQ(nullptr, ref->get());
+}
+
+TEST(SafeElementReferenceTest, MoveOperator) {
+ TestElement e1(kElementIdentifier1, kElementContext1);
+ e1.Show();
+ SafeElementReference ref;
+ {
+ SafeElementReference ref2(&e1);
+ ref = std::move(ref2);
+ }
+ EXPECT_EQ(&e1, ref.get());
+ e1.Hide();
+ EXPECT_EQ(nullptr, ref.get());
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/interaction/expect_call_in_scope.h b/chromium/ui/base/interaction/expect_call_in_scope.h
new file mode 100644
index 00000000000..a5c81cb9ea3
--- /dev/null
+++ b/chromium/ui/base/interaction/expect_call_in_scope.h
@@ -0,0 +1,56 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_INTERACTION_EXPECT_CALL_IN_SCOPE_H_
+#define UI_BASE_INTERACTION_EXPECT_CALL_IN_SCOPE_H_
+
+#include "base/test/mock_callback.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+// TODO(dfried): move this code to base/test.
+
+// Declares a MockCallback that will cause the current test to fail if called
+// before the first EXPECT_CALL or EXPECT_CALL_IN_SCOPE (see below).
+#define UNCALLED_MOCK_CALLBACK(callback_type, name) \
+ base::MockCallback<callback_type> name; \
+ EXPECT_CALL(name, Run).Times(0)
+
+// Requires that a specific base::MockCallback is called inside a specific block
+// of code, or the current test will fail. `Block` may be a single statement or
+// a block of code enclosed in {}.
+//
+// Syntax for the first two arguments is the same as EXPECT_CALL().
+#define EXPECT_CALL_IN_SCOPE(Name, Call, Block) \
+ EXPECT_CALL(Name, Call).Times(1); \
+ Block; \
+ EXPECT_CALL(Name, Run).Times(0)
+
+// As EXPECT_CALL_IN_SCOPE but expects `Name1` and `Name2` to be called in order
+// in the specified `Block`.
+#define EXPECT_CALLS_IN_SCOPE_2(Name1, Call1, Name2, Call2, Block) \
+ { \
+ testing::InSequence in_sequence; \
+ EXPECT_CALL(Name1, Call1).Times(1); \
+ EXPECT_CALL(Name2, Call2).Times(1); \
+ } \
+ Block; \
+ EXPECT_CALL(Name1, Run).Times(0); \
+ EXPECT_CALL(Name2, Run).Times(0)
+
+// As EXPECT_CALL_IN_SCOPE but expects `Name1`, `Name2`, and `Name3` to be
+// called in order in the specified `Block`.
+#define EXPECT_CALLS_IN_SCOPE_3(Name1, Call1, Name2, Call2, Name3, Call3, \
+ Block) \
+ { \
+ testing::InSequence in_sequence; \
+ EXPECT_CALL(Name1, Call1).Times(1); \
+ EXPECT_CALL(Name2, Call2).Times(1); \
+ EXPECT_CALL(Name3, Call3).Times(1); \
+ } \
+ Block; \
+ EXPECT_CALL(Name1, Run).Times(0); \
+ EXPECT_CALL(Name2, Run).Times(0); \
+ EXPECT_CALL(Name3, Run).Times(0)
+
+#endif // UI_BASE_INTERACTION_EXPECT_CALL_IN_SCOPE_H_
diff --git a/chromium/ui/base/interaction/interaction_sequence.cc b/chromium/ui/base/interaction/interaction_sequence.cc
new file mode 100644
index 00000000000..1980a82c5f4
--- /dev/null
+++ b/chromium/ui/base/interaction/interaction_sequence.cc
@@ -0,0 +1,515 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/interaction/interaction_sequence.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/weak_ptr.h"
+#include "base/scoped_observation.h"
+#include "ui/base/interaction/element_tracker.h"
+
+namespace ui {
+
+namespace {
+
+// Runs |callback| if it is valid.
+// We have a lot of callbacks that can be null, so calling through this method
+// prevents accidentally trying to run a null callback.
+template <typename Signature, typename... Args>
+void RunIfValid(base::OnceCallback<Signature> callback, Args... args) {
+ if (callback)
+ std::move(callback).Run(args...);
+}
+
+// Version of AutoReset that takes a pointer-to-member and a weak reference in
+// case the object that owns the value goes away before the AutoReset does.
+template <class T, class U>
+class SafeAutoReset {
+ public:
+ SafeAutoReset(base::WeakPtr<T> ptr, U T::*ref, U new_value)
+ : ptr_(ptr), ref_(ref), old_value_(ptr.get()->*ref) {
+ ptr.get()->*ref = new_value;
+ }
+
+ SafeAutoReset(SafeAutoReset<T, U>&& other)
+ : ptr_(std::move(other.ptr_)),
+ ref_(other.ref_),
+ old_value_(other.old_value_) {}
+
+ SafeAutoReset& operator=(SafeAutoReset<T, U>&& other) {
+ if (this != &other) {
+ Reset();
+ ptr_ = std::move(other.ptr_);
+ ref_ = other.ref_;
+ old_value_ = other.old_value_;
+ }
+ return *this;
+ }
+
+ ~SafeAutoReset() { Reset(); }
+
+ private:
+ void Reset() {
+ if (ptr_)
+ ptr_.get()->*ref_ = old_value_;
+ }
+
+ base::WeakPtr<T> ptr_;
+ U T::*ref_ = nullptr;
+ U old_value_ = U();
+};
+
+// Convenience method to create a SafeAutoReset with less boilerplate.
+template <class T, class U>
+static SafeAutoReset<T, U> MakeSafeAutoReset(base::WeakPtr<T> ptr,
+ U T::*ref,
+ U new_value) {
+ return SafeAutoReset<T, U>(ptr, ref, new_value);
+}
+
+} // anonymous namespace
+
+InteractionSequence::Step::Step() = default;
+InteractionSequence::Step::~Step() = default;
+
+struct InteractionSequence::Configuration {
+ Configuration() = default;
+ ~Configuration() = default;
+
+ std::list<std::unique_ptr<Step>> steps;
+ ElementContext context;
+ AbortedCallback aborted_callback;
+ CompletedCallback completed_callback;
+};
+
+InteractionSequence::Builder::Builder()
+ : configuration_(std::make_unique<Configuration>()) {}
+
+InteractionSequence::Builder::~Builder() {
+ DCHECK(!configuration_);
+}
+
+InteractionSequence::Builder& InteractionSequence::Builder::SetAbortedCallback(
+ AbortedCallback callback) {
+ DCHECK(!configuration_->aborted_callback);
+ configuration_->aborted_callback = std::move(callback);
+ return *this;
+}
+
+InteractionSequence::Builder&
+InteractionSequence::Builder::SetCompletedCallback(CompletedCallback callback) {
+ DCHECK(!configuration_->completed_callback);
+ configuration_->completed_callback = std::move(callback);
+ return *this;
+}
+
+InteractionSequence::Builder& InteractionSequence::Builder::AddStep(
+ std::unique_ptr<Step> step) {
+ DCHECK(step->id);
+ DCHECK(configuration_->steps.empty() || !step->element)
+ << " Only the initial step of a sequence may have a pre-set element.";
+ DCHECK(!step->element || step->must_be_visible)
+ << " Initial step with associated element must be visible from start.";
+ step->must_be_visible =
+ step->must_be_visible.value_or(step->type == StepType::kActivated);
+ step->must_remain_visible =
+ step->must_remain_visible.value_or(step->type == StepType::kShown);
+ DCHECK(step->type != StepType::kHidden || !step->must_remain_visible.value());
+ if (!configuration_->context)
+ configuration_->context = step->context;
+ else
+ DCHECK(!step->context || step->context == configuration_->context);
+ configuration_->steps.emplace_back(std::move(step));
+ return *this;
+}
+
+InteractionSequence::Builder& InteractionSequence::Builder::SetContext(
+ ElementContext context) {
+ configuration_->context = context;
+ return *this;
+}
+
+std::unique_ptr<InteractionSequence> InteractionSequence::Builder::Build() {
+ DCHECK(!configuration_->steps.empty());
+ DCHECK(configuration_->context)
+ << "If no view is provided, Builder::SetContext() must be called.";
+ return base::WrapUnique(new InteractionSequence(std::move(configuration_)));
+}
+
+InteractionSequence::StepBuilder::StepBuilder()
+ : step_(std::make_unique<Step>()) {}
+InteractionSequence::StepBuilder::~StepBuilder() = default;
+
+InteractionSequence::StepBuilder&
+InteractionSequence::StepBuilder::SetElementID(ElementIdentifier element_id) {
+ DCHECK(element_id);
+ step_->id = element_id;
+ return *this;
+}
+
+InteractionSequence::StepBuilder& InteractionSequence::StepBuilder::SetContext(
+ ElementContext context) {
+ DCHECK(context);
+ step_->context = context;
+ return *this;
+}
+
+InteractionSequence::StepBuilder&
+InteractionSequence::StepBuilder::SetMustBeVisibleAtStart(
+ bool must_be_visible) {
+ step_->must_be_visible = must_be_visible;
+ return *this;
+}
+
+InteractionSequence::StepBuilder&
+InteractionSequence::StepBuilder::SetMustRemainVisible(
+ bool must_remain_visible) {
+ step_->must_remain_visible = must_remain_visible;
+ return *this;
+}
+
+InteractionSequence::StepBuilder& InteractionSequence::StepBuilder::SetType(
+ StepType step_type) {
+ step_->type = step_type;
+ return *this;
+}
+
+InteractionSequence::StepBuilder&
+InteractionSequence::StepBuilder::SetStartCallback(
+ StepCallback start_callback) {
+ step_->start_callback = std::move(start_callback);
+ return *this;
+}
+
+InteractionSequence::StepBuilder&
+InteractionSequence::StepBuilder::SetEndCallback(StepCallback end_callback) {
+ step_->end_callback = std::move(end_callback);
+ return *this;
+}
+
+std::unique_ptr<InteractionSequence::Step>
+InteractionSequence::StepBuilder::Build() {
+ return std::move(step_);
+}
+
+InteractionSequence::InteractionSequence(
+ std::unique_ptr<Configuration> configuration)
+ : configuration_(std::move(configuration)) {
+ TrackedElement* const first_element = next_step()->element;
+ if (first_element) {
+ DCHECK(first_element->identifier() == next_step()->id);
+ DCHECK(first_element->context() == context());
+ next_step()->subscription =
+ ElementTracker::GetElementTracker()->AddElementHiddenCallback(
+ first_element->identifier(), first_element->context(),
+ base::BindRepeating(&InteractionSequence::OnElementHidden,
+ base::Unretained(this)));
+ }
+}
+
+// static
+std::unique_ptr<InteractionSequence::Step>
+InteractionSequence::WithInitialElement(TrackedElement* element,
+ StepCallback start_callback,
+ StepCallback end_callback) {
+ StepBuilder step;
+ step.step_->element = element;
+ step.SetType(StepType::kShown)
+ .SetElementID(element->identifier())
+ .SetContext(element->context())
+ .SetMustBeVisibleAtStart(true)
+ .SetMustRemainVisible(true)
+ .SetStartCallback(std::move(start_callback))
+ .SetEndCallback(std::move(end_callback));
+ return step.Build();
+}
+
+InteractionSequence::~InteractionSequence() {
+ // We can abort during a step callback, but we cannot destroy this object.
+ if (started_)
+ Abort();
+}
+
+void InteractionSequence::Start() {
+ // Ensure we're not already started.
+ DCHECK(!started_);
+ started_ = true;
+ if (missing_first_element_) {
+ Abort();
+ return;
+ }
+ StageNextStep();
+}
+
+void InteractionSequence::OnElementShown(TrackedElement* element) {
+ DCHECK_EQ(StepType::kShown, next_step()->type);
+ DCHECK(element->identifier() == next_step()->id);
+ DoStepTransition(element);
+}
+
+void InteractionSequence::OnElementActivated(TrackedElement* element) {
+ DCHECK_EQ(StepType::kActivated, next_step()->type);
+ DCHECK(element->identifier() == next_step()->id);
+ DoStepTransition(element);
+}
+
+void InteractionSequence::OnElementHidden(TrackedElement* element) {
+ if (!started_) {
+ DCHECK_EQ(next_step()->element, element);
+ missing_first_element_ = true;
+ next_step()->subscription = ElementTracker::Subscription();
+ next_step()->element = nullptr;
+ return;
+ }
+
+ if (current_step_->element == element) {
+ // If the current step is marked as needing to remain visible and we haven't
+ // seen the triggering event for the next step, abort.
+ if (current_step_->must_remain_visible.value() &&
+ !activated_during_callback_) {
+ Abort();
+ return;
+ }
+
+ // This element pointer is no longer valid and we can stop watching.
+ current_step_->subscription = ElementTracker::Subscription();
+ current_step_->element = nullptr;
+ }
+
+ // If we got a hidden callback and it wasn't to abort the current step, it
+ // must be because we're waiting on the next step to start.
+ if (next_step() && next_step()->id == element->identifier() &&
+ next_step()->type == StepType::kHidden) {
+ DoStepTransition(element);
+ }
+}
+
+void InteractionSequence::OnElementActivatedDuringStepTransition(
+ TrackedElement* element) {
+ if (!next_step())
+ return;
+
+ DCHECK(element->identifier() == next_step()->id);
+ next_step()->element = element;
+ next_step()->subscription =
+ ElementTracker::GetElementTracker()->AddElementHiddenCallback(
+ next_step()->id, context(),
+ base::BindRepeating(
+ &InteractionSequence::OnElementHiddenDuringStepTransition,
+ base::Unretained(this)));
+
+ activated_during_callback_ = true;
+}
+
+void InteractionSequence::OnElementHiddenDuringStepTransition(
+ TrackedElement* element) {
+ if (!next_step() || element != next_step()->element)
+ return;
+
+ next_step()->element = nullptr;
+ next_step()->subscription = ElementTracker::Subscription();
+}
+
+void InteractionSequence::DoStepTransition(TrackedElement* element) {
+ // There are a number of callbacks during this method that could potentially
+ // result in this InteractionSequence being destructed, so maintain a weak
+ // pointer we can check to see if we need to bail out early.
+ base::WeakPtr<InteractionSequence> delete_guard = weak_factory_.GetWeakPtr();
+ auto* const tracker = ElementTracker::GetElementTracker();
+ {
+ // This block is non-re-entrant.
+ DCHECK(!processing_step_);
+ auto processing =
+ MakeSafeAutoReset(weak_factory_.GetWeakPtr(),
+ &InteractionSequence::processing_step_, true);
+
+ // End the current step.
+ if (current_step_) {
+ // Unsubscribe from any events during the step-end process. Since the step
+ // has ended, conditions like "must remain visible" no longer apply.
+ current_step_->subscription = ElementTracker::Subscription();
+ RunIfValid(std::move(current_step_->end_callback), current_step_->element,
+ current_step_->id, current_step_->type);
+ if (!delete_guard || AbortedDuringCallback())
+ return;
+ }
+
+ // Set up the new current step.
+ current_step_ = std::move(configuration_->steps.front());
+ configuration_->steps.pop_front();
+ DCHECK(!current_step_->element || current_step_->element == element);
+ current_step_->element =
+ current_step_->type == StepType::kHidden ? nullptr : element;
+ if (current_step_->element) {
+ current_step_->subscription = tracker->AddElementHiddenCallback(
+ current_step_->id, context(),
+ base::BindRepeating(&InteractionSequence::OnElementHidden,
+ base::Unretained(this)));
+ } else {
+ current_step_->subscription = ElementTracker::Subscription();
+ }
+
+ // Special care must be taken here, because theoretically *anything* could
+ // happen as a result of this callback. If the next step is a shown or
+ // hidden step and the element becomes shown or hidden (or it's a step that
+ // requires the element to be visible and it is not), then the appropriate
+ // transition (or Abort()) will happen in StageNextStep() below.
+ //
+ // If, however, the callback *activates* the next target element, and the
+ // next element is of type kActivated, then the activation will not
+ // register unless we explicitly listen for it. But we still don't want to
+ if (next_step() && next_step()->type == StepType::kActivated) {
+ next_step()->subscription = tracker->AddElementActivatedCallback(
+ next_step()->id, context(),
+ base::BindRepeating(
+ &InteractionSequence::OnElementActivatedDuringStepTransition,
+ base::Unretained((this))));
+ }
+
+ // Start the step. Like all callbacks, this could abort the sequence, or
+ // cause `element` to become invalid. Because of this we use the element
+ // field of the current step from here forward, because we've installed a
+ // callback above that will null it out if it becomes invalid.
+ RunIfValid(std::move(current_step_->start_callback), current_step_->element,
+ current_step_->id, current_step_->type);
+ if (!delete_guard || AbortedDuringCallback())
+ return;
+ }
+
+ if (configuration_->steps.empty()) {
+ // Reset anything that might cause state change during the final callback.
+ // After this, Abort() will have basically no effect, since by the time it
+ // gets called, both the aborted and step end callbacks will be null.
+ current_step_->subscription = ElementTracker::Subscription();
+ configuration_->aborted_callback.Reset();
+ // Last step end callback needs to be run before sequence completed.
+ // Because the InteractionSequence could conceivably be destroyed during
+ // one of these callbacks, make local copies of the callbacks and data.
+ CompletedCallback completed_callback =
+ std::move(configuration_->completed_callback);
+ std::unique_ptr<Step> last_step = std::move(current_step_);
+ RunIfValid(std::move(last_step->end_callback), last_step->element,
+ last_step->id, last_step->type);
+ RunIfValid(std::move(completed_callback));
+ return;
+ }
+
+ // Since we're not done, load up the next step.
+ StageNextStep();
+}
+
+void InteractionSequence::StageNextStep() {
+ auto* const tracker = ElementTracker::GetElementTracker();
+
+ Step* const next = next_step();
+ DCHECK(!activated_during_callback_ || next->type == StepType::kActivated);
+
+ // Note that if the target element for the next step was activated and then
+ // hidden during the previous step transition, `next_element` could be null.
+ TrackedElement* const next_element =
+ (activated_during_callback_ || next->element)
+ ? next->element
+ : tracker->GetFirstMatchingElement(next->id, context());
+
+ if (!activated_during_callback_ && next->must_be_visible.value() &&
+ !next_element) {
+ // Fast forward to the next step before aborting so we get the correct
+ // information on the failed step in the abort callback.
+ current_step_ = std::move(configuration_->steps.front());
+ configuration_->steps.pop_front();
+ // We don't want to call the step-end callback during Abort() since we
+ // didn't technically start the step.
+ current_step_->end_callback = StepCallback();
+ Abort();
+ return;
+ }
+
+ switch (next_step()->type) {
+ case StepType::kShown:
+ if (next_element) {
+ DoStepTransition(next_element);
+ } else {
+ next_step()->subscription = tracker->AddElementShownCallback(
+ next_step()->id, context(),
+ base::BindRepeating(&InteractionSequence::OnElementShown,
+ base::Unretained(this)));
+ }
+ break;
+ case StepType::kHidden:
+ if (!next_element) {
+ DoStepTransition(nullptr);
+ } else {
+ next_step()->subscription = tracker->AddElementHiddenCallback(
+ next_step()->id, context(),
+ base::BindRepeating(&InteractionSequence::OnElementHidden,
+ base::Unretained(this)));
+ }
+ break;
+ case StepType::kActivated:
+ if (activated_during_callback_) {
+ activated_during_callback_ = false;
+ DoStepTransition(next_element);
+ } else {
+ next_step()->subscription = tracker->AddElementActivatedCallback(
+ next_step()->id, context(),
+ base::BindRepeating(&InteractionSequence::OnElementActivated,
+ base::Unretained(this)));
+ }
+ break;
+ }
+}
+
+void InteractionSequence::Abort() {
+ DCHECK(started_);
+ configuration_->steps.clear();
+ if (current_step_) {
+ // Stop listening for events; we don't want additional callbacks during
+ // teardown.
+ current_step_->subscription = ElementTracker::Subscription();
+ // The current step's element could go away during a callback, so hedge our
+ // bets by using a safe reference.
+ SafeElementReference element(current_step_->element);
+ // The entire InteractionSequence could also go away during a callback, so
+ // save anything we need locally so that we don't have to access any class
+ // members as we finish terminating the sequence.
+ std::unique_ptr<Step> last_step = std::move(current_step_);
+ AbortedCallback aborted_callback =
+ std::move(configuration_->aborted_callback);
+ RunIfValid(std::move(last_step->end_callback), element.get(), last_step->id,
+ last_step->type);
+ RunIfValid(std::move(aborted_callback), element.get(), last_step->id,
+ last_step->type);
+ } else {
+ // Aborted before any steps were run. Pass default values.
+ // Note that if the sequence has already been aborted, this is a no-op, the
+ // callback will already be null.
+ RunIfValid(std::move(configuration_->aborted_callback), nullptr,
+ ElementIdentifier(), StepType::kShown);
+ }
+}
+
+bool InteractionSequence::AbortedDuringCallback() const {
+ // All step callbacks are sourced from the current step. If the current step
+ // is null, then the sequence must have aborted (which clears out the current
+ // step). Completion can only happen after step callbacks are finished
+ if (current_step_)
+ return false;
+
+ DCHECK(configuration_->steps.empty());
+ DCHECK(!configuration_->aborted_callback);
+ return true;
+}
+
+InteractionSequence::Step* InteractionSequence::next_step() {
+ return configuration_->steps.empty() ? nullptr
+ : configuration_->steps.front().get();
+}
+
+ElementContext InteractionSequence::context() const {
+ return configuration_->context;
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/interaction/interaction_sequence.h b/chromium/ui/base/interaction/interaction_sequence.h
new file mode 100644
index 00000000000..90d2a14b12c
--- /dev/null
+++ b/chromium/ui/base/interaction/interaction_sequence.h
@@ -0,0 +1,278 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_INTERACTION_INTERACTION_SEQUENCE_H_
+#define UI_BASE_INTERACTION_INTERACTION_SEQUENCE_H_
+
+#include <list>
+
+#include "base/callback_forward.h"
+#include "base/component_export.h"
+#include "base/memory/weak_ptr.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/base/interaction/element_identifier.h"
+#include "ui/base/interaction/element_tracker.h"
+
+namespace ui {
+
+// Follows an expected sequence of user-UI interactions and provides callbacks
+// at each step. Useful for creating interaction tests and user tutorials.
+//
+// An interaction sequence consists of an ordered series of steps, each of which
+// refers to an interface element tagged with a ElementIdentifier and each of
+// which represents that element being either shown, activated, or hidden. Other
+// unrelated events such as element hover or focus are ignored (but could be
+// supported in the future).
+//
+// Each step has an optional callback that is triggered when the expected
+// interaction happens, and an optional callback that is triggered when the step
+// ends - either because the next step has started or because the user has
+// aborted the sequence (typically by dismissing UI such as a dialog or menu,
+// resulting in the element from the current step being hidden/destroyed). Once
+// the first callback is called/the step starts, the second callback will always
+// be called.
+//
+// Furthermore, when the last step in the sequence completes, in addition to its
+// end callback, an optional sequence-completed callback will be called. If the
+// user aborts the sequence or if this object is destroyed, then an optional
+// sequence-aborted callback is called instead.
+//
+// To use a InteractionSequence, start with a builder:
+//
+// sequence_ = InteractionSequence::Builder()
+// .SetCompletedCallback(base::BindOnce(...))
+// .AddStep(InteractionSequence::WithInitialElement(initial_element))
+// .AddStep(InteractionSequence::StepBuilder()
+// .SetElementID(kDialogElementID)
+// .SetType(StepType::kShown)
+// .SetStartCallback(...)
+// .Build())
+// .AddStep(...)
+// .Build();
+// sequence_->Start();
+//
+// For more detailed instructions on using the ui/base/interaction library, see
+// README.md in this folder.
+//
+class COMPONENT_EXPORT(UI_BASE) InteractionSequence {
+ public:
+ // The type of event that is expected to happen next in the sequence.
+ enum class StepType {
+ // Represents the element with the specified ID becoming visible to the
+ // user.
+ kShown,
+ // Represents an element with the specified ID becoming activated by the
+ // user (for buttons or menu items, being clicked).
+ kActivated,
+ // Represents an element with the specified ID becoming hidden or destroyed.
+ kHidden
+ };
+
+ // Callback when a step happens in the sequence, or when a step ends. If
+ // |element| is no longer available, it will be null.
+ using StepCallback = base::OnceCallback<void(TrackedElement* element,
+ ElementIdentifier element_id,
+ StepType step_type)>;
+
+ // Callback for when the user aborts the sequence by failing to follow the
+ // sequence of steps, or if this object is deleted after the sequence starts.
+ // The most recent event is described by the parameters; if the target element
+ // is no longer available it will be null.
+ using AbortedCallback = base::OnceCallback<void(TrackedElement* last_element,
+ ElementIdentifier last_id,
+ StepType last_step_type)>;
+
+ using CompletedCallback = base::OnceClosure;
+
+ struct Configuration;
+ class StepBuilder;
+
+ struct COMPONENT_EXPORT(UI_BASE) Step {
+ Step();
+ Step(const Step& other) = delete;
+ void operator=(const Step& other) = delete;
+ ~Step();
+
+ StepType type = StepType::kShown;
+ ElementIdentifier id;
+ ElementContext context;
+
+ // These will always have values when the sequence is built, but can be
+ // unspecified during construction. If unspecified, they will be set to
+ // appropriate defaults for `type`.
+ absl::optional<bool> must_be_visible;
+ absl::optional<bool> must_remain_visible;
+
+ StepCallback start_callback;
+ StepCallback end_callback;
+ ElementTracker::Subscription subscription;
+
+ // Tracks the element associated with the step, if known. We could use a
+ // SafeElementReference here, but there are cases where we want to do
+ // additional processing if this element goes away, so we'll add the
+ // listeners manually instead.
+ TrackedElement* element = nullptr;
+ };
+
+ // Use a Builder to specify parameters when creating an InteractionSequence.
+ class COMPONENT_EXPORT(UI_BASE) Builder {
+ public:
+ Builder();
+ Builder(const Builder& other) = delete;
+ void operator=(const Builder& other) = delete;
+ ~Builder();
+
+ // Sets the callback if the user exits the sequence early.
+ Builder& SetAbortedCallback(AbortedCallback callback);
+
+ // Sets the callback if the user completes the sequence.
+ // Convenience method so that the last step's end callback doesn't need to
+ // have special logic in it.
+ Builder& SetCompletedCallback(CompletedCallback callback);
+
+ // Adds an expected step in the sequence. All sequences must have at least
+ // one step.
+ Builder& AddStep(std::unique_ptr<Step> step);
+
+ // Sets the context for this sequence. Must be called if no step is added
+ // by element or has had SetContext() called. Typically the initial step of
+ // a sequence will use WithInitialElement() so it won't be necessary to call
+ // this method.
+ Builder& SetContext(ElementContext context);
+
+ // Creates the InteractionSequence. You must call Start() to initiate the
+ // sequence; sequences cannot be re-used, and a Builder is no longer valid
+ // after Build() is called.
+ std::unique_ptr<InteractionSequence> Build();
+
+ private:
+ std::unique_ptr<Configuration> configuration_;
+ };
+
+ // Used inline in calls to Builder::AddStep to specify step parameters.
+ class COMPONENT_EXPORT(UI_BASE) StepBuilder {
+ public:
+ StepBuilder();
+ ~StepBuilder();
+ StepBuilder(const StepBuilder& other) = delete;
+ void operator=(StepBuilder& other) = delete;
+
+ // Sets the unique identifier for this step. Required.
+ StepBuilder& SetElementID(ElementIdentifier element_id);
+
+ // Sets the context for the element; useful for setting up the initial
+ // element of the sequence if you do not know the context ahead of time.
+ // Prefer to use Builder::SetContext() if possible.
+ StepBuilder& SetContext(ElementContext context);
+
+ // Sets the type of step. Required.
+ StepBuilder& SetType(StepType step_type);
+
+ // Indicates that the specified element must be visible at the start of the
+ // step. Defaults to true for StepType::kActivated, false otherwise. Failure
+ // To meet this condition will abort the sequence.
+ StepBuilder& SetMustBeVisibleAtStart(bool must_be_visible);
+
+ // Indicates that the specified element must remain visible throughout the
+ // step once it has been shown. Defaults to true for StepType::kShown, false
+ // otherwise (and incompatible with StepType::kHidden). Failure to meet this
+ // condition will abort the sequence.
+ StepBuilder& SetMustRemainVisible(bool must_remain_visible);
+
+ // Sets the callback called at the start of the step.
+ StepBuilder& SetStartCallback(StepCallback start_callback);
+
+ // Sets the callback called at the end of the step. Guaranteed to be called
+ // if the start callback is called, before the start callback of the next
+ // step or the sequence aborted or completed callback. Also called if this
+ // object is destroyed while the step is still in-process.
+ StepBuilder& SetEndCallback(StepCallback end_callback);
+
+ // Builds the step. The builder will not be valid after calling Build().
+ std::unique_ptr<Step> Build();
+
+ private:
+ friend class InteractionSequence;
+ std::unique_ptr<Step> step_;
+ };
+
+ // Returns a step with the following values already set, typically used as the
+ // first step in a sequence (because the first element is usually present):
+ // ElementID: element->identifier()
+ // MustBeVisibleAtStart: true
+ // MustRemainVisible: true
+ //
+ // This is a convenience method and also removes the need to call
+ // Builder::SetContext(). Specific framework implementations may provide
+ // wrappers around this method that allow direct conversion from framework UI
+ // elements (e.g. a views::View) to the target element.
+ static std::unique_ptr<Step> WithInitialElement(
+ TrackedElement* element,
+ StepCallback start_callback = StepCallback(),
+ StepCallback end_callback = StepCallback());
+
+ ~InteractionSequence();
+
+ // Starts the sequence. All of the elements in the sequence must belong to the
+ // same top-level application window (which includes menus, bubbles, etc.
+ // associated with that window).
+ void Start();
+
+ private:
+ explicit InteractionSequence(std::unique_ptr<Configuration> configuration);
+
+ // Callbacks from the ElementTracker.
+ void OnElementShown(TrackedElement* element);
+ void OnElementActivated(TrackedElement* element);
+ void OnElementHidden(TrackedElement* element);
+
+ // Callbacks used only during step transitions to cache certain events.
+ void OnElementActivatedDuringStepTransition(TrackedElement* element);
+ void OnElementHiddenDuringStepTransition(TrackedElement* element);
+
+ // A note on the next three methods - DoStepTransition(), StageNextStep(), and
+ // Abort(): To prevent re-entrancy issues, they must always be the final call
+ // in any method before it returns. This greatly simplifies the consistency
+ // checks and safeguards that need to be put into place to make sure we aren't
+ // making contradictory changes to state or calling callbacks in the wrong
+ // order.
+
+ // Perform the transition from the current step to the next step.
+ void DoStepTransition(TrackedElement* element);
+
+ // Looks at the next step to determine what needs to be done. Called at the
+ // start of the sequence and after each subsequent step starts.
+ void StageNextStep();
+
+ // Cancels the sequence and cleans up.
+ void Abort();
+
+ // Returns true (and does some sanity checking) if the sequence was aborted
+ // during the most recent callback.
+ bool AbortedDuringCallback() const;
+
+ // The following would be inline if not for the fact that the data that holds
+ // the values is an implementation detail.
+
+ // Returns the next step, or null if none.
+ Step* next_step();
+
+ // Returns the context for the current sequence.
+ ElementContext context() const;
+
+ bool missing_first_element_ = false;
+ bool started_ = false;
+ bool activated_during_callback_ = false;
+ bool processing_step_ = false;
+ std::unique_ptr<Step> current_step_;
+ std::unique_ptr<Configuration> configuration_;
+
+ // This is necessary because this object could be deleted during any callback,
+ // and we don't want to risk a UAF if that happens.
+ base::WeakPtrFactory<InteractionSequence> weak_factory_{this};
+};
+
+} // namespace ui
+
+#endif // UI_BASE_INTERACTION_INTERACTION_SEQUENCE_H_
diff --git a/chromium/ui/base/interaction/interaction_sequence_unittest.cc b/chromium/ui/base/interaction/interaction_sequence_unittest.cc
new file mode 100644
index 00000000000..0d4feedf16c
--- /dev/null
+++ b/chromium/ui/base/interaction/interaction_sequence_unittest.cc
@@ -0,0 +1,1402 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/interaction/interaction_sequence.h"
+
+#include "base/callback_forward.h"
+#include "base/test/bind.h"
+#include "base/test/mock_callback.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/interaction/element_identifier.h"
+#include "ui/base/interaction/element_test_util.h"
+#include "ui/base/interaction/element_tracker.h"
+#include "ui/base/interaction/expect_call_in_scope.h"
+
+namespace ui {
+
+namespace {
+
+DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTestIdentifier1);
+DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTestIdentifier2);
+DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTestIdentifier3);
+const ElementContext kTestContext1(1);
+const ElementContext kTestContext2(2);
+
+} // namespace
+
+TEST(InteractionSequenceTest, ConstructAndDestructContext) {
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetContext(kTestContext1)
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(kTestIdentifier1)
+ .SetType(InteractionSequence::StepType::kActivated)
+ .Build())
+ .Build();
+ tracker.reset();
+}
+
+TEST(InteractionSequenceTest, ConstructAndDestructWithWithInitialElement) {
+ TestElement element(kTestIdentifier1, kTestContext1);
+ element.Show();
+ auto tracker = InteractionSequence::Builder()
+ .AddStep(InteractionSequence::WithInitialElement(&element))
+ .Build();
+ tracker.reset();
+}
+
+TEST(InteractionSequenceTest, StartAndDestruct) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ TestElement element(kTestIdentifier1, kTestContext1);
+ element.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .Build())
+ .Build();
+ tracker->Start();
+ EXPECT_CALL_IN_SCOPE(aborted, Run, tracker.reset());
+}
+
+TEST(InteractionSequenceTest, StartFailsIfWithInitialElementNotVisible) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ TestElement element(kTestIdentifier1, kTestContext1);
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .Build())
+ .Build();
+ EXPECT_CALL_IN_SCOPE(aborted, Run, tracker->Start());
+}
+
+TEST(InteractionSequenceTest,
+ StartFailsIfWithInitialElementNotVisibleIdentifierOnly) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ TestElement element(kTestIdentifier1, kTestContext1);
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .SetContext(element.context())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetMustBeVisibleAtStart(true)
+ .SetMustRemainVisible(true)
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .Build())
+ .Build();
+ EXPECT_CALL_IN_SCOPE(aborted, Run, tracker->Start());
+}
+
+TEST(InteractionSequenceTest, AbortIfWithInitialElementHiddenBeforeStart) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ TestElementPtr element =
+ std::make_unique<TestElement>(kTestIdentifier1, kTestContext1);
+ element->Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(element.get()))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element->identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .Build())
+ .Build();
+ element.reset();
+ EXPECT_CALL_IN_SCOPE(aborted, Run, tracker->Start());
+}
+
+TEST(InteractionSequenceTest,
+ AbortIfWithInitialElementHiddenBeforeStartIdentifierOnly) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ TestElementPtr element =
+ std::make_unique<TestElement>(kTestIdentifier1, kTestContext1);
+ element->Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .SetContext(element->context())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element->identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetMustBeVisibleAtStart(true)
+ .SetMustRemainVisible(true)
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element->identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .Build())
+ .Build();
+ element.reset();
+ EXPECT_CALL_IN_SCOPE(aborted, Run, tracker->Start());
+}
+
+TEST(InteractionSequenceTest, HideWithInitialElementAborts) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ TestElement element(kTestIdentifier1, kTestContext1);
+ element.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .Build())
+ .Build();
+ tracker->Start();
+ EXPECT_CALL_IN_SCOPE(aborted, Run, element.Hide());
+}
+
+TEST(InteractionSequenceTest,
+ HideWithInitialElementDoesNotAbortIfMustRemainVisibleIsFalse) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ TestElement element(kTestIdentifier1, kTestContext1);
+ element.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .SetContext(element.context())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetMustBeVisibleAtStart(true)
+ .SetMustRemainVisible(false)
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .Build())
+ .Build();
+ tracker->Start();
+ element.Hide();
+ EXPECT_CALL_IN_SCOPE(aborted, Run, tracker.reset());
+}
+
+TEST(InteractionSequenceTest, TransitionOnActivated) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step);
+ TestElement element(kTestIdentifier1, kTestContext1);
+ element.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step.Get())
+ .Build())
+ .Build();
+ tracker->Start();
+ EXPECT_CALL(step, Run(&element, element.identifier(),
+ InteractionSequence::StepType::kActivated))
+ .Times(1);
+ EXPECT_CALL(completed, Run).Times(1);
+ element.Activate();
+}
+
+TEST(InteractionSequenceTest, TransitionOnElementShown) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(step.Get())
+ .Build())
+ .Build();
+ tracker->Start();
+ EXPECT_CALL(step, Run(&element2, element2.identifier(),
+ InteractionSequence::StepType::kShown))
+ .Times(1);
+ EXPECT_CALL(completed, Run).Times(1);
+ element2.Show();
+}
+
+TEST(InteractionSequenceTest, TransitionFailsOnElementShownIfMustBeVisible) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(step.Get())
+ .SetMustBeVisibleAtStart(true)
+ .Build())
+ .Build();
+ EXPECT_CALL(aborted, Run(nullptr, element2.identifier(),
+ InteractionSequence::StepType::kShown))
+ .Times(1);
+ tracker->Start();
+}
+
+TEST(InteractionSequenceTest, TransitionOnSameElementHidden) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetMustRemainVisible(false)
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kHidden)
+ .SetStartCallback(step.Get())
+ .Build())
+ .Build();
+ tracker->Start();
+ element2.Show();
+ EXPECT_CALL(step, Run(nullptr, element2.identifier(),
+ InteractionSequence::StepType::kHidden))
+ .Times(1);
+ EXPECT_CALL(completed, Run).Times(1);
+ element2.Hide();
+}
+
+TEST(InteractionSequenceTest, TransitionOnOtherElementHidden) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+ element2.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kHidden)
+ .SetStartCallback(step.Get())
+ .Build())
+ .Build();
+ tracker->Start();
+ EXPECT_CALL(step, Run(nullptr, element2.identifier(),
+ InteractionSequence::StepType::kHidden))
+ .Times(1);
+ EXPECT_CALL(completed, Run).Times(1);
+ element2.Hide();
+}
+
+TEST(InteractionSequenceTest, TransitionOnOtherElementAlreadyHidden) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kHidden)
+ .SetStartCallback(step.Get())
+ .Build())
+ .Build();
+ EXPECT_CALL(step, Run(testing::_, element2.identifier(),
+ InteractionSequence::StepType::kHidden))
+ .Times(1);
+ EXPECT_CALL(completed, Run).Times(1);
+ tracker->Start();
+}
+
+TEST(InteractionSequenceTest, FailOnOtherElementAlreadyHiddenIfMustBeVisible) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kHidden)
+ .SetMustBeVisibleAtStart(true)
+ .SetStartCallback(step.Get())
+ .Build())
+ .Build();
+ EXPECT_CALL(aborted, Run(nullptr, element2.identifier(),
+ InteractionSequence::StepType::kHidden))
+ .Times(1);
+ tracker->Start();
+}
+
+TEST(InteractionSequenceTest, NoWithInitialElementTransitionsOnActivation) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step);
+ TestElement element(kTestIdentifier1, kTestContext1);
+ element.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .SetContext(element.context())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetMustBeVisibleAtStart(false)
+ .SetStartCallback(step.Get())
+ .Build())
+ .Build();
+ tracker->Start();
+ EXPECT_CALL(step, Run(&element, element.identifier(),
+ InteractionSequence::StepType::kActivated))
+ .Times(1);
+ EXPECT_CALL(completed, Run).Times(1);
+ element.Activate();
+}
+
+TEST(InteractionSequenceTest, NoWithInitialElementTransitionsOnShown) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step);
+ TestElement element(kTestIdentifier1, kTestContext1);
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .SetContext(element.context())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(step.Get())
+ .Build())
+ .Build();
+ tracker->Start();
+ EXPECT_CALL(step, Run(&element, element.identifier(),
+ InteractionSequence::StepType::kShown))
+ .Times(1);
+ EXPECT_CALL(completed, Run).Times(1);
+ element.Show();
+}
+
+TEST(InteractionSequenceTest, StepEndCallbackCalled) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step_end);
+ TestElement element(kTestIdentifier1, kTestContext1);
+ element.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step_start.Get())
+ .SetEndCallback(step_end.Get())
+ .Build())
+ .Build();
+ tracker->Start();
+ EXPECT_CALLS_IN_SCOPE_3(step_start,
+ Run(&element, element.identifier(),
+ InteractionSequence::StepType::kActivated),
+ step_end,
+ Run(&element, element.identifier(),
+ InteractionSequence::StepType::kActivated),
+ completed, Run, element.Activate());
+}
+
+TEST(InteractionSequenceTest, StepEndCallbackCalledForInitialStep) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step_end);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2);
+ TestElement element(kTestIdentifier1, kTestContext1);
+ element.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(
+ &element, step_start.Get(), step_end.Get()))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step2.Get())
+ .Build())
+ .Build();
+ EXPECT_CALL_IN_SCOPE(step_start, Run, tracker->Start());
+ EXPECT_CALLS_IN_SCOPE_3(step_end,
+ Run(&element, element.identifier(),
+ InteractionSequence::StepType::kShown),
+ step2,
+ Run(&element, element.identifier(),
+ InteractionSequence::StepType::kActivated),
+ completed, Run, element.Activate());
+}
+
+TEST(InteractionSequenceTest, MultipleStepsComplete) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_end);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_end);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ TestElement element3(kTestIdentifier3, kTestContext1);
+ element1.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(step1_start.Get())
+ .SetEndCallback(step1_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step2_start.Get())
+ .SetEndCallback(step2_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element3.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .Build())
+ .Build();
+
+ tracker->Start();
+
+ EXPECT_CALL_IN_SCOPE(step1_start, Run, element2.Show());
+
+ EXPECT_CALLS_IN_SCOPE_2(step1_end, Run, step2_start, Run,
+ element2.Activate());
+
+ EXPECT_CALLS_IN_SCOPE_2(step2_end, Run, completed, Run, element3.Show());
+}
+
+TEST(InteractionSequenceTest, MultipleStepsWithImmediateTransition) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_end);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_end);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ TestElement element3(kTestIdentifier3, kTestContext1);
+ element1.Show();
+ element3.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(step1_start.Get())
+ .SetEndCallback(step1_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step2_start.Get())
+ .SetEndCallback(step2_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element3.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .Build())
+ .Build();
+
+ tracker->Start();
+
+ EXPECT_CALL_IN_SCOPE(step1_start, Run, element2.Show());
+
+ // Since element3 is already visible, we skip straight to the end.
+ {
+ testing::InSequence in_sequence;
+ EXPECT_CALL(step1_end, Run).Times(1);
+ EXPECT_CALL(step2_start, Run).Times(1);
+ EXPECT_CALL(step2_end, Run).Times(1);
+ EXPECT_CALL(completed, Run).Times(1);
+ }
+ element2.Activate();
+}
+
+TEST(InteractionSequenceTest, CancelMidSequenceWhenViewHidden) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_end);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_end);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ TestElement element3(kTestIdentifier3, kTestContext1);
+ element1.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(step1_start.Get())
+ .SetEndCallback(step1_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ // Specify that this element must remain visible:
+ .SetMustRemainVisible(true)
+ .SetStartCallback(step2_start.Get())
+ .SetEndCallback(step2_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element3.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .Build())
+ .Build();
+
+ tracker->Start();
+
+ EXPECT_CALL_IN_SCOPE(step1_start, Run, element2.Show());
+
+ EXPECT_CALLS_IN_SCOPE_2(step1_end, Run, step2_start, Run,
+ element2.Activate());
+
+ EXPECT_CALLS_IN_SCOPE_2(step2_end, Run, aborted,
+ Run(testing::_, element2.identifier(),
+ InteractionSequence::StepType::kActivated),
+ element2.Hide());
+}
+
+TEST(InteractionSequenceTest, DontCancelIfViewDoesNotNeedToRemainVisible) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_end);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_end);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ TestElement element3(kTestIdentifier3, kTestContext1);
+ element1.Show();
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(step1_start.Get())
+ .SetEndCallback(step1_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ // Specify that this element need not remain visible:
+ .SetMustRemainVisible(false)
+ .SetStartCallback(step2_start.Get())
+ .SetEndCallback(step2_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element3.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .Build())
+ .Build();
+
+ tracker->Start();
+
+ EXPECT_CALL_IN_SCOPE(step1_start, Run, element2.Show());
+
+ EXPECT_CALLS_IN_SCOPE_2(step1_end, Run, step2_start, Run,
+ element2.Activate());
+
+ element2.Hide();
+
+ EXPECT_CALLS_IN_SCOPE_2(step2_end, Run, completed, Run, element3.Show());
+}
+
+TEST(InteractionSequenceTest,
+ MultipleSequencesInDifferentContextsOneCompletes) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted2);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed2);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier1, kTestContext2);
+ element1.Show();
+ element2.Show();
+
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element1.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step.Get())
+ .Build())
+ .Build();
+
+ auto tracker2 =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted2.Get())
+ .SetCompletedCallback(completed2.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element2))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step2.Get())
+ .Build())
+ .Build();
+
+ tracker->Start();
+ tracker2->Start();
+
+ EXPECT_CALLS_IN_SCOPE_2(step,
+ Run(&element1, element1.identifier(),
+ InteractionSequence::StepType::kActivated),
+ completed, Run, element1.Activate());
+
+ EXPECT_CALL_IN_SCOPE(aborted2, Run, element2.Hide());
+}
+
+TEST(InteractionSequenceTest,
+ MultipleSequencesInDifferentContextsBothComplete) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted2);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed2);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier1, kTestContext2);
+ element1.Show();
+ element2.Show();
+
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element1.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step.Get())
+ .Build())
+ .Build();
+
+ auto tracker2 =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted2.Get())
+ .SetCompletedCallback(completed2.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element2))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step2.Get())
+ .Build())
+ .Build();
+
+ tracker->Start();
+ tracker2->Start();
+
+ EXPECT_CALLS_IN_SCOPE_2(step,
+ Run(&element1, element1.identifier(),
+ InteractionSequence::StepType::kActivated),
+ completed, Run, element1.Activate());
+
+ EXPECT_CALLS_IN_SCOPE_2(step2,
+ Run(&element2, element2.identifier(),
+ InteractionSequence::StepType::kActivated),
+ completed2, Run, element2.Activate());
+}
+
+// These tests verify that events sent during callbacks (as might be used by an
+// interactive UI test powered by an InteractionSequence) do not break the
+// sequence.
+
+TEST(InteractionSequenceTest, ShowDuringCallback) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_end);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { element2.Show(); };
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element1.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(
+ base::BindLambdaForTesting(std::move(callback)))
+ .SetEndCallback(step1_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(step2_start.Get())
+ .Build())
+ .Build();
+
+ tracker->Start();
+ EXPECT_CALLS_IN_SCOPE_3(step1_end, Run, step2_start, Run, completed, Run,
+ element1.Activate());
+}
+
+TEST(InteractionSequenceTest, HideDuringCallback) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_end);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+ element2.Show();
+
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { element2.Hide(); };
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element1.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(
+ base::BindLambdaForTesting(std::move(callback)))
+ .SetEndCallback(step1_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kHidden)
+ .SetStartCallback(step2_start.Get())
+ .Build())
+ .Build();
+
+ tracker->Start();
+ EXPECT_CALLS_IN_SCOPE_3(step1_end, Run, step2_start, Run, completed, Run,
+ element1.Activate());
+}
+
+TEST(InteractionSequenceTest, ActivateDuringCallbackDifferentView) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_end);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+ element2.Show();
+
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { element2.Activate(); };
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element1.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(
+ base::BindLambdaForTesting(std::move(callback)))
+ .SetEndCallback(step1_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step2_start.Get())
+ .Build())
+ .Build();
+
+ tracker->Start();
+ EXPECT_CALLS_IN_SCOPE_3(step1_end, Run, step2_start, Run, completed, Run,
+ element1.Activate());
+}
+
+TEST(InteractionSequenceTest, ActivateDuringCallbackSameView) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_end);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { element2.Activate(); };
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(
+ base::BindLambdaForTesting(std::move(callback)))
+ .SetEndCallback(step1_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step2_start.Get())
+ .Build())
+ .Build();
+
+ tracker->Start();
+ EXPECT_CALLS_IN_SCOPE_3(step1_end, Run, step2_start, Run, completed, Run,
+ element2.Show());
+}
+
+TEST(InteractionSequenceTest, HideAfterActivateDoesntAbort) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ TestElement element3(kTestIdentifier3, kTestContext1);
+ element1.Show();
+ element3.Show();
+
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) {
+ element2.Activate();
+ element2.Hide();
+ };
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(
+ base::BindLambdaForTesting(std::move(callback)))
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element3.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .Build())
+ .Build();
+
+ tracker->Start();
+ EXPECT_CALL_IN_SCOPE(completed, Run, element2.Show());
+}
+
+TEST(InteractionSequenceTest, HideDuringStepStartedCallbackAborts) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { element2.Hide(); };
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(
+ base::BindLambdaForTesting(std::move(callback)))
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .Build())
+ .Build();
+
+ tracker->Start();
+ EXPECT_CALL_IN_SCOPE(aborted, Run, element2.Show());
+}
+
+TEST(InteractionSequenceTest, HideDuringStepEndedCallbackAborts) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_end);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { element2.Hide(); };
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(
+ &element1, InteractionSequence::StepCallback(),
+ base::BindLambdaForTesting(std::move(callback))))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetMustBeVisibleAtStart(true)
+ .SetStartCallback(step2_start.Get())
+ .SetEndCallback(step2_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .Build())
+ .Build();
+
+ EXPECT_CALL_IN_SCOPE(aborted, Run, tracker->Start());
+}
+
+TEST(InteractionSequenceTest, ElementHiddenDuringFinalStepStart) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step_end);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { element2.Hide(); };
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetMustRemainVisible(false)
+ .SetStartCallback(base::BindLambdaForTesting(callback))
+ .SetEndCallback(step_end.Get())
+ .Build())
+ .Build();
+
+ tracker->Start();
+ EXPECT_CALLS_IN_SCOPE_2(step_end,
+ Run(nullptr, element2.identifier(),
+ InteractionSequence::StepType::kShown),
+ completed, Run, element2.Show());
+}
+
+TEST(InteractionSequenceTest, ElementHiddenDuringFinalStepEnd) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { element2.Hide(); };
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetMustRemainVisible(false)
+ .SetEndCallback(base::BindLambdaForTesting(callback))
+ .Build())
+ .Build();
+
+ tracker->Start();
+ EXPECT_CALL_IN_SCOPE(completed, Run, element2.Show());
+}
+
+TEST(InteractionSequenceTest, ElementHiddenDuringStepEndDuringAbort) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { element2.Hide(); };
+ auto tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetEndCallback(base::BindLambdaForTesting(callback))
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .Build())
+ .Build();
+
+ tracker->Start();
+ element2.Show();
+
+ // First parameter will be null because during the delete the step end
+ // callback will hide the element, which happens before the abort callback is
+ // called.
+ EXPECT_CALL_IN_SCOPE(aborted,
+ Run(nullptr, element2.identifier(),
+ InteractionSequence::StepType::kShown),
+ tracker.reset());
+}
+
+TEST(InteractionSequenceTest, SequenceDestroyedDuringInitialStepStartCallback) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_end);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ element1.Show();
+
+ std::unique_ptr<InteractionSequence> tracker;
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { tracker.reset(); };
+ tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(
+ &element1, base::BindLambdaForTesting(callback), step1_end.Get()))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element1.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .Build())
+ .Build();
+
+ EXPECT_CALLS_IN_SCOPE_2(step1_end, Run, aborted, Run, tracker->Start());
+}
+
+TEST(InteractionSequenceTest, SequenceDestroyedDuringInitialStepEndCallback) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_end);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ element1.Show();
+
+ std::unique_ptr<InteractionSequence> tracker;
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { tracker.reset(); };
+ tracker = InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(
+ &element1, InteractionSequence::StepCallback(),
+ base::BindLambdaForTesting(callback)))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element1.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step2_start.Get())
+ .SetEndCallback(step2_end.Get())
+ .Build())
+ .Build();
+
+ tracker->Start();
+ EXPECT_CALL_IN_SCOPE(aborted, Run, element1.Activate());
+}
+
+TEST(InteractionSequenceTest, SequenceDestroyedDuringInitialStepAbort) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_end);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_end);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ element1.Show();
+
+ std::unique_ptr<InteractionSequence> tracker;
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { tracker.reset(); };
+ tracker = InteractionSequence::Builder()
+ .SetAbortedCallback(base::BindLambdaForTesting(callback))
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(
+ &element1, step1_start.Get(), step1_end.Get()))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element1.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step2_start.Get())
+ .SetEndCallback(step2_end.Get())
+ .Build())
+ .Build();
+
+ EXPECT_CALL_IN_SCOPE(step1_start, Run, tracker->Start());
+ EXPECT_CALL_IN_SCOPE(step1_end, Run, element1.Hide());
+ EXPECT_FALSE(tracker);
+}
+
+TEST(InteractionSequenceTest, SequenceDestroyedDuringMidSequenceStepStart) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_end);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_end);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+
+ std::unique_ptr<InteractionSequence> tracker;
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { tracker.reset(); };
+ tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(base::BindLambdaForTesting(callback))
+ .SetEndCallback(step1_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step2_start.Get())
+ .SetEndCallback(step2_end.Get())
+ .Build())
+ .Build();
+
+ tracker->Start();
+ EXPECT_CALLS_IN_SCOPE_2(step1_end, Run, aborted, Run, element2.Show());
+ EXPECT_FALSE(tracker);
+}
+
+TEST(InteractionSequenceTest, SequenceDestroyedDuringMidSequenceStepEnd) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_end);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+
+ std::unique_ptr<InteractionSequence> tracker;
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { tracker.reset(); };
+ tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(step1_start.Get())
+ .SetEndCallback(base::BindLambdaForTesting(callback))
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step2_start.Get())
+ .SetEndCallback(step2_end.Get())
+ .Build())
+ .Build();
+
+ tracker->Start();
+ EXPECT_CALL_IN_SCOPE(step1_start, Run, element2.Show());
+ EXPECT_CALL_IN_SCOPE(aborted, Run, element2.Activate());
+ EXPECT_FALSE(tracker);
+}
+
+TEST(InteractionSequenceTest, SequenceDestroyedDuringMidSequenceAbort) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_end);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_end);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+
+ std::unique_ptr<InteractionSequence> tracker;
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { tracker.reset(); };
+ tracker = InteractionSequence::Builder()
+ .SetAbortedCallback(base::BindLambdaForTesting(callback))
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(step1_start.Get())
+ .SetEndCallback(step1_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step2_start.Get())
+ .SetEndCallback(step2_end.Get())
+ .Build())
+ .Build();
+
+ tracker->Start();
+ EXPECT_CALL_IN_SCOPE(step1_start, Run, element2.Show());
+ EXPECT_CALL_IN_SCOPE(step1_end, Run, element2.Hide());
+ EXPECT_FALSE(tracker);
+}
+
+TEST(InteractionSequenceTest, SequenceDestroyedDuringFinalStepEnd) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_end);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+
+ std::unique_ptr<InteractionSequence> tracker;
+ auto callback = [&](TrackedElement*, ElementIdentifier,
+ InteractionSequence::StepType) { tracker.reset(); };
+ tracker =
+ InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(step1_start.Get())
+ .SetEndCallback(step1_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step2_start.Get())
+ .SetEndCallback(base::BindLambdaForTesting(callback))
+ .Build())
+ .Build();
+
+ tracker->Start();
+ EXPECT_CALL_IN_SCOPE(step1_start, Run, element2.Show());
+ EXPECT_CALLS_IN_SCOPE_3(step1_end, Run, step2_start, Run, completed, Run,
+ element2.Activate());
+ EXPECT_FALSE(tracker);
+}
+
+TEST(InteractionSequenceTest, SequenceDestroyedDuringCompleted) {
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step1_end);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_start);
+ UNCALLED_MOCK_CALLBACK(InteractionSequence::StepCallback, step2_end);
+ TestElement element1(kTestIdentifier1, kTestContext1);
+ TestElement element2(kTestIdentifier2, kTestContext1);
+ element1.Show();
+
+ std::unique_ptr<InteractionSequence> tracker;
+ auto callback = [&]() { tracker.reset(); };
+ tracker = InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(base::BindLambdaForTesting(callback))
+ .AddStep(InteractionSequence::WithInitialElement(&element1))
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kShown)
+ .SetStartCallback(step1_start.Get())
+ .SetEndCallback(step1_end.Get())
+ .Build())
+ .AddStep(InteractionSequence::StepBuilder()
+ .SetElementID(element2.identifier())
+ .SetType(InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step2_start.Get())
+ .SetEndCallback(step2_end.Get())
+ .Build())
+ .Build();
+
+ tracker->Start();
+ EXPECT_CALL_IN_SCOPE(step1_start, Run, element2.Show());
+ EXPECT_CALLS_IN_SCOPE_3(step1_end, Run, step2_start, Run, step2_end, Run,
+ element2.Activate());
+ EXPECT_FALSE(tracker);
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/l10n/OWNERS b/chromium/ui/base/l10n/OWNERS
index a3be676b08b..d717b8dabb7 100644
--- a/chromium/ui/base/l10n/OWNERS
+++ b/chromium/ui/base/l10n/OWNERS
@@ -1 +1 @@
-jshin@chromium.org \ No newline at end of file
+jshin@chromium.org
diff --git a/chromium/ui/base/l10n/l10n_font_util.h b/chromium/ui/base/l10n/l10n_font_util.h
index 979be47f05d..a12f23044f0 100644
--- a/chromium/ui/base/l10n/l10n_font_util.h
+++ b/chromium/ui/base/l10n/l10n_font_util.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_BASE_L10N_FONT_UTIL_H_
-#define UI_BASE_L10N_FONT_UTIL_H_
+#ifndef UI_BASE_L10N_L10N_FONT_UTIL_H_
+#define UI_BASE_L10N_L10N_FONT_UTIL_H_
#include "base/component_export.h"
#include "ui/gfx/geometry/size.h"
@@ -27,4 +27,4 @@ int GetLocalizedContentsHeightForFontList(int row_resource_id,
} // namespace ui
-#endif // UI_BASE_L10N_FONT_UTIL_H_
+#endif // UI_BASE_L10N_L10N_FONT_UTIL_H_
diff --git a/chromium/ui/base/l10n/l10n_util.cc b/chromium/ui/base/l10n/l10n_util.cc
index c69597f5aa5..897c5b80b3d 100644
--- a/chromium/ui/base/l10n/l10n_util.cc
+++ b/chromium/ui/base/l10n/l10n_util.cc
@@ -27,7 +27,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
@@ -55,10 +54,13 @@
namespace {
static const char* const kAcceptLanguageList[] = {
- "af", // Afrikaans
- "am", // Amharic
- "an", // Aragonese
- "ar", // Arabic
+ "af", // Afrikaans
+ "am", // Amharic
+ "an", // Aragonese
+ "ar", // Arabic
+#if defined(ENABLE_PSEUDOLOCALES)
+ "ar-XB", // RTL Pseudolocale
+#endif // defined(ENABLE_PSEUDOLOCALES)
"as", // Assamese
"ast", // Asturian
"az", // Azerbaijani
@@ -89,8 +91,11 @@ static const char* const kAcceptLanguageList[] = {
"en-IN", // English (India)
"en-NZ", // English (New Zealand)
"en-US", // English (US)
- "en-ZA", // English (South Africa)
- "eo", // Esperanto
+#if defined(ENABLE_PSEUDOLOCALES)
+ "en-XA", // Long strings Pseudolocale
+#endif // defined(ENABLE_PSEUDOLOCALES)
+ "en-ZA", // English (South Africa)
+ "eo", // Esperanto
// TODO(jungshik) : Do we want to list all es-Foo for Latin-American
// Spanish speaking countries?
"es", // Spanish
@@ -609,6 +614,15 @@ std::u16string GetDisplayNameForLocale(const std::string& locale,
locale_code = "ro-MD";
std::u16string display_name;
+
+#if defined(ENABLE_PSEUDOLOCALES)
+ if (locale_code == "en-XA") {
+ return u"Long strings pseudolocale (en-XA)";
+ } else if (locale_code == "ar-XB") {
+ return u"RTL pseudolocale (ar-XB)";
+ }
+#endif // defined(ENABLE_PSEUDOLOCALES)
+
#if defined(OS_IOS)
// Use the Foundation API to get the localized display name, removing the need
// for the ICU data file to include this data.
diff --git a/chromium/ui/base/linux/linux_ui_delegate.cc b/chromium/ui/base/linux/linux_ui_delegate.cc
new file mode 100644
index 00000000000..7b0aefd4311
--- /dev/null
+++ b/chromium/ui/base/linux/linux_ui_delegate.cc
@@ -0,0 +1,46 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/linux/linux_ui_delegate.h"
+
+#include "base/callback.h"
+#include "base/notreached.h"
+
+namespace ui {
+
+// static
+LinuxUiDelegate* LinuxUiDelegate::instance_ = nullptr;
+
+// static
+LinuxUiDelegate* LinuxUiDelegate::GetInstance() {
+ return instance_;
+}
+
+LinuxUiDelegate::LinuxUiDelegate() {
+ DCHECK(!instance_);
+ instance_ = this;
+}
+
+LinuxUiDelegate::~LinuxUiDelegate() {
+ DCHECK_EQ(instance_, this);
+ instance_ = nullptr;
+}
+
+bool LinuxUiDelegate::SetWidgetTransientFor(
+ uint32_t parent_widget,
+ base::OnceCallback<void(const std::string&)> callback) {
+ // This function should not be called when using a platform that doesn't
+ // implement it.
+ NOTREACHED();
+ return false;
+}
+
+int LinuxUiDelegate::GetKeyState() {
+ // This function should not be called when using a platform that doesn't
+ // implement it.
+ NOTREACHED();
+ return 0;
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/linux/linux_ui_delegate.h b/chromium/ui/base/linux/linux_ui_delegate.h
new file mode 100644
index 00000000000..1ed7f90c366
--- /dev/null
+++ b/chromium/ui/base/linux/linux_ui_delegate.h
@@ -0,0 +1,44 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_LINUX_LINUX_UI_DELEGATE_H_
+#define UI_BASE_LINUX_LINUX_UI_DELEGATE_H_
+
+#include <cstdint>
+#include <string>
+
+#include "base/callback_forward.h"
+#include "base/component_export.h"
+
+namespace ui {
+
+enum class LinuxUiBackend {
+ kX11,
+ kWayland,
+};
+
+class COMPONENT_EXPORT(UI_BASE) LinuxUiDelegate {
+ public:
+ static LinuxUiDelegate* GetInstance();
+
+ LinuxUiDelegate();
+ virtual ~LinuxUiDelegate();
+
+ virtual LinuxUiBackend GetBackend() const = 0;
+
+ // Only implemented on Wayland.
+ virtual bool SetWidgetTransientFor(
+ uint32_t parent_widget,
+ base::OnceCallback<void(const std::string&)> callback);
+
+ // Only implemented on Wayland.
+ virtual int GetKeyState();
+
+ private:
+ static LinuxUiDelegate* instance_;
+};
+
+} // namespace ui
+
+#endif // UI_BASE_LINUX_LINUX_UI_DELEGATE_H_
diff --git a/chromium/ui/base/metadata/OWNERS b/chromium/ui/base/metadata/OWNERS
new file mode 100644
index 00000000000..657bd638ff5
--- /dev/null
+++ b/chromium/ui/base/metadata/OWNERS
@@ -0,0 +1 @@
+kylixrd@chromium.org
diff --git a/chromium/ui/base/metadata/base_type_conversion.cc b/chromium/ui/base/metadata/base_type_conversion.cc
new file mode 100644
index 00000000000..431cd6cc06f
--- /dev/null
+++ b/chromium/ui/base/metadata/base_type_conversion.cc
@@ -0,0 +1,602 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/metadata/base_type_conversion.h"
+
+#include <cmath>
+#include <string>
+
+#include "base/containers/fixed_flat_set.h"
+#include "base/no_destructor.h"
+#include "base/numerics/ranges.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_tokenizer.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time_delta_from_string.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/skia/include/core/SkScalar.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace ui {
+namespace metadata {
+
+const char kNoPrefix[] = "";
+const char kSkColorPrefix[] = "--";
+
+std::u16string PointerToString(const void* pointer_val) {
+ return pointer_val ? u"(assigned)" : u"(not assigned)";
+}
+
+const std::u16string& GetNullOptStr() {
+ static const base::NoDestructor<std::u16string> kNullOptStr(u"<Empty>");
+ return *kNullOptStr;
+}
+
+/***** String Conversions *****/
+
+#define CONVERT_NUMBER_TO_STRING(T) \
+ std::u16string TypeConverter<T>::ToString(T source_value) { \
+ return base::NumberToString16(source_value); \
+ }
+
+CONVERT_NUMBER_TO_STRING(int8_t)
+CONVERT_NUMBER_TO_STRING(int16_t)
+CONVERT_NUMBER_TO_STRING(int32_t)
+CONVERT_NUMBER_TO_STRING(int64_t)
+CONVERT_NUMBER_TO_STRING(uint8_t)
+CONVERT_NUMBER_TO_STRING(uint16_t)
+CONVERT_NUMBER_TO_STRING(uint32_t)
+CONVERT_NUMBER_TO_STRING(uint64_t)
+CONVERT_NUMBER_TO_STRING(float)
+CONVERT_NUMBER_TO_STRING(double)
+
+std::u16string TypeConverter<bool>::ToString(bool source_value) {
+ return source_value ? u"true" : u"false";
+}
+
+ValidStrings TypeConverter<bool>::GetValidStrings() {
+ return {u"false", u"true"};
+}
+
+std::u16string TypeConverter<const char*>::ToString(const char* source_value) {
+ return base::UTF8ToUTF16(source_value);
+}
+
+std::u16string TypeConverter<base::FilePath>::ToString(
+ const base::FilePath& source_value) {
+ return source_value.AsUTF16Unsafe();
+}
+
+std::u16string TypeConverter<std::u16string>::ToString(
+ const std::u16string& source_value) {
+ return source_value;
+}
+
+std::u16string TypeConverter<base::TimeDelta>::ToString(
+ const base::TimeDelta& source_value) {
+ return base::NumberToString16(source_value.InSecondsF()) + u"s";
+}
+
+std::u16string TypeConverter<gfx::Insets>::ToString(
+ const gfx::Insets& source_value) {
+ return base::ASCIIToUTF16(source_value.ToString());
+}
+
+std::u16string TypeConverter<gfx::Point>::ToString(
+ const gfx::Point& source_value) {
+ return base::ASCIIToUTF16(source_value.ToString());
+}
+
+std::u16string TypeConverter<gfx::PointF>::ToString(
+ const gfx::PointF& source_value) {
+ return base::ASCIIToUTF16(source_value.ToString());
+}
+
+std::u16string TypeConverter<gfx::Range>::ToString(
+ const gfx::Range& source_value) {
+ return base::ASCIIToUTF16(source_value.ToString());
+}
+
+std::u16string TypeConverter<gfx::Rect>::ToString(
+ const gfx::Rect& source_value) {
+ return base::ASCIIToUTF16(source_value.ToString());
+}
+
+std::u16string TypeConverter<gfx::RectF>::ToString(
+ const gfx::RectF& source_value) {
+ return base::ASCIIToUTF16(source_value.ToString());
+}
+
+std::u16string TypeConverter<gfx::ShadowValues>::ToString(
+ const gfx::ShadowValues& source_value) {
+ std::u16string ret = u"[";
+ for (auto shadow_value : source_value) {
+ ret += u" " + base::ASCIIToUTF16(shadow_value.ToString()) + u";";
+ }
+
+ ret[ret.length() - 1] = ' ';
+ ret += u"]";
+ return ret;
+}
+
+std::u16string TypeConverter<gfx::Size>::ToString(
+ const gfx::Size& source_value) {
+ return base::ASCIIToUTF16(source_value.ToString());
+}
+
+std::u16string TypeConverter<gfx::SizeF>::ToString(
+ const gfx::SizeF& source_value) {
+ return base::ASCIIToUTF16(source_value.ToString());
+}
+
+std::u16string TypeConverter<std::string>::ToString(
+ const std::string& source_value) {
+ return base::UTF8ToUTF16(source_value);
+}
+
+std::u16string TypeConverter<url::Component>::ToString(
+ const url::Component& source_value) {
+ return base::ASCIIToUTF16(
+ base::StringPrintf("{%d,%d}", source_value.begin, source_value.len));
+}
+
+absl::optional<int8_t> TypeConverter<int8_t>::FromString(
+ const std::u16string& source_value) {
+ int32_t ret = 0;
+ if (base::StringToInt(source_value, &ret) &&
+ base::IsValueInRangeForNumericType<int8_t>(ret)) {
+ return static_cast<int8_t>(ret);
+ }
+ return absl::nullopt;
+}
+
+absl::optional<int16_t> TypeConverter<int16_t>::FromString(
+ const std::u16string& source_value) {
+ int32_t ret = 0;
+ if (base::StringToInt(source_value, &ret) &&
+ base::IsValueInRangeForNumericType<int16_t>(ret)) {
+ return static_cast<int16_t>(ret);
+ }
+ return absl::nullopt;
+}
+
+absl::optional<int32_t> TypeConverter<int32_t>::FromString(
+ const std::u16string& source_value) {
+ int value;
+ return base::StringToInt(source_value, &value) ? absl::make_optional(value)
+ : absl::nullopt;
+}
+
+absl::optional<int64_t> TypeConverter<int64_t>::FromString(
+ const std::u16string& source_value) {
+ int64_t value;
+ return base::StringToInt64(source_value, &value) ? absl::make_optional(value)
+ : absl::nullopt;
+}
+
+absl::optional<uint8_t> TypeConverter<uint8_t>::FromString(
+ const std::u16string& source_value) {
+ unsigned ret = 0;
+ if (base::StringToUint(source_value, &ret) &&
+ base::IsValueInRangeForNumericType<uint8_t>(ret)) {
+ return static_cast<uint8_t>(ret);
+ }
+ return absl::nullopt;
+}
+
+absl::optional<uint16_t> TypeConverter<uint16_t>::FromString(
+ const std::u16string& source_value) {
+ unsigned ret = 0;
+ if (base::StringToUint(source_value, &ret) &&
+ base::IsValueInRangeForNumericType<uint16_t>(ret)) {
+ return static_cast<uint16_t>(ret);
+ }
+ return absl::nullopt;
+}
+
+absl::optional<uint32_t> TypeConverter<uint32_t>::FromString(
+ const std::u16string& source_value) {
+ unsigned value;
+ return base::StringToUint(source_value, &value) ? absl::make_optional(value)
+ : absl::nullopt;
+}
+
+absl::optional<uint64_t> TypeConverter<uint64_t>::FromString(
+ const std::u16string& source_value) {
+ uint64_t value;
+ return base::StringToUint64(source_value, &value) ? absl::make_optional(value)
+ : absl::nullopt;
+}
+
+absl::optional<float> TypeConverter<float>::FromString(
+ const std::u16string& source_value) {
+ if (absl::optional<double> temp =
+ TypeConverter<double>::FromString(source_value))
+ return static_cast<float>(temp.value());
+ return absl::nullopt;
+}
+
+absl::optional<double> TypeConverter<double>::FromString(
+ const std::u16string& source_value) {
+ double value;
+ return base::StringToDouble(base::UTF16ToUTF8(source_value), &value)
+ ? absl::make_optional(value)
+ : absl::nullopt;
+}
+
+absl::optional<bool> TypeConverter<bool>::FromString(
+ const std::u16string& source_value) {
+ const bool is_true = source_value == u"true";
+ if (is_true || source_value == u"false")
+ return is_true;
+ return absl::nullopt;
+}
+
+absl::optional<std::u16string> TypeConverter<std::u16string>::FromString(
+ const std::u16string& source_value) {
+ return source_value;
+}
+
+absl::optional<base::FilePath> TypeConverter<base::FilePath>::FromString(
+ const std::u16string& source_value) {
+ return base::FilePath::FromUTF16Unsafe(source_value);
+}
+
+absl::optional<base::TimeDelta> TypeConverter<base::TimeDelta>::FromString(
+ const std::u16string& source_value) {
+ std::string source = base::UTF16ToUTF8(source_value);
+ return base::TimeDeltaFromString(source);
+}
+
+absl::optional<gfx::Insets> TypeConverter<gfx::Insets>::FromString(
+ const std::u16string& source_value) {
+ const auto values = base::SplitStringPiece(
+ source_value, u",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ int top, left, bottom, right;
+ if ((values.size() == 4) && base::StringToInt(values[0], &top) &&
+ base::StringToInt(values[1], &left) &&
+ base::StringToInt(values[2], &bottom) &&
+ base::StringToInt(values[3], &right)) {
+ return gfx::Insets(top, left, bottom, right);
+ }
+ return absl::nullopt;
+}
+
+absl::optional<gfx::Point> TypeConverter<gfx::Point>::FromString(
+ const std::u16string& source_value) {
+ const auto values = base::SplitStringPiece(
+ source_value, u",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ int x, y;
+ if ((values.size() == 2) && base::StringToInt(values[0], &x) &&
+ base::StringToInt(values[1], &y)) {
+ return gfx::Point(x, y);
+ }
+ return absl::nullopt;
+}
+
+absl::optional<gfx::PointF> TypeConverter<gfx::PointF>::FromString(
+ const std::u16string& source_value) {
+ const auto values = base::SplitStringPiece(
+ source_value, u",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ double x, y;
+ if ((values.size() == 2) && base::StringToDouble(values[0], &x) &&
+ base::StringToDouble(values[1], &y)) {
+ return gfx::PointF(x, y);
+ }
+ return absl::nullopt;
+}
+
+absl::optional<gfx::Range> TypeConverter<gfx::Range>::FromString(
+ const std::u16string& source_value) {
+ const auto values = base::SplitStringPiece(
+ source_value, u"{,}", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ unsigned min, max;
+ if ((values.size() == 2) && base::StringToUint(values[0], &min) &&
+ base::StringToUint(values[1], &max)) {
+ return gfx::Range(min, max);
+ }
+ return absl::nullopt;
+}
+
+absl::optional<gfx::Rect> TypeConverter<gfx::Rect>::FromString(
+ const std::u16string& source_value) {
+ const auto values = base::SplitString(
+ source_value, u" ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ if (values.size() != 2)
+ return absl::nullopt;
+ const absl::optional<gfx::Point> origin =
+ TypeConverter<gfx::Point>::FromString(values[0]);
+ const absl::optional<gfx::Size> size =
+ TypeConverter<gfx::Size>::FromString(values[1]);
+ if (origin && size)
+ return gfx::Rect(*origin, *size);
+ return absl::nullopt;
+}
+
+absl::optional<gfx::RectF> TypeConverter<gfx::RectF>::FromString(
+ const std::u16string& source_value) {
+ const auto values = base::SplitString(
+ source_value, u" ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ if (values.size() != 2)
+ return absl::nullopt;
+ const absl::optional<gfx::PointF> origin =
+ TypeConverter<gfx::PointF>::FromString(values[0]);
+ const absl::optional<gfx::SizeF> size =
+ TypeConverter<gfx::SizeF>::FromString(values[1]);
+ if (origin && size)
+ return gfx::RectF(*origin, *size);
+ return absl::nullopt;
+}
+
+absl::optional<gfx::ShadowValues> TypeConverter<gfx::ShadowValues>::FromString(
+ const std::u16string& source_value) {
+ gfx::ShadowValues ret;
+ const auto shadow_value_strings = base::SplitStringPiece(
+ source_value, u"[;]", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+ for (auto v : shadow_value_strings) {
+ std::u16string value = std::u16string(v);
+ base::String16Tokenizer tokenizer(
+ value, u"(,)", base::String16Tokenizer::WhitespacePolicy::kSkipOver);
+ tokenizer.set_options(base::String16Tokenizer::RETURN_DELIMS);
+ int x, y;
+ double blur;
+ if (tokenizer.GetNext() && tokenizer.token_piece() == u"(" &&
+ tokenizer.GetNext() && base::StringToInt(tokenizer.token_piece(), &x) &&
+ tokenizer.GetNext() && tokenizer.token_piece() == u"," &&
+ tokenizer.GetNext() && base::StringToInt(tokenizer.token_piece(), &y) &&
+ tokenizer.GetNext() && tokenizer.token_piece() == u")" &&
+ tokenizer.GetNext() && tokenizer.token_piece() == u"," &&
+ tokenizer.GetNext() &&
+ base::StringToDouble(tokenizer.token_piece(), &blur) &&
+ tokenizer.GetNext() && tokenizer.token_piece() == u"," &&
+ tokenizer.GetNext()) {
+ const auto color =
+ SkColorConverter::GetNextColor(tokenizer.token_begin(), value.cend());
+ if (color)
+ ret.emplace_back(gfx::Vector2d(x, y), blur, color.value());
+ }
+ }
+ return ret;
+}
+
+absl::optional<gfx::Size> TypeConverter<gfx::Size>::FromString(
+ const std::u16string& source_value) {
+ const auto values = base::SplitStringPiece(
+ source_value, u"x", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ int width, height;
+ if ((values.size() == 2) && base::StringToInt(values[0], &width) &&
+ base::StringToInt(values[1], &height)) {
+ return gfx::Size(width, height);
+ }
+ return absl::nullopt;
+}
+
+absl::optional<gfx::SizeF> TypeConverter<gfx::SizeF>::FromString(
+ const std::u16string& source_value) {
+ const auto values = base::SplitStringPiece(
+ source_value, u"x", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ double width, height;
+ if ((values.size() == 2) && base::StringToDouble(values[0], &width) &&
+ base::StringToDouble(values[1], &height)) {
+ return gfx::SizeF(width, height);
+ }
+ return absl::nullopt;
+}
+
+absl::optional<std::string> TypeConverter<std::string>::FromString(
+ const std::u16string& source_value) {
+ return base::UTF16ToUTF8(source_value);
+}
+
+absl::optional<url::Component> TypeConverter<url::Component>::FromString(
+ const std::u16string& source_value) {
+ const auto values = base::SplitStringPiece(
+ source_value, u"{,}", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ int begin, len;
+ if ((values.size() == 2) && base::StringToInt(values[0], &begin) &&
+ base::StringToInt(values[1], &len) && len >= -1) {
+ return url::Component(begin, len);
+ }
+ return absl::nullopt;
+}
+
+std::u16string TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ToString(
+ SkColor source_value) {
+ return base::UTF8ToUTF16(color_utils::SkColorToRgbaString(source_value));
+}
+
+absl::optional<SkColor> TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::FromString(
+ const std::u16string& source_value) {
+ return GetNextColor(source_value.cbegin(), source_value.cend());
+}
+
+ValidStrings TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetValidStrings() {
+ return {};
+}
+
+bool TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
+ std::u16string::const_iterator start,
+ std::u16string::const_iterator end,
+ std::u16string& color,
+ std::u16string::const_iterator& next_token) {
+ static const auto open_paren = u'(';
+ static const auto close_paren = u')';
+ static constexpr auto schemes = base::MakeFixedFlatSet<base::StringPiece16>(
+ {u"hsl", u"hsla", u"rgb", u"rgba"});
+
+ base::String16Tokenizer tokenizer(
+ start, end, u"(,)", base::String16Tokenizer::WhitespacePolicy::kSkipOver);
+ tokenizer.set_options(base::String16Tokenizer::RETURN_DELIMS);
+ for (; tokenizer.GetNext();) {
+ if (!tokenizer.token_is_delim()) {
+ base::StringPiece16 token = tokenizer.token_piece();
+ std::u16string::const_iterator start_color = tokenizer.token_begin();
+ if (base::ranges::find(schemes.begin(), schemes.end(), token) !=
+ schemes.end()) {
+ if (!tokenizer.GetNext() || *tokenizer.token_begin() != open_paren)
+ return false;
+ for (;
+ tokenizer.GetNext() && *tokenizer.token_begin() != close_paren;) {
+ }
+ if (*tokenizer.token_begin() != close_paren)
+ return false;
+ }
+ next_token = tokenizer.token_end();
+ color = std::u16string(start_color, next_token);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
+ std::u16string::const_iterator start,
+ std::u16string::const_iterator end,
+ std::u16string& color) {
+ std::u16string::const_iterator next_token;
+ return GetNextColor(start, end, color, next_token);
+}
+
+absl::optional<SkColor> TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
+ std::u16string::const_iterator start,
+ std::u16string::const_iterator end,
+ std::u16string::const_iterator& next_token) {
+ std::u16string color;
+ if (GetNextColor(start, end, color, next_token)) {
+ if (base::StartsWith(color, u"hsl", base::CompareCase::SENSITIVE))
+ return ParseHslString(color);
+ if (base::StartsWith(color, u"rgb", base::CompareCase::SENSITIVE))
+ return ParseRgbString(color);
+ if (base::StartsWith(color, u"0x", base::CompareCase::INSENSITIVE_ASCII))
+ return ParseHexString(color);
+ SkColor value;
+ if (base::StringToUint(color, &value))
+ return absl::make_optional(value);
+ }
+ return absl::nullopt;
+}
+
+absl::optional<SkColor> TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
+ std::u16string::const_iterator start,
+ std::u16string::const_iterator end) {
+ std::u16string::const_iterator next_token;
+ return GetNextColor(start, end, next_token);
+}
+
+absl::optional<SkColor>
+TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::RgbaPiecesToSkColor(
+ const std::vector<base::StringPiece16>& pieces,
+ size_t start_piece) {
+ int r, g, b;
+ double a;
+ return ((pieces.size() >= start_piece + 4) &&
+ base::StringToInt(pieces[start_piece], &r) &&
+ base::IsValueInRangeForNumericType<uint8_t>(r) &&
+ base::StringToInt(pieces[start_piece + 1], &g) &&
+ base::IsValueInRangeForNumericType<uint8_t>(g) &&
+ base::StringToInt(pieces[start_piece + 2], &b) &&
+ base::IsValueInRangeForNumericType<uint8_t>(b) &&
+ base::StringToDouble(pieces[start_piece + 3], &a) && a >= 0.0 &&
+ a <= 1.0)
+ ? absl::make_optional(SkColorSetARGB(
+ base::ClampRound<SkAlpha>(a * SK_AlphaOPAQUE), r, g, b))
+ : absl::nullopt;
+}
+
+absl::optional<SkColor>
+TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ParseHexString(
+ const std::u16string& hex_string) {
+ SkColor value;
+ if (base::HexStringToUInt(base::UTF16ToUTF8(hex_string), &value)) {
+ // Add in a 1.0 alpha channel if it wasn't included in the input.
+ if (hex_string.length() <= 8)
+ value = SkColorSetA(value, 0xFF);
+ return absl::make_optional(value);
+ }
+ return absl::nullopt;
+}
+
+absl::optional<SkColor>
+TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ParseHslString(
+ const std::u16string& hsl_string) {
+ std::u16string pruned_string;
+ base::RemoveChars(hsl_string, u"(%)hsla", &pruned_string);
+ const auto values = base::SplitStringPiece(
+ pruned_string, u", ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ double h, s, v;
+ double a = 1.0;
+ if (values.size() >= 3 && values.size() <= 4 &&
+ base::StringToDouble(values[0], &h) &&
+ base::StringToDouble(values[1], &s) &&
+ base::StringToDouble(values[2], &v) &&
+ (values.size() == 3 ||
+ (base::StringToDouble(values[3], &a) && a >= 0.0 && a <= 1.0))) {
+ SkScalar hsv[3];
+ hsv[0] = base::ClampToRange(std::fmod(h, 360.0), 0.0, 360.0);
+ hsv[1] = s > 1.0 ? base::ClampToRange(s, 0.0, 100.0) / 100.0
+ : base::ClampToRange(s, 0.0, 1.0);
+ hsv[2] = v > 1.0 ? base::ClampToRange(v, 0.0, 100.0) / 100.0
+ : base::ClampToRange(v, 0.0, 1.0);
+ return absl::make_optional(
+ SkHSVToColor(base::ClampRound<SkAlpha>(a * SK_AlphaOPAQUE), hsv));
+ }
+ return absl::nullopt;
+}
+
+absl::optional<SkColor>
+TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ParseRgbString(
+ const std::u16string& rgb_string) {
+ // Declare a constant string here for use below since it might trigger an
+ // ASAN error due to the stack temp going out of scope before the call to
+ // RgbaPiecesToSkColor.
+ std::u16string pruned_string;
+ base::RemoveChars(rgb_string, u"()rgba", &pruned_string);
+ auto values = base::SplitStringPiece(
+ pruned_string, u", ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ // if it was just an rgb string, add the 1.0 alpha
+ if (values.size() == 3)
+ values.push_back(u"1.0");
+ return RgbaPiecesToSkColor(values, 0);
+}
+
+} // namespace metadata
+} // namespace ui
+
+DEFINE_ENUM_CONVERTERS(gfx::HorizontalAlignment,
+ {gfx::HorizontalAlignment::ALIGN_LEFT, u"ALIGN_LEFT"},
+ {gfx::HorizontalAlignment::ALIGN_CENTER,
+ u"ALIGN_CENTER"},
+ {gfx::HorizontalAlignment::ALIGN_RIGHT, u"ALIGN_RIGHT"},
+ {gfx::HorizontalAlignment::ALIGN_TO_HEAD,
+ u"ALIGN_TO_HEAD"})
+
+DEFINE_ENUM_CONVERTERS(gfx::VerticalAlignment,
+ {gfx::VerticalAlignment::ALIGN_TOP, u"ALIGN_TOP"},
+ {gfx::VerticalAlignment::ALIGN_MIDDLE, u"ALIGN_MIDDLE"},
+ {gfx::VerticalAlignment::ALIGN_BOTTOM, u"ALIGN_BOTTOM"})
+
+DEFINE_ENUM_CONVERTERS(gfx::ElideBehavior,
+ {gfx::ElideBehavior::NO_ELIDE, u"NO_ELIDE"},
+ {gfx::ElideBehavior::TRUNCATE, u"TRUNCATE"},
+ {gfx::ElideBehavior::ELIDE_HEAD, u"ELIDE_HEAD"},
+ {gfx::ElideBehavior::ELIDE_MIDDLE, u"ELIDE_MIDDLE"},
+ {gfx::ElideBehavior::ELIDE_TAIL, u"ELIDE_TAIL"},
+ {gfx::ElideBehavior::ELIDE_EMAIL, u"ELIDE_EMAIL"},
+ {gfx::ElideBehavior::FADE_TAIL, u"FADE_TAIL"})
+
+DEFINE_ENUM_CONVERTERS(
+ ui::MenuSeparatorType,
+ {ui::MenuSeparatorType::NORMAL_SEPARATOR, u"NORMAL_SEPARATOR"},
+ {ui::MenuSeparatorType::DOUBLE_SEPARATOR, u"DOUBLE_SEPARATOR"},
+ {ui::MenuSeparatorType::UPPER_SEPARATOR, u"UPPER_SEPARATOR"},
+ {ui::MenuSeparatorType::LOWER_SEPARATOR, u"LOWER_SEPARATOR"},
+ {ui::MenuSeparatorType::SPACING_SEPARATOR, u"SPACING_SEPARATOR"},
+ {ui::MenuSeparatorType::VERTICAL_SEPARATOR, u"VERTICAL_SEPARATOR"},
+ {ui::MenuSeparatorType::PADDED_SEPARATOR, u"PADDED_SEPARATOR"})
diff --git a/chromium/ui/base/metadata/base_type_conversion.h b/chromium/ui/base/metadata/base_type_conversion.h
new file mode 100644
index 00000000000..3262802f347
--- /dev/null
+++ b/chromium/ui/base/metadata/base_type_conversion.h
@@ -0,0 +1,378 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_METADATA_BASE_TYPE_CONVERSION_H_
+#define UI_BASE_METADATA_BASE_TYPE_CONVERSION_H_
+
+#include <stdint.h>
+
+#include <algorithm> // Silence broken lint check
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/component_export.h"
+#include "base/containers/fixed_flat_map.h"
+#include "base/files/file_path.h"
+#include "base/ranges/algorithm.h"
+#include "base/ranges/ranges.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/models/menu_separator_types.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/size_f.h"
+#include "ui/gfx/range/range.h"
+#include "ui/gfx/shadow_value.h"
+#include "ui/gfx/text_constants.h"
+#include "url/gurl.h"
+#include "url/third_party/mozilla/url_parse.h"
+
+namespace ui {
+namespace metadata {
+
+using ValidStrings = std::vector<std::u16string>;
+
+// Various metadata methods pass types either by value or const ref depending on
+// whether the types are "small" (defined as "fundamental, enum, or pointer").
+// ArgType<T> gives the appropriate type to use as an argument in such cases.
+template <typename T>
+using ArgType =
+ typename std::conditional<std::is_fundamental<T>::value ||
+ std::is_enum<T>::value ||
+ std::is_pointer<T>::value ||
+ (std::is_move_assignable<T>::value &&
+ std::is_move_constructible<T>::value &&
+ !std::is_copy_assignable<T>::value &&
+ !std::is_copy_constructible<T>::value),
+ T,
+ const T&>::type;
+
+COMPONENT_EXPORT(UI_BASE) extern const char kNoPrefix[];
+COMPONENT_EXPORT(UI_BASE) extern const char kSkColorPrefix[];
+
+// General Type Conversion Template Functions ---------------------------------
+template <bool serializable,
+ bool read_only = false,
+ const char* name_prefix = kNoPrefix>
+struct BaseTypeConverter {
+ static constexpr bool is_serializable = serializable;
+ static constexpr bool is_read_only = read_only;
+ static bool IsSerializable() { return is_serializable; }
+ static bool IsReadOnly() { return is_read_only; }
+ static const char* PropertyNamePrefix() { return name_prefix; }
+};
+
+template <typename T>
+struct TypeConverter : BaseTypeConverter<std::is_enum<T>::value> {
+ static std::u16string ToString(ArgType<T> source_value);
+ static absl::optional<T> FromString(const std::u16string& source_value);
+ static ValidStrings GetValidStrings();
+};
+
+// The following definitions and macros are needed only in cases where a type
+// is a mere alias to a POD type AND a specialized type converter is also needed
+// to handle different the string conversions different from the existing POD
+// type converter. See SkColor below as an example of their use.
+// NOTE: This should be a rare occurrence and if possible use a unique type and
+// a TypeConverter specialization based on that unique type.
+
+template <typename T, typename K>
+struct Uniquifier {
+ using type = T;
+ using tag = K;
+};
+
+#define MAKE_TYPE_UNIQUE(type_name) \
+ struct type_name##Tag {}; \
+ using type_name##Unique = \
+ ::ui::metadata::Uniquifier<type_name, type_name##Tag>
+
+#define _UNIQUE_TYPE_NAME1(type_name) type_name##Unique
+
+#define _UNIQUE_TYPE_NAME2(qualifier, type_name) qualifier::type_name##Unique
+
+#define _GET_TYPE_MACRO(_1, _2, NAME, ...) NAME
+
+#define UNIQUE_TYPE_NAME(name, ...) \
+ _GET_TYPE_MACRO(name, ##__VA_ARGS__, _UNIQUE_TYPE_NAME2, _UNIQUE_TYPE_NAME1) \
+ (name, ##__VA_ARGS__)
+
+// Types and macros for generating enum converters ----------------------------
+template <typename T>
+struct EnumStringsMap;
+
+// *****************************************************************
+// * NOTE: The ENUM macros *must* be placed outside any namespace. *
+// *****************************************************************
+//
+// Use this macro only if your enum converters need to be accessible across
+// modules. Place this in the header file for the module and use the other macro
+// below as described.
+//
+#define EXPORT_ENUM_CONVERTERS(T, EXPORT) \
+ template <> \
+ EXPORT std::u16string ui::metadata::TypeConverter<T>::ToString( \
+ ui::metadata::ArgType<T> source_value); \
+ \
+ template <> \
+ EXPORT absl::optional<T> ui::metadata::TypeConverter<T>::FromString( \
+ const std::u16string& str); \
+ \
+ template <> \
+ EXPORT ui::metadata::ValidStrings \
+ ui::metadata::TypeConverter<T>::GetValidStrings();
+
+// Generate the code to define a enum type to and from std::u16string
+// conversions. The first argument is the type T, and the rest of the argument
+// should have the enum value and string pairs defined in a format like
+// "{enum_value0, string16_value0}, {enum_value1, string16_value1} ...".
+// Both enum_values and string16_values need to be compile time constants.
+//
+#define DEFINE_ENUM_CONVERTERS(T, ...) \
+ template <> \
+ struct ui::metadata::EnumStringsMap<T> { \
+ static_assert(std::is_enum<T>::value, "Error: " #T " is not an enum."); \
+ \
+ static const auto& Get() { \
+ static constexpr auto kMap = \
+ base::MakeFixedFlatMap<T, base::StringPiece16>({__VA_ARGS__}); \
+ return kMap; \
+ } \
+ }; \
+ \
+ template <> \
+ std::u16string ui::metadata::TypeConverter<T>::ToString( \
+ ui::metadata::ArgType<T> source_value) { \
+ const auto& map = EnumStringsMap<T>::Get(); \
+ auto* it = map.find(source_value); \
+ return it != map.end() ? std::u16string(it->second) : std::u16string(); \
+ } \
+ \
+ template <> \
+ absl::optional<T> ui::metadata::TypeConverter<T>::FromString( \
+ const std::u16string& str) { \
+ const auto& map = EnumStringsMap<T>::Get(); \
+ using Pair = base::ranges::range_value_t<decltype(map)>; \
+ auto* it = base::ranges::find(map, str, &Pair::second); \
+ return it != map.end() ? absl::make_optional(it->first) : absl::nullopt; \
+ } \
+ \
+ template <> \
+ ui::metadata::ValidStrings \
+ ui::metadata::TypeConverter<T>::GetValidStrings() { \
+ ValidStrings string_values; \
+ base::ranges::transform( \
+ EnumStringsMap<T>::Get(), std::back_inserter(string_values), \
+ [](const auto& pair) { return std::u16string(pair.second); }); \
+ return string_values; \
+ }
+
+// String Conversions ---------------------------------------------------------
+
+COMPONENT_EXPORT(UI_BASE)
+std::u16string PointerToString(const void* pointer_val);
+
+#define DECLARE_CONVERSIONS(T) \
+ template <> \
+ struct COMPONENT_EXPORT(UI_BASE) \
+ TypeConverter<T> : BaseTypeConverter<true> { \
+ static std::u16string ToString(ArgType<T> source_value); \
+ static absl::optional<T> FromString(const std::u16string& source_value); \
+ static ValidStrings GetValidStrings() { return {}; } \
+ };
+
+DECLARE_CONVERSIONS(int8_t)
+DECLARE_CONVERSIONS(int16_t)
+DECLARE_CONVERSIONS(int32_t)
+DECLARE_CONVERSIONS(int64_t)
+DECLARE_CONVERSIONS(uint8_t)
+DECLARE_CONVERSIONS(uint16_t)
+DECLARE_CONVERSIONS(uint32_t)
+DECLARE_CONVERSIONS(uint64_t)
+DECLARE_CONVERSIONS(float)
+DECLARE_CONVERSIONS(double)
+DECLARE_CONVERSIONS(const char*)
+DECLARE_CONVERSIONS(base::FilePath)
+DECLARE_CONVERSIONS(std::u16string)
+DECLARE_CONVERSIONS(base::TimeDelta)
+DECLARE_CONVERSIONS(gfx::Insets)
+DECLARE_CONVERSIONS(gfx::Point)
+DECLARE_CONVERSIONS(gfx::PointF)
+DECLARE_CONVERSIONS(gfx::Range)
+DECLARE_CONVERSIONS(gfx::Rect)
+DECLARE_CONVERSIONS(gfx::RectF)
+DECLARE_CONVERSIONS(gfx::ShadowValues)
+DECLARE_CONVERSIONS(gfx::Size)
+DECLARE_CONVERSIONS(gfx::SizeF)
+DECLARE_CONVERSIONS(std::string)
+DECLARE_CONVERSIONS(url::Component)
+
+#undef DECLARE_CONVERSIONS
+
+template <>
+struct COMPONENT_EXPORT(UI_BASE) TypeConverter<bool> : BaseTypeConverter<true> {
+ static std::u16string ToString(bool source_value);
+ static absl::optional<bool> FromString(const std::u16string& source_value);
+ static ValidStrings GetValidStrings();
+};
+
+// Special conversions for wrapper types --------------------------------------
+
+COMPONENT_EXPORT(UI_BASE) const std::u16string& GetNullOptStr();
+
+template <typename T>
+struct TypeConverter<absl::optional<T>>
+ : BaseTypeConverter<TypeConverter<T>::is_serializable> {
+ static std::u16string ToString(ArgType<absl::optional<T>> source_value) {
+ if (!source_value)
+ return GetNullOptStr();
+ return TypeConverter<T>::ToString(source_value.value());
+ }
+ static absl::optional<absl::optional<T>> FromString(
+ const std::u16string& source_value) {
+ if (source_value == GetNullOptStr())
+ return absl::make_optional<absl::optional<T>>(absl::nullopt);
+
+ auto ret = TypeConverter<T>::FromString(source_value);
+ return ret ? absl::make_optional(ret) : absl::nullopt;
+ }
+ static ValidStrings GetValidStrings() { return {}; }
+};
+
+// Special Conversions for std:unique_ptr<T> and T* types ----------------------
+
+template <typename T>
+struct TypeConverter<std::unique_ptr<T>> : BaseTypeConverter<false, true> {
+ static std::u16string ToString(const std::unique_ptr<T>& source_value) {
+ return PointerToString(source_value.get());
+ }
+ static std::u16string ToString(const T* source_value) {
+ return PointerToString(source_value);
+ }
+ static absl::optional<std::unique_ptr<T>> FromString(
+ const std::u16string& source_value) {
+ DCHECK(false) << "Type converter cannot convert from string.";
+ return absl::nullopt;
+ }
+ static ValidStrings GetValidStrings() { return {}; }
+};
+
+template <typename T>
+struct TypeConverter<T*> : BaseTypeConverter<false, true> {
+ static std::u16string ToString(ArgType<T*> source_value) {
+ return PointerToString(source_value);
+ }
+ static absl::optional<T*> FromString(const std::u16string& source_value) {
+ DCHECK(false) << "Type converter cannot convert from string.";
+ return absl::nullopt;
+ }
+ static ValidStrings GetValidStrings() { return {}; }
+};
+
+template <typename T>
+struct TypeConverter<std::vector<T>>
+ : BaseTypeConverter<TypeConverter<T>::is_serializable> {
+ static std::u16string ToString(ArgType<std::vector<T>> source_value) {
+ std::vector<std::u16string> serialized;
+ base::ranges::transform(source_value, std::back_inserter(serialized),
+ &TypeConverter<T>::ToString);
+ return u"{" + base::JoinString(serialized, u",") + u"}";
+ }
+ static absl::optional<std::vector<T>> FromString(
+ const std::u16string& source_value) {
+ if (source_value.empty() || source_value.front() != u'{' ||
+ source_value.back() != u'}')
+ return absl::nullopt;
+ const auto values =
+ base::SplitString(source_value.substr(1, source_value.length() - 2),
+ u",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ std::vector<T> output;
+ for (const auto& value : values) {
+ auto ret = TypeConverter<T>::FromString(value);
+ if (!ret)
+ return absl::nullopt;
+ output.push_back(*ret);
+ }
+ return absl::make_optional(output);
+ }
+ static ValidStrings GetValidStrings() { return {}; }
+};
+
+MAKE_TYPE_UNIQUE(SkColor);
+
+template <>
+struct COMPONENT_EXPORT(UI_BASE) TypeConverter<UNIQUE_TYPE_NAME(SkColor)>
+ : BaseTypeConverter<true, false, kSkColorPrefix> {
+ static std::u16string ToString(SkColor source_value);
+ static absl::optional<SkColor> FromString(const std::u16string& source_value);
+ static ValidStrings GetValidStrings();
+
+ // Parses a string within |start| and |end| for a color string in the forms
+ // rgb(r, g, b), rgba(r, g, b, a), hsl(h, s%, l%), hsla(h, s%, l%, a),
+ // 0xXXXXXX, 0xXXXXXXXX, <decimal number>
+ // Returns the full string in |color| and the position immediately following
+ // the last token in |next_token|.
+ // Returns false if the input string cannot be properly parsed. |color| and
+ // |next_token| will be undefined.
+ static bool GetNextColor(std::u16string::const_iterator start,
+ std::u16string::const_iterator end,
+ std::u16string& color,
+ std::u16string::const_iterator& next_token);
+ static bool GetNextColor(std::u16string::const_iterator start,
+ std::u16string::const_iterator end,
+ std::u16string& color);
+
+ // Same as above, except returns the color string converted into an |SkColor|.
+ // Returns absl::nullopt if the color string cannot be properly parsed or the
+ // string cannot be converted into a valid SkColor and |next_token| may be
+ // undefined.
+ static absl::optional<SkColor> GetNextColor(
+ std::u16string::const_iterator start,
+ std::u16string::const_iterator end,
+ std::u16string::const_iterator& next_token);
+ static absl::optional<SkColor> GetNextColor(
+ std::u16string::const_iterator start,
+ std::u16string::const_iterator end);
+
+ // Converts the four elements of |pieces| beginning at |start_piece| to an
+ // SkColor by assuming the pieces are split from a string like
+ // "rgba(r,g,b,a)". Returns nullopt if conversion was unsuccessful.
+ static absl::optional<SkColor> RgbaPiecesToSkColor(
+ const std::vector<base::StringPiece16>& pieces,
+ size_t start_piece);
+
+ private:
+ static absl::optional<SkColor> ParseHexString(
+ const std::u16string& hex_string);
+ static absl::optional<SkColor> ParseHslString(
+ const std::u16string& hsl_string);
+ static absl::optional<SkColor> ParseRgbString(
+ const std::u16string& rgb_string);
+};
+
+using SkColorConverter = TypeConverter<UNIQUE_TYPE_NAME(SkColor)>;
+
+} // namespace metadata
+} // namespace ui
+
+EXPORT_ENUM_CONVERTERS(gfx::HorizontalAlignment, COMPONENT_EXPORT(UI_BASE))
+EXPORT_ENUM_CONVERTERS(gfx::VerticalAlignment, COMPONENT_EXPORT(UI_BASE))
+EXPORT_ENUM_CONVERTERS(gfx::ElideBehavior, COMPONENT_EXPORT(UI_BASE))
+EXPORT_ENUM_CONVERTERS(ui::MenuSeparatorType, COMPONENT_EXPORT(UI_BASE))
+
+#endif // UI_BASE_METDATA_BASE_TYPE_CONVERSION_H_ \ No newline at end of file
diff --git a/chromium/ui/base/metadata/base_type_conversion_unittest.cc b/chromium/ui/base/metadata/base_type_conversion_unittest.cc
new file mode 100644
index 00000000000..d4d12888e49
--- /dev/null
+++ b/chromium/ui/base/metadata/base_type_conversion_unittest.cc
@@ -0,0 +1,258 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/metadata/base_type_conversion.h"
+
+#include "base/ranges/ranges.h"
+#include "base/strings/string_tokenizer.h"
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/rect.h"
+//#include "ui/views/controls/button/button.h"
+
+using TypeConversionTest = PlatformTest;
+
+// Used in CheckIsSerializable test case.
+enum TestResult {
+ TEST_TRUE,
+ TEST_FALSE,
+};
+DEFINE_ENUM_CONVERTERS(TestResult, {TEST_TRUE, u"TRUE"}, {TEST_FALSE, u"FALSE"})
+
+TEST_F(TypeConversionTest, TestConversion_IntToString) {
+ int from_int = 5;
+ std::u16string to_string =
+ ui::metadata::TypeConverter<int>::ToString(from_int);
+
+ EXPECT_EQ(to_string, u"5");
+}
+
+TEST_F(TypeConversionTest, TestConversion_StringToInt) {
+ std::u16string from_string = u"10";
+ EXPECT_EQ(ui::metadata::TypeConverter<int>::FromString(from_string), 10);
+}
+
+// This tests whether the converter handles a bogus input string, in which case
+// the return value should be nullopt.
+TEST_F(TypeConversionTest, TestConversion_BogusStringToInt) {
+ std::u16string from_string = u"Foo";
+ EXPECT_EQ(ui::metadata::TypeConverter<int>::FromString(from_string),
+ absl::nullopt);
+}
+
+TEST_F(TypeConversionTest, TestConversion_BogusStringToFloat) {
+ std::u16string from_string = u"1.2";
+ EXPECT_EQ(ui::metadata::TypeConverter<float>::FromString(from_string), 1.2f);
+}
+
+TEST_F(TypeConversionTest, TestConversion_OptionalIntToString) {
+ absl::optional<int> src;
+ std::u16string to_string =
+ ui::metadata::TypeConverter<absl::optional<int>>::ToString(src);
+ EXPECT_EQ(to_string, ui::metadata::GetNullOptStr());
+
+ src = 5;
+ to_string = ui::metadata::TypeConverter<absl::optional<int>>::ToString(src);
+ EXPECT_EQ(to_string, u"5");
+}
+
+TEST_F(TypeConversionTest, TestConversion_StringToOptionalInt) {
+ absl::optional<int> ret;
+ EXPECT_EQ(ui::metadata::TypeConverter<absl::optional<int>>::FromString(
+ ui::metadata::GetNullOptStr()),
+ absl::make_optional(ret));
+
+ EXPECT_EQ(ui::metadata::TypeConverter<absl::optional<int>>::FromString(u"10"),
+ 10);
+
+ EXPECT_EQ(
+ ui::metadata::TypeConverter<absl::optional<int>>::FromString(u"ab0"),
+ absl::nullopt);
+}
+
+TEST_F(TypeConversionTest, TestConversion_ShadowValuesToString) {
+ gfx::ShadowValues shadow_values;
+ shadow_values.emplace_back(gfx::Vector2d(1, 2), .3,
+ SkColorSetARGB(128, 255, 0, 0));
+
+ EXPECT_EQ(
+ ui::metadata::TypeConverter<gfx::ShadowValues>::ToString(shadow_values),
+ u"[ (1,2),0.30,rgba(255,0,0,128) ]");
+
+ shadow_values.emplace_back(gfx::Vector2d(9, 8), .76,
+ SkColorSetARGB(20, 0, 64, 255));
+
+ EXPECT_EQ(
+ ui::metadata::TypeConverter<gfx::ShadowValues>::ToString(shadow_values),
+ u"[ (1,2),0.30,rgba(255,0,0,128); (9,8),0.76,rgba(0,64,255,20) ]");
+}
+
+TEST_F(TypeConversionTest, TestConversion_StringToShadowValues) {
+ absl::optional<gfx::ShadowValues> opt_result =
+ ui::metadata::TypeConverter<gfx::ShadowValues>::FromString(
+ u"[ (6,4),0.53,rgba(23,44,0,1); (93,83),4.33,rgba(10,20,0,0.059) ]");
+
+ EXPECT_EQ(opt_result.has_value(), true);
+ gfx::ShadowValues result = opt_result.value();
+ EXPECT_EQ(result.size(), 2U);
+
+ EXPECT_EQ(result[0].color(), SkColorSetARGB(255, 23, 44, 0));
+ EXPECT_EQ(result[1].color(), SkColorSetARGB(15, 10, 20, 0));
+
+ EXPECT_EQ(result[0].x(), 6);
+ EXPECT_EQ(result[1].x(), 93);
+
+ EXPECT_EQ(result[0].y(), 4);
+ EXPECT_EQ(result[1].y(), 83);
+
+ EXPECT_EQ(result[0].blur(), 0.53);
+ EXPECT_EQ(result[1].blur(), 4.33);
+}
+
+TEST_F(TypeConversionTest, TestConversion_SkColorConversions) {
+ // Check conversion from rgb hex string
+ absl::optional<SkColor> result =
+ ui::metadata::SkColorConverter::FromString(u"0x112233");
+ EXPECT_TRUE(result);
+ EXPECT_EQ(result.value(), SkColorSetRGB(0x11, 0x22, 0x33));
+
+ // Check conversion from argb hex string
+ result = ui::metadata::SkColorConverter::FromString(u"0x7F112233");
+ EXPECT_TRUE(result);
+ EXPECT_EQ(result.value(), SkColorSetARGB(0x7F, 0x11, 0x22, 0x33));
+
+ // Check conversion from rgb(r,g,b) string
+ result = ui::metadata::SkColorConverter::FromString(u"rgb(0, 128, 192)");
+ EXPECT_TRUE(result);
+ EXPECT_EQ(result.value(), SkColorSetRGB(0, 128, 192));
+
+ // Check conversion from rgba(r,g,b,a) string
+ result =
+ ui::metadata::SkColorConverter::FromString(u"rgba(0, 128, 192, 0.5)");
+ EXPECT_TRUE(result);
+ EXPECT_EQ(result.value(), SkColorSetARGB(128, 0, 128, 192));
+
+ // Check conversion from hsl(h,s,l) string
+ result = ui::metadata::SkColorConverter::FromString(u"hsl(195, 100%, 50%)");
+ EXPECT_TRUE(result);
+ const SkScalar hsv[3] = {195.0, 1.0, 0.5};
+ EXPECT_EQ(result.value(), SkHSVToColor(hsv));
+
+ // Check conversion from hsla(h,s,l,a) string
+ result =
+ ui::metadata::SkColorConverter::FromString(u"hsl(195, 100%, 50%, 0.5)");
+ EXPECT_TRUE(result);
+ EXPECT_EQ(result.value(), SkHSVToColor(128, hsv));
+
+ // Check conversion from a decimal integer value
+ result = ui::metadata::SkColorConverter::FromString(u"4278239231");
+ EXPECT_TRUE(result);
+ EXPECT_EQ(result.value(), SkColorSetARGB(255, 0, 191, 255));
+
+ // Check without commas.
+ result = ui::metadata::SkColorConverter::FromString(u"rgba(92 92 92 1)");
+ EXPECT_TRUE(result);
+ EXPECT_EQ(result.value(), SkColorSetARGB(255, 92, 92, 92));
+
+ // Don't support the CSS hash color style
+ result = ui::metadata::SkColorConverter::FromString(u"#03254");
+ EXPECT_FALSE(result);
+
+ // Don't support some common invalid values
+ result = ui::metadata::SkColorConverter::FromString(u"rgba(1,2,3,4)");
+ EXPECT_FALSE(result);
+
+ result = ui::metadata::SkColorConverter::FromString(u"rgba(1,2,3,4");
+ EXPECT_FALSE(result);
+
+ result = ui::metadata::SkColorConverter::FromString(u"hsla(1,2,3,4)");
+ EXPECT_FALSE(result);
+}
+
+TEST_F(TypeConversionTest, TestConversion_ColorParserTest) {
+ using converter = ui::metadata::SkColorConverter;
+ std::u16string color;
+ const std::u16string source =
+ u"rgb(0, 128, 192), hsl(90, 100%, 30%), rgba(128, 128, 128, 0.5), "
+ u"hsla(240, 100%, 50%, 0.5)";
+ auto start_pos = source.cbegin();
+ EXPECT_TRUE(
+ converter::GetNextColor(start_pos, source.cend(), color, start_pos));
+ EXPECT_EQ(color, u"rgb(0, 128, 192)");
+ EXPECT_TRUE(
+ converter::GetNextColor(start_pos, source.cend(), color, start_pos));
+ EXPECT_EQ(color, u"hsl(90, 100%, 30%)");
+ EXPECT_TRUE(
+ converter::GetNextColor(start_pos, source.cend(), color, start_pos));
+ EXPECT_EQ(color, u"rgba(128, 128, 128, 0.5)");
+ EXPECT_TRUE(converter::GetNextColor(start_pos, source.cend(), color));
+ EXPECT_EQ(color, u"hsla(240, 100%, 50%, 0.5)");
+}
+
+TEST_F(TypeConversionTest, TestConversion_InsetsToString) {
+ constexpr gfx::Insets kInsets(3, 5, 7, 9);
+
+ std::u16string to_string =
+ ui::metadata::TypeConverter<gfx::Insets>::ToString(kInsets);
+
+ EXPECT_EQ(to_string, base::ASCIIToUTF16(kInsets.ToString()));
+}
+
+TEST_F(TypeConversionTest, TestConversion_StringToInsets) {
+ std::u16string from_string = u"2,3,4,5";
+ EXPECT_EQ(ui::metadata::TypeConverter<gfx::Insets>::FromString(from_string),
+ gfx::Insets(2, 3, 4, 5));
+}
+
+TEST_F(TypeConversionTest, TestConversion_VectorToString) {
+ const std::vector<int> kVector{3, 5, 7, 9};
+
+ std::u16string to_string =
+ ui::metadata::TypeConverter<std::vector<int>>::ToString(kVector);
+
+ EXPECT_EQ(to_string, u"{3,5,7,9}");
+}
+
+TEST_F(TypeConversionTest, TestConversion_StringToVector) {
+ std::u16string from_string = u"{2,3,4,5}";
+ EXPECT_EQ(
+ ui::metadata::TypeConverter<std::vector<int>>::FromString(from_string),
+ std::vector<int>({2, 3, 4, 5}));
+}
+
+TEST_F(TypeConversionTest, CheckIsSerializable) {
+ // Test types with explicitly added converters.
+ EXPECT_TRUE(ui::metadata::TypeConverter<int8_t>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<int16_t>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<int32_t>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<int64_t>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<uint8_t>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<uint16_t>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<uint32_t>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<uint64_t>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<float>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<double>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<bool>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<const char*>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<std::u16string>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<gfx::ShadowValues>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<gfx::Size>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<gfx::Range>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<gfx::Insets>::IsSerializable());
+
+ // Test enum type.
+ EXPECT_TRUE(ui::metadata::TypeConverter<TestResult>::IsSerializable());
+
+ // Test aliased types.
+ EXPECT_TRUE(ui::metadata::TypeConverter<int>::IsSerializable());
+ EXPECT_TRUE(ui::metadata::TypeConverter<SkColor>::IsSerializable());
+
+ // Test absl::optional type.
+ EXPECT_TRUE(ui::metadata::TypeConverter<
+ absl::optional<const char*>>::IsSerializable());
+ EXPECT_TRUE(
+ ui::metadata::TypeConverter<absl::optional<int>>::IsSerializable());
+}
diff --git a/chromium/ui/views/metadata/metadata_cache.cc b/chromium/ui/base/metadata/metadata_cache.cc
index d37abba27de..4a848f43f66 100644
--- a/chromium/ui/views/metadata/metadata_cache.cc
+++ b/chromium/ui/base/metadata/metadata_cache.cc
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/views/metadata/metadata_cache.h"
+#include "ui/base/metadata/metadata_cache.h"
#include <algorithm>
#include "base/check_op.h"
#include "base/no_destructor.h"
-#include "ui/views/metadata/metadata_types.h"
+#include "ui/base/metadata/metadata_types.h"
-namespace views {
+namespace ui {
namespace metadata {
MetaDataCache::MetaDataCache() = default;
@@ -47,4 +47,4 @@ void RegisterClassInfo(std::unique_ptr<ClassMetaData> meta_data) {
}
} // namespace metadata
-} // namespace views
+} // namespace ui
diff --git a/chromium/ui/views/metadata/metadata_cache.h b/chromium/ui/base/metadata/metadata_cache.h
index f30874d6bb1..70ceaa6e606 100644
--- a/chromium/ui/views/metadata/metadata_cache.h
+++ b/chromium/ui/base/metadata/metadata_cache.h
@@ -2,18 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_METADATA_METADATA_CACHE_H_
-#define UI_VIEWS_METADATA_METADATA_CACHE_H_
+#ifndef UI_BASE_METADATA_METADATA_CACHE_H_
+#define UI_BASE_METADATA_METADATA_CACHE_H_
#include <memory>
#include <utility>
#include <vector>
+#include "base/component_export.h"
#include "base/macros.h"
-#include "ui/views/metadata/metadata_types.h"
-#include "ui/views/views_export.h"
+#include "ui/base/metadata/metadata_types.h"
-namespace views {
+namespace ui {
namespace metadata {
class ClassMetaData;
@@ -23,7 +23,7 @@ class ClassMetaData;
// MetaDataCache is implemented as a singleton. This also implies that each
// instance of ClassMetaData registered into the cache represents one and only
// one class type.
-class VIEWS_EXPORT MetaDataCache {
+class COMPONENT_EXPORT(UI_BASE) MetaDataCache {
public:
MetaDataCache();
@@ -46,7 +46,8 @@ class VIEWS_EXPORT MetaDataCache {
//
// Registers the class metadata into the global cache. Will DCHECK if the
// metadata for a class is already registered.
-VIEWS_EXPORT void RegisterClassInfo(std::unique_ptr<ClassMetaData> meta_data);
+COMPONENT_EXPORT(UI_BASE)
+void RegisterClassInfo(std::unique_ptr<ClassMetaData> meta_data);
// Help function for creating and registering the metadata container into the
// global cache for a given class. The metadata information is owned by the
@@ -60,6 +61,6 @@ ClassMetaData* MakeAndRegisterClassInfo() {
}
} // namespace metadata
-} // namespace views
+} // namespace ui
-#endif // UI_VIEWS_METADATA_METADATA_CACHE_H_
+#endif // UI_BASE_METADATA_METADATA_CACHE_H_
diff --git a/chromium/ui/views/metadata/metadata_header_macros.h b/chromium/ui/base/metadata/metadata_header_macros.h
index f983ac97d30..dba286ea743 100644
--- a/chromium/ui/views/metadata/metadata_header_macros.h
+++ b/chromium/ui/base/metadata/metadata_header_macros.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_METADATA_METADATA_HEADER_MACROS_H_
-#define UI_VIEWS_METADATA_METADATA_HEADER_MACROS_H_
+#ifndef UI_BASE_METADATA_METADATA_HEADER_MACROS_H_
+#define UI_BASE_METADATA_METADATA_HEADER_MACROS_H_
-#include "ui/views/metadata/metadata_macros_internal.h"
+#include "ui/base/metadata/metadata_macros_internal.h"
// Generate Metadata's accessor functions and internal class declaration.
// This should be used in a header file of the View class or its subclasses.
@@ -19,4 +19,4 @@
METADATA_ACCESSORS_INTERNAL_BASE(class_name) \
METADATA_CLASS_INTERNAL(class_name, __FILE__, __LINE__)
-#endif // UI_VIEWS_METADATA_METADATA_HEADER_MACROS_H_
+#endif // UI_BASE_METADATA_METADATA_HEADER_MACROS_H_
diff --git a/chromium/ui/views/metadata/metadata_impl_macros.h b/chromium/ui/base/metadata/metadata_impl_macros.h
index 640d83e6d07..162b8940038 100644
--- a/chromium/ui/views/metadata/metadata_impl_macros.h
+++ b/chromium/ui/base/metadata/metadata_impl_macros.h
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_METADATA_METADATA_IMPL_MACROS_H_
-#define UI_VIEWS_METADATA_METADATA_IMPL_MACROS_H_
+#ifndef UI_BASE_METADATA_METADATA_IMPL_MACROS_H_
+#define UI_BASE_METADATA_METADATA_IMPL_MACROS_H_
#include <memory>
#include <string>
#include <utility>
-#include "ui/views/metadata/metadata_cache.h"
-#include "ui/views/metadata/metadata_macros_internal.h"
-#include "ui/views/metadata/property_metadata.h"
+#include "ui/base/metadata/metadata_cache.h"
+#include "ui/base/metadata/metadata_macros_internal.h"
+#include "ui/base/metadata/property_metadata.h"
// Generate the implementation of the metadata accessors and internal class with
// additional macros for defining the class' properties.
@@ -78,4 +78,4 @@
#property_type); \
AddMemberData(std::move(property_key##_prop));
-#endif // UI_VIEWS_METADATA_METADATA_IMPL_MACROS_H_
+#endif // UI_BASE_METADATA_METADATA_IMPL_MACROS_H_
diff --git a/chromium/ui/views/metadata/metadata_macros_internal.h b/chromium/ui/base/metadata/metadata_macros_internal.h
index 0fb4f6f9441..a87c0879756 100644
--- a/chromium/ui/views/metadata/metadata_macros_internal.h
+++ b/chromium/ui/base/metadata/metadata_macros_internal.h
@@ -2,92 +2,93 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_METADATA_METADATA_MACROS_INTERNAL_H_
-#define UI_VIEWS_METADATA_METADATA_MACROS_INTERNAL_H_
+#ifndef UI_BASE_METADATA_METADATA_MACROS_INTERNAL_H_
+#define UI_BASE_METADATA_METADATA_MACROS_INTERNAL_H_
#include <string>
#include <utility>
#include "base/compiler_specific.h"
-#include "ui/views/metadata/metadata_types.h"
+#include "ui/base/metadata/metadata_types.h"
+#include "ui/base/metadata/property_metadata.h"
// Internal Metadata Generation Helpers ---------------------------------------
#define METADATA_CLASS_NAME_INTERNAL(class_name) class_name##_MetaData
// Metadata Accessors ---------------------------------------------------------
-#define METADATA_ACCESSORS_INTERNAL(class_name) \
- static const char kViewClassName[]; \
- const char* GetClassName() const override; \
- static views::metadata::ClassMetaData* MetaData(); \
- views::metadata::ClassMetaData* GetClassMetaData() override;
+#define METADATA_ACCESSORS_INTERNAL(class_name) \
+ static const char kViewClassName[]; \
+ const char* GetClassName() const override; \
+ static ui::metadata::ClassMetaData* MetaData(); \
+ ui::metadata::ClassMetaData* GetClassMetaData() override;
// A version of METADATA_ACCESSORS_INTERNAL for View, the root of the metadata
// hierarchy; here GetClassName() is not declared as an override.
#define METADATA_ACCESSORS_INTERNAL_BASE(class_name) \
static const char kViewClassName[]; \
virtual const char* GetClassName() const; \
- static views::metadata::ClassMetaData* MetaData(); \
- views::metadata::ClassMetaData* GetClassMetaData() override;
+ static ui::metadata::ClassMetaData* MetaData(); \
+ ui::metadata::ClassMetaData* GetClassMetaData() override;
// Metadata Class -------------------------------------------------------------
-#define METADATA_CLASS_INTERNAL(class_name, file, line) \
- class METADATA_CLASS_NAME_INTERNAL(class_name) \
- : public views::metadata::ClassMetaData { \
- public: \
- using ViewClass = class_name; \
- explicit METADATA_CLASS_NAME_INTERNAL(class_name)() \
- : ClassMetaData(file, line) { \
- BuildMetaData(); \
- } \
- METADATA_CLASS_NAME_INTERNAL(class_name) \
- (const METADATA_CLASS_NAME_INTERNAL(class_name) &) = delete; \
- METADATA_CLASS_NAME_INTERNAL(class_name) & operator=( \
- const METADATA_CLASS_NAME_INTERNAL(class_name) &) = delete; \
- \
- private: \
- friend class class_name; \
- virtual void BuildMetaData(); \
- static views::metadata::ClassMetaData* meta_data_ ALLOW_UNUSED_TYPE; \
+#define METADATA_CLASS_INTERNAL(class_name, file, line) \
+ class METADATA_CLASS_NAME_INTERNAL(class_name) \
+ : public ui::metadata::ClassMetaData { \
+ public: \
+ using TheClass = class_name; \
+ explicit METADATA_CLASS_NAME_INTERNAL(class_name)() \
+ : ClassMetaData(file, line) { \
+ BuildMetaData(); \
+ } \
+ METADATA_CLASS_NAME_INTERNAL(class_name) \
+ (const METADATA_CLASS_NAME_INTERNAL(class_name) &) = delete; \
+ METADATA_CLASS_NAME_INTERNAL(class_name) & operator=( \
+ const METADATA_CLASS_NAME_INTERNAL(class_name) &) = delete; \
+ \
+ private: \
+ friend class class_name; \
+ virtual void BuildMetaData(); \
+ static ui::metadata::ClassMetaData* meta_data_ ALLOW_UNUSED_TYPE; \
}
#define METADATA_PROPERTY_TYPE_INTERNAL(property_type, property_name, ...) \
- views::metadata::ObjectPropertyMetaData< \
- ViewClass, property_type, decltype(&ViewClass::Set##property_name), \
- &ViewClass::Set##property_name, \
- decltype(std::declval<ViewClass>().Get##property_name()), \
- &ViewClass::Get##property_name, ##__VA_ARGS__>
+ ui::metadata::ObjectPropertyMetaData< \
+ TheClass, property_type, decltype(&TheClass::Set##property_name), \
+ &TheClass::Set##property_name, \
+ decltype(std::declval<TheClass>().Get##property_name()), \
+ &TheClass::Get##property_name, ##__VA_ARGS__>
#define METADATA_READONLY_PROPERTY_TYPE_INTERNAL(property_type, property_name, \
...) \
- views::metadata::ObjectPropertyReadOnlyMetaData< \
- ViewClass, property_type, \
- decltype(std::declval<ViewClass>().Get##property_name()), \
- &ViewClass::Get##property_name, ##__VA_ARGS__>
+ ui::metadata::ObjectPropertyReadOnlyMetaData< \
+ TheClass, property_type, \
+ decltype(std::declval<TheClass>().Get##property_name()), \
+ &TheClass::Get##property_name, ##__VA_ARGS__>
#define METADATA_CLASS_PROPERTY_TYPE_INTERNAL(property_type, property_key, \
...) \
- views::metadata::ClassPropertyMetaData<decltype(property_key), \
- property_type, ##__VA_ARGS__>
+ ui::metadata::ClassPropertyMetaData<TheClass, decltype(property_key), \
+ property_type, ##__VA_ARGS__>
#define BEGIN_METADATA_INTERNAL(qualified_class_name, metadata_class_name, \
parent_class_name) \
- views::metadata::ClassMetaData* \
+ ui::metadata::ClassMetaData* \
qualified_class_name::metadata_class_name::meta_data_ = nullptr; \
\
- views::metadata::ClassMetaData* qualified_class_name::MetaData() { \
+ ui::metadata::ClassMetaData* qualified_class_name::MetaData() { \
static_assert( \
std::is_base_of<parent_class_name, qualified_class_name>::value, \
"class not child of parent"); \
if (!qualified_class_name::metadata_class_name::meta_data_) { \
qualified_class_name::metadata_class_name::meta_data_ = \
- views::metadata::MakeAndRegisterClassInfo< \
+ ui::metadata::MakeAndRegisterClassInfo< \
qualified_class_name::metadata_class_name>(); \
} \
return qualified_class_name::metadata_class_name::meta_data_; \
} \
\
- views::metadata::ClassMetaData* qualified_class_name::GetClassMetaData() { \
+ ui::metadata::ClassMetaData* qualified_class_name::GetClassMetaData() { \
return MetaData(); \
} \
\
@@ -102,4 +103,4 @@
#define METADATA_PARENT_CLASS_INTERNAL(parent_class_name) \
SetParentClassMetaData(parent_class_name::MetaData());
-#endif // UI_VIEWS_METADATA_METADATA_MACROS_INTERNAL_H_
+#endif // UI_BASE_METADATA_METADATA_MACROS_INTERNAL_H_
diff --git a/chromium/ui/views/metadata/metadata_types.cc b/chromium/ui/base/metadata/metadata_types.cc
index 9a27ec6e10e..39862c3522e 100644
--- a/chromium/ui/views/metadata/metadata_types.cc
+++ b/chromium/ui/base/metadata/metadata_types.cc
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/views/metadata/metadata_types.h"
+#include "ui/base/metadata/metadata_types.h"
#include <utility>
#include "base/check_op.h"
#include "base/notreached.h"
#include "base/strings/string_util.h"
-#include "ui/views/metadata/type_conversion.h"
+#include "ui/base/metadata/base_type_conversion.h"
-namespace views {
+namespace ui {
namespace metadata {
PropertyFlags operator|(PropertyFlags op1, PropertyFlags op2) {
@@ -33,6 +33,33 @@ bool operator!(PropertyFlags op) {
return !static_cast<bool>(op);
}
+MetaDataProvider::MetaDataProvider() = default;
+
+MetaDataProvider::~MetaDataProvider() = default;
+
+base::CallbackListSubscription MetaDataProvider::AddPropertyChangedCallback(
+ PropertyKey property,
+ PropertyChangedCallback callback) {
+ auto entry = property_changed_vectors_.find(property);
+ if (entry == property_changed_vectors_.end()) {
+ entry = property_changed_vectors_
+ .emplace(property, std::make_unique<PropertyChangedCallbacks>())
+ .first;
+ }
+ PropertyChangedCallbacks* property_changed_callbacks = entry->second.get();
+
+ return property_changed_callbacks->Add(std::move(callback));
+}
+
+void MetaDataProvider::TriggerChangedCallback(PropertyKey property) {
+ auto entry = property_changed_vectors_.find(property);
+ if (entry == property_changed_vectors_.end())
+ return;
+
+ PropertyChangedCallbacks* property_changed_callbacks = entry->second.get();
+ property_changed_callbacks->Notify();
+}
+
ClassMetaData::ClassMetaData() = default;
ClassMetaData::ClassMetaData(std::string file, int line) : line_(line) {
@@ -91,14 +118,14 @@ bool ClassMetaData::ClassMemberIterator::operator==(
current_collection_ == rhs.current_collection_;
}
-ClassMetaData::ClassMemberIterator& ClassMetaData::ClassMemberIterator::
-operator++() {
+ClassMetaData::ClassMemberIterator&
+ClassMetaData::ClassMemberIterator::operator++() {
IncrementHelper();
return *this;
}
-ClassMetaData::ClassMemberIterator ClassMetaData::ClassMemberIterator::
-operator++(int) {
+ClassMetaData::ClassMemberIterator
+ClassMetaData::ClassMemberIterator::operator++(int) {
ClassMetaData::ClassMemberIterator tmp(*this);
IncrementHelper();
return tmp;
@@ -137,7 +164,7 @@ void ClassMetaData::SetTypeName(const std::string& type_name) {
type_name_ = type_name;
}
-void MemberMetaDataBase::SetValueAsString(View* obj,
+void MemberMetaDataBase::SetValueAsString(void* obj,
const std::u16string& new_value) {
NOTREACHED();
}
@@ -151,4 +178,4 @@ MemberMetaDataBase::ValueStrings MemberMetaDataBase::GetValidValues() const {
}
} // namespace metadata
-} // namespace views
+} // namespace ui
diff --git a/chromium/ui/views/metadata/metadata_types.h b/chromium/ui/base/metadata/metadata_types.h
index d4d30174e22..db631ee031d 100644
--- a/chromium/ui/views/metadata/metadata_types.h
+++ b/chromium/ui/base/metadata/metadata_types.h
@@ -2,20 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_METADATA_METADATA_TYPES_H_
-#define UI_VIEWS_METADATA_METADATA_TYPES_H_
+#ifndef UI_BASE_METADATA_METADATA_TYPES_H_
+#define UI_BASE_METADATA_METADATA_TYPES_H_
+#include <map>
#include <memory>
#include <string>
#include <vector>
+#include "base/callback.h"
+#include "base/callback_list.h"
+#include "base/compiler_specific.h"
+#include "base/component_export.h"
#include "base/macros.h"
-#include "ui/views/views_export.h"
-
-namespace views {
-
-class View;
+namespace ui {
namespace metadata {
enum class PropertyFlags : uint32_t {
@@ -34,30 +35,51 @@ enum class PropertyFlags : uint32_t {
kSerializable = 0x100,
};
-VIEWS_EXPORT extern PropertyFlags operator|(PropertyFlags op1,
- PropertyFlags op2);
-VIEWS_EXPORT extern PropertyFlags operator&(PropertyFlags op1,
- PropertyFlags op2);
-VIEWS_EXPORT extern PropertyFlags operator^(PropertyFlags op1,
- PropertyFlags op2);
-VIEWS_EXPORT extern bool operator!(PropertyFlags op);
+COMPONENT_EXPORT(UI_BASE)
+extern PropertyFlags operator|(PropertyFlags op1, PropertyFlags op2);
+COMPONENT_EXPORT(UI_BASE)
+extern PropertyFlags operator&(PropertyFlags op1, PropertyFlags op2);
+COMPONENT_EXPORT(UI_BASE)
+extern PropertyFlags operator^(PropertyFlags op1, PropertyFlags op2);
+COMPONENT_EXPORT(UI_BASE) extern bool operator!(PropertyFlags op);
+
+// Used to identify the CallbackList<> within the PropertyChangedVectors map.
+using PropertyKey = const void*;
+
+using PropertyChangedCallbacks = base::RepeatingClosureList;
+using PropertyChangedCallback = PropertyChangedCallbacks::CallbackType;
// Interface for classes that provide ClassMetaData (via macros in
// metadata_header_macros.h). GetClassMetaData() is automatically overridden and
// implemented in the relevant macros, so a class must merely have
// MetaDataProvider somewhere in its ancestry.
-class MetaDataProvider {
+class COMPONENT_EXPORT(UI_BASE) MetaDataProvider {
public:
+ MetaDataProvider();
+ virtual ~MetaDataProvider();
virtual class ClassMetaData* GetClassMetaData() = 0;
+
+ protected:
+ base::CallbackListSubscription AddPropertyChangedCallback(
+ PropertyKey property,
+ PropertyChangedCallback callback) WARN_UNUSED_RESULT;
+ void TriggerChangedCallback(PropertyKey property);
+
+ private:
+ using PropertyChangedVectors =
+ std::map<PropertyKey, std::unique_ptr<PropertyChangedCallbacks>>;
+
+ // Property Changed Callbacks ------------------------------------------------
+ PropertyChangedVectors property_changed_vectors_;
};
class MemberMetaDataBase;
// Represents the 'meta data' that describes a class. Using the appropriate
-// macros in ui/views/metadata/metadata_impl_macros.h, a descendant of this
+// macros in ui/base/metadata/metadata_impl_macros.h, a descendant of this
// class is declared within the scope of the containing class. See information
// about using the macros in the comment for the views::View class.
-class VIEWS_EXPORT ClassMetaData {
+class COMPONENT_EXPORT(UI_BASE) ClassMetaData {
public:
ClassMetaData();
ClassMetaData(std::string file, int line);
@@ -89,7 +111,7 @@ class VIEWS_EXPORT ClassMetaData {
// for(views::MemberMetaDataBase* member : class_meta_data) {
// OperateOn(member);
// }
- class VIEWS_EXPORT ClassMemberIterator
+ class COMPONENT_EXPORT(UI_BASE) ClassMemberIterator
: public std::iterator<std::forward_iterator_tag, MemberMetaDataBase*> {
public:
ClassMemberIterator(const ClassMemberIterator& other);
@@ -143,7 +165,7 @@ class VIEWS_EXPORT ClassMetaData {
// Abstract base class to represent meta data about class members.
// Provides basic information (such as the name of the member), and templated
// accessors to get/set the value of the member on an object.
-class VIEWS_EXPORT MemberMetaDataBase {
+class COMPONENT_EXPORT(UI_BASE) MemberMetaDataBase {
public:
using ValueStrings = std::vector<std::u16string>;
MemberMetaDataBase(const std::string& member_name,
@@ -156,12 +178,12 @@ class VIEWS_EXPORT MemberMetaDataBase {
// Access the value of this member and return it as a string.
// |obj| is the instance on which to obtain the value of the property this
// metadata represents.
- virtual std::u16string GetValueAsString(View* obj) const = 0;
+ virtual std::u16string GetValueAsString(void* obj) const = 0;
// Set the value of this member through a string on a specified object.
// |obj| is the instance on which to set the value of the property this
// metadata represents.
- virtual void SetValueAsString(View* obj, const std::u16string& new_value);
+ virtual void SetValueAsString(void* obj, const std::u16string& new_value);
// Return various information flags about the property.
virtual PropertyFlags GetPropertyFlags() const = 0;
@@ -186,6 +208,6 @@ class VIEWS_EXPORT MemberMetaDataBase {
}; // class MemberMetaDataBase
} // namespace metadata
-} // namespace views
+} // namespace ui
-#endif // UI_VIEWS_METADATA_METADATA_TYPES_H_
+#endif // UI_BASE_METADATA_METADATA_TYPES_H_
diff --git a/chromium/ui/views/metadata/metadata_unittest.cc b/chromium/ui/base/metadata/metadata_unittest.cc
index 511a6290551..a987df42a9c 100644
--- a/chromium/ui/views/metadata/metadata_unittest.cc
+++ b/chromium/ui/base/metadata/metadata_unittest.cc
@@ -5,17 +5,17 @@
#include <string>
#include "base/bind.h"
+#include "base/callback_list.h"
#include "base/strings/string_number_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#include "ui/base/class_property.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/metadata/metadata_types.h"
#include "ui/gfx/geometry/insets.h"
-#include "ui/views/metadata/metadata_header_macros.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
-#include "ui/views/metadata/metadata_types.h"
-#include "ui/views/view.h"
-namespace VM = views::metadata;
+namespace UM = ui::metadata;
class MetadataTest : public PlatformTest {
public:
@@ -27,13 +27,13 @@ class MetadataTest : public PlatformTest {
protected:
template <typename T>
- VM::MemberMetaDataBase* GetMemberMetaData(T* obj,
+ UM::MemberMetaDataBase* GetMemberMetaData(T* obj,
const std::string& member_name) {
- VM::ClassMetaData* meta_data = obj->GetClassMetaData();
+ UM::ClassMetaData* meta_data = obj->GetClassMetaData();
if (meta_data == nullptr)
return nullptr;
- VM::MemberMetaDataBase* member_data =
+ UM::MemberMetaDataBase* member_data =
meta_data->FindMemberData(member_name);
return member_data;
}
@@ -42,24 +42,25 @@ class MetadataTest : public PlatformTest {
bool float_property_changed_ = false;
};
-// Base view in which a simple hierarchy is created for testing metadata
+// Base class in which a simple hierarchy is created for testing metadata
// iteration across class types.
-class MetadataTestBaseView : public views::View {
+class MetadataTestBaseClass : public ui::metadata::MetaDataProvider,
+ public ui::PropertyHandler {
public:
- MetadataTestBaseView() = default;
- ~MetadataTestBaseView() override = default;
+ MetadataTestBaseClass() = default;
+ ~MetadataTestBaseClass() override = default;
- METADATA_HEADER(MetadataTestBaseView);
+ METADATA_HEADER_BASE(MetadataTestBaseClass);
void SetIntProperty(int new_value) {
if (new_value == int_property_)
return;
int_property_ = new_value;
- OnPropertyChanged(&int_property_, views::kPropertyEffectsNone);
+ TriggerChangedCallback(&int_property_);
}
int GetIntProperty() const { return int_property_; }
base::CallbackListSubscription AddIntPropertyChangedCallback(
- views::PropertyChangedCallback callback) WARN_UNUSED_RESULT {
+ ui::metadata::PropertyChangedCallback callback) WARN_UNUSED_RESULT {
return AddPropertyChangedCallback(&int_property_, std::move(callback));
}
@@ -67,28 +68,28 @@ class MetadataTestBaseView : public views::View {
int int_property_ = 0;
};
-BEGIN_METADATA(MetadataTestBaseView, views::View)
+BEGIN_METADATA_BASE(MetadataTestBaseClass)
ADD_PROPERTY_METADATA(int, IntProperty)
END_METADATA
-// Descendent view in the simple hierarchy. The inherited properties are visible
-// within the metadata.
-class MetadataTestView : public MetadataTestBaseView {
+// Descendent class in the simple hierarchy. The inherited properties are
+// visible within the metadata.
+class MetadataTestClass : public MetadataTestBaseClass {
public:
- MetadataTestView() = default;
- ~MetadataTestView() override = default;
+ MetadataTestClass() = default;
+ ~MetadataTestClass() override = default;
- METADATA_HEADER(MetadataTestView);
+ METADATA_HEADER(MetadataTestClass);
void SetFloatProperty(float new_value) {
if (float_property_ == new_value)
return;
float_property_ = new_value;
- OnPropertyChanged(&float_property_, views::kPropertyEffectsNone);
+ TriggerChangedCallback(&float_property_);
}
float GetFloatProperty() const { return float_property_; }
base::CallbackListSubscription AddFloatPropertyChangedCallback(
- views::PropertyChangedCallback callback) WARN_UNUSED_RESULT {
+ ui::metadata::PropertyChangedCallback callback) WARN_UNUSED_RESULT {
return AddPropertyChangedCallback(&float_property_, std::move(callback));
}
@@ -96,17 +97,17 @@ class MetadataTestView : public MetadataTestBaseView {
float float_property_ = 0.f;
};
-BEGIN_METADATA(MetadataTestView, MetadataTestBaseView)
+BEGIN_METADATA(MetadataTestClass, MetadataTestBaseClass)
ADD_PROPERTY_METADATA(float, FloatProperty)
END_METADATA
// Test view to which class properties are attached.
-class ClassPropertyMetaDataTestView : public views::View {
+class ClassPropertyMetaDataTestClass : public MetadataTestBaseClass {
public:
- ClassPropertyMetaDataTestView() = default;
- ~ClassPropertyMetaDataTestView() override = default;
+ ClassPropertyMetaDataTestClass() = default;
+ ~ClassPropertyMetaDataTestClass() override = default;
- METADATA_HEADER(ClassPropertyMetaDataTestView);
+ METADATA_HEADER(ClassPropertyMetaDataTestClass);
};
DEFINE_UI_CLASS_PROPERTY_KEY(int, kIntKey, -1)
@@ -114,8 +115,9 @@ DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Insets, kOwnedInsetsKey1, nullptr)
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Insets, kOwnedInsetsKey2, nullptr)
DEFINE_UI_CLASS_PROPERTY_KEY(gfx::Insets*, kInsetsKey1, nullptr)
DEFINE_UI_CLASS_PROPERTY_KEY(gfx::Insets*, kInsetsKey2, nullptr)
+DEFINE_UI_CLASS_PROPERTY_TYPE(gfx::Insets*)
-BEGIN_METADATA(ClassPropertyMetaDataTestView, views::View)
+BEGIN_METADATA(ClassPropertyMetaDataTestClass, MetadataTestBaseClass)
ADD_CLASS_PROPERTY_METADATA(int, kIntKey)
ADD_CLASS_PROPERTY_METADATA(gfx::Insets, kOwnedInsetsKey1)
ADD_CLASS_PROPERTY_METADATA(gfx::Insets*, kOwnedInsetsKey2)
@@ -126,57 +128,57 @@ END_METADATA
TEST_F(MetadataTest, TestFloatMetadataPropertyAccess) {
const float start_value = 12.34f;
- MetadataTestView test_obj;
+ MetadataTestClass test_obj;
test_obj.SetFloatProperty(start_value);
- VM::MemberMetaDataBase* member_data =
+ UM::MemberMetaDataBase* member_data =
GetMemberMetaData(&test_obj, "FloatProperty");
ASSERT_TRUE(member_data);
std::u16string member_value = member_data->GetValueAsString(&test_obj);
- CHECK_EQ(member_value, base::NumberToString16(start_value));
+ EXPECT_EQ(member_value, base::NumberToString16(start_value));
}
TEST_F(MetadataTest, TestFloatPropertyChangedCallback) {
const float start_value = 12.34f;
- MetadataTestView test_obj;
+ MetadataTestClass test_obj;
base::CallbackListSubscription callback =
test_obj.AddFloatPropertyChangedCallback(base::BindRepeating(
&MetadataTest::OnFloatPropertyChanged, base::Unretained(this)));
- VM::MemberMetaDataBase* member_data =
+ UM::MemberMetaDataBase* member_data =
GetMemberMetaData(&test_obj, "FloatProperty");
ASSERT_TRUE(member_data);
member_data->SetValueAsString(&test_obj, base::NumberToString16(start_value));
- CHECK(float_property_changed());
+ EXPECT_TRUE(float_property_changed());
std::u16string member_value = member_data->GetValueAsString(&test_obj);
- CHECK_EQ(member_value, base::NumberToString16(start_value));
+ EXPECT_EQ(member_value, base::NumberToString16(start_value));
}
TEST_F(MetadataTest, TestMetaDataParentClassTracking) {
- VM::ClassMetaData* base_class_meta_data = MetadataTestBaseView::MetaData();
- VM::ClassMetaData* derived_class_meta_data = MetadataTestView::MetaData();
+ UM::ClassMetaData* base_class_meta_data = MetadataTestBaseClass::MetaData();
+ UM::ClassMetaData* derived_class_meta_data = MetadataTestClass::MetaData();
- CHECK_EQ(base_class_meta_data,
- derived_class_meta_data->parent_class_meta_data());
+ EXPECT_EQ(base_class_meta_data,
+ derived_class_meta_data->parent_class_meta_data());
}
TEST_F(MetadataTest, TestMetaDataFindParentClassMember) {
- VM::ClassMetaData* derived_class_meta_data = MetadataTestView::MetaData();
+ UM::ClassMetaData* derived_class_meta_data = MetadataTestClass::MetaData();
- VM::MemberMetaDataBase* member_data =
+ UM::MemberMetaDataBase* member_data =
derived_class_meta_data->FindMemberData("IntProperty");
- CHECK_NE(member_data, nullptr);
+ EXPECT_NE(member_data, nullptr);
}
TEST_F(MetadataTest, TestMetaDataMemberIterator) {
- VM::ClassMetaData* derived_class_meta_data = MetadataTestView::MetaData();
+ UM::ClassMetaData* derived_class_meta_data = MetadataTestClass::MetaData();
std::string derived_class_member_name = "IntProperty";
bool found_derived_class_member = false;
@@ -184,7 +186,7 @@ TEST_F(MetadataTest, TestMetaDataMemberIterator) {
std::string base_class_member_name = "IntProperty";
bool found_base_class_member = false;
- for (VM::MemberMetaDataBase* member_data : *derived_class_meta_data) {
+ for (UM::MemberMetaDataBase* member_data : *derived_class_meta_data) {
if (member_data->member_name() == derived_class_member_name)
found_derived_class_member = true;
@@ -192,29 +194,29 @@ TEST_F(MetadataTest, TestMetaDataMemberIterator) {
found_base_class_member = true;
}
- CHECK(found_derived_class_member);
- CHECK(found_base_class_member);
+ EXPECT_TRUE(found_derived_class_member);
+ EXPECT_TRUE(found_base_class_member);
}
TEST_F(MetadataTest, TestTypeCacheContainsTestClass) {
- VM::MetaDataCache* cache = VM::MetaDataCache::GetInstance();
+ UM::MetaDataCache* cache = UM::MetaDataCache::GetInstance();
ASSERT_TRUE(cache != nullptr);
- VM::ClassMetaData* test_class_meta = MetadataTestView::MetaData();
+ UM::ClassMetaData* test_class_meta = MetadataTestClass::MetaData();
const auto& cache_meta = cache->GetCachedTypes();
- CHECK(std::find(cache_meta.begin(), cache_meta.end(), test_class_meta) !=
- cache_meta.end());
+ EXPECT_NE(std::find(cache_meta.begin(), cache_meta.end(), test_class_meta),
+ cache_meta.end());
}
TEST_F(MetadataTest, TestMetaDataFile) {
- VM::ClassMetaData* metadata = MetadataTestBaseView::MetaData();
+ UM::ClassMetaData* metadata = MetadataTestBaseClass::MetaData();
- CHECK_EQ(metadata->file(), "ui/views/metadata/metadata_unittest.cc");
+ EXPECT_EQ(metadata->file(), "ui/base/metadata/metadata_unittest.cc");
}
TEST_F(MetadataTest, TestClassPropertyMetaData) {
- ClassPropertyMetaDataTestView view;
+ ClassPropertyMetaDataTestClass test_class;
gfx::Insets insets1(8, 8, 8, 8), insets2 = insets1;
std::map<std::string, std::u16string> expected_kv = {
@@ -225,24 +227,24 @@ TEST_F(MetadataTest, TestClassPropertyMetaData) {
{"kInsetsKey2", u"(not assigned)"}};
auto verify = [&]() {
- views::metadata::ClassMetaData* metadata = view.GetClassMetaData();
+ ui::metadata::ClassMetaData* metadata = test_class.GetClassMetaData();
for (auto member = metadata->begin(); member != metadata->end(); member++) {
std::string key = (*member)->member_name();
if (expected_kv.count(key)) {
- EXPECT_EQ((*member)->GetValueAsString(&view), expected_kv[key]);
+ EXPECT_EQ((*member)->GetValueAsString(&test_class), expected_kv[key]);
expected_kv.erase(key);
}
}
- EXPECT_EQ(expected_kv.empty(), true);
+ EXPECT_TRUE(expected_kv.empty());
};
verify();
- view.SetProperty(kIntKey, 1);
- view.SetProperty(kOwnedInsetsKey1, insets1);
- view.SetProperty(kOwnedInsetsKey2, insets1);
- view.SetProperty(kInsetsKey1, &insets1);
- view.SetProperty(kInsetsKey2, &insets2);
+ test_class.SetProperty(kIntKey, 1);
+ test_class.SetProperty(kOwnedInsetsKey1, insets1);
+ test_class.SetProperty(kOwnedInsetsKey2, insets1);
+ test_class.SetProperty(kInsetsKey1, &insets1);
+ test_class.SetProperty(kInsetsKey2, &insets2);
expected_kv = {{"kIntKey", u"1"},
{"kOwnedInsetsKey1", u"8,8,8,8"},
diff --git a/chromium/ui/views/metadata/property_metadata.h b/chromium/ui/base/metadata/property_metadata.h
index 3bd28bb68d3..bca6d0f2999 100644
--- a/chromium/ui/views/metadata/property_metadata.h
+++ b/chromium/ui/base/metadata/property_metadata.h
@@ -2,22 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_METADATA_PROPERTY_METADATA_H_
-#define UI_VIEWS_METADATA_PROPERTY_METADATA_H_
+#ifndef UI_BASE_METADATA_PROPERTY_METADATA_H_
+#define UI_BASE_METADATA_PROPERTY_METADATA_H_
#include <string>
#include <type_traits>
#include <utility>
+#include "base/component_export.h"
#include "base/macros.h"
#include "ui/base/class_property.h"
-#include "ui/views/metadata/metadata_cache.h"
-#include "ui/views/metadata/metadata_types.h"
-#include "ui/views/metadata/type_conversion.h"
-#include "ui/views/view.h"
-#include "ui/views/views_export.h"
+#include "ui/base/metadata/base_type_conversion.h"
+#include "ui/base/metadata/metadata_cache.h"
+#include "ui/base/metadata/metadata_types.h"
-namespace views {
+namespace ui {
namespace metadata {
namespace internal {
@@ -62,8 +61,8 @@ template <typename TClass,
typename TValue,
typename TRet,
TRet (TClass::*Get)() const,
- typename TConverter = TypeConverter<TValue>>
-class ObjectPropertyReadOnlyMetaData : public MemberMetaDataBase {
+ typename TConverter = ui::metadata::TypeConverter<TValue>>
+class ObjectPropertyReadOnlyMetaData : public ui::metadata::MemberMetaDataBase {
public:
using MemberMetaDataBase::MemberMetaDataBase;
ObjectPropertyReadOnlyMetaData(const ObjectPropertyReadOnlyMetaData&) =
@@ -72,16 +71,16 @@ class ObjectPropertyReadOnlyMetaData : public MemberMetaDataBase {
const ObjectPropertyReadOnlyMetaData&) = delete;
~ObjectPropertyReadOnlyMetaData() override = default;
- std::u16string GetValueAsString(View* obj) const override {
+ std::u16string GetValueAsString(void* obj) const override {
if (!kTypeIsSerializable && !kTypeIsReadOnly)
return std::u16string();
return TConverter::ToString((static_cast<TClass*>(obj)->*Get)());
}
- PropertyFlags GetPropertyFlags() const override {
- return kTypeIsSerializable
- ? (PropertyFlags::kReadOnly | PropertyFlags::kSerializable)
- : PropertyFlags::kReadOnly;
+ ui::metadata::PropertyFlags GetPropertyFlags() const override {
+ return kTypeIsSerializable ? (ui::metadata::PropertyFlags::kReadOnly |
+ ui::metadata::PropertyFlags::kSerializable)
+ : ui::metadata::PropertyFlags::kReadOnly;
}
const char* GetMemberNamePrefix() const override {
@@ -104,7 +103,7 @@ template <typename TClass,
TSig Set,
typename TRet,
TRet (TClass::*Get)() const,
- typename TConverter = TypeConverter<TValue>>
+ typename TConverter = ui::metadata::TypeConverter<TValue>>
class ObjectPropertyMetaData
: public ObjectPropertyReadOnlyMetaData<TClass,
TValue,
@@ -118,26 +117,27 @@ class ObjectPropertyMetaData
ObjectPropertyMetaData& operator=(const ObjectPropertyMetaData&) = delete;
~ObjectPropertyMetaData() override = default;
- void SetValueAsString(View* obj, const std::u16string& new_value) override {
+ void SetValueAsString(void* obj, const std::u16string& new_value) override {
if (!kTypeIsSerializable || kTypeIsReadOnly)
return;
- if (base::Optional<TValue> result = TConverter::FromString(new_value)) {
+ if (absl::optional<TValue> result = TConverter::FromString(new_value)) {
(static_cast<TClass*>(obj)->*Set)(std::move(result.value()));
}
}
- MemberMetaDataBase::ValueStrings GetValidValues() const override {
+ ui::metadata::MemberMetaDataBase::ValueStrings GetValidValues()
+ const override {
if (!kTypeIsSerializable)
return {};
return TConverter::GetValidStrings();
}
- PropertyFlags GetPropertyFlags() const override {
- PropertyFlags flags = PropertyFlags::kEmpty;
+ ui::metadata::PropertyFlags GetPropertyFlags() const override {
+ ui::metadata::PropertyFlags flags = ui::metadata::PropertyFlags::kEmpty;
if (kTypeIsSerializable)
- flags = flags | PropertyFlags::kSerializable;
+ flags = flags | ui::metadata::PropertyFlags::kSerializable;
if (kTypeIsReadOnly)
- flags = flags | PropertyFlags::kReadOnly;
+ flags = flags | ui::metadata::PropertyFlags::kReadOnly;
return flags;
}
@@ -149,10 +149,11 @@ class ObjectPropertyMetaData
// Represents metadata for a ui::ClassProperty attached on a class instance.
// Converts property value to |TValue| when possible. This allows inspecting
// the actual value when the property is a pointer of type |TValue*|.
-template <typename TKey,
+template <typename TClass,
+ typename TKey,
typename TValue,
- typename TConverter = TypeConverter<TValue>>
-class ClassPropertyMetaData : public MemberMetaDataBase {
+ typename TConverter = ui::metadata::TypeConverter<TValue>>
+class ClassPropertyMetaData : public ui::metadata::MemberMetaDataBase {
public:
using TypeHelper = internal::ClassPropertyMetaDataTypeHelper<TKey, TValue>;
ClassPropertyMetaData(TKey key, const std::string& property_type)
@@ -164,8 +165,9 @@ class ClassPropertyMetaData : public MemberMetaDataBase {
// Returns the property value as a string.
// If the property value is an pointer of type |TKValue*| and
// |TKValue| == |TValue|, dereferences the pointer.
- std::u16string GetValueAsString(View* obj) const override {
- typename TypeHelper::TKValue value = obj->GetProperty(key_);
+ std::u16string GetValueAsString(void* obj) const override {
+ typename TypeHelper::TKValue value =
+ static_cast<TClass*>(obj)->GetProperty(key_);
if (std::is_pointer<typename TypeHelper::TKValue>::value && !value) {
return u"(not assigned)";
} else {
@@ -176,18 +178,18 @@ class ClassPropertyMetaData : public MemberMetaDataBase {
}
}
- void SetValueAsString(View* obj, const std::u16string& new_value) override {
- base::Optional<TValue> value = TConverter::FromString(new_value);
+ void SetValueAsString(void* obj, const std::u16string& new_value) override {
+ absl::optional<TValue> value = TConverter::FromString(new_value);
if (value)
- obj->SetProperty(key_, *value);
+ static_cast<TClass*>(obj)->SetProperty(key_, *value);
}
- PropertyFlags GetPropertyFlags() const override {
- PropertyFlags flags = PropertyFlags::kEmpty;
+ ui::metadata::PropertyFlags GetPropertyFlags() const override {
+ ui::metadata::PropertyFlags flags = ui::metadata::PropertyFlags::kEmpty;
if (kTypeIsSerializable)
- flags = flags | PropertyFlags::kSerializable;
+ flags = flags | ui::metadata::PropertyFlags::kSerializable;
if (kTypeIsReadOnly)
- flags = flags | PropertyFlags::kReadOnly;
+ flags = flags | ui::metadata::PropertyFlags::kReadOnly;
return flags;
}
@@ -199,6 +201,6 @@ class ClassPropertyMetaData : public MemberMetaDataBase {
};
} // namespace metadata
-} // namespace views
+} // namespace ui
-#endif // UI_VIEWS_METADATA_PROPERTY_METADATA_H_
+#endif // UI_BASE_METADATA_PROPERTY_METADATA_H_
diff --git a/chromium/ui/base/models/dialog_model.h b/chromium/ui/base/models/dialog_model.h
index 59ae51833a4..4d870a45dfe 100644
--- a/chromium/ui/base/models/dialog_model.h
+++ b/chromium/ui/base/models/dialog_model.h
@@ -284,7 +284,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModel final {
host_ = host;
}
- const base::Optional<bool>& override_show_close_button(
+ const absl::optional<bool>& override_show_close_button(
base::PassKey<DialogModelHost>) const {
return override_show_close_button_;
}
@@ -295,7 +295,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModel final {
const ImageModel& icon(base::PassKey<DialogModelHost>) const { return icon_; }
- base::Optional<int> initially_focused_field(
+ absl::optional<int> initially_focused_field(
base::PassKey<DialogModelHost>) const {
return initially_focused_field_;
}
@@ -338,18 +338,18 @@ class COMPONENT_EXPORT(UI_BASE) DialogModel final {
std::unique_ptr<DialogModelDelegate> delegate_;
DialogModelHost* host_ = nullptr;
- base::Optional<bool> override_show_close_button_;
+ absl::optional<bool> override_show_close_button_;
bool close_on_deactivate_ = true;
std::u16string title_;
ImageModel icon_;
std::vector<std::unique_ptr<DialogModelField>> fields_;
- base::Optional<int> initially_focused_field_;
+ absl::optional<int> initially_focused_field_;
bool is_alert_dialog_ = false;
- base::Optional<DialogModelButton> ok_button_;
- base::Optional<DialogModelButton> cancel_button_;
- base::Optional<DialogModelButton> extra_button_;
+ absl::optional<DialogModelButton> ok_button_;
+ absl::optional<DialogModelButton> cancel_button_;
+ absl::optional<DialogModelButton> extra_button_;
base::OnceClosure accept_callback_;
base::OnceClosure cancel_callback_;
diff --git a/chromium/ui/base/models/image_model.cc b/chromium/ui/base/models/image_model.cc
index cffa1fab5f0..1ccf83f1011 100644
--- a/chromium/ui/base/models/image_model.cc
+++ b/chromium/ui/base/models/image_model.cc
@@ -6,6 +6,7 @@
#include "ui/base/models/image_model.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/vector_icon_utils.h"
namespace ui {
@@ -13,13 +14,21 @@ VectorIconModel::VectorIconModel() = default;
VectorIconModel::VectorIconModel(const gfx::VectorIcon& vector_icon,
int color_id,
- int icon_size)
- : vector_icon_(&vector_icon), icon_size_(icon_size), color_(color_id) {}
+ int icon_size,
+ const gfx::VectorIcon* badge_icon)
+ : vector_icon_(&vector_icon),
+ icon_size_(icon_size),
+ color_(color_id),
+ badge_icon_(badge_icon) {}
VectorIconModel::VectorIconModel(const gfx::VectorIcon& vector_icon,
SkColor color,
- int icon_size)
- : vector_icon_(&vector_icon), icon_size_(icon_size), color_(color) {}
+ int icon_size,
+ const gfx::VectorIcon* badge_icon)
+ : vector_icon_(&vector_icon),
+ icon_size_(icon_size),
+ color_(color),
+ badge_icon_(badge_icon) {}
VectorIconModel::~VectorIconModel() = default;
@@ -32,8 +41,9 @@ VectorIconModel::VectorIconModel(VectorIconModel&&) = default;
VectorIconModel& VectorIconModel::operator=(VectorIconModel&&) = default;
bool VectorIconModel::operator==(const VectorIconModel& other) const {
- return std::tie(vector_icon_, icon_size_, color_) ==
- std::tie(other.vector_icon_, other.icon_size_, other.color_);
+ return std::tie(vector_icon_, icon_size_, color_, badge_icon_) ==
+ std::tie(other.vector_icon_, other.icon_size_, other.color_,
+ other.badge_icon_);
}
bool VectorIconModel::operator!=(const VectorIconModel& other) const {
@@ -63,15 +73,22 @@ ImageModel& ImageModel::operator=(ImageModel&&) = default;
// static
ImageModel ImageModel::FromVectorIcon(const gfx::VectorIcon& vector_icon,
int color_id,
- int icon_size) {
- return ImageModel(VectorIconModel(vector_icon, color_id, icon_size));
+ int icon_size,
+ const gfx::VectorIcon* badge_icon) {
+ if (!icon_size)
+ icon_size = gfx::GetDefaultSizeOfVectorIcon(vector_icon);
+ return ImageModel(
+ VectorIconModel(vector_icon, color_id, icon_size, badge_icon));
}
// static
ImageModel ImageModel::FromVectorIcon(const gfx::VectorIcon& vector_icon,
SkColor color,
- int icon_size) {
- return ImageModel(VectorIconModel(vector_icon, color, icon_size));
+ int icon_size,
+ const gfx::VectorIcon* badge_icon) {
+ if (!icon_size)
+ icon_size = gfx::GetDefaultSizeOfVectorIcon(vector_icon);
+ return ImageModel(VectorIconModel(vector_icon, color, icon_size, badge_icon));
}
// static
@@ -106,7 +123,7 @@ bool ImageModel::IsImage() const {
gfx::Size ImageModel::Size() const {
if (IsVectorIcon()) {
- const int icon_size = GetVectorIcon().icon_size();
+ const int icon_size = GetVectorIcon().icon_size_;
return gfx::Size(icon_size, icon_size);
}
return IsImage() ? GetImage().Size() : gfx::Size();
diff --git a/chromium/ui/base/models/image_model.h b/chromium/ui/base/models/image_model.h
index 69a0f778677..af0297a2187 100644
--- a/chromium/ui/base/models/image_model.h
+++ b/chromium/ui/base/models/image_model.h
@@ -43,28 +43,31 @@ class COMPONENT_EXPORT(UI_BASE) VectorIconModel {
bool operator==(const VectorIconModel& other) const;
bool operator!=(const VectorIconModel& other) const;
+ const gfx::VectorIcon* vector_icon() const { return vector_icon_; }
+ int icon_size() const { return icon_size_; }
+ int color_id() const { return absl::get<int>(color_); }
+ SkColor color() const { return absl::get<SkColor>(color_); }
+ bool has_color() const { return absl::holds_alternative<SkColor>(color_); }
+ const gfx::VectorIcon* badge_icon() const { return badge_icon_; }
+
private:
- friend class ThemedVectorIcon;
friend class ImageModel;
VectorIconModel(const gfx::VectorIcon& vector_icon,
int color_id,
- int icon_size);
+ int icon_size,
+ const gfx::VectorIcon* badge_icon);
// TODO (kylixrd): This should be eventually removed once all instances of
// hard-coded SkColor constants are removed in favor of using a color id.
VectorIconModel(const gfx::VectorIcon& vector_icon,
SkColor color,
- int icon_size);
-
- const gfx::VectorIcon* vector_icon() const { return vector_icon_; }
- int icon_size() const { return icon_size_; }
- int color_id() const { return absl::get<int>(color_); }
- SkColor color() const { return absl::get<SkColor>(color_); }
- bool has_color() const { return absl::holds_alternative<SkColor>(color_); }
+ int icon_size,
+ const gfx::VectorIcon* badge_icon);
const gfx::VectorIcon* vector_icon_ = nullptr;
int icon_size_ = 0;
absl::variant<int, SkColor> color_ = gfx::kPlaceholderColor;
+ const gfx::VectorIcon* badge_icon_ = nullptr;
};
// ImageModel encapsulates either a gfx::Image or a VectorIconModel. Only one
@@ -82,10 +85,12 @@ class COMPONENT_EXPORT(UI_BASE) ImageModel {
static ImageModel FromVectorIcon(const gfx::VectorIcon& vector_icon,
int color_id = -1,
- int icon_size = 0);
+ int icon_size = 0,
+ const gfx::VectorIcon* badge_icon = nullptr);
static ImageModel FromVectorIcon(const gfx::VectorIcon& vector_icon,
SkColor color,
- int icon_size = 0);
+ int icon_size = 0,
+ const gfx::VectorIcon* badge_icon = nullptr);
static ImageModel FromImage(const gfx::Image& image);
static ImageModel FromImageSkia(const gfx::ImageSkia& image_skia);
static ImageModel FromResourceId(int resource_id);
diff --git a/chromium/ui/base/models/image_model_unittest.cc b/chromium/ui/base/models/image_model_unittest.cc
index 660375004d1..ea116c55609 100644
--- a/chromium/ui/base/models/image_model_unittest.cc
+++ b/chromium/ui/base/models/image_model_unittest.cc
@@ -50,7 +50,8 @@ TEST(ImageModelTest, DefaultVectorIconEmpty) {
}
TEST(ImageModelTest, CheckForVectorIcon) {
- ImageModel image_model = ImageModel::FromVectorIcon(GetCircleVectorIcon());
+ ImageModel image_model =
+ ImageModel::FromVectorIcon(GetCircleVectorIcon(), -1, 16);
EXPECT_FALSE(image_model.IsEmpty());
EXPECT_TRUE(image_model.IsVectorIcon());
@@ -75,7 +76,7 @@ TEST(ImageModelTest, Size) {
TEST(ImageModelTest, CheckAssignVectorIcon) {
VectorIconModel vector_icon_model_dest;
VectorIconModel vector_icon_model_src =
- ImageModel::FromVectorIcon(GetCircleVectorIcon()).GetVectorIcon();
+ ImageModel::FromVectorIcon(GetCircleVectorIcon(), -1, 16).GetVectorIcon();
EXPECT_TRUE(vector_icon_model_dest.is_empty());
EXPECT_FALSE(vector_icon_model_src.is_empty());
@@ -100,7 +101,7 @@ TEST(ImageModelTest, CheckAssignImage) {
EXPECT_TRUE(image_model_dest.IsImage());
EXPECT_FALSE(image_model_dest.IsVectorIcon());
- image_model_src = ImageModel::FromVectorIcon(GetCircleVectorIcon());
+ image_model_src = ImageModel::FromVectorIcon(GetCircleVectorIcon(), -1, 16);
EXPECT_TRUE(image_model_src.IsVectorIcon());
@@ -125,28 +126,28 @@ TEST(ImageModelTest, CheckEqual) {
image_model_src = image_model_dest;
EXPECT_EQ(image_model_src, image_model_dest);
- image_model_dest = ImageModel::FromVectorIcon(GetRectVectorIcon());
+ image_model_dest = ImageModel::FromVectorIcon(GetRectVectorIcon(), -1, 16);
EXPECT_NE(image_model_src, image_model_dest);
- image_model_src = ImageModel::FromVectorIcon(GetRectVectorIcon());
+ image_model_src = ImageModel::FromVectorIcon(GetRectVectorIcon(), -1, 16);
EXPECT_EQ(image_model_src, image_model_dest);
- image_model_dest = ImageModel::FromVectorIcon(GetCircleVectorIcon());
+ image_model_dest = ImageModel::FromVectorIcon(GetCircleVectorIcon(), -1, 16);
EXPECT_NE(image_model_src, image_model_dest);
image_model_src = image_model_dest;
EXPECT_EQ(image_model_src, image_model_dest);
- image_model_src = ImageModel::FromVectorIcon(GetCircleVectorIcon(), 1);
+ image_model_src = ImageModel::FromVectorIcon(GetCircleVectorIcon(), 1, 16);
image_model_dest =
- ImageModel::FromVectorIcon(GetCircleVectorIcon(), SK_ColorMAGENTA);
+ ImageModel::FromVectorIcon(GetCircleVectorIcon(), SK_ColorMAGENTA, 16);
EXPECT_NE(image_model_src, image_model_dest);
- image_model_src = ImageModel::FromVectorIcon(GetCircleVectorIcon(), 1);
- image_model_dest = ImageModel::FromVectorIcon(GetCircleVectorIcon(), 2);
+ image_model_src = ImageModel::FromVectorIcon(GetCircleVectorIcon(), 1, 16);
+ image_model_dest = ImageModel::FromVectorIcon(GetCircleVectorIcon(), 2, 16);
EXPECT_NE(image_model_src, image_model_dest);
image_model_src =
- ImageModel::FromVectorIcon(GetCircleVectorIcon(), SK_ColorCYAN);
+ ImageModel::FromVectorIcon(GetCircleVectorIcon(), SK_ColorCYAN, 16);
image_model_dest =
- ImageModel::FromVectorIcon(GetCircleVectorIcon(), SK_ColorMAGENTA);
+ ImageModel::FromVectorIcon(GetCircleVectorIcon(), SK_ColorMAGENTA, 16);
EXPECT_NE(image_model_src, image_model_dest);
image_model_src =
diff --git a/chromium/ui/base/models/menu_model.cc b/chromium/ui/base/models/menu_model.cc
index d0eb4390321..b2621d4d882 100644
--- a/chromium/ui/base/models/menu_model.cc
+++ b/chromium/ui/base/models/menu_model.cc
@@ -27,6 +27,10 @@ bool MenuModel::IsNewFeatureAt(int index) const {
return false;
}
+ElementIdentifier MenuModel::GetElementIdentifierAt(int index) const {
+ return ElementIdentifier();
+}
+
// static
bool MenuModel::GetModelAndIndexForCommandId(int command_id,
MenuModel** model,
diff --git a/chromium/ui/base/models/menu_model.h b/chromium/ui/base/models/menu_model.h
index 2f8dd2c08a9..279be87a33e 100644
--- a/chromium/ui/base/models/menu_model.h
+++ b/chromium/ui/base/models/menu_model.h
@@ -9,6 +9,7 @@
#include "base/component_export.h"
#include "base/memory/weak_ptr.h"
+#include "ui/base/interaction/element_identifier.h"
#include "ui/base/models/menu_model_delegate.h"
#include "ui/base/models/menu_separator_types.h"
#include "ui/gfx/native_widget_types.h"
@@ -127,6 +128,10 @@ class COMPONENT_EXPORT(UI_BASE) MenuModel
// the appropriate flag is enabled).
virtual bool IsNewFeatureAt(int index) const;
+ // Returns an application-window-unique identifier that can be used to track
+ // the menu item irrespective of menu-specific command IDs.
+ virtual ElementIdentifier GetElementIdentifierAt(int index) const;
+
// Returns the model for the submenu at the specified index.
virtual MenuModel* GetSubmenuModelAt(int index) const = 0;
diff --git a/chromium/ui/base/models/simple_combobox_model.cc b/chromium/ui/base/models/simple_combobox_model.cc
index 42895146ee9..fd2ef3ed090 100644
--- a/chromium/ui/base/models/simple_combobox_model.cc
+++ b/chromium/ui/base/models/simple_combobox_model.cc
@@ -8,22 +8,51 @@
namespace ui {
-SimpleComboboxModel::SimpleComboboxModel(std::vector<std::u16string> items)
+SimpleComboboxModel::Item::Item(std::u16string text) : text(std::move(text)) {}
+SimpleComboboxModel::Item::Item(std::u16string text,
+ std::u16string dropdown_secondary_text,
+ ui::ImageModel icon)
+ : text(std::move(text)),
+ dropdown_secondary_text(std::move(dropdown_secondary_text)),
+ icon(std::move(icon)) {}
+SimpleComboboxModel::Item::Item(const SimpleComboboxModel::Item& other) =
+ default;
+SimpleComboboxModel::Item& SimpleComboboxModel::Item::operator=(
+ const SimpleComboboxModel::Item& other) = default;
+SimpleComboboxModel::Item::Item(SimpleComboboxModel::Item&& other) = default;
+SimpleComboboxModel::Item& SimpleComboboxModel::Item::operator=(
+ SimpleComboboxModel::Item&& other) = default;
+SimpleComboboxModel::Item::~Item() = default;
+
+// static
+SimpleComboboxModel::Item SimpleComboboxModel::Item::CreateSeparator() {
+ return SimpleComboboxModel::Item(std::u16string());
+}
+
+SimpleComboboxModel::SimpleComboboxModel(std::vector<Item> items)
: items_(std::move(items)) {}
-SimpleComboboxModel::~SimpleComboboxModel() {
-}
+SimpleComboboxModel::~SimpleComboboxModel() = default;
int SimpleComboboxModel::GetItemCount() const {
return items_.size();
}
std::u16string SimpleComboboxModel::GetItemAt(int index) const {
- return items_[index];
+ return items_[index].text;
+}
+
+std::u16string SimpleComboboxModel::GetDropDownSecondaryTextAt(
+ int index) const {
+ return items_[index].dropdown_secondary_text;
+}
+
+ui::ImageModel SimpleComboboxModel::GetIconAt(int index) const {
+ return items_[index].icon;
}
bool SimpleComboboxModel::IsItemSeparatorAt(int index) const {
- return items_[index].empty();
+ return items_[index].text.empty();
}
int SimpleComboboxModel::GetDefaultIndex() const {
diff --git a/chromium/ui/base/models/simple_combobox_model.h b/chromium/ui/base/models/simple_combobox_model.h
index 468fdc8e783..c8463d8a93c 100644
--- a/chromium/ui/base/models/simple_combobox_model.h
+++ b/chromium/ui/base/models/simple_combobox_model.h
@@ -8,26 +8,48 @@
#include "base/component_export.h"
#include "base/macros.h"
#include "ui/base/models/combobox_model.h"
+#include "ui/base/models/image_model.h"
#include <vector>
namespace ui {
-// A simple data model for a combobox that takes a string16 vector as the items.
-// An empty string will be a separator.
+// A simple data model for a combobox that takes a vector of
+// SimpleComboboxModel::Item that has support for icons and secondary dropdown
+// text. Items with empty text represent separators.
class COMPONENT_EXPORT(UI_BASE) SimpleComboboxModel : public ComboboxModel {
public:
- explicit SimpleComboboxModel(std::vector<std::u16string> items);
+ struct COMPONENT_EXPORT(UI_BASE) Item {
+ explicit Item(std::u16string text);
+ Item(std::u16string text,
+ std::u16string dropdown_secondary_text,
+ ui::ImageModel icon);
+ Item(const Item& other);
+ Item& operator=(const Item& other);
+ Item(Item&& other);
+ Item& operator=(Item&& other);
+ ~Item();
+
+ static Item CreateSeparator();
+
+ std::u16string text;
+ std::u16string dropdown_secondary_text;
+ ui::ImageModel icon;
+ };
+
+ explicit SimpleComboboxModel(std::vector<Item> items);
~SimpleComboboxModel() override;
// ui::ComboboxModel:
int GetItemCount() const override;
std::u16string GetItemAt(int index) const override;
+ std::u16string GetDropDownSecondaryTextAt(int index) const override;
+ ui::ImageModel GetIconAt(int index) const override;
bool IsItemSeparatorAt(int index) const override;
int GetDefaultIndex() const override;
private:
- const std::vector<std::u16string> items_;
+ const std::vector<Item> items_;
DISALLOW_COPY_AND_ASSIGN(SimpleComboboxModel);
};
diff --git a/chromium/ui/base/models/simple_combobox_model_unittest.cc b/chromium/ui/base/models/simple_combobox_model_unittest.cc
new file mode 100644
index 00000000000..524d6c9e392
--- /dev/null
+++ b/chromium/ui/base/models/simple_combobox_model_unittest.cc
@@ -0,0 +1,43 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/models/simple_combobox_model.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/image/image_unittest_util.h"
+
+namespace ui {
+
+TEST(SimpleComboboxModelTest, StringItems) {
+ std::vector<ui::SimpleComboboxModel::Item> items = {
+ ui::SimpleComboboxModel::Item(u"item0"),
+ ui::SimpleComboboxModel::Item::CreateSeparator(),
+ ui::SimpleComboboxModel::Item(u"item2")};
+ SimpleComboboxModel model(items);
+ EXPECT_EQ(u"item0", model.GetItemAt(0));
+ EXPECT_TRUE(model.IsItemSeparatorAt(1));
+ EXPECT_EQ(u"item2", model.GetItemAt(2));
+}
+
+TEST(SimpleComboboxModelTest, ComboboxItems) {
+ ui::SimpleComboboxModel::Item item16(
+ u"Text16", u"SecondaryText16",
+ ui::ImageModel::FromImage(gfx::test::CreateImage(16, 16)));
+
+ ui::SimpleComboboxModel::Item item20(
+ u"Text20", u"SecondaryText20",
+ ui::ImageModel::FromImage(gfx::test::CreateImage(20, 20)));
+
+ SimpleComboboxModel model({item16, item20});
+ EXPECT_EQ(u"Text16", model.GetItemAt(0));
+ EXPECT_EQ(u"Text16", model.GetDropDownTextAt(0));
+ EXPECT_EQ(u"SecondaryText16", model.GetDropDownSecondaryTextAt(0));
+ EXPECT_EQ(16, model.GetIconAt(0).Size().width());
+ EXPECT_EQ(u"Text20", model.GetItemAt(1));
+ EXPECT_EQ(u"Text20", model.GetDropDownTextAt(1));
+ EXPECT_EQ(u"SecondaryText20", model.GetDropDownSecondaryTextAt(1));
+ EXPECT_EQ(20, model.GetIconAt(1).Size().width());
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/models/simple_menu_model.cc b/chromium/ui/base/models/simple_menu_model.cc
index 016dab77761..976a45c49c8 100644
--- a/chromium/ui/base/models/simple_menu_model.cc
+++ b/chromium/ui/base/models/simple_menu_model.cc
@@ -330,6 +330,11 @@ void SimpleMenuModel::SetMayHaveMnemonicsAt(int index,
items_[ValidateItemIndex(index)].may_have_mnemonics = may_have_mnemonics;
}
+void SimpleMenuModel::SetElementIdentifierAt(int index,
+ ElementIdentifier unique_id) {
+ items_[ValidateItemIndex(index)].unique_id = unique_id;
+}
+
void SimpleMenuModel::Clear() {
items_.clear();
MenuItemsChanged();
@@ -461,6 +466,10 @@ bool SimpleMenuModel::MayHaveMnemonicsAt(int index) const {
return items_[ValidateItemIndex(index)].may_have_mnemonics;
}
+ElementIdentifier SimpleMenuModel::GetElementIdentifierAt(int index) const {
+ return items_[ValidateItemIndex(index)].unique_id;
+}
+
void SimpleMenuModel::ActivatedAt(int index) {
ActivatedAt(index, 0);
}
diff --git a/chromium/ui/base/models/simple_menu_model.h b/chromium/ui/base/models/simple_menu_model.h
index 5ab6c93bb35..6127fb6a161 100644
--- a/chromium/ui/base/models/simple_menu_model.h
+++ b/chromium/ui/base/models/simple_menu_model.h
@@ -170,6 +170,9 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel {
// Sets whether the item at |index| is may have mnemonics.
void SetMayHaveMnemonicsAt(int index, bool may_have_mnemonics);
+ // Sets an application-window unique identifier associated with this menu item
+ // allowing it to be tracked without knowledge of menu-specific command IDs.
+ void SetElementIdentifierAt(int index, ElementIdentifier unique_id);
// Clears all items. Note that it does not free MenuModel of submenu.
void Clear();
@@ -198,6 +201,7 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel {
bool IsAlertedAt(int index) const override;
bool IsNewFeatureAt(int index) const override;
bool MayHaveMnemonicsAt(int index) const override;
+ ElementIdentifier GetElementIdentifierAt(int index) const override;
void ActivatedAt(int index) override;
void ActivatedAt(int index, int event_flags) override;
MenuModel* GetSubmenuModelAt(int index) const override;
@@ -233,6 +237,7 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel {
bool visible = true;
bool is_new_feature = false;
bool may_have_mnemonics = true;
+ ElementIdentifier unique_id;
};
typedef std::vector<Item> ItemVector;
diff --git a/chromium/ui/base/models/simple_menu_model_unittest.cc b/chromium/ui/base/models/simple_menu_model_unittest.cc
index 73d387086a6..691c3b05057 100644
--- a/chromium/ui/base/models/simple_menu_model_unittest.cc
+++ b/chromium/ui/base/models/simple_menu_model_unittest.cc
@@ -16,6 +16,9 @@ namespace ui {
namespace {
+DECLARE_ELEMENT_IDENTIFIER_VALUE(kTestElementID);
+DEFINE_ELEMENT_IDENTIFIER_VALUE(kTestElementID);
+
constexpr int kAlertedCommandId = 2;
class DelegateBase : public SimpleMenuModel::Delegate {
@@ -56,7 +59,7 @@ class DelegateBase : public SimpleMenuModel::Delegate {
}
private:
- base::Optional<int> item_with_icon_;
+ absl::optional<int> item_with_icon_;
DISALLOW_COPY_AND_ASSIGN(DelegateBase);
};
@@ -168,6 +171,18 @@ TEST(SimpleMenuModelTest, SetIsNewFeatureAt) {
ASSERT_TRUE(simple_menu_model.IsNewFeatureAt(1));
}
+TEST(SimpleMenuModelTest, SetElementIdentifierAt) {
+ SimpleMenuModel simple_menu_model(nullptr);
+ simple_menu_model.AddItem(/*command_id*/ 5, u"menu item 0");
+ simple_menu_model.AddItem(/*command_id*/ 6, u"menu item 1");
+
+ simple_menu_model.SetElementIdentifierAt(/*index*/ 1, kTestElementID);
+
+ EXPECT_EQ(ui::ElementIdentifier(),
+ simple_menu_model.GetElementIdentifierAt(0));
+ EXPECT_EQ(kTestElementID, simple_menu_model.GetElementIdentifierAt(1));
+}
+
TEST(SimpleMenuModelTest, HasIconsViaDelegate) {
DelegateBase delegate;
SimpleMenuModel simple_menu_model(&delegate);
@@ -203,7 +218,7 @@ TEST(SimpleMenuModelTest, HasIconsViaVectorIcon) {
simple_menu_model.AddItemWithIcon(
/*command_id*/ 11, u"menu item",
- ui::ImageModel::FromVectorIcon(circle_icon));
+ ui::ImageModel::FromVectorIcon(circle_icon, -1, 16));
EXPECT_TRUE(simple_menu_model.HasIcons());
}
diff --git a/chromium/ui/base/mojom/ui_base_types.mojom b/chromium/ui/base/mojom/ui_base_types.mojom
index 034b4e3963f..73f86c12ec8 100644
--- a/chromium/ui/base/mojom/ui_base_types.mojom
+++ b/chromium/ui/base/mojom/ui_base_types.mojom
@@ -29,6 +29,7 @@ enum ModalType {
// It's mapped to ui::MenuSourceType. Any new type here needs to be synced
// with ui::MenuSourceType in ui_base_types.h.
+[Stable, Extensible, Default=NONE]
enum MenuSourceType {
NONE,
MOUSE,
diff --git a/chromium/ui/base/prediction/empty_predictor.cc b/chromium/ui/base/prediction/empty_predictor.cc
index c1cacb3641c..cefbc244bc9 100644
--- a/chromium/ui/base/prediction/empty_predictor.cc
+++ b/chromium/ui/base/prediction/empty_predictor.cc
@@ -18,7 +18,7 @@ const char* EmptyPredictor::GetName() const {
}
void EmptyPredictor::Reset() {
- last_input_ = base::nullopt;
+ last_input_ = absl::nullopt;
}
void EmptyPredictor::Update(const InputData& cur_input) {
diff --git a/chromium/ui/base/prediction/empty_predictor.h b/chromium/ui/base/prediction/empty_predictor.h
index ebb41b3972e..519f0eb4b2e 100644
--- a/chromium/ui/base/prediction/empty_predictor.h
+++ b/chromium/ui/base/prediction/empty_predictor.h
@@ -6,7 +6,7 @@
#define UI_BASE_PREDICTION_EMPTY_PREDICTOR_H_
#include "base/component_export.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/prediction/input_predictor.h"
namespace ui {
@@ -38,7 +38,7 @@ class COMPONENT_EXPORT(UI_BASE_PREDICTION) EmptyPredictor
private:
// store the last_input_ point for testing
- base::Optional<InputData> last_input_;
+ absl::optional<InputData> last_input_;
DISALLOW_COPY_AND_ASSIGN(EmptyPredictor);
};
diff --git a/chromium/ui/base/prediction/linear_resampling.cc b/chromium/ui/base/prediction/linear_resampling.cc
index 2f0590de7b7..b0dabac18ec 100644
--- a/chromium/ui/base/prediction/linear_resampling.cc
+++ b/chromium/ui/base/prediction/linear_resampling.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
#include "base/strings/string_number_conversions.h"
#include "ui/base/ui_base_features.h"
diff --git a/chromium/ui/base/prediction/prediction_metrics_handler.cc b/chromium/ui/base/prediction/prediction_metrics_handler.cc
index f01862443c8..f8d4354d38c 100644
--- a/chromium/ui/base/prediction/prediction_metrics_handler.cc
+++ b/chromium/ui/base/prediction/prediction_metrics_handler.cc
@@ -11,7 +11,7 @@
namespace ui {
-PredictionMetricsHandler::PredictionMetricsHandler(const char* histogram_name)
+PredictionMetricsHandler::PredictionMetricsHandler(std::string histogram_name)
: histogram_name_(std::move(histogram_name)) {}
PredictionMetricsHandler::~PredictionMetricsHandler() = default;
@@ -110,7 +110,7 @@ void PredictionMetricsHandler::EvaluatePrediction() {
void PredictionMetricsHandler::Reset() {
events_queue_.clear();
predicted_events_queue_.clear();
- last_predicted_ = base::nullopt;
+ last_predicted_ = absl::nullopt;
}
int PredictionMetricsHandler::GetInterpolatedEventForPredictedEvent(
diff --git a/chromium/ui/base/prediction/prediction_metrics_handler.h b/chromium/ui/base/prediction/prediction_metrics_handler.h
index 24167f5954f..55dd4a33ebe 100644
--- a/chromium/ui/base/prediction/prediction_metrics_handler.h
+++ b/chromium/ui/base/prediction/prediction_metrics_handler.h
@@ -6,11 +6,11 @@
#define UI_BASE_PREDICTION_PREDICTION_METRICS_HANDLER_H_
#include <deque>
-#include <unordered_map>
+#include <string>
#include "base/component_export.h"
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/point_f.h"
namespace ui {
@@ -25,7 +25,7 @@ class PredictionMetricsHandlerTest;
// few metrics.
class COMPONENT_EXPORT(UI_BASE_PREDICTION) PredictionMetricsHandler {
public:
- explicit PredictionMetricsHandler(const char* histogram_name);
+ explicit PredictionMetricsHandler(std::string histogram_name);
~PredictionMetricsHandler();
// Struct used to store predicted and real event information.
@@ -100,7 +100,7 @@ class COMPONENT_EXPORT(UI_BASE_PREDICTION) PredictionMetricsHandler {
gfx::PointF last_interpolated_, last_frame_interpolated_;
// Last predicted point that pop from predicted_event_queue_. Use for
// computing Jitter metrics.
- base::Optional<gfx::PointF> last_predicted_ = base::nullopt;
+ absl::optional<gfx::PointF> last_predicted_ = absl::nullopt;
// The first real event position which time is later than the predicted time.
gfx::PointF next_real_;
@@ -108,7 +108,7 @@ class COMPONENT_EXPORT(UI_BASE_PREDICTION) PredictionMetricsHandler {
// names (.OverPrediction, .UnderPrediction, .WrongDirection,
// .PredictionJitter, .VisualJitter) appended to it when counting the metric
// in a histogram.
- const char* const histogram_name_;
+ const std::string histogram_name_;
};
} // namespace ui
diff --git a/chromium/ui/base/resource/OWNERS b/chromium/ui/base/resource/OWNERS
index 56c2d34b387..3591139e952 100644
--- a/chromium/ui/base/resource/OWNERS
+++ b/chromium/ui/base/resource/OWNERS
@@ -1 +1 @@
-per-file *_android.*=file://chrome/browser/android/OWNERS \ No newline at end of file
+per-file *_android.*=file://chrome/browser/android/OWNERS
diff --git a/chromium/ui/base/resource/allowlist.h b/chromium/ui/base/resource/allowlist.h
index 412541cd7f9..040560e7767 100644
--- a/chromium/ui/base/resource/allowlist.h
+++ b/chromium/ui/base/resource/allowlist.h
@@ -36,4 +36,4 @@ __attribute__((used)) constexpr void AllowlistedResource() {}
} // namespace ui
-#endif
+#endif // UI_BASE_RESOURCE_ALLOWLIST_H_
diff --git a/chromium/ui/base/resource/data_pack_unittest.cc b/chromium/ui/base/resource/data_pack_unittest.cc
index 386d1841c5c..25d3063a709 100644
--- a/chromium/ui/base/resource/data_pack_unittest.cc
+++ b/chromium/ui/base/resource/data_pack_unittest.cc
@@ -143,8 +143,8 @@ TEST(DataPackTest, LoadFromFileRegion) {
// by the actual pak file content.
const uint8_t kPadding[5678] = {0};
ASSERT_TRUE(base::WriteFile(data_path, kPadding));
- ASSERT_TRUE(
- base::AppendToFile(data_path, kSamplePakContentsV4, kSamplePakSizeV4));
+ ASSERT_TRUE(base::AppendToFile(
+ data_path, base::StringPiece(kSamplePakContentsV4, kSamplePakSizeV4)));
base::File file(data_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
ASSERT_TRUE(file.IsValid());
diff --git a/chromium/ui/base/resource/mock_resource_bundle_delegate.h b/chromium/ui/base/resource/mock_resource_bundle_delegate.h
index 68b519c3a76..1bf8531a47b 100644
--- a/chromium/ui/base/resource/mock_resource_bundle_delegate.h
+++ b/chromium/ui/base/resource/mock_resource_bundle_delegate.h
@@ -27,7 +27,7 @@ class MockResourceBundleDelegate : public ResourceBundle::Delegate {
base::RefCountedMemory*(int resource_id,
ScaleFactor scale_factor));
MOCK_METHOD1(LoadDataResourceString,
- base::Optional<std::string>(int resource_id));
+ absl::optional<std::string>(int resource_id));
MOCK_CONST_METHOD3(GetRawDataResource,
bool(int resource_id,
ScaleFactor scale_factor,
diff --git a/chromium/ui/base/resource/resource_bundle.cc b/chromium/ui/base/resource/resource_bundle.cc
index bb1381fd20f..65b1649050a 100644
--- a/chromium/ui/base/resource/resource_bundle.cc
+++ b/chromium/ui/base/resource/resource_bundle.cc
@@ -26,6 +26,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
+#include "base/trace_event/base_tracing.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "net/filter/gzip_header.h"
@@ -576,6 +577,14 @@ base::RefCountedMemory* ResourceBundle::LoadDataResourceBytes(
base::RefCountedMemory* ResourceBundle::LoadDataResourceBytesForScale(
int resource_id,
ScaleFactor scale_factor) const {
+ TRACE_EVENT("ui", "ResourceBundle::LoadDataResourceBytesForScale",
+ [&](perfetto::EventContext ctx) {
+ auto* event =
+ ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
+ auto* data = event->set_resource_bundle();
+ data->set_resource_id(resource_id);
+ });
+
if (delegate_) {
base::RefCountedMemory* bytes =
delegate_->LoadDataResourceBytes(resource_id, scale_factor);
@@ -635,7 +644,7 @@ base::StringPiece ResourceBundle::GetRawDataResourceForScale(
std::string ResourceBundle::LoadDataResourceString(int resource_id) const {
if (delegate_) {
- base::Optional<std::string> data =
+ absl::optional<std::string> data =
delegate_->LoadDataResourceString(resource_id);
if (data)
return data.value();
@@ -861,7 +870,7 @@ void ResourceBundle::InitSharedInstance(Delegate* delegate) {
// On platforms other than iOS, 100P is always a supported scale factor.
// For Windows we have a separate case in this function.
supported_scale_factors.push_back(SCALE_FACTOR_100P);
-#if defined(OS_APPLE) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \
+#if defined(OS_MAC) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \
defined(OS_WIN)
supported_scale_factors.push_back(SCALE_FACTOR_200P);
#endif
diff --git a/chromium/ui/base/resource/resource_bundle.h b/chromium/ui/base/resource/resource_bundle.h
index 9487fbaa237..c20987a4b16 100644
--- a/chromium/ui/base/resource/resource_bundle.h
+++ b/chromium/ui/base/resource/resource_bundle.h
@@ -18,9 +18,9 @@
#include "base/files/memory_mapped_file.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/strings/string_piece.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/layout.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/image/image.h"
@@ -128,11 +128,11 @@ class COMPONENT_EXPORT(UI_BASE) ResourceBundle {
ScaleFactor scale_factor) = 0;
// Supports intercepting of ResourceBundle::LoadDataResourceString(): Return
- // a populated base::Optional instance to override the value that
+ // a populated absl::optional instance to override the value that
// ResourceBundle::LoadDataResourceString() would return by default, or an
- // empty base::Optional instance to pass through to the default behavior of
+ // empty absl::optional instance to pass through to the default behavior of
// ResourceBundle::LoadDataResourceString().
- virtual base::Optional<std::string> LoadDataResourceString(
+ virtual absl::optional<std::string> LoadDataResourceString(
int resource_id) = 0;
// Retrieve a raw data resource. Return true if a resource was provided or
diff --git a/chromium/ui/base/resource/resource_bundle_win.h b/chromium/ui/base/resource/resource_bundle_win.h
index 44956d2244a..a4817481416 100644
--- a/chromium/ui/base/resource/resource_bundle_win.h
+++ b/chromium/ui/base/resource/resource_bundle_win.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_BASE_RESOURCE_RESOURCE_BUNDLE_WIN_
-#define UI_BASE_RESOURCE_RESOURCE_BUNDLE_WIN_
+#ifndef UI_BASE_RESOURCE_RESOURCE_BUNDLE_WIN_H_
+#define UI_BASE_RESOURCE_RESOURCE_BUNDLE_WIN_H_
#include "build/build_config.h"
@@ -25,4 +25,4 @@ HCURSOR LoadCursorFromResourcesDataDLL(const wchar_t* cursor_id);
} // namespace ui
-#endif // UI_BASE_RESOURCE_RESOURCE_DATA_DLL_WIN_H_
+#endif // UI_BASE_RESOURCE_RESOURCE_BUNDLE_WIN_H_
diff --git a/chromium/ui/base/scoped_visibility_tracker.h b/chromium/ui/base/scoped_visibility_tracker.h
index 2f53bc552b3..7082ee369b2 100644
--- a/chromium/ui/base/scoped_visibility_tracker.h
+++ b/chromium/ui/base/scoped_visibility_tracker.h
@@ -5,7 +5,6 @@
#ifndef UI_BASE_SCOPED_VISIBILITY_TRACKER_H_
#define UI_BASE_SCOPED_VISIBILITY_TRACKER_H_
-#include <memory>
#include "base/component_export.h"
#include "base/time/time.h"
diff --git a/chromium/ui/base/template_expressions.cc b/chromium/ui/base/template_expressions.cc
index 34064ebadd1..c28d58da732 100644
--- a/chromium/ui/base/template_expressions.cc
+++ b/chromium/ui/base/template_expressions.cc
@@ -9,11 +9,12 @@
#include <ostream>
#include "base/check_op.h"
-#include "base/optional.h"
#include "base/stl_util.h"
+#include "base/strings/string_piece.h"
#include "base/values.h"
#include "build/chromeos_buildflags.h"
#include "net/base/escape.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#if DCHECK_IS_ON()
#include "third_party/re2/src/re2/re2.h" // nogncheck
@@ -94,7 +95,7 @@ std::string PolymerParameterEscape(const std::string& in_string,
}
bool EscapeForJS(const std::string& in_string,
- base::Optional<char> in_previous,
+ absl::optional<char> in_previous,
std::string* out_string) {
out_string->reserve(in_string.size() * 2);
bool last_was_dollar = in_previous && in_previous.value() == '$';
@@ -160,8 +161,7 @@ bool ReplaceTemplateExpressionsInternal(
size_t key_end = source.find(kKeyClose, current_pos);
CHECK_NE(key_end, std::string::npos);
- std::string key =
- source.substr(current_pos, key_end - current_pos).as_string();
+ std::string key(source.substr(current_pos, key_end - current_pos));
CHECK(!key.empty());
auto value = replacements.find(key);
@@ -171,9 +171,9 @@ bool ReplaceTemplateExpressionsInternal(
std::string replacement = value->second;
if (is_javascript) {
// Run JS escaping first.
- base::Optional<char> last = formatted->empty()
- ? base::nullopt
- : base::make_optional(formatted->back());
+ absl::optional<char> last = formatted->empty()
+ ? absl::nullopt
+ : absl::make_optional(formatted->back());
std::string escaped_replacement;
if (!EscapeForJS(replacement, last, &escaped_replacement))
return false;
@@ -240,12 +240,12 @@ bool ReplaceTemplateExpressionsInJS(base::StringPiece source,
// If there are no more templates, copy the remaining JS to the output and
// return true.
if (current_template.type == NONE) {
- formatted->append(remaining.as_string());
+ formatted->append(std::string(remaining));
return true;
}
// Copy the JS before the template to the output.
- formatted->append(remaining.substr(0, current_template.start).as_string());
+ formatted->append(std::string(remaining.substr(0, current_template.start)));
// Retrieve the HTML portion of the source.
base::StringPiece html_template =
diff --git a/chromium/ui/base/ui_base_features.cc b/chromium/ui/base/ui_base_features.cc
index 58662f2778b..55c38066699 100644
--- a/chromium/ui/base/ui_base_features.cc
+++ b/chromium/ui/base/ui_base_features.cc
@@ -58,14 +58,6 @@ bool IsNewShortcutMappingEnabled() {
base::FeatureList::IsEnabled(kNewShortcutMapping);
}
-// This feature supercedes kNewShortcutMapping.
-const base::Feature kImprovedKeyboardShortcuts = {
- "ImprovedKeyboardShortcuts", base::FEATURE_DISABLED_BY_DEFAULT};
-
-bool IsImprovedKeyboardShortcutsEnabled() {
- return base::FeatureList::IsEnabled(kImprovedKeyboardShortcuts);
-}
-
const base::Feature kDeprecateAltClick = {"DeprecateAltClick",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -180,6 +172,28 @@ const base::Feature kPrecisionTouchpadLogging{
"PrecisionTouchpadLogging", base::FEATURE_DISABLED_BY_DEFAULT};
#endif // defined(OS_WIN)
+#if defined(OS_CHROMEOS)
+// This feature supercedes kNewShortcutMapping.
+const base::Feature kImprovedKeyboardShortcuts = {
+ "ImprovedKeyboardShortcuts", base::FEATURE_ENABLED_BY_DEFAULT};
+
+bool IsImprovedKeyboardShortcutsEnabled() {
+ return base::FeatureList::IsEnabled(kImprovedKeyboardShortcuts);
+}
+
+// Whether to deprecate the Alt-Based event rewrites that map to the
+// Page Up/Down, Home/End, Insert/Delete keys. This feature was a
+// part of kImprovedKeyboardShortcuts, but it is being postponed until
+// the new shortcut customization app ships.
+// TODO(crbug.com/1179893): Remove after the customization app ships.
+const base::Feature kDeprecateAltBasedSixPack = {
+ "DeprecateAltBasedSixPack", base::FEATURE_DISABLED_BY_DEFAULT};
+
+bool IsDeprecateAltBasedSixPackEnabled() {
+ return base::FeatureList::IsEnabled(kDeprecateAltBasedSixPack);
+}
+#endif // defined(OS_CHROMEOS)
+
#if defined(OS_WIN) || defined(OS_APPLE) || defined(OS_LINUX) || \
defined(OS_CHROMEOS)
// Enables stylus appearing as touch when in contact with digitizer.
@@ -249,7 +263,7 @@ bool IsUseCommonSelectPopupEnabled() {
// Enables keyboard accessible tooltip.
const base::Feature kKeyboardAccessibleTooltip{
- "KeyboardAccessibleTooltip", base::FEATURE_ENABLED_BY_DEFAULT};
+ "KeyboardAccessibleTooltip", base::FEATURE_DISABLED_BY_DEFAULT};
bool IsKeyboardAccessibleTooltipEnabled() {
static const bool keyboard_accessible_tooltip_enabled =
diff --git a/chromium/ui/base/ui_base_features.h b/chromium/ui/base/ui_base_features.h
index fbcac263e2c..9699e8b8f57 100644
--- a/chromium/ui/base/ui_base_features.h
+++ b/chromium/ui/base/ui_base_features.h
@@ -65,6 +65,18 @@ COMPONENT_EXPORT(UI_BASE_FEATURES) extern const base::Feature kTSFImeSupport;
COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsUsingWMPointerForTouch();
#endif // defined(OS_WIN)
+#if defined(OS_CHROMEOS)
+// This flag is intended to supercede kNewShortcutMapping.
+COMPONENT_EXPORT(UI_BASE_FEATURES)
+extern const base::Feature kImprovedKeyboardShortcuts;
+COMPONENT_EXPORT(UI_BASE_FEATURES)
+bool IsImprovedKeyboardShortcutsEnabled();
+COMPONENT_EXPORT(UI_BASE_FEATURES)
+extern const base::Feature kDeprecateAltBasedSixPack;
+COMPONENT_EXPORT(UI_BASE_FEATURES)
+bool IsDeprecateAltBasedSixPackEnabled();
+#endif // defined(OS_CHROMEOS)
+
#if defined(OS_WIN) || defined(OS_APPLE) || defined(OS_LINUX) || \
defined(OS_CHROMEOS)
COMPONENT_EXPORT(UI_BASE_FEATURES)
@@ -110,13 +122,6 @@ extern const base::Feature kNewShortcutMapping;
COMPONENT_EXPORT(UI_BASE_FEATURES)
bool IsNewShortcutMappingEnabled();
-// This flag is intended to supercede kNewShortcutMapping above.
-COMPONENT_EXPORT(UI_BASE_FEATURES)
-extern const base::Feature kImprovedKeyboardShortcuts;
-
-COMPONENT_EXPORT(UI_BASE_FEATURES)
-bool IsImprovedKeyboardShortcutsEnabled();
-
COMPONENT_EXPORT(UI_BASE_FEATURES)
extern const base::Feature kDeprecateAltClick;
diff --git a/chromium/ui/base/webui/jstemplate_builder.cc b/chromium/ui/base/webui/jstemplate_builder.cc
index 5122d831cb2..db4026e6b16 100644
--- a/chromium/ui/base/webui/jstemplate_builder.cc
+++ b/chromium/ui/base/webui/jstemplate_builder.cc
@@ -71,15 +71,23 @@ void AppendJsTemplateSourceHtml(std::string* output) {
}
// Appends the code that processes the JsTemplate with the JSON. You should
-// call AppendJsTemplateSourceHtml and AppendJsonHtml before calling this.
-void AppendJsTemplateProcessHtml(
- const base::StringPiece& template_id,
- std::string* output) {
+// call AppendJsTemplateSourceHtml and AppendLoadTimeData before calling this.
+void AppendJsTemplateProcessHtml(const base::DictionaryValue* json,
+ const base::StringPiece& template_id,
+ std::string* output) {
+ std::string jstext;
+ JSONStringValueSerializer serializer(&jstext);
+ serializer.Serialize(*json);
+
output->append("<script>");
+ output->append("const pageData = ");
+ output->append(jstext);
+ output->append(";");
+ output->append("loadTimeData.data = pageData;");
output->append("var tp = document.getElementById('");
output->append(template_id.data(), template_id.size());
output->append("');");
- output->append("jstProcess(loadTimeData.createJsEvalContext(), tp);");
+ output->append("jstProcess(new JsEvalContext(pageData), tp);");
output->append("</script>");
}
@@ -106,10 +114,9 @@ std::string GetTemplatesHtml(const base::StringPiece& html_template,
std::string output =
ui::ReplaceTemplateExpressions(html_template, replacements);
- AppendLoadTimeData(&output);
- AppendJsonHtml(json, &output);
AppendJsTemplateSourceHtml(&output);
- AppendJsTemplateProcessHtml(template_id, &output);
+ AppendLoadTimeData(&output);
+ AppendJsTemplateProcessHtml(json, template_id, &output);
return output;
}
diff --git a/chromium/ui/base/win/session_change_observer.cc b/chromium/ui/base/win/session_change_observer.cc
index a717568fb19..5c555146b93 100644
--- a/chromium/ui/base/win/session_change_observer.cc
+++ b/chromium/ui/base/win/session_change_observer.cc
@@ -13,6 +13,7 @@
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/location.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/observer_list.h"
diff --git a/chromium/ui/base/x/BUILD.gn b/chromium/ui/base/x/BUILD.gn
index dc005256ec0..5dc75c90901 100644
--- a/chromium/ui/base/x/BUILD.gn
+++ b/chromium/ui/base/x/BUILD.gn
@@ -16,6 +16,8 @@ component("x") {
"selection_requestor.h",
"selection_utils.cc",
"selection_utils.h",
+ "visual_picker_glx.cc",
+ "visual_picker_glx.h",
"x11_clipboard_helper.cc",
"x11_clipboard_helper.h",
"x11_cursor.cc",
@@ -34,6 +36,8 @@ component("x") {
"x11_global_shortcut_listener.h",
"x11_idle_query.cc",
"x11_idle_query.h",
+ "x11_keyboard_hook.cc",
+ "x11_keyboard_hook.h",
"x11_menu_list.cc",
"x11_menu_list.h",
"x11_menu_registrar.cc",
@@ -42,8 +46,8 @@ component("x") {
"x11_move_loop_delegate.h",
"x11_pointer_grab.cc",
"x11_pointer_grab.h",
- "x11_screensaver_window_finder.cc",
- "x11_screensaver_window_finder.h",
+ "x11_screensaver.cc",
+ "x11_screensaver.h",
"x11_shm_image_pool.cc",
"x11_shm_image_pool.h",
"x11_software_bitmap_presenter.cc",
@@ -66,7 +70,7 @@ component("x") {
defines = [ "IS_UI_BASE_X_IMPL" ]
- public_deps = []
+ public_deps = [ "//ui/base/cursor:cursor_base" ]
deps = [
"//base",
"//base:i18n",
@@ -77,11 +81,11 @@ component("x") {
"//ui/base:features",
"//ui/base/clipboard:clipboard_types",
"//ui/base/clipboard:file_info",
- "//ui/base/cursor:cursor_base",
"//ui/base/cursor:theme_manager",
"//ui/base/cursor/mojom:cursor_type",
"//ui/display/util",
"//ui/events",
+ "//ui/events:dom_keycode_converter",
"//ui/events/devices/x11",
"//ui/events/keycodes:x11",
"//ui/events/platform/x11",
@@ -103,7 +107,11 @@ component("x") {
"x11_os_exchange_data_provider.cc",
"x11_os_exchange_data_provider.h",
]
- public_deps += [ "//ui/base/dragdrop:types" ]
+ public_deps += [ "//ui/base/dragdrop/mojom:mojom_shared" ]
+ deps += [
+ "//ui/base/dragdrop:types",
+ "//ui/base/dragdrop/mojom",
+ ]
}
}
diff --git a/chromium/ui/gl/gl_visual_picker_glx.cc b/chromium/ui/base/x/visual_picker_glx.cc
index abe58bdf274..349598fdcd2 100644
--- a/chromium/ui/gl/gl_visual_picker_glx.cc
+++ b/chromium/ui/base/x/visual_picker_glx.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/gl/gl_visual_picker_glx.h"
+#include "ui/base/x/visual_picker_glx.h"
#include <algorithm>
#include <bitset>
@@ -13,11 +13,47 @@
#include "base/memory/singleton.h"
#include "base/stl_util.h"
#include "ui/gfx/x/future.h"
-#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_surface_glx.h"
-namespace gl {
+// These constants are obtained from GL/glx.h and GL/glxext.h.
+constexpr uint32_t GLX_LEVEL = 3;
+constexpr uint32_t GLX_DOUBLEBUFFER = 5;
+constexpr uint32_t GLX_STEREO = 6;
+constexpr uint32_t GLX_BUFFER_SIZE = 2;
+constexpr uint32_t GLX_AUX_BUFFERS = 7;
+constexpr uint32_t GLX_RED_SIZE = 8;
+constexpr uint32_t GLX_GREEN_SIZE = 9;
+constexpr uint32_t GLX_BLUE_SIZE = 10;
+constexpr uint32_t GLX_ALPHA_SIZE = 11;
+constexpr uint32_t GLX_DEPTH_SIZE = 12;
+constexpr uint32_t GLX_STENCIL_SIZE = 13;
+constexpr uint32_t GLX_ACCUM_RED_SIZE = 14;
+constexpr uint32_t GLX_ACCUM_GREEN_SIZE = 15;
+constexpr uint32_t GLX_ACCUM_BLUE_SIZE = 16;
+constexpr uint32_t GLX_ACCUM_ALPHA_SIZE = 17;
+
+constexpr uint32_t GLX_CONFIG_CAVEAT = 0x20;
+constexpr uint32_t GLX_VISUAL_CAVEAT_EXT = 0x20;
+constexpr uint32_t GLX_X_VISUAL_TYPE = 0x22;
+
+constexpr uint32_t GLX_BIND_TO_TEXTURE_TARGETS_EXT = 0x20D3;
+
+constexpr uint32_t GLX_NONE = 0x8000;
+constexpr uint32_t GLX_NONE_EXT = 0x8000;
+constexpr uint32_t GLX_TRUE_COLOR = 0x8002;
+constexpr uint32_t GLX_VISUAL_ID = 0x800B;
+constexpr uint32_t GLX_DRAWABLE_TYPE = 0x8010;
+constexpr uint32_t GLX_RENDER_TYPE = 0x8011;
+constexpr uint32_t GLX_FBCONFIG_ID = 0x8013;
+
+constexpr uint32_t GLX_PIXMAP_BIT = 0x00000002;
+constexpr uint32_t GLX_TEXTURE_2D_BIT_EXT = 0x00000002;
+
+constexpr uint32_t GLX_SAMPLE_BUFFERS_ARB = 100000;
+constexpr uint32_t GLX_SAMPLES = 100001;
+
+constexpr uint32_t GL_FALSE = 0;
+
+namespace ui {
namespace {
@@ -47,17 +83,19 @@ int VisualScore(x11::VisualClass c_class) {
} // anonymous namespace
// static
-GLVisualPickerGLX* GLVisualPickerGLX::GetInstance() {
- return base::Singleton<GLVisualPickerGLX>::get();
+VisualPickerGlx* VisualPickerGlx::GetInstance() {
+ return base::Singleton<VisualPickerGlx>::get();
}
-x11::Glx::FbConfig GLVisualPickerGLX::GetFbConfigForFormat(
- gfx::BufferFormat format) const {
- auto it = config_map_.find(format);
- return it == config_map_.end() ? x11::Glx::FbConfig{} : it->second;
+x11::Glx::FbConfig VisualPickerGlx::GetFbConfigForFormat(
+ gfx::BufferFormat format) {
+ if (!config_map_)
+ FillConfigMap();
+ auto it = config_map_->find(format);
+ return it == config_map_->end() ? x11::Glx::FbConfig{} : it->second;
}
-x11::VisualId GLVisualPickerGLX::PickBestGlVisual(
+x11::VisualId VisualPickerGlx::PickBestGlVisual(
const x11::Glx::GetVisualConfigsReply& configs,
base::RepeatingCallback<bool(const x11::Connection::VisualInfo&)> pred,
bool want_alpha) const {
@@ -129,7 +167,7 @@ x11::VisualId GLVisualPickerGLX::PickBestGlVisual(
return best_visual;
}
-x11::VisualId GLVisualPickerGLX::PickBestSystemVisual(
+x11::VisualId VisualPickerGlx::PickBestSystemVisual(
const x11::Glx::GetVisualConfigsReply& configs) const {
x11::Connection::VisualInfo default_visual_info =
*connection_->GetVisualInfoFromId(
@@ -154,7 +192,7 @@ x11::VisualId GLVisualPickerGLX::PickBestSystemVisual(
IsArgbVisual(default_visual_info));
}
-x11::VisualId GLVisualPickerGLX::PickBestRgbaVisual(
+x11::VisualId VisualPickerGlx::PickBestRgbaVisual(
const x11::Glx::GetVisualConfigsReply& configs) const {
int best_class_score = -1;
for (const auto& depth : connection_->default_screen().allowed_depths) {
@@ -171,9 +209,10 @@ x11::VisualId GLVisualPickerGLX::PickBestRgbaVisual(
true);
}
-void GLVisualPickerGLX::FillConfigMap() {
- if (!GLSurfaceGLX::HasGLXExtension("GLX_EXT_texture_from_pixmap"))
- return;
+void VisualPickerGlx::FillConfigMap() {
+ DCHECK(!config_map_);
+ config_map_ =
+ std::make_unique<base::flat_map<gfx::BufferFormat, x11::Glx::FbConfig>>();
if (auto configs = connection_->glx()
.GetFBConfigs({connection_->DefaultScreenId()})
@@ -235,18 +274,18 @@ void GLVisualPickerGLX::FillConfigMap() {
auto b = get(GLX_BLUE_SIZE);
auto a = get(GLX_ALPHA_SIZE);
if (r == 5 && g == 6 && b == 5 && a == 0)
- config_map_[gfx::BufferFormat::BGR_565] = fbconfig;
+ (*config_map_)[gfx::BufferFormat::BGR_565] = fbconfig;
else if (r == 8 && g == 8 && b == 8 && a == 0)
- config_map_[gfx::BufferFormat::BGRX_8888] = fbconfig;
+ (*config_map_)[gfx::BufferFormat::BGRX_8888] = fbconfig;
else if (r == 10 && g == 10 && b == 10 && a == 0)
- config_map_[gfx::BufferFormat::BGRA_1010102] = fbconfig;
+ (*config_map_)[gfx::BufferFormat::BGRA_1010102] = fbconfig;
else if (r == 8 && g == 8 && b == 8 && a == 8)
- config_map_[gfx::BufferFormat::BGRA_8888] = fbconfig;
+ (*config_map_)[gfx::BufferFormat::BGRA_8888] = fbconfig;
}
}
}
-GLVisualPickerGLX::GLVisualPickerGLX() : connection_(x11::Connection::Get()) {
+VisualPickerGlx::VisualPickerGlx() : connection_(x11::Connection::Get()) {
auto configs = connection_->glx()
.GetVisualConfigs({connection_->DefaultScreenId()})
.Sync();
@@ -255,10 +294,8 @@ GLVisualPickerGLX::GLVisualPickerGLX() : connection_(x11::Connection::Get()) {
system_visual_ = PickBestSystemVisual(*configs.reply);
rgba_visual_ = PickBestRgbaVisual(*configs.reply);
}
-
- FillConfigMap();
}
-GLVisualPickerGLX::~GLVisualPickerGLX() = default;
+VisualPickerGlx::~VisualPickerGlx() = default;
-} // namespace gl
+} // namespace ui
diff --git a/chromium/ui/gl/gl_visual_picker_glx.h b/chromium/ui/base/x/visual_picker_glx.h
index d780aa277cb..39b6d670523 100644
--- a/chromium/ui/gl/gl_visual_picker_glx.h
+++ b/chromium/ui/base/x/visual_picker_glx.h
@@ -2,44 +2,42 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_GL_GL_VISUAL_PICKER_GLX_H_
-#define UI_GL_GL_VISUAL_PICKER_GLX_H_
-
-#include <vector>
+#ifndef UI_BASE_X_VISUAL_PICKER_GLX_H_
+#define UI_BASE_X_VISUAL_PICKER_GLX_H_
+#include "base/component_export.h"
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/x/connection.h"
#include "ui/gfx/x/glx.h"
-#include "ui/gl/gl_export.h"
namespace base {
template <typename T>
struct DefaultSingletonTraits;
}
-namespace gl {
+namespace ui {
// Picks the best X11 visuals to use for GL. This class is adapted from GTK's
// pick_better_visual_for_gl. Tries to find visuals that
// 1. Support GL
// 2. Support double buffer
// 3. Have an alpha channel only if we want one
-class GL_EXPORT GLVisualPickerGLX {
+class COMPONENT_EXPORT(UI_BASE_X) VisualPickerGlx {
public:
- static GLVisualPickerGLX* GetInstance();
+ static VisualPickerGlx* GetInstance();
- ~GLVisualPickerGLX();
+ ~VisualPickerGlx();
x11::VisualId system_visual() const { return system_visual_; }
x11::VisualId rgba_visual() const { return rgba_visual_; }
- x11::Glx::FbConfig GetFbConfigForFormat(gfx::BufferFormat format) const;
+ x11::Glx::FbConfig GetFbConfigForFormat(gfx::BufferFormat format);
private:
- friend struct base::DefaultSingletonTraits<GLVisualPickerGLX>;
+ friend struct base::DefaultSingletonTraits<VisualPickerGlx>;
x11::VisualId PickBestGlVisual(
const x11::Glx::GetVisualConfigsReply& configs,
@@ -56,16 +54,17 @@ class GL_EXPORT GLVisualPickerGLX {
x11::Connection* const connection_;
- x11::VisualId system_visual_;
- x11::VisualId rgba_visual_;
+ x11::VisualId system_visual_{};
+ x11::VisualId rgba_visual_{};
- base::flat_map<gfx::BufferFormat, x11::Glx::FbConfig> config_map_;
+ std::unique_ptr<base::flat_map<gfx::BufferFormat, x11::Glx::FbConfig>>
+ config_map_;
- GLVisualPickerGLX();
+ VisualPickerGlx();
- DISALLOW_COPY_AND_ASSIGN(GLVisualPickerGLX);
+ DISALLOW_COPY_AND_ASSIGN(VisualPickerGlx);
};
-} // namespace gl
+} // namespace ui
-#endif // UI_GL_GL_VISUAL_PICKER_GLX_H_
+#endif // UI_BASE_X_VISUAL_PICKER_GLX_H_
diff --git a/chromium/ui/base/x/x11_cursor.cc b/chromium/ui/base/x/x11_cursor.cc
index 0b9d548d8b8..5edb782a24e 100644
--- a/chromium/ui/base/x/x11_cursor.cc
+++ b/chromium/ui/base/x/x11_cursor.cc
@@ -4,6 +4,7 @@
#include "ui/base/x/x11_cursor.h"
+#include "base/memory/scoped_refptr.h"
#include "ui/base/x/x11_cursor_loader.h"
#include "ui/gfx/x/connection.h"
#include "ui/gfx/x/future.h"
@@ -11,6 +12,12 @@
namespace ui {
+// static
+scoped_refptr<X11Cursor> X11Cursor::FromPlatformCursor(
+ scoped_refptr<PlatformCursor> platform_cursor) {
+ return base::WrapRefCounted(static_cast<X11Cursor*>(platform_cursor.get()));
+}
+
X11Cursor::X11Cursor() = default;
X11Cursor::X11Cursor(x11::Cursor cursor) : loaded_(true), xcursor_(cursor) {}
diff --git a/chromium/ui/base/x/x11_cursor.h b/chromium/ui/base/x/x11_cursor.h
index bf5966298ed..b004f1ce040 100644
--- a/chromium/ui/base/x/x11_cursor.h
+++ b/chromium/ui/base/x/x11_cursor.h
@@ -9,20 +9,23 @@
#include "base/callback.h"
#include "base/component_export.h"
-#include "base/memory/ref_counted.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/gfx/x/xproto.h"
+template <class T>
+class scoped_refptr;
+
namespace ui {
// Ref counted class to hold an X11 cursor resource. Clears the X11 resources
// on destruction
-class COMPONENT_EXPORT(UI_BASE_X) X11Cursor
- : public base::RefCounted<X11Cursor> {
+class COMPONENT_EXPORT(UI_BASE_X) X11Cursor : public PlatformCursor {
public:
- REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
-
using Callback = base::OnceCallback<void(x11::Cursor)>;
+ static scoped_refptr<X11Cursor> FromPlatformCursor(
+ scoped_refptr<PlatformCursor> platform_cursor);
+
X11Cursor();
explicit X11Cursor(x11::Cursor cursor);
@@ -35,16 +38,16 @@ class COMPONENT_EXPORT(UI_BASE_X) X11Cursor
x11::Cursor xcursor() const { return xcursor_; }
private:
- friend class base::RefCounted<X11Cursor>;
+ friend class base::RefCounted<PlatformCursor>;
friend class XCursorLoader;
+ ~X11Cursor() override;
+
void SetCursor(x11::Cursor cursor);
// This cannot be named Release() since it conflicts with base::RefCounted.
x11::Cursor ReleaseCursor();
- ~X11Cursor();
-
bool loaded_ = false;
x11::Cursor xcursor_ = x11::Cursor::None;
diff --git a/chromium/ui/base/x/x11_cursor_factory.cc b/chromium/ui/base/x/x11_cursor_factory.cc
index 5a569835525..46c0560bea4 100644
--- a/chromium/ui/base/x/x11_cursor_factory.cc
+++ b/chromium/ui/base/x/x11_cursor_factory.cc
@@ -6,6 +6,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/x/x11_cursor.h"
#include "ui/base/x/x11_cursor_loader.h"
#include "ui/base/x/x11_util.h"
@@ -16,14 +17,6 @@ namespace ui {
namespace {
-X11Cursor* ToX11Cursor(PlatformCursor cursor) {
- return static_cast<X11Cursor*>(cursor);
-}
-
-PlatformCursor ToPlatformCursor(X11Cursor* cursor) {
- return static_cast<PlatformCursor>(cursor);
-}
-
scoped_refptr<X11Cursor> CreateInvisibleCursor(XCursorLoader* cursor_loader) {
SkBitmap bitmap;
bitmap.allocN32Pixels(1, 1);
@@ -37,28 +30,20 @@ X11CursorFactory::X11CursorFactory()
X11CursorFactory::~X11CursorFactory() = default;
-PlatformCursor X11CursorFactory::CreateImageCursor(mojom::CursorType type,
- const SkBitmap& bitmap,
- const gfx::Point& hotspot) {
+scoped_refptr<PlatformCursor> X11CursorFactory::CreateImageCursor(
+ mojom::CursorType type,
+ const SkBitmap& bitmap,
+ const gfx::Point& hotspot) {
// There is a problem with custom cursors that have no custom data. The
// resulting SkBitmap is empty and X crashes when creating a zero size cursor
// image. Return invisible cursor here instead.
- if (bitmap.drawsNothing()) {
- // The result of `CreateImageCursor()` is owned by the caller, and will be
- // Unref()ed by code far away. (Usually in web_cursor.cc in content, among
- // others.) If we don't manually add another reference before we cast this
- // to a void*, we can end up with the cursor being freed out from under us.
- auto* invisible_cursor = GetDefaultCursor(mojom::CursorType::kNone);
- RefImageCursor(invisible_cursor);
- return invisible_cursor;
- }
+ if (bitmap.drawsNothing())
+ return GetDefaultCursor(mojom::CursorType::kNone);
- auto cursor = cursor_loader_->CreateCursor(bitmap, hotspot);
- cursor->AddRef();
- return ToPlatformCursor(cursor.get());
+ return cursor_loader_->CreateCursor(bitmap, hotspot);
}
-PlatformCursor X11CursorFactory::CreateAnimatedCursor(
+scoped_refptr<PlatformCursor> X11CursorFactory::CreateAnimatedCursor(
mojom::CursorType type,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& hotspot,
@@ -67,17 +52,7 @@ PlatformCursor X11CursorFactory::CreateAnimatedCursor(
images.reserve(bitmaps.size());
for (const auto& bitmap : bitmaps)
images.push_back(XCursorLoader::Image{bitmap, hotspot, frame_delay});
- auto cursor = cursor_loader_->CreateCursor(images);
- cursor->AddRef();
- return ToPlatformCursor(cursor.get());
-}
-
-void X11CursorFactory::RefImageCursor(PlatformCursor cursor) {
- ToX11Cursor(cursor)->AddRef();
-}
-
-void X11CursorFactory::UnrefImageCursor(PlatformCursor cursor) {
- ToX11Cursor(cursor)->Release();
+ return cursor_loader_->CreateCursor(images);
}
void X11CursorFactory::ObserveThemeChanges() {
@@ -95,7 +70,8 @@ void X11CursorFactory::OnCursorThemeSizeChanged(int cursor_theme_size) {
ClearThemeCursors();
}
-PlatformCursor X11CursorFactory::GetDefaultCursor(mojom::CursorType type) {
+scoped_refptr<PlatformCursor> X11CursorFactory::GetDefaultCursor(
+ mojom::CursorType type) {
if (!default_cursors_.count(type)) {
// Try to load a predefined X11 cursor.
default_cursors_[type] =
@@ -104,8 +80,7 @@ PlatformCursor X11CursorFactory::GetDefaultCursor(mojom::CursorType type) {
: cursor_loader_->LoadCursor(CursorNamesFromType(type));
}
- // Returns owned default cursor for this type.
- return default_cursors_[type].get();
+ return default_cursors_[type];
}
void X11CursorFactory::ClearThemeCursors() {
diff --git a/chromium/ui/base/x/x11_cursor_factory.h b/chromium/ui/base/x/x11_cursor_factory.h
index 44b6ffbd7ef..2b3a61a82aa 100644
--- a/chromium/ui/base/x/x11_cursor_factory.h
+++ b/chromium/ui/base/x/x11_cursor_factory.h
@@ -21,7 +21,7 @@ namespace ui {
class X11Cursor;
class XCursorLoader;
-// CursorFactoryOzone implementation for X11 cursors.
+// CursorFactory implementation for X11 cursors.
class COMPONENT_EXPORT(UI_BASE_X) X11CursorFactory
: public CursorFactory,
public CursorThemeManagerObserver {
@@ -32,16 +32,17 @@ class COMPONENT_EXPORT(UI_BASE_X) X11CursorFactory
~X11CursorFactory() override;
// CursorFactory:
- PlatformCursor GetDefaultCursor(mojom::CursorType type) override;
- PlatformCursor CreateImageCursor(mojom::CursorType type,
- const SkBitmap& bitmap,
- const gfx::Point& hotspot) override;
- PlatformCursor CreateAnimatedCursor(mojom::CursorType type,
- const std::vector<SkBitmap>& bitmaps,
- const gfx::Point& hotspot,
- base::TimeDelta frame_delay) override;
- void RefImageCursor(PlatformCursor cursor) override;
- void UnrefImageCursor(PlatformCursor cursor) override;
+ scoped_refptr<PlatformCursor> GetDefaultCursor(
+ mojom::CursorType type) override;
+ scoped_refptr<PlatformCursor> CreateImageCursor(
+ mojom::CursorType type,
+ const SkBitmap& bitmap,
+ const gfx::Point& hotspot) override;
+ scoped_refptr<PlatformCursor> CreateAnimatedCursor(
+ mojom::CursorType type,
+ const std::vector<SkBitmap>& bitmaps,
+ const gfx::Point& hotspot,
+ base::TimeDelta frame_delay) override;
void ObserveThemeChanges() override;
private:
diff --git a/chromium/ui/base/x/x11_cursor_factory_unittest.cc b/chromium/ui/base/x/x11_cursor_factory_unittest.cc
index 93b2ea926df..9bdb14158b4 100644
--- a/chromium/ui/base/x/x11_cursor_factory_unittest.cc
+++ b/chromium/ui/base/x/x11_cursor_factory_unittest.cc
@@ -6,28 +6,24 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/x/x11_cursor.h"
#include "ui/gfx/geometry/point.h"
namespace ui {
-TEST(X11CursorFactoryTest, InvisibleRefcount) {
+using mojom::CursorType;
+
+TEST(X11CursorFactoryTest, InvisibleCursor) {
X11CursorFactory factory;
// Building an image cursor with an invalid SkBitmap should return the
- // invisible cursor in X11. The invisible cursor instance should have more
- // than a single reference since the factory should hold a reference and
- // CreateImageCursor should return an incremented refcount.
- auto* invisible_cursor = static_cast<X11Cursor*>(
- factory.CreateImageCursor({}, SkBitmap(), gfx::Point()));
+ // invisible cursor in X11.
+ auto invisible_cursor =
+ factory.CreateImageCursor({}, SkBitmap(), gfx::Point());
ASSERT_NE(invisible_cursor, nullptr);
- ASSERT_FALSE(invisible_cursor->HasOneRef());
-
- // Release our refcount on the cursor
- factory.UnrefImageCursor(invisible_cursor);
-
- // The invisible cursor should still exist.
- EXPECT_TRUE(invisible_cursor->HasOneRef());
+ EXPECT_EQ(invisible_cursor, factory.GetDefaultCursor(CursorType::kNone));
}
} // namespace ui
diff --git a/chromium/ui/base/x/x11_drag_drop_client.cc b/chromium/ui/base/x/x11_drag_drop_client.cc
index 91dba2f20d9..c96e99425d5 100644
--- a/chromium/ui/base/x/x11_drag_drop_client.cc
+++ b/chromium/ui/base/x/x11_drag_drop_client.cc
@@ -6,8 +6,10 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
+#include "base/notreached.h"
#include "ui/base/clipboard/clipboard_constants.h"
#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/x/x11_os_exchange_data_provider.h"
#include "ui/base/x/x11_util.h"
@@ -28,9 +30,10 @@
// All the readings are freely available online.
namespace ui {
-
namespace {
+using mojom::DragOperation;
+
constexpr int kWillAcceptDrop = 1;
constexpr int kWantFurtherPosEvents = 2;
@@ -120,29 +123,29 @@ const char kXdndStatus[] = "XdndStatus";
static base::LazyInstance<std::map<x11::Window, XDragDropClient*>>::Leaky
g_live_client_map = LAZY_INSTANCE_INITIALIZER;
-// Converts a bitfield of actions into an Atom that represents what action
-// we're most likely to take on drop.
-x11::Atom XDragOperationToAtom(int drag_operation) {
- if (drag_operation & DragDropTypes::DRAG_COPY)
- return x11::GetAtom(kXdndActionCopy);
- if (drag_operation & DragDropTypes::DRAG_MOVE)
- return x11::GetAtom(kXdndActionMove);
- if (drag_operation & DragDropTypes::DRAG_LINK)
- return x11::GetAtom(kXdndActionLink);
-
+x11::Atom DragOperationToAtom(DragOperation operation) {
+ switch (operation) {
+ case DragOperation::kNone:
+ return x11::Atom::None;
+ case DragOperation::kCopy:
+ return x11::GetAtom(kXdndActionCopy);
+ case DragOperation::kMove:
+ return x11::GetAtom(kXdndActionMove);
+ case DragOperation::kLink:
+ return x11::GetAtom(kXdndActionLink);
+ }
+ NOTREACHED();
return x11::Atom::None;
}
-// Converts a single action atom to a drag operation.
-DragDropTypes::DragOperation AtomToDragOperation(x11::Atom atom) {
+DragOperation AtomToDragOperation(x11::Atom atom) {
if (atom == x11::GetAtom(kXdndActionCopy))
- return DragDropTypes::DRAG_COPY;
+ return DragOperation::kCopy;
if (atom == x11::GetAtom(kXdndActionMove))
- return DragDropTypes::DRAG_MOVE;
+ return DragOperation::kMove;
if (atom == x11::GetAtom(kXdndActionLink))
- return DragDropTypes::DRAG_LINK;
-
- return DragDropTypes::DRAG_NONE;
+ return DragOperation::kLink;
+ return DragOperation::kNone;
}
} // namespace
@@ -203,18 +206,19 @@ XDragDropClient::~XDragDropClient() {
std::vector<x11::Atom> XDragDropClient::GetOfferedDragOperations() const {
std::vector<x11::Atom> operations;
- if (drag_operation_ & DragDropTypes::DRAG_COPY)
+ if (allowed_operations_ & DragDropTypes::DRAG_COPY)
operations.push_back(x11::GetAtom(kXdndActionCopy));
- if (drag_operation_ & DragDropTypes::DRAG_MOVE)
+ if (allowed_operations_ & DragDropTypes::DRAG_MOVE)
operations.push_back(x11::GetAtom(kXdndActionMove));
- if (drag_operation_ & DragDropTypes::DRAG_LINK)
+ if (allowed_operations_ & DragDropTypes::DRAG_LINK)
operations.push_back(x11::GetAtom(kXdndActionLink));
return operations;
}
void XDragDropClient::CompleteXdndPosition(x11::Window source_window,
const gfx::Point& screen_point) {
- int drag_operation = delegate_->UpdateDrag(screen_point);
+ DragOperation drag_operation =
+ PreferredDragOperation(delegate_->UpdateDrag(screen_point));
// Sends an XdndStatus message back to the source_window. l[2,3]
// theoretically represent an area in the window where the current action is
@@ -223,10 +227,11 @@ void XDragDropClient::CompleteXdndPosition(x11::Window source_window,
// first bit of l[1] to disable the feature, and it appears that gtk neither
// sets this nor respects it if set.
auto xev = PrepareXdndClientMessage(kXdndStatus, source_window);
- xev.data.data32[1] =
- (drag_operation != 0) ? (kWantFurtherPosEvents | kWillAcceptDrop) : 0;
+ xev.data.data32[1] = (drag_operation != DragOperation::kNone)
+ ? (kWantFurtherPosEvents | kWillAcceptDrop)
+ : 0;
xev.data.data32[4] =
- static_cast<uint32_t>(XDragOperationToAtom(drag_operation));
+ static_cast<uint32_t>(DragOperationToAtom(drag_operation));
SendXClientEvent(source_window, xev);
}
@@ -246,7 +251,7 @@ void XDragDropClient::ProcessMouseMove(const gfx::Point& screen_point,
waiting_on_status_ = false;
next_position_message_.reset();
status_received_since_enter_ = false;
- negotiated_operation_ = DragDropTypes::DRAG_NONE;
+ negotiated_operation_ = DragOperation::kNone;
if (target_current_window_ != x11::Window::None) {
std::vector<x11::Atom> targets;
@@ -367,12 +372,12 @@ void XDragDropClient::OnXdndStatus(const x11::ClientMessageEvent& event) {
x11::Atom atom_operation = static_cast<x11::Atom>(event.data.data32[4]);
negotiated_operation_ = AtomToDragOperation(atom_operation);
} else {
- negotiated_operation_ = DragDropTypes::DRAG_NONE;
+ negotiated_operation_ = DragOperation::kNone;
}
if (source_state_ == SourceState::kPendingDrop) {
// We were waiting on the status message so we could send the XdndDrop.
- if (negotiated_operation_ == DragDropTypes::DRAG_NONE) {
+ if (negotiated_operation_ == DragOperation::kNone) {
EndMoveLoop();
return;
}
@@ -411,12 +416,12 @@ void XDragDropClient::OnXdndDrop(const x11::ClientMessageEvent& event) {
auto source_window = static_cast<x11::Window>(event.data.data32[0]);
- int drag_operation = delegate_->PerformDrop();
+ DragOperation drag_operation = delegate_->PerformDrop();
auto xev = PrepareXdndClientMessage(kXdndFinished, source_window);
- xev.data.data32[1] = (drag_operation != 0) ? 1 : 0;
+ xev.data.data32[1] = (drag_operation != DragOperation::kNone) ? 1 : 0;
xev.data.data32[2] =
- static_cast<uint32_t>(XDragOperationToAtom(drag_operation));
+ static_cast<uint32_t>(DragOperationToAtom(drag_operation));
SendXClientEvent(source_window, xev);
}
@@ -428,7 +433,7 @@ void XDragDropClient::OnXdndFinished(const x11::ClientMessageEvent& event) {
// Clear |negotiated_operation_| if the drag was rejected.
if ((event.data.data32[1] & 1) == 0)
- negotiated_operation_ = DragDropTypes::DRAG_NONE;
+ negotiated_operation_ = DragOperation::kNone;
// Clear |target_current_window_| to avoid sending XdndLeave upon ending the
// move loop.
@@ -447,14 +452,15 @@ void XDragDropClient::OnSelectionNotify(
x11::DeleteProperty(xwindow_, xselection.property);
}
-void XDragDropClient::InitDrag(int operation, const OSExchangeData* data) {
+void XDragDropClient::InitDrag(int allowed_operations,
+ const OSExchangeData* data) {
target_current_window_ = x11::Window::None;
source_state_ = SourceState::kOther;
waiting_on_status_ = false;
next_position_message_.reset();
status_received_since_enter_ = false;
- drag_operation_ = operation;
- negotiated_operation_ = DragDropTypes::DRAG_NONE;
+ allowed_operations_ = allowed_operations;
+ negotiated_operation_ = DragOperation::kNone;
source_provider_ =
static_cast<const XOSExchangeDataProvider*>(&data->provider());
@@ -544,7 +550,7 @@ void XDragDropClient::HandleMouseReleased() {
return;
}
- if (negotiated_operation() != DragDropTypes::DRAG_NONE) {
+ if (negotiated_operation() != DragOperation::kNone) {
// Start timer to end the move loop if the target takes too long to send
// an XdndFinished message. It is important that StartEndMoveLoopTimer()
// is called before SendXdndDrop() because SendXdndDrop()
@@ -657,8 +663,8 @@ void XDragDropClient::SendXdndPosition(x11::Window dest_window,
auto xev = PrepareXdndClientMessage(kXdndPosition, dest_window);
xev.data.data32[2] = (screen_point.x() << 16) | screen_point.y();
xev.data.data32[3] = event_time;
- xev.data.data32[4] =
- static_cast<uint32_t>(XDragOperationToAtom(drag_operation_));
+ xev.data.data32[4] = static_cast<uint32_t>(
+ DragOperationToAtom(PreferredDragOperation(allowed_operations_)));
SendXClientEvent(dest_window, xev);
// http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html and
diff --git a/chromium/ui/base/x/x11_drag_drop_client.h b/chromium/ui/base/x/x11_drag_drop_client.h
index e32e73185ce..b5eff05fab5 100644
--- a/chromium/ui/base/x/x11_drag_drop_client.h
+++ b/chromium/ui/base/x/x11_drag_drop_client.h
@@ -9,7 +9,7 @@
#include "base/component_export.h"
#include "base/timer/timer.h"
-#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
#include "ui/base/x/selection_utils.h"
#include "ui/base/x/x11_drag_context.h"
#include "ui/base/x/x11_topmost_window_finder.h"
@@ -40,7 +40,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragDropClient {
// Creates the window finder.
virtual std::unique_ptr<XTopmostWindowFinder> CreateWindowFinder() = 0;
- // Updates the drag status by the new position. Returns the drag operation
+ // Updates the drag status by the new position. Returns the drag operations
// possible at that position.
//
// Handling XdndPosition can be paused while waiting for more data; this is
@@ -49,8 +49,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragDropClient {
virtual int UpdateDrag(const gfx::Point& screen_point) = 0;
// Updates the mouse cursor shape.
- virtual void UpdateCursor(
- DragDropTypes::DragOperation negotiated_operation) = 0;
+ virtual void UpdateCursor(mojom::DragOperation negotiated_operation) = 0;
// Called when data from another application (not Chrome) enters the window.
virtual void OnBeginForeignDrag(x11::Window window) = 0;
@@ -63,7 +62,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragDropClient {
virtual void OnBeforeDragLeave() = 0;
// Drops data at the current location and returns the resulting operation.
- virtual int PerformDrop() = 0;
+ virtual mojom::DragOperation PerformDrop() = 0;
// Called to end the drag loop that is maintained by the subclass.
virtual void EndDragLoop() = 0;
@@ -148,7 +147,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragDropClient {
kOther,
};
- DragDropTypes::DragOperation negotiated_operation() const {
+ mojom::DragOperation negotiated_operation() const {
return negotiated_operation_;
}
@@ -214,18 +213,18 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragDropClient {
const XOSExchangeDataProvider* source_provider_ = nullptr;
// The operation bitfield as requested by StartDragAndDrop.
- int drag_operation_ = 0;
+ int allowed_operations_ = 0;
// The modifier state for the most recent mouse move. Used to bypass an
// asynchronous roundtrip through the X11 server.
int current_modifier_state_ = 0;
- // We offer the other window a list of possible operations,
- // XdndActionsList. This is the requested action from the other window. This
- // is DRAG_NONE if we haven't sent out an XdndPosition message yet, haven't
- // yet received an XdndStatus or if the other window has told us that there's
- // no action that we can agree on.
- DragDropTypes::DragOperation negotiated_operation_ = DragDropTypes::DRAG_NONE;
+ // We offer the other window a list of possible operations, XdndActionsList.
+ // This is the requested action from the other window. This is
+ // DragOperation::kNone if we haven't sent out an XdndPosition message yet,
+ // haven't yet received an XdndStatus or if the other window has told us that
+ // there's no action that we can agree on.
+ mojom::DragOperation negotiated_operation_ = mojom::DragOperation::kNone;
// In the Xdnd protocol, we aren't supposed to send another XdndPosition
// message until we have received a confirming XdndStatus message.
diff --git a/chromium/ui/base/x/x11_gl_egl_utility.cc b/chromium/ui/base/x/x11_gl_egl_utility.cc
index bf92de82142..624c6f9483b 100644
--- a/chromium/ui/base/x/x11_gl_egl_utility.cc
+++ b/chromium/ui/base/x/x11_gl_egl_utility.cc
@@ -21,6 +21,10 @@
#define EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE 0x348F
#endif
+#ifndef EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE 0x3487
+#endif
+
#ifndef EGL_ANGLE_platform_angle
#define EGL_ANGLE_platform_angle 1
#define EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE 0x348F
@@ -35,17 +39,8 @@ namespace ui {
void GetPlatformExtraDisplayAttribs(EGLenum platform_type,
std::vector<EGLAttrib>* attributes) {
- // ANGLE_NULL doesn't use the visual, and may run without X11 where we can't
- // get it anyway.
- if (platform_type != EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE) {
- x11::VisualId visual_id;
- XVisualManager::GetInstance()->ChooseVisualForWindow(
- true, &visual_id, nullptr, nullptr, nullptr);
- attributes->push_back(EGL_X11_VISUAL_ID_ANGLE);
- attributes->push_back(static_cast<EGLAttrib>(visual_id));
- attributes->push_back(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE);
- attributes->push_back(EGL_PLATFORM_X11_EXT);
- }
+ attributes->push_back(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE);
+ attributes->push_back(EGL_PLATFORM_X11_EXT);
}
void ChoosePlatformCustomAlphaAndBufferSize(EGLint* alpha_size,
@@ -65,11 +60,4 @@ bool IsTransparentBackgroundSupported() {
return ui::XVisualManager::GetInstance()->ArgbVisualAvailable();
}
-bool UpdateVisualsOnGpuInfoChanged(bool software_rendering,
- x11::VisualId default_visual_id,
- x11::VisualId transparent_visual_id) {
- return XVisualManager::GetInstance()->UpdateVisualsOnGpuInfoChanged(
- software_rendering, default_visual_id, transparent_visual_id);
-}
-
} // namespace ui
diff --git a/chromium/ui/base/x/x11_gl_egl_utility.h b/chromium/ui/base/x/x11_gl_egl_utility.h
index fd33bbbe842..8f559f28e28 100644
--- a/chromium/ui/base/x/x11_gl_egl_utility.h
+++ b/chromium/ui/base/x/x11_gl_egl_utility.h
@@ -8,7 +8,6 @@
#include <vector>
#include "third_party/khronos/EGL/egl.h"
-#include "ui/gfx/x/xproto.h"
namespace ui {
@@ -23,12 +22,6 @@ void ChoosePlatformCustomAlphaAndBufferSize(EGLint* alpha_size,
// Returns whether transparent background is suppored.
bool IsTransparentBackgroundSupported();
-// Wraps XVisualManager::UpdateVisualsOnGpuInfoChanged(), passes parameters to
-// it directly. Returns whether provided visuals are valid.
-bool UpdateVisualsOnGpuInfoChanged(bool software_rendering,
- x11::VisualId default_visual_id,
- x11::VisualId transparent_visual_id);
-
} // namespace ui
#endif // UI_BASE_X_X11_GL_EGL_UTILITY_H_
diff --git a/chromium/ui/base/x/x11_keyboard_hook.cc b/chromium/ui/base/x/x11_keyboard_hook.cc
new file mode 100644
index 00000000000..5877761a6e5
--- /dev/null
+++ b/chromium/ui/base/x/x11_keyboard_hook.cc
@@ -0,0 +1,122 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/x/x11_keyboard_hook.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/check_op.h"
+#include "base/stl_util.h"
+#include "ui/events/event.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
+#include "ui/gfx/x/future.h"
+#include "ui/gfx/x/xproto.h"
+
+namespace ui {
+
+namespace {
+
+static XKeyboardHook* g_instance = nullptr;
+
+// GrabKey essentially requires the modifier mask to explicitly be specified.
+// One can specify 'x11::ModMask::Any' however doing so means the call to
+// GrabKey will fail if that key has been grabbed with any combination of
+// modifiers. The common practice is to call GrabKey with each individual
+// modifier mask to avoid that problem.
+const x11::ModMask kModifierMasks[] = {
+ {}, // No additional modifier.
+ x11::ModMask::c_2, // Num lock
+ x11::ModMask::Lock, // Caps lock
+ x11::ModMask::c_5, // Scroll lock
+ x11::ModMask::c_2 | x11::ModMask::Lock,
+ x11::ModMask::c_2 | x11::ModMask::c_5,
+ x11::ModMask::Lock | x11::ModMask::c_5,
+ x11::ModMask::c_2 | x11::ModMask::Lock | x11::ModMask::c_5};
+
+// This is the set of keys to lock when the website requests that all keys be
+// locked.
+const DomCode kDomCodesForLockAllKeys[] = {
+ DomCode::ESCAPE, DomCode::CONTEXT_MENU, DomCode::CONTROL_LEFT,
+ DomCode::SHIFT_LEFT, DomCode::ALT_LEFT, DomCode::META_LEFT,
+ DomCode::CONTROL_RIGHT, DomCode::SHIFT_RIGHT, DomCode::ALT_RIGHT,
+ DomCode::META_RIGHT};
+
+} // namespace
+
+XKeyboardHook::XKeyboardHook(gfx::AcceleratedWidget accelerated_widget)
+ : connection_(x11::Connection::Get()),
+ x_window_(static_cast<x11::Window>(accelerated_widget)) {}
+
+XKeyboardHook::~XKeyboardHook() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ DCHECK_EQ(g_instance, this);
+ g_instance = nullptr;
+
+ // Use UngrabKey for each key that has been grabbed. UngrabKeyboard
+ // purportedly releases all keys when called and would not require the nested
+ // loops, however in practice the keys are not actually released.
+ for (int native_key_code : grabbed_keys_) {
+ for (auto modifier : kModifierMasks) {
+ connection_->UngrabKey(
+ {static_cast<x11::KeyCode>(native_key_code), x_window_, modifier});
+ }
+ }
+}
+
+bool XKeyboardHook::RegisterHook(
+ const absl::optional<base::flat_set<DomCode>>& dom_codes) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ // Only one instance of this class can be registered at a time.
+ DCHECK(!g_instance);
+ g_instance = this;
+
+ if (dom_codes.has_value())
+ CaptureSpecificKeys(dom_codes);
+ else
+ CaptureAllKeys();
+
+ return true;
+}
+
+void XKeyboardHook::CaptureAllKeys() {
+ // We could have used the XGrabKeyboard API here instead of calling XGrabKeys
+ // on a hard-coded set of shortcut keys. Calling XGrabKeyboard would make
+ // this work much simpler, however it has side-effects which prevents its use.
+ // An example side-effect is that it prevents the lock screen from starting as
+ // the screensaver process also calls XGrabKeyboard but will receive an error
+ // since it was already grabbed by the window with KeyboardLock.
+ for (auto kDomCodesForLockAllKey : kDomCodesForLockAllKeys)
+ CaptureKeyForDomCode(kDomCodesForLockAllKey);
+}
+
+void XKeyboardHook::CaptureSpecificKeys(
+ const absl::optional<base::flat_set<DomCode>>& dom_codes) {
+ for (DomCode dom_code : dom_codes.value())
+ CaptureKeyForDomCode(dom_code);
+}
+
+void XKeyboardHook::CaptureKeyForDomCode(DomCode dom_code) {
+ int native_key_code = KeycodeConverter::DomCodeToNativeKeycode(dom_code);
+ if (native_key_code == KeycodeConverter::InvalidNativeKeycode())
+ return;
+
+ for (auto modifier : kModifierMasks) {
+ connection_->GrabKey({
+ .owner_events = false,
+ .grab_window = x_window_,
+ .modifiers = modifier,
+ .key = static_cast<x11::KeyCode>(native_key_code),
+ .pointer_mode = x11::GrabMode::Async,
+ .keyboard_mode = x11::GrabMode::Async,
+ });
+ }
+
+ grabbed_keys_.push_back(native_key_code);
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/x/x11_keyboard_hook.h b/chromium/ui/base/x/x11_keyboard_hook.h
new file mode 100644
index 00000000000..f08b865c073
--- /dev/null
+++ b/chromium/ui/base/x/x11_keyboard_hook.h
@@ -0,0 +1,53 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_X_X11_KEYBOARD_HOOK_H_
+#define UI_BASE_X_X11_KEYBOARD_HOOK_H_
+
+#include <vector>
+
+#include "base/containers/flat_set.h"
+#include "base/threading/thread_checker.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/x/connection.h"
+
+namespace ui {
+
+enum class DomCode;
+class KeyEvent;
+
+// X11-specific implementation of the class that intercepts keyboard input.
+class COMPONENT_EXPORT(UI_BASE_X) XKeyboardHook {
+ public:
+ using KeyEventCallback = base::RepeatingCallback<void(KeyEvent* event)>;
+
+ explicit XKeyboardHook(gfx::AcceleratedWidget accelerated_widget);
+ XKeyboardHook(const XKeyboardHook&) = delete;
+ XKeyboardHook& operator=(const XKeyboardHook&) = delete;
+ virtual ~XKeyboardHook();
+
+ protected:
+ bool RegisterHook(const absl::optional<base::flat_set<DomCode>>& dom_codes);
+
+ private:
+ // Helper methods for setting up key event capture.
+ void CaptureAllKeys();
+ void CaptureSpecificKeys(
+ const absl::optional<base::flat_set<DomCode>>& dom_codes);
+ void CaptureKeyForDomCode(DomCode dom_code);
+
+ THREAD_CHECKER(thread_checker_);
+
+ // Tracks the keys that were grabbed.
+ std::vector<int> grabbed_keys_;
+
+ // The x11 default connection and the owner's native window.
+ x11::Connection* const connection_ = nullptr;
+ const x11::Window x_window_ = x11::Window::None;
+};
+
+} // namespace ui
+
+#endif // UI_BASE_X_X11_KEYBOARD_HOOK_H_
diff --git a/chromium/ui/base/x/x11_screensaver.cc b/chromium/ui/base/x/x11_screensaver.cc
new file mode 100644
index 00000000000..32d74ffe1c9
--- /dev/null
+++ b/chromium/ui/base/x/x11_screensaver.cc
@@ -0,0 +1,99 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/x/x11_screensaver.h"
+
+#include <memory>
+
+#include "base/command_line.h"
+#include "base/no_destructor.h"
+#include "base/notreached.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/switches.h"
+#include "ui/gfx/x/connection.h"
+#include "ui/gfx/x/property_cache.h"
+#include "ui/gfx/x/screensaver.h"
+#include "ui/gfx/x/x11_atom_cache.h"
+#include "ui/gfx/x/xproto_util.h"
+
+namespace ui {
+
+namespace {
+
+bool IsMitScreensaverActive(x11::ScreenSaver::State state) {
+ switch (state) {
+ case x11::ScreenSaver::State::Off:
+ case x11::ScreenSaver::State::Disabled:
+ return false;
+ case x11::ScreenSaver::State::On:
+ case x11::ScreenSaver::State::Cycle:
+ return true;
+ }
+ NOTREACHED();
+ return false;
+}
+
+class ScreensaverStatusWatcher : public x11::EventObserver {
+ public:
+ ScreensaverStatusWatcher() {
+ auto* connection = x11::Connection::Get();
+
+ x_screensaver_status_ = std::make_unique<x11::PropertyCache>(
+ connection, connection->default_root(),
+ std::vector<x11::Atom>{x11::GetAtom("_SCREENSAVER_STATUS")});
+
+ // Let the server know the client version before making any requests.
+ connection->screensaver().QueryVersion(
+ {x11::ScreenSaver::major_version, x11::ScreenSaver::minor_version});
+
+ connection->AddEventObserver(this);
+ connection->screensaver().SelectInput(connection->default_root(),
+ x11::ScreenSaver::Event::NotifyMask);
+
+ auto reply =
+ connection->screensaver().QueryInfo(connection->default_root()).Sync();
+ if (reply) {
+ mit_screensaver_active_ = IsMitScreensaverActive(
+ static_cast<x11::ScreenSaver::State>(reply->state));
+ }
+ }
+
+ ScreensaverStatusWatcher(const ScreensaverStatusWatcher&) = delete;
+ ScreensaverStatusWatcher& operator=(const ScreensaverStatusWatcher&) = delete;
+
+ ~ScreensaverStatusWatcher() override = default;
+
+ bool ScreensaverActive() {
+ if (mit_screensaver_active_)
+ return true;
+
+ // Ironically, xscreensaver does not use the MIT-SCREENSAVER extension,
+ // so add a special check for xscreensaver.
+ auto* status = x_screensaver_status_->GetAs<x11::Atom>(
+ x11::GetAtom("_SCREENSAVER_STATUS"));
+ return status && *status == x11::GetAtom("LOCK");
+ }
+
+ private:
+ void OnEvent(const x11::Event& event) override {
+ if (auto* notify = event.As<x11::ScreenSaver::NotifyEvent>())
+ mit_screensaver_active_ = IsMitScreensaverActive(notify->state);
+ }
+
+ std::unique_ptr<x11::PropertyCache> x_screensaver_status_;
+ bool mit_screensaver_active_ = false;
+};
+
+} // namespace
+
+bool IsXScreensaverActive() {
+ // Avoid calling into potentially missing X11 APIs in headless mode.
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless))
+ return false;
+
+ static base::NoDestructor<ScreensaverStatusWatcher> watcher;
+ return watcher->ScreensaverActive();
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/x/x11_screensaver.h b/chromium/ui/base/x/x11_screensaver.h
new file mode 100644
index 00000000000..cb67abd2e6e
--- /dev/null
+++ b/chromium/ui/base/x/x11_screensaver.h
@@ -0,0 +1,16 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_X_X11_SCREENSAVER_H_
+#define UI_BASE_X_X11_SCREENSAVER_H_
+
+#include "base/component_export.h"
+
+namespace ui {
+
+COMPONENT_EXPORT(UI_BASE_X) bool IsXScreensaverActive();
+
+} // namespace ui
+
+#endif // UI_BASE_X_X11_SCREENSAVER_H_
diff --git a/chromium/ui/base/x/x11_screensaver_window_finder.cc b/chromium/ui/base/x/x11_screensaver_window_finder.cc
deleted file mode 100644
index accaf0717d8..00000000000
--- a/chromium/ui/base/x/x11_screensaver_window_finder.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/base/x/x11_screensaver_window_finder.h"
-
-#include "base/command_line.h"
-#include "base/strings/string_piece_forward.h"
-#include "ui/base/x/x11_util.h"
-#include "ui/gfx/switches.h"
-#include "ui/gfx/x/connection.h"
-#include "ui/gfx/x/scoped_ignore_errors.h"
-#include "ui/gfx/x/screensaver.h"
-#include "ui/gfx/x/x11_atom_cache.h"
-#include "ui/gfx/x/xproto_util.h"
-
-namespace ui {
-
-ScreensaverWindowFinder::ScreensaverWindowFinder() : exists_(false) {}
-
-// static
-bool ScreensaverWindowFinder::ScreensaverWindowExists() {
- // Avoid calling into potentially missing X11 APIs in headless mode.
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless))
- return false;
-
- auto* connection = x11::Connection::Get();
-
- // Let the server know the client version before making any requests.
- connection->screensaver().QueryVersion(
- {x11::ScreenSaver::major_version, x11::ScreenSaver::minor_version});
-
- auto reply =
- connection->screensaver().QueryInfo(connection->default_root()).Sync();
- if (reply && static_cast<x11::ScreenSaver::State>(reply->state) ==
- x11::ScreenSaver::State::On) {
- return true;
- }
-
- // Ironically, xscreensaver does not conform to the XScreenSaver protocol, so
- // info.state == ScreenSaverOff or info.state == ScreenSaverDisabled does not
- // necessarily mean that a screensaver is not active, so add a special check
- // for xscreensaver.
- x11::Atom lock_atom = x11::GetAtom("LOCK");
- std::vector<x11::Atom> atom_properties;
- if (GetArrayProperty(GetX11RootWindow(), x11::GetAtom("_SCREENSAVER_STATUS"),
- &atom_properties) &&
- atom_properties.size() > 0) {
- if (atom_properties[0] == lock_atom)
- return true;
- }
-
- // Also check the top level windows to see if any of them are screensavers.
- x11::ScopedIgnoreErrors ignore_errors(connection);
- ScreensaverWindowFinder finder;
- ui::EnumerateTopLevelWindows(&finder);
- return finder.exists_;
-}
-
-bool ScreensaverWindowFinder::ShouldStopIterating(x11::Window window) {
- if (!ui::IsWindowVisible(window) || !IsScreensaverWindow(window))
- return false;
- exists_ = true;
- return true;
-}
-
-bool ScreensaverWindowFinder::IsScreensaverWindow(x11::Window window) const {
- // It should occupy the full screen.
- if (!ui::IsX11WindowFullScreen(window))
- return false;
-
- // For xscreensaver, the window should have _SCREENSAVER_VERSION property.
- if (ui::PropertyExists(window, x11::GetAtom("_SCREENSAVER_VERSION")))
- return true;
-
- // For all others, like gnome-screensaver, the window's WM_CLASS property
- // should contain "screensaver".
- std::vector<char> value;
- if (!GetArrayProperty(window, x11::Atom::WM_CLASS, &value))
- return false;
-
- return base::StringPiece(value.data(), value.size()).find("screensaver") !=
- base::StringPiece::npos;
-}
-
-} // namespace ui
diff --git a/chromium/ui/base/x/x11_screensaver_window_finder.h b/chromium/ui/base/x/x11_screensaver_window_finder.h
deleted file mode 100644
index 147099a629c..00000000000
--- a/chromium/ui/base/x/x11_screensaver_window_finder.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_BASE_X_X11_SCREENSAVER_WINDOW_FINDER_H_
-#define UI_BASE_X_X11_SCREENSAVER_WINDOW_FINDER_H_
-
-#include "base/component_export.h"
-#include "base/macros.h"
-#include "ui/base/x/x11_util.h"
-
-namespace ui {
-
-class COMPONENT_EXPORT(UI_BASE_X) ScreensaverWindowFinder
- : public ui::EnumerateWindowsDelegate {
- public:
- static bool ScreensaverWindowExists();
-
- protected:
- bool ShouldStopIterating(x11::Window window) override;
-
- private:
- ScreensaverWindowFinder();
-
- bool IsScreensaverWindow(x11::Window window) const;
-
- bool exists_;
-
- DISALLOW_COPY_AND_ASSIGN(ScreensaverWindowFinder);
-};
-
-} // namespace ui
-
-#endif // UI_BASE_X_X11_SCREENSAVER_WINDOW_FINDER_H_
diff --git a/chromium/ui/base/x/x11_util.cc b/chromium/ui/base/x/x11_util.cc
index 2efcfb9f456..e96116b2d94 100644
--- a/chromium/ui/base/x/x11_util.cc
+++ b/chromium/ui/base/x/x11_util.cc
@@ -49,6 +49,7 @@
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkTypes.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
+#include "ui/base/x/visual_picker_glx.h"
#include "ui/base/x/x11_cursor.h"
#include "ui/base/x/x11_cursor_loader.h"
#include "ui/base/x/x11_menu_list.h"
@@ -706,81 +707,6 @@ bool GetWindowDesktop(x11::Window window, int32_t* desktop) {
return GetProperty(window, x11::GetAtom("_NET_WM_DESKTOP"), desktop);
}
-// Returns true if |window| is a named window.
-bool IsWindowNamed(x11::Window window) {
- return PropertyExists(window, x11::Atom::WM_NAME);
-}
-
-bool EnumerateChildren(EnumerateWindowsDelegate* delegate,
- x11::Window window,
- const int max_depth,
- int depth) {
- if (depth > max_depth)
- return false;
-
- std::vector<x11::Window> windows;
- std::vector<x11::Window>::iterator iter;
- if (depth == 0) {
- XMenuList::GetInstance()->InsertMenuWindows(&windows);
- // Enumerate the menus first.
- for (iter = windows.begin(); iter != windows.end(); iter++) {
- if (delegate->ShouldStopIterating(*iter))
- return true;
- }
- windows.clear();
- }
-
- auto query_tree = x11::Connection::Get()->QueryTree({window}).Sync();
- if (!query_tree)
- return false;
- windows = std::move(query_tree->children);
-
- // XQueryTree returns the children of |window| in bottom-to-top order, so
- // reverse-iterate the list to check the windows from top-to-bottom.
- for (iter = windows.begin(); iter != windows.end(); iter++) {
- if (IsWindowNamed(*iter) && delegate->ShouldStopIterating(*iter))
- return true;
- }
-
- // If we're at this point, we didn't find the window we're looking for at the
- // current level, so we need to recurse to the next level. We use a second
- // loop because the recursion and call to XQueryTree are expensive and is only
- // needed for a small number of cases.
- if (++depth <= max_depth) {
- for (iter = windows.begin(); iter != windows.end(); iter++) {
- if (EnumerateChildren(delegate, *iter, max_depth, depth))
- return true;
- }
- }
-
- return false;
-}
-
-bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate, int max_depth) {
- x11::Window root = GetX11RootWindow();
- return EnumerateChildren(delegate, root, max_depth, 0);
-}
-
-void EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate) {
- std::vector<x11::Window> stack;
- if (!ui::GetXWindowStack(ui::GetX11RootWindow(), &stack)) {
- // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back
- // to old school enumeration of all X windows. Some WMs parent 'top-level'
- // windows in unnamed actual top-level windows (ion WM), so extend the
- // search depth to all children of top-level windows.
- const int kMaxSearchDepth = 1;
- ui::EnumerateAllWindows(delegate, kMaxSearchDepth);
- return;
- }
- XMenuList::GetInstance()->InsertMenuWindows(&stack);
-
- std::vector<x11::Window>::iterator iter;
- for (iter = stack.begin(); iter != stack.end(); iter++) {
- if (delegate->ShouldStopIterating(*iter))
- return;
- }
-}
-
bool GetXWindowStack(x11::Window window, std::vector<x11::Window>* windows) {
if (!GetArrayProperty(window, x11::GetAtom("_NET_CLIENT_LIST_STACKING"),
windows)) {
@@ -1081,14 +1007,10 @@ bool IsVulkanSurfaceSupported() {
}
bool DoesVisualHaveAlphaForTest() {
- // testing/xvfb.py runs xvfb and xcompmgr.
- std::unique_ptr<base::Environment> env(base::Environment::Create());
-
uint8_t depth = 0;
bool visual_has_alpha = false;
ui::XVisualManager::GetInstance()->ChooseVisualForWindow(
- env->HasVar("_CHROMIUM_INSIDE_XVFB"), nullptr, &depth, nullptr,
- &visual_has_alpha);
+ true, nullptr, &depth, nullptr, &visual_has_alpha);
if (visual_has_alpha)
DCHECK_EQ(32, depth);
@@ -1144,36 +1066,48 @@ XVisualManager* XVisualManager::GetInstance() {
return base::Singleton<XVisualManager>::get();
}
-XVisualManager::XVisualManager() : connection_(x11::Connection::Get()) {
- base::AutoLock lock(lock_);
-
- for (const auto& depth : connection_->default_screen().allowed_depths) {
+XVisualManager::XVisualManager() {
+ auto* connection = x11::Connection::Get();
+ for (const auto& depth : connection->default_screen().allowed_depths) {
for (const auto& visual : depth.visuals) {
visuals_[visual.visual_id] =
- std::make_unique<XVisualData>(connection_, depth.depth, &visual);
+ std::make_unique<XVisualData>(connection, depth.depth, &visual);
}
}
+ auto* visual_picker = VisualPickerGlx::GetInstance();
+ x11::ColorMap colormap;
+
// Choose the opaque visual.
- default_visual_id_ = connection_->default_screen().root_visual;
- system_visual_id_ = default_visual_id_;
- DCHECK_NE(system_visual_id_, x11::VisualId{});
- DCHECK(visuals_.find(system_visual_id_) != visuals_.end());
+ opaque_visual_id_ = visual_picker->system_visual();
+ if (opaque_visual_id_ == x11::VisualId{})
+ opaque_visual_id_ = connection->default_screen().root_visual;
+ // opaque_visual_id_ may be unset in headless environments
+ if (opaque_visual_id_ != x11::VisualId{}) {
+ DCHECK(visuals_.find(opaque_visual_id_) != visuals_.end());
+ ChooseVisualForWindow(false, nullptr, nullptr, &colormap, nullptr);
+ }
// Choose the transparent visual.
- for (const auto& pair : visuals_) {
- // Why support only 8888 ARGB? Because it's all that GTK+ supports. In
- // gdkvisual-x11.cc, they look for this specific visual and use it for
- // all their alpha channel using needs.
- const auto& data = *pair.second;
- if (data.depth == 32 && data.info->red_mask == 0xff0000 &&
- data.info->green_mask == 0x00ff00 && data.info->blue_mask == 0x0000ff) {
- transparent_visual_id_ = pair.first;
- break;
+ transparent_visual_id_ = visual_picker->rgba_visual();
+ if (transparent_visual_id_ == x11::VisualId{}) {
+ for (const auto& pair : visuals_) {
+ // Why support only 8888 ARGB? Because it's all that GTK+ supports. In
+ // gdkvisual-x11.cc, they look for this specific visual and use it for
+ // all their alpha channel using needs.
+ const auto& data = *pair.second;
+ if (data.depth == 32 && data.info->red_mask == 0xff0000 &&
+ data.info->green_mask == 0x00ff00 &&
+ data.info->blue_mask == 0x0000ff) {
+ transparent_visual_id_ = pair.first;
+ break;
+ }
}
}
- if (transparent_visual_id_ != x11::VisualId{})
+ if (transparent_visual_id_ != x11::VisualId{}) {
DCHECK(visuals_.find(transparent_visual_id_) != visuals_.end());
+ ChooseVisualForWindow(true, nullptr, nullptr, &colormap, nullptr);
+ }
}
XVisualManager::~XVisualManager() = default;
@@ -1183,16 +1117,12 @@ void XVisualManager::ChooseVisualForWindow(bool want_argb_visual,
uint8_t* depth,
x11::ColorMap* colormap,
bool* visual_has_alpha) {
- base::AutoLock lock(lock_);
- bool use_argb = want_argb_visual && IsCompositingManagerPresent() &&
- (using_software_rendering_ || have_gpu_argb_visual_);
- x11::VisualId visual = use_argb && transparent_visual_id_ != x11::VisualId{}
- ? transparent_visual_id_
- : system_visual_id_;
+ bool use_argb = want_argb_visual && ArgbVisualAvailable();
+ x11::VisualId visual = use_argb ? transparent_visual_id_ : opaque_visual_id_;
if (visual_id)
*visual_id = visual;
- bool success = GetVisualInfoImpl(visual, depth, colormap, visual_has_alpha);
+ bool success = GetVisualInfo(visual, depth, colormap, visual_has_alpha);
DCHECK(success);
}
@@ -1200,54 +1130,20 @@ bool XVisualManager::GetVisualInfo(x11::VisualId visual_id,
uint8_t* depth,
x11::ColorMap* colormap,
bool* visual_has_alpha) {
- base::AutoLock lock(lock_);
- return GetVisualInfoImpl(visual_id, depth, colormap, visual_has_alpha);
-}
-
-bool XVisualManager::UpdateVisualsOnGpuInfoChanged(
- bool software_rendering,
- x11::VisualId system_visual_id,
- x11::VisualId transparent_visual_id) {
- base::AutoLock lock(lock_);
- // TODO(thomasanderson): Cache these visual IDs as a property of the root
- // window so that newly created browser processes can get them immediately.
- if ((system_visual_id != x11::VisualId{} &&
- !visuals_.count(system_visual_id)) ||
- (transparent_visual_id != x11::VisualId{} &&
- !visuals_.count(transparent_visual_id)))
- return false;
- using_software_rendering_ = software_rendering;
- have_gpu_argb_visual_ =
- have_gpu_argb_visual_ || transparent_visual_id != x11::VisualId{};
- if (system_visual_id != x11::VisualId{})
- system_visual_id_ = system_visual_id;
- if (transparent_visual_id != x11::VisualId{})
- transparent_visual_id_ = transparent_visual_id;
- return true;
-}
-
-bool XVisualManager::ArgbVisualAvailable() const {
- base::AutoLock lock(lock_);
- return IsCompositingManagerPresent() &&
- (using_software_rendering_ || have_gpu_argb_visual_);
-}
-
-bool XVisualManager::GetVisualInfoImpl(x11::VisualId visual_id,
- uint8_t* depth,
- x11::ColorMap* colormap,
- bool* visual_has_alpha) {
+ DCHECK_NE(visual_id, x11::VisualId{});
auto it = visuals_.find(visual_id);
if (it == visuals_.end())
return false;
XVisualData& data = *it->second;
const x11::VisualType& info = *data.info;
- bool is_default_visual = visual_id == default_visual_id_;
-
if (depth)
*depth = data.depth;
- if (colormap)
+ if (colormap) {
+ bool is_default_visual =
+ visual_id == x11::Connection::Get()->default_root_visual().visual_id;
*colormap = is_default_visual ? x11::ColorMap{} : data.GetColormap();
+ }
if (visual_has_alpha) {
auto popcount = [](auto x) {
return std::bitset<8 * sizeof(decltype(x))>(x).count();
@@ -1259,10 +1155,15 @@ bool XVisualManager::GetVisualInfoImpl(x11::VisualId visual_id,
return true;
}
+bool XVisualManager::ArgbVisualAvailable() const {
+ return IsCompositingManagerPresent() &&
+ transparent_visual_id_ != x11::VisualId{};
+}
+
XVisualManager::XVisualData::XVisualData(x11::Connection* connection,
uint8_t depth,
const x11::VisualType* info)
- : depth(depth), info(info), connection_(connection) {}
+ : depth(depth), info(info) {}
// Do not free the colormap as this would uninstall the colormap even for
// non-Chromium clients.
@@ -1270,9 +1171,10 @@ XVisualManager::XVisualData::~XVisualData() = default;
x11::ColorMap XVisualManager::XVisualData::GetColormap() {
if (colormap_ == x11::ColorMap{}) {
- colormap_ = connection_->GenerateId<x11::ColorMap>();
- connection_->CreateColormap({x11::ColormapAlloc::None, colormap_,
- connection_->default_root(), info->visual_id});
+ auto* connection = x11::Connection::Get();
+ colormap_ = connection->GenerateId<x11::ColorMap>();
+ connection->CreateColormap({x11::ColormapAlloc::None, colormap_,
+ connection->default_root(), info->visual_id});
}
return colormap_;
}
diff --git a/chromium/ui/base/x/x11_util.h b/chromium/ui/base/x/x11_util.h
index fc3f2d9360b..bf38c1fba42 100644
--- a/chromium/ui/base/x/x11_util.h
+++ b/chromium/ui/base/x/x11_util.h
@@ -40,7 +40,6 @@ class SkPixmap;
namespace base {
template <typename T>
struct DefaultSingletonTraits;
-class Value;
}
namespace gfx {
@@ -288,27 +287,6 @@ static const int32_t kAllDesktops = -1;
COMPONENT_EXPORT(UI_BASE_X)
bool GetWindowDesktop(x11::Window window, int32_t* desktop);
-// Implementers of this interface receive a notification for every X window of
-// the main display.
-class EnumerateWindowsDelegate {
- public:
- // |window| is the X Window ID of the enumerated window. Return true to stop
- // further iteration.
- virtual bool ShouldStopIterating(x11::Window window) = 0;
-
- protected:
- virtual ~EnumerateWindowsDelegate() = default;
-};
-
-// Enumerates all windows in the current display. Will recurse into child
-// windows up to a depth of |max_depth|.
-COMPONENT_EXPORT(UI_BASE_X)
-bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate, int max_depth);
-
-// Enumerates the top-level windows of the current display.
-COMPONENT_EXPORT(UI_BASE_X)
-void EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate);
-
// Returns all children windows of a given window in top-to-bottom stacking
// order.
COMPONENT_EXPORT(UI_BASE_X)
@@ -399,13 +377,6 @@ COMPONENT_EXPORT(UI_BASE_X) bool IsX11WindowFullScreen(x11::Window window);
// Suspends or resumes the X screen saver. Must be called on the UI thread.
COMPONENT_EXPORT(UI_BASE_X) void SuspendX11ScreenSaver(bool suspend);
-// Returns human readable description of the window manager, desktop, and
-// other system properties related to the compositing.
-COMPONENT_EXPORT(UI_BASE_X)
-void StoreGpuExtraInfoIntoListValue(x11::VisualId system_visual,
- x11::VisualId rgba_visual,
- base::Value& list_value);
-
// Returns true if the window manager supports the given hint.
COMPONENT_EXPORT(UI_BASE_X) bool WmSupportsHint(x11::Atom atom);
@@ -433,8 +404,7 @@ x11::Future<void> SendClientMessage(
// Return true if VulkanSurface is supported.
COMPONENT_EXPORT(UI_BASE_X) bool IsVulkanSurfaceSupported();
-// Returns whether the visual supports alpha.
-// The function examines the _CHROMIUM_INSIDE_XVFB environment variable.
+// Returns whether ARGB visuals are supported.
COMPONENT_EXPORT(UI_BASE_X) bool DoesVisualHaveAlphaForTest();
// Returns an icon for a native window referred by |target_window_id|. Can be
@@ -461,14 +431,6 @@ class COMPONENT_EXPORT(UI_BASE_X) XVisualManager {
x11::ColorMap* colormap,
bool* visual_has_alpha);
- // Called by GpuDataManagerImplPrivate when GPUInfo becomes available. It is
- // necessary for the GPU process to find out which visuals are best for GL
- // because we don't want to load GL in the browser process. Returns false iff
- // |default_visual_id| or |transparent_visual_id| are invalid.
- bool UpdateVisualsOnGpuInfoChanged(bool software_rendering,
- x11::VisualId default_visual_id,
- x11::VisualId transparent_visual_id);
-
// Are all of the system requirements met for using transparent visuals?
bool ArgbVisualAvailable() const;
@@ -491,32 +453,15 @@ class COMPONENT_EXPORT(UI_BASE_X) XVisualManager {
private:
x11::ColorMap colormap_{};
- x11::Connection* const connection_;
};
XVisualManager();
- bool GetVisualInfoImpl(x11::VisualId visual_id,
- uint8_t* depth,
- x11::ColorMap* colormap,
- bool* visual_has_alpha);
-
- mutable base::Lock lock_;
-
std::unordered_map<x11::VisualId, std::unique_ptr<XVisualData>> visuals_;
- x11::Connection* const connection_;
-
- x11::VisualId default_visual_id_{};
-
- // The system visual is usually the same as the default visual, but
- // may not be in general.
- x11::VisualId system_visual_id_{};
+ x11::VisualId opaque_visual_id_{};
x11::VisualId transparent_visual_id_{};
- bool using_software_rendering_ = false;
- bool have_gpu_argb_visual_ = false;
-
DISALLOW_COPY_AND_ASSIGN(XVisualManager);
};
@@ -526,7 +471,7 @@ class COMPONENT_EXPORT(UI_BASE_X) ScopedUnsetDisplay {
~ScopedUnsetDisplay();
private:
- base::Optional<std::string> display_;
+ absl::optional<std::string> display_;
DISALLOW_COPY_AND_ASSIGN(ScopedUnsetDisplay);
};
diff --git a/chromium/ui/base/x/x11_whole_screen_move_loop.h b/chromium/ui/base/x/x11_whole_screen_move_loop.h
index 72e7ed09968..62c596b2172 100644
--- a/chromium/ui/base/x/x11_whole_screen_move_loop.h
+++ b/chromium/ui/base/x/x11_whole_screen_move_loop.h
@@ -73,7 +73,7 @@ class COMPONENT_EXPORT(UI_BASE_X) X11WholeScreenMoveLoop
// Cursor in use prior to the move loop starting. Restored when the move loop
// quits.
- scoped_refptr<X11Cursor> initial_cursor_ = nullptr;
+ scoped_refptr<X11Cursor> initial_cursor_;
// An invisible InputOnly window. Keyboard grab and sometimes mouse grab
// are set on this window.
diff --git a/chromium/ui/chromeos/events/BUILD.gn b/chromium/ui/chromeos/events/BUILD.gn
index 39af81f32b7..dc5da8cd93c 100644
--- a/chromium/ui/chromeos/events/BUILD.gn
+++ b/chromium/ui/chromeos/events/BUILD.gn
@@ -29,6 +29,7 @@ source_set("events") {
"//ui/events:dom_keycode_converter",
"//ui/events/devices",
"//ui/events/ozone/evdev",
+ "//ui/events/ozone/evdev:event_device_info",
]
if (ozone_platform_x11) {
deps += [
diff --git a/chromium/ui/color/DIR_METADATA b/chromium/ui/color/DIR_METADATA
deleted file mode 100644
index f31293e3139..00000000000
--- a/chromium/ui/color/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail: {
- component: "UI"
-}
diff --git a/chromium/ui/color/color_id.h b/chromium/ui/color/color_id.h
index 748c21d1496..02bdde3cbcf 100644
--- a/chromium/ui/color/color_id.h
+++ b/chromium/ui/color/color_id.h
@@ -38,6 +38,12 @@
E(kColorAvatarIconIncognito, NativeTheme::kColorId_AvatarIconIncognito) \
E(kColorBubbleBackground, NativeTheme::kColorId_BubbleBackground) \
E(kColorBubbleBorder, NativeTheme::kColorId_BubbleBorder) \
+ E(kColorBubbleBorderShadowLarge, \
+ NativeTheme::kColorId_BubbleBorderShadowLarge) \
+ E(kColorBubbleBorderShadowSmall, \
+ NativeTheme::kColorId_BubbleBorderShadowSmall) \
+ E(kColorBubbleBorderWhenShadowPresent, \
+ NativeTheme::kColorId_BubbleBorderWhenShadowPresent) \
E(kColorBubbleFooterBackground, \
NativeTheme::kColorId_BubbleFooterBackground) \
E(kColorBubbleFooterBorder, NativeTheme::kColorId_BubbleFooterBorder) \
@@ -71,12 +77,14 @@
E(kColorFocusableBorderFocused, NativeTheme::kColorId_FocusedBorderColor) \
E(kColorFocusableBorderUnfocused, \
NativeTheme::kColorId_UnfocusedBorderColor) \
+ E(kColorFocusAura, NativeTheme::kColorId_FocusAuraColor) \
E(kColorFrameActive, NativeTheme::kColorId_CustomFrameActiveColor) \
E(kColorFrameInactive, NativeTheme::kColorId_CustomFrameInactiveColor) \
E(kColorHelpIconActive, NativeTheme::kColorId_TooltipIconHovered) \
E(kColorHelpIconInactive, NativeTheme::kColorId_TooltipIcon) \
E(kColorIcon, NativeTheme::kColorId_DefaultIconColor) \
E(kColorIconDisabled, NativeTheme::kColorId_DisabledIconColor) \
+ E(kColorIconSecondary, NativeTheme::kColorId_SecondaryIconColor) \
E(kColorLabelForeground, NativeTheme::kColorId_LabelEnabledColor) \
E(kColorLabelForegroundDisabled, NativeTheme::kColorId_LabelDisabledColor) \
E(kColorLabelForegroundSecondary, NativeTheme::kColorId_LabelSecondaryColor) \
@@ -151,6 +159,15 @@
E(kColorPwaToolbarForeground, \
NativeTheme::kColorId_CustomTabBarForegroundColor) \
E(kColorSeparator, NativeTheme::kColorId_SeparatorColor) \
+ E(kColorShadowBase, NativeTheme::kColorId_ShadowBase) \
+ E(kColorShadowValueAmbientShadowElevationThree, \
+ NativeTheme::kColorId_ShadowValueAmbientShadowElevationThree) \
+ E(kColorShadowValueKeyShadowElevationThree, \
+ NativeTheme::kColorId_ShadowValueKeyShadowElevationThree) \
+ E(kColorShadowValueAmbientShadowElevationSixteen, \
+ NativeTheme::kColorId_ShadowValueAmbientShadowElevationSixteen) \
+ E(kColorShadowValueKeyShadowElevationSixteen, \
+ NativeTheme::kColorId_ShadowValueKeyShadowElevationSixteen) \
E(kColorSliderThumb, NativeTheme::kColorId_SliderThumbDefault) \
E(kColorSliderThumbMinimal, NativeTheme::kColorId_SliderThumbMinimal) \
E(kColorSliderTrack, NativeTheme::kColorId_SliderTroughDefault) \
diff --git a/chromium/ui/color/color_provider_manager.cc b/chromium/ui/color/color_provider_manager.cc
index 0d18cd29572..5318232ef08 100644
--- a/chromium/ui/color/color_provider_manager.cc
+++ b/chromium/ui/color/color_provider_manager.cc
@@ -10,8 +10,8 @@
#include "base/check.h"
#include "base/logging.h"
#include "base/no_destructor.h"
-#include "base/optional.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/color/color_provider.h"
#include "ui/color/color_provider_utils.h"
@@ -33,10 +33,10 @@ class GlobalManager : public ColorProviderManager {
static_assert(sizeof(GlobalManager) == sizeof(ColorProviderManager),
"Global manager is intended to provide constructor visibility to "
- "base::Optional, nothing more.");
+ "absl::optional, nothing more.");
-base::Optional<GlobalManager>& GetGlobalManager() {
- static base::NoDestructor<base::Optional<GlobalManager>> manager;
+absl::optional<GlobalManager>& GetGlobalManager() {
+ static base::NoDestructor<absl::optional<GlobalManager>> manager;
return *manager;
}
@@ -50,13 +50,14 @@ ColorProviderManager::~ColorProviderManager() = default;
// static
ColorProviderManager& ColorProviderManager::Get() {
- base::Optional<GlobalManager>& manager = GetGlobalManager();
+ absl::optional<GlobalManager>& manager = GetGlobalManager();
if (!manager.has_value()) {
manager.emplace();
#if !defined(OS_ANDROID)
manager.value().AppendColorProviderInitializer(base::BindRepeating(
[](ColorProvider* provider, ColorProviderManager::ColorMode color_mode,
- ColorProviderManager::ContrastMode contrast_mode) {
+ ColorProviderManager::ContrastMode contrast_mode,
+ ColorProviderManager::ThemeName theme_name) {
const bool dark_mode =
color_mode == ColorProviderManager::ColorMode::kDark;
const bool high_contrast =
@@ -75,7 +76,7 @@ ColorProviderManager& ColorProviderManager::Get() {
// static
ColorProviderManager& ColorProviderManager::GetForTesting() {
- base::Optional<GlobalManager>& manager = GetGlobalManager();
+ absl::optional<GlobalManager>& manager = GetGlobalManager();
if (!manager.has_value())
manager.emplace();
return manager.value();
@@ -112,9 +113,11 @@ ColorProvider* ColorProviderManager::GetColorProviderFor(ColorProviderKey key) {
DVLOG(2) << "ColorProviderManager: Initializing Color Provider"
<< " - ColorMode: " << ColorModeName(std::get<ColorMode>(key))
<< " - ContrastMode: "
- << ContrastModeName(std::get<ContrastMode>(key));
+ << ContrastModeName(std::get<ContrastMode>(key))
+ << " - ThemeName: " << std::get<ThemeName>(key);
initializer_list_->Notify(provider.get(), std::get<ColorMode>(key),
- std::get<ContrastMode>(key));
+ std::get<ContrastMode>(key),
+ std::get<ThemeName>(key));
}
iter = color_providers_.emplace(key, std::move(provider)).first;
diff --git a/chromium/ui/color/color_provider_manager.h b/chromium/ui/color/color_provider_manager.h
index 26c1257b0af..d70fc14da50 100644
--- a/chromium/ui/color/color_provider_manager.h
+++ b/chromium/ui/color/color_provider_manager.h
@@ -32,9 +32,10 @@ class COMPONENT_EXPORT(COLOR) ColorProviderManager {
kNormal,
kHigh,
};
- using ColorProviderKey = std::tuple<ColorMode, ContrastMode>;
+ using ThemeName = std::string;
+ using ColorProviderKey = std::tuple<ColorMode, ContrastMode, ThemeName>;
using ColorProviderInitializerList = base::RepeatingCallbackList<
- void(ColorProvider*, ColorMode, ContrastMode)>;
+ void(ColorProvider*, ColorMode, ContrastMode, ThemeName)>;
ColorProviderManager(const ColorProviderManager&) = delete;
ColorProviderManager& operator=(const ColorProviderManager&) = delete;
diff --git a/chromium/ui/color/color_provider_manager_unittest.cc b/chromium/ui/color/color_provider_manager_unittest.cc
index 46a007eace6..e28ddec81ea 100644
--- a/chromium/ui/color/color_provider_manager_unittest.cc
+++ b/chromium/ui/color/color_provider_manager_unittest.cc
@@ -29,7 +29,7 @@ class ColorProviderManagerTest : public testing::Test {
ColorProvider* GetLightNormalColorProvider() {
return ColorProviderManager::GetForTesting().GetColorProviderFor(
{ColorProviderManager::ColorMode::kLight,
- ColorProviderManager::ContrastMode::kNormal});
+ ColorProviderManager::ContrastMode::kNormal, std::string()});
}
} // namespace
@@ -50,7 +50,8 @@ TEST_F(ColorProviderManagerTest, SetInitializer) {
ColorProviderManager::GetForTesting().AppendColorProviderInitializer(
base::BindRepeating([](ColorProvider* provider,
ColorProviderManager::ColorMode,
- ColorProviderManager::ContrastMode) {
+ ColorProviderManager::ContrastMode,
+ ColorProviderManager::ThemeName) {
provider->AddMixer().AddSet(
{kColorSetTest0, {{kColorTest0, SK_ColorBLUE}}});
}));
diff --git a/chromium/ui/color/color_transform.cc b/chromium/ui/color/color_transform.cc
index e433af7d7bd..6becb1e839b 100644
--- a/chromium/ui/color/color_transform.cc
+++ b/chromium/ui/color/color_transform.cc
@@ -80,23 +80,23 @@ ColorTransform AlphaBlend(ColorTransform foreground_transform,
ColorTransform BlendForMinContrast(
ColorTransform foreground_transform,
ColorTransform background_transform,
- base::Optional<ColorTransform> high_contrast_foreground_transform,
+ absl::optional<ColorTransform> high_contrast_foreground_transform,
float contrast_ratio) {
const auto generator =
[](ColorTransform foreground_transform,
ColorTransform background_transform,
- base::Optional<ColorTransform> high_contrast_foreground_transform,
+ absl::optional<ColorTransform> high_contrast_foreground_transform,
float contrast_ratio, SkColor input_color, const ColorMixer& mixer) {
const SkColor foreground_color =
foreground_transform.Run(input_color, mixer);
const SkColor background_color =
background_transform.Run(input_color, mixer);
- const base::Optional<SkColor> high_contrast_foreground =
+ const absl::optional<SkColor> high_contrast_foreground =
high_contrast_foreground_transform.has_value()
- ? base::make_optional(
+ ? absl::make_optional(
high_contrast_foreground_transform.value().Run(
input_color, mixer))
- : base::nullopt;
+ : absl::nullopt;
const SkColor result_color =
color_utils::BlendForMinContrast(foreground_color, background_color,
high_contrast_foreground,
@@ -121,7 +121,7 @@ ColorTransform BlendForMinContrast(
ColorTransform BlendForMinContrastWithSelf(ColorTransform transform,
float contrast_ratio) {
- return BlendForMinContrast(transform, transform, base::nullopt,
+ return BlendForMinContrast(transform, transform, absl::nullopt,
contrast_ratio);
}
@@ -153,7 +153,7 @@ ColorTransform ContrastInvert(ColorTransform transform) {
color_utils::GetContrastRatio(foreground, far_endpoint);
const SkColor result_color =
color_utils::BlendForMinContrast(foreground, near_endpoint,
- base::nullopt, contrast_ratio)
+ absl::nullopt, contrast_ratio)
.color;
DVLOG(2) << "ColorTransform ContrastInvert:"
<< " Input Color: " << SkColorName(input_color)
diff --git a/chromium/ui/color/color_transform.h b/chromium/ui/color/color_transform.h
index 5d954842b4b..752200ec9a5 100644
--- a/chromium/ui/color/color_transform.h
+++ b/chromium/ui/color/color_transform.h
@@ -7,8 +7,8 @@
#include "base/callback.h"
#include "base/component_export.h"
-#include "base/optional.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/color/color_id.h"
#include "ui/gfx/color_utils.h"
@@ -59,8 +59,8 @@ COMPONENT_EXPORT(COLOR)
ColorTransform BlendForMinContrast(
ColorTransform foreground_transform,
ColorTransform background_transform,
- base::Optional<ColorTransform> high_contrast_foreground_transform =
- base::nullopt,
+ absl::optional<ColorTransform> high_contrast_foreground_transform =
+ absl::nullopt,
float contrast_ratio = color_utils::kMinimumReadableContrastRatio);
// A transform which blends the result of |transform| toward the color with max
diff --git a/chromium/ui/color/mac/scoped_current_nsappearance.h b/chromium/ui/color/mac/scoped_current_nsappearance.h
index 73e8901c000..8efa0bf048c 100644
--- a/chromium/ui/color/mac/scoped_current_nsappearance.h
+++ b/chromium/ui/color/mac/scoped_current_nsappearance.h
@@ -25,4 +25,4 @@ class COMPONENT_EXPORT(COLOR) ScopedCurrentNSAppearance {
} // namespace ui
-#endif \ No newline at end of file
+#endif // UI_COLOR_MAC_SCOPED_CURRENT_NSAPPEARANCE_H_
diff --git a/chromium/ui/color/ui_color_mixer.cc b/chromium/ui/color/ui_color_mixer.cc
index a9c3b72ff6a..3c41a4a9ca3 100644
--- a/chromium/ui/color/ui_color_mixer.cc
+++ b/chromium/ui/color/ui_color_mixer.cc
@@ -21,6 +21,9 @@ void AddUiColorMixer(ColorProvider* provider,
mixer[kColorAvatarIconIncognito] = {kColorPrimaryForeground};
mixer[kColorBubbleBackground] = {kColorPrimaryBackground};
mixer[kColorBubbleBorder] = {kColorMidground};
+ mixer[kColorBubbleBorderShadowLarge] = {SetAlpha(kColorShadowBase, 0x1A)};
+ mixer[kColorBubbleBorderShadowSmall] = {SetAlpha(kColorShadowBase, 0x33)};
+ mixer[kColorBubbleBorderWhenShadowPresent] = {SetAlpha(SK_ColorBLACK, 0x26)};
mixer[kColorBubbleFooterBackground] = {kColorSubtleEmphasisBackground};
mixer[kColorBubbleFooterBorder] = {kColorMidground};
mixer[kColorButtonBackground] = {kColorPrimaryBackground};
@@ -46,6 +49,7 @@ void AddUiColorMixer(ColorProvider* provider,
mixer[kColorDropdownForegroundSelected] = {kColorPrimaryForeground};
mixer[kColorFocusableBorderFocused] = {kColorItemHighlight};
mixer[kColorFocusableBorderUnfocused] = {kColorMidground};
+ mixer[kColorFocusAura] = SetAlpha(kColorAccent, 0x3D);
mixer[kColorFrameActive] = {dark_window ? gfx::kGoogleGrey900
: SkColorSetRGB(0xDE, 0xE1, 0xE6)};
mixer[kColorFrameInactive] = {dark_window ? gfx::kGoogleGrey800
@@ -54,6 +58,7 @@ void AddUiColorMixer(ColorProvider* provider,
mixer[kColorHelpIconInactive] = {kColorSecondaryForeground};
mixer[kColorIcon] = {kColorSecondaryForeground};
mixer[kColorIconDisabled] = SetAlpha(kColorIcon, gfx::kDisabledControlAlpha);
+ mixer[kColorIconSecondary] = {gfx::kGoogleGrey600};
mixer[kColorLabelForeground] = {kColorPrimaryForeground};
mixer[kColorLabelForegroundDisabled] = {kColorDisabledForeground};
mixer[kColorLabelForegroundSecondary] = {kColorSecondaryForeground};
@@ -109,6 +114,15 @@ void AddUiColorMixer(ColorProvider* provider,
mixer[kColorPwaToolbarBackground] = {kColorEndpointBackground};
mixer[kColorPwaToolbarForeground] = {kColorEndpointForeground};
mixer[kColorSeparator] = {kColorMidground};
+ mixer[kColorShadowBase] = {dark_window ? SK_ColorBLACK : gfx::kGoogleGrey800};
+ mixer[kColorShadowValueAmbientShadowElevationThree] =
+ SetAlpha(kColorShadowBase, 0x40);
+ mixer[kColorShadowValueKeyShadowElevationThree] =
+ SetAlpha(kColorShadowBase, 0x66);
+ mixer[kColorShadowValueAmbientShadowElevationSixteen] =
+ SetAlpha(kColorShadowBase, 0x3d);
+ mixer[kColorShadowValueKeyShadowElevationSixteen] =
+ SetAlpha(kColorShadowBase, 0x1a);
mixer[kColorSliderThumb] = {kColorAccent};
mixer[kColorSliderThumbMinimal] = {kColorSecondaryForeground};
mixer[kColorSliderTrack] = {kColorSubtleAccent};
diff --git a/chromium/ui/compositor/BUILD.gn b/chromium/ui/compositor/BUILD.gn
index ea8c813108d..9f3cca807e0 100644
--- a/chromium/ui/compositor/BUILD.gn
+++ b/chromium/ui/compositor/BUILD.gn
@@ -267,6 +267,7 @@ test("compositor_unittests") {
"//testing/gtest",
"//ui/base",
"//ui/gfx",
+ "//ui/gfx:test_support",
"//ui/gfx/geometry",
"//ui/gl",
"//ui/resources",
diff --git a/chromium/ui/compositor/animation_throughput_reporter.cc b/chromium/ui/compositor/animation_throughput_reporter.cc
index 043a349fccd..d7c623467c9 100644
--- a/chromium/ui/compositor/animation_throughput_reporter.cc
+++ b/chromium/ui/compositor/animation_throughput_reporter.cc
@@ -10,8 +10,8 @@
#include "base/bind.h"
#include "base/check.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "cc/animation/animation.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/compositor/callback_layer_animation_observer.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
@@ -131,9 +131,9 @@ class AnimationThroughputReporter::AnimationTracker
LayerAnimator* const animator_;
- base::Optional<ThroughputTracker> throughput_tracker_;
+ absl::optional<ThroughputTracker> throughput_tracker_;
- base::Optional<int> first_animation_group_id_;
+ absl::optional<int> first_animation_group_id_;
bool started_animations_aborted_ = false;
AnimationThroughputReporter::ReportCallback report_callback_;
diff --git a/chromium/ui/compositor/compositor.cc b/chromium/ui/compositor/compositor.cc
index 34f84bbdc2c..bc4437e99ca 100644
--- a/chromium/ui/compositor/compositor.cc
+++ b/chromium/ui/compositor/compositor.cc
@@ -57,6 +57,7 @@
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/display/display_switches.h"
#include "ui/gfx/icc_profile.h"
+#include "ui/gfx/presentation_feedback.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
@@ -744,27 +745,49 @@ void Compositor::OnFrameTokenChanged(uint32_t frame_token,
NOTREACHED();
}
+Compositor::TrackerState::TrackerState() = default;
+Compositor::TrackerState::TrackerState(TrackerState&&) = default;
+Compositor::TrackerState& Compositor::TrackerState::operator=(TrackerState&&) =
+ default;
+Compositor::TrackerState::~TrackerState() = default;
+
void Compositor::StartThroughputTracker(
TrackerId tracker_id,
ThroughputTrackerHost::ReportCallback callback) {
DCHECK(!base::Contains(throughput_tracker_map_, tracker_id));
- throughput_tracker_map_[tracker_id] = std::move(callback);
+
+ auto& tracker_state = throughput_tracker_map_[tracker_id];
+ tracker_state.report_callback = std::move(callback);
+
animation_host_->StartThroughputTracking(tracker_id);
}
-void Compositor::StopThroughtputTracker(TrackerId tracker_id) {
- // TODO(crbug.com/1183374): DCHECKs are disabled during automated testing on
- // CrOS and this check failed when tested on an experimental builder. Revert
- // https://crrev.com/c/2727841 (or uncomment) to enable it. See
- // go/chrome-dcheck-on-cros or http://crbug.com/1113456 for more details.
- // DCHECK(base::Contains(throughput_tracker_map_, tracker_id));
+bool Compositor::StopThroughtputTracker(TrackerId tracker_id) {
+ auto it = throughput_tracker_map_.find(tracker_id);
+ DCHECK(it != throughput_tracker_map_.end());
+
+ // Clean up if report has happened since StopThroughputTracking would
+ // not trigger report in this case.
+ if (it->second.report_attempted) {
+ throughput_tracker_map_.erase(it);
+ return false;
+ }
+
+ it->second.should_report = true;
animation_host_->StopThroughputTracking(tracker_id);
+ return true;
}
void Compositor::CancelThroughtputTracker(TrackerId tracker_id) {
- DCHECK(base::Contains(throughput_tracker_map_, tracker_id));
- StopThroughtputTracker(tracker_id);
- throughput_tracker_map_.erase(tracker_id);
+ auto it = throughput_tracker_map_.find(tracker_id);
+ DCHECK(it != throughput_tracker_map_.end());
+
+ const bool should_stop = !it->second.report_attempted;
+
+ throughput_tracker_map_.erase(it);
+
+ if (should_stop)
+ animation_host_->StopThroughputTracking(tracker_id);
}
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
@@ -803,15 +826,22 @@ void Compositor::ReportMetricsForTracker(
if (it == throughput_tracker_map_.end())
return;
+ // Set `report_attempted` but not reporting if relevant ThroughputTrackers
+ // are not stopped and waiting for reports.
+ if (!it->second.should_report) {
+ it->second.report_attempted = true;
+ return;
+ }
+
// Callback may modify `throughput_tracker_map_` so update the map first.
// See https://crbug.com/1193382.
- auto callback = std::move(it->second);
+ auto callback = std::move(it->second.report_callback);
throughput_tracker_map_.erase(it);
std::move(callback).Run(data);
}
void Compositor::SetDelegatedInkPointRenderer(
- mojo::PendingReceiver<viz::mojom::DelegatedInkPointRenderer> receiver) {
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer> receiver) {
if (display_private_)
display_private_->SetDelegatedInkPointRenderer(std::move(receiver));
}
diff --git a/chromium/ui/compositor/compositor.h b/chromium/ui/compositor/compositor.h
index e4ff4cb0a2e..fe4e33a6208 100644
--- a/chromium/ui/compositor/compositor.h
+++ b/chromium/ui/compositor/compositor.h
@@ -61,6 +61,9 @@ class TaskGraphRunner;
}
namespace gfx {
+namespace mojom {
+class DelegatedInkPointRenderer;
+} // namespace mojom
struct PresentationFeedback;
class Rect;
class ScrollOffset;
@@ -75,7 +78,6 @@ namespace viz {
namespace mojom {
class DisplayPrivate;
class ExternalBeginFrameController;
-class DelegatedInkPointRenderer;
} // namespace mojom
class ContextProvider;
class HostFrameSinkManager;
@@ -370,7 +372,7 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
void StartThroughputTracker(
TrackerId tracker_id,
ThroughputTrackerHost::ReportCallback callback) override;
- void StopThroughtputTracker(TrackerId tracker_id) override;
+ bool StopThroughtputTracker(TrackerId tracker_id) override;
void CancelThroughtputTracker(TrackerId tracker_id) override;
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
@@ -410,7 +412,7 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
}
virtual void SetDelegatedInkPointRenderer(
- mojo::PendingReceiver<viz::mojom::DelegatedInkPointRenderer> receiver);
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer> receiver);
private:
friend class base::RefCounted<Compositor>;
@@ -502,8 +504,23 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
bool disabled_swap_until_resize_ = false;
TrackerId next_throughput_tracker_id_ = 1u;
- using ThroughputTrackerMap =
- base::flat_map<TrackerId, ThroughputTrackerHost::ReportCallback>;
+ struct TrackerState {
+ TrackerState();
+ TrackerState(TrackerState&&);
+ TrackerState& operator=(TrackerState&&);
+ ~TrackerState();
+
+ // Whether a tracker is waiting for report and `report_callback` should be
+ // invoked. This is set to true when a tracker is stopped.
+ bool should_report = false;
+ // Whether the report for a tracker has happened. This is set when an
+ // involuntary report happens before the tracker is stopped and set
+ // `should_report` field above.
+ bool report_attempted = false;
+ // Invoked to send report to the owner of a tracker.
+ ThroughputTrackerHost::ReportCallback report_callback;
+ };
+ using ThroughputTrackerMap = base::flat_map<TrackerId, TrackerState>;
ThroughputTrackerMap throughput_tracker_map_;
base::WeakPtrFactory<Compositor> context_creation_weak_ptr_factory_{this};
diff --git a/chromium/ui/compositor/compositor_unittest.cc b/chromium/ui/compositor/compositor_unittest.cc
index 7eaa8bbe4ab..7e3faff7a9b 100644
--- a/chromium/ui/compositor/compositor_unittest.cc
+++ b/chromium/ui/compositor/compositor_unittest.cc
@@ -192,7 +192,7 @@ TEST_F(CompositorTestWithMessageLoop, MoveThroughputTracker) {
// May be called since Stop() is called.
}));
auto moved_tracker = std::move(tracker);
- moved_tracker.Stop();
+ EXPECT_TRUE(moved_tracker.Stop());
}
// Move a started instance and cancel.
@@ -214,7 +214,7 @@ TEST_F(CompositorTestWithMessageLoop, MoveThroughputTracker) {
[&](const cc::FrameSequenceMetrics::CustomReportData& data) {
// May be called since Stop() is called.
}));
- tracker.Stop();
+ EXPECT_TRUE(tracker.Stop());
auto moved_tracker = std::move(tracker);
}
@@ -257,7 +257,7 @@ TEST_F(CompositorTestWithMessageLoop, ThroughputTracker) {
DrawWaiterForTest::WaitForCompositingEnded(compositor());
}
- tracker.Stop();
+ EXPECT_TRUE(tracker.Stop());
// Generates a few frames after tracker stops. Note the number of frames
// must be at least two: one to trigger underlying cc::FrameSequenceTracker to
@@ -279,8 +279,8 @@ TEST_F(CompositorTestWithMessageLoop, ThroughputTrackerOutliveCompositor) {
DestroyCompositor();
- // No crash, no use-after-free and no report.
- tracker.Stop();
+ // Stop() fails but no crash, no use-after-free and no report.
+ EXPECT_FALSE(tracker.Stop());
}
TEST_F(CompositorTestWithMessageLoop, ThroughputTrackerCallbackStateChange) {
@@ -315,7 +315,7 @@ TEST_F(CompositorTestWithMessageLoop, ThroughputTrackerCallbackStateChange) {
DrawWaiterForTest::WaitForCompositingEnded(compositor());
}
- tracker.Stop();
+ EXPECT_TRUE(tracker.Stop());
// Generates a few frames after tracker stops. Note the number of frames
// must be at least two: one to trigger underlying cc::FrameSequenceTracker to
@@ -328,6 +328,38 @@ TEST_F(CompositorTestWithMessageLoop, ThroughputTrackerCallbackStateChange) {
run_loop.Run();
}
+TEST_F(CompositorTestWithMessageLoop, ThroughputTrackerInvoluntaryReport) {
+ auto root_layer = std::make_unique<Layer>(ui::LAYER_SOLID_COLOR);
+ viz::ParentLocalSurfaceIdAllocator allocator;
+ allocator.GenerateId();
+ root_layer->SetBounds(gfx::Rect(10, 10));
+ compositor()->SetRootLayer(root_layer.get());
+ compositor()->SetScaleAndSize(1.0f, gfx::Size(10, 10),
+ allocator.GetCurrentLocalSurfaceId());
+ ASSERT_TRUE(compositor()->IsVisible());
+
+ ThroughputTracker tracker = compositor()->RequestNewThroughputTracker();
+
+ tracker.Start(base::BindLambdaForTesting(
+ [&](const cc::FrameSequenceMetrics::CustomReportData& data) {
+ ADD_FAILURE() << "No report should happen";
+ }));
+
+ // Generates a few frames after tracker starts to have some data collected.
+ for (int i = 0; i < 5; ++i) {
+ compositor()->ScheduleFullRedraw();
+ DrawWaiterForTest::WaitForCompositingEnded(compositor());
+ }
+
+ // ReleaseAcceleratedWidget() destroys underlying cc::FrameSequenceTracker
+ // and triggers reports before Stop(). Such reports are dropped.
+ compositor()->SetVisible(false);
+ compositor()->ReleaseAcceleratedWidget();
+
+ // Stop() fails but no DCHECK or crash.
+ EXPECT_FALSE(tracker.Stop());
+}
+
#if defined(OS_WIN)
// TODO(crbug.com/608436): Flaky on windows trybots
#define MAYBE_CreateAndReleaseOutputSurface \
diff --git a/chromium/ui/compositor/layer.cc b/chromium/ui/compositor/layer.cc
index e6217f583f0..a869508f757 100644
--- a/chromium/ui/compositor/layer.cc
+++ b/chromium/ui/compositor/layer.cc
@@ -213,6 +213,9 @@ Layer::~Layer() {
// Destroying the animator may cause observers to use the layer. Destroy the
// animator first so that the layer is still around.
+#if defined(ADDRESS_SANITIZER)
+ destroyed_ = true;
+#endif
SetAnimator(nullptr);
if (compositor_)
compositor_->SetRootLayer(nullptr);
@@ -229,7 +232,7 @@ Layer::~Layer() {
content_layer_->ClearClient();
cc_layer_->RemoveFromParent();
if (transfer_release_callback_)
- transfer_release_callback_->Run(gpu::SyncToken(), false);
+ std::move(transfer_release_callback_).Run(gpu::SyncToken(), false);
ResetSubtreeReflectedLayer();
}
@@ -296,8 +299,7 @@ std::unique_ptr<Layer> Layer::Mirror() {
// freed up until the original layer releases it.
mirror->SetTransferableResource(
transfer_resource_,
- viz::SingleReleaseCallback::Create(base::BindOnce(
- [](const gpu::SyncToken& sync_token, bool is_lost) {})),
+ base::BindOnce([](const gpu::SyncToken& sync_token, bool is_lost) {}),
frame_size_in_dip_);
}
@@ -436,6 +438,9 @@ bool Layer::Contains(const Layer* other) const {
}
void Layer::SetAnimator(LayerAnimator* animator) {
+#if defined(ADDRESS_SANITIZER)
+ CHECK(!destroyed_ || !animator);
+#endif
Compositor* compositor = GetCompositor();
if (animator_) {
@@ -710,9 +715,22 @@ void Layer::SetIsFastRoundedCorner(bool enable) {
mirror->dest()->SetIsFastRoundedCorner(enable);
}
+bool Layer::GetTargetTransformRelativeTo(const Layer* ancestor,
+ gfx::Transform* transform) const {
+ return GetTransformRelativeToImpl(ancestor, /*is_target_transform=*/true,
+ transform);
+}
+
+bool Layer::GetTransformRelativeTo(const Layer* ancestor,
+ gfx::Transform* transform) const {
+ return GetTransformRelativeToImpl(ancestor, /*is_target_transform=*/false,
+ transform);
+}
+
// static
void Layer::ConvertPointToLayer(const Layer* source,
const Layer* target,
+ bool use_target_transform,
gfx::PointF* point) {
if (source == target)
return;
@@ -721,25 +739,9 @@ void Layer::ConvertPointToLayer(const Layer* source,
CHECK_EQ(root_layer, GetRoot(target));
if (source != root_layer)
- source->ConvertPointForAncestor(root_layer, point);
+ source->ConvertPointForAncestor(root_layer, use_target_transform, point);
if (target != root_layer)
- target->ConvertPointFromAncestor(root_layer, point);
-}
-
-bool Layer::GetTargetTransformRelativeTo(const Layer* ancestor,
- gfx::Transform* transform) const {
- const Layer* p = this;
- for (; p && p != ancestor; p = p->parent()) {
- gfx::Transform translation;
- translation.Translate(static_cast<float>(p->bounds().x()),
- static_cast<float>(p->bounds().y()));
- // Use target transform so that result will be correct once animation is
- // finished.
- if (!p->GetTargetTransform().IsIdentity())
- transform->ConcatTransform(p->GetTargetTransform());
- transform->ConcatTransform(translation);
- }
- return p == ancestor;
+ target->ConvertPointFromAncestor(root_layer, use_target_transform, point);
}
void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
@@ -921,10 +923,9 @@ bool Layer::ContainsMirrorForTest(Layer* mirror) const {
return it != mirrors_.end();
}
-void Layer::SetTransferableResource(
- const viz::TransferableResource& resource,
- std::unique_ptr<viz::SingleReleaseCallback> release_callback,
- gfx::Size texture_size_in_dip) {
+void Layer::SetTransferableResource(const viz::TransferableResource& resource,
+ viz::ReleaseCallback release_callback,
+ gfx::Size texture_size_in_dip) {
DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
DCHECK(!resource.mailbox_holder.mailbox.IsZero());
DCHECK(release_callback);
@@ -942,7 +943,7 @@ void Layer::SetTransferableResource(
frame_size_in_dip_ = gfx::Size();
}
if (transfer_release_callback_)
- transfer_release_callback_->Run(gpu::SyncToken(), false);
+ std::move(transfer_release_callback_).Run(gpu::SyncToken(), false);
transfer_release_callback_ = std::move(release_callback);
transfer_resource_ = resource;
SetTextureSize(texture_size_in_dip);
@@ -952,8 +953,7 @@ void Layer::SetTransferableResource(
// should be able to release the texture resource.
mirror->dest()->SetTransferableResource(
transfer_resource_,
- viz::SingleReleaseCallback::Create(base::BindOnce(
- [](const gpu::SyncToken& sync_token, bool is_lost) {})),
+ base::BindOnce([](const gpu::SyncToken& sync_token, bool is_lost) {}),
frame_size_in_dip_);
}
}
@@ -1062,8 +1062,7 @@ void Layer::SetShowSolidColorContent() {
transfer_resource_ = viz::TransferableResource();
if (transfer_release_callback_) {
- transfer_release_callback_->Run(gpu::SyncToken(), false);
- transfer_release_callback_.reset();
+ std::move(transfer_release_callback_).Run(gpu::SyncToken(), false);
}
RecomputeDrawsContentAndUVRect();
@@ -1336,7 +1335,7 @@ bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_; }
bool Layer::PrepareTransferableResource(
cc::SharedBitmapIdRegistrar* bitmap_registar,
viz::TransferableResource* resource,
- std::unique_ptr<viz::SingleReleaseCallback>* release_callback) {
+ viz::ReleaseCallback* release_callback) {
if (!transfer_release_callback_)
return false;
*resource = transfer_resource_;
@@ -1377,9 +1376,12 @@ void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) {
}
bool Layer::ConvertPointForAncestor(const Layer* ancestor,
+ bool use_target_transform,
gfx::PointF* point) const {
gfx::Transform transform;
- bool result = GetTargetTransformRelativeTo(ancestor, &transform);
+ bool result = use_target_transform
+ ? GetTargetTransformRelativeTo(ancestor, &transform)
+ : GetTransformRelativeTo(ancestor, &transform);
auto p = gfx::Point3F(*point);
transform.TransformPoint(&p);
*point = p.AsPointF();
@@ -1387,9 +1389,12 @@ bool Layer::ConvertPointForAncestor(const Layer* ancestor,
}
bool Layer::ConvertPointFromAncestor(const Layer* ancestor,
+ bool use_target_transform,
gfx::PointF* point) const {
gfx::Transform transform;
- bool result = GetTargetTransformRelativeTo(ancestor, &transform);
+ bool result = use_target_transform
+ ? GetTargetTransformRelativeTo(ancestor, &transform)
+ : GetTransformRelativeTo(ancestor, &transform);
auto p = gfx::Point3F(*point);
transform.TransformPointReverse(&p);
*point = p.AsPointF();
@@ -1564,12 +1569,12 @@ LayerAnimatorCollection* Layer::GetLayerAnimatorCollection() {
return compositor ? compositor->layer_animator_collection() : nullptr;
}
-base::Optional<int> Layer::GetFrameNumber() const {
+absl::optional<int> Layer::GetFrameNumber() const {
if (const Compositor* compositor = GetCompositor()) {
return compositor->activated_frame_count();
}
- return base::nullopt;
+ return absl::nullopt;
}
float Layer::GetRefreshRate() const {
@@ -1718,4 +1723,21 @@ void Layer::SetFillsBoundsOpaquelyWithReason(bool fills_bounds_opaquely,
delegate_->OnLayerFillsBoundsOpaquelyChanged(reason);
}
+bool Layer::GetTransformRelativeToImpl(const Layer* ancestor,
+ bool is_target_transform,
+ gfx::Transform* transform) const {
+ const Layer* p = this;
+ for (; p && p != ancestor; p = p->parent()) {
+ gfx::Transform translation;
+ translation.Translate(static_cast<float>(p->bounds().x()),
+ static_cast<float>(p->bounds().y()));
+ const gfx::Transform& layer_transform =
+ is_target_transform ? p->GetTargetTransform() : p->transform();
+ if (!layer_transform.IsIdentity())
+ transform->ConcatTransform(layer_transform);
+ transform->ConcatTransform(translation);
+ }
+ return p == ancestor;
+}
+
} // namespace ui
diff --git a/chromium/ui/compositor/layer.h b/chromium/ui/compositor/layer.h
index e82ad7e1692..f572b6f720f 100644
--- a/chromium/ui/compositor/layer.h
+++ b/chromium/ui/compositor/layer.h
@@ -330,14 +330,19 @@ class COMPOSITOR_EXPORT Layer : public LayerAnimationDelegate,
// Converts a point from the coordinates of |source| to the coordinates of
// |target|. Necessarily, |source| and |target| must inhabit the same Layer
- // tree.
+ // tree. If `use_target_transform` is true, the target transform is used in
+ // coordinate conversions; otherwise, the current transform is used. If there
+ // is no animation ongoing, the target transform is the same as the current
+ // transform.
static void ConvertPointToLayer(const Layer* source,
const Layer* target,
+ bool use_target_transform,
gfx::PointF* point);
- // Converts a transform to be relative to the given |ancestor|. Returns
- // whether success (that is, whether the given ancestor was really an
- // ancestor of this layer).
+ // Calculates the relative transform. See the comment of
+ // `GetTransformRelativeToImpl()` for further details.
+ bool GetTransformRelativeTo(const Layer* ancestor,
+ gfx::Transform* transform) const;
bool GetTargetTransformRelativeTo(const Layer* ancestor,
gfx::Transform* transform) const;
@@ -356,10 +361,9 @@ class COMPOSITOR_EXPORT Layer : public LayerAnimationDelegate,
// Set new TransferableResource for this layer. This method only supports
// a gpu-backed |resource|.
- void SetTransferableResource(
- const viz::TransferableResource& resource,
- std::unique_ptr<viz::SingleReleaseCallback> release_callback,
- gfx::Size texture_size_in_dip);
+ void SetTransferableResource(const viz::TransferableResource& resource,
+ viz::ReleaseCallback release_callback,
+ gfx::Size texture_size_in_dip);
void SetTextureSize(gfx::Size texture_size_in_dip);
void SetTextureFlipped(bool flipped);
bool TextureFlipped() const;
@@ -470,7 +474,7 @@ class COMPOSITOR_EXPORT Layer : public LayerAnimationDelegate,
bool PrepareTransferableResource(
cc::SharedBitmapIdRegistrar* bitmap_registar,
viz::TransferableResource* resource,
- std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override;
+ viz::ReleaseCallback* release_callback) override;
float device_scale_factor() const { return device_scale_factor_; }
@@ -541,8 +545,16 @@ class COMPOSITOR_EXPORT Layer : public LayerAnimationDelegate,
// StackBelow().
void StackRelativeTo(Layer* child, Layer* other, bool above);
- bool ConvertPointForAncestor(const Layer* ancestor, gfx::PointF* point) const;
+ // If `use_target_transform` is true, coordinate conversions use the target
+ // transform. The target transform is the end value of a transform animation.
+ // If `use_target_transform` is false, coordinate conversions use the current
+ // transform. If there is no animation ongoing, the target transform is the
+ // same as the current transform.
+ bool ConvertPointForAncestor(const Layer* ancestor,
+ bool use_target_transform,
+ gfx::PointF* point) const;
bool ConvertPointFromAncestor(const Layer* ancestor,
+ bool use_target_transform,
gfx::PointF* point) const;
// Implementation of LayerAnimatorDelegate
@@ -580,7 +592,7 @@ class COMPOSITOR_EXPORT Layer : public LayerAnimationDelegate,
cc::Layer* GetCcLayer() const override;
LayerThreadedAnimationDelegate* GetThreadedAnimationDelegate() override;
LayerAnimatorCollection* GetLayerAnimatorCollection() override;
- base::Optional<int> GetFrameNumber() const override;
+ absl::optional<int> GetFrameNumber() const override;
float GetRefreshRate() const override;
// Creates a corresponding composited layer for |type_|.
@@ -626,6 +638,15 @@ class COMPOSITOR_EXPORT Layer : public LayerAnimationDelegate,
void SetFillsBoundsOpaquelyWithReason(bool fills_bounds_opaquely,
PropertyChangeReason reason);
+ // Converts a transform to be relative to the given |ancestor|. If
+ // `is_target_transform` is true, the target transform is used in the
+ // coordinate conversions; otherwise, the current transform is used. Returns
+ // whether success (that is, whether the given ancestor was really an ancestor
+ // of this layer).
+ bool GetTransformRelativeToImpl(const Layer* ancestor,
+ bool is_target_transform,
+ gfx::Transform* transform) const;
+
const LayerType type_;
Compositor* compositor_;
@@ -736,7 +757,7 @@ class COMPOSITOR_EXPORT Layer : public LayerAnimationDelegate,
// The callback to release the mailbox. This is only set after
// SetTransferableResource() is called, before we give it to the TextureLayer.
- std::unique_ptr<viz::SingleReleaseCallback> transfer_release_callback_;
+ viz::ReleaseCallback transfer_release_callback_;
// The size of the frame or texture in DIP, set when SetShowDelegatedContent
// or SetTransferableResource() was called.
@@ -760,6 +781,11 @@ class COMPOSITOR_EXPORT Layer : public LayerAnimationDelegate,
// layer.
unsigned trilinear_filtering_request_;
+ // TODO(crbug.com/1172694): Remove once the root cause is identified.
+#if defined(ADDRESS_SANITIZER)
+ bool destroyed_ = false;
+#endif
+
base::WeakPtrFactory<Layer> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(Layer);
diff --git a/chromium/ui/compositor/layer_animation_delegate.h b/chromium/ui/compositor/layer_animation_delegate.h
index 9626869011d..a91a5e70d70 100644
--- a/chromium/ui/compositor/layer_animation_delegate.h
+++ b/chromium/ui/compositor/layer_animation_delegate.h
@@ -5,7 +5,7 @@
#ifndef UI_COMPOSITOR_LAYER_ANIMATION_DELEGATE_H_
#define UI_COMPOSITOR_LAYER_ANIMATION_DELEGATE_H_
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/compositor/compositor_export.h"
#include "ui/compositor/property_change_reason.h"
@@ -60,9 +60,9 @@ class COMPOSITOR_EXPORT LayerAnimationDelegate {
virtual cc::Layer* GetCcLayer() const = 0;
virtual LayerAnimatorCollection* GetLayerAnimatorCollection() = 0;
virtual LayerThreadedAnimationDelegate* GetThreadedAnimationDelegate() = 0;
- // Returns base::nullopt if the frame number is not available, e.g. when
+ // Returns absl::nullopt if the frame number is not available, e.g. when
// Layer is not attached to a Compositor. Otherwise, returns the frame number.
- virtual base::Optional<int> GetFrameNumber() const = 0;
+ virtual absl::optional<int> GetFrameNumber() const = 0;
virtual float GetRefreshRate() const = 0;
protected:
diff --git a/chromium/ui/compositor/layer_animator.h b/chromium/ui/compositor/layer_animator.h
index 80020984c1d..a778d010378 100644
--- a/chromium/ui/compositor/layer_animator.h
+++ b/chromium/ui/compositor/layer_animator.h
@@ -378,7 +378,7 @@ class COMPOSITOR_EXPORT LayerAnimator : public base::RefCounted<LayerAnimator>,
base::TimeTicks animation_start_time,
std::unique_ptr<gfx::AnimationCurve> curve) override {}
void NotifyLocalTimeUpdated(
- base::Optional<base::TimeDelta> local_time) override {}
+ absl::optional<base::TimeDelta> local_time) override {}
// Implementation of LayerThreadedAnimationDelegate.
void AddThreadedAnimation(
diff --git a/chromium/ui/compositor/layer_owner.cc b/chromium/ui/compositor/layer_owner.cc
index 3eaf415111b..818281e2779 100644
--- a/chromium/ui/compositor/layer_owner.cc
+++ b/chromium/ui/compositor/layer_owner.cc
@@ -4,6 +4,13 @@
#include "ui/compositor/layer_owner.h"
+// layer_owner.h is a widely included header and its size impacts build
+// time. Try not to raise this limit unless necessary. See
+// https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md
+#pragma clang max_tokens_here 480000
+
+#include "ui/compositor/layer.h"
+
#include <utility>
diff --git a/chromium/ui/compositor/layer_owner.h b/chromium/ui/compositor/layer_owner.h
index f3ea42e7eb8..0277d6103e1 100644
--- a/chromium/ui/compositor/layer_owner.h
+++ b/chromium/ui/compositor/layer_owner.h
@@ -11,10 +11,11 @@
#include "base/macros.h"
#include "base/observer_list.h"
#include "ui/compositor/compositor_export.h"
-#include "ui/compositor/layer.h"
namespace ui {
+class Layer;
+
class COMPOSITOR_EXPORT LayerOwner {
public:
class Observer {
diff --git a/chromium/ui/compositor/layer_unittest.cc b/chromium/ui/compositor/layer_unittest.cc
index fb1e5fd34f4..4169b58ae4c 100644
--- a/chromium/ui/compositor/layer_unittest.cc
+++ b/chromium/ui/compositor/layer_unittest.cc
@@ -64,6 +64,7 @@
#include "ui/gfx/font_list.h"
#include "ui/gfx/interpolated_transform.h"
#include "ui/gfx/skia_util.h"
+#include "ui/gfx/test/gfx_util.h"
using cc::MatchesPNGFile;
using cc::WritePNGFile;
@@ -108,10 +109,9 @@ class ColoredLayer : public Layer, public LayerDelegate {
class LayerWithRealCompositorTest : public testing::TestWithParam<bool> {
public:
LayerWithRealCompositorTest()
- : task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {
- gfx::FontList::SetDefaultFontDescription("Segoe UI, 15px");
- }
- ~LayerWithRealCompositorTest() override {}
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI),
+ default_font_desc_setter_("Segoe UI, 15px") {}
+ ~LayerWithRealCompositorTest() override = default;
// Overridden from testing::Test:
void SetUp() override {
@@ -251,6 +251,8 @@ class LayerWithRealCompositorTest : public testing::TestWithParam<bool> {
// The root directory for test files.
base::FilePath test_data_dir_;
+ gfx::ScopedDefaultFontDescription default_font_desc_setter_;
+
DISALLOW_COPY_AND_ASSIGN(LayerWithRealCompositorTest);
};
@@ -567,11 +569,9 @@ TEST(LayerStandaloneTest, ReleaseMailboxOnDestruction) {
auto resource = viz::TransferableResource::MakeGL(
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
size, false /* is_overlay_candidate */);
- layer->SetTransferableResource(
- resource,
- viz::SingleReleaseCallback::Create(
- base::BindOnce(ReturnMailbox, &callback_run)),
- gfx::Size(10, 10));
+ layer->SetTransferableResource(resource,
+ base::BindOnce(ReturnMailbox, &callback_run),
+ gfx::Size(10, 10));
EXPECT_FALSE(callback_run);
layer.reset();
EXPECT_TRUE(callback_run);
@@ -588,12 +588,14 @@ TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Simple) {
DrawTree(l1.get());
gfx::PointF point1_in_l2_coords(5, 5);
- Layer::ConvertPointToLayer(l2.get(), l1.get(), &point1_in_l2_coords);
+ Layer::ConvertPointToLayer(l2.get(), l1.get(), /*use_target_transform=*/true,
+ &point1_in_l2_coords);
gfx::PointF point1_in_l1_coords(15, 15);
EXPECT_EQ(point1_in_l1_coords, point1_in_l2_coords);
gfx::PointF point2_in_l1_coords(5, 5);
- Layer::ConvertPointToLayer(l1.get(), l2.get(), &point2_in_l1_coords);
+ Layer::ConvertPointToLayer(l1.get(), l2.get(), /*use_target_transform=*/true,
+ &point2_in_l1_coords);
gfx::PointF point2_in_l2_coords(-5, -5);
EXPECT_EQ(point2_in_l2_coords, point2_in_l1_coords);
}
@@ -613,12 +615,14 @@ TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Medium) {
DrawTree(l1.get());
gfx::PointF point1_in_l3_coords(5, 5);
- Layer::ConvertPointToLayer(l3.get(), l1.get(), &point1_in_l3_coords);
+ Layer::ConvertPointToLayer(l3.get(), l1.get(), /*use_target_transform=*/true,
+ &point1_in_l3_coords);
gfx::PointF point1_in_l1_coords(25, 25);
EXPECT_EQ(point1_in_l1_coords, point1_in_l3_coords);
gfx::PointF point2_in_l1_coords(5, 5);
- Layer::ConvertPointToLayer(l1.get(), l3.get(), &point2_in_l1_coords);
+ Layer::ConvertPointToLayer(l1.get(), l3.get(), /*use_target_transform=*/true,
+ &point2_in_l1_coords);
gfx::PointF point2_in_l3_coords(-15, -15);
EXPECT_EQ(point2_in_l3_coords, point2_in_l1_coords);
}
@@ -1050,8 +1054,7 @@ TEST_F(LayerWithNullDelegateTest, SwitchLayerPreservesCCLayerState) {
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
size, false /* is_overlay_candidate */);
l1->SetTransferableResource(resource,
- viz::SingleReleaseCallback::Create(base::BindOnce(
- ReturnMailbox, &callback1_run)),
+ base::BindOnce(ReturnMailbox, &callback1_run),
gfx::Size(10, 10));
EXPECT_NE(before_layer, l1->cc_layer_for_testing());
@@ -1074,8 +1077,7 @@ TEST_F(LayerWithNullDelegateTest, SwitchLayerPreservesCCLayerState) {
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
size, false /* is_overlay_candidate */);
l1->SetTransferableResource(resource,
- viz::SingleReleaseCallback::Create(base::BindOnce(
- ReturnMailbox, &callback2_run)),
+ base::BindOnce(ReturnMailbox, &callback2_run),
gfx::Size(10, 10));
EXPECT_TRUE(callback1_run);
EXPECT_FALSE(callback2_run);
@@ -1100,8 +1102,7 @@ TEST_F(LayerWithNullDelegateTest, SwitchLayerPreservesCCLayerState) {
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
size, false /* is_overlay_candidate */);
l1->SetTransferableResource(resource,
- viz::SingleReleaseCallback::Create(base::BindOnce(
- ReturnMailbox, &callback3_run)),
+ base::BindOnce(ReturnMailbox, &callback3_run),
gfx::Size(10, 10));
EXPECT_NE(before_layer, l1->cc_layer_for_testing());
@@ -1423,9 +1424,8 @@ TEST_F(LayerWithNullDelegateTest, EmptyDamagedRect) {
auto resource = viz::TransferableResource::MakeGL(
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
size, false /* is_overlay_candidate */);
- root->SetTransferableResource(
- resource, viz::SingleReleaseCallback::Create(std::move(callback)),
- gfx::Size(10, 10));
+ root->SetTransferableResource(resource, std::move(callback),
+ gfx::Size(10, 10));
compositor()->SetRootLayer(root.get());
root->SetBounds(gfx::Rect(0, 0, 10, 10));
@@ -2275,7 +2275,7 @@ TEST_F(LayerWithDelegateTest, ExternalContent) {
const auto* surface = static_cast<cc::SurfaceLayer*>(after.get());
EXPECT_TRUE(after.get());
EXPECT_NE(before.get(), after.get());
- EXPECT_EQ(base::nullopt, surface->deadline_in_frames());
+ EXPECT_EQ(absl::nullopt, surface->deadline_in_frames());
allocator.GenerateId();
child->SetShowSurface(
@@ -2326,9 +2326,7 @@ TEST_F(LayerWithDelegateTest, TransferableResourceMirroring) {
bool release_callback_run = false;
layer->SetTransferableResource(
- resource,
- viz::SingleReleaseCallback::Create(
- base::BindOnce(ReturnMailbox, &release_callback_run)),
+ resource, base::BindOnce(ReturnMailbox, &release_callback_run),
gfx::Size(10, 10));
EXPECT_FALSE(release_callback_run);
EXPECT_TRUE(layer->has_external_content());
@@ -2359,9 +2357,7 @@ TEST_F(LayerWithDelegateTest, TransferableResourceMirroring) {
// Setting a transferable resource on the source layer should set it on the
// mirror layers as well.
layer->SetTransferableResource(
- resource,
- viz::SingleReleaseCallback::Create(
- base::BindOnce(ReturnMailbox, &release_callback_run)),
+ resource, base::BindOnce(ReturnMailbox, &release_callback_run),
gfx::Size(10, 10));
EXPECT_FALSE(release_callback_run);
EXPECT_TRUE(layer->has_external_content());
diff --git a/chromium/ui/compositor/overscroll/scroll_input_handler.h b/chromium/ui/compositor/overscroll/scroll_input_handler.h
index 41a28a0d617..d5c750be480 100644
--- a/chromium/ui/compositor/overscroll/scroll_input_handler.h
+++ b/chromium/ui/compositor/overscroll/scroll_input_handler.h
@@ -48,4 +48,4 @@ class COMPOSITOR_EXPORT ScrollInputHandler : public cc::InputHandlerClient {
} // namespace ui
-#endif // UI_COMPOSITOR_OVERSCROLL_UI_INPUT_HANDLER_H_
+#endif // UI_COMPOSITOR_OVERSCROLL_SCROLL_INPUT_HANDLER_H_
diff --git a/chromium/ui/compositor/paint_cache.h b/chromium/ui/compositor/paint_cache.h
index 1863e202d5d..2d2fb14b577 100644
--- a/chromium/ui/compositor/paint_cache.h
+++ b/chromium/ui/compositor/paint_cache.h
@@ -6,7 +6,7 @@
#define UI_COMPOSITOR_PAINT_CACHE_H_
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "ui/compositor/compositor_export.h"
#include "ui/gfx/geometry/rect.h"
diff --git a/chromium/ui/compositor/paint_context.h b/chromium/ui/compositor/paint_context.h
index c2d3dcaa2af..f8b456503c6 100644
--- a/chromium/ui/compositor/paint_context.h
+++ b/chromium/ui/compositor/paint_context.h
@@ -5,7 +5,6 @@
#ifndef UI_COMPOSITOR_PAINT_CONTEXT_H_
#define UI_COMPOSITOR_PAINT_CONTEXT_H_
-#include <memory>
#include "base/check.h"
#include "base/macros.h"
diff --git a/chromium/ui/compositor/paint_recorder.h b/chromium/ui/compositor/paint_recorder.h
index 609d6f0bf42..5aebaa5e7f3 100644
--- a/chromium/ui/compositor/paint_recorder.h
+++ b/chromium/ui/compositor/paint_recorder.h
@@ -5,7 +5,6 @@
#ifndef UI_COMPOSITOR_PAINT_RECORDER_H_
#define UI_COMPOSITOR_PAINT_RECORDER_H_
-#include <memory>
#include "base/macros.h"
#include "cc/paint/display_item_list.h"
diff --git a/chromium/ui/compositor/scoped_animation_duration_scale_mode.h b/chromium/ui/compositor/scoped_animation_duration_scale_mode.h
index 800f0ee1089..1dd45861339 100644
--- a/chromium/ui/compositor/scoped_animation_duration_scale_mode.h
+++ b/chromium/ui/compositor/scoped_animation_duration_scale_mode.h
@@ -43,4 +43,4 @@ class COMPOSITOR_EXPORT ScopedAnimationDurationScaleMode {
} // namespace ui
-#endif // UI_COMPOSITOR_SCOPED_ANIMATION_DURATION_SCALE_MODE_H
+#endif // UI_COMPOSITOR_SCOPED_ANIMATION_DURATION_SCALE_MODE_H_
diff --git a/chromium/ui/compositor/throughput_tracker.cc b/chromium/ui/compositor/throughput_tracker.cc
index 95bcb01cd2a..f0a819d37f8 100644
--- a/chromium/ui/compositor/throughput_tracker.cc
+++ b/chromium/ui/compositor/throughput_tracker.cc
@@ -46,12 +46,14 @@ void ThroughputTracker::Start(ThroughputTrackerHost::ReportCallback callback) {
host_->StartThroughputTracker(id_, std::move(callback));
}
-void ThroughputTracker::Stop() {
+bool ThroughputTracker::Stop() {
DCHECK(started_);
started_ = false;
if (host_)
- host_->StopThroughtputTracker(id_);
+ return host_->StopThroughtputTracker(id_);
+
+ return false;
}
void ThroughputTracker::Cancel() {
diff --git a/chromium/ui/compositor/throughput_tracker.h b/chromium/ui/compositor/throughput_tracker.h
index ae18af42b66..e536423bb82 100644
--- a/chromium/ui/compositor/throughput_tracker.h
+++ b/chromium/ui/compositor/throughput_tracker.h
@@ -35,10 +35,11 @@ class COMPOSITOR_EXPORT ThroughputTracker {
// throughput data collection starts after the next commit.
void Start(ThroughputTrackerHost::ReportCallback callback);
- // Stops tracking. The supplied callback will be invoked when the data
- // collection finishes after the next frame presentation. Note that no data
- // will be reported if Stop() is not called,
- void Stop();
+ // Stops tracking. Returns true when the supplied callback will be invoked
+ // when the data collection finishes. Returns false when the data collection
+ // is finished before Stop() is called, e.g. when gpu process crashes.
+ // Note that no data will be reported if Stop() is not called,
+ bool Stop();
// Cancels tracking. The supplied callback will not be invoked.
void Cancel();
diff --git a/chromium/ui/compositor/throughput_tracker_host.h b/chromium/ui/compositor/throughput_tracker_host.h
index d763516edb3..6c694e00795 100644
--- a/chromium/ui/compositor/throughput_tracker_host.h
+++ b/chromium/ui/compositor/throughput_tracker_host.h
@@ -25,8 +25,9 @@ class COMPOSITOR_EXPORT ThroughputTrackerHost {
virtual void StartThroughputTracker(TrackerId tracker_id,
ReportCallback callback) = 0;
- // Stops the tracking for the given tracker id.
- virtual void StopThroughtputTracker(TrackerId tracker_id) = 0;
+ // Stops the tracking for the given tracker id. Returns true if tracking
+ // is stopped successfully. Otherwise, returns false.
+ virtual bool StopThroughtputTracker(TrackerId tracker_id) = 0;
// Cancels the tracking for the given tracker id.
virtual void CancelThroughtputTracker(TrackerId tracker_id) = 0;
diff --git a/chromium/ui/compositor/total_animation_throughput_reporter.h b/chromium/ui/compositor/total_animation_throughput_reporter.h
index 6edc347a7bc..9d1f5669238 100644
--- a/chromium/ui/compositor/total_animation_throughput_reporter.h
+++ b/chromium/ui/compositor/total_animation_throughput_reporter.h
@@ -5,12 +5,10 @@
#ifndef UI_COMPOSITOR_TOTAL_ANIMATION_THROUGHPUT_REPORTER_H_
#define UI_COMPOSITOR_TOTAL_ANIMATION_THROUGHPUT_REPORTER_H_
-#include <memory>
-
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "cc/metrics/frame_sequence_metrics.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/compositor/compositor_export.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/throughput_tracker.h"
@@ -79,7 +77,7 @@ class COMPOSITOR_EXPORT TotalAnimationThroughputReporter
ReportRepeatingCallback report_repeating_callback_;
ReportOnceCallback report_once_callback_;
bool should_delete_ = false;
- base::Optional<ThroughputTracker> throughput_tracker_;
+ absl::optional<ThroughputTracker> throughput_tracker_;
base::WeakPtrFactory<TotalAnimationThroughputReporter> ptr_factory_{this};
};
diff --git a/chromium/ui/content_accelerators/accelerator_util.cc b/chromium/ui/content_accelerators/accelerator_util.cc
index 223df257be0..d5f2965d56a 100644
--- a/chromium/ui/content_accelerators/accelerator_util.cc
+++ b/chromium/ui/content_accelerators/accelerator_util.cc
@@ -17,11 +17,16 @@ namespace ui {
ui::Accelerator GetAcceleratorFromNativeWebKeyboardEvent(
const content::NativeWebKeyboardEvent& event) {
#if BUILDFLAG(IS_CHROMEOS_ASH)
- if (::features::IsNewShortcutMappingEnabled()) {
+ if (::features::IsNewShortcutMappingEnabled() ||
+ ::features::IsImprovedKeyboardShortcutsEnabled()) {
// TODO: This must be the same as below and it's simpler.
// Cleanup if this change sticks.
auto* os_event = static_cast<ui::KeyEvent*>(event.os_event);
- return ui::Accelerator(*os_event);
+
+ // If there is no |os_event| fall through to the default code path.
+ // This can occur when keys are injected from dev tools.
+ if (os_event)
+ return ui::Accelerator(*os_event);
}
#endif
Accelerator::KeyState key_state =
diff --git a/chromium/ui/display/BUILD.gn b/chromium/ui/display/BUILD.gn
index db0a7cf668b..b0890b9ffcd 100644
--- a/chromium/ui/display/BUILD.gn
+++ b/chromium/ui/display/BUILD.gn
@@ -200,6 +200,7 @@ test("display_unittests") {
"manager/display_manager_utilities_unittest.cc",
"manager/json_converter_unittest.cc",
"manager/managed_display_info_unittest.cc",
+ "mojom/display_list_mojom_traits_unittest.cc",
"mojom/display_mojom_traits_unittest.cc",
"screen_unittest.cc",
"unified_desktop_utils_unittests.cc",
@@ -238,6 +239,7 @@ test("display_unittests") {
"//build:chromeos_buildflags",
"//cc/base",
"//mojo/core/test:run_all_unittests",
+ "//mojo/public/cpp/test_support:test_utils",
"//testing/gmock",
"//testing/gtest",
"//ui/display/fake",
diff --git a/chromium/ui/display/display.h b/chromium/ui/display/display.h
index 16c1c2b9c68..e284c7bf065 100644
--- a/chromium/ui/display/display.h
+++ b/chromium/ui/display/display.h
@@ -8,8 +8,8 @@
#include <stdint.h>
#include "base/compiler_specific.h"
-#include "base/optional.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/display/display_export.h"
#include "ui/display/types/display_constants.h"
#include "ui/gfx/display_color_spaces.h"
@@ -281,7 +281,7 @@ class DISPLAY_EXPORT Display final {
gfx::Rect work_area_;
float device_scale_factor_;
Rotation rotation_ = ROTATE_0;
- base::Optional<Rotation> panel_rotation_;
+ absl::optional<Rotation> panel_rotation_;
TouchSupport touch_support_ = TouchSupport::UNKNOWN;
AccelerometerSupport accelerometer_support_ = AccelerometerSupport::UNKNOWN;
gfx::Size maximum_cursor_size_;
diff --git a/chromium/ui/display/display_change_notifier.cc b/chromium/ui/display/display_change_notifier.cc
index 53880858e23..37035b67841 100644
--- a/chromium/ui/display/display_change_notifier.cc
+++ b/chromium/ui/display/display_change_notifier.cc
@@ -43,16 +43,23 @@ void DisplayChangeNotifier::RemoveObserver(DisplayObserver* obs) {
void DisplayChangeNotifier::NotifyDisplaysChanged(
const std::vector<Display>& old_displays,
const std::vector<Display>& new_displays) {
+ bool did_remove_displays = false;
// Display present in old_displays but not in new_displays has been removed.
auto old_it = old_displays.begin();
for (; old_it != old_displays.end(); ++old_it) {
if (std::find_if(new_displays.begin(), new_displays.end(),
DisplayComparator(*old_it)) == new_displays.end()) {
+ did_remove_displays = true;
for (DisplayObserver& observer : observer_list_)
observer.OnDisplayRemoved(*old_it);
}
}
+ if (did_remove_displays) {
+ for (DisplayObserver& observer : observer_list_)
+ observer.OnDidRemoveDisplays();
+ }
+
// Display present in new_displays but not in old_displays has been added.
// Display present in both might have been modified.
for (auto new_it = new_displays.begin(); new_it != new_displays.end();
diff --git a/chromium/ui/display/display_layout.cc b/chromium/ui/display/display_layout.cc
index e681213346c..898aea81813 100644
--- a/chromium/ui/display/display_layout.cc
+++ b/chromium/ui/display/display_layout.cc
@@ -12,7 +12,6 @@
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "ui/display/display.h"
#include "ui/gfx/geometry/insets.h"
diff --git a/chromium/ui/display/display_list.cc b/chromium/ui/display/display_list.cc
index 8c32cc1e3c3..ad642e1e8f4 100644
--- a/chromium/ui/display/display_list.cc
+++ b/chromium/ui/display/display_list.cc
@@ -4,24 +4,52 @@
#include "ui/display/display_list.h"
+#include "base/containers/flat_set.h"
#include "base/memory/ptr_util.h"
+#include "build/build_config.h"
#include "ui/display/display_observer.h"
namespace display {
-DisplayListObserverLock::~DisplayListObserverLock() {
- display_list_->DecrementObserverSuspendLockCount();
+DisplayList::DisplayList() = default;
+
+DisplayList::~DisplayList() = default;
+
+DisplayList::DisplayList(const Displays& displays,
+ int64_t primary_id,
+ int64_t current_id)
+ : displays_(displays), primary_id_(primary_id), current_id_(current_id) {
+#if defined(OS_FUCHSIA)
+ // TODO(crbug.com/1207996): Resolve ScenicScreen's lack of primary display.
+ if (!displays_.empty() && primary_id_ == kInvalidDisplayId)
+ primary_id_ = displays_[0].id();
+#endif // OS_FUCHSIA
+ DCHECK(observers_.empty());
+ DCHECK(IsValid());
}
-DisplayListObserverLock::DisplayListObserverLock(DisplayList* display_list)
- : display_list_(display_list) {
- display_list_->IncrementObserverSuspendLockCount();
+DisplayList::DisplayList(const DisplayList& other)
+ : displays_(other.displays_),
+ primary_id_(other.primary_id_),
+ current_id_(other.current_id_) {
+ DCHECK(other.observers_.empty());
+ DCHECK(observers_.empty());
+ DCHECK(IsValid());
}
-DisplayList::DisplayList() {}
+DisplayList& DisplayList::operator=(const DisplayList& other) {
+ displays_ = other.displays_;
+ primary_id_ = other.primary_id_;
+ current_id_ = other.current_id_;
+ DCHECK(other.observers_.empty());
+ DCHECK(observers_.empty());
+ DCHECK(IsValid());
+ return *this;
+}
-DisplayList::~DisplayList() {
- DCHECK_EQ(0, observer_suspend_lock_count_);
+bool DisplayList::operator==(const DisplayList& other) const {
+ return displays_ == other.displays_ && primary_id_ == other.primary_id_ &&
+ current_id_ == other.current_id_;
}
void DisplayList::AddObserver(DisplayObserver* observer) {
@@ -34,22 +62,24 @@ void DisplayList::RemoveObserver(DisplayObserver* observer) {
DisplayList::Displays::const_iterator DisplayList::FindDisplayById(
int64_t id) const {
- for (auto iter = displays_.begin(); iter != displays_.end(); ++iter) {
- if (iter->id() == id)
- return iter;
- }
- return displays_.end();
+ return base::ranges::find(displays_, id, &Display::id);
}
DisplayList::Displays::const_iterator DisplayList::GetPrimaryDisplayIterator()
const {
- return primary_display_index_ == -1
- ? displays_.end()
- : displays_.begin() + primary_display_index_;
+ return FindDisplayById(primary_id_);
}
-std::unique_ptr<DisplayListObserverLock> DisplayList::SuspendObserverUpdates() {
- return base::WrapUnique(new DisplayListObserverLock(this));
+const Display& DisplayList::GetPrimaryDisplay() const {
+ Displays::const_iterator primary_iter = GetPrimaryDisplayIterator();
+ CHECK(primary_iter != displays_.end());
+ return *primary_iter;
+}
+
+const Display& DisplayList::GetCurrentDisplay() const {
+ Displays::const_iterator current_iter = FindDisplayById(current_id_);
+ CHECK(current_iter != displays_.end());
+ return *current_iter;
}
void DisplayList::AddOrUpdateDisplay(const Display& display, Type type) {
@@ -69,10 +99,10 @@ uint32_t DisplayList::UpdateDisplay(const Display& display, Type type) {
Display* local_display = &(*iter);
uint32_t changed_values = 0;
- if (type == Type::PRIMARY &&
- static_cast<int>(iter - displays_.begin()) !=
- static_cast<int>(GetPrimaryDisplayIterator() - displays_.begin())) {
- primary_display_index_ = static_cast<int>(iter - displays_.begin());
+ // TODO(crbug.com/1207996): Guard against removal of the primary designation.
+ // DCHECK(type == Type::PRIMARY || local_display->id() != primary_id_);
+ if (type == Type::PRIMARY && local_display->id() != primary_id_) {
+ primary_id_ = local_display->id();
// ash::DisplayManager only notifies for the Display gaining primary, not
// the one losing it.
changed_values |= DisplayObserver::DISPLAY_METRIC_PRIMARY;
@@ -108,68 +138,86 @@ uint32_t DisplayList::UpdateDisplay(const Display& display, Type type) {
if (local_display->GetSizeInPixel() != display.GetSizeInPixel()) {
local_display->set_size_in_pixels(display.GetSizeInPixel());
}
- if (should_notify_observers()) {
- for (DisplayObserver& observer : observers_)
- observer.OnDisplayMetricsChanged(*local_display, changed_values);
- }
+ for (DisplayObserver& observer : observers_)
+ observer.OnDisplayMetricsChanged(*local_display, changed_values);
+ DCHECK(IsValid());
return changed_values;
}
void DisplayList::AddDisplay(const Display& display, Type type) {
- DCHECK(displays_.end() == FindDisplayByIdInternal(display.id()));
+ DCHECK(displays_.end() == FindDisplayById(display.id()));
displays_.push_back(display);
- if (type == Type::PRIMARY)
- primary_display_index_ = static_cast<int>(displays_.size()) - 1;
- if (should_notify_observers()) {
- for (DisplayObserver& observer : observers_)
- observer.OnDisplayAdded(display);
- }
+ // The first display added should always be designated as the primary display.
+ // Displays added later can take on the primary designation as appropriate.
+ if (type == Type::PRIMARY || displays_.size() == 1)
+ primary_id_ = display.id();
+ for (DisplayObserver& observer : observers_)
+ observer.OnDisplayAdded(display);
+ DCHECK(IsValid());
}
void DisplayList::RemoveDisplay(int64_t id) {
auto iter = FindDisplayByIdInternal(id);
DCHECK(displays_.end() != iter);
- if (primary_display_index_ == static_cast<int>(iter - displays_.begin())) {
+ if (id == primary_id_) {
// The primary display can only be removed if it is the last display.
// Users must choose a new primary before removing an old primary display.
DCHECK_EQ(1u, displays_.size());
- primary_display_index_ = -1;
- } else if (primary_display_index_ >
- static_cast<int>(iter - displays_.begin())) {
- primary_display_index_--;
+ primary_id_ = kInvalidDisplayId;
+ }
+ if (id == current_id_) {
+ // The current display can only be removed if it is the last display.
+ // Users must choose a new current before removing an old current display.
+ DCHECK_EQ(1u, displays_.size());
+ current_id_ = kInvalidDisplayId;
}
const Display display = *iter;
displays_.erase(iter);
- if (should_notify_observers()) {
- for (DisplayObserver& observer : observers_)
- observer.OnDisplayRemoved(display);
+ for (DisplayObserver& observer : observers_) {
+ observer.OnDisplayRemoved(display);
+ observer.OnDidRemoveDisplays();
}
+ DCHECK(IsValid());
}
-void DisplayList::IncrementObserverSuspendLockCount() {
- observer_suspend_lock_count_++;
+bool DisplayList::IsValid() const {
+ // The primary and current ids must be invalid when `displays_` is empty.
+ if (displays_.empty())
+ return primary_id_ == kInvalidDisplayId && current_id_ == kInvalidDisplayId;
+
+ // Ensure ids are unique.
+ base::flat_set<int64_t> display_ids;
+ display_ids.reserve(displays_.size());
+ for (const auto& display : displays_) {
+ if (!display_ids.insert(display.id()).second)
+ return false;
+ }
+
+ // The primary id must correspond to a `displays_` entry.
+ if (GetPrimaryDisplayIterator() == displays_.end())
+ return false;
+
+ // The current id may be invalid, or must correspond to a `displays_` entry.
+ if (current_id_ != kInvalidDisplayId &&
+ FindDisplayById(current_id_) == displays_.end()) {
+ return false;
+ }
+
+ return true;
}
-void DisplayList::DecrementObserverSuspendLockCount() {
- DCHECK_GT(observer_suspend_lock_count_, 0);
- observer_suspend_lock_count_--;
+bool DisplayList::IsValidAndHasPrimaryAndCurrentDisplays() const {
+ return IsValid() && GetPrimaryDisplayIterator() != displays_.end() &&
+ FindDisplayById(current_id_) != displays_.end();
}
DisplayList::Type DisplayList::GetTypeByDisplayId(int64_t display_id) const {
- if (primary_display_index_ == -1)
- return Type::NOT_PRIMARY;
- return (displays_[primary_display_index_].id() == display_id
- ? Type::PRIMARY
- : Type::NOT_PRIMARY);
+ return display_id == primary_id_ ? Type::PRIMARY : Type::NOT_PRIMARY;
}
DisplayList::Displays::iterator DisplayList::FindDisplayByIdInternal(
int64_t id) {
- for (auto iter = displays_.begin(); iter != displays_.end(); ++iter) {
- if (iter->id() == id)
- return iter;
- }
- return displays_.end();
+ return base::ranges::find(displays_, id, &Display::id);
}
} // namespace display
diff --git a/chromium/ui/display/display_list.h b/chromium/ui/display/display_list.h
index 295dc3fb57a..73fe1d0601a 100644
--- a/chromium/ui/display/display_list.h
+++ b/chromium/ui/display/display_list.h
@@ -7,7 +7,6 @@
#include <stdint.h>
-#include <memory>
#include <vector>
#include "base/observer_list.h"
@@ -16,25 +15,8 @@
namespace display {
-class Display;
-class DisplayList;
class DisplayObserver;
-// See description in DisplayLock::SuspendObserverUpdates.
-class DISPLAY_EXPORT DisplayListObserverLock {
- public:
- ~DisplayListObserverLock();
-
- private:
- friend class DisplayList;
-
- explicit DisplayListObserverLock(DisplayList* display_list);
-
- DisplayList* display_list_;
-
- DISALLOW_COPY_AND_ASSIGN(DisplayListObserverLock);
-};
-
// Maintains an ordered list of Displays as well as operations to add, remove
// and update said list. Additionally maintains DisplayObservers and updates
// them as appropriate.
@@ -50,19 +32,31 @@ class DISPLAY_EXPORT DisplayList {
DisplayList();
~DisplayList();
+ // WARNING: The copy constructor and assignment operator do not copy nor move
+ // observers; also, the comparison operator does not compare observers.
+ DisplayList(const Displays& displays, int64_t primary_id, int64_t current_id);
+ DisplayList(const DisplayList& other);
+ DisplayList& operator=(const DisplayList& other);
+ bool operator==(const DisplayList& other) const;
+
void AddObserver(DisplayObserver* observer);
void RemoveObserver(DisplayObserver* observer);
const Displays& displays() const { return displays_; }
+ int64_t primary_id() const { return primary_id_; }
+ int64_t current_id() const { return current_id_; }
Displays::const_iterator FindDisplayById(int64_t id) const;
+ // Get an iterator for the primary display. This returns an invalid iterator
+ // if no such display is available. Callers must check the returned value
+ // against `displays().end()` before dereferencing.
Displays::const_iterator GetPrimaryDisplayIterator() const;
- // Internally increments a counter that while non-zero results in observers
- // not being called for any changes to the displays. It is assumed once
- // callers release the last lock they call the observers appropriately.
- std::unique_ptr<DisplayListObserverLock> SuspendObserverUpdates();
+ // Get a reference to the primary or current display. This will CHECK if no
+ // such display is available. Callers must know that the display is available.
+ const Display& GetPrimaryDisplay() const;
+ const Display& GetCurrentDisplay() const;
void AddOrUpdateDisplay(const Display& display, Type type);
@@ -82,28 +76,36 @@ class DISPLAY_EXPORT DisplayList {
// Removes the Display with the specified id.
void RemoveDisplay(int64_t id);
- base::ObserverList<DisplayObserver>* observers() { return &observers_; }
+ // Checks for general struct validity. This permits empty lists, and the
+ // current display may be unspecified, but non-empty lists must specify a
+ // primary display and the displays must not use repeated id values.
+ // TODO(msw): Rename this IsValidOrEmpty().
+ bool IsValid() const;
- private:
- friend class DisplayListObserverLock;
+ // Checks for validity, and for the presence of primary and current displays.
+ // This is a stronger check than IsValid, which allows the list to be empty.
+ bool IsValidAndHasPrimaryAndCurrentDisplays() const;
- bool should_notify_observers() const {
- return observer_suspend_lock_count_ == 0;
- }
- void IncrementObserverSuspendLockCount();
- void DecrementObserverSuspendLockCount();
+ base::ObserverList<DisplayObserver>* observers() { return &observers_; }
+ private:
Type GetTypeByDisplayId(int64_t display_id) const;
Displays::iterator FindDisplayByIdInternal(int64_t id);
+ // The list of displays tracked by the display::Screen or other client.
std::vector<Display> displays_;
- int primary_display_index_ = -1;
+ // The id of the primary Display in `displays_` for the display::Screen.
+ int64_t primary_id_ = kInvalidDisplayId;
+ // The id of the current Display in `displays_`, for some client's context.
+ // This is used when DisplayList needs to track which display a client is on,
+ // typically for a cached DisplayList owned by the client window itself. This
+ // should be kInvalidDisplayId for the DisplayList owned by display::Screen,
+ // which represents the system-wide state and needs to work for all clients.
+ // This member is included in this structure to maintain consistency with some
+ // list of cached displays, perhaps that's not ideal. See crbug.com/1207996.
+ int64_t current_id_ = kInvalidDisplayId;
base::ObserverList<DisplayObserver> observers_;
-
- int observer_suspend_lock_count_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(DisplayList);
};
} // namespace display
diff --git a/chromium/ui/display/display_list_unittest.cc b/chromium/ui/display/display_list_unittest.cc
index bd5e6cbba56..1067c61a09e 100644
--- a/chromium/ui/display/display_list_unittest.cc
+++ b/chromium/ui/display/display_list_unittest.cc
@@ -8,6 +8,7 @@
#include <vector>
#include "base/strings/string_number_conversions.h"
+#include "base/test/gtest_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/display/display.h"
#include "ui/display/display_observer.h"
@@ -92,45 +93,132 @@ TEST(DisplayListTest, AddUpdateRemove) {
ASSERT_EQ(2u, display_list.displays().size());
EXPECT_EQ(2, display_list.displays()[0].id());
EXPECT_EQ(3, display_list.displays()[1].id());
- EXPECT_EQ(2, display_list.GetPrimaryDisplayIterator()->id());
+ EXPECT_EQ(2, display_list.GetPrimaryDisplay().id());
// Make the second the primary.
display_list.UpdateDisplay(display_list.displays()[1],
DisplayList::Type::PRIMARY);
EXPECT_EQ("Changed id=3 primary", observer.GetAndClearChanges());
- EXPECT_EQ(3, display_list.GetPrimaryDisplayIterator()->id());
+ EXPECT_EQ(3, display_list.GetPrimaryDisplay().id());
// Delete the first.
display_list.RemoveDisplay(2);
ASSERT_EQ(1u, display_list.displays().size());
EXPECT_EQ("Removed id=2", observer.GetAndClearChanges());
- EXPECT_EQ(3, display_list.GetPrimaryDisplayIterator()->id());
+ EXPECT_EQ(3, display_list.GetPrimaryDisplay().id());
}
-TEST(DisplayListTest, SuspendUpdates) {
+TEST(DisplayListTest, EmptyIsValid) {
DisplayList display_list;
- display_list.AddDisplay(Display(2, gfx::Rect(0, 0, 801, 802)),
- DisplayList::Type::PRIMARY);
- DisplayObserverImpl observer;
- display_list.AddObserver(&observer);
- {
- // Suspend updates and add a new display.
- std::unique_ptr<DisplayListObserverLock> lock =
- display_list.SuspendObserverUpdates();
- display_list.AddDisplay(Display(3, gfx::Rect(0, 0, 809, 802)),
- DisplayList::Type::NOT_PRIMARY);
- EXPECT_EQ(2u, display_list.displays().size());
- // No update should have been generated.
- EXPECT_TRUE(observer.GetAndClearChanges().empty());
- }
- // The lock has been destroyed, but no updates should be sent yet.
- EXPECT_TRUE(observer.GetAndClearChanges().empty());
-
- // Update a display and verify observer called.
- Display updated_display = display_list.displays()[0];
- updated_display.set_bounds(gfx::Rect(0, 0, 803, 802));
- display_list.UpdateDisplay(updated_display, DisplayList::Type::PRIMARY);
- EXPECT_EQ("Changed id=2 bounds", observer.GetAndClearChanges());
+ EXPECT_TRUE(display_list.IsValid());
+}
+
+TEST(DisplayListTest, FirstDisplayAddedIsForcedToBePrimary) {
+ DisplayList display_list;
+ display_list.AddDisplay(Display(1), DisplayList::Type::NOT_PRIMARY);
+ EXPECT_EQ(1, display_list.primary_id());
+}
+
+TEST(DisplayListTest, SinglePrimaryDisplayNoCurrentIdIsValid) {
+ DisplayList display_list({Display(1)}, /*primary_id=*/1,
+ /*current_id=*/kInvalidDisplayId);
+ EXPECT_TRUE(display_list.IsValid());
+}
+
+TEST(DisplayListTest, SinglePrimaryDisplayWithCurrentIdIsValid) {
+ DisplayList display_list({Display(1)}, /*primary_id=*/1, /*current_id=*/1);
+ EXPECT_TRUE(display_list.IsValid());
+}
+
+TEST(DisplayListTest, PrimaryMustBeInvalidWhenEmpty) {
+ // `primary_id` must be kInvalidDisplayId if `displays` is empty.
+ EXPECT_DCHECK_DEATH(EXPECT_FALSE(
+ DisplayList({}, /*primary_id=*/1, /*current_id=*/kInvalidDisplayId)
+ .IsValid()));
+}
+
+TEST(DisplayListTest, CurrentMustBeInvalidWhenEmpty) {
+ // `primary_id` must be kInvalidDisplayId if `displays` is empty.
+ EXPECT_DCHECK_DEATH(
+ EXPECT_FALSE(DisplayList({}, /*primary_id=*/kInvalidDisplayId,
+ /*current_id=*/1)
+ .IsValid()));
+}
+
+TEST(DisplayListTest, PrimaryIdMustBePresent) {
+ // `primary_id` must match an element of `displays`.
+ EXPECT_DCHECK_DEATH(EXPECT_FALSE(DisplayList({Display(1)}, /*primary_id=*/2,
+ /*current_id=*/1)
+ .IsValid()));
+}
+
+TEST(DisplayListTest, CurrentIdMustBePresent) {
+ // `current_id` must match an element of `displays`.
+ EXPECT_DCHECK_DEATH(EXPECT_FALSE(DisplayList({Display(1)}, /*primary_id=*/1,
+ /*current_id=*/2)
+ .IsValid()));
+}
+
+TEST(DisplayListTest, DisplaysIdsMustBeUnique) {
+ // `displays` must use unique id values.
+ EXPECT_DCHECK_DEATH(EXPECT_FALSE(DisplayList({Display(1), Display(1)},
+ /*primary_id=*/1,
+ /*current_id=*/1)
+ .IsValid()));
+}
+
+TEST(DisplayListTest, IsValidAndHasPrimaryAndCurrentDisplaysEmpty) {
+ EXPECT_FALSE(DisplayList().IsValidAndHasPrimaryAndCurrentDisplays());
+}
+
+TEST(DisplayListTest, IsValidAndHasPrimaryAndCurrentDisplaysNoCurrent) {
+ EXPECT_FALSE(DisplayList({Display(1)}, /*primary_id=*/1,
+ /*current_id=*/kInvalidDisplayId)
+ .IsValidAndHasPrimaryAndCurrentDisplays());
+}
+
+TEST(DisplayListTest, IsValidAndHasPrimaryAndCurrentDisplaysOk) {
+ EXPECT_TRUE(DisplayList({Display(1)}, /*primary_id=*/1, /*current_id=*/1)
+ .IsValidAndHasPrimaryAndCurrentDisplays());
+}
+
+TEST(DisplayListTest, GetPrimaryDisplayEmpty) {
+ DisplayList display_list;
+ EXPECT_EQ(display_list.displays().end(),
+ display_list.FindDisplayById(display_list.primary_id()));
+ EXPECT_DEATH_IF_SUPPORTED(EXPECT_NE(1, display_list.GetPrimaryDisplay().id()),
+ "");
+}
+
+TEST(DisplayListTest, GetPrimaryDisplayOk) {
+ DisplayList display_list({Display(1)}, /*primary_id=*/1, /*current_id=*/1);
+ EXPECT_NE(display_list.displays().end(),
+ display_list.FindDisplayById(display_list.primary_id()));
+ EXPECT_EQ(1, display_list.GetPrimaryDisplay().id());
+}
+
+TEST(DisplayListTest, GetCurrentDisplayEmpty) {
+ DisplayList display_list;
+ EXPECT_EQ(display_list.displays().end(),
+ display_list.FindDisplayById(display_list.current_id()));
+ EXPECT_DEATH_IF_SUPPORTED(EXPECT_NE(1, display_list.GetCurrentDisplay().id()),
+ "");
+}
+
+TEST(DisplayListTest, GetCurrentDisplayUnset) {
+ DisplayList display_list({Display(1)}, /*primary_id=*/1,
+ /*current_id=*/kInvalidDisplayId);
+ EXPECT_EQ(display_list.displays().end(),
+ display_list.FindDisplayById(display_list.current_id()));
+ EXPECT_DEATH_IF_SUPPORTED(EXPECT_NE(1, display_list.GetCurrentDisplay().id()),
+ "");
+}
+
+TEST(DisplayListTest, GetCurrentDisplayOk) {
+ DisplayList display_list({Display(1)}, /*primary_id=*/1, /*current_id=*/1);
+ EXPECT_NE(display_list.displays().end(),
+ display_list.FindDisplayById(display_list.current_id()));
+ EXPECT_EQ(1, display_list.GetCurrentDisplay().id());
}
} // namespace
diff --git a/chromium/ui/display/display_observer.cc b/chromium/ui/display/display_observer.cc
index 5c2802278d5..5b6d8874fd6 100644
--- a/chromium/ui/display/display_observer.cc
+++ b/chromium/ui/display/display_observer.cc
@@ -18,6 +18,8 @@ void DisplayObserver::OnDisplayAdded(const Display& new_display) {}
void DisplayObserver::OnDisplayRemoved(const Display& old_display) {}
+void DisplayObserver::OnDidRemoveDisplays() {}
+
void DisplayObserver::OnDisplayMetricsChanged(const Display& display,
uint32_t changed_metrics) {}
diff --git a/chromium/ui/display/display_observer.h b/chromium/ui/display/display_observer.h
index 8f06a745f13..673439307e2 100644
--- a/chromium/ui/display/display_observer.h
+++ b/chromium/ui/display/display_observer.h
@@ -42,8 +42,15 @@ class DISPLAY_EXPORT DisplayObserver : public base::CheckedObserver {
virtual void OnDisplayAdded(const Display& new_display);
// Called when |old_display| has been removed.
+ // In Ash, this is called *before* the display has been removed.
+ // Everywhere else, this is called *after* the display has been removed.
virtual void OnDisplayRemoved(const Display& old_display);
+ // Called *after* any displays have been removed. Not called per display.
+ // TODO(enne): resolve the Ash inconsistency for OnDisplayRemoved and
+ // remove this function.
+ virtual void OnDidRemoveDisplays();
+
// Called when the metrics of a display change.
// |changed_metrics| is a bitmask of DisplayMatric types indicating which
// metrics have changed. Eg; if mirroring changes (either from true to false,
diff --git a/chromium/ui/display/fake/fake_display_delegate.cc b/chromium/ui/display/fake/fake_display_delegate.cc
index 2932ce31fd9..f941343b8e2 100644
--- a/chromium/ui/display/fake/fake_display_delegate.cc
+++ b/chromium/ui/display/fake/fake_display_delegate.cc
@@ -12,7 +12,6 @@
#include "base/hash/hash.h"
#include "base/logging.h"
#include "base/strings/string_split.h"
-#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "ui/display/display.h"
#include "ui/display/display_switches.h"
diff --git a/chromium/ui/display/fake/fake_display_snapshot.cc b/chromium/ui/display/fake/fake_display_snapshot.cc
index f91f4baea51..f795f8d2eee 100644
--- a/chromium/ui/display/fake/fake_display_snapshot.cc
+++ b/chromium/ui/display/fake/fake_display_snapshot.cc
@@ -13,6 +13,7 @@
#include "base/logging.h"
#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "third_party/re2/src/re2/re2.h"
@@ -373,7 +374,7 @@ std::unique_ptr<DisplaySnapshot> FakeDisplaySnapshot::CreateFromSpec(
// Leftovers should be just the native mode at this point.
std::unique_ptr<DisplayMode> native_mode =
- ParseDisplayMode(leftover.as_string());
+ ParseDisplayMode(std::string(leftover));
// Fail without valid native mode.
if (!native_mode)
diff --git a/chromium/ui/display/mac/display_link_mac.h b/chromium/ui/display/mac/display_link_mac.h
index 3db8d3cbfb6..42a601dde32 100644
--- a/chromium/ui/display/mac/display_link_mac.h
+++ b/chromium/ui/display/mac/display_link_mac.h
@@ -7,7 +7,6 @@
#include <QuartzCore/CVDisplayLink.h>
-#include <map>
#include "base/mac/scoped_typeref.h"
#include "base/memory/ref_counted.h"
diff --git a/chromium/ui/display/mac/screen_mac.mm b/chromium/ui/display/mac/screen_mac.mm
index 00415aac8b8..4d4ed7e8e5f 100644
--- a/chromium/ui/display/mac/screen_mac.mm
+++ b/chromium/ui/display/mac/screen_mac.mm
@@ -58,8 +58,8 @@ Display BuildDisplayForScreen(NSScreen* screen) {
TRACE_EVENT0("ui", "BuildDisplayForScreen");
NSRect frame = [screen frame];
- CGDirectDisplayID display_id = [[[screen deviceDescription]
- objectForKey:@"NSScreenNumber"] unsignedIntValue];
+ CGDirectDisplayID display_id =
+ [[screen deviceDescription][@"NSScreenNumber"] unsignedIntValue];
Display display(display_id, gfx::Rect(NSRectToCGRect(frame)));
NSRect visible_frame = [screen visibleFrame];
@@ -175,8 +175,8 @@ std::vector<Display> BuildDisplaysFromQuartz() {
ScreenIdsToScreensMap screen_ids_to_screens;
for (NSScreen* screen in [NSScreen screens]) {
NSDictionary* screen_device_description = [screen deviceDescription];
- int64_t screen_id = [[screen_device_description
- objectForKey:@"NSScreenNumber"] unsignedIntValue];
+ int64_t screen_id =
+ [screen_device_description[@"NSScreenNumber"] unsignedIntValue];
screen_ids_to_screens[screen_id] = screen;
}
@@ -328,7 +328,7 @@ class ScreenMac : public Screen {
return GetPrimaryDisplay();
NSPoint ns_point = NSPointFromCGPoint(point.ToCGPoint());
- NSScreen* primary = [screens objectAtIndex:0];
+ NSScreen* primary = screens[0];
ns_point.y = NSMaxY([primary frame]) - ns_point.y;
for (NSScreen* screen in screens) {
if (NSMouseInRect(ns_point, [screen frame], NO))
@@ -379,8 +379,8 @@ class ScreenMac : public Screen {
private:
Display GetCachedDisplayForScreen(NSScreen* screen) const {
- const CGDirectDisplayID display_id = [[[screen deviceDescription]
- objectForKey:@"NSScreenNumber"] unsignedIntValue];
+ const CGDirectDisplayID display_id =
+ [[screen deviceDescription][@"NSScreenNumber"] unsignedIntValue];
for (const Display& display : displays_) {
if (display_id == display.id())
return display;
diff --git a/chromium/ui/display/manager/content_protection_manager.cc b/chromium/ui/display/manager/content_protection_manager.cc
index 4b3bda1ad4b..2e89d92cd2f 100644
--- a/chromium/ui/display/manager/content_protection_manager.cc
+++ b/chromium/ui/display/manager/content_protection_manager.cc
@@ -38,7 +38,7 @@ ContentProtectionManager::~ContentProtectionManager() {
ContentProtectionManager::ClientId ContentProtectionManager::RegisterClient() {
if (disabled())
- return base::nullopt;
+ return absl::nullopt;
ClientId client_id = next_client_id_++;
bool success = requests_.emplace(*client_id, ContentProtections()).second;
@@ -58,7 +58,7 @@ void ContentProtectionManager::UnregisterClient(ClientId client_id) {
layout_manager_, native_display_delegate_, AggregateContentProtections(),
base::BindOnce(&ContentProtectionManager::OnContentProtectionApplied,
weak_ptr_factory_.GetWeakPtr(),
- ApplyContentProtectionCallback(), base::nullopt)));
+ ApplyContentProtectionCallback(), absl::nullopt)));
ToggleDisplaySecurityPolling();
}
diff --git a/chromium/ui/display/manager/content_protection_manager.h b/chromium/ui/display/manager/content_protection_manager.h
index 549319f94c1..7dddabfc458 100644
--- a/chromium/ui/display/manager/content_protection_manager.h
+++ b/chromium/ui/display/manager/content_protection_manager.h
@@ -14,8 +14,8 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/timer/timer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/display/manager/display_configurator.h"
#include "ui/display/manager/display_manager_export.h"
@@ -76,7 +76,7 @@ class DISPLAY_MANAGER_EXPORT ContentProtectionManager
native_display_delegate_ = delegate;
}
- using ClientId = base::Optional<uint64_t>;
+ using ClientId = absl::optional<uint64_t>;
// On display reconfiguration, pending requests are cancelled, i.e. clients
// receive failure callbacks, and are responsible for renewing requests. If a
diff --git a/chromium/ui/display/manager/display_change_observer.cc b/chromium/ui/display/manager/display_change_observer.cc
index 059ed70eabe..311cfe9e4f8 100644
--- a/chromium/ui/display/manager/display_change_observer.cc
+++ b/chromium/ui/display/manager/display_change_observer.cc
@@ -424,11 +424,14 @@ float DisplayChangeObserver::FindDeviceScaleFactor(
constexpr gfx::Size k225DisplaySizeHackNocturne(3000, 2000);
// Keep the Chell's scale factor 2.252 until we make decision.
constexpr gfx::Size k2DisplaySizeHackChell(3200, 1800);
+ constexpr gfx::Size k18DisplaySizeHackCoachZ(2160, 1440);
if (size_in_pixels == k225DisplaySizeHackNocturne) {
return kDsf_2_252;
} else if (size_in_pixels == k2DisplaySizeHackChell) {
return 2.f;
+ } else if (size_in_pixels == k18DisplaySizeHackCoachZ) {
+ return kDsf_1_8;
} else {
for (size_t i = 0; i < base::size(kThresholdTableForInternal); ++i) {
if (dpi >= kThresholdTableForInternal[i].dpi)
diff --git a/chromium/ui/display/manager/display_change_observer.h b/chromium/ui/display/manager/display_change_observer.h
index 33909247ef5..7d5795c36d0 100644
--- a/chromium/ui/display/manager/display_change_observer.h
+++ b/chromium/ui/display/manager/display_change_observer.h
@@ -7,8 +7,6 @@
#include <stdint.h>
-#include <memory>
-#include <vector>
#include "base/macros.h"
#include "ui/display/manager/display_configurator.h"
diff --git a/chromium/ui/display/manager/display_change_observer_unittest.cc b/chromium/ui/display/manager/display_change_observer_unittest.cc
index 04b41e627ed..7745c32f540 100644
--- a/chromium/ui/display/manager/display_change_observer_unittest.cc
+++ b/chromium/ui/display/manager/display_change_observer_unittest.cc
@@ -5,7 +5,9 @@
#include "ui/display/manager/display_change_observer.h"
#include <cmath>
+#include <set>
#include <string>
+#include <tuple>
#include "base/strings/stringprintf.h"
#include "base/test/scoped_feature_list.h"
@@ -235,10 +237,19 @@ TEST_P(DisplayChangeObserverTest, FindDeviceScaleFactor) {
EXPECT_EQ(kDsf_2_666,
DisplayChangeObserver::FindDeviceScaleFactor(310, gfx::Size()));
+ std::set<std::tuple<float, int, int>> dup_check;
+
for (auto& entry : display_configs) {
+ std::tuple<float, int, int> key{entry.diagonal_size,
+ entry.resolution.width(),
+ entry.resolution.height()};
+ DCHECK(!dup_check.count(key));
+ dup_check.emplace(key);
+
SCOPED_TRACE(base::StringPrintf(
"%dx%d, diag=%1.3f inch, expected=%1.10f", entry.resolution.width(),
entry.resolution.height(), entry.diagonal_size, entry.expected_dsf));
+
float dpi = ComputeDpi(entry.diagonal_size, entry.resolution);
// Check ScaleFactor.
float scale_factor = ComputeDeviceScaleFactor(dpi, entry.resolution);
@@ -496,19 +507,23 @@ TEST_F(DisplayResolutionTest, CheckEffectiveResoutionUMAIndex) {
const float dsf = display_config.expected_dsf;
std::array<float, kNumOfZoomFactors> zoom_levels;
-
+ bool found = false;
if (dsf == 1.f) {
for (const ZoomListBucket& zoom_list_bucket : kZoomListBuckets) {
- if (size.width() >= zoom_list_bucket.first)
+ if (size.width() >= zoom_list_bucket.first) {
zoom_levels = zoom_list_bucket.second;
+ found = true;
+ }
}
} else {
for (const ZoomListBucketDsf& zoom_list_bucket : kZoomListBucketsForDsf) {
- if (cc::MathUtil::IsWithinEpsilon(dsf, zoom_list_bucket.first))
+ if (cc::MathUtil::IsWithinEpsilon(dsf, zoom_list_bucket.first)) {
zoom_levels = zoom_list_bucket.second;
+ found = true;
+ }
}
}
-
+ EXPECT_TRUE(found);
for (float zoom_level : zoom_levels) {
float effective_scale = 1.f / (zoom_level * dsf);
gfx::SizeF effective_resolution_f(size);
@@ -539,10 +554,20 @@ TEST_F(DisplayResolutionTest, CheckEffectiveResoutionUMAIndex) {
}
}
- // With the current set of display configs and zoom levels, there are only 288
+#if 0
+ // Enable this code to re-generate the "EffectiveResolution" in enums.xml.
+ for (auto pair : effective_resolutions) {
+ LOG(ERROR) << "<int value=\"" << pair.first << "\" label=\""
+ << pair.second.width() << " x " << pair.second.height()
+ << "\"/>";
+ }
+#endif
+
+ // With the current set of display configs and zoom levels, there are only 314
// possible effective resolutions for internal displays in chromebooks. Update
- // this value when adding a new display config.
- EXPECT_EQ(effective_resolutions.size(), 288ul);
+ // this value when adding a new display config, and re-generate the
+ // EffectiveResolution value in enum.xml.
+ EXPECT_EQ(effective_resolutions.size(), 322ul);
}
#endif
diff --git a/chromium/ui/display/manager/display_configurator.h b/chromium/ui/display/manager/display_configurator.h
index fcf74a0b186..27a3bedff56 100644
--- a/chromium/ui/display/manager/display_configurator.h
+++ b/chromium/ui/display/manager/display_configurator.h
@@ -13,8 +13,8 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/timer/timer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/display/manager/display_manager_export.h"
#include "ui/display/types/display_constants.h"
@@ -274,10 +274,10 @@ class DISPLAY_MANAGER_EXPORT DisplayConfigurator
chromeos::DisplayPowerState GetRequestedPowerState() const;
void reset_requested_power_state_for_test() {
- requested_power_state_ = base::nullopt;
+ requested_power_state_ = absl::nullopt;
}
- base::Optional<chromeos::DisplayPowerState> GetRequestedPowerStateForTest()
+ absl::optional<chromeos::DisplayPowerState> GetRequestedPowerStateForTest()
const {
return requested_power_state_;
}
@@ -378,7 +378,7 @@ class DISPLAY_MANAGER_EXPORT DisplayConfigurator
MultipleDisplayState requested_display_state_;
// Stores the requested power state.
- base::Optional<chromeos::DisplayPowerState> requested_power_state_;
+ absl::optional<chromeos::DisplayPowerState> requested_power_state_;
// The power state used by RunPendingConfiguration(). May be
// |requested_power_state_| or DISPLAY_POWER_ALL_OFF for suspend.
diff --git a/chromium/ui/display/manager/display_manager.cc b/chromium/ui/display/manager/display_manager.cc
index 9b6c151b30b..29720df9ebd 100644
--- a/chromium/ui/display/manager/display_manager.cc
+++ b/chromium/ui/display/manager/display_manager.cc
@@ -1067,6 +1067,14 @@ void DisplayManager::UpdateDisplaysWith(
active_display_list_.resize(active_display_list_size);
is_updating_display_list_ = false;
+ // OnDidRemoveDisplays is called after the displays have been removed,
+ // in comparison to NotifyDisplayRemoved/OnDisplayRemoved which on Ash
+ // is called before.
+ if (!removed_displays.empty()) {
+ for (auto& observer : observers_)
+ observer.OnDidRemoveDisplays();
+ }
+
UpdatePrimaryDisplayIdIfNecessary();
bool notify_primary_change =
@@ -1352,7 +1360,7 @@ bool DisplayManager::ShouldSetMirrorModeOn(
void DisplayManager::SetMirrorMode(
MirrorMode mode,
- const base::Optional<MixedMirrorModeParams>& mixed_params) {
+ const absl::optional<MixedMirrorModeParams>& mixed_params) {
if (num_connected_displays() < 2)
return;
@@ -1363,10 +1371,10 @@ void DisplayManager::SetMirrorMode(
// 2. Restore the mixed mirror mode when display configuration changes.
mixed_mirror_mode_params_ = mixed_params;
} else {
- DCHECK(mixed_params == base::nullopt);
+ DCHECK(mixed_params == absl::nullopt);
// Clear mixed mirror mode parameters here to avoid restoring the mode after
// display configuration changes.
- mixed_mirror_mode_params_ = base::nullopt;
+ mixed_mirror_mode_params_ = absl::nullopt;
}
const bool enabled = mode != MirrorMode::kOff;
@@ -1431,20 +1439,6 @@ void DisplayManager::AddRemoveDisplay(
UpdateDisplaysWith(new_display_info_list);
}
-void DisplayManager::ToggleDisplayScaleFactor() {
- DCHECK(!active_display_list_.empty());
- DisplayInfoList new_display_info_list;
- for (Displays::const_iterator iter = active_display_list_.begin();
- iter != active_display_list_.end(); ++iter) {
- ManagedDisplayInfo display_info = GetDisplayInfo(iter->id());
- display_info.set_device_scale_factor(
- display_info.device_scale_factor() == 1.0f ? 2.0f : 1.0f);
- new_display_info_list.push_back(display_info);
- }
- AddMirrorDisplayInfoIfAny(&new_display_info_list);
- UpdateDisplaysWith(new_display_info_list);
-}
-
#if BUILDFLAG(IS_CHROMEOS_ASH)
void DisplayManager::InitConfigurator(
std::unique_ptr<NativeDisplayDelegate> delegate) {
@@ -1546,7 +1540,7 @@ void DisplayManager::SetTouchCalibrationData(
void DisplayManager::ClearTouchCalibrationData(
int64_t display_id,
- base::Optional<ui::TouchscreenDevice> touchdevice) {
+ absl::optional<ui::TouchscreenDevice> touchdevice) {
if (touchdevice) {
touch_device_manager_->ClearTouchCalibrationData(*touchdevice, display_id);
} else {
diff --git a/chromium/ui/display/manager/display_manager.h b/chromium/ui/display/manager/display_manager.h
index b072991fb40..8146b4b89b7 100644
--- a/chromium/ui/display/manager/display_manager.h
+++ b/chromium/ui/display/manager/display_manager.h
@@ -36,7 +36,7 @@
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "base/cancelable_callback.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/display/manager/display_configurator.h"
#include "ui/display/manager/touch_device_manager.h"
#endif
@@ -351,7 +351,7 @@ class DISPLAY_MANAGER_EXPORT DisplayManager
should_restore_mirror_mode_from_display_prefs_ = value;
}
- const base::Optional<MixedMirrorModeParams>& mixed_mirror_mode_params()
+ const absl::optional<MixedMirrorModeParams>& mixed_mirror_mode_params()
const {
return mixed_mirror_mode_params_;
}
@@ -360,7 +360,7 @@ class DISPLAY_MANAGER_EXPORT DisplayManager
// mixed mirror mode in the next display configuration. (Use SetMirrorMode()
// to immediately switch to mixed mirror mode.)
void set_mixed_mirror_mode_params(
- const base::Optional<MixedMirrorModeParams> mixed_params) {
+ const absl::optional<MixedMirrorModeParams> mixed_params) {
mixed_mirror_mode_params_ = mixed_params;
}
@@ -428,7 +428,7 @@ class DISPLAY_MANAGER_EXPORT DisplayManager
// the specified destination displays and all other connected displays will be
// extended.
void SetMirrorMode(MirrorMode mode,
- const base::Optional<MixedMirrorModeParams>& mixed_params);
+ const absl::optional<MixedMirrorModeParams>& mixed_params);
// Used to emulate display change when run in a desktop environment instead
// of on a device.
@@ -453,7 +453,7 @@ class DISPLAY_MANAGER_EXPORT DisplayManager
const ui::TouchscreenDevice& touchdevice);
void ClearTouchCalibrationData(
int64_t display_id,
- base::Optional<ui::TouchscreenDevice> touchdevice);
+ absl::optional<ui::TouchscreenDevice> touchdevice);
void UpdateZoomFactor(int64_t display_id, float zoom_factor);
bool HasUnassociatedDisplay() const;
#endif
@@ -684,7 +684,7 @@ class DISPLAY_MANAGER_EXPORT DisplayManager
// Not empty if mixed mirror mode should be turned on (the specified source
// display is mirrored to the specified destination displays). Empty if mixed
// mirror mode is disabled.
- base::Optional<MixedMirrorModeParams> mixed_mirror_mode_params_;
+ absl::optional<MixedMirrorModeParams> mixed_mirror_mode_params_;
// This is incremented whenever a BeginEndNotifier is created and decremented
// when destroyed. BeginEndNotifier uses this to track when it should call
diff --git a/chromium/ui/display/manager/display_util.cc b/chromium/ui/display/manager/display_util.cc
index 23881ec2d10..b2213f8cbc9 100644
--- a/chromium/ui/display/manager/display_util.cc
+++ b/chromium/ui/display/manager/display_util.cc
@@ -12,7 +12,6 @@
#include "base/check_op.h"
#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "build/chromeos_buildflags.h"
#include "ui/display/manager/managed_display_info.h"
#include "ui/display/types/display_snapshot.h"
diff --git a/chromium/ui/display/manager/display_util.h b/chromium/ui/display/manager/display_util.h
index 33dc3167b74..3149e484c8a 100644
--- a/chromium/ui/display/manager/display_util.h
+++ b/chromium/ui/display/manager/display_util.h
@@ -59,7 +59,7 @@ std::vector<float> DISPLAY_MANAGER_EXPORT GetDisplayZoomFactorForDsf(float dsf);
// the element it is closest to in the list. It also ensures that it never
// replaces the default zoom value of 1.0 from the list and that the size of the
// list never changes.
-// TODO(malaykeshav): Remove this after a few milestones.
+// TODO(crbug.com/1203004): Remove this after a few milestones.
void DISPLAY_MANAGER_EXPORT InsertDsfIntoList(std::vector<float>* zoom_values,
float dsf);
diff --git a/chromium/ui/display/manager/json_converter.cc b/chromium/ui/display/manager/json_converter.cc
index ae7a3562bd9..22161a96e69 100644
--- a/chromium/ui/display/manager/json_converter.cc
+++ b/chromium/ui/display/manager/json_converter.cc
@@ -28,17 +28,17 @@ const char kDisplayPlacementDisplayIdKey[] = "display_id";
const char kDisplayPlacementParentDisplayIdKey[] = "parent_display_id";
bool AddLegacyValuesFromValue(const base::Value& value, DisplayLayout* layout) {
- const base::DictionaryValue* dict_value = nullptr;
- if (!value.GetAsDictionary(&dict_value))
+ if (!value.is_dict())
return false;
- int offset;
- if (dict_value->GetInteger(kOffsetKey, &offset)) {
+
+ absl::optional<int> optional_offset = value.FindIntKey(kOffsetKey);
+ if (optional_offset) {
DisplayPlacement::Position position;
- std::string position_str;
- if (!dict_value->GetString(kPositionKey, &position_str))
+ const std::string* position_str = value.FindStringKey(kPositionKey);
+ if (!position_str)
return false;
- DisplayPlacement::StringToPosition(position_str, &position);
- layout->placement_list.emplace_back(position, offset);
+ DisplayPlacement::StringToPosition(*position_str, &position);
+ layout->placement_list.emplace_back(position, *optional_offset);
}
return true;
}
@@ -46,92 +46,112 @@ bool AddLegacyValuesFromValue(const base::Value& value, DisplayLayout* layout) {
// Returns true if
// The key is missing - output is left unchanged
// The key matches the type - output is updated to the value.
-template <typename Getter, typename Output>
-bool UpdateFromDict(const base::DictionaryValue* dict_value,
+bool UpdateFromDict(const base::Value& value,
const std::string& field_name,
- Getter getter,
- Output* output) {
- const base::Value* field = nullptr;
- if (!dict_value->Get(field_name, &field)) {
+ bool* output) {
+ const base::Value* field = value.FindKey(field_name);
+ if (!field) {
LOG(WARNING) << "Missing field: " << field_name;
return true;
}
- return (field->*getter)(output);
-}
-
-// No implementation here as specialization is required.
-template <typename Output>
-bool UpdateFromDict(const base::DictionaryValue* dict_value,
- const std::string& field_name,
- Output* output);
+ absl::optional<bool> field_value = field->GetIfBool();
+ if (!field_value)
+ return false;
-template <>
-bool UpdateFromDict(const base::DictionaryValue* dict_value,
- const std::string& field_name,
- bool* output) {
- return UpdateFromDict(dict_value, field_name, &base::Value::GetAsBoolean,
- output);
+ *output = *field_value;
+ return true;
}
-template <>
-bool UpdateFromDict(const base::DictionaryValue* dict_value,
+// Returns true if
+// The key is missing - output is left unchanged
+// The key matches the type - output is updated to the value.
+bool UpdateFromDict(const base::Value& value,
const std::string& field_name,
int* output) {
- return UpdateFromDict(dict_value, field_name, &base::Value::GetAsInteger,
- output);
+ const base::Value* field = value.FindKey(field_name);
+ if (!field) {
+ LOG(WARNING) << "Missing field: " << field_name;
+ return true;
+ }
+
+ absl::optional<int> field_value = field->GetIfInt();
+ if (!field_value)
+ return false;
+
+ *output = *field_value;
+ return true;
}
-template <>
-bool UpdateFromDict(const base::DictionaryValue* dict_value,
+// Returns true if
+// The key is missing - output is left unchanged
+// The key matches the type - output is updated to the value.
+bool UpdateFromDict(const base::Value& value,
const std::string& field_name,
DisplayPlacement::Position* output) {
- bool (base::Value::*getter)(std::string*) const = &base::Value::GetAsString;
- std::string value;
- if (!UpdateFromDict(dict_value, field_name, getter, &value))
+ const base::Value* field = value.FindKey(field_name);
+ if (!field) {
+ LOG(WARNING) << "Missing field: " << field_name;
+ return true;
+ }
+
+ const std::string* field_value = field->GetIfString();
+ if (!field_value)
return false;
- return value.empty() ? true
- : DisplayPlacement::StringToPosition(value, output);
+ return field_value->empty()
+ ? true
+ : DisplayPlacement::StringToPosition(*field_value, output);
}
-template <>
-bool UpdateFromDict(const base::DictionaryValue* dict_value,
+// Returns true if
+// The key is missing - output is left unchanged
+// The key matches the type - output is updated to the value.
+bool UpdateFromDict(const base::Value& value,
const std::string& field_name,
int64_t* output) {
- bool (base::Value::*getter)(std::string*) const = &base::Value::GetAsString;
- std::string value;
- if (!UpdateFromDict(dict_value, field_name, getter, &value))
+ const base::Value* field = value.FindKey(field_name);
+ if (!field) {
+ LOG(WARNING) << "Missing field: " << field_name;
+ return true;
+ }
+
+ const std::string* field_value = field->GetIfString();
+ if (!field_value)
return false;
- return value.empty() ? true : base::StringToInt64(value, output);
+ return field_value->empty() ? true
+ : base::StringToInt64(*field_value, output);
}
-template <>
-bool UpdateFromDict(const base::DictionaryValue* dict_value,
+// Returns true if
+// The key is missing - output is left unchanged
+// The key matches the type - output is updated to the value.
+bool UpdateFromDict(const base::Value& value,
const std::string& field_name,
std::vector<DisplayPlacement>* output) {
- bool (base::Value::*getter)(const base::ListValue**) const =
- &base::Value::GetAsList;
- const base::ListValue* list = nullptr;
- if (!UpdateFromDict(dict_value, field_name, getter, &list))
+ const base::Value* field = value.FindKey(field_name);
+ if (!field) {
+ LOG(WARNING) << "Missing field: " << field_name;
+ return true;
+ }
+
+ if (!field->is_list())
return false;
- if (list == nullptr)
- return true;
+ const base::Value::ConstListView list = field->GetList();
+ output->reserve(list.size());
- output->reserve(list->GetSize());
- for (const auto& list_item : *list) {
- const base::DictionaryValue* item_values = nullptr;
- if (!list_item.GetAsDictionary(&item_values))
+ for (const base::Value& list_item : list) {
+ if (!list_item.is_dict())
return false;
DisplayPlacement item;
- if (!UpdateFromDict(item_values, kOffsetKey, &item.offset) ||
- !UpdateFromDict(item_values, kPositionKey, &item.position) ||
- !UpdateFromDict(item_values, kDisplayPlacementDisplayIdKey,
+ if (!UpdateFromDict(list_item, kOffsetKey, &item.offset) ||
+ !UpdateFromDict(list_item, kPositionKey, &item.position) ||
+ !UpdateFromDict(list_item, kDisplayPlacementDisplayIdKey,
&item.display_id) ||
- !UpdateFromDict(item_values, kDisplayPlacementParentDisplayIdKey,
+ !UpdateFromDict(list_item, kDisplayPlacementParentDisplayIdKey,
&item.parent_display_id)) {
return false;
}
@@ -145,18 +165,15 @@ bool UpdateFromDict(const base::DictionaryValue* dict_value,
bool JsonToDisplayLayout(const base::Value& value, DisplayLayout* layout) {
layout->placement_list.clear();
- const base::DictionaryValue* dict_value = nullptr;
- if (!value.GetAsDictionary(&dict_value))
+ if (!value.is_dict())
return false;
- if (!UpdateFromDict(dict_value, kDefaultUnifiedKey,
- &layout->default_unified) ||
- !UpdateFromDict(dict_value, kPrimaryIdKey, &layout->primary_id)) {
+ if (!UpdateFromDict(value, kDefaultUnifiedKey, &layout->default_unified) ||
+ !UpdateFromDict(value, kPrimaryIdKey, &layout->primary_id)) {
return false;
}
- UpdateFromDict(dict_value, kDisplayPlacementKey, &layout->placement_list);
-
+ UpdateFromDict(value, kDisplayPlacementKey, &layout->placement_list);
if (layout->placement_list.size() != 0u)
return true;
@@ -165,28 +182,27 @@ bool JsonToDisplayLayout(const base::Value& value, DisplayLayout* layout) {
}
bool DisplayLayoutToJson(const DisplayLayout& layout, base::Value* value) {
- base::DictionaryValue* dict_value = nullptr;
- if (!value->GetAsDictionary(&dict_value))
+ if (!value->is_dict())
return false;
- dict_value->SetBoolean(kDefaultUnifiedKey, layout.default_unified);
- dict_value->SetString(kPrimaryIdKey, base::NumberToString(layout.primary_id));
+ value->SetBoolKey(kDefaultUnifiedKey, layout.default_unified);
+ value->SetStringKey(kPrimaryIdKey, base::NumberToString(layout.primary_id));
- std::unique_ptr<base::ListValue> placement_list(new base::ListValue);
+ base::Value::ListStorage placement_list;
for (const auto& placement : layout.placement_list) {
- std::unique_ptr<base::DictionaryValue> placement_value(
- new base::DictionaryValue);
- placement_value->SetString(
+ base::Value placement_value(base::Value::Type::DICTIONARY);
+ placement_value.SetStringKey(
kPositionKey, DisplayPlacement::PositionToString(placement.position));
- placement_value->SetInteger(kOffsetKey, placement.offset);
- placement_value->SetString(kDisplayPlacementDisplayIdKey,
- base::NumberToString(placement.display_id));
- placement_value->SetString(
+ placement_value.SetIntKey(kOffsetKey, placement.offset);
+ placement_value.SetStringKey(kDisplayPlacementDisplayIdKey,
+ base::NumberToString(placement.display_id));
+ placement_value.SetStringKey(
kDisplayPlacementParentDisplayIdKey,
base::NumberToString(placement.parent_display_id));
- placement_list->Append(std::move(placement_value));
+ placement_list.push_back(std::move(placement_value));
}
- dict_value->Set(kDisplayPlacementKey, std::move(placement_list));
+ value->SetKey(kDisplayPlacementKey, base::Value(std::move(placement_list)));
+
return true;
}
diff --git a/chromium/ui/display/manager/query_content_protection_task_unittest.cc b/chromium/ui/display/manager/query_content_protection_task_unittest.cc
index 43c99745113..eb396e2d9d4 100644
--- a/chromium/ui/display/manager/query_content_protection_task_unittest.cc
+++ b/chromium/ui/display/manager/query_content_protection_task_unittest.cc
@@ -11,8 +11,8 @@
#include "base/bind.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/display/fake/fake_display_snapshot.h"
#include "ui/display/manager/display_layout_manager.h"
#include "ui/display/manager/test/action_logger_util.h"
@@ -59,7 +59,7 @@ class QueryContentProtectionTaskTest : public testing::Test {
uint32_t protection_mask;
};
- base::Optional<Response> response_;
+ absl::optional<Response> response_;
private:
DISALLOW_COPY_AND_ASSIGN(QueryContentProtectionTaskTest);
diff --git a/chromium/ui/display/manager/update_display_configuration_task.cc b/chromium/ui/display/manager/update_display_configuration_task.cc
index bfee8b7d58e..f607981885a 100644
--- a/chromium/ui/display/manager/update_display_configuration_task.cc
+++ b/chromium/ui/display/manager/update_display_configuration_task.cc
@@ -4,6 +4,8 @@
#include "ui/display/manager/update_display_configuration_task.h"
+#include <memory>
+
#include "base/bind.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
@@ -95,8 +97,8 @@ void UpdateDisplayConfigurationTask::EnterState(
return;
}
if (!requests.empty()) {
- configure_task_.reset(
- new ConfigureDisplaysTask(delegate_, requests, std::move(callback)));
+ configure_task_ = std::make_unique<ConfigureDisplaysTask>(
+ delegate_, requests, std::move(callback));
configure_task_->Run();
} else {
VLOG(2) << "No displays";
diff --git a/chromium/ui/display/manager/update_display_configuration_task.h b/chromium/ui/display/manager/update_display_configuration_task.h
index 060b6a4e196..6b8f177fb35 100644
--- a/chromium/ui/display/manager/update_display_configuration_task.h
+++ b/chromium/ui/display/manager/update_display_configuration_task.h
@@ -12,8 +12,8 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/display/manager/configure_displays_task.h"
#include "ui/display/manager/display_configurator.h"
#include "ui/display/types/native_display_observer.h"
@@ -109,7 +109,7 @@ class DISPLAY_MANAGER_EXPORT UpdateDisplayConfigurationTask
std::unique_ptr<ConfigureDisplaysTask> configure_task_;
// The timestamp when Run() was called. Null if the task is not running.
- base::Optional<base::TimeTicks> start_timestamp_;
+ absl::optional<base::TimeTicks> start_timestamp_;
base::WeakPtrFactory<UpdateDisplayConfigurationTask> weak_ptr_factory_{this};
diff --git a/chromium/ui/display/mojom/BUILD.gn b/chromium/ui/display/mojom/BUILD.gn
index 5a412b8a29f..b0a0da2bdae 100644
--- a/chromium/ui/display/mojom/BUILD.gn
+++ b/chromium/ui/display/mojom/BUILD.gn
@@ -12,6 +12,7 @@ mojom("mojom") {
"display_configuration_params.mojom",
"display_constants.mojom",
"display_layout.mojom",
+ "display_list.mojom",
"display_mode.mojom",
"display_snapshot.mojom",
"gamma_ramp_rgb_entry.mojom",
@@ -151,6 +152,17 @@ mojom("mojom") {
traits_public_deps = [ "//ui/display" ]
traits_deps = [ "//ui/gfx/geometry" ]
},
+ {
+ types = [
+ {
+ mojom = "display.mojom.DisplayList"
+ cpp = "::display::DisplayList"
+ },
+ ]
+ traits_sources = [ "display_list_mojom_traits.cc" ]
+ traits_headers = [ "display_list_mojom_traits.h" ]
+ traits_public_deps = [ ":shared_mojom_traits" ]
+ },
]
cpp_typemaps += shared_cpp_typemaps
diff --git a/chromium/ui/display/mojom/display_configuration_params_mojom_traits.cc b/chromium/ui/display/mojom/display_configuration_params_mojom_traits.cc
index 8f0cf48b631..20f0e34d9c2 100644
--- a/chromium/ui/display/mojom/display_configuration_params_mojom_traits.cc
+++ b/chromium/ui/display/mojom/display_configuration_params_mojom_traits.cc
@@ -15,7 +15,7 @@ bool StructTraits<display::mojom::DisplayConfigurationParamsDataView,
if (!data.ReadOrigin(&origin))
return false;
- base::Optional<std::unique_ptr<display::DisplayMode>> mode;
+ absl::optional<std::unique_ptr<display::DisplayMode>> mode;
if (!data.ReadMode(&mode))
return false;
diff --git a/chromium/ui/display/mojom/display_configuration_params_mojom_traits.h b/chromium/ui/display/mojom/display_configuration_params_mojom_traits.h
index 736c9e7e002..0f0e758a558 100644
--- a/chromium/ui/display/mojom/display_configuration_params_mojom_traits.h
+++ b/chromium/ui/display/mojom/display_configuration_params_mojom_traits.h
@@ -25,7 +25,7 @@ struct StructTraits<display::mojom::DisplayConfigurationParamsDataView,
return display_configuration_params.origin;
}
- static const base::Optional<std::unique_ptr<display::DisplayMode>>& mode(
+ static const absl::optional<std::unique_ptr<display::DisplayMode>>& mode(
const display::DisplayConfigurationParams& display_configuration_params) {
return display_configuration_params.mode;
}
diff --git a/chromium/ui/display/mojom/display_layout_mojom_traits.h b/chromium/ui/display/mojom/display_layout_mojom_traits.h
index cf161dc4684..cd8f11caf5c 100644
--- a/chromium/ui/display/mojom/display_layout_mojom_traits.h
+++ b/chromium/ui/display/mojom/display_layout_mojom_traits.h
@@ -84,4 +84,4 @@ struct StructTraits<display::mojom::DisplayLayoutDataView,
} // namespace mojo
-#endif // UI_DISPLAY_MOJOM_DISPLAY_MOJOM_TRAITS_H_
+#endif // UI_DISPLAY_MOJOM_DISPLAY_LAYOUT_MOJOM_TRAITS_H_
diff --git a/chromium/ui/display/mojom/display_list.mojom b/chromium/ui/display/mojom/display_list.mojom
new file mode 100644
index 00000000000..953da655a24
--- /dev/null
+++ b/chromium/ui/display/mojom/display_list.mojom
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module display.mojom;
+
+import "ui/display/mojom/display.mojom";
+
+// A vector of Displays and indices of notable entries.
+// Corresponds to display::DisplayList and roughly parallels blink::ScreenInfos.
+// WARNING: This does not convey observers held by display::DisplayList.
+struct DisplayList {
+ // The array of Display objects for the set of relevant displays.
+ array<Display> displays;
+
+ // The id of the primary Display in `displays` for the aggregate Screen.
+ int64 primary_id;
+ // The id of the current Display in `displays` for a context (e.g. a window).
+ int64 current_id;
+}; \ No newline at end of file
diff --git a/chromium/ui/display/mojom/display_list_mojom_traits.cc b/chromium/ui/display/mojom/display_list_mojom_traits.cc
new file mode 100644
index 00000000000..42c18f267b8
--- /dev/null
+++ b/chromium/ui/display/mojom/display_list_mojom_traits.cc
@@ -0,0 +1,21 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/mojom/display_list_mojom_traits.h"
+
+#include "ui/display/mojom/display.mojom.h"
+
+namespace mojo {
+
+// static
+bool StructTraits<display::mojom::DisplayListDataView, display::DisplayList>::
+ Read(display::mojom::DisplayListDataView data, display::DisplayList* out) {
+ std::vector<display::Display> displays;
+ if (!data.ReadDisplays(&displays))
+ return false;
+ *out = display::DisplayList(displays, data.primary_id(), data.current_id());
+ return out->IsValid();
+}
+
+} // namespace mojo
diff --git a/chromium/ui/display/mojom/display_list_mojom_traits.h b/chromium/ui/display/mojom/display_list_mojom_traits.h
new file mode 100644
index 00000000000..a6b480191f3
--- /dev/null
+++ b/chromium/ui/display/mojom/display_list_mojom_traits.h
@@ -0,0 +1,41 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_DISPLAY_MOJOM_DISPLAY_LIST_MOJOM_TRAITS_H_
+#define UI_DISPLAY_MOJOM_DISPLAY_LIST_MOJOM_TRAITS_H_
+
+#include "ui/display/display_list.h"
+#include "ui/display/mojom/display_list.mojom-shared.h"
+
+namespace display {
+class Display;
+} // namespace display
+
+namespace mojo {
+
+template <>
+struct StructTraits<display::mojom::DisplayListDataView, display::DisplayList> {
+ static const std::vector<display::Display>& displays(
+ const display::DisplayList& r) {
+ DCHECK(r.IsValid());
+ return r.displays();
+ }
+
+ static int64_t primary_id(const display::DisplayList& r) {
+ DCHECK(r.IsValid());
+ return r.primary_id();
+ }
+
+ static int64_t current_id(const display::DisplayList& r) {
+ DCHECK(r.IsValid());
+ return r.current_id();
+ }
+
+ static bool Read(display::mojom::DisplayListDataView r,
+ display::DisplayList* out);
+};
+
+} // namespace mojo
+
+#endif // UI_DISPLAY_MOJOM_DISPLAY_LIST_MOJOM_TRAITS_H_
diff --git a/chromium/ui/display/mojom/display_list_mojom_traits_unittest.cc b/chromium/ui/display/mojom/display_list_mojom_traits_unittest.cc
new file mode 100644
index 00000000000..bc59e58c458
--- /dev/null
+++ b/chromium/ui/display/mojom/display_list_mojom_traits_unittest.cc
@@ -0,0 +1,101 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/mojom/display_list_mojom_traits.h"
+
+#include "base/test/gtest_util.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/display/display_list.h"
+#include "ui/display/mojom/display_list.mojom.h"
+
+namespace {
+
+using mojo::test::SerializeAndDeserialize;
+
+TEST(StructTraitsTest, DisplayListRoundtripEmpty) {
+ display::DisplayList i, o;
+ ASSERT_TRUE(SerializeAndDeserialize<display::mojom::DisplayList>(i, o));
+ EXPECT_EQ(i, o);
+}
+
+TEST(StructTraitsTest, DisplayListRoundtripValid) {
+ display::DisplayList i, o;
+ i = display::DisplayList({display::Display(1)}, /*primary_id=*/1,
+ /*current_id=*/1);
+ EXPECT_EQ(i.primary_id(), i.displays()[0].id());
+ EXPECT_EQ(i.current_id(), i.displays()[0].id());
+ ASSERT_TRUE(SerializeAndDeserialize<display::mojom::DisplayList>(i, o));
+ EXPECT_EQ(i, o);
+}
+
+TEST(StructTraitsTest, DisplayListPrimaryMustBeInvalidWhenEmpty) {
+ // `primary_id` must be kInvalidDisplayId if `displays` is empty.
+ display::mojom::DisplayListPtr i = display::mojom::DisplayList::New();
+ display::DisplayList o;
+ i->displays = {};
+ i->primary_id = 1;
+ i->current_id = display::kInvalidDisplayId;
+ EXPECT_DCHECK_DEATH({
+ SerializeAndDeserialize<display::mojom::DisplayList>(i, o);
+ EXPECT_FALSE(o.IsValid());
+ });
+}
+
+TEST(StructTraitsTest, DisplayListCurrentMustBeInvalidWhenEmpty) {
+ // `current_id` must be kInvalidDisplayId if `displays` is empty.
+ display::mojom::DisplayListPtr i = display::mojom::DisplayList::New();
+ display::DisplayList o;
+ i->displays = {};
+ i->primary_id = display::kInvalidDisplayId;
+ i->current_id = 1;
+ EXPECT_DCHECK_DEATH({
+ SerializeAndDeserialize<display::mojom::DisplayList>(i, o);
+ EXPECT_FALSE(o.IsValid());
+ });
+}
+
+TEST(StructTraitsTest, DisplayListPrimaryIdMustBePresent) {
+ // `primary_id` must match an element of `displays`.
+ display::mojom::DisplayListPtr i = display::mojom::DisplayList::New();
+ display::DisplayList o;
+ i->displays = {display::Display(1)};
+ i->primary_id = 2;
+ i->current_id = display::kInvalidDisplayId;
+ EXPECT_NE(i->primary_id, i->displays[0].id());
+ EXPECT_DCHECK_DEATH({
+ SerializeAndDeserialize<display::mojom::DisplayList>(i, o);
+ EXPECT_FALSE(o.IsValid());
+ });
+}
+
+TEST(StructTraitsTest, DisplayListCurrentIdMustBePresent) {
+ // `current_id` must match an element of `displays`.
+ display::mojom::DisplayListPtr i = display::mojom::DisplayList::New();
+ display::DisplayList o;
+ i->displays = {display::Display(1)};
+ i->primary_id = 1;
+ i->current_id = 2;
+ EXPECT_NE(i->current_id, i->displays[0].id());
+ EXPECT_DCHECK_DEATH({
+ SerializeAndDeserialize<display::mojom::DisplayList>(i, o);
+ EXPECT_FALSE(o.IsValid());
+ });
+}
+
+TEST(StructTraitsTest, DisplayListDisplaysIdsMustBeUnique) {
+ // `displays` must use unique id values.
+ display::mojom::DisplayListPtr i = display::mojom::DisplayList::New();
+ display::DisplayList o;
+ i->displays = {display::Display(1), display::Display(1)};
+ i->primary_id = 1;
+ i->current_id = 1;
+ EXPECT_EQ(i->displays[0].id(), i->displays[1].id());
+ EXPECT_DCHECK_DEATH({
+ SerializeAndDeserialize<display::mojom::DisplayList>(i, o);
+ EXPECT_FALSE(o.IsValid());
+ });
+}
+
+} // namespace
diff --git a/chromium/ui/display/mojom/display_snapshot_mojom_traits.h b/chromium/ui/display/mojom/display_snapshot_mojom_traits.h
index 5ae471d6aa5..2dfa2e5cb2e 100644
--- a/chromium/ui/display/mojom/display_snapshot_mojom_traits.h
+++ b/chromium/ui/display/mojom/display_snapshot_mojom_traits.h
@@ -5,7 +5,6 @@
#ifndef UI_DISPLAY_MOJOM_DISPLAY_SNAPSHOT_MOJOM_TRAITS_H_
#define UI_DISPLAY_MOJOM_DISPLAY_SNAPSHOT_MOJOM_TRAITS_H_
-#include "ipc/ipc_message_utils.h"
#include "ui/display/mojom/display_constants_mojom_traits.h"
#include "ui/display/mojom/display_mode_mojom_traits.h"
#include "ui/display/mojom/display_snapshot.mojom.h"
diff --git a/chromium/ui/display/screen.cc b/chromium/ui/display/screen.cc
index 95588119d57..6da99944a75 100644
--- a/chromium/ui/display/screen.cc
+++ b/chromium/ui/display/screen.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/check.h"
+#include "base/containers/contains.h"
#include "base/notreached.h"
#include "base/time/time.h"
#include "ui/display/display.h"
@@ -64,6 +65,17 @@ void Screen::SetDisplayForNewWindows(int64_t display_id) {
display_id_for_new_windows_ = display_id;
}
+DisplayList Screen::GetDisplayListNearestViewWithFallbacks(
+ gfx::NativeView view) const {
+ return GetDisplayListNearestDisplayWithFallbacks(GetDisplayNearestView(view));
+}
+
+DisplayList Screen::GetDisplayListNearestWindowWithFallbacks(
+ gfx::NativeWindow window) const {
+ return GetDisplayListNearestDisplayWithFallbacks(
+ GetDisplayNearestWindow(window));
+}
+
void Screen::SetScreenSaverSuspended(bool suspend) {
NOTIMPLEMENTED_LOG_ONCE();
}
@@ -128,4 +140,34 @@ void Screen::SetScopedDisplayForNewWindows(int64_t display_id) {
scoped_display_id_for_new_windows_ = display_id;
}
+DisplayList Screen::GetDisplayListNearestDisplayWithFallbacks(
+ Display nearest) const {
+ DisplayList display_list;
+ const std::vector<Display>& displays = GetAllDisplays();
+ Display primary = GetPrimaryDisplay();
+ if (displays.empty()) {
+ // The nearest display's metrics are of greater value to clients of this
+ // function than those of the primary display, so prefer to use that Display
+ // object as the fallback, if GetAllDisplays() returned an empty array.
+ if (nearest.id() == kInvalidDisplayId && primary.id() != kInvalidDisplayId)
+ display_list = DisplayList({primary}, primary.id(), primary.id());
+ else
+ display_list = DisplayList({nearest}, nearest.id(), nearest.id());
+ } else {
+ // Use the primary and nearest displays as fallbacks for each other, if the
+ // counterpart exists in `displays`. Otherwise, use `display[0]` for both.
+ int64_t primary_id = primary.id();
+ int64_t nearest_id = nearest.id();
+ const bool has_primary = base::Contains(displays, primary_id, &Display::id);
+ const bool has_nearest = base::Contains(displays, nearest_id, &Display::id);
+ if (!has_primary)
+ primary_id = has_nearest ? nearest_id : displays[0].id();
+ if (!has_nearest)
+ nearest_id = primary_id;
+ display_list = DisplayList(displays, primary_id, nearest_id);
+ }
+ CHECK(display_list.IsValidAndHasPrimaryAndCurrentDisplays());
+ return display_list;
+}
+
} // namespace display
diff --git a/chromium/ui/display/screen.h b/chromium/ui/display/screen.h
index d670bfde658..1f8a0464ddc 100644
--- a/chromium/ui/display/screen.h
+++ b/chromium/ui/display/screen.h
@@ -12,6 +12,7 @@
#include "base/values.h"
#include "ui/display/display.h"
#include "ui/display/display_export.h"
+#include "ui/display/display_list.h"
#include "ui/gfx/gpu_extra_info.h"
#include "ui/gfx/native_widget_types.h"
@@ -102,6 +103,16 @@ class DISPLAY_EXPORT Screen {
// Sets the suggested display to use when creating a new window.
void SetDisplayForNewWindows(int64_t display_id);
+ // Returns a DisplayList with its `current` display set to the display nearest
+ // the specified window or view. These functions perform fallback to ensure
+ // the list is non-empty and has coherent primary and current display ids.
+ // This is useful to cache a sensible multi-display snapshot for clients that
+ // otherwise relied on fallback Displays from Screen::GetDisplayNearestView.
+ DisplayList GetDisplayListNearestViewWithFallbacks(
+ gfx::NativeView view) const;
+ DisplayList GetDisplayListNearestWindowWithFallbacks(
+ gfx::NativeWindow window) const;
+
// Suspends the platform-specific screensaver, if applicable.
virtual void SetScreenSaverSuspended(bool suspend);
@@ -157,6 +168,9 @@ class DISPLAY_EXPORT Screen {
static gfx::NativeWindow GetWindowForView(gfx::NativeView view);
+ // A shared helper for GetDisplayListNearest[Window|View]WithFallbacks().
+ DisplayList GetDisplayListNearestDisplayWithFallbacks(Display nearest) const;
+
int64_t display_id_for_new_windows_;
int64_t scoped_display_id_for_new_windows_ = display::kInvalidDisplayId;
diff --git a/chromium/ui/display/screen_unittest.cc b/chromium/ui/display/screen_unittest.cc
index ac09e4e9f9a..97ff347da55 100644
--- a/chromium/ui/display/screen_unittest.cc
+++ b/chromium/ui/display/screen_unittest.cc
@@ -8,6 +8,7 @@
#include "ui/display/display.h"
#include "ui/display/scoped_display_for_new_windows.h"
#include "ui/display/test/test_screen.h"
+#include "ui/gfx/native_widget_types.h"
namespace display {
@@ -87,4 +88,15 @@ TEST_F(ScreenTest, ScopedDisplayForNewWindows) {
EXPECT_EQ(DEFAULT_DISPLAY_ID, screen->GetDisplayForNewWindows().id());
}
+TEST_F(ScreenTest, GetDisplayListNearestWindowWithFallbacks) {
+ Screen* screen = Screen::GetScreen();
+ DisplayList display_list =
+ screen->GetDisplayListNearestWindowWithFallbacks(gfx::kNullNativeWindow);
+ ASSERT_FALSE(display_list.displays().empty());
+ EXPECT_EQ(screen->GetPrimaryDisplay().id(),
+ display_list.GetPrimaryDisplay().id());
+ EXPECT_EQ(screen->GetPrimaryDisplay().id(),
+ display_list.GetCurrentDisplay().id());
+}
+
} // namespace display
diff --git a/chromium/ui/display/types/display_configuration_params.h b/chromium/ui/display/types/display_configuration_params.h
index 31c44f6281d..0b505044d72 100644
--- a/chromium/ui/display/types/display_configuration_params.h
+++ b/chromium/ui/display/types/display_configuration_params.h
@@ -7,7 +7,7 @@
#include <stdint.h>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/display/types/display_mode.h"
#include "ui/display/types/display_types_export.h"
#include "ui/gfx/geometry/point.h"
@@ -25,7 +25,7 @@ struct DISPLAY_TYPES_EXPORT DisplayConfigurationParams {
int64_t id = 0;
gfx::Point origin = gfx::Point();
- base::Optional<std::unique_ptr<display::DisplayMode>> mode = base::nullopt;
+ absl::optional<std::unique_ptr<display::DisplayMode>> mode = absl::nullopt;
};
} // namespace display
diff --git a/chromium/ui/display/types/display_constants.h b/chromium/ui/display/types/display_constants.h
index ab139363e7d..482e4ced992 100644
--- a/chromium/ui/display/types/display_constants.h
+++ b/chromium/ui/display/types/display_constants.h
@@ -95,10 +95,11 @@ enum PrivacyScreenState {
constexpr float kDsf_1_777 = 1.77777779102325439453125f;
constexpr float kDsf_2_252 = 2.2522523403167724609375f;
constexpr float kDsf_2_666 = 2.6666667461395263671875f;
-
+constexpr float kDsf_1_8 = 1.80000007152557373046875f;
constexpr char kDsfStr_1_777[] = "1.77777779102325439453125";
constexpr char kDsfStr_2_252[] = "2.2522523403167724609375";
constexpr char kDsfStr_2_666[] = "2.6666667461395263671875";
+constexpr char kDsfStr_1_8[] = "1.80000007152557373046875";
// The total number of display zoom factors to enumerate.
constexpr int kNumOfZoomFactors = 9;
@@ -131,11 +132,13 @@ constexpr std::array<ZoomListBucket, 8> kZoomListBuckets{{
// zoom values that includes a zoom level to go to the native resolution of the
// display. Ensure that the list of DSFs are in sync with the list of default
// device scale factors in display_change_observer.cc.
-constexpr std::array<ZoomListBucketDsf, 7> kZoomListBucketsForDsf{{
+constexpr std::array<ZoomListBucketDsf, 8> kZoomListBucketsForDsf{{
{1.25f, {0.7f, 1.f / 1.25f, 0.85f, 0.9f, 0.95f, 1.f, 1.1f, 1.2f, 1.3f}},
{1.6f, {1.f / 1.6f, 0.7f, 0.75f, 0.8f, 0.85f, 0.9f, 1.f, 1.15f, 1.3f}},
{kDsf_1_777,
{1.f / kDsf_1_777, 0.65f, 0.75f, 0.8f, 0.9f, 1.f, 1.1f, 1.2f, 1.3f}},
+ {kDsf_1_8,
+ {1.f / kDsf_1_8, 0.65f, 0.75f, 0.8f, 0.9f, 1.f, 1.1f, 1.2f, 1.3f}},
{2.f, {1.f / 2.f, 0.6f, 0.7f, 0.8f, 0.9f, 1.f, 1.1f, 1.25f, 1.5f}},
{kDsf_2_252,
{1.f / kDsf_2_252, 0.6f, 0.7f, 0.8f, 0.9f, 1.f, 1.15f, 1.3f, 1.5f}},
@@ -149,13 +152,14 @@ constexpr gfx::Size kWXGA_768{1366, 768};
constexpr gfx::Size kWXGA_800{1280, 800};
constexpr gfx::Size kHD_PLUS{1600, 900};
constexpr gfx::Size kFHD{1920, 1080};
+constexpr gfx::Size kSHD{1280, 720};
constexpr gfx::Size kWUXGA{1920, 1200};
// Dru
constexpr gfx::Size kQXGA_P{1536, 2048};
constexpr gfx::Size kQHD{2560, 1440};
// Chell
constexpr gfx::Size kQHD_PLUS{3200, 1800};
-constexpr gfx::Size kUHD{3840, 2160};
+constexpr gfx::Size k4K_UHD{3840, 2160};
// Chromebook special panels
constexpr gfx::Size kLux{2160, 1440};
@@ -180,32 +184,48 @@ constexpr struct Data {
} display_configs[] = {
// clang-format off
// inch, resolution, DSF, size in DP, Bad range, size error
+ {9.7f, kQXGA_P, 2.0f, {768, 1024}, false, kExact},
+ {10.f, kWXGA_800, 1.25f, {1024, 640}, false, kExact},
{10.1f, kWXGA_800, 1.f, kWXGA_800, false, kExact},
- {12.1f, kWXGA_800, 1.f, kWXGA_800, true, kExact},
+ {10.1f, kFHD, 1.6, {1200, 675}, true, kExact},
+ {10.1f, kWUXGA, kDsf_1_777, {1080, 675}, false, kExact},
+ {10.5f, kWUXGA, 1.6f, {1200, 750}, true, kExact},
{11.6f, kWXGA_768, 1.f, kWXGA_768, false, kExact},
- {13.3f, kWXGA_768, 1.f, kWXGA_768, true, kExact},
- {14.f, kWXGA_768, 1.f, kWXGA_768, true, kExact},
- {15.6f, kWXGA_768, 1.f, kWXGA_768, true, kExact},
- {9.7f, kQXGA_P, 2.0f, {768, 1024}, false, kExact},
+ {11.6f, kSHD, 1.f, kSHD, false, kExact},
{11.6f, kFHD, 1.6f, {1200, 675}, false, kExact},
+ {12.f, kFHD, 1.6f, {1200, 675}, false, kExact},
+ {12.1f, kWXGA_800, 1.f, kWXGA_800, true, kExact},
+ {12.2f, kWUXGA, 1.6f, {1200, 750}, false, kExact},
+ {12.2f, kFHD, 1.6f, {1200, 675}, false, kExact},
+ {12.3f, kQHD, 2.f, {1280, 720}, false, kExact},
{13.0f, kFHD, 1.25f, {1536, 864}, true, kExact},
+ {13.1f, k4K_UHD, kDsf_2_666, {1440, 810}, false, kExact},
+ {13.3f, kWXGA_768, 1.f, kWXGA_768, true, kExact},
{13.3f, kFHD, 1.25f, {1536, 864}, true, kExact},
+ {13.3f, k4K_UHD, kDsf_2_666, {1440, 810}, false, kExact},
+ {13.5f, kFHD, 1.25f, {1536, 864}, false, kExact},
+ {14.f, kWXGA_768, 1.f, kWXGA_768, true, kExact},
{14.f, kFHD, 1.25f, {1536, 864}, false, kExact},
- {10.1f, kWUXGA, kDsf_1_777, {1080, 675}, false, kExact},
- {12.2f, kWUXGA, 1.6f, {1200, 750}, false, kExact},
+ {14.f, kWUXGA, 1.25f, {1536, 960}, false, kExact},
+ {14.f, k4K_UHD, kDsf_2_666, {1440, 810}, false, kExact},
+ {15.6f, kWXGA_768, 1.f, kWXGA_768, true, kExact},
{15.6f, kWUXGA, 1.f, kWUXGA, false, kExact},
- {12.3f, kQHD, 2.f, {1280, 720}, false, kExact},
+ {15.6f, kFHD, 1.f, kFHD, false, kExact},
+ {15.6f, k4K_UHD, 2.4f, {1600, 900}, false, kEpsilon},
+ {17.f, kHD_PLUS, 1.f, kHD_PLUS, true, kExact},
+ {17.f, kFHD, 1.0f, {1920, 1080},false, kExact},
+ {17.3f, kFHD, 1.0f, {1920, 1080},false, kExact},
+ {18.51f, kWXGA_768, 1.0f, kWXGA_768, true, kExact},
// Non standard panels
- {11.0f, kLux, 2.f, {1080, 720}, false, kExact},
- {12.02f, kLux, 1.6f, {1350, 900}, true, kExact},
- {13.3f, kQHD_PLUS, 2.f, {1600, 900}, false, kSkip},
- {13.3f, kAkaliQHD, 1.6f, {1410, 940}, false, kExact},
+ {11.0f, kLux, kDsf_1_8, {1200, 800}, false, kExact},
+ {12.f, {1366, 912},1.f, {1366, 912}, false, kExact},
{12.3f, kEveDisplay,2.0f, {1200, 800}, false, kExact},
{12.85f, kLink, 2.0f, {1280, 850}, false, kExact},
{12.3f, kNocturne, kDsf_2_252, {1332, 888}, false, kEpsilon},
- {13.1f, kUHD, kDsf_2_666, {1440, 810}, false, kExact},
- {15.6f, kUHD, 2.4f, {1600, 900}, false, kEpsilon},
+ {13.3f, kQHD_PLUS, 2.f, {1600, 900}, false, kExact},
+ {13.3f, kAkaliQHD, 1.6f, {1410, 940}, false, kExact},
+ {13.6f, kAkaliQHD, 1.6f, {1410, 940}, false, kExact},
// Chromebase
{19.5, kHD_PLUS, 1.f, kHD_PLUS, true, kExact},
diff --git a/chromium/ui/display/types/display_types_export.h b/chromium/ui/display/types/display_types_export.h
index b2ddbd1c627..dde9486c2bd 100644
--- a/chromium/ui/display/types/display_types_export.h
+++ b/chromium/ui/display/types/display_types_export.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_DISPLAY_DISPLAY_TYPES_EXPORT_H_
-#define UI_DISPLAY_DISPLAY_TYPES_EXPORT_H_
+#ifndef UI_DISPLAY_TYPES_DISPLAY_TYPES_EXPORT_H_
+#define UI_DISPLAY_TYPES_DISPLAY_TYPES_EXPORT_H_
// Defines DISPLAY_TYPES_EXPORT so that functionality implemented by the
// DISPLAY_TYPES module can be exported to consumers.
@@ -34,4 +34,4 @@
#endif
-#endif // UI_DISPLAY_DISPLAY_TYPES_EXPORT_H_
+#endif // UI_DISPLAY_TYPES_DISPLAY_TYPES_EXPORT_H_
diff --git a/chromium/ui/display/util/edid_parser.cc b/chromium/ui/display/util/edid_parser.cc
index d1b248b92ed..cf09ef93689 100644
--- a/chromium/ui/display/util/edid_parser.cc
+++ b/chromium/ui/display/util/edid_parser.cc
@@ -463,22 +463,24 @@ void EdidParser::ParseEdid(const std::vector<uint8_t>& edid) {
if (length_of_data_block <= 3)
break;
const uint8_t desired_content_max_luminance = edid[data_offset + 4];
- luminance_ = base::make_optional<Luminance>({});
- luminance_->max = 50.0 * pow(2, desired_content_max_luminance / 32.0);
+ hdr_static_metadata_ =
+ absl::make_optional<gfx::HDRStaticMetadata>({});
+ hdr_static_metadata_->max =
+ 50.0 * pow(2, desired_content_max_luminance / 32.0);
if (length_of_data_block <= 4)
break;
const uint8_t desired_content_max_frame_average_luminance =
edid[data_offset + 5];
- luminance_->max_avg =
+ hdr_static_metadata_->max_avg =
50.0 * pow(2, desired_content_max_frame_average_luminance / 32.0);
if (length_of_data_block <= 5)
break;
const uint8_t desired_content_min_luminance = edid[data_offset + 6];
- luminance_->min = luminance_->max *
- pow(desired_content_min_luminance / 255.0, 2) /
- 100.0;
+ hdr_static_metadata_->min =
+ hdr_static_metadata_->max *
+ pow(desired_content_min_luminance / 255.0, 2) / 100.0;
break;
}
default:
diff --git a/chromium/ui/display/util/edid_parser.h b/chromium/ui/display/util/edid_parser.h
index b8cb1b707e7..3b1b12f6b28 100644
--- a/chromium/ui/display/util/edid_parser.h
+++ b/chromium/ui/display/util/edid_parser.h
@@ -13,12 +13,13 @@
#include "base/compiler_specific.h"
#include "base/containers/flat_set.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/stl_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "ui/display/util/display_util_export.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/hdr_static_metadata.h"
namespace display {
@@ -27,22 +28,6 @@ namespace display {
// a few utility postprocessings.
class DISPLAY_UTIL_EXPORT EdidParser {
public:
- // Reflects CEA 861.G-2018, Sec.7.5.13, "HDR Static Metadata Data Block"
- // A value of 0.0 in any of this fields means that it's not indicated.
- struct Luminance {
- // "Desired Content Max Luminance Data. This is the content’s absolute peak
- // luminance (in cd/m2) (likely only in a small area of the screen) that the
- // display prefers for optimal content rendering."
- double max;
- // "Desired Content Max Frame-average Luminance. This is the content’s max
- // frame-average luminance (in cd/m2) that the display prefers for optimal
- // content rendering."
- double max_avg;
- // "Desired Content Min Luminance. This is the minimum value of the content
- // (in cd/m2) that the display prefers for optimal content rendering."
- double min;
- };
-
explicit EdidParser(const std::vector<uint8_t>& edid_blob);
~EdidParser();
@@ -64,8 +49,8 @@ class DISPLAY_UTIL_EXPORT EdidParser {
supported_color_transfer_ids() const {
return supported_color_transfer_ids_;
}
- const Luminance* luminance() const {
- return base::OptionalOrNullptr(luminance_);
+ const gfx::HDRStaticMetadata* hdr_static_metadata() const {
+ return base::OptionalOrNullptr(hdr_static_metadata_);
}
// Returns a 32-bit identifier for this display |manufacturer_id_| and
// |product_id_|.
@@ -96,14 +81,14 @@ class DISPLAY_UTIL_EXPORT EdidParser {
// Active pixel size from the first detailed timing descriptor in the EDID.
gfx::Size active_pixel_size_;
int32_t year_of_manufacture_;
- base::Optional<bool> overscan_flag_;
+ absl::optional<bool> overscan_flag_;
double gamma_;
int bits_per_channel_;
SkColorSpacePrimaries primaries_;
base::flat_set<gfx::ColorSpace::PrimaryID> supported_color_primary_ids_;
base::flat_set<gfx::ColorSpace::TransferID> supported_color_transfer_ids_;
- base::Optional<Luminance> luminance_;
+ absl::optional<gfx::HDRStaticMetadata> hdr_static_metadata_;
DISALLOW_COPY_AND_ASSIGN(EdidParser);
};
diff --git a/chromium/ui/display/util/edid_parser_unittest.cc b/chromium/ui/display/util/edid_parser_unittest.cc
index 73dda4af53c..1bb431c7999 100644
--- a/chromium/ui/display/util/edid_parser_unittest.cc
+++ b/chromium/ui/display/util/edid_parser_unittest.cc
@@ -256,7 +256,7 @@ struct TestParams {
base::flat_set<gfx::ColorSpace::PrimaryID> supported_color_primary_ids_;
base::flat_set<gfx::ColorSpace::TransferID> supported_color_transfer_ids_;
- base::Optional<EdidParser::Luminance> luminance_;
+ absl::optional<gfx::HDRStaticMetadata> hdr_static_metadata_;
const unsigned char* edid_blob;
size_t edid_blob_length;
@@ -276,7 +276,7 @@ struct TestParams {
"286C",
{},
{},
- base::nullopt,
+ absl::nullopt,
kBadDisplayName,
kBadDisplayNameLength},
{0x22f0u,
@@ -294,7 +294,7 @@ struct TestParams {
"286C",
{},
{},
- base::nullopt,
+ absl::nullopt,
kNormalDisplay,
kNormalDisplayLength},
{0x4ca3u,
@@ -312,7 +312,7 @@ struct TestParams {
"3142",
{},
{},
- base::nullopt,
+ absl::nullopt,
kInternalDisplay,
kInternalDisplayLength},
{0x4c2du,
@@ -330,7 +330,7 @@ struct TestParams {
"08FE",
{},
{},
- base::nullopt,
+ absl::nullopt,
kOverscanDisplay,
kOverscanDisplayLength},
{0x10ACu,
@@ -348,7 +348,7 @@ struct TestParams {
"4064",
{gfx::ColorSpace::PrimaryID::BT709, gfx::ColorSpace::PrimaryID::SMPTE170M},
{},
- base::nullopt,
+ absl::nullopt,
kMisdetectedDisplay,
kMisdetectedDisplayLength},
{0x22f0u,
@@ -366,7 +366,7 @@ struct TestParams {
"2676",
{},
{},
- base::nullopt,
+ absl::nullopt,
kLP2565A,
kLP2565ALength},
{0x22f0u,
@@ -384,7 +384,7 @@ struct TestParams {
"2675",
{},
{},
- base::nullopt,
+ absl::nullopt,
kLP2565B,
kLP2565BLength},
{0x22f0u,
@@ -402,7 +402,7 @@ struct TestParams {
"3275",
{},
{},
- base::nullopt,
+ absl::nullopt,
kHPz32x,
kHPz32xLength},
{0x30E4u,
@@ -420,7 +420,7 @@ struct TestParams {
"042E",
{},
{},
- base::nullopt,
+ absl::nullopt,
kSamus,
kSamusLength},
{0x4D10u,
@@ -438,7 +438,7 @@ struct TestParams {
"148A",
{},
{},
- base::nullopt,
+ absl::nullopt,
kEve,
kEveLength},
{19501u,
@@ -459,7 +459,7 @@ struct TestParams {
{gfx::ColorSpace::TransferID::BT709,
gfx::ColorSpace::TransferID::SMPTEST2084,
gfx::ColorSpace::TransferID::ARIB_STD_B67},
- base::Optional<EdidParser::Luminance>({603.666, 530.095, 0.00454}),
+ absl::make_optional<gfx::HDRStaticMetadata>(603.666, 530.095, 0.00454),
kHDRMetadata,
kHDRMetadataLength},
@@ -479,7 +479,7 @@ struct TestParams {
"0000",
{},
{},
- base::nullopt,
+ absl::nullopt,
nullptr,
0u},
};
@@ -525,13 +525,18 @@ TEST_P(EDIDParserTest, ParseEdids) {
EXPECT_EQ(GetParam().supported_color_transfer_ids_,
parser_.supported_color_transfer_ids());
- const EdidParser::Luminance* luminance = parser_.luminance();
- EXPECT_EQ(GetParam().luminance_.has_value(), luminance != nullptr);
- if (GetParam().luminance_.has_value() && luminance) {
+ const gfx::HDRStaticMetadata* hdr_static_metadata =
+ parser_.hdr_static_metadata();
+ EXPECT_EQ(GetParam().hdr_static_metadata_.has_value(),
+ hdr_static_metadata != nullptr);
+ if (GetParam().hdr_static_metadata_.has_value() && hdr_static_metadata) {
constexpr double epsilon = 0.001;
- EXPECT_NEAR(GetParam().luminance_->max, luminance->max, epsilon);
- EXPECT_NEAR(GetParam().luminance_->max_avg, luminance->max_avg, epsilon);
- EXPECT_NEAR(GetParam().luminance_->min, luminance->min, epsilon);
+ EXPECT_NEAR(GetParam().hdr_static_metadata_->max, hdr_static_metadata->max,
+ epsilon);
+ EXPECT_NEAR(GetParam().hdr_static_metadata_->max_avg,
+ hdr_static_metadata->max_avg, epsilon);
+ EXPECT_NEAR(GetParam().hdr_static_metadata_->min, hdr_static_metadata->min,
+ epsilon);
}
}
diff --git a/chromium/ui/display/win/screen_win.cc b/chromium/ui/display/win/screen_win.cc
index 9fe7bb96703..e173772e8d6 100644
--- a/chromium/ui/display/win/screen_win.cc
+++ b/chromium/ui/display/win/screen_win.cc
@@ -15,10 +15,10 @@
#include "base/metrics/histogram_functions.h"
#include "base/numerics/ranges.h"
#include "base/numerics/safe_conversions.h"
-#include "base/optional.h"
#include "base/trace_event/trace_event.h"
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/display/display.h"
#include "ui/display/display_layout.h"
#include "ui/display/display_layout_builder.h"
@@ -43,9 +43,9 @@ namespace {
ScreenWin* g_instance = nullptr;
// Gets the DPI for a particular monitor.
-base::Optional<int> GetPerMonitorDPI(HMONITOR monitor) {
+absl::optional<int> GetPerMonitorDPI(HMONITOR monitor) {
if (!base::win::IsProcessPerMonitorDpiAware())
- return base::nullopt;
+ return absl::nullopt;
static auto get_dpi_for_monitor_func = []() {
const HMODULE shcore_dll = ::LoadLibrary(L"shcore.dll");
@@ -57,7 +57,7 @@ base::Optional<int> GetPerMonitorDPI(HMONITOR monitor) {
if (!get_dpi_for_monitor_func ||
!SUCCEEDED(
get_dpi_for_monitor_func(monitor, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y)))
- return base::nullopt;
+ return absl::nullopt;
DCHECK_EQ(dpi_x, dpi_y);
return int{dpi_x};
@@ -106,12 +106,12 @@ std::vector<DISPLAYCONFIG_PATH_INFO> GetPathInfos() {
return {};
}
-base::Optional<DISPLAYCONFIG_PATH_INFO> GetPathInfo(HMONITOR monitor) {
+absl::optional<DISPLAYCONFIG_PATH_INFO> GetPathInfo(HMONITOR monitor) {
// Get the monitor name.
MONITORINFOEX monitor_info = {};
monitor_info.cbSize = sizeof(monitor_info);
if (!GetMonitorInfo(monitor, &monitor_info))
- return base::nullopt;
+ return absl::nullopt;
// Look for a path info with a matching name.
std::vector<DISPLAYCONFIG_PATH_INFO> path_infos = GetPathInfos();
@@ -125,10 +125,10 @@ base::Optional<DISPLAYCONFIG_PATH_INFO> GetPathInfo(HMONITOR monitor) {
(wcscmp(monitor_info.szDevice, device_name.viewGdiDeviceName) == 0))
return info;
}
- return base::nullopt;
+ return absl::nullopt;
}
-float GetSDRWhiteLevel(const base::Optional<DISPLAYCONFIG_PATH_INFO>& path) {
+float GetSDRWhiteLevel(const absl::optional<DISPLAYCONFIG_PATH_INFO>& path) {
if (path) {
DISPLAYCONFIG_SDR_WHITE_LEVEL white_level = {};
white_level.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL;
@@ -142,7 +142,7 @@ float GetSDRWhiteLevel(const base::Optional<DISPLAYCONFIG_PATH_INFO>& path) {
}
DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY GetOutputTechnology(
- const base::Optional<DISPLAYCONFIG_PATH_INFO>& path) {
+ const absl::optional<DISPLAYCONFIG_PATH_INFO>& path) {
if (path)
return path->targetInfo.outputTechnology;
return DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER;
@@ -380,7 +380,7 @@ MONITORINFOEX MonitorInfoFromHMONITOR(HMONITOR monitor) {
return monitor_info;
}
-base::Optional<gfx::Vector2dF> GetPixelsPerInchForPointerDevice(
+absl::optional<gfx::Vector2dF> GetPixelsPerInchForPointerDevice(
HANDLE source_device) {
static const auto get_pointer_device_rects =
reinterpret_cast<decltype(&::GetPointerDeviceRects)>(
@@ -388,7 +388,7 @@ base::Optional<gfx::Vector2dF> GetPixelsPerInchForPointerDevice(
RECT device_rect, screen_rect;
if (!get_pointer_device_rects ||
!get_pointer_device_rects(source_device, &device_rect, &screen_rect))
- return base::nullopt;
+ return absl::nullopt;
const gfx::RectF device{gfx::Rect(device_rect)};
const gfx::RectF screen{gfx::Rect(screen_rect)};
@@ -407,7 +407,7 @@ gfx::Vector2dF GetDefaultMonitorPhysicalPixelsPerInch() {
// Retrieves PPI for |monitor| based on touch pointer device handles. Returns
// nullopt if a pointer device for |monitor| can't be found.
-base::Optional<gfx::Vector2dF> GetMonitorPixelsPerInch(HMONITOR monitor) {
+absl::optional<gfx::Vector2dF> GetMonitorPixelsPerInch(HMONITOR monitor) {
static const auto get_pointer_devices =
reinterpret_cast<decltype(&::GetPointerDevices)>(
base::win::GetUser32FunctionPointer("GetPointerDevices"));
@@ -415,18 +415,18 @@ base::Optional<gfx::Vector2dF> GetMonitorPixelsPerInch(HMONITOR monitor) {
if (!get_pointer_devices ||
!get_pointer_devices(&pointer_device_count, nullptr) ||
(pointer_device_count == 0))
- return base::nullopt;
+ return absl::nullopt;
std::vector<POINTER_DEVICE_INFO> pointer_devices(pointer_device_count);
if (!get_pointer_devices(&pointer_device_count, pointer_devices.data()))
- return base::nullopt;
+ return absl::nullopt;
for (const auto& device : pointer_devices) {
if (device.pointerDeviceType == POINTER_DEVICE_TYPE_TOUCH &&
device.monitor == monitor)
return GetPixelsPerInchForPointerDevice(device.device);
}
- return base::nullopt;
+ return absl::nullopt;
}
BOOL CALLBACK EnumMonitorForDisplayInfoCallback(HMONITOR monitor,
diff --git a/chromium/ui/events/BUILD.gn b/chromium/ui/events/BUILD.gn
index 767c19f3432..82b8ba7a5e0 100644
--- a/chromium/ui/events/BUILD.gn
+++ b/chromium/ui/events/BUILD.gn
@@ -158,6 +158,15 @@ component("events_base") {
"//ui/gfx/geometry",
]
+ if (is_fuchsia) {
+ sources += [
+ "keycodes/keyboard_code_conversion_fuchsia.cc",
+ "keycodes/keyboard_code_conversion_fuchsia.h",
+ ]
+
+ deps += [ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.input3" ]
+ }
+
if (use_x11 || ozone_platform_x11) {
public_deps += [ "//ui/events/keycodes:x11" ]
@@ -200,7 +209,6 @@ component("events") {
"events_export.h",
"gestures/gesture_recognizer.h",
"gestures/gesture_types.h",
- "keyboard_hook.h",
"null_event_targeter.h",
"scoped_target_handler.h",
]
@@ -220,8 +228,6 @@ component("events") {
"events_stub.cc",
"gestures/gesture_recognizer.cc",
"gestures/gesture_types.cc",
- "keyboard_hook_base.cc",
- "keyboard_hook_base.h",
"null_event_targeter.cc",
"scoped_target_handler.cc",
]
@@ -229,8 +235,6 @@ component("events") {
if (is_win) {
public += [
"win/events_win_utils.h",
- "win/keyboard_hook_monitor.h",
- "win/keyboard_hook_observer.h",
"win/system_event_state_lookup.h",
]
@@ -239,12 +243,6 @@ component("events") {
"keycodes/platform_key_map_win.h",
"win/events_win.cc",
"win/events_win_utils.cc",
- "win/keyboard_hook_monitor_impl.cc",
- "win/keyboard_hook_monitor_impl.h",
- "win/keyboard_hook_win_base.cc",
- "win/keyboard_hook_win_base.h",
- "win/media_keyboard_hook_win.cc",
- "win/modifier_keyboard_hook_win.cc",
"win/system_event_state_lookup.cc",
]
}
@@ -256,7 +254,6 @@ component("events") {
"cocoa/cocoa_event_utils.mm",
"cocoa/events_mac.mm",
"gestures/gesture_recognizer_impl_mac.cc",
- "mac/keyboard_hook_mac.mm",
]
}
@@ -288,13 +285,6 @@ component("events") {
# template which generates different target names on different platforms.
friend = [ ":*" ]
- if (use_x11) {
- sources += [
- "x/keyboard_hook_x11.cc",
- "x/keyboard_hook_x11.h",
- ]
- }
-
if (use_x11 || ozone_platform_x11) {
public += [ "x/x11_event_translation.h" ]
sources += [ "x/x11_event_translation.cc" ]
@@ -313,12 +303,6 @@ component("events") {
if (use_ozone || use_x11) {
sources += [ "events_default.cc" ]
-
- if (is_linux || is_chromeos) {
- # TODO(https://crbug.com/1099225): refactor X11 kbd hook and implement
- # that for Ozone.
- sources += [ "keyboard_hook_linux.cc" ]
- }
}
if (is_win && use_ozone) {
@@ -326,14 +310,8 @@ component("events") {
}
if (use_ozone) {
- public += [
- "ozone/events_ozone.h",
- "ozone/keyboard_hook_ozone.h",
- ]
- sources += [
- "ozone/events_ozone.cc",
- "ozone/keyboard_hook_ozone.cc",
- ]
+ public += [ "ozone/events_ozone.h" ]
+ sources += [ "ozone/events_ozone.cc" ]
deps += [
"//ui/base:features",
"//ui/events/ozone/layout",
@@ -375,7 +353,6 @@ component("events") {
"android/gesture_event_android.cc",
"android/key_event_android.cc",
"android/key_event_utils.cc",
- "android/keyboard_hook_android.cc",
"android/motion_event_android.cc",
]
deps += [
@@ -398,6 +375,80 @@ component("events") {
}
}
+component("keyboard_hook") {
+ public = [ "keyboard_hook.h" ]
+
+ defines = [ "IS_KEYBOARD_HOOK_IMPL" ]
+
+ sources = [
+ "keyboard_hook_base.cc",
+ "keyboard_hook_base.h",
+ ]
+
+ deps = [
+ "//base",
+ "//ui/events",
+ "//ui/events:dom_keycode_converter",
+ "//ui/gfx",
+ ]
+
+ # Expose the internals of this target to other packages in this BUILD file
+ # so the unit tests can access the private header files.
+ friend = [ ":*" ]
+
+ if (is_win) {
+ public += [
+ "win/keyboard_hook_monitor.h",
+ "win/keyboard_hook_observer.h",
+ ]
+
+ sources += [
+ "win/keyboard_hook_monitor_impl.cc",
+ "win/keyboard_hook_monitor_impl.h",
+ "win/keyboard_hook_win_base.cc",
+ "win/keyboard_hook_win_base.h",
+ "win/media_keyboard_hook_win.cc",
+ "win/modifier_keyboard_hook_win.cc",
+ ]
+ }
+
+ if (is_mac) {
+ sources += [ "mac/keyboard_hook_mac.mm" ]
+ }
+
+ if (use_x11) {
+ sources += [
+ "x/keyboard_hook_x11.cc",
+ "x/keyboard_hook_x11.h",
+ ]
+ deps += [
+ "//ui/base/x",
+ "//ui/gfx/x",
+ ]
+ }
+
+ if (use_ozone || use_x11) {
+ if (is_linux || is_chromeos) {
+ # TODO(https://crbug.com/1099225): refactor X11 kbd hook and implement
+ # that for Ozone.
+ sources += [ "keyboard_hook_linux.cc" ]
+ }
+ }
+
+ if (use_ozone) {
+ public += [ "ozone/keyboard_hook_ozone.h" ]
+ sources += [ "ozone/keyboard_hook_ozone.cc" ]
+ deps += [
+ "//ui/base:features",
+ "//ui/ozone",
+ ]
+ }
+
+ if (is_android) {
+ sources += [ "android/keyboard_hook_android.cc" ]
+ }
+}
+
component("gesture_detection") {
sources = [
"gesture_detection/bitset_32.h",
@@ -490,14 +541,6 @@ static_library("test_support") {
"test/test_event_targeter.h",
]
- if (is_win) {
- sources += [
- "test/keyboard_hook_monitor_utils.cc",
- "test/keyboard_hook_monitor_utils.h",
- "test/keyboard_layout_win.cc",
- ]
- }
-
if (is_mac) {
sources += [
"test/cocoa_test_event_utils.h",
@@ -522,6 +565,15 @@ static_library("test_support") {
"//ui/gfx/geometry",
]
+ if (is_win) {
+ sources += [
+ "test/keyboard_hook_monitor_utils.cc",
+ "test/keyboard_hook_monitor_utils.h",
+ "test/keyboard_layout_win.cc",
+ ]
+ deps += [ "//ui/events:keyboard_hook" ]
+ }
+
if (is_mac) {
frameworks = [ "Carbon.framework" ]
}
@@ -589,14 +641,6 @@ if (!is_ios) {
sources += [ "cocoa/events_mac_unittest.mm" ]
}
- if (is_win) {
- sources += [
- "keycodes/platform_key_map_win_unittest.cc",
- "win/event_utils_win_unittest.cc",
- "win/media_keyboard_hook_win_unittest.cc",
- "win/modifier_keyboard_hook_win_unittest.cc",
- ]
- }
if (is_linux || is_chromeos || is_win) {
sources += [ "keyboard_event_counter_unittest.cc" ]
}
@@ -656,7 +700,14 @@ if (!is_ios) {
}
if (is_win) {
- sources += [ "blink/web_input_event_builders_win_unittest.cc" ]
+ sources += [
+ "blink/web_input_event_builders_win_unittest.cc",
+ "keycodes/platform_key_map_win_unittest.cc",
+ "win/event_utils_win_unittest.cc",
+ "win/media_keyboard_hook_win_unittest.cc",
+ "win/modifier_keyboard_hook_win_unittest.cc",
+ ]
+ deps += [ "//ui/events:keyboard_hook" ]
}
if (is_chromecast && !is_android) {
@@ -664,8 +715,15 @@ if (!is_ios) {
}
if (is_fuchsia) {
- sources += [ "fuchsia/input_event_dispatcher_unittest.cc" ]
- deps += [ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.input" ]
+ sources += [
+ "fuchsia/input_event_dispatcher_unittest.cc",
+ "keycodes/keyboard_code_conversion_fuchsia_unittest.cc",
+ ]
+
+ deps += [
+ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.input",
+ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.input3",
+ ]
}
if (is_win || is_mac || use_ozone) {
@@ -694,6 +752,7 @@ source_set("events_interactive_ui_tests") {
deps = [
":events",
+ ":keyboard_hook",
":test_support",
"//base/test:test_support",
"//testing/gtest",
diff --git a/chromium/ui/events/DEPS b/chromium/ui/events/DEPS
index d9f4d652ad3..ead7e66e799 100644
--- a/chromium/ui/events/DEPS
+++ b/chromium/ui/events/DEPS
@@ -1,7 +1,8 @@
include_rules = [
"+ui/base/ui_base_features.h",
+ "+ui/base/x/x11_keyboard_hook.h",
"+ui/display",
"+ui/gfx",
"+ui/latency",
- "+ui/base/ui_base_features.h",
+ "+ui/ozone/public/platform_keyboard_hook.h",
]
diff --git a/chromium/ui/events/OWNERS b/chromium/ui/events/OWNERS
index 230180c6641..7c6fd6febf5 100644
--- a/chromium/ui/events/OWNERS
+++ b/chromium/ui/events/OWNERS
@@ -1,4 +1,4 @@
sadrul@chromium.org
# If you're doing structural changes get a review from one of the OWNERS.
-per-file BUILD.gn=* \ No newline at end of file
+per-file BUILD.gn=*
diff --git a/chromium/ui/events/android/drag_event_android.cc b/chromium/ui/events/android/drag_event_android.cc
index f7343f01ebe..ebcc699713a 100644
--- a/chromium/ui/events/android/drag_event_android.cc
+++ b/chromium/ui/events/android/drag_event_android.cc
@@ -3,6 +3,9 @@
// found in the LICENSE file.
#include "ui/events/android/drag_event_android.h"
+
+#include <memory>
+
#include "base/android/jni_android.h"
using base::android::ScopedJavaLocalRef;
@@ -43,9 +46,9 @@ std::unique_ptr<DragEventAndroid> DragEventAndroid::CreateFor(
gfx::PointF new_screen_location =
new_location + (screen_location_f() - location_f());
JNIEnv* env = AttachCurrentThread();
- return std::unique_ptr<DragEventAndroid>(
- new DragEventAndroid(env, action_, new_location, new_screen_location,
- mime_types_, content_.obj()));
+ return std::make_unique<DragEventAndroid>(env, action_, new_location,
+ new_screen_location, mime_types_,
+ content_.obj());
}
} // namespace ui
diff --git a/chromium/ui/events/android/event_handler_android.cc b/chromium/ui/events/android/event_handler_android.cc
index e74e3e15211..ea6f2572b0b 100644
--- a/chromium/ui/events/android/event_handler_android.cc
+++ b/chromium/ui/events/android/event_handler_android.cc
@@ -52,7 +52,7 @@ bool EventHandlerAndroid::ScrollTo(float x, float y) {
void EventHandlerAndroid::OnSizeChanged() {}
void EventHandlerAndroid::OnPhysicalBackingSizeChanged(
- base::Optional<base::TimeDelta> deadline_override) {}
+ absl::optional<base::TimeDelta> deadline_override) {}
void EventHandlerAndroid::OnBrowserControlsHeightChanged() {}
diff --git a/chromium/ui/events/android/event_handler_android.h b/chromium/ui/events/android/event_handler_android.h
index 99bb3959897..8ac2e143aee 100644
--- a/chromium/ui/events/android/event_handler_android.h
+++ b/chromium/ui/events/android/event_handler_android.h
@@ -5,8 +5,8 @@
#ifndef UI_EVENTS_ANDROID_EVENT_HANDLER_ANDROID_H_
#define UI_EVENTS_ANDROID_EVENT_HANDLER_ANDROID_H_
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/events_export.h"
namespace gfx {
@@ -35,7 +35,7 @@ class EVENTS_EXPORT EventHandlerAndroid {
virtual bool OnGestureEvent(const GestureEventAndroid& event);
virtual void OnSizeChanged();
virtual void OnPhysicalBackingSizeChanged(
- base::Optional<base::TimeDelta> deadline_override);
+ absl::optional<base::TimeDelta> deadline_override);
virtual void OnBrowserControlsHeightChanged();
virtual void OnControlsResizeViewChanged();
diff --git a/chromium/ui/events/android/gesture_event_android.cc b/chromium/ui/events/android/gesture_event_android.cc
index fcd298da3bf..64b18324642 100644
--- a/chromium/ui/events/android/gesture_event_android.cc
+++ b/chromium/ui/events/android/gesture_event_android.cc
@@ -4,6 +4,8 @@
#include "ui/events/android/gesture_event_android.h"
+#include <memory>
+
#include "ui/gfx/geometry/point_f.h"
namespace ui {
@@ -39,10 +41,10 @@ std::unique_ptr<GestureEventAndroid> GestureEventAndroid::CreateFor(
const gfx::PointF& new_location) const {
auto offset = new_location - location_;
gfx::PointF new_screen_location = screen_location_ + offset;
- return std::unique_ptr<GestureEventAndroid>(new GestureEventAndroid(
+ return std::make_unique<GestureEventAndroid>(
type_, new_location, new_screen_location, time_ms_, scale_, delta_x_,
delta_y_, velocity_x_, velocity_y_, target_viewport_, synthetic_scroll_,
- prevent_boosting_));
+ prevent_boosting_);
}
} // namespace ui
diff --git a/chromium/ui/events/android/gesture_event_type.h b/chromium/ui/events/android/gesture_event_type.h
index f92af979dc1..e4d3550be5e 100644
--- a/chromium/ui/events/android/gesture_event_type.h
+++ b/chromium/ui/events/android/gesture_event_type.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_ANDROID_GESTURE_EVENT_TYPE_H_
-#define UI_ANDROID_GESTURE_EVENT_TYPE_H_
+#ifndef UI_EVENTS_ANDROID_GESTURE_EVENT_TYPE_H_
+#define UI_EVENTS_ANDROID_GESTURE_EVENT_TYPE_H_
namespace ui {
@@ -36,4 +36,4 @@ enum GestureEventType {
} // namespace ui
-#endif // UI_ANDROID_GESTURE_EVENT_TYPE_H_
+#endif // UI_EVENTS_ANDROID_GESTURE_EVENT_TYPE_H_
diff --git a/chromium/ui/events/android/key_event_utils.h b/chromium/ui/events/android/key_event_utils.h
index a47ee8eb7e8..3e4705b329e 100644
--- a/chromium/ui/events/android/key_event_utils.h
+++ b/chromium/ui/events/android/key_event_utils.h
@@ -26,4 +26,4 @@ EVENTS_EXPORT int GetKeyEventUnicodeChar(
} // namespace events
} // namespace ui
-#endif // UI_EVENTS_ANDROID_KEY_EVENT_UTISL_H_
+#endif // UI_EVENTS_ANDROID_KEY_EVENT_UTILS_H_
diff --git a/chromium/ui/events/android/keyboard_hook_android.cc b/chromium/ui/events/android/keyboard_hook_android.cc
index 31937535ffc..6ee96cf1e3a 100644
--- a/chromium/ui/events/android/keyboard_hook_android.cc
+++ b/chromium/ui/events/android/keyboard_hook_android.cc
@@ -7,7 +7,7 @@
#include <memory>
#include "base/callback.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/gfx/native_widget_types.h"
@@ -15,7 +15,7 @@ namespace ui {
// static
std::unique_ptr<KeyboardHook> KeyboardHook::CreateModifierKeyboardHook(
- base::Optional<base::flat_set<DomCode>> dom_codes,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
gfx::AcceleratedWidget accelerated_widget,
KeyboardHook::KeyEventCallback callback) {
return nullptr;
diff --git a/chromium/ui/events/base_event_utils.h b/chromium/ui/events/base_event_utils.h
index 2c5743c11b5..401ae76ac8c 100644
--- a/chromium/ui/events/base_event_utils.h
+++ b/chromium/ui/events/base_event_utils.h
@@ -5,7 +5,6 @@
#ifndef UI_EVENTS_BASE_EVENT_UTILS_H_
#define UI_EVENTS_BASE_EVENT_UTILS_H_
-#include <memory>
#include <stdint.h>
#include "base/time/tick_clock.h"
diff --git a/chromium/ui/events/blink/blink_event_util.cc b/chromium/ui/events/blink/blink_event_util.cc
index 882781c40b4..a757780a4b9 100644
--- a/chromium/ui/events/blink/blink_event_util.cc
+++ b/chromium/ui/events/blink/blink_event_util.cc
@@ -26,7 +26,8 @@
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/types/event_type.h"
#include "ui/gfx/geometry/angle_conversions.h"
-#include "ui/gfx/geometry/vector2d.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/vector2d_f.h"
#include "ui/gfx/transform.h"
using blink::WebGestureDevice;
@@ -473,12 +474,12 @@ WebGestureEvent CreateWebGestureEventFromGestureEventData(
std::unique_ptr<blink::WebInputEvent> ScaleWebInputEvent(
const blink::WebInputEvent& event,
float scale) {
- return TranslateAndScaleWebInputEvent(event, gfx::Vector2d(0, 0), scale);
+ return TranslateAndScaleWebInputEvent(event, gfx::Vector2dF(0, 0), scale);
}
std::unique_ptr<blink::WebInputEvent> TranslateAndScaleWebInputEvent(
const blink::WebInputEvent& event,
- const gfx::Vector2d& delta,
+ const gfx::Vector2dF& delta,
float scale) {
std::unique_ptr<blink::WebInputEvent> scaled_event;
if (scale == 1.f && delta.IsZero())
@@ -487,9 +488,8 @@ std::unique_ptr<blink::WebInputEvent> TranslateAndScaleWebInputEvent(
blink::WebMouseWheelEvent* wheel_event = new blink::WebMouseWheelEvent;
scaled_event.reset(wheel_event);
*wheel_event = static_cast<const blink::WebMouseWheelEvent&>(event);
- float x = (wheel_event->PositionInWidget().x() + delta.x()) * scale;
- float y = (wheel_event->PositionInWidget().y() + delta.y()) * scale;
- wheel_event->SetPositionInWidget(x, y);
+ wheel_event->SetPositionInWidget(
+ gfx::ScalePoint(wheel_event->PositionInWidget() + delta, scale));
if (wheel_event->delta_units != ui::ScrollGranularity::kScrollByPage) {
wheel_event->delta_x *= scale;
wheel_event->delta_y *= scale;
@@ -500,9 +500,8 @@ std::unique_ptr<blink::WebInputEvent> TranslateAndScaleWebInputEvent(
blink::WebMouseEvent* mouse_event = new blink::WebMouseEvent;
scaled_event.reset(mouse_event);
*mouse_event = static_cast<const blink::WebMouseEvent&>(event);
- float x = (mouse_event->PositionInWidget().x() + delta.x()) * scale;
- float y = (mouse_event->PositionInWidget().y() + delta.y()) * scale;
- mouse_event->SetPositionInWidget(x, y);
+ mouse_event->SetPositionInWidget(
+ gfx::ScalePoint(mouse_event->PositionInWidget() + delta, scale));
// Do not scale movement of raw movement events.
if (!mouse_event->is_raw_movement_event) {
mouse_event->movement_x *= scale;
@@ -513,9 +512,8 @@ std::unique_ptr<blink::WebInputEvent> TranslateAndScaleWebInputEvent(
scaled_event.reset(touch_event);
*touch_event = static_cast<const blink::WebTouchEvent&>(event);
for (unsigned i = 0; i < touch_event->touches_length; i++) {
- touch_event->touches[i].SetPositionInWidget(
- (touch_event->touches[i].PositionInWidget().x() + delta.x()) * scale,
- (touch_event->touches[i].PositionInWidget().y() + delta.y()) * scale);
+ touch_event->touches[i].SetPositionInWidget(gfx::ScalePoint(
+ touch_event->touches[i].PositionInWidget() + delta, scale));
touch_event->touches[i].radius_x *= scale;
touch_event->touches[i].radius_y *= scale;
}
@@ -523,9 +521,8 @@ std::unique_ptr<blink::WebInputEvent> TranslateAndScaleWebInputEvent(
blink::WebGestureEvent* gesture_event = new blink::WebGestureEvent;
scaled_event.reset(gesture_event);
*gesture_event = static_cast<const blink::WebGestureEvent&>(event);
- gesture_event->SetPositionInWidget(gfx::PointF(
- (gesture_event->PositionInWidget().x() + delta.x()) * scale,
- (gesture_event->PositionInWidget().y() + delta.y()) * scale));
+ gesture_event->SetPositionInWidget(
+ gfx::ScalePoint(gesture_event->PositionInWidget() + delta, scale));
switch (gesture_event->GetType()) {
case blink::WebInputEvent::Type::kGestureScrollUpdate:
if (gesture_event->data.scroll_update.delta_units ==
diff --git a/chromium/ui/events/blink/blink_event_util.h b/chromium/ui/events/blink/blink_event_util.h
index 29ce4a9985c..1982c72c04d 100644
--- a/chromium/ui/events/blink/blink_event_util.h
+++ b/chromium/ui/events/blink/blink_event_util.h
@@ -7,8 +7,8 @@
#include <memory>
-#include "base/optional.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/input/web_gesture_event.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/input/web_touch_event.h"
@@ -20,7 +20,7 @@
namespace gfx {
class PointF;
-class Vector2d;
+class Vector2dF;
}
namespace ui {
@@ -59,7 +59,7 @@ std::unique_ptr<blink::WebInputEvent> ScaleWebInputEvent(
// Otherwise, returns the transformed version of |event|.
std::unique_ptr<blink::WebInputEvent> TranslateAndScaleWebInputEvent(
const blink::WebInputEvent& event,
- const gfx::Vector2d& delta,
+ const gfx::Vector2dF& delta,
float scale);
blink::WebInputEvent::Type ToWebMouseEventType(MotionEvent::Action action);
diff --git a/chromium/ui/events/blink/web_input_event.cc b/chromium/ui/events/blink/web_input_event.cc
index a07b99f9d02..cae38e28958 100644
--- a/chromium/ui/events/blink/web_input_event.cc
+++ b/chromium/ui/events/blink/web_input_event.cc
@@ -473,7 +473,13 @@ blink::WebMouseWheelEvent MakeWebMouseWheelEventFromUiEvent(
// mousewheel events are built in the Windows web input event builder.
// Percent based scrolling is not supported on Mac because the current
// roadmap for scroll personality work is reserved for Windows and Linux.
- if (base::FeatureList::IsEnabled(features::kPercentBasedScrolling)) {
+ // Page based scrolling isn't specified in terms of pixels so we don't convert
+ // deltas to a percentage here - it's resolved into percent, then pixels,
+ // in the renderer.
+ // TODO(yshalivskyy) Currently, for page based scrolling we always scroll
+ // by one page dismissing delta_y/delta_x values. https://crbug.com/1196092
+ if (base::FeatureList::IsEnabled(features::kPercentBasedScrolling) &&
+ webkit_event.delta_units != ui::ScrollGranularity::kScrollByPage) {
webkit_event.delta_units = ui::ScrollGranularity::kScrollByPercentage;
webkit_event.delta_y *=
(kScrollPercentPerLineOrChar / MouseWheelEvent::kWheelDelta);
diff --git a/chromium/ui/events/blink/web_input_event_builders_win.cc b/chromium/ui/events/blink/web_input_event_builders_win.cc
index 619602f3fb6..155402fcb09 100644
--- a/chromium/ui/events/blink/web_input_event_builders_win.cc
+++ b/chromium/ui/events/blink/web_input_event_builders_win.cc
@@ -4,6 +4,8 @@
#include "ui/events/blink/web_input_event_builders_win.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/trace_event/trace_event.h"
#include "base/win/windowsx_shim.h"
#include "ui/base/ui_base_features.h"
#include "ui/display/win/screen_win.h"
@@ -289,10 +291,18 @@ WebMouseWheelEvent WebMouseWheelEventBuilder::Build(
if (horizontal_scroll) {
unsigned long scroll_chars = kDefaultScrollCharsPerWheelDelta;
SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scroll_chars, 0);
+ TRACE_EVENT1("input", "WebMouseWheelEventBuilder::Build", "scroll_chars",
+ scroll_chars);
+ base::UmaHistogramCounts10M("InputMethod.MouseWheel.ScrollCharacters",
+ base::saturated_cast<int>(scroll_chars));
scroll_delta *= static_cast<float>(scroll_chars);
} else {
unsigned long scroll_lines = kDefaultScrollLinesPerWheelDelta;
SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scroll_lines, 0);
+ TRACE_EVENT1("input", "WebMouseWheelEventBuilder::Build", "scroll_lines",
+ scroll_lines);
+ base::UmaHistogramCounts10M("InputMethod.MouseWheel.ScrollLines",
+ base::saturated_cast<int>(scroll_lines));
if (scroll_lines == WHEEL_PAGESCROLL)
result.delta_units = ui::ScrollGranularity::kScrollByPage;
else
diff --git a/chromium/ui/events/blink/web_input_event_builders_win_unittest.cc b/chromium/ui/events/blink/web_input_event_builders_win_unittest.cc
index b1002c167b7..97feeb3948a 100644
--- a/chromium/ui/events/blink/web_input_event_builders_win_unittest.cc
+++ b/chromium/ui/events/blink/web_input_event_builders_win_unittest.cc
@@ -4,6 +4,7 @@
#include "ui/events/blink/web_input_event_builders_win.h"
#include "base/command_line.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "base/win/windows_version.h"
@@ -88,4 +89,54 @@ TEST(WebInputEventBuilderTest, TestPercentMouseWheelScroll) {
EXPECT_FLOAT_EQ(0.f, mouse_wheel.wheel_ticks_y);
}
+void VerifyWebMouseWheelEventBuilderHistograms(
+ UINT message,
+ blink::WebPointerProperties::PointerType type,
+ const char* histogram,
+ std::vector<int>& event_timestamps_in_ms,
+ std::map<int, int>& histogram_expectations) {
+ base::HistogramTester histogram_tester;
+
+ EXPECT_TRUE(event_timestamps_in_ms.size() > 0 &&
+ histogram_expectations.size() > 0);
+ for (int event_timestamp : event_timestamps_in_ms) {
+ WebMouseWheelEventBuilder::Build(
+ ::GetDesktopWindow(), message, MAKEWPARAM(0, -WHEEL_DELTA),
+ MAKELPARAM(0, 0),
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(event_timestamp),
+ type);
+ }
+
+ for (std::map<int, int>::iterator it = histogram_expectations.begin();
+ it != histogram_expectations.end(); ++it) {
+ // Key is the (unique) velocity bucket.
+ // Value is the count of data points for that bucket.
+ EXPECT_EQ(histogram_tester.GetBucketCount(histogram, it->first),
+ it->second);
+ }
+}
+
+TEST(WebInputEventBuilderTest, TestMouseWheelScrollHistograms) {
+ // Tests mouse wheel horizontal scrolling logging.
+ unsigned long scroll_chars = 1;
+ SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scroll_chars, 0);
+ std::vector<int> event_timestamps = {300, 600, 900, 1200};
+ std::map<int, int> histogram_expectations = {
+ {scroll_chars - 1, 0}, {scroll_chars, 4}, {scroll_chars + 1, 0}};
+ VerifyWebMouseWheelEventBuilderHistograms(
+ WM_HSCROLL, blink::WebPointerProperties::PointerType::kTouch,
+ "InputMethod.MouseWheel.ScrollCharacters", event_timestamps,
+ histogram_expectations);
+ // Tests mouse wheel vertical scrolling logging.
+ unsigned long scroll_lines = 1;
+ SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scroll_lines, 0);
+ histogram_expectations.clear();
+ histogram_expectations = {
+ {scroll_lines - 1, 0}, {scroll_lines, 4}, {scroll_lines + 1, 0}};
+ VerifyWebMouseWheelEventBuilderHistograms(
+ WM_VSCROLL, blink::WebPointerProperties::PointerType::kTouch,
+ "InputMethod.MouseWheel.ScrollLines", event_timestamps,
+ histogram_expectations);
+}
+
} // namespace ui
diff --git a/chromium/ui/events/cocoa/events_mac.mm b/chromium/ui/events/cocoa/events_mac.mm
index 6f0983524c2..b716ef85eec 100644
--- a/chromium/ui/events/cocoa/events_mac.mm
+++ b/chromium/ui/events/cocoa/events_mac.mm
@@ -84,6 +84,11 @@ base::TimeTicks EventTimeFromNative(const PlatformEvent& native_event) {
return timestamp;
}
+base::TimeTicks EventLatencyTimeFromNative(const PlatformEvent& native_event,
+ base::TimeTicks current_time) {
+ return EventTimeFromNative(native_event);
+}
+
gfx::PointF EventLocationFromNative(const PlatformEvent& native_event) {
NSWindow* window = [native_event window];
NSPoint location = [native_event locationInWindow];
diff --git a/chromium/ui/events/devices/BUILD.gn b/chromium/ui/events/devices/BUILD.gn
index c8c06e7335e..bcd753dbb7d 100644
--- a/chromium/ui/events/devices/BUILD.gn
+++ b/chromium/ui/events/devices/BUILD.gn
@@ -18,6 +18,8 @@ component("devices") {
"input_device.cc",
"input_device.h",
"input_device_event_observer.h",
+ "microphone_mute_switch_monitor.cc",
+ "microphone_mute_switch_monitor.h",
"stylus_state.h",
"touch_device_transform.cc",
"touch_device_transform.h",
diff --git a/chromium/ui/events/devices/microphone_mute_switch_monitor.cc b/chromium/ui/events/devices/microphone_mute_switch_monitor.cc
new file mode 100644
index 00000000000..fc53f980d37
--- /dev/null
+++ b/chromium/ui/events/devices/microphone_mute_switch_monitor.cc
@@ -0,0 +1,37 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/devices/microphone_mute_switch_monitor.h"
+
+#include "base/no_destructor.h"
+
+namespace ui {
+
+MicrophoneMuteSwitchMonitor::MicrophoneMuteSwitchMonitor() = default;
+
+MicrophoneMuteSwitchMonitor::~MicrophoneMuteSwitchMonitor() = default;
+
+// static
+MicrophoneMuteSwitchMonitor* MicrophoneMuteSwitchMonitor::Get() {
+ static base::NoDestructor<MicrophoneMuteSwitchMonitor> instance;
+ return instance.get();
+}
+
+void MicrophoneMuteSwitchMonitor::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void MicrophoneMuteSwitchMonitor::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void MicrophoneMuteSwitchMonitor::SetMicrophoneMuteSwitchValue(bool switch_on) {
+ if (microphone_mute_switch_on_ == switch_on)
+ return;
+ microphone_mute_switch_on_ = switch_on;
+ for (auto& observer : observers_)
+ observer.OnMicrophoneMuteSwitchValueChanged(microphone_mute_switch_on_);
+}
+
+} // namespace ui
diff --git a/chromium/ui/events/devices/microphone_mute_switch_monitor.h b/chromium/ui/events/devices/microphone_mute_switch_monitor.h
new file mode 100644
index 00000000000..3b25f6ddf46
--- /dev/null
+++ b/chromium/ui/events/devices/microphone_mute_switch_monitor.h
@@ -0,0 +1,62 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_DEVICES_MICROPHONE_MUTE_SWITCH_MONITOR_H_
+#define UI_EVENTS_DEVICES_MICROPHONE_MUTE_SWITCH_MONITOR_H_
+
+#include "base/no_destructor.h"
+#include "base/observer_list.h"
+#include "base/observer_list_types.h"
+#include "ui/events/devices/events_devices_export.h"
+
+namespace ui {
+
+// Monitors the state of the Microphone mute switch device - Chrome OS devices
+// may have a hardware toggle that disables audio input. The toggle state is
+// exposed using the SW_MUTE_DEVICE event on an input device.
+// MicrophoneMuteSwitchMonitor can be used to track the state of the microphone
+// mute switch. The switch state will be updated by the input device's event
+// converter, and can be observed using the Observer interface exposed by the
+// MicrophoneMuteSwitchMonitor.
+//
+// NOTE: The mute switch state will be monitored only on Chrome OS with ozone.
+class EVENTS_DEVICES_EXPORT MicrophoneMuteSwitchMonitor {
+ public:
+ class Observer : public base::CheckedObserver {
+ public:
+ // Called when the microphone mute switch value changes.
+ virtual void OnMicrophoneMuteSwitchValueChanged(bool muted) = 0;
+ };
+
+ MicrophoneMuteSwitchMonitor();
+ ~MicrophoneMuteSwitchMonitor();
+ MicrophoneMuteSwitchMonitor(const MicrophoneMuteSwitchMonitor&) = delete;
+ MicrophoneMuteSwitchMonitor& operator=(const MicrophoneMuteSwitchMonitor&) =
+ delete;
+
+ static MicrophoneMuteSwitchMonitor* Get();
+
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
+ bool microphone_mute_switch_on() const { return microphone_mute_switch_on_; }
+
+ // Updates the microphone mute switch value. Set in response to a
+ // SW_MUTE_DEVICE event on the input device associated with the microphone
+ // mute switch.
+ void SetMicrophoneMuteSwitchValue(bool switch_on);
+
+ private:
+ friend class base::NoDestructor<MicrophoneMuteSwitchMonitor>;
+
+ // Whether the microphone mute switch was toggled to on, in which case the
+ // internal microphone will be muted.
+ bool microphone_mute_switch_on_ = false;
+
+ base::ObserverList<MicrophoneMuteSwitchMonitor::Observer> observers_;
+};
+
+} // namespace ui
+
+#endif // UI_EVENTS_DEVICES_MICROPHONE_MUTE_SWITCH_MONITOR_H_
diff --git a/chromium/ui/events/devices/touchscreen_device.cc b/chromium/ui/events/devices/touchscreen_device.cc
index 61238d21054..7ae0eafad8b 100644
--- a/chromium/ui/events/devices/touchscreen_device.cc
+++ b/chromium/ui/events/devices/touchscreen_device.cc
@@ -17,20 +17,24 @@ TouchscreenDevice::TouchscreenDevice(int id,
const std::string& name,
const gfx::Size& size,
int touch_points,
- bool has_stylus)
+ bool has_stylus,
+ bool has_stylus_garage_switch)
: InputDevice(id, type, name),
size(size),
touch_points(touch_points),
- has_stylus(has_stylus) {}
+ has_stylus(has_stylus),
+ has_stylus_garage_switch(has_stylus_garage_switch) {}
TouchscreenDevice::TouchscreenDevice(const InputDevice& input_device,
const gfx::Size& size,
int touch_points,
- bool has_stylus)
+ bool has_stylus,
+ bool has_stylus_garage_switch)
: InputDevice(input_device),
size(size),
touch_points(touch_points),
- has_stylus(has_stylus) {}
+ has_stylus(has_stylus),
+ has_stylus_garage_switch(has_stylus_garage_switch) {}
TouchscreenDevice::TouchscreenDevice(const TouchscreenDevice& other) = default;
diff --git a/chromium/ui/events/devices/touchscreen_device.h b/chromium/ui/events/devices/touchscreen_device.h
index f786bdaa0f6..5c4a5bb637d 100644
--- a/chromium/ui/events/devices/touchscreen_device.h
+++ b/chromium/ui/events/devices/touchscreen_device.h
@@ -26,12 +26,14 @@ struct EVENTS_DEVICES_EXPORT TouchscreenDevice : public InputDevice {
const std::string& name,
const gfx::Size& size,
int touch_points,
- bool has_stylus = false);
+ bool has_stylus = false,
+ bool has_stylus_garage_switch = false);
TouchscreenDevice(const InputDevice& input_device,
const gfx::Size& size,
int touch_points,
- bool has_stylus = false);
+ bool has_stylus = false,
+ bool has_stylus_garage_switch = false);
TouchscreenDevice(const TouchscreenDevice& other);
@@ -42,6 +44,9 @@ struct EVENTS_DEVICES_EXPORT TouchscreenDevice : public InputDevice {
int touch_points = 0;
// True if the specified touchscreen device is stylus capable.
bool has_stylus = false;
+ // True if there is a garage/dock switch associated with the stylus.
+ bool has_stylus_garage_switch = false;
+
// Id of the display the touch device targets.
// NOTE: when obtaining TouchscreenDevice from DeviceDataManager this value
// may not have been updated. See
diff --git a/chromium/ui/events/devices/x11/touch_factory_x11.cc b/chromium/ui/events/devices/x11/touch_factory_x11.cc
index c6670959664..5a4175608be 100644
--- a/chromium/ui/events/devices/x11/touch_factory_x11.cc
+++ b/chromium/ui/events/devices/x11/touch_factory_x11.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/system/sys_info.h"
#include "build/build_config.h"
@@ -36,7 +37,7 @@ void AddPointerDevicesFromString(
if (base::StringToInt(dev, &devid))
devices->push_back({devid, type});
else
- DLOG(WARNING) << "Invalid device id: " << dev.as_string();
+ DLOG(WARNING) << "Invalid device id: " << dev;
}
}
diff --git a/chromium/ui/events/devices/x11/touch_factory_x11.h b/chromium/ui/events/devices/x11/touch_factory_x11.h
index 254e018c647..727eb67afe8 100644
--- a/chromium/ui/events/devices/x11/touch_factory_x11.h
+++ b/chromium/ui/events/devices/x11/touch_factory_x11.h
@@ -148,7 +148,7 @@ class EVENTS_DEVICES_X11_EXPORT TouchFactory {
std::set<std::pair<int, int>> touchscreen_ids_;
// Device ID of the virtual core keyboard.
- base::Optional<x11::Input::DeviceId> virtual_core_keyboard_device_;
+ absl::optional<x11::Input::DeviceId> virtual_core_keyboard_device_;
SequentialIDGenerator id_generator_;
diff --git a/chromium/ui/events/event.cc b/chromium/ui/events/event.cc
index 5ab31094b77..b55d5ba508f 100644
--- a/chromium/ui/events/event.cc
+++ b/chromium/ui/events/event.cc
@@ -152,6 +152,11 @@ uint32_t ScanCodeFromNative(const PlatformEvent& native_event) {
}
#endif // defined(USE_OZONE)
+bool IsNearZero(const float num) {
+ // Epsilon of 1e-10 at 0.
+ return (std::fabs(num) < 1e-10);
+}
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -618,7 +623,8 @@ void MouseEvent::SetClickCount(int click_count) {
std::string MouseEvent::ToString() const {
return base::StrCat(
{LocatedEvent::ToString(), " flags ",
- base::JoinString(make_span(MouseEventFlagsNames(flags())), " | ")});
+ base::JoinString(base::make_span(MouseEventFlagsNames(flags())),
+ " | ")});
}
////////////////////////////////////////////////////////////////////////////////
@@ -657,7 +663,7 @@ MouseWheelEvent::MouseWheelEvent(
base::TimeTicks time_stamp,
int flags,
int changed_button_flags,
- const base::Optional<gfx::Vector2d> tick_120ths)
+ const absl::optional<gfx::Vector2d> tick_120ths)
: MouseEvent(ET_UNKNOWN,
location,
root_location,
@@ -759,13 +765,39 @@ void TouchEvent::UpdateForRootTransform(
const gfx::Transform& inverted_local_transform) {
LocatedEvent::UpdateForRootTransform(inverted_root_transform,
inverted_local_transform);
- gfx::DecomposedTransform decomp;
- bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform);
- DCHECK(success);
- if (decomp.scale[0])
- pointer_details_.radius_x *= decomp.scale[0];
- if (decomp.scale[1])
- pointer_details_.radius_y *= decomp.scale[1];
+
+ // We could create a vector and then rely on Transform::TransformVector , but
+ // that ends up creating a 4 dimensional vector and applying a 4 dim
+ // transform. Really what we're looking at is only in the (x,y) plane, and
+ // given that we can run this relatively frequently we will inline execute the
+ // matrix here.
+ const auto& matrix = inverted_root_transform.matrix();
+ const double new_x = fabs(pointer_details_.radius_x * matrix.get(0, 0) +
+ pointer_details_.radius_y * matrix.get(0, 1));
+ const double new_y = fabs(pointer_details_.radius_x * matrix.get(1, 0) +
+ pointer_details_.radius_y * matrix.get(1, 1));
+ pointer_details_.radius_x = new_x;
+ pointer_details_.radius_y = new_y;
+
+ // for stylus touches, tilt needs to be rotated appropriately. We don't handle
+ // screen rotations other than 0/90/180/270, but those should be handled and
+ // translated appropriately. Other rotations leave tilts untouched for now. We
+ // add a small check that tilt is set at all before looking through this
+ // section.
+ if (!IsNearZero(pointer_details_.tilt_x) ||
+ !IsNearZero(pointer_details_.tilt_y)) {
+ if (IsNearZero(matrix.get(0, 1)) && IsNearZero(matrix.get(1, 0))) {
+ pointer_details_.tilt_x *= std::copysign(1, matrix.get(0, 0));
+ pointer_details_.tilt_y *= std::copysign(1, matrix.get(1, 1));
+ } else if (IsNearZero(matrix.get(0, 0)) && IsNearZero(matrix.get(1, 1))) {
+ double new_tilt_x =
+ pointer_details_.tilt_y * std::copysign(1, matrix.get(0, 1));
+ double new_tilt_y =
+ pointer_details_.tilt_x * std::copysign(1, matrix.get(1, 0));
+ pointer_details_.tilt_x = new_tilt_x;
+ pointer_details_.tilt_y = new_tilt_y;
+ }
+ }
}
void TouchEvent::DisableSynchronousHandling() {
@@ -1104,7 +1136,7 @@ std::string KeyEvent::ToString() const {
return base::StrCat(
{Event::ToString(), " key ", base::StringPrintf("(0x%.4x)", key_code_),
" flags ",
- base::JoinString(make_span(KeyEventFlagsNames(flags())), " | ")});
+ base::JoinString(base::make_span(KeyEventFlagsNames(flags())), " | ")});
}
KeyboardCode KeyEvent::GetLocatedWindowsKeyboardCode() const {
diff --git a/chromium/ui/events/event.h b/chromium/ui/events/event.h
index 8a5d246439a..e562e07d4c1 100644
--- a/chromium/ui/events/event.h
+++ b/chromium/ui/events/event.h
@@ -609,7 +609,7 @@ class EVENTS_EXPORT MouseWheelEvent : public MouseEvent {
base::TimeTicks time_stamp,
int flags,
int changed_button_flags,
- const base::Optional<gfx::Vector2d> tick_120ths = base::nullopt);
+ const absl::optional<gfx::Vector2d> tick_120ths = absl::nullopt);
// DEPRECATED: Prefer the constructor that takes gfx::PointF.
MouseWheelEvent(const gfx::Vector2d& offset,
diff --git a/chromium/ui/events/event_handler.cc b/chromium/ui/events/event_handler.cc
index 68321ed555e..b327eddbdc5 100644
--- a/chromium/ui/events/event_handler.cc
+++ b/chromium/ui/events/event_handler.cc
@@ -6,17 +6,12 @@
#include "base/logging.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "ui/events/event.h"
#include "ui/events/event_dispatcher.h"
namespace ui {
-// static
-bool EventHandler::check_targets_ = true;
-
-EventHandler::EventHandler() {
-}
+EventHandler::EventHandler() = default;
EventHandler::~EventHandler() {
while (!dispatchers_.empty()) {
@@ -24,9 +19,6 @@ EventHandler::~EventHandler() {
dispatchers_.pop();
dispatcher->OnHandlerDestroyed(this);
}
-
- // Should have been removed from all pre-target handlers.
- CHECK(!check_targets_ || targets_installed_on_.empty());
}
void EventHandler::OnEvent(Event* event) {
diff --git a/chromium/ui/events/event_handler.h b/chromium/ui/events/event_handler.h
index 4feb49155d6..3870be3556f 100644
--- a/chromium/ui/events/event_handler.h
+++ b/chromium/ui/events/event_handler.h
@@ -5,12 +5,8 @@
#ifndef UI_EVENTS_EVENT_HANDLER_H_
#define UI_EVENTS_EVENT_HANDLER_H_
-#include <vector>
-
#include "base/containers/stack.h"
-#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "ui/events/event_constants.h"
#include "ui/events/events_export.h"
namespace ui {
@@ -30,13 +26,10 @@ class TouchEvent;
class EVENTS_EXPORT EventHandler {
public:
EventHandler();
+ EventHandler(const EventHandler&) = delete;
+ EventHandler& operator=(const EventHandler&) = delete;
virtual ~EventHandler();
- // Disables a CHECK() that this has been removed from all pre-target
- // handlers in the destructor.
- // TODO(sky): remove, used to track https://crbug.com/867035.
- static void DisableCheckTargets() { check_targets_ = false; }
-
// This is called for all events. The default implementation routes the event
// to one of the event-specific callbacks (OnKeyEvent, OnMouseEvent etc.). If
// this is overridden, then normally, the override should chain into the
@@ -66,19 +59,9 @@ class EVENTS_EXPORT EventHandler {
// EventDispatcher pushes itself on the top of this stack while dispatching
// events to this then pops itself off when done.
base::stack<EventDispatcher*> dispatchers_;
-
- // Set of EventTargets |this| has been installed as a pre-target handler on.
- // This is a vector as AddPreTargetHandler() may be called multiple times for
- // the same EventTarget.
- // TODO(sky): remove, used to track https://crbug.com/867035.
- std::vector<EventTarget*> targets_installed_on_;
-
- static bool check_targets_;
-
- DISALLOW_COPY_AND_ASSIGN(EventHandler);
};
-typedef std::vector<EventHandler*> EventHandlerList;
+using EventHandlerList = std::vector<EventHandler*>;
} // namespace ui
diff --git a/chromium/ui/events/event_switches.h b/chromium/ui/events/event_switches.h
index d94309b4edc..7e6d73602bc 100644
--- a/chromium/ui/events/event_switches.h
+++ b/chromium/ui/events/event_switches.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_EVENTS_SWITCHES_H_
-#define UI_EVENTS_EVENTS_SWITCHES_H_
+#ifndef UI_EVENTS_EVENT_SWITCHES_H_
+#define UI_EVENTS_EVENT_SWITCHES_H_
#include "base/compiler_specific.h"
#include "build/build_config.h"
@@ -25,4 +25,4 @@ EVENTS_BASE_EXPORT extern const char kDisableCancelAllTouches[];
} // namespace switches
-#endif // UI_EVENTS_EVENTS_SWITCHES_H_
+#endif // UI_EVENTS_EVENT_SWITCHES_H_
diff --git a/chromium/ui/events/event_target.cc b/chromium/ui/events/event_target.cc
index 9ce28b23711..c7c6ceb741e 100644
--- a/chromium/ui/events/event_target.cc
+++ b/chromium/ui/events/event_target.cc
@@ -40,18 +40,10 @@ void EventTarget::AddPreTargetHandler(EventHandler* handler,
pre_target_list_.push_back(prioritized);
else
pre_target_list_.insert(pre_target_list_.begin(), prioritized);
- handler->targets_installed_on_.push_back(this);
}
void EventTarget::RemovePreTargetHandler(EventHandler* handler) {
CHECK(handler);
- // Only erase a single one, which matches the removal code right after this.
- auto installed_on_iter =
- std::find(handler->targets_installed_on_.begin(),
- handler->targets_installed_on_.end(), this);
- if (installed_on_iter != handler->targets_installed_on_.end())
- handler->targets_installed_on_.erase(installed_on_iter);
-
EventHandlerPriorityList::iterator it, end;
for (it = pre_target_list_.begin(), end = pre_target_list_.end(); it != end;
++it) {
diff --git a/chromium/ui/events/event_unittest.cc b/chromium/ui/events/event_unittest.cc
index e651e1dbf36..ade042bb2d7 100644
--- a/chromium/ui/events/event_unittest.cc
+++ b/chromium/ui/events/event_unittest.cc
@@ -29,6 +29,10 @@
#include "ui/events/test/test_event_target.h"
#include "ui/gfx/transform.h"
+#if defined(OS_WIN)
+#include "ui/events/win/events_win_utils.h"
+#endif
+
namespace ui {
TEST(EventTest, NoNativeEvent) {
@@ -652,19 +656,14 @@ TEST(EventTest, OrdinalMotionConversion) {
EXPECT_FALSE(mouseev3.flags() & EF_UNADJUSTED_MOUSE);
}
-// Checks that Event.Latency.OS.MOUSE_WHEEL histogram is computed properly.
+// Checks that Event.Latency.OS2.MOUSE_WHEEL histogram is computed properly.
TEST(EventTest, EventLatencyOSMouseWheelHistogram) {
#if defined(OS_WIN)
base::HistogramTester histogram_tester;
MSG event = {nullptr, WM_MOUSEWHEEL, 0, 0};
MouseWheelEvent mouseWheelEvent(event);
histogram_tester.ExpectTotalCount("Event.Latency.OS.MOUSE_WHEEL", 1);
- histogram_tester.ExpectTotalCount("Event.Latency.OS_WIN.HIGH_RES.MOUSE_WHEEL",
- 0);
- histogram_tester.ExpectTotalCount("Event.Latency.OS_WIN.LOW_RES.MOUSE_WHEEL",
- 0);
- histogram_tester.ExpectTotalCount("Event.Latency.OS_WIN_IS_VALID.MOUSE_WHEEL",
- 0);
+ histogram_tester.ExpectTotalCount("Event.Latency.OS2.MOUSE_WHEEL", 1);
#endif
}
@@ -672,6 +671,8 @@ TEST(EventTest, UpdateForRootTransformation) {
gfx::Transform identity_transform;
const gfx::Point location(10, 10);
const gfx::Point root_location(20, 20);
+ const gfx::PointF f_location(10, 10);
+ const gfx::PointF f_root_location(20, 20);
// A mouse event that is untargeted should reset the root location when
// transformed. Though the events start out with different locations and
@@ -684,6 +685,74 @@ TEST(EventTest, UpdateForRootTransformation) {
ui::test::TestEventTarget target;
+ // A touch event should behave the same way as others.
+ {
+ PointerDetails pointer_details(EventPointerType::kTouch, 0 /* pointer id */,
+ 3, 4, 50, 0 /* twist */, 0, 0);
+ ui::TouchEvent targeted(ET_TOUCH_PRESSED, f_location, f_root_location,
+ EventTimeForNow(), pointer_details);
+ targeted.UpdateForRootTransform(identity_transform, identity_transform);
+ EXPECT_EQ(location, targeted.location());
+ EXPECT_EQ(location, targeted.root_location());
+ EXPECT_EQ(pointer_details, targeted.pointer_details());
+ }
+
+ // A touch event should scale the same way as others.
+ {
+ // Targeted event with 2x and 3x scales.
+ gfx::Transform transform2x;
+ transform2x.Scale(2, 2);
+ gfx::Transform transform3x;
+ transform3x.Scale(3, 3);
+ PointerDetails pointer_details(EventPointerType::kTouch, 0 /* pointer id */,
+ 3, 4, 50, 0 /* twist */, 17.2 /* tilt_x */,
+ -28.3 /* tilt_y */);
+
+ ui::TouchEvent targeted(ET_TOUCH_PRESSED, f_location, f_root_location,
+ EventTimeForNow(), pointer_details);
+ targeted.UpdateForRootTransform(transform2x, transform3x);
+ auto updated_location = ScalePoint(f_location, 2.0f);
+ EXPECT_EQ(updated_location, targeted.location_f());
+ EXPECT_EQ(updated_location, targeted.root_location_f());
+ auto updated_pointer_details(pointer_details);
+ updated_pointer_details.radius_x *= 2;
+ updated_pointer_details.radius_y *= 2;
+ EXPECT_EQ(updated_pointer_details, targeted.pointer_details())
+ << " orig: " << pointer_details.ToString() << " vs "
+ << targeted.pointer_details().ToString();
+ }
+
+ // A touch event should rotate appropriately.
+ {
+ // Rotate by 90 degrees, then scale by a half or 0.75 (depending on axis),
+ // and then offset by 720/1080. Note that the offset should have no impact
+ // on vectors, i.e. radius.
+ // The scale happens after rotation, so x should be 0.75 * the y.
+ gfx::Transform rotate90;
+ rotate90.Rotate(90.0f);
+ rotate90.Translate(gfx::Vector2dF(720.0f, 1080.0f));
+ rotate90.Scale(0.5, 0.75);
+ gfx::Transform transform3x;
+ transform3x.Scale(3, 3);
+ PointerDetails pointer_details(EventPointerType::kTouch, 0 /* pointer id */,
+ 3, 4, 50, 0 /* twist */, -17.4 /* tilt_x */,
+ 31.2 /* tilt_y */);
+
+ ui::TouchEvent targeted(ET_TOUCH_PRESSED, f_location, f_root_location,
+ EventTimeForNow(), pointer_details);
+ Event::DispatcherApi(&targeted).set_target(&target);
+ targeted.UpdateForRootTransform(rotate90, transform3x);
+ auto updated_pointer_details(pointer_details);
+ updated_pointer_details.radius_x = pointer_details.radius_y * 0.75;
+ updated_pointer_details.radius_y = pointer_details.radius_x * 0.5;
+ updated_pointer_details.tilt_x = -31.2;
+ updated_pointer_details.tilt_y = -17.4;
+
+ EXPECT_EQ(updated_pointer_details, targeted.pointer_details())
+ << " orig: " << updated_pointer_details.ToString() << " vs "
+ << targeted.pointer_details().ToString();
+ }
+
// A mouse event that is targeted should not set the root location to the
// local location. They start with different locations and should stay
// unequal after a transform is applied.
@@ -841,104 +910,13 @@ INSTANTIATE_TEST_SUITE_P(
::testing::Combine(::testing::Values(WM_CHAR),
::testing::ValuesIn(kAltGraphEventTestCases)));
-// Tests for ComputeEventLatencyOSWin
-
-constexpr struct EventLatencyTickCountTestCase {
- EventType event_type;
- const char* histogram_suffix;
-} kEventLatencyTickCountTestCases[] = {
- {
- ET_KEY_PRESSED,
- "KEY_PRESSED",
- },
- {
- ET_MOUSE_PRESSED,
- "MOUSE_PRESSED",
- },
- {
- ET_TOUCH_PRESSED,
- "TOUCH_PRESSED",
- },
-};
-
-class EventLatencyTestBase : public ::testing::Test {
- protected:
- static constexpr char kHighResHistogram[] = "Event.Latency.OS_WIN.HIGH_RES";
- static constexpr char kLowResHistogram[] = "Event.Latency.OS_WIN.LOW_RES";
- static constexpr char kIsValidHistogram[] = "Event.Latency.OS_WIN_IS_VALID";
-
- std::string HighResEventHistogram(base::StringPiece suffix) const {
- return base::StrCat({kHighResHistogram, ".", suffix});
- }
-
- std::string LowResEventHistogram(base::StringPiece suffix) const {
- return base::StrCat({kLowResHistogram, ".", suffix});
- }
-
- std::string IsValidEventHistogram(base::StringPiece suffix) const {
- return base::StrCat({kIsValidHistogram, ".", suffix});
- }
-
- // Tests for all expected histograms for an event that has a valid timestamp.
- void ExpectValidHistograms(const base::HistogramTester& histogram_tester,
- base::TimeDelta delta,
- base::StringPiece suffix) {
- // Expect both general and per-event histograms to be set.
- histogram_tester.ExpectUniqueSample(kIsValidHistogram, true, 1);
- histogram_tester.ExpectUniqueSample(IsValidEventHistogram(suffix), true, 1);
- if (base::TimeTicks::IsHighResolution()) {
- histogram_tester.ExpectUniqueTimeSample(kHighResHistogram, delta, 1);
- histogram_tester.ExpectUniqueTimeSample(HighResEventHistogram(suffix),
- delta, 1);
- histogram_tester.ExpectTotalCount(kLowResHistogram, 0);
- histogram_tester.ExpectTotalCount(LowResEventHistogram(suffix), 0);
- } else {
- histogram_tester.ExpectUniqueTimeSample(kLowResHistogram, delta, 1);
- histogram_tester.ExpectUniqueTimeSample(LowResEventHistogram(suffix),
- delta, 1);
- histogram_tester.ExpectTotalCount(kHighResHistogram, 0);
- histogram_tester.ExpectTotalCount(HighResEventHistogram(suffix), 0);
- }
- }
-
- // Tests for all expected histograms for an event that has an invalid
- // timestamp.
- void ExpectInvalidHistograms(const base::HistogramTester& histogram_tester,
- base::StringPiece suffix) {
- histogram_tester.ExpectUniqueSample(kIsValidHistogram, false, 1);
- histogram_tester.ExpectUniqueSample(IsValidEventHistogram(suffix), false,
- 1);
- histogram_tester.ExpectTotalCount(kHighResHistogram, 0);
- histogram_tester.ExpectTotalCount(HighResEventHistogram(suffix), 0);
- histogram_tester.ExpectTotalCount(kLowResHistogram, 0);
- histogram_tester.ExpectTotalCount(LowResEventHistogram(suffix), 0);
- }
-
- // Tests that no histograms were recorded for the given event. (For example
- // if it has a type that should be excluded from the metric.)
- void ExpectNoHistograms(const base::HistogramTester& histogram_tester,
- base::StringPiece suffix) {
- histogram_tester.ExpectTotalCount(kIsValidHistogram, 0);
- histogram_tester.ExpectTotalCount(IsValidEventHistogram(suffix), 0);
- histogram_tester.ExpectTotalCount(kHighResHistogram, 0);
- histogram_tester.ExpectTotalCount(HighResEventHistogram(suffix), 0);
- histogram_tester.ExpectTotalCount(kLowResHistogram, 0);
- histogram_tester.ExpectTotalCount(LowResEventHistogram(suffix), 0);
- }
-
- base::test::TaskEnvironment task_environment_{
- base::test::TaskEnvironment::TimeSource::MOCK_TIME};
-};
+// Tests for ComputeEventLatencyOS variants.
-class EventLatencyTickCountTest
- : public EventLatencyTestBase,
- public ::testing::WithParamInterface<EventLatencyTickCountTestCase> {
+class EventLatencyTest : public ::testing::Test {
public:
- EventLatencyTickCountTest() {
- SetEventLatencyTickClockForTesting(&tick_clock_);
- }
+ EventLatencyTest() { SetEventLatencyTickClockForTesting(&tick_clock_); }
- ~EventLatencyTickCountTest() { SetEventLatencyTickClockForTesting(nullptr); }
+ ~EventLatencyTest() override { SetEventLatencyTickClockForTesting(nullptr); }
protected:
void UpdateTickClock(DWORD timestamp) {
@@ -946,17 +924,25 @@ class EventLatencyTickCountTest
base::TimeDelta::FromMilliseconds(timestamp));
}
- // The inherited |task_environment_| mocks the base::TimeTicks clock while
- // |tick_clock_| mocks ::GetTickCount.
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+
+ // |task_environment_| mocks the base::TimeTicks clock while |tick_clock_|
+ // mocks ::GetTickCount.
base::SimpleTestTickClock tick_clock_;
};
-TEST_P(EventLatencyTickCountTest, ComputeEventLatencyOSWinFromTickCount) {
- // Create an event whose timestamp is very close to the max range of
+TEST_F(EventLatencyTest, ComputeEventLatencyOSFromTickCount) {
+ // Create events whose timestamps are very close to the max range of
// ::GetTickCount.
constexpr DWORD timestamp_msec = std::numeric_limits<DWORD>::max() - 10;
-
- const std::string suffix = GetParam().histogram_suffix;
+ constexpr TOUCHINPUT touch_input = {
+ .dwTime = timestamp_msec,
+ };
+ constexpr POINTER_INFO pointer_info = {
+ .dwTime = timestamp_msec,
+ .PerformanceCount = 0UL,
+ };
// This test will create several events with the same timestamp, and change
// the mocked result of ::GetTickCount for each measurement. This makes it
@@ -967,10 +953,16 @@ TEST_P(EventLatencyTickCountTest, ComputeEventLatencyOSWinFromTickCount) {
UpdateTickClock(timestamp_msec + 5);
{
base::HistogramTester histogram_tester;
- ComputeEventLatencyOSWinFromTickCount(GetParam().event_type, timestamp_msec,
+ ComputeEventLatencyOSFromTOUCHINPUT(ET_TOUCH_PRESSED, touch_input,
+ base::TimeTicks::Now());
+ ComputeEventLatencyOSFromPOINTER_INFO(ET_TOUCH_PRESSED, pointer_info,
base::TimeTicks::Now());
- ExpectValidHistograms(histogram_tester,
- base::TimeDelta::FromMilliseconds(5), suffix);
+ histogram_tester.ExpectUniqueSample(
+ "Event.Latency.OS.TOUCH_PRESSED",
+ base::TimeDelta::FromMilliseconds(5).InMicroseconds(), 2);
+ histogram_tester.ExpectUniqueTimeSample(
+ "Event.Latency.OS2.TOUCH_PRESSED", base::TimeDelta::FromMilliseconds(5),
+ 2);
}
// Simulate ::GetTickCount advancing 15 msec, which wraps around past 0.
@@ -980,30 +972,34 @@ TEST_P(EventLatencyTickCountTest, ComputeEventLatencyOSWinFromTickCount) {
UpdateTickClock(wrapped_timestamp_msec);
{
base::HistogramTester histogram_tester;
- ComputeEventLatencyOSWinFromTickCount(GetParam().event_type, timestamp_msec,
+ ComputeEventLatencyOSFromTOUCHINPUT(ET_TOUCH_PRESSED, touch_input,
+ base::TimeTicks::Now());
+ ComputeEventLatencyOSFromPOINTER_INFO(ET_TOUCH_PRESSED, pointer_info,
base::TimeTicks::Now());
- ExpectValidHistograms(histogram_tester,
- base::TimeDelta::FromMilliseconds(15), suffix);
+ histogram_tester.ExpectUniqueSample(
+ "Event.Latency.OS.TOUCH_PRESSED",
+ base::TimeDelta::FromMilliseconds(15).InMicroseconds(), 2);
+ histogram_tester.ExpectUniqueTimeSample(
+ "Event.Latency.OS2.TOUCH_PRESSED",
+ base::TimeDelta::FromMilliseconds(15), 2);
}
- // Simulate an event with a bogus timestamp.
+ // Simulate an event with a bogus timestamp. The delta should be recorded as
+ // 0.
UpdateTickClock(timestamp_msec - 1000);
{
base::HistogramTester histogram_tester;
- ComputeEventLatencyOSWinFromTickCount(GetParam().event_type, timestamp_msec,
+ ComputeEventLatencyOSFromTOUCHINPUT(ET_TOUCH_PRESSED, touch_input,
+ base::TimeTicks::Now());
+ ComputeEventLatencyOSFromPOINTER_INFO(ET_TOUCH_PRESSED, pointer_info,
base::TimeTicks::Now());
- ExpectInvalidHistograms(histogram_tester, suffix);
+ histogram_tester.ExpectUniqueSample("Event.Latency.OS.TOUCH_PRESSED", 0, 2);
+ histogram_tester.ExpectUniqueTimeSample("Event.Latency.OS2.TOUCH_PRESSED",
+ base::TimeDelta(), 2);
}
}
-INSTANTIATE_TEST_SUITE_P(All,
- EventLatencyTickCountTest,
- ::testing::ValuesIn(kEventLatencyTickCountTestCases));
-
-using EventLatencyPerformanceCounterTest = EventLatencyTestBase;
-
-TEST_F(EventLatencyPerformanceCounterTest,
- ComputeEventLatencyOSWinFromPerformanceCounter) {
+TEST_F(EventLatencyTest, ComputeEventLatencyOSFromPerformanceCounter) {
// Make sure there's enough time before Now() to create an event that's
// several minutes old.
task_environment_.AdvanceClock(base::TimeDelta::FromMinutes(5));
@@ -1025,39 +1021,82 @@ TEST_F(EventLatencyPerformanceCounterTest,
// Event created shortly before now.
{
+ const POINTER_INFO pointer_info = {
+ .dwTime = 0U,
+ .PerformanceCount = current_timestamp - ticks_per_second,
+ };
base::HistogramTester histogram_tester;
- ComputeEventLatencyOSWinFromPerformanceCounter(
- ET_TOUCH_PRESSED, current_timestamp - ticks_per_second,
- base::TimeTicks::Now());
- ExpectValidHistograms(histogram_tester, base::TimeDelta::FromSeconds(1),
- "TOUCH_PRESSED");
+ ComputeEventLatencyOSFromPOINTER_INFO(ET_TOUCH_PRESSED, pointer_info,
+ base::TimeTicks::Now());
+ histogram_tester.ExpectUniqueSample(
+ "Event.Latency.OS.TOUCH_PRESSED",
+ base::TimeDelta::FromSeconds(1).InMicroseconds(), 1);
+ histogram_tester.ExpectUniqueTimeSample("Event.Latency.OS2.TOUCH_PRESSED",
+ base::TimeDelta::FromSeconds(1), 1);
}
// Event created several minutes before now (IsValidTimebase should return
- // false).
+ // false). The delta should be recorded as 0.
{
+ const POINTER_INFO pointer_info = {
+ .dwTime = 0U,
+ .PerformanceCount = current_timestamp - 5 * 60 * ticks_per_second,
+ };
base::HistogramTester histogram_tester;
- ComputeEventLatencyOSWinFromPerformanceCounter(
- ET_TOUCH_PRESSED, current_timestamp - 5 * 60 * ticks_per_second,
- base::TimeTicks::Now());
- ExpectInvalidHistograms(histogram_tester, "TOUCH_PRESSED");
+ ComputeEventLatencyOSFromPOINTER_INFO(ET_TOUCH_PRESSED, pointer_info,
+ base::TimeTicks::Now());
+ histogram_tester.ExpectUniqueSample("Event.Latency.OS.TOUCH_PRESSED", 0, 1);
+ histogram_tester.ExpectUniqueTimeSample("Event.Latency.OS2.TOUCH_PRESSED",
+ base::TimeDelta(), 1);
+ }
+
+ // Event created in the future (IsValidTimebase should return false). The
+ // delta should be recorded as 0.
+ {
+ const POINTER_INFO pointer_info = {
+ .dwTime = 0U,
+ .PerformanceCount = current_timestamp + ticks_per_second,
+ };
+ base::HistogramTester histogram_tester;
+ ComputeEventLatencyOSFromPOINTER_INFO(ET_TOUCH_PRESSED, pointer_info,
+ base::TimeTicks::Now());
+ histogram_tester.ExpectUniqueSample("Event.Latency.OS.TOUCH_PRESSED", 0, 1);
+ histogram_tester.ExpectUniqueTimeSample("Event.Latency.OS2.TOUCH_PRESSED",
+ base::TimeDelta(), 1);
}
- // Event created in the future (IsValidTimebase should return false).
+ // Invalid event with no timestamp.
{
+ const POINTER_INFO pointer_info = {
+ .dwTime = 0U,
+ .PerformanceCount = 0UL,
+ };
base::HistogramTester histogram_tester;
- ComputeEventLatencyOSWinFromPerformanceCounter(
- ET_TOUCH_PRESSED, current_timestamp + ticks_per_second,
- base::TimeTicks::Now());
- ExpectInvalidHistograms(histogram_tester, "TOUCH_PRESSED");
+ ComputeEventLatencyOSFromPOINTER_INFO(ET_TOUCH_PRESSED, pointer_info,
+ base::TimeTicks::Now());
+ histogram_tester.ExpectTotalCount("Event.Latency.OS.TOUCH_PRESSED", 0);
+ histogram_tester.ExpectTotalCount("Event.Latency.OS2.TOUCH_PRESSED", 0);
}
- // Event that should not be recorded.
+ // Invalid event with 2 timestamps should take the higher-precision one.
{
+ const DWORD now_msec = 1000;
+ UpdateTickClock(now_msec);
+
+ const POINTER_INFO pointer_info = {
+ // 10 milliseconds ago.
+ .dwTime = now_msec - 10,
+ // 1 second ago.
+ .PerformanceCount = current_timestamp - ticks_per_second,
+ };
base::HistogramTester histogram_tester;
- ComputeEventLatencyOSWinFromPerformanceCounter(
- ET_TOUCH_MOVED, current_timestamp - 10, base::TimeTicks::Now());
- ExpectNoHistograms(histogram_tester, "TOUCH_MOVED");
+ ComputeEventLatencyOSFromPOINTER_INFO(ET_TOUCH_PRESSED, pointer_info,
+ base::TimeTicks::Now());
+ histogram_tester.ExpectUniqueSample(
+ "Event.Latency.OS.TOUCH_PRESSED",
+ base::TimeDelta::FromSeconds(1).InMicroseconds(), 1);
+ histogram_tester.ExpectUniqueTimeSample("Event.Latency.OS2.TOUCH_PRESSED",
+ base::TimeDelta::FromSeconds(1), 1);
}
}
diff --git a/chromium/ui/events/event_utils.cc b/chromium/ui/events/event_utils.cc
index 93045d6ba57..98a61ac4fa5 100644
--- a/chromium/ui/events/event_utils.cc
+++ b/chromium/ui/events/event_utils.cc
@@ -10,120 +10,25 @@
#include "base/check.h"
#include "base/metrics/histogram_macros.h"
-#include "base/no_destructor.h"
#include "base/notreached.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/time/tick_clock.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/base_event_utils.h"
+#if defined(OS_WIN)
+#include "ui/events/win/events_win_utils.h"
+#endif
+
namespace ui {
namespace {
int g_custom_event_types = ET_LAST;
-#if defined(OS_WIN)
-
-#define UMA_HISTOGRAM_WIN_EVENT_LATENCY_TIMES(name, sample) \
+#define UMA_HISTOGRAM_EVENT_LATENCY_TIMES(name, sample) \
UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, \
base::TimeDelta::FromMilliseconds(1), \
- base::TimeDelta::FromMilliseconds(100000), 100)
-
-class GetTickCountClock : public base::TickClock {
- public:
- GetTickCountClock() = default;
- ~GetTickCountClock() override = default;
-
- base::TimeTicks NowTicks() const override {
- return base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(::GetTickCount());
- }
-};
-
-const base::TickClock* g_tick_count_clock = nullptr;
-
-// Logs experimental Event.Latency.OS_WIN.* metrics to parallel
-// Event.Latency.OS.*.
-// TODO(crbug.com/1189656): Check that these are accurate enough to replace
-// Event.Latency.OS.*.
-void ComputeEventLatencyOSWin(ui::EventType event_type,
- base::TimeTicks event_time,
- base::TimeTicks current_time) {
- // Check that the event doesn't come from a device giving bogus timestamps.
- // On most platforms this is done inside EventTimeFromNative.
- const bool is_valid = IsValidTimebase(current_time, event_time);
- UMA_HISTOGRAM_BOOLEAN("Event.Latency.OS_WIN_IS_VALID", is_valid);
- switch (event_type) {
- case ET_KEY_PRESSED:
- UMA_HISTOGRAM_BOOLEAN("Event.Latency.OS_WIN_IS_VALID.KEY_PRESSED",
- is_valid);
- break;
- case ET_MOUSE_PRESSED:
- UMA_HISTOGRAM_BOOLEAN("Event.Latency.OS_WIN_IS_VALID.MOUSE_PRESSED",
- is_valid);
- break;
- case ET_TOUCH_PRESSED:
- UMA_HISTOGRAM_BOOLEAN("Event.Latency.OS_WIN_IS_VALID.TOUCH_PRESSED",
- is_valid);
- break;
- default:
- // Caller should have filtered out unhandled events.
- NOTREACHED();
- break;
- }
- if (!is_valid)
- return;
-
- const base::TimeDelta delta = current_time - event_time;
-
- if (base::TimeTicks::IsHighResolution()) {
- UMA_HISTOGRAM_WIN_EVENT_LATENCY_TIMES("Event.Latency.OS_WIN.HIGH_RES",
- delta);
- switch (event_type) {
- case ET_KEY_PRESSED:
- UMA_HISTOGRAM_WIN_EVENT_LATENCY_TIMES(
- "Event.Latency.OS_WIN.HIGH_RES.KEY_PRESSED", delta);
- break;
- case ET_MOUSE_PRESSED:
- UMA_HISTOGRAM_WIN_EVENT_LATENCY_TIMES(
- "Event.Latency.OS_WIN.HIGH_RES.MOUSE_PRESSED", delta);
- break;
- case ET_TOUCH_PRESSED:
- UMA_HISTOGRAM_WIN_EVENT_LATENCY_TIMES(
- "Event.Latency.OS_WIN.HIGH_RES.TOUCH_PRESSED", delta);
- break;
- default:
- // Caller should have filtered out unhandled events.
- NOTREACHED();
- break;
- }
- } else {
- UMA_HISTOGRAM_WIN_EVENT_LATENCY_TIMES("Event.Latency.OS_WIN.LOW_RES",
- delta);
- switch (event_type) {
- case ET_KEY_PRESSED:
- UMA_HISTOGRAM_WIN_EVENT_LATENCY_TIMES(
- "Event.Latency.OS_WIN.LOW_RES.KEY_PRESSED", delta);
- break;
- case ET_MOUSE_PRESSED:
- UMA_HISTOGRAM_WIN_EVENT_LATENCY_TIMES(
- "Event.Latency.OS_WIN.LOW_RES.MOUSE_PRESSED", delta);
- break;
- case ET_TOUCH_PRESSED:
- UMA_HISTOGRAM_WIN_EVENT_LATENCY_TIMES(
- "Event.Latency.OS_WIN.LOW_RES.TOUCH_PRESSED", delta);
- break;
- default:
- // Caller should have filtered out unhandled events.
- NOTREACHED();
- break;
- }
- }
-}
-
-#endif // OS_WIN
+ base::TimeDelta::FromMinutes(1), 50)
} // namespace
@@ -190,86 +95,22 @@ display::Display::TouchSupport GetInternalDisplayTouchSupport() {
return display::Display::TouchSupport::UNAVAILABLE;
}
-#if defined(OS_WIN)
-void SetEventLatencyTickClockForTesting(const base::TickClock* clock) {
- g_tick_count_clock = clock;
-}
-
-void ComputeEventLatencyOSWinFromTickCount(ui::EventType event_type,
- DWORD event_time,
- base::TimeTicks current_time) {
- static const base::NoDestructor<GetTickCountClock> default_tick_count_clock;
- if (!g_tick_count_clock)
- g_tick_count_clock = default_tick_count_clock.get();
-
- if (event_type != ET_KEY_PRESSED && event_type != ET_MOUSE_PRESSED &&
- event_type != ET_TOUCH_PRESSED) {
- // Only log this metric for events that indicate strong user intent (eg.
- // clicks and keypresses), not every move event. This will detect jank that
- // causes the most user pain.
- return;
- }
-
- base::TimeTicks current_tick_count = g_tick_count_clock->NowTicks();
+void ComputeEventLatencyOS(const PlatformEvent& native_event) {
+ base::TimeTicks current_time = EventTimeForNow();
base::TimeTicks time_stamp =
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(event_time);
- // Check if the 32-bit tick count wrapped around after the event.
- if (current_tick_count < time_stamp) {
- // ::GetTickCount returns an unsigned 32-bit value, which will fit into the
- // signed 64-bit base::TimeTicks.
- current_tick_count +=
- base::TimeDelta::FromMilliseconds(std::numeric_limits<DWORD>::max());
- }
-
- // |event_time| is from the GetTickCount clock, which has a different 0-point
- // from |current_time| (which uses either the high-resolution timer or
- // timeGetTime). Adjust it to be compatible.
- //
- // This offset will vary by up to ~16 msec because it depends on when exactly
- // we sample the high-resolution clock. It would be more consistent to
- // calculate one offset at the start of the program and apply it every time,
- // but that consistency isn't needed for jank investigations and then we
- // would have to adjust for clock drift.
- const base::TimeDelta time_source_offset = current_time - current_tick_count;
- time_stamp += time_source_offset;
-
- ComputeEventLatencyOSWin(event_type, time_stamp, current_time);
-}
-
-void ComputeEventLatencyOSWinFromPerformanceCounter(
- ui::EventType event_type,
- UINT64 event_time,
- base::TimeTicks current_time) {
- if (event_type != ET_TOUCH_PRESSED) {
- // Only log this metric for events that indicate strong user intent (ie.
- // touch press), not every touch move event. This will detect jank that
- // causes the most user pain.
- return;
- }
- if (!base::TimeTicks::IsHighResolution()) {
- // The tick clock will be incompatible with |event_time|.
- return;
- }
- ComputeEventLatencyOSWin(
- event_type, base::TimeTicks::FromQPCValue(event_time), current_time);
+ EventLatencyTimeFromNative(native_event, current_time);
+ EventType type = EventTypeFromNative(native_event);
+ ComputeEventLatencyOS(type, time_stamp, current_time);
}
-#endif
-void ComputeEventLatencyOS(const PlatformEvent& native_event) {
- base::TimeTicks current_time = EventTimeForNow();
- base::TimeTicks time_stamp = EventTimeFromNative(native_event);
+void ComputeEventLatencyOS(EventType type,
+ base::TimeTicks time_stamp,
+ base::TimeTicks current_time) {
base::TimeDelta delta = current_time - time_stamp;
- EventType type = EventTypeFromNative(native_event);
-#if defined(OS_WIN)
- // Also record windows-only metrics.
- //
- // On Windows EventTimeFromNative returns the current time instead of the
- // timestamp from |native_event|, which makes it useless for latency metrics,
- // so retrieve the time stamp directly.
- ComputeEventLatencyOSWinFromTickCount(type, native_event.time, current_time);
-#endif
-
+ // TODO(crbug.com/1189656): Remove the legacy Event.Latency.OS.* histograms
+ // after M92 (which introduced Event.Latency.OS2.*) has been replaced in the
+ // stable channel.
switch (type) {
#if defined(OS_APPLE)
// On Mac, ET_SCROLL and ET_MOUSEWHEEL represent the same class of events.
@@ -279,42 +120,86 @@ void ComputeEventLatencyOS(const PlatformEvent& native_event) {
UMA_HISTOGRAM_CUSTOM_COUNTS(
"Event.Latency.OS.MOUSE_WHEEL",
base::saturated_cast<int>(delta.InMicroseconds()), 1, 1000000, 50);
+ UMA_HISTOGRAM_EVENT_LATENCY_TIMES("Event.Latency.OS2.MOUSE_WHEEL", delta);
return;
case ET_TOUCH_MOVED:
UMA_HISTOGRAM_CUSTOM_COUNTS(
"Event.Latency.OS.TOUCH_MOVED",
base::saturated_cast<int>(delta.InMicroseconds()), 1, 1000000, 50);
+ UMA_HISTOGRAM_EVENT_LATENCY_TIMES("Event.Latency.OS2.TOUCH_MOVED", delta);
return;
case ET_TOUCH_PRESSED:
UMA_HISTOGRAM_CUSTOM_COUNTS(
"Event.Latency.OS.TOUCH_PRESSED",
base::saturated_cast<int>(delta.InMicroseconds()), 1, 1000000, 50);
+ UMA_HISTOGRAM_EVENT_LATENCY_TIMES("Event.Latency.OS2.TOUCH_PRESSED",
+ delta);
return;
case ET_TOUCH_RELEASED:
UMA_HISTOGRAM_CUSTOM_COUNTS(
"Event.Latency.OS.TOUCH_RELEASED",
base::saturated_cast<int>(delta.InMicroseconds()), 1, 1000000, 50);
+ UMA_HISTOGRAM_EVENT_LATENCY_TIMES("Event.Latency.OS2.TOUCH_RELEASED",
+ delta);
return;
case ET_TOUCH_CANCELLED:
UMA_HISTOGRAM_CUSTOM_COUNTS(
"Event.Latency.OS.TOUCH_CANCELLED",
base::saturated_cast<int>(delta.InMicroseconds()), 1, 1000000, 50);
+ UMA_HISTOGRAM_EVENT_LATENCY_TIMES("Event.Latency.OS2.TOUCH_CANCELLED",
+ delta);
return;
case ET_KEY_PRESSED:
UMA_HISTOGRAM_CUSTOM_COUNTS(
"Event.Latency.OS.KEY_PRESSED",
base::saturated_cast<int>(delta.InMicroseconds()), 1, 1000000, 50);
+ UMA_HISTOGRAM_EVENT_LATENCY_TIMES("Event.Latency.OS2.KEY_PRESSED", delta);
return;
case ET_MOUSE_PRESSED:
UMA_HISTOGRAM_CUSTOM_COUNTS(
"Event.Latency.OS.MOUSE_PRESSED",
base::saturated_cast<int>(delta.InMicroseconds()), 1, 1000000, 50);
+ UMA_HISTOGRAM_EVENT_LATENCY_TIMES("Event.Latency.OS2.MOUSE_PRESSED",
+ delta);
return;
default:
return;
}
}
+#if defined(OS_WIN)
+
+void ComputeEventLatencyOSFromTOUCHINPUT(EventType event_type,
+ TOUCHINPUT touch_input,
+ base::TimeTicks current_time) {
+ base::TimeTicks time_stamp =
+ EventLatencyTimeFromTickClock(touch_input.dwTime, current_time);
+ ComputeEventLatencyOS(event_type, time_stamp, current_time);
+}
+
+void ComputeEventLatencyOSFromPOINTER_INFO(EventType event_type,
+ POINTER_INFO pointer_info,
+ base::TimeTicks current_time) {
+ base::TimeTicks time_stamp;
+ if (pointer_info.PerformanceCount) {
+ if (!base::TimeTicks::IsHighResolution()) {
+ // The tick clock will be incompatible with |event_time|.
+ return;
+ }
+ time_stamp =
+ EventLatencyTimeFromPerformanceCounter(pointer_info.PerformanceCount);
+ } else if (pointer_info.dwTime) {
+ time_stamp =
+ EventLatencyTimeFromTickClock(pointer_info.dwTime, current_time);
+ } else {
+ // Bad POINTER_INFO with no timestamp.
+ return;
+ }
+ ComputeEventLatencyOS(event_type, time_stamp, current_time);
+}
+
+#endif // defined(OS_WIN)
+
void ConvertEventLocationToTargetWindowLocation(
const gfx::Point& target_window_origin,
const gfx::Point& current_window_origin,
diff --git a/chromium/ui/events/event_utils.h b/chromium/ui/events/event_utils.h
index e60e7d58cba..10311a01e57 100644
--- a/chromium/ui/events/event_utils.h
+++ b/chromium/ui/events/event_utils.h
@@ -33,7 +33,6 @@ class Vector2d;
} // namespace gfx
namespace base {
-class TickClock;
class TimeTicks;
}
@@ -87,6 +86,15 @@ EVENTS_EXPORT int EventFlagsFromNative(const PlatformEvent& native_event);
EVENTS_EXPORT base::TimeTicks EventTimeFromNative(
const PlatformEvent& native_event);
+// Get the timestamp to use for latency metrics from |native_event|.
+// |current_time| is a timestamp returned by EventTimeForNow which will be
+// compared to the |native_event| timestamp to calculate latency. This is
+// different from EventTimeFromNative because on some platforms (eg. Windows)
+// EventTimeFromNative returns a synthesized timestamp.
+EVENTS_EXPORT base::TimeTicks EventLatencyTimeFromNative(
+ const PlatformEvent& native_event,
+ base::TimeTicks current_time);
+
// Get the location from a native event. The coordinate system of the resultant
// |Point| has the origin at top-left of the "root window". The nature of
// this "root window" and how it maps to platform-specific drawing surfaces is
@@ -169,25 +177,23 @@ EVENTS_EXPORT display::Display::TouchSupport GetInternalDisplayTouchSupport();
EVENTS_EXPORT void ComputeEventLatencyOS(const PlatformEvent& native_event);
+EVENTS_EXPORT void ComputeEventLatencyOS(ui::EventType type,
+ base::TimeTicks time_stamp,
+ base::TimeTicks current_time);
+
#if defined(OS_WIN)
-// Makes ComputeEventLatencyOSWinFromTickCount call the given |clock| to find
-// the current time ticks to compare to an MSG timestamp. If |clock| is nullptr,
-// it will call ::GetTickCount, which is the default.
-EVENTS_EXPORT void SetEventLatencyTickClockForTesting(
- const base::TickClock* clock);
-
-// Records Event.Latency.OS_WIN.* metrics for events whose timestamp comes from
-// ::GetTickCount (such as an MSG).
-EVENTS_EXPORT void ComputeEventLatencyOSWinFromTickCount(
+// Like ComputeEventLatencyOS, but for events whose timestamp comes from a
+// TOUCHINPUT structure instead of PlatformEvent.
+EVENTS_EXPORT void ComputeEventLatencyOSFromTOUCHINPUT(
ui::EventType event_type,
- DWORD event_time,
+ TOUCHINPUT touch_input,
base::TimeTicks current_time);
-// Records Event.Latency.OS_WIN.* metrics for events whose timestamp comes from
-// a Performance Counter (such as POINTER_INFO).
-EVENTS_EXPORT void ComputeEventLatencyOSWinFromPerformanceCounter(
+// Like ComputeEventLatencyOS, but for events whose timestamp comes from a
+// POINTER_INFO structure instead of PlatformEvent.
+EVENTS_EXPORT void ComputeEventLatencyOSFromPOINTER_INFO(
ui::EventType event_type,
- UINT64 event_time,
+ POINTER_INFO pointer_info,
base::TimeTicks current_time);
EVENTS_EXPORT int GetModifiersFromKeyState();
diff --git a/chromium/ui/events/events_default.cc b/chromium/ui/events/events_default.cc
index e48fc5ca90f..aed4891fb07 100644
--- a/chromium/ui/events/events_default.cc
+++ b/chromium/ui/events/events_default.cc
@@ -15,6 +15,11 @@ base::TimeTicks EventTimeFromNative(const PlatformEvent& native_event) {
return event->time_stamp();
}
+base::TimeTicks EventLatencyTimeFromNative(const PlatformEvent& native_event,
+ base::TimeTicks current_time) {
+ return EventTimeFromNative(native_event);
+}
+
int EventFlagsFromNative(const PlatformEvent& native_event) {
const ui::Event* event = static_cast<const ui::Event*>(native_event);
return event->flags();
diff --git a/chromium/ui/events/events_stub.cc b/chromium/ui/events/events_stub.cc
index 710c38411dd..badd355fab5 100644
--- a/chromium/ui/events/events_stub.cc
+++ b/chromium/ui/events/events_stub.cc
@@ -32,6 +32,11 @@ base::TimeTicks EventTimeFromNative(const PlatformEvent& native_event) {
return base::TimeTicks();
}
+base::TimeTicks EventLatencyTimeFromNative(const PlatformEvent& native_event,
+ base::TimeTicks current_time) {
+ return EventTimeFromNative(native_event);
+}
+
gfx::PointF EventLocationFromNative(const PlatformEvent& native_event) {
NOTIMPLEMENTED();
return gfx::PointF();
diff --git a/chromium/ui/events/fraction_of_time_without_user_input_recorder.h b/chromium/ui/events/fraction_of_time_without_user_input_recorder.h
index daa3035c400..82b7688d727 100644
--- a/chromium/ui/events/fraction_of_time_without_user_input_recorder.h
+++ b/chromium/ui/events/fraction_of_time_without_user_input_recorder.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_IDLE_FRACTION_RECORDER_H_
-#define UI_EVENTS_IDLE_FRACTION_RECORDER_H_
+#ifndef UI_EVENTS_FRACTION_OF_TIME_WITHOUT_USER_INPUT_RECORDER_H_
+#define UI_EVENTS_FRACTION_OF_TIME_WITHOUT_USER_INPUT_RECORDER_H_
#include "base/time/time.h"
#include "ui/events/events_base_export.h"
@@ -48,4 +48,4 @@ class EVENTS_BASE_EXPORT FractionOfTimeWithoutUserInputRecorder {
} // namespace ui
-#endif // UI_EVENTS_IDLE_FRACTION_RECORDER_H_
+#endif // UI_EVENTS_FRACTION_OF_TIME_WITHOUT_USER_INPUT_RECORDER_H_
diff --git a/chromium/ui/events/gesture_detection/filtered_gesture_provider.cc b/chromium/ui/events/gesture_detection/filtered_gesture_provider.cc
index efde83eae72..9b32920fe2d 100644
--- a/chromium/ui/events/gesture_detection/filtered_gesture_provider.cc
+++ b/chromium/ui/events/gesture_detection/filtered_gesture_provider.cc
@@ -69,6 +69,10 @@ void FilteredGestureProvider::ResetGestureHandlingState() {
gesture_filter_.ResetGestureHandlingState();
}
+void FilteredGestureProvider::SendSynthesizedEndEvents() {
+ gesture_provider_->SendSynthesizedEndEvents();
+}
+
void FilteredGestureProvider::ResetDetection() {
gesture_provider_->ResetDetection();
}
diff --git a/chromium/ui/events/gesture_detection/filtered_gesture_provider.h b/chromium/ui/events/gesture_detection/filtered_gesture_provider.h
index 3595c8aeb67..447a1490202 100644
--- a/chromium/ui/events/gesture_detection/filtered_gesture_provider.h
+++ b/chromium/ui/events/gesture_detection/filtered_gesture_provider.h
@@ -51,6 +51,9 @@ class GESTURE_DETECTION_EXPORT FilteredGestureProvider final
void ResetGestureHandlingState();
+ // Synthesizes and propagates gesture end events.
+ void SendSynthesizedEndEvents();
+
// Methods delegated to |gesture_provider_|.
void ResetDetection();
void SetMultiTouchZoomSupportEnabled(bool enabled);
diff --git a/chromium/ui/events/gesture_detection/gesture_provider.cc b/chromium/ui/events/gesture_detection/gesture_provider.cc
index d451fcdcc0e..3aa2a18d64a 100644
--- a/chromium/ui/events/gesture_detection/gesture_provider.cc
+++ b/chromium/ui/events/gesture_detection/gesture_provider.cc
@@ -163,26 +163,7 @@ class GestureProvider::GestureListenerImpl : public ScaleGestureListener,
}
}
- void Send(GestureEventData gesture) {
- DCHECK(!gesture.time.is_null());
- // The only valid events that should be sent without an active touch
- // sequence are SHOW_PRESS, TAP and TAP_CANCEL, potentially triggered by
- // the double-tap delay timing out or being cancelled.
- DCHECK(!current_down_action_event_time_.is_null() ||
- gesture.type() == ET_GESTURE_TAP ||
- gesture.type() == ET_GESTURE_SHOW_PRESS ||
- gesture.type() == ET_GESTURE_TAP_CANCEL ||
- gesture.type() == ET_GESTURE_BEGIN ||
- gesture.type() == ET_GESTURE_END);
-
- if (gesture.primary_tool_type == MotionEvent::ToolType::UNKNOWN ||
- gesture.primary_tool_type == MotionEvent::ToolType::FINGER) {
- gesture.details.set_bounding_box(
- ClampBoundingBox(gesture.details.bounding_box_f(),
- config_.min_gesture_bounds_length,
- config_.max_gesture_bounds_length));
- }
-
+ void UpdateStateForEventPost(GestureEventData gesture) {
switch (gesture.type()) {
case ET_GESTURE_LONG_PRESS:
DCHECK(!IsScaleGestureDetectionInProgress());
@@ -197,8 +178,6 @@ class GestureProvider::GestureListenerImpl : public ScaleGestureListener,
break;
case ET_GESTURE_SCROLL_END:
DCHECK(scroll_event_sent_);
- if (pinch_event_sent_)
- Send(GestureEventData(ET_GESTURE_PINCH_END, gesture));
scroll_event_sent_ = false;
break;
case ET_SCROLL_FLING_START:
@@ -207,10 +186,6 @@ class GestureProvider::GestureListenerImpl : public ScaleGestureListener,
break;
case ET_GESTURE_PINCH_BEGIN:
DCHECK(!pinch_event_sent_);
- if (!scroll_event_sent_ &&
- !scale_gesture_detector_.InAnchoredScaleMode()) {
- Send(GestureEventData(ET_GESTURE_SCROLL_BEGIN, gesture));
- }
pinch_event_sent_ = true;
break;
case ET_GESTURE_PINCH_END:
@@ -227,9 +202,77 @@ class GestureProvider::GestureListenerImpl : public ScaleGestureListener,
default:
break;
};
+ }
+
+ // `should_update` indicates whether sending `gesture` should update the
+ // internal states.
+ void SendImpl(GestureEventData gesture, bool should_update) {
+ DCHECK(!gesture.time.is_null());
+ // The only valid events that should be sent without an active touch
+ // sequence are SHOW_PRESS, TAP and TAP_CANCEL, potentially triggered by
+ // the double-tap delay timing out or being cancelled.
+ DCHECK(!current_down_action_event_time_.is_null() ||
+ gesture.type() == ET_GESTURE_TAP ||
+ gesture.type() == ET_GESTURE_SHOW_PRESS ||
+ gesture.type() == ET_GESTURE_TAP_CANCEL ||
+ gesture.type() == ET_GESTURE_BEGIN ||
+ gesture.type() == ET_GESTURE_END);
+
+ if (gesture.primary_tool_type == MotionEvent::ToolType::UNKNOWN ||
+ gesture.primary_tool_type == MotionEvent::ToolType::FINGER) {
+ gesture.details.set_bounding_box(ClampBoundingBox(
+ gesture.details.bounding_box_f(), config_.min_gesture_bounds_length,
+ config_.max_gesture_bounds_length));
+ }
+
+ // Sending one gesture event may trigger propagation of another.
+ switch (gesture.type()) {
+ case ET_GESTURE_SCROLL_END:
+ DCHECK(scroll_event_sent_);
+ if (pinch_event_sent_)
+ SendImpl(GestureEventData(ET_GESTURE_PINCH_END, gesture),
+ should_update);
+ break;
+ case ET_GESTURE_PINCH_BEGIN:
+ DCHECK(!pinch_event_sent_);
+ if (!scroll_event_sent_ &&
+ !scale_gesture_detector_.InAnchoredScaleMode()) {
+ SendImpl(GestureEventData(ET_GESTURE_SCROLL_BEGIN, gesture),
+ should_update);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (should_update) {
+ UpdateStateForEventPost(gesture);
+ GestureTouchUMAHistogram::RecordGestureEvent(gesture);
+ }
client_->OnGestureEvent(gesture);
- GestureTouchUMAHistogram::RecordGestureEvent(gesture);
+ }
+
+ void Send(GestureEventData gesture) {
+ SendImpl(gesture, /*should_update=*/true);
+ }
+
+ void SendSynthesizedEndEvents() {
+ MotionEventGeneric generic_cancel_event(MotionEvent::Action::CANCEL,
+ base::TimeTicks::Now(),
+ PointerProperties());
+
+ // Sending the synthesized end events should not update the internal states.
+ // Because this function may be called when a new event handler replaces the
+ // old one. In that scenario, the old event handler is informed of the
+ // gesture end through the synthesized end events while the new handler
+ // should handle the incoming gestures.
+ if (scroll_event_sent_) {
+ SendImpl(CreateGesture(ET_GESTURE_SCROLL_END, generic_cancel_event),
+ /*should_update=*/false);
+ }
+ SendImpl(CreateGesture(ET_GESTURE_END, generic_cancel_event),
+ /*should_update=*/false);
}
// ScaleGestureListener implementation.
@@ -254,17 +297,14 @@ class GestureProvider::GestureListenerImpl : public ScaleGestureListener,
bool first_scale = false;
if (!pinch_event_sent_) {
first_scale = true;
- Send(CreateGesture(ET_GESTURE_PINCH_BEGIN,
- e.GetPointerId(),
- e.GetToolType(),
- detector.GetEventTime(),
- detector.GetFocusX(),
- detector.GetFocusY(),
- detector.GetFocusX() + e.GetRawOffsetX(),
- detector.GetFocusY() + e.GetRawOffsetY(),
- e.GetPointerCount(),
- GetBoundingBox(e, ET_GESTURE_PINCH_BEGIN),
- e.GetFlags()));
+ GestureEventDetails details(ET_GESTURE_PINCH_BEGIN);
+ details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
+ Send(CreateGesture(
+ details, e.GetPointerId(), e.GetToolType(), detector.GetEventTime(),
+ detector.GetFocusX(), detector.GetFocusY(),
+ detector.GetFocusX() + e.GetRawOffsetX(),
+ detector.GetFocusY() + e.GetRawOffsetY(), e.GetPointerCount(),
+ GetBoundingBox(e, ET_GESTURE_PINCH_BEGIN), e.GetFlags()));
}
if (std::abs(detector.GetCurrentSpan() - detector.GetPreviousSpan()) <
@@ -555,33 +595,6 @@ class GestureProvider::GestureListenerImpl : public ScaleGestureListener,
0U);
}
- GestureEventData CreateGesture(EventType type,
- int motion_event_id,
- MotionEvent::ToolType primary_tool_type,
- base::TimeTicks time,
- float x,
- float y,
- float raw_x,
- float raw_y,
- size_t touch_point_count,
- const gfx::RectF& bounding_box,
- int flags) const {
- GestureEventDetails details(type);
- details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
- return GestureEventData(details,
- motion_event_id,
- primary_tool_type,
- time,
- x,
- y,
- raw_x,
- raw_y,
- touch_point_count,
- bounding_box,
- flags,
- 0U);
- }
-
GestureEventData CreateGesture(const GestureEventDetails& details,
const MotionEvent& event) const {
return GestureEventData(details, event.GetPointerId(), event.GetToolType(),
@@ -865,6 +878,10 @@ bool GestureProvider::IsDoubleTapInProgress() const {
return gesture_listener_->IsDoubleTapInProgress();
}
+void GestureProvider::SendSynthesizedEndEvents() {
+ gesture_listener_->SendSynthesizedEndEvents();
+}
+
bool GestureProvider::CanHandle(const MotionEvent& event) const {
// Aura requires one cancel event per touch point, whereas Android requires
// one cancel event per touch sequence. Thus we need to allow extra cancel
@@ -885,16 +902,13 @@ void GestureProvider::OnTouchEventHandlingBegin(const MotionEvent& event) {
case MotionEvent::Action::POINTER_DOWN:
if (gesture_begin_end_types_enabled_) {
const int action_index = event.GetActionIndex();
+ GestureEventDetails details(ET_GESTURE_BEGIN);
+ details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
gesture_listener_->Send(gesture_listener_->CreateGesture(
- ET_GESTURE_BEGIN,
- event.GetPointerId(),
- event.GetToolType(),
- event.GetEventTime(),
- event.GetX(action_index),
- event.GetY(action_index),
- event.GetRawX(action_index),
- event.GetRawY(action_index),
- event.GetPointerCount(),
+ details, event.GetPointerId(), event.GetToolType(),
+ event.GetEventTime(), event.GetX(action_index),
+ event.GetY(action_index), event.GetRawX(action_index),
+ event.GetRawY(action_index), event.GetPointerCount(),
gesture_listener_->GetBoundingBox(event, ET_GESTURE_BEGIN),
event.GetFlags()));
}
diff --git a/chromium/ui/events/gesture_detection/gesture_provider.h b/chromium/ui/events/gesture_detection/gesture_provider.h
index f4c7bcccb8a..01c36018b83 100644
--- a/chromium/ui/events/gesture_detection/gesture_provider.h
+++ b/chromium/ui/events/gesture_detection/gesture_provider.h
@@ -96,6 +96,9 @@ class GESTURE_DETECTION_EXPORT GestureProvider {
// double-tap drag zoom).
bool IsDoubleTapInProgress() const;
+ // Synthesizes and propagates gesture end events.
+ void SendSynthesizedEndEvents();
+
// May be NULL if there is no currently active touch sequence.
const ui::MotionEvent* current_down_event() const {
return current_down_event_.get();
diff --git a/chromium/ui/events/gesture_detection/gesture_touch_uma_histogram.h b/chromium/ui/events/gesture_detection/gesture_touch_uma_histogram.h
index c14ef2c2e96..66ee6e5da71 100644
--- a/chromium/ui/events/gesture_detection/gesture_touch_uma_histogram.h
+++ b/chromium/ui/events/gesture_detection/gesture_touch_uma_histogram.h
@@ -5,7 +5,6 @@
#ifndef UI_EVENTS_GESTURE_DETECTION_GESTURE_TOUCH_UMA_HISTOGRAM_H_
#define UI_EVENTS_GESTURE_DETECTION_GESTURE_TOUCH_UMA_HISTOGRAM_H_
-#include "base/time/time.h"
#include "ui/events/gesture_detection/gesture_detection_export.h"
#include "ui/events/gesture_detection/gesture_event_data.h"
#include "ui/events/gesture_detection/motion_event.h"
diff --git a/chromium/ui/events/gesture_detection/motion_event_generic.h b/chromium/ui/events/gesture_detection/motion_event_generic.h
index c672eec56ae..e9ae85c83e2 100644
--- a/chromium/ui/events/gesture_detection/motion_event_generic.h
+++ b/chromium/ui/events/gesture_detection/motion_event_generic.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_GESTURE_DETECTION_UI_MOTION_EVENT_GENERIC_H_
-#define UI_EVENTS_GESTURE_DETECTION_UI_MOTION_EVENT_GENERIC_H_
+#ifndef UI_EVENTS_GESTURE_DETECTION_MOTION_EVENT_GENERIC_H_
+#define UI_EVENTS_GESTURE_DETECTION_MOTION_EVENT_GENERIC_H_
#include <stddef.h>
#include <stdint.h>
@@ -137,4 +137,4 @@ class GESTURE_DETECTION_EXPORT MotionEventGeneric : public MotionEvent {
} // namespace ui
-#endif // UI_EVENTS_GESTURE_DETECTION_UI_MOTION_EVENT_GENERIC_H_
+#endif // UI_EVENTS_GESTURE_DETECTION_MOTION_EVENT_GENERIC_H_
diff --git a/chromium/ui/events/gesture_event_details.h b/chromium/ui/events/gesture_event_details.h
index 668f07489eb..65c474a0688 100644
--- a/chromium/ui/events/gesture_event_details.h
+++ b/chromium/ui/events/gesture_event_details.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_GESTURE_DETECTION_GESTURE_EVENT_DETAILS_H_
-#define UI_EVENTS_GESTURE_DETECTION_GESTURE_EVENT_DETAILS_H_
+#ifndef UI_EVENTS_GESTURE_EVENT_DETAILS_H_
+#define UI_EVENTS_GESTURE_EVENT_DETAILS_H_
#include <string.h>
@@ -237,4 +237,4 @@ struct EVENTS_BASE_EXPORT GestureEventDetails {
} // namespace ui
-#endif // UI_EVENTS_GESTURE_DETECTION_GESTURE_EVENT_DETAILS_H_
+#endif // UI_EVENTS_GESTURE_EVENT_DETAILS_H_
diff --git a/chromium/ui/events/gestures/OWNERS b/chromium/ui/events/gestures/OWNERS
index 85a182d6324..854bbfa6ab0 100644
--- a/chromium/ui/events/gestures/OWNERS
+++ b/chromium/ui/events/gestures/OWNERS
@@ -1,3 +1,3 @@
rjkroege@chromium.org
sadrul@chromium.org
-flackr@chromium.org \ No newline at end of file
+flackr@chromium.org
diff --git a/chromium/ui/events/gestures/gesture_provider_aura.cc b/chromium/ui/events/gestures/gesture_provider_aura.cc
index eb43a56ceda..0efa57213c6 100644
--- a/chromium/ui/events/gestures/gesture_provider_aura.cc
+++ b/chromium/ui/events/gestures/gesture_provider_aura.cc
@@ -71,6 +71,10 @@ void GestureProviderAura::ResetGestureHandlingState() {
filtered_gesture_provider_.ResetGestureHandlingState();
}
+void GestureProviderAura::SendSynthesizedEndEvents() {
+ filtered_gesture_provider_.SendSynthesizedEndEvents();
+}
+
void GestureProviderAura::OnGestureEvent(const GestureEventData& gesture) {
std::unique_ptr<ui::GestureEvent> event(
new ui::GestureEvent(gesture.x, gesture.y, gesture.flags,
diff --git a/chromium/ui/events/gestures/gesture_provider_aura.h b/chromium/ui/events/gestures/gesture_provider_aura.h
index 1cf2b3a47dc..07ad70e2ad9 100644
--- a/chromium/ui/events/gestures/gesture_provider_aura.h
+++ b/chromium/ui/events/gestures/gesture_provider_aura.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_GESTURE_DETECTION_UI_GESTURE_PROVIDER_H_
-#define UI_EVENTS_GESTURE_DETECTION_UI_GESTURE_PROVIDER_H_
+#ifndef UI_EVENTS_GESTURES_GESTURE_PROVIDER_AURA_H_
+#define UI_EVENTS_GESTURES_GESTURE_PROVIDER_AURA_H_
#include <stdint.h>
@@ -51,6 +51,9 @@ class EVENTS_EXPORT GestureProviderAura : public GestureProviderClient {
void ResetGestureHandlingState();
+ // Synthesizes gesture end events and sends to the associated consumer.
+ void SendSynthesizedEndEvents();
+
// GestureProviderClient implementation
void OnGestureEvent(const GestureEventData& gesture) override;
bool RequiresDoubleTapGestureEvents() const override;
@@ -71,4 +74,4 @@ class EVENTS_EXPORT GestureProviderAura : public GestureProviderClient {
} // namespace ui
-#endif // UI_EVENTS_GESTURE_DETECTION_UI_GESTURE_PROVIDER_H_
+#endif // UI_EVENTS_GESTURES_GESTURE_PROVIDER_AURA_H_
diff --git a/chromium/ui/events/gestures/gesture_recognizer.h b/chromium/ui/events/gestures/gesture_recognizer.h
index c7878fdf1ad..df4f3df6684 100644
--- a/chromium/ui/events/gestures/gesture_recognizer.h
+++ b/chromium/ui/events/gestures/gesture_recognizer.h
@@ -107,6 +107,13 @@ class EVENTS_EXPORT GestureRecognizer {
// and must be cleaned up appropriately by the caller.
virtual void RemoveGestureEventHelper(GestureEventHelper* helper) = 0;
+ // Returns whether `consumer` has active touch or not.
+ virtual bool DoesConsumerHaveActiveTouch(GestureConsumer* consumer) const = 0;
+
+ // Synthesizes gesture end events (including ET_GESTURE_END and
+ // ET_GESTURE_SCROLL_END) and send to `consumer`.
+ virtual void SendSynthesizedEndEvents(GestureConsumer* consumer) = 0;
+
private:
DISALLOW_COPY_AND_ASSIGN(GestureRecognizer);
};
diff --git a/chromium/ui/events/gestures/gesture_recognizer_impl.cc b/chromium/ui/events/gestures/gesture_recognizer_impl.cc
index 85912f5ad4e..8f7bd8ae94c 100644
--- a/chromium/ui/events/gestures/gesture_recognizer_impl.cc
+++ b/chromium/ui/events/gestures/gesture_recognizer_impl.cc
@@ -388,6 +388,21 @@ void GestureRecognizerImpl::RemoveGestureEventHelper(
helpers_.erase(it);
}
+bool GestureRecognizerImpl::DoesConsumerHaveActiveTouch(
+ GestureConsumer* consumer) const {
+ for (const auto& id_consumer_pair : touch_id_target_) {
+ if (id_consumer_pair.second == consumer)
+ return true;
+ }
+
+ return false;
+}
+
+void GestureRecognizerImpl::SendSynthesizedEndEvents(
+ GestureConsumer* consumer) {
+ GetGestureProviderForConsumer(consumer)->SendSynthesizedEndEvents();
+}
+
void GestureRecognizerImpl::OnGestureEvent(GestureConsumer* raw_input_consumer,
GestureEvent* event) {
DispatchGestureEvent(raw_input_consumer, event);
diff --git a/chromium/ui/events/gestures/gesture_recognizer_impl.h b/chromium/ui/events/gestures/gesture_recognizer_impl.h
index 54d9c1079a3..1baf466eb34 100644
--- a/chromium/ui/events/gestures/gesture_recognizer_impl.h
+++ b/chromium/ui/events/gestures/gesture_recognizer_impl.h
@@ -90,6 +90,8 @@ class EVENTS_EXPORT GestureRecognizerImpl : public GestureRecognizer,
bool CleanupStateForConsumer(GestureConsumer* consumer) override;
void AddGestureEventHelper(GestureEventHelper* helper) override;
void RemoveGestureEventHelper(GestureEventHelper* helper) override;
+ bool DoesConsumerHaveActiveTouch(GestureConsumer* consumer) const override;
+ void SendSynthesizedEndEvents(GestureConsumer* consumer) override;
// Overridden from GestureProviderAuraClient
void OnGestureEvent(GestureConsumer* raw_input_consumer,
diff --git a/chromium/ui/events/gestures/gesture_recognizer_impl_mac.cc b/chromium/ui/events/gestures/gesture_recognizer_impl_mac.cc
index eff4e4159dd..c3fae93991d 100644
--- a/chromium/ui/events/gestures/gesture_recognizer_impl_mac.cc
+++ b/chromium/ui/events/gestures/gesture_recognizer_impl_mac.cc
@@ -75,4 +75,12 @@ void GestureRecognizerImplMac::AddGestureEventHelper(
void GestureRecognizerImplMac::RemoveGestureEventHelper(
GestureEventHelper* helper) {}
+bool GestureRecognizerImplMac::DoesConsumerHaveActiveTouch(
+ GestureConsumer* consumer) const {
+ return false;
+}
+
+void GestureRecognizerImplMac::SendSynthesizedEndEvents(
+ GestureConsumer* consumer) {}
+
} // namespace ui
diff --git a/chromium/ui/events/gestures/gesture_recognizer_impl_mac.h b/chromium/ui/events/gestures/gesture_recognizer_impl_mac.h
index 5d22b145360..0541e4b5b32 100644
--- a/chromium/ui/events/gestures/gesture_recognizer_impl_mac.h
+++ b/chromium/ui/events/gestures/gesture_recognizer_impl_mac.h
@@ -50,6 +50,8 @@ class EVENTS_EXPORT GestureRecognizerImplMac : public GestureRecognizer {
bool CancelActiveTouches(GestureConsumer* consumer) override;
void AddGestureEventHelper(GestureEventHelper* helper) override;
void RemoveGestureEventHelper(GestureEventHelper* helper) override;
+ bool DoesConsumerHaveActiveTouch(GestureConsumer* consumer) const override;
+ void SendSynthesizedEndEvents(GestureConsumer* consumer) override;
DISALLOW_COPY_AND_ASSIGN(GestureRecognizerImplMac);
};
diff --git a/chromium/ui/events/gestures/motion_event_aura.h b/chromium/ui/events/gestures/motion_event_aura.h
index 29a9e5d85ad..a1cc913649f 100644
--- a/chromium/ui/events/gestures/motion_event_aura.h
+++ b/chromium/ui/events/gestures/motion_event_aura.h
@@ -2,16 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_GESTURE_DETECTION_UI_MOTION_EVENT_H_
-#define UI_EVENTS_GESTURE_DETECTION_UI_MOTION_EVENT_H_
+#ifndef UI_EVENTS_GESTURES_MOTION_EVENT_AURA_H_
+#define UI_EVENTS_GESTURES_MOTION_EVENT_AURA_H_
#include <stddef.h>
-#include <map>
-#include <memory>
#include "base/macros.h"
-#include "base/time/time.h"
#include "ui/events/event.h"
#include "ui/events/events_export.h"
#include "ui/events/gesture_detection/motion_event_generic.h"
@@ -48,4 +45,4 @@ class EVENTS_EXPORT MotionEventAura : public MotionEventGeneric {
} // namespace ui
-#endif // UI_EVENTS_GESTURE_DETECTION_UI_MOTION_EVENT_H_
+#endif // UI_EVENTS_GESTURES_MOTION_EVENT_AURA_H_
diff --git a/chromium/ui/events/keyboard_hook.h b/chromium/ui/events/keyboard_hook.h
index ca88fec0dfa..3757d222be3 100644
--- a/chromium/ui/events/keyboard_hook.h
+++ b/chromium/ui/events/keyboard_hook.h
@@ -8,9 +8,9 @@
#include <memory>
#include "base/callback.h"
+#include "base/component_export.h"
#include "base/containers/flat_set.h"
-#include "base/optional.h"
-#include "ui/events/events_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/native_widget_types.h"
namespace ui {
@@ -20,7 +20,7 @@ class KeyEvent;
// Intercepts keyboard events typically handled by the OS or browser.
// Destroying the instance will unregister and clean up the keyboard hook.
-class EVENTS_EXPORT KeyboardHook {
+class COMPONENT_EXPORT(KEYBOARD_HOOK) KeyboardHook {
public:
using KeyEventCallback = base::RepeatingCallback<void(KeyEvent* event)>;
@@ -33,7 +33,7 @@ class EVENTS_EXPORT KeyboardHook {
// Returns a valid instance if the hook was created and successfully
// registered otherwise nullptr.
static std::unique_ptr<KeyboardHook> CreateModifierKeyboardHook(
- base::Optional<base::flat_set<DomCode>> dom_codes,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
gfx::AcceleratedWidget accelerated_widget,
KeyEventCallback callback);
diff --git a/chromium/ui/events/keyboard_hook_base.cc b/chromium/ui/events/keyboard_hook_base.cc
index da356f91b59..e05dc646453 100644
--- a/chromium/ui/events/keyboard_hook_base.cc
+++ b/chromium/ui/events/keyboard_hook_base.cc
@@ -14,7 +14,7 @@
namespace ui {
KeyboardHookBase::KeyboardHookBase(
- base::Optional<base::flat_set<DomCode>> dom_codes,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
KeyEventCallback callback)
: key_event_callback_(std::move(callback)),
dom_codes_(std::move(dom_codes)) {
diff --git a/chromium/ui/events/keyboard_hook_base.h b/chromium/ui/events/keyboard_hook_base.h
index c5a7f2dd9cd..a598df8b78c 100644
--- a/chromium/ui/events/keyboard_hook_base.h
+++ b/chromium/ui/events/keyboard_hook_base.h
@@ -5,7 +5,6 @@
#ifndef UI_EVENTS_KEYBOARD_HOOK_BASE_H_
#define UI_EVENTS_KEYBOARD_HOOK_BASE_H_
-#include <memory>
#include "base/macros.h"
#include "ui/events/keyboard_hook.h"
@@ -17,7 +16,7 @@ class KeyEvent;
class KeyboardHookBase : public KeyboardHook {
public:
- KeyboardHookBase(base::Optional<base::flat_set<DomCode>> dom_codes,
+ KeyboardHookBase(absl::optional<base::flat_set<DomCode>> dom_codes,
KeyEventCallback callback);
~KeyboardHookBase() override;
@@ -35,7 +34,7 @@ class KeyboardHookBase : public KeyboardHook {
// returns.
void ForwardCapturedKeyEvent(KeyEvent* event);
- const base::Optional<base::flat_set<DomCode>>& dom_codes() {
+ const absl::optional<base::flat_set<DomCode>>& dom_codes() {
return dom_codes_;
}
@@ -44,7 +43,7 @@ class KeyboardHookBase : public KeyboardHook {
KeyEventCallback key_event_callback_;
// The set of keys which should be intercepted by the keyboard hook.
- base::Optional<base::flat_set<DomCode>> dom_codes_;
+ absl::optional<base::flat_set<DomCode>> dom_codes_;
DISALLOW_COPY_AND_ASSIGN(KeyboardHookBase);
};
diff --git a/chromium/ui/events/keyboard_hook_linux.cc b/chromium/ui/events/keyboard_hook_linux.cc
index 45ee6ee3de0..4f8c599c25a 100644
--- a/chromium/ui/events/keyboard_hook_linux.cc
+++ b/chromium/ui/events/keyboard_hook_linux.cc
@@ -2,13 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/events/keyboard_hook_base.h"
+#include "ui/events/keyboard_hook.h"
#include <memory>
#include "base/callback.h"
-#include "base/optional.h"
-#include "ui/base/ui_base_features.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/gfx/native_widget_types.h"
@@ -17,34 +16,35 @@
#endif
#if defined(USE_OZONE)
+#include "ui/base/ui_base_features.h"
#include "ui/events/ozone/keyboard_hook_ozone.h"
+#include "ui/ozone/public/platform_keyboard_hook.h"
#endif
namespace ui {
// static
std::unique_ptr<KeyboardHook> KeyboardHook::CreateModifierKeyboardHook(
- base::Optional<base::flat_set<DomCode>> dom_codes,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
gfx::AcceleratedWidget accelerated_widget,
KeyEventCallback callback) {
- std::unique_ptr<KeyboardHookBase> keyboard_hook;
#if defined(USE_OZONE)
if (features::IsUsingOzonePlatform()) {
- keyboard_hook = std::make_unique<KeyboardHookOzone>(std::move(dom_codes),
- std::move(callback));
+ return std::make_unique<KeyboardHookOzone>(
+ PlatformKeyboardHookTypes::kModifier, std::move(callback),
+ std::move(dom_codes), accelerated_widget);
}
#endif
#if defined(USE_X11)
- if (!keyboard_hook) {
- keyboard_hook = std::make_unique<KeyboardHookX11>(
- std::move(dom_codes), accelerated_widget, std::move(callback));
- }
-#endif
- DCHECK(keyboard_hook);
- if (!keyboard_hook->RegisterHook())
+ auto keyboard_hook_x11 = std::make_unique<KeyboardHookX11>(
+ std::move(dom_codes), accelerated_widget, std::move(callback));
+ if (!keyboard_hook_x11->RegisterHook())
return nullptr;
-
- return keyboard_hook;
+ return keyboard_hook_x11;
+#else
+ NOTREACHED();
+ return nullptr;
+#endif
}
// static
diff --git a/chromium/ui/events/keycodes/DEPS b/chromium/ui/events/keycodes/DEPS
index 0186a15eeb0..d974f6c24be 100644
--- a/chromium/ui/events/keycodes/DEPS
+++ b/chromium/ui/events/keycodes/DEPS
@@ -7,6 +7,7 @@ include_rules = [
"-third_party",
"-ui",
+ "+third_party/abseil-cpp/absl",
"+ui/base/buildflags.h", # Doesn't bring in all of UI.
"+ui/gfx/x",
"+ui/events",
diff --git a/chromium/ui/events/keycodes/dom/dom_code.h b/chromium/ui/events/keycodes/dom/dom_code.h
index 4fbf542ce98..3f53f7534ca 100644
--- a/chromium/ui/events/keycodes/dom/dom_code.h
+++ b/chromium/ui/events/keycodes/dom/dom_code.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_KEYCODES_DOM3_DOM_CODE_H_
-#define UI_EVENTS_KEYCODES_DOM3_DOM_CODE_H_
+#ifndef UI_EVENTS_KEYCODES_DOM_DOM_CODE_H_
+#define UI_EVENTS_KEYCODES_DOM_DOM_CODE_H_
namespace ui {
@@ -15,4 +15,4 @@ namespace ui {
} // namespace ui
-#endif // UI_EVENTS_KEYCODES_DOM3_DOM_CODE_H_
+#endif // UI_EVENTS_KEYCODES_DOM_DOM_CODE_H_
diff --git a/chromium/ui/events/keycodes/dom/dom_key.h b/chromium/ui/events/keycodes/dom/dom_key.h
index 3835537f4b7..730ab2ecf47 100644
--- a/chromium/ui/events/keycodes/dom/dom_key.h
+++ b/chromium/ui/events/keycodes/dom/dom_key.h
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_KEYCODES_DOM3_DOM_KEY_H_
-#define UI_EVENTS_KEYCODES_DOM3_DOM_KEY_H_
+#ifndef UI_EVENTS_KEYCODES_DOM_DOM_KEY_H_
+#define UI_EVENTS_KEYCODES_DOM_DOM_KEY_H_
#include <stdint.h>
#include <ostream>
#include "base/check.h"
-#include "base/optional.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace ui {
@@ -105,9 +105,9 @@ class DomKey {
// Factory that returns a DomKey for the specified value. Returns nullopt if
// |value| is not a valid value (or NONE).
- static base::Optional<DomKey> FromBase(Base value) {
+ static absl::optional<DomKey> FromBase(Base value) {
if (value != 0 && !IsValidValue(value))
- return base::nullopt;
+ return absl::nullopt;
return Base(value);
}
@@ -169,4 +169,4 @@ class DomKey {
} // namespace ui
-#endif // UI_EVENTS_KEYCODES_DOM3_DOM_KEY_H_
+#endif // UI_EVENTS_KEYCODES_DOM_DOM_KEY_H_
diff --git a/chromium/ui/events/keycodes/dom/keycode_converter.cc b/chromium/ui/events/keycodes/dom/keycode_converter.cc
index c6ed4ac20a8..4c3881badab 100644
--- a/chromium/ui/events/keycodes/dom/keycode_converter.cc
+++ b/chromium/ui/events/keycodes/dom/keycode_converter.cc
@@ -178,6 +178,60 @@ int KeycodeConverter::DomCodeToEvdevCode(DomCode code) {
}
#endif
+#if defined(OS_CHROMEOS)
+// static
+DomCode KeycodeConverter::MapUSPositionalShortcutKeyToDomCode(
+ KeyboardCode key_code) {
+ // VKEY Mapping: http://kbdlayout.info/kbdus/overview+virtualkeys
+ // DomCode Mapping:
+ // https://www.w3.org/TR/DOM-Level-3-Events-code/#writing-system-keys
+ switch (key_code) {
+ case VKEY_OEM_MINUS:
+ return DomCode::MINUS;
+ case VKEY_OEM_PLUS:
+ return DomCode::EQUAL;
+ case VKEY_OEM_2:
+ return DomCode::SLASH;
+ case VKEY_OEM_4:
+ return DomCode::BRACKET_LEFT;
+ case VKEY_OEM_6:
+ return DomCode::BRACKET_RIGHT;
+ case VKEY_OEM_COMMA:
+ return DomCode::COMMA;
+ case VKEY_OEM_PERIOD:
+ return DomCode::PERIOD;
+ default:
+ return DomCode::NONE;
+ }
+}
+
+// static
+KeyboardCode KeycodeConverter::MapPositionalDomCodeToUSShortcutKey(
+ DomCode code) {
+ // VKEY Mapping: http://kbdlayout.info/kbdus/overview+virtualkeys
+ // DomCode Mapping:
+ // https://www.w3.org/TR/DOM-Level-3-Events-code/#writing-system-keys
+ switch (code) {
+ case DomCode::MINUS:
+ return VKEY_OEM_MINUS;
+ case DomCode::EQUAL:
+ return VKEY_OEM_PLUS;
+ case DomCode::SLASH:
+ return VKEY_OEM_2;
+ case DomCode::BRACKET_LEFT:
+ return VKEY_OEM_4;
+ case DomCode::BRACKET_RIGHT:
+ return VKEY_OEM_6;
+ case DomCode::COMMA:
+ return VKEY_OEM_COMMA;
+ case DomCode::PERIOD:
+ return VKEY_OEM_PERIOD;
+ default:
+ return VKEY_UNKNOWN;
+ }
+}
+#endif
+
// static
DomCode KeycodeConverter::CodeStringToDomCode(const std::string& code) {
if (code.empty())
diff --git a/chromium/ui/events/keycodes/dom/keycode_converter.h b/chromium/ui/events/keycodes/dom/keycode_converter.h
index b6d0f12539b..032ab082894 100644
--- a/chromium/ui/events/keycodes/dom/keycode_converter.h
+++ b/chromium/ui/events/keycodes/dom/keycode_converter.h
@@ -12,6 +12,10 @@
#include "build/build_config.h"
#include "ui/events/keycodes/dom/dom_key.h"
+#if defined(OS_CHROMEOS)
+#include "ui/events/keycodes/keyboard_codes_posix.h"
+#endif
+
// For reference, the W3C UI Event spec is located at:
// http://www.w3.org/TR/uievents/
@@ -73,6 +77,20 @@ class KeycodeConverter {
static int DomCodeToEvdevCode(DomCode code);
#endif
+#if defined(OS_CHROMEOS)
+ // If |key_code| is one of the keys (plus, minus, brackets, period, comma),
+ // that are treated positionally for keyboard shortcuts, this returns the
+ // DomCode of that key in the US layout. Any other key returns
+ // |DomCode::NONE|.
+ static DomCode MapUSPositionalShortcutKeyToDomCode(KeyboardCode key_code);
+
+ // If |code| is one of the keys (plus, minus, brackets, period, comma) that
+ // are treated positionally for keyboard shortcuts, this returns the
+ // KeyboardCode (aka VKEY) of that key in the US layout. Any other key
+ // returns |VKEY_UNKNOWN|
+ static KeyboardCode MapPositionalDomCodeToUSShortcutKey(DomCode code);
+#endif
+
// Convert a UI Events |code| string value into a DomCode.
static DomCode CodeStringToDomCode(const std::string& code);
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion.cc b/chromium/ui/events/keycodes/keyboard_code_conversion.cc
index 143e054fa2e..dad614ba8b8 100644
--- a/chromium/ui/events/keycodes/keyboard_code_conversion.cc
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion.cc
@@ -294,4 +294,21 @@ int ModifierDomKeyToEventFlag(DomKey key) {
// DomKey::SYMBOL_LOCK
}
+DomCode UsLayoutDomKeyToDomCode(DomKey dom_key) {
+ if (dom_key.IsCharacter()) {
+ char16_t c = dom_key.ToCharacter();
+ for (const auto& it : kPrintableCodeMap) {
+ if (it.character[0] == c || it.character[1] == c) {
+ return it.dom_code;
+ }
+ }
+ }
+
+ for (const auto& it : kNonPrintableCodeMap) {
+ if (it.dom_key == dom_key)
+ return it.dom_code;
+ }
+ return DomCode::NONE;
+}
+
} // namespace ui
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion.h b/chromium/ui/events/keycodes/keyboard_code_conversion.h
index 73cdecd70af..7efa5bfe8bc 100644
--- a/chromium/ui/events/keycodes/keyboard_code_conversion.h
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion.h
@@ -5,7 +5,6 @@
#ifndef UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_H_
#define UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_H_
-#include <string>
#include "base/compiler_specific.h"
#include "ui/events/events_base_export.h"
@@ -112,6 +111,10 @@ DomCodeToUsLayoutNonLocatedKeyboardCode(DomCode dom_code);
// or 0 (EF_NONE) if the key is not a modifier.
EVENTS_BASE_EXPORT int ModifierDomKeyToEventFlag(DomKey key);
+// Returns the physical DOM code along with a corresponding non-located
+// Windows-based key_code.
+EVENTS_BASE_EXPORT DomCode UsLayoutDomKeyToDomCode(DomKey dom_key);
+
} // namespace ui
#endif // UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_H_
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_fuchsia.cc b/chromium/ui/events/keycodes/keyboard_code_conversion_fuchsia.cc
new file mode 100644
index 00000000000..0a75fbbe91e
--- /dev/null
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion_fuchsia.cc
@@ -0,0 +1,38 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/keycodes/keyboard_code_conversion_fuchsia.h"
+
+#include <fuchsia/ui/input3/cpp/fidl.h>
+
+#include "base/containers/flat_map.h"
+
+namespace ui {
+namespace {
+
+DomKey DomKeyFromFuchsiaNonPrintableKey(
+ const fuchsia::ui::input3::NonPrintableKey& key) {
+ if (key == fuchsia::ui::input3::NonPrintableKey::ENTER)
+ return DomKey::ENTER;
+ if (key == fuchsia::ui::input3::NonPrintableKey::TAB)
+ return DomKey::TAB;
+ if (key == fuchsia::ui::input3::NonPrintableKey::BACKSPACE)
+ return DomKey::BACKSPACE;
+
+ return DomKey::UNIDENTIFIED;
+}
+
+} // namespace
+
+DomKey DomKeyFromFuchsiaKeyMeaning(
+ const fuchsia::ui::input3::KeyMeaning& key_meaning) {
+ if (key_meaning.is_codepoint())
+ return DomKey::FromCharacter(key_meaning.codepoint());
+ if (key_meaning.is_non_printable_key())
+ return DomKeyFromFuchsiaNonPrintableKey(key_meaning.non_printable_key());
+
+ return DomKey::UNIDENTIFIED;
+}
+
+} // namespace ui
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_fuchsia.h b/chromium/ui/events/keycodes/keyboard_code_conversion_fuchsia.h
new file mode 100644
index 00000000000..a3c7b98bb9a
--- /dev/null
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion_fuchsia.h
@@ -0,0 +1,27 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_FUCHSIA_H_
+#define UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_FUCHSIA_H_
+
+#include "ui/events/events_base_export.h"
+#include "ui/events/keycodes/dom/dom_key.h"
+
+namespace fuchsia {
+namespace ui {
+namespace input3 {
+class KeyMeaning;
+} // namespace input3
+} // namespace ui
+} // namespace fuchsia
+
+namespace ui {
+
+// Converts a Fuchsia KeyMeaning to a DomKey.
+EVENTS_BASE_EXPORT DomKey
+DomKeyFromFuchsiaKeyMeaning(const fuchsia::ui::input3::KeyMeaning& key_meaning);
+
+} // namespace ui
+
+#endif // UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_FUCHSIA_H_ \ No newline at end of file
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_fuchsia_unittest.cc b/chromium/ui/events/keycodes/keyboard_code_conversion_fuchsia_unittest.cc
new file mode 100644
index 00000000000..03f40358c15
--- /dev/null
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion_fuchsia_unittest.cc
@@ -0,0 +1,67 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/keycodes/keyboard_code_conversion_fuchsia.h"
+
+#include <fuchsia/input/cpp/fidl.h>
+#include <fuchsia/ui/input3/cpp/fidl.h>
+#include <cstdint>
+
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/keycodes/dom/dom_key.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
+
+namespace {
+
+using fuchsia::input::Key;
+using fuchsia::ui::input3::KeyMeaning;
+using fuchsia::ui::input3::NonPrintableKey;
+
+#define EXPECT_CODEPOINT_MAPS(codepoint) \
+ EXPECT_EQ( \
+ ui::DomKey::FromCharacter(codepoint), \
+ ui::DomKeyFromFuchsiaKeyMeaning(KeyMeaning::WithCodepoint(codepoint))) \
+ << " for codepoint " << codepoint;
+
+// For |size| Unicode values beginning with code |start|, check that they are
+// converted to the correct DomKey.
+void CheckConversionsInRange(int start, int size) {
+ for (int i = 0; i < size; i++)
+ EXPECT_CODEPOINT_MAPS(start + i);
+}
+
+// Check that the for the below ranges, Fuchsia Keys are correctly converted to
+// DomKeys.
+TEST(FuchsiaKeyboardCodeConversion, FuchsiaKeyToDomKeyConversionRanges) {
+ // Check digits 1 through 0.
+ CheckConversionsInRange(0x0030, 10);
+
+ // Check capital letters.
+ CheckConversionsInRange(0x0041, 26);
+
+ // Check lower case letters.
+ CheckConversionsInRange(0x0061, 26);
+}
+
+TEST(FuchsiaKeyboardCodeConversion, FuchsiaKeyToDomKeySpecificValues) {
+ // Yen sign.
+ EXPECT_EQ(ui::DomKey::FromCharacter(0x00a5),
+ ui::DomKeyFromFuchsiaKeyMeaning(KeyMeaning::WithCodepoint(165)));
+
+ // Right brace.
+ EXPECT_EQ(ui::DomKey::FromCharacter(0x007d),
+ ui::DomKeyFromFuchsiaKeyMeaning(KeyMeaning::WithCodepoint(125)));
+
+ // Lower case c with circumflex.
+ EXPECT_EQ(ui::DomKey::FromCharacter(0x0109),
+ ui::DomKeyFromFuchsiaKeyMeaning(KeyMeaning::WithCodepoint(265)));
+
+ // Check that NonPrintableKeys are converted correctly.
+ EXPECT_EQ(ui::DomKey::ENTER,
+ ui::DomKeyFromFuchsiaKeyMeaning(KeyMeaning::WithNonPrintableKey(
+ NonPrintableKey(NonPrintableKey::ENTER))));
+}
+
+} // namespace
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_x.cc b/chromium/ui/events/keycodes/keyboard_code_conversion_x.cc
index b38af7a8010..4bd961dba66 100644
--- a/chromium/ui/events/keycodes/keyboard_code_conversion_x.cc
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion_x.cc
@@ -1177,7 +1177,12 @@ KeyboardCode DefaultKeyboardCodeFromHardwareKeycode(
case 0xB5: // KEY_REFRESH
return VKEY_BROWSER_REFRESH;
case 0xD4: // KEY_DASHBOARD
- return VKEY_MEDIA_LAUNCH_APP2;
+ // This was changed from VKEY_MEDIA_LAUNCH_APP2 when the full screen
+ // key was moved to VKEY_ZOOM with crbug.com/1204710. In order to
+ // maintain existing behavior this was kept consistent but it
+ // seems like this should have been VKEY_MEDIA_LAUNCH_APP1 aka
+ // overview in the first place.
+ return VKEY_ZOOM;
case 0xE8: // KEY_BRIGHTNESSDOWN
return VKEY_BRIGHTNESS_DOWN;
case 0xE9: // KEY_BRIGHTNESSUP
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_x.h b/chromium/ui/events/keycodes/keyboard_code_conversion_x.h
index ae3742cbf51..118895c4760 100644
--- a/chromium/ui/events/keycodes/keyboard_code_conversion_x.h
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion_x.h
@@ -7,7 +7,6 @@
#include <stdint.h>
-#include <string>
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/events/keycodes/keyboard_codes_posix.h"
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.h b/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.h
index 8f56878d4bb..e1fefa4cead 100644
--- a/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.h
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.h
@@ -7,7 +7,6 @@
// These functions are used by X11 targets and by Ozone/XKBcommon targets.
-#include <string>
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/events/keycodes/xkb_keysym.h"
diff --git a/chromium/ui/events/mac/keyboard_hook_mac.mm b/chromium/ui/events/mac/keyboard_hook_mac.mm
index 1da9d4ce421..9796df89d26 100644
--- a/chromium/ui/events/mac/keyboard_hook_mac.mm
+++ b/chromium/ui/events/mac/keyboard_hook_mac.mm
@@ -10,7 +10,7 @@ namespace ui {
// static
std::unique_ptr<KeyboardHook> KeyboardHook::CreateModifierKeyboardHook(
- base::Optional<base::flat_set<DomCode>> dom_codes,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
gfx::AcceleratedWidget accelerated_widget,
KeyEventCallback callback) {
return nullptr;
diff --git a/chromium/ui/events/mojom/event_mojom_traits.cc b/chromium/ui/events/mojom/event_mojom_traits.cc
index 3f666ef5a63..72ca1a956ad 100644
--- a/chromium/ui/events/mojom/event_mojom_traits.cc
+++ b/chromium/ui/events/mojom/event_mojom_traits.cc
@@ -366,7 +366,7 @@ bool StructTraits<ui::mojom::EventDataView, EventUniquePtr>::Read(
if (!event.ReadKeyData<ui::mojom::KeyDataPtr>(&key_data))
return false;
- base::Optional<ui::DomKey> dom_key =
+ absl::optional<ui::DomKey> dom_key =
ui::DomKey::FromBase(key_data->dom_key);
if (!dom_key)
return false;
@@ -477,7 +477,7 @@ bool StructTraits<ui::mojom::EventDataView, EventUniquePtr>::Read(
if (!event.ReadLatency((*out)->latency()))
return false;
- base::Optional<ui::Event::Properties> properties;
+ absl::optional<ui::Event::Properties> properties;
if (!event.ReadProperties(&properties))
return false;
if (properties && !properties->empty())
diff --git a/chromium/ui/events/ozone/device/device_event.h b/chromium/ui/events/ozone/device/device_event.h
index d8ed9c58c48..bc17a640af9 100644
--- a/chromium/ui/events/ozone/device/device_event.h
+++ b/chromium/ui/events/ozone/device/device_event.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_OZONE_DEVICE_EVENT_H_
-#define UI_EVENTS_OZONE_DEVICE_EVENT_H_
+#ifndef UI_EVENTS_OZONE_DEVICE_DEVICE_EVENT_H_
+#define UI_EVENTS_OZONE_DEVICE_DEVICE_EVENT_H_
#include "base/component_export.h"
#include "base/files/file_path.h"
@@ -40,4 +40,4 @@ class COMPONENT_EXPORT(EVENTS_OZONE) DeviceEvent {
} // namespace ui
-#endif // UI_EVENTS_OZONE_DEVICE_EVENT_H_
+#endif // UI_EVENTS_OZONE_DEVICE_DEVICE_EVENT_H_
diff --git a/chromium/ui/events/ozone/device/device_event_observer.h b/chromium/ui/events/ozone/device/device_event_observer.h
index 55580845464..4aa86221441 100644
--- a/chromium/ui/events/ozone/device/device_event_observer.h
+++ b/chromium/ui/events/ozone/device/device_event_observer.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_OZONE_DEVICE_EVENT_OBSERVER_H_
-#define UI_EVENTS_OZONE_DEVICE_EVENT_OBSERVER_H_
+#ifndef UI_EVENTS_OZONE_DEVICE_DEVICE_EVENT_OBSERVER_H_
+#define UI_EVENTS_OZONE_DEVICE_DEVICE_EVENT_OBSERVER_H_
#include "base/component_export.h"
@@ -20,5 +20,4 @@ class COMPONENT_EXPORT(EVENTS_OZONE) DeviceEventObserver {
} // namespace ui
-#endif // UI_EVENTS_OZONE_DEVICE_EVENT_OBSERVER_H_
-
+#endif // UI_EVENTS_OZONE_DEVICE_DEVICE_EVENT_OBSERVER_H_
diff --git a/chromium/ui/events/ozone/evdev/BUILD.gn b/chromium/ui/events/ozone/evdev/BUILD.gn
index 74ce8cb434a..c020fdd3213 100644
--- a/chromium/ui/events/ozone/evdev/BUILD.gn
+++ b/chromium/ui/events/ozone/evdev/BUILD.gn
@@ -43,8 +43,6 @@ component("evdev") {
"event_converter_evdev.h",
"event_converter_evdev_impl.cc",
"event_converter_evdev_impl.h",
- "event_device_info.cc",
- "event_device_info.h",
"event_factory_evdev.cc",
"event_factory_evdev.h",
"event_thread_evdev.cc",
@@ -63,10 +61,14 @@ component("evdev") {
"input_injector_evdev.h",
"keyboard_evdev.cc",
"keyboard_evdev.h",
+ "microphone_mute_switch_event_converter_evdev.cc",
+ "microphone_mute_switch_event_converter_evdev.h",
"mouse_button_map_evdev.cc",
"mouse_button_map_evdev.h",
"stylus_button_event_converter_evdev.cc",
"stylus_button_event_converter_evdev.h",
+ "switches.cc",
+ "switches.h",
"tablet_event_converter_evdev.cc",
"tablet_event_converter_evdev.h",
"touch_evdev_debug_buffer.cc",
@@ -106,6 +108,7 @@ component("evdev") {
defines = [ "IS_EVDEV_IMPL" ]
deps = [
+ ":event_device_info",
"//base",
"//build:chromeos_buildflags",
"//ui/display",
@@ -156,6 +159,40 @@ component("evdev") {
]
}
+source_set("event_device_info") {
+ sources = [
+ "event_device_info.cc",
+ "event_device_info.h",
+ ]
+
+ deps = [
+ "//base",
+ "//ui/events/devices",
+ ]
+
+ visibility += [
+ "//chromeos/components/diagnostics_ui/backend:*",
+ "//ui/chromeos/*",
+ ]
+}
+
+source_set("event_device_info_test_utils") {
+ testonly = true
+
+ sources = [
+ "event_device_test_util.cc",
+ "event_device_test_util.h",
+ ]
+
+ deps = [
+ ":evdev",
+ ":event_device_info",
+ "//base",
+ ]
+
+ visibility += [ "//chromeos/components/diagnostics_ui/backend:unit_tests" ]
+}
+
source_set("unittests") {
testonly = true
@@ -164,12 +201,11 @@ source_set("unittests") {
"event_converter_test_util.cc",
"event_converter_test_util.h",
"event_device_info_unittest.cc",
- "event_device_test_util.cc",
- "event_device_test_util.h",
"event_factory_evdev_unittest.cc",
"gamepad_event_converter_evdev_unittest.cc",
"input_controller_evdev_unittest.cc",
"input_injector_evdev_unittest.cc",
+ "microphone_mute_switch_event_converter_evdev_unittest.cc",
"stylus_button_event_converter_evdev_unittest.cc",
"tablet_event_converter_evdev_unittest.cc",
"testing/fake_cursor_delegate_evdev.h",
@@ -185,6 +221,8 @@ source_set("unittests") {
deps = [
":evdev",
+ ":event_device_info",
+ ":event_device_info_test_utils",
"//base",
"//base/test:test_support",
"//build:chromeos_buildflags",
diff --git a/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.cc b/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.cc
index 66e8e2c5ce1..6bc2d685d1a 100644
--- a/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace ui {
@@ -36,8 +36,8 @@ MouseMoveEventParams::MouseMoveEventParams(int device_id,
flags(flags),
location(location),
ordinal_delta(ordinal_delta
- ? base::Optional<gfx::Vector2dF>(*ordinal_delta)
- : base::nullopt),
+ ? absl::optional<gfx::Vector2dF>(*ordinal_delta)
+ : absl::nullopt),
pointer_details(details),
timestamp(timestamp) {}
diff --git a/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.h b/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.h
index 2f168e1323c..386c72e4563 100644
--- a/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.h
+++ b/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_OZONE_EVDEV_DEVICE_EVENT_DISPATCHER_H_
-#define UI_EVENTS_OZONE_EVDEV_DEVICE_EVENT_DISPATCHER_H_
+#ifndef UI_EVENTS_OZONE_EVDEV_DEVICE_EVENT_DISPATCHER_EVDEV_H_
+#define UI_EVENTS_OZONE_EVDEV_DEVICE_EVENT_DISPATCHER_EVDEV_H_
#include <vector>
#include "base/component_export.h"
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/devices/gamepad_device.h"
#include "ui/events/devices/input_device.h"
#include "ui/events/devices/touchscreen_device.h"
@@ -59,7 +59,7 @@ struct COMPONENT_EXPORT(EVDEV) MouseMoveEventParams {
int device_id;
int flags;
gfx::PointF location;
- base::Optional<gfx::Vector2dF> ordinal_delta;
+ absl::optional<gfx::Vector2dF> ordinal_delta;
PointerDetails pointer_details;
base::TimeTicks timestamp;
};
@@ -192,6 +192,7 @@ class COMPONENT_EXPORT(EVDEV) DeviceEventDispatcherEvdev {
virtual void DispatchScrollEvent(const ScrollEventParams& params) = 0;
virtual void DispatchTouchEvent(const TouchEventParams& params) = 0;
virtual void DispatchGamepadEvent(const GamepadEvent& event) = 0;
+ virtual void DispatchMicrophoneMuteSwitchValueChanged(bool muted) = 0;
// Device lifecycle events.
virtual void DispatchKeyboardDevicesUpdated(
@@ -214,4 +215,4 @@ class COMPONENT_EXPORT(EVDEV) DeviceEventDispatcherEvdev {
} // namespace ui
-#endif // UI_EVENTS_OZONE_EVDEV_DEVICE_EVENT_DISPATCHER_H_
+#endif // UI_EVENTS_OZONE_EVDEV_DEVICE_EVENT_DISPATCHER_EVDEV_H_
diff --git a/chromium/ui/events/ozone/evdev/event_converter_evdev.cc b/chromium/ui/events/ozone/evdev/event_converter_evdev.cc
index 75e85ad2aee..1daf7ba0e74 100644
--- a/chromium/ui/events/ozone/evdev/event_converter_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/event_converter_evdev.cc
@@ -15,6 +15,7 @@
#include "ui/events/base_event_utils.h"
#include "ui/events/devices/device_util_linux.h"
#include "ui/events/devices/input_device.h"
+#include "ui/events/devices/stylus_state.h"
#include "ui/events/event_utils.h"
#ifndef input_event_sec
@@ -128,6 +129,15 @@ bool EventConverterEvdev::HasCapsLockLed() const {
return false;
}
+bool EventConverterEvdev::HasStylusSwitch() const {
+ return false;
+}
+
+ui::StylusState EventConverterEvdev::GetStylusSwitchState() {
+ NOTREACHED();
+ return ui::StylusState::REMOVED;
+}
+
gfx::Size EventConverterEvdev::GetTouchscreenSize() const {
NOTREACHED();
return gfx::Size();
diff --git a/chromium/ui/events/ozone/evdev/event_converter_evdev.h b/chromium/ui/events/ozone/evdev/event_converter_evdev.h
index 2d184811a00..94200288aff 100644
--- a/chromium/ui/events/ozone/evdev/event_converter_evdev.h
+++ b/chromium/ui/events/ozone/evdev/event_converter_evdev.h
@@ -17,6 +17,7 @@
#include "base/task/current_thread.h"
#include "ui/events/devices/gamepad_device.h"
#include "ui/events/devices/input_device.h"
+#include "ui/events/devices/stylus_state.h"
#include "ui/events/ozone/evdev/event_dispatch_callback.h"
#include "ui/gfx/geometry/size.h"
@@ -97,6 +98,15 @@ class COMPONENT_EXPORT(EVDEV) EventConverterEvdev
// Returns true if the converter is used for a device with a caps lock LED.
virtual bool HasCapsLockLed() const;
+ // Returns true if the converter is used for a device with a stylus switch
+ // (also known as garage or dock sensor, not buttons on a stylus).
+ virtual bool HasStylusSwitch() const;
+
+ // Returns the current state of the stylus garage switch, indicating whether a
+ // stylus is inserted in (or attached) to a stylus dock or garage, or has been
+ // removed.
+ virtual ui::StylusState GetStylusSwitchState();
+
// Returns the size of the touchscreen device if the converter is used for a
// touchscreen device.
virtual gfx::Size GetTouchscreenSize() const;
diff --git a/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.cc b/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.cc
index c54eebe573e..6b879e29d8b 100644
--- a/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.cc
+++ b/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.cc
@@ -15,6 +15,7 @@
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h"
+#include "ui/events/ozone/evdev/event_device_util.h"
namespace ui {
@@ -48,6 +49,7 @@ EventConverterEvdevImpl::EventConverterEvdevImpl(
input_device_fd_(std::move(fd)),
has_keyboard_(devinfo.HasKeyboard()),
has_touchpad_(devinfo.HasTouchpad()),
+ has_stylus_switch_(devinfo.HasStylusSwitch()),
has_caps_lock_led_(devinfo.HasLedEvent(LED_CAPSL)),
controller_(FROM_HERE),
cursor_(cursor),
@@ -90,6 +92,10 @@ bool EventConverterEvdevImpl::HasCapsLockLed() const {
return has_caps_lock_led_;
}
+bool EventConverterEvdevImpl::HasStylusSwitch() const {
+ return has_stylus_switch_;
+}
+
void EventConverterEvdevImpl::SetKeyFilter(bool enable_filter,
std::vector<DomCode> allowed_keys) {
if (!enable_filter) {
@@ -115,6 +121,22 @@ void EventConverterEvdevImpl::OnDisabled() {
ReleaseMouseButtons();
}
+ui::StylusState EventConverterEvdevImpl::GetStylusSwitchState() {
+ if (!HasStylusSwitch()) {
+ return ui::StylusState::REMOVED;
+ }
+
+ // Prepare storage for SW_MAX bits
+ unsigned long array[EVDEV_BITS_TO_LONGS(SW_MAX)] = {0};
+ int result = ioctl(input_device_fd_.get(), EVIOCGSW(SW_MAX), array);
+ if (result == -1) {
+ return ui::StylusState::REMOVED;
+ }
+
+ return EvdevBitIsSet(array, kSwitchStylusInserted) ? ui::StylusState::INSERTED
+ : ui::StylusState::REMOVED;
+}
+
void EventConverterEvdevImpl::ProcessEvents(const input_event* inputs,
int count) {
for (int i = 0; i < count; ++i) {
diff --git a/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.h b/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.h
index 63c5218a22f..f7e9a90323e 100644
--- a/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.h
+++ b/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.h
@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "base/message_loop/message_pump_libevent.h"
#include "ui/events/devices/input_device.h"
+#include "ui/events/devices/stylus_state.h"
#include "ui/events/event.h"
#include "ui/events/event_modifiers.h"
#include "ui/events/ozone/evdev/cursor_delegate_evdev.h"
@@ -20,6 +21,7 @@
#include "ui/events/ozone/evdev/event_device_info.h"
#include "ui/events/ozone/evdev/keyboard_evdev.h"
#include "ui/events/ozone/evdev/mouse_button_map_evdev.h"
+#include "ui/ozone/public/input_controller.h"
struct input_event;
@@ -43,6 +45,8 @@ class COMPONENT_EXPORT(EVDEV) EventConverterEvdevImpl
bool HasKeyboard() const override;
bool HasTouchpad() const override;
bool HasCapsLockLed() const override;
+ bool HasStylusSwitch() const override;
+ ui::StylusState GetStylusSwitchState() override;
void SetKeyFilter(bool enable_filter,
std::vector<DomCode> allowed_keys) override;
void OnDisabled() override;
@@ -71,6 +75,7 @@ class COMPONENT_EXPORT(EVDEV) EventConverterEvdevImpl
// Input modalities for this device.
bool has_keyboard_;
bool has_touchpad_;
+ bool has_stylus_switch_;
// LEDs for this device.
bool has_caps_lock_led_;
@@ -111,4 +116,3 @@ class COMPONENT_EXPORT(EVDEV) EventConverterEvdevImpl
} // namespace ui
#endif // UI_EVENTS_OZONE_EVDEV_EVENT_CONVERTER_EVDEV_IMPL_H_
-
diff --git a/chromium/ui/events/ozone/evdev/event_converter_test_util.cc b/chromium/ui/events/ozone/evdev/event_converter_test_util.cc
index a60136c3f18..176bec24353 100644
--- a/chromium/ui/events/ozone/evdev/event_converter_test_util.cc
+++ b/chromium/ui/events/ozone/evdev/event_converter_test_util.cc
@@ -62,6 +62,10 @@ class TestDeviceEventDispatcherEvdev : public DeviceEventDispatcherEvdev {
event_factory_evdev_->DispatchTouchEvent(params);
}
+ void DispatchMicrophoneMuteSwitchValueChanged(bool muted) override {
+ event_factory_evdev_->DispatchMicrophoneMuteSwitchValueChanged(muted);
+ }
+
void DispatchKeyboardDevicesUpdated(
const std::vector<InputDevice>& devices) override {
event_factory_evdev_->DispatchKeyboardDevicesUpdated(devices);
diff --git a/chromium/ui/events/ozone/evdev/event_device_info.cc b/chromium/ui/events/ozone/evdev/event_device_info.cc
index 5f3ed1eb57a..d55f5603ff5 100644
--- a/chromium/ui/events/ozone/evdev/event_device_info.cc
+++ b/chromium/ui/events/ozone/evdev/event_device_info.cc
@@ -9,7 +9,6 @@
#include <cstring>
#include "base/files/file_path.h"
-#include "base/logging.h"
#include "base/notreached.h"
#include "base/stl_util.h"
#include "base/threading/thread_restrictions.h"
@@ -503,6 +502,10 @@ bool EventDeviceInfo::IsStylusButtonDevice() const {
return false;
}
+bool EventDeviceInfo::IsMicrophoneMuteSwitchDevice() const {
+ return HasSwEvent(SW_MUTE_DEVICE) && device_type_ == INPUT_DEVICE_INTERNAL;
+}
+
bool IsInKeyboardBlockList(input_id input_id_) {
for (const auto& blocklist_id : kKeyboardBlocklist) {
if (input_id_.vendor == blocklist_id.vendor &&
@@ -557,6 +560,11 @@ bool EventDeviceInfo::HasTouchscreen() const {
return HasAbsXY() && HasDirect();
}
+bool EventDeviceInfo::HasStylusSwitch() const {
+ return HasSwEvent(SW_PEN_INSERTED) && (device_type_ == INPUT_DEVICE_UNKNOWN ||
+ device_type_ == INPUT_DEVICE_INTERNAL);
+}
+
bool EventDeviceInfo::HasGamepad() const {
if (!HasEventType(EV_KEY))
return false;
diff --git a/chromium/ui/events/ozone/evdev/event_device_info.h b/chromium/ui/events/ozone/evdev/event_device_info.h
index 4b73534c9da..e71d2e16fda 100644
--- a/chromium/ui/events/ozone/evdev/event_device_info.h
+++ b/chromium/ui/events/ozone/evdev/event_device_info.h
@@ -152,6 +152,9 @@ class COMPONENT_EXPORT(EVDEV) EventDeviceInfo {
// Determine whether there's a touchscreen on this device.
bool HasTouchscreen() const;
+ // Determine whether there's a stylus garage switch on this device.
+ bool HasStylusSwitch() const;
+
// Determine whether there's a gamepad on this device.
bool HasGamepad() const;
@@ -161,6 +164,11 @@ class COMPONENT_EXPORT(EVDEV) EventDeviceInfo {
// Determine if this is a dedicated device for a stylus button.
bool IsStylusButtonDevice() const;
+ // Determine whether this is a dedicated device for microphone mute hw switch
+ // on Chrome OS. The switch disables the internal microphone feed. The input
+ // device is used to track the mute switch state.
+ bool IsMicrophoneMuteSwitchDevice() const;
+
// The device type (internal or external.)
InputDeviceType device_type() const { return device_type_; }
diff --git a/chromium/ui/events/ozone/evdev/event_device_info_unittest.cc b/chromium/ui/events/ozone/evdev/event_device_info_unittest.cc
index 3bbeebe3d06..ba704e6efd7 100644
--- a/chromium/ui/events/ozone/evdev/event_device_info_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/event_device_info_unittest.cc
@@ -7,7 +7,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/ozone/evdev/event_device_info.h"
#include "ui/events/ozone/evdev/event_device_test_util.h"
@@ -26,6 +25,8 @@ TEST(EventDeviceInfoTest, BasicUsbGamepad) {
EXPECT_FALSE(devinfo.HasTouchscreen());
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_TRUE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_USB, devinfo.device_type());
}
@@ -56,6 +57,8 @@ TEST(EventDeviceInfoTest, SideVolumeButton) {
EXPECT_FALSE(devinfo.HasTouchscreen());
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
}
TEST(EventDeviceInfoTest, BasicCrosTouchscreen) {
@@ -69,6 +72,8 @@ TEST(EventDeviceInfoTest, BasicCrosTouchscreen) {
EXPECT_TRUE(devinfo.HasTouchscreen());
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_INTERNAL, devinfo.device_type());
}
@@ -84,6 +89,8 @@ TEST(EventDeviceInfoTest, BasicCrosTouchpad) {
EXPECT_FALSE(devinfo.HasTouchscreen());
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_INTERNAL, devinfo.device_type());
}
@@ -114,6 +121,8 @@ TEST(EventDeviceInfoTest, BasicUsbKeyboard) {
EXPECT_FALSE(devinfo.HasTouchscreen());
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_USB, devinfo.device_type());
}
@@ -129,6 +138,8 @@ TEST(EventDeviceInfoTest, BasicUsbKeyboard_Extra) {
EXPECT_FALSE(devinfo.HasTouchscreen());
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_USB, devinfo.device_type());
}
@@ -159,6 +170,8 @@ TEST(EventDeviceInfoTest, BasicUsbTouchscreen) {
EXPECT_TRUE(devinfo.HasTouchscreen());
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_USB, devinfo.device_type());
}
@@ -174,6 +187,8 @@ TEST(EventDeviceInfoTest, BasicUsbTablet) {
EXPECT_FALSE(devinfo.HasTouchscreen());
EXPECT_TRUE(devinfo.HasTablet());
EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_USB, devinfo.device_type());
}
@@ -205,6 +220,8 @@ TEST(EventDeviceInfoTest, HybridKeyboardWithMouse) {
EXPECT_FALSE(devinfo.HasTouchscreen());
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
}
TEST(EventDeviceInfoTest, AbsoluteMouseTouchscreen) {
@@ -219,6 +236,8 @@ TEST(EventDeviceInfoTest, AbsoluteMouseTouchscreen) {
EXPECT_TRUE(devinfo.HasTouchscreen());
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_USB, devinfo.device_type());
}
@@ -234,6 +253,8 @@ TEST(EventDeviceInfoTest, OnScreenStylus) {
EXPECT_TRUE(devinfo.HasTouchscreen());
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_INTERNAL, devinfo.device_type());
}
@@ -249,6 +270,8 @@ TEST(EventDeviceInfoTest, HammerKeyboard) {
EXPECT_FALSE(devinfo.HasTouchscreen());
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_INTERNAL, devinfo.device_type());
}
@@ -264,6 +287,8 @@ TEST(EventDeviceInfoTest, HammerTouchpad) {
EXPECT_FALSE(devinfo.HasTouchscreen());
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_INTERNAL, devinfo.device_type());
}
@@ -279,6 +304,8 @@ TEST(EventDeviceInfoTest, IllitekTP_Mouse) {
EXPECT_FALSE(devinfo.HasTouchscreen());
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_USB, devinfo.device_type());
}
@@ -294,6 +321,8 @@ TEST(EventDeviceInfoTest, IllitekTP) {
EXPECT_TRUE(devinfo.HasTouchscreen());
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_USB, devinfo.device_type());
}
@@ -316,6 +345,8 @@ TEST(EventDeviceInfoTest, XboxElite) {
EXPECT_FALSE(devinfo.HasTouchscreen());
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_TRUE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_BLUETOOTH, devinfo.device_type());
}
@@ -332,8 +363,26 @@ TEST(EventDeviceInfoTest, DellActivePen_Button) {
EXPECT_FALSE(devinfo.HasTablet());
EXPECT_FALSE(devinfo.HasGamepad());
EXPECT_TRUE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_BLUETOOTH, devinfo.device_type());
}
+TEST(EventDeviceInfoTest, BasicStylusGarageSwitch) {
+ EventDeviceInfo devinfo;
+ EXPECT_TRUE(CapabilitiesToDeviceInfo(kDrawciaStylusGarage, &devinfo));
+
+ EXPECT_FALSE(devinfo.HasKeyboard());
+ EXPECT_FALSE(devinfo.HasMouse());
+ EXPECT_FALSE(devinfo.HasPointingStick());
+ EXPECT_FALSE(devinfo.HasTouchpad());
+ EXPECT_FALSE(devinfo.HasTouchscreen());
+ EXPECT_FALSE(devinfo.HasTablet());
+ EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_TRUE(devinfo.HasStylusSwitch());
+
+ EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_UNKNOWN, devinfo.device_type());
+}
+
} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/event_device_test_util.cc b/chromium/ui/events/ozone/evdev/event_device_test_util.cc
index 63f4b53e835..e445d0eb9ab 100644
--- a/chromium/ui/events/ozone/evdev/event_device_test_util.cc
+++ b/chromium/ui/events/ozone/evdev/event_device_test_util.cc
@@ -1068,6 +1068,47 @@ const DeviceCapabilities kDrallionStylus = {
base::size(kDrallionStylusAxes),
};
+const DeviceCapabilities kPuffMicrophoneMuteSwitch = {
+ /* path */
+ "/sys/devices/pci0000:00/0000:00:19.0/PRP0001:00/input/input3/event3",
+ /* name */ "mic_mute_switch",
+ /* phys */ "gpio-keys/input0",
+ /* uniq */ "",
+ /* bustype */ "0019",
+ /* vendor */ "0001",
+ /* product */ "0001",
+ /* version */ "0100",
+ /* prop */ "0",
+ /* ev */ "21",
+ /* key */ "0",
+ /* rel */ "0",
+ /* abs */ "0",
+ /* msc */ "0",
+ /* sw */ "4000",
+ /* led */ "0",
+ /* ff */ "0",
+};
+
+const DeviceCapabilities kDrawciaStylusGarage = {
+ /* path */
+ "/sys/devices/pci0000:00/0000:00:15.2/PRP0001:00/input/input4/event4",
+ /* name */ "PRP0001:00",
+ /* phys */ "gpio-keys/input0",
+ /* uniq */ "",
+ /* bustype */ "0019",
+ /* vendor */ "0001",
+ /* product */ "0001",
+ /* version */ "0100",
+ /* prop */ "0",
+ /* ev */ "21",
+ /* key */ "0",
+ /* rel */ "0",
+ /* abs */ "0",
+ /* msc */ "0",
+ /* sw */ "8000",
+ /* led */ "0",
+ /* ff */ "0",
+};
// NB: Please use the capture_device_capabilities.py script to add more
// test data here. This will help ensure the data matches what the kernel
// reports for a real device and is entered correctly.
@@ -1100,6 +1141,11 @@ bool CapabilitiesToDeviceInfo(const DeviceCapabilities& capabilities,
return false;
devinfo->SetAbsEvents(&abs_bits[0], abs_bits.size());
+ std::vector<unsigned long> sw_bits;
+ if (!ParseBitfield(capabilities.sw, SW_CNT, &sw_bits))
+ return false;
+ devinfo->SetSwEvents(&sw_bits[0], sw_bits.size());
+
std::vector<unsigned long> msc_bits;
if (!ParseBitfield(capabilities.msc, MSC_CNT, &msc_bits))
return false;
diff --git a/chromium/ui/events/ozone/evdev/event_device_test_util.h b/chromium/ui/events/ozone/evdev/event_device_test_util.h
index b6c0b7c07c5..91d1206635e 100644
--- a/chromium/ui/events/ozone/evdev/event_device_test_util.h
+++ b/chromium/ui/events/ozone/evdev/event_device_test_util.h
@@ -91,6 +91,8 @@ extern const DeviceCapabilities kKohakuStylus;
extern const DeviceCapabilities kXboxElite;
extern const DeviceCapabilities kDrallionStylus;
extern const DeviceCapabilities kDellActivePenButton;
+extern const DeviceCapabilities kPuffMicrophoneMuteSwitch;
+extern const DeviceCapabilities kDrawciaStylusGarage;
} // namspace ui
#endif // UI_EVENTS_OZONE_EVDEV_EVENT_DEVICE_TEST_UTIL_H_
diff --git a/chromium/ui/events/ozone/evdev/event_factory_evdev.cc b/chromium/ui/events/ozone/evdev/event_factory_evdev.cc
index 519cadda1c1..364355e3118 100644
--- a/chromium/ui/events/ozone/evdev/event_factory_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/event_factory_evdev.cc
@@ -15,6 +15,7 @@
#include "base/trace_event/trace_event.h"
#include "ui/events/devices/device_data_manager.h"
#include "ui/events/devices/input_device.h"
+#include "ui/events/devices/microphone_mute_switch_monitor.h"
#include "ui/events/event_utils.h"
#include "ui/events/ozone/device/device_event.h"
#include "ui/events/ozone/device/device_manager.h"
@@ -136,6 +137,14 @@ class ProxyDeviceEventDispatcher : public DeviceEventDispatcherEvdev {
event_factory_evdev_, stylus_state));
}
+ void DispatchMicrophoneMuteSwitchValueChanged(bool muted) override {
+ ui_thread_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &EventFactoryEvdev::DispatchMicrophoneMuteSwitchValueChanged,
+ event_factory_evdev_, muted));
+ }
+
void DispatchGamepadDevicesUpdated(
const std::vector<GamepadDevice>& devices) override {
ui_thread_runner_->PostTask(
@@ -433,6 +442,12 @@ void EventFactoryEvdev::DispatchStylusStateChanged(StylusState stylus_state) {
observer->OnStylusStateChanged(stylus_state);
}
+void EventFactoryEvdev::DispatchMicrophoneMuteSwitchValueChanged(bool muted) {
+ TRACE_EVENT0("evdev",
+ "EventFactoryEvdev::DispatchMicrophoneMuteSwitchValueChanged");
+ MicrophoneMuteSwitchMonitor::Get()->SetMicrophoneMuteSwitchValue(muted);
+}
+
void EventFactoryEvdev::DispatchUncategorizedDevicesUpdated(
const std::vector<InputDevice>& devices) {
TRACE_EVENT0("evdev",
diff --git a/chromium/ui/events/ozone/evdev/event_factory_evdev.h b/chromium/ui/events/ozone/evdev/event_factory_evdev.h
index de4498f447e..e40eea4dc46 100644
--- a/chromium/ui/events/ozone/evdev/event_factory_evdev.h
+++ b/chromium/ui/events/ozone/evdev/event_factory_evdev.h
@@ -8,7 +8,6 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/component_export.h"
-#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/task_runner.h"
@@ -87,6 +86,7 @@ class COMPONENT_EXPORT(EVDEV) EventFactoryEvdev : public DeviceEventObserver,
const std::vector<InputDevice>& devices);
void DispatchDeviceListsComplete();
void DispatchStylusStateChanged(StylusState stylus_state);
+ void DispatchMicrophoneMuteSwitchValueChanged(bool muted);
// Gamepad event and gamepad device event. These events are dispatched to
// GamepadObserver through GamepadProviderOzone.
diff --git a/chromium/ui/events/ozone/evdev/event_factory_evdev_unittest.cc b/chromium/ui/events/ozone/evdev/event_factory_evdev_unittest.cc
index ac57d231fda..f9c13253bb0 100644
--- a/chromium/ui/events/ozone/evdev/event_factory_evdev_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/event_factory_evdev_unittest.cc
@@ -4,11 +4,11 @@
#include "ui/events/ozone/evdev/event_factory_evdev.h"
-#include "base/optional.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/ozone/device/device_manager.h"
#include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h"
diff --git a/chromium/ui/events/ozone/evdev/event_thread_evdev.cc b/chromium/ui/events/ozone/evdev/event_thread_evdev.cc
index 99aa8998a6c..14f6ed14f36 100644
--- a/chromium/ui/events/ozone/evdev/event_thread_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/event_thread_evdev.cc
@@ -4,6 +4,7 @@
#include "ui/events/ozone/evdev/event_thread_evdev.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -80,12 +81,12 @@ void EventThreadEvdev::Start(
CursorDelegateEvdev* cursor,
EventThreadStartCallback callback) {
TRACE_EVENT0("evdev", "EventThreadEvdev::Start");
- thread_.reset(
- new EvdevThread(std::move(dispatcher), cursor, std::move(callback)));
+ thread_ = std::make_unique<EvdevThread>(std::move(dispatcher), cursor,
+ std::move(callback));
base::Thread::Options thread_options;
thread_options.message_pump_type = base::MessagePumpType::UI;
thread_options.priority = base::ThreadPriority::DISPLAY;
- if (!thread_->StartWithOptions(thread_options))
+ if (!thread_->StartWithOptions(std::move(thread_options)))
LOG(FATAL) << "Failed to create input thread";
}
diff --git a/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev.h b/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev.h
index 28960b800a9..290c920634c 100644
--- a/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev.h
+++ b/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_OZONE_GAMEPAD_EVENT_CONVERTER_EVDEV_H_
-#define UI_EVENTS_OZONE_GAMEPAD_EVENT_CONVERTER_EVDEV_H_
+#ifndef UI_EVENTS_OZONE_EVDEV_GAMEPAD_EVENT_CONVERTER_EVDEV_H_
+#define UI_EVENTS_OZONE_EVDEV_GAMEPAD_EVENT_CONVERTER_EVDEV_H_
#include <vector>
@@ -127,4 +127,4 @@ class COMPONENT_EXPORT(EVDEV) GamepadEventConverterEvdev
} // namespace ui
-#endif // UI_EVENTS_OZONE_GAMEPAD_EVENT_CONVERTER_EVDEV_H_
+#endif // UI_EVENTS_OZONE_EVDEV_GAMEPAD_EVENT_CONVERTER_EVDEV_H_
diff --git a/chromium/ui/events/ozone/evdev/input_controller_evdev.cc b/chromium/ui/events/ozone/evdev/input_controller_evdev.cc
index a039ca65db5..70c15bf393c 100644
--- a/chromium/ui/events/ozone/evdev/input_controller_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/input_controller_evdev.cc
@@ -14,6 +14,7 @@
#include "base/callback.h"
#include "base/threading/thread_task_runner_handle.h"
#include "ui/events/devices/device_data_manager.h"
+#include "ui/events/devices/stylus_state.h"
#include "ui/events/ozone/evdev/input_device_factory_evdev_proxy.h"
#include "ui/events/ozone/evdev/keyboard_evdev.h"
#include "ui/events/ozone/evdev/mouse_button_map_evdev.h"
@@ -248,6 +249,14 @@ void InputControllerEvdev::SetTapToClickPaused(bool state) {
ScheduleUpdateDeviceSettings();
}
+void InputControllerEvdev::GetStylusSwitchState(
+ GetStylusSwitchStateReply reply) {
+ if (input_device_factory_)
+ input_device_factory_->GetStylusSwitchState(std::move(reply));
+ else
+ std::move(reply).Run(ui::StylusState::REMOVED);
+}
+
void InputControllerEvdev::GetTouchDeviceStatus(
GetTouchDeviceStatusReply reply) {
if (input_device_factory_)
diff --git a/chromium/ui/events/ozone/evdev/input_controller_evdev.h b/chromium/ui/events/ozone/evdev/input_controller_evdev.h
index 49ece6de5f4..16e53e579c1 100644
--- a/chromium/ui/events/ozone/evdev/input_controller_evdev.h
+++ b/chromium/ui/events/ozone/evdev/input_controller_evdev.h
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "ui/events/devices/stylus_state.h"
#include "ui/events/ozone/evdev/input_device_settings_evdev.h"
#include "ui/ozone/public/input_controller.h"
@@ -77,6 +78,7 @@ class COMPONENT_EXPORT(EVDEV) InputControllerEvdev : public InputController {
void GetTouchDeviceStatus(GetTouchDeviceStatusReply reply) override;
void GetTouchEventLog(const base::FilePath& out_dir,
GetTouchEventLogReply reply) override;
+ void GetStylusSwitchState(GetStylusSwitchStateReply reply) override;
void SetInternalTouchpadEnabled(bool enabled) override;
bool IsInternalTouchpadEnabled() const override;
void SetTouchscreensEnabled(bool enabled) override;
diff --git a/chromium/ui/events/ozone/evdev/input_device_factory_evdev.cc b/chromium/ui/events/ozone/evdev/input_device_factory_evdev.cc
index c75707baf58..0228268961d 100644
--- a/chromium/ui/events/ozone/evdev/input_device_factory_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/input_device_factory_evdev.cc
@@ -11,6 +11,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/files/scoped_file.h"
#include "base/memory/ptr_util.h"
@@ -19,11 +20,14 @@
#include "base/trace_event/trace_event.h"
#include "ui/events/devices/device_data_manager.h"
#include "ui/events/devices/device_util_linux.h"
+#include "ui/events/devices/stylus_state.h"
#include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h"
#include "ui/events/ozone/evdev/event_converter_evdev_impl.h"
#include "ui/events/ozone/evdev/event_device_info.h"
#include "ui/events/ozone/evdev/gamepad_event_converter_evdev.h"
+#include "ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev.h"
#include "ui/events/ozone/evdev/stylus_button_event_converter_evdev.h"
+#include "ui/events/ozone/evdev/switches.h"
#include "ui/events/ozone/evdev/tablet_event_converter_evdev.h"
#include "ui/events/ozone/evdev/touch_event_converter_evdev.h"
#include "ui/events/ozone/features.h"
@@ -131,6 +135,14 @@ std::unique_ptr<EventConverterEvdev> CreateConverter(
std::move(fd), params.path, params.id, devinfo, params.dispatcher));
}
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ kEnableMicrophoneMuteSwitchDeviceSwitch) &&
+ devinfo.IsMicrophoneMuteSwitchDevice()) {
+ return base::WrapUnique<EventConverterEvdev>(
+ new MicrophoneMuteSwitchEventConverterEvdev(
+ std::move(fd), params.path, params.id, devinfo, params.dispatcher));
+ }
+
// Everything else: use EventConverterEvdevImpl.
return base::WrapUnique<EventConverterEvdevImpl>(
new EventConverterEvdevImpl(std::move(fd), params.path, params.id,
@@ -275,6 +287,18 @@ void InputDeviceFactoryEvdev::DetachInputDevice(const base::FilePath& path) {
}
}
+void InputDeviceFactoryEvdev::GetStylusSwitchState(
+ InputController::GetStylusSwitchStateReply reply) {
+ for (const auto& it : converters_) {
+ if (it.second->HasStylusSwitch()) {
+ auto result = it.second->GetStylusSwitchState();
+ std::move(reply).Run(result);
+ return;
+ }
+ }
+ std::move(reply).Run(ui::StylusState::REMOVED);
+}
+
void InputDeviceFactoryEvdev::SetCapsLockLed(bool enabled) {
caps_lock_led_enabled_ = enabled;
ApplyCapsLockLed();
@@ -494,11 +518,27 @@ void InputDeviceFactoryEvdev::NotifyDevicesUpdated() {
void InputDeviceFactoryEvdev::NotifyTouchscreensUpdated() {
std::vector<TouchscreenDevice> touchscreens;
- for (auto it = converters_.begin(); it != converters_.end(); ++it) {
- if (it->second->HasTouchscreen()) {
+ bool has_stylus_switch = false;
+
+ // Check if there is a stylus garage/dock presence detection switch
+ // among the devices. The internal touchscreen controller is not currently
+ // responsible for exposing this device, it usually is a gpio-keys
+ // device only containing the single switch.
+
+ for (const auto& it : converters_) {
+ if (it.second->HasStylusSwitch()) {
+ has_stylus_switch = true;
+ break;
+ }
+ }
+
+ for (const auto& it : converters_) {
+ if (it.second->HasTouchscreen()) {
touchscreens.emplace_back(
- it->second->input_device(), it->second->GetTouchscreenSize(),
- it->second->GetTouchPoints(), it->second->HasPen());
+ it.second->input_device(), it.second->GetTouchscreenSize(),
+ it.second->GetTouchPoints(), it.second->HasPen(),
+ it.second->type() == ui::InputDeviceType::INPUT_DEVICE_INTERNAL &&
+ has_stylus_switch);
}
}
diff --git a/chromium/ui/events/ozone/evdev/input_device_factory_evdev.h b/chromium/ui/events/ozone/evdev/input_device_factory_evdev.h
index 1cd73a736fa..9b39da15f03 100644
--- a/chromium/ui/events/ozone/evdev/input_device_factory_evdev.h
+++ b/chromium/ui/events/ozone/evdev/input_device_factory_evdev.h
@@ -62,6 +62,8 @@ class COMPONENT_EXPORT(EVDEV) InputDeviceFactoryEvdev {
// LED state.
void SetCapsLockLed(bool enabled);
+ void GetStylusSwitchState(InputController::GetStylusSwitchStateReply reply);
+
// Handle gamepad force feedback effects.
void PlayVibrationEffect(int id, uint8_t amplitude, uint16_t duration_millis);
void StopVibration(int id);
diff --git a/chromium/ui/events/ozone/evdev/input_device_factory_evdev_proxy.cc b/chromium/ui/events/ozone/evdev/input_device_factory_evdev_proxy.cc
index 9767cbdfd18..d7ea386cdfc 100644
--- a/chromium/ui/events/ozone/evdev/input_device_factory_evdev_proxy.cc
+++ b/chromium/ui/events/ozone/evdev/input_device_factory_evdev_proxy.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "ui/events/devices/stylus_state.h"
#include "ui/events/ozone/evdev/input_device_factory_evdev.h"
namespace ui {
@@ -32,6 +33,14 @@ void ForwardGetTouchEventLogReply(
base::BindOnce(std::move(reply), log_paths));
}
+void ForwardGetStylusSwitchStateReply(
+ scoped_refptr<base::SingleThreadTaskRunner> reply_runner,
+ InputController::GetStylusSwitchStateReply reply,
+ ui::StylusState state) {
+ // Thread hop back to UI for reply.
+ reply_runner->PostTask(FROM_HERE, base::BindOnce(std::move(reply), state));
+}
+
} // namespace
InputDeviceFactoryEvdevProxy::InputDeviceFactoryEvdevProxy(
@@ -69,6 +78,17 @@ void InputDeviceFactoryEvdevProxy::SetCapsLockLed(bool enabled) {
input_device_factory_, enabled));
}
+void InputDeviceFactoryEvdevProxy::GetStylusSwitchState(
+ InputController::GetStylusSwitchStateReply reply) {
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&InputDeviceFactoryEvdev::GetStylusSwitchState,
+ input_device_factory_,
+ base::BindOnce(&ForwardGetStylusSwitchStateReply,
+ base::ThreadTaskRunnerHandle::Get(),
+ std::move(reply))));
+}
+
void InputDeviceFactoryEvdevProxy::UpdateInputDeviceSettings(
const InputDeviceSettingsEvdev& settings) {
task_runner_->PostTask(
diff --git a/chromium/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h b/chromium/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h
index 94dc5cb92c8..bbf3c9fd1d9 100644
--- a/chromium/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h
+++ b/chromium/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h
@@ -5,9 +5,6 @@
#ifndef UI_EVENTS_OZONE_EVDEV_INPUT_DEVICE_FACTORY_EVDEV_PROXY_H_
#define UI_EVENTS_OZONE_EVDEV_INPUT_DEVICE_FACTORY_EVDEV_PROXY_H_
-#include <memory>
-#include <set>
-#include <vector>
#include "base/compiler_specific.h"
#include "base/component_export.h"
@@ -42,6 +39,7 @@ class COMPONENT_EXPORT(EVDEV) InputDeviceFactoryEvdevProxy {
void RemoveInputDevice(const base::FilePath& path);
void OnStartupScanComplete();
void SetCapsLockLed(bool enabled);
+ void GetStylusSwitchState(InputController::GetStylusSwitchStateReply reply);
void SetTouchEventLoggingEnabled(bool enabled);
void UpdateInputDeviceSettings(const InputDeviceSettingsEvdev& settings);
void GetTouchDeviceStatus(InputController::GetTouchDeviceStatusReply reply);
diff --git a/chromium/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc b/chromium/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc
index 110850f1d7e..748c91403e5 100644
--- a/chromium/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc
+++ b/chromium/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc
@@ -46,6 +46,7 @@ EventReaderLibevdevCros::EventReaderLibevdevCros(
has_mouse_(devinfo.HasMouse()),
has_pointing_stick_(devinfo.HasPointingStick()),
has_touchpad_(devinfo.HasTouchpad()),
+ has_stylus_switch_(devinfo.HasSwEvent(SW_PEN_INSERTED)),
has_caps_lock_led_(devinfo.HasLedEvent(LED_CAPSL)),
delegate_(std::move(delegate)) {
// This class assumes it does not deal with internal keyboards.
@@ -108,6 +109,10 @@ bool EventReaderLibevdevCros::HasCapsLockLed() const {
return has_caps_lock_led_;
}
+bool EventReaderLibevdevCros::HasStylusSwitch() const {
+ return has_stylus_switch_;
+}
+
void EventReaderLibevdevCros::OnDisabled() {
delegate_->OnLibEvdevCrosStopped(&evdev_, &evstate_);
}
diff --git a/chromium/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h b/chromium/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h
index 722e46508ed..b2759bd42a3 100644
--- a/chromium/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h
+++ b/chromium/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h
@@ -56,6 +56,7 @@ class EventReaderLibevdevCros : public EventConverterEvdev {
bool HasPointingStick() const override;
bool HasTouchpad() const override;
bool HasCapsLockLed() const override;
+ bool HasStylusSwitch() const override;
void OnDisabled() override;
private:
@@ -69,6 +70,7 @@ class EventReaderLibevdevCros : public EventConverterEvdev {
bool has_mouse_;
bool has_pointing_stick_;
bool has_touchpad_;
+ bool has_stylus_switch_;
// LEDs for this device.
bool has_caps_lock_led_;
diff --git a/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_properties_service.h b/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_properties_service.h
index 72c6117a6f7..a698c429309 100644
--- a/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_properties_service.h
+++ b/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_properties_service.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_OZONE_CHROMEOS_GESTURE_PROPERTIES_SERVICE_H_
-#define UI_EVENTS_OZONE_CHROMEOS_GESTURE_PROPERTIES_SERVICE_H_
+#ifndef UI_EVENTS_OZONE_EVDEV_LIBGESTURES_GLUE_GESTURE_PROPERTIES_SERVICE_H_
+#define UI_EVENTS_OZONE_EVDEV_LIBGESTURES_GLUE_GESTURE_PROPERTIES_SERVICE_H_
#include "base/component_export.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -41,4 +41,4 @@ class COMPONENT_EXPORT(EVDEV) GesturePropertiesService
} // namespace ui
-#endif // UI_EVENTS_OZONE_CHROMEOS_GESTURE_PROPERTIES_SERVICE_H_
+#endif // UI_EVENTS_OZONE_EVDEV_LIBGESTURES_GLUE_GESTURE_PROPERTIES_SERVICE_H_
diff --git a/chromium/ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev.cc b/chromium/ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev.cc
new file mode 100644
index 00000000000..66d2db70a7d
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev.cc
@@ -0,0 +1,95 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev.h"
+
+#include <errno.h>
+#include <linux/input.h>
+
+#include "base/logging.h"
+#include "base/trace_event/trace_event.h"
+#include "ui/events/event_utils.h"
+#include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h"
+#include "ui/events/ozone/evdev/event_device_util.h"
+
+namespace ui {
+
+namespace {
+
+int32_t GetSwValue(int fd, unsigned int code) {
+ unsigned long bitmask[EVDEV_BITS_TO_LONGS(SW_MAX)] = {0};
+ if (ioctl(fd, EVIOCGSW(sizeof(bitmask)), bitmask) < 0) {
+ PLOG(ERROR) << "Failed EVIOCGSW";
+ return 0;
+ }
+ return EvdevBitIsSet(bitmask, code);
+}
+
+} // namespace
+
+MicrophoneMuteSwitchEventConverterEvdev::
+ MicrophoneMuteSwitchEventConverterEvdev(
+ base::ScopedFD fd,
+ base::FilePath path,
+ int id,
+ const EventDeviceInfo& devinfo,
+ DeviceEventDispatcherEvdev* dispatcher)
+ : EventConverterEvdev(fd.get(),
+ path,
+ id,
+ devinfo.device_type(),
+ devinfo.name(),
+ devinfo.phys(),
+ devinfo.vendor_id(),
+ devinfo.product_id(),
+ devinfo.version()),
+ input_device_fd_(std::move(fd)),
+ dispatcher_(dispatcher) {
+ DCHECK(devinfo.IsMicrophoneMuteSwitchDevice());
+}
+
+MicrophoneMuteSwitchEventConverterEvdev::
+ ~MicrophoneMuteSwitchEventConverterEvdev() = default;
+
+void MicrophoneMuteSwitchEventConverterEvdev::OnDisabled() {
+ dispatcher_->DispatchMicrophoneMuteSwitchValueChanged(false);
+}
+
+void MicrophoneMuteSwitchEventConverterEvdev::OnEnabled() {
+ // Send out the initial switch state, as clients (e.g. system UI) depend on
+ // the current mute switch state.
+ dispatcher_->DispatchMicrophoneMuteSwitchValueChanged(
+ GetSwValue(input_device_fd_.get(), SW_MUTE_DEVICE));
+}
+
+void MicrophoneMuteSwitchEventConverterEvdev::OnFileCanReadWithoutBlocking(
+ int fd) {
+ TRACE_EVENT1(
+ "evdev",
+ "MicrophoneMuteSwitchEventConverterEvdev::OnFileCanReadWithoutBlocking",
+ "fd", fd);
+
+ while (true) {
+ input_event input;
+ ssize_t read_size = read(fd, &input, sizeof(input));
+ if (read_size != sizeof(input)) {
+ if (errno == EINTR || errno == EAGAIN)
+ return;
+ if (errno != ENODEV)
+ PLOG(ERROR) << "error reading device " << path_.value();
+ Stop();
+ return;
+ }
+
+ ProcessEvent(input);
+ }
+}
+
+void MicrophoneMuteSwitchEventConverterEvdev::ProcessEvent(
+ const input_event& input) {
+ if (input.type == EV_SW && input.code == SW_MUTE_DEVICE)
+ dispatcher_->DispatchMicrophoneMuteSwitchValueChanged(input.value);
+}
+
+} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev.h b/chromium/ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev.h
new file mode 100644
index 00000000000..476ebb46a7e
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev.h
@@ -0,0 +1,51 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_OZONE_EVDEV_MICROPHONE_MUTE_SWITCH_EVENT_CONVERTER_EVDEV_H_
+#define UI_EVENTS_OZONE_EVDEV_MICROPHONE_MUTE_SWITCH_EVENT_CONVERTER_EVDEV_H_
+
+#include "base/component_export.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_file.h"
+#include "base/macros.h"
+#include "ui/events/ozone/evdev/event_converter_evdev.h"
+#include "ui/events/ozone/evdev/event_device_info.h"
+
+namespace ui {
+
+class DeviceEventDispatcherEvdev;
+
+class COMPONENT_EXPORT(EVDEV) MicrophoneMuteSwitchEventConverterEvdev
+ : public EventConverterEvdev {
+ public:
+ MicrophoneMuteSwitchEventConverterEvdev(
+ base::ScopedFD fd,
+ base::FilePath path,
+ int id,
+ const EventDeviceInfo& devinfo,
+ DeviceEventDispatcherEvdev* dispatcher);
+ MicrophoneMuteSwitchEventConverterEvdev(
+ const MicrophoneMuteSwitchEventConverterEvdev&) = delete;
+ MicrophoneMuteSwitchEventConverterEvdev& operator=(
+ const MicrophoneMuteSwitchEventConverterEvdev&) = delete;
+ ~MicrophoneMuteSwitchEventConverterEvdev() override;
+
+ // EventConverterEvdev
+ void OnDisabled() override;
+ void OnEnabled() override;
+ void OnFileCanReadWithoutBlocking(int fd) override;
+
+ void ProcessEvent(const struct input_event& input);
+
+ private:
+ // Input device file descriptor.
+ const base::ScopedFD input_device_fd_;
+
+ // Callbacks for dispatching events.
+ DeviceEventDispatcherEvdev* const dispatcher_;
+};
+
+} // namespace ui
+
+#endif // UI_EVENTS_OZONE_EVDEV_MICROPHONE_MUTE_SWITCH_EVENT_CONVERTER_EVDEV_H_
diff --git a/chromium/ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev_unittest.cc b/chromium/ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev_unittest.cc
new file mode 100644
index 00000000000..1b31f563937
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev_unittest.cc
@@ -0,0 +1,140 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/input.h>
+#include <unistd.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/files/scoped_file.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/devices/microphone_mute_switch_monitor.h"
+#include "ui/events/ozone/device/device_manager.h"
+#include "ui/events/ozone/evdev/event_converter_test_util.h"
+#include "ui/events/ozone/evdev/event_device_test_util.h"
+#include "ui/events/ozone/evdev/event_factory_evdev.h"
+#include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
+
+namespace {
+
+const char kTestDevicePath[] = "/dev/input/test-device";
+
+class TestMicrophoneMuteObserver
+ : public ui::MicrophoneMuteSwitchMonitor::Observer {
+ public:
+ TestMicrophoneMuteObserver() {
+ ui::MicrophoneMuteSwitchMonitor::Get()->AddObserver(this);
+ }
+ TestMicrophoneMuteObserver(const TestMicrophoneMuteObserver&) = delete;
+ TestMicrophoneMuteObserver& operator=(const TestMicrophoneMuteObserver&) =
+ delete;
+ ~TestMicrophoneMuteObserver() override {
+ ui::MicrophoneMuteSwitchMonitor::Get()->RemoveObserver(this);
+ }
+
+ void OnMicrophoneMuteSwitchValueChanged(bool muted) override {
+ observed_values_.push_back(muted);
+ }
+
+ std::vector<bool> GetAndResetObservedValues() {
+ std::vector<bool> result;
+ result.swap(observed_values_);
+ return result;
+ }
+
+ private:
+ std::vector<bool> observed_values_;
+};
+
+} // namespace
+
+class MicrophoneMuteSwitchEventConverterEvdevTest : public testing::Test {
+ public:
+ MicrophoneMuteSwitchEventConverterEvdevTest() = default;
+ ~MicrophoneMuteSwitchEventConverterEvdevTest() override = default;
+
+ // Overridden from testing::Test:
+ void SetUp() override {
+ device_manager_ = ui::CreateDeviceManagerForTest();
+ keyboard_layout_engine_ = std::make_unique<ui::StubKeyboardLayoutEngine>();
+ event_factory_ = ui::CreateEventFactoryEvdevForTest(
+ nullptr, device_manager_.get(), keyboard_layout_engine_.get(),
+ base::BindRepeating([](ui::Event* event) {
+ ADD_FAILURE() << "Unexpected event dispatch " << event->ToString();
+ }));
+ dispatcher_ =
+ ui::CreateDeviceEventDispatcherEvdevForTest(event_factory_.get());
+ }
+ void TearDown() override {
+ // Reset any switch value that might have been changed during the test.
+ ui::MicrophoneMuteSwitchMonitor::Get()->SetMicrophoneMuteSwitchValue(false);
+ }
+
+ std::unique_ptr<ui::MicrophoneMuteSwitchEventConverterEvdev> CreateDevice(
+ const ui::DeviceCapabilities& caps) {
+ int evdev_io[2];
+ if (pipe(evdev_io))
+ PLOG(FATAL) << "failed pipe";
+ base::ScopedFD events_in(evdev_io[0]);
+ events_out_.reset(evdev_io[1]);
+
+ ui::EventDeviceInfo devinfo;
+ CapabilitiesToDeviceInfo(caps, &devinfo);
+ // The internal device type is derived from sysfs subsystem symlink on DUT.
+ // Unittest doesn't run GetInputDeviceTypeFromPath. Set it here manually.
+ devinfo.SetDeviceType(ui::InputDeviceType::INPUT_DEVICE_INTERNAL);
+ return std::make_unique<ui::MicrophoneMuteSwitchEventConverterEvdev>(
+ std::move(events_in), base::FilePath(kTestDevicePath), 1, devinfo,
+ dispatcher_.get());
+ }
+
+ private:
+ std::unique_ptr<ui::DeviceManager> device_manager_;
+ std::unique_ptr<ui::KeyboardLayoutEngine> keyboard_layout_engine_;
+ std::unique_ptr<ui::EventFactoryEvdev> event_factory_;
+ std::unique_ptr<ui::DeviceEventDispatcherEvdev> dispatcher_;
+
+ std::vector<std::unique_ptr<ui::Event>> dispatched_events_;
+
+ base::ScopedFD events_out_;
+};
+
+TEST_F(MicrophoneMuteSwitchEventConverterEvdevTest, MuteChangeEvents) {
+ TestMicrophoneMuteObserver test_observer;
+
+ std::unique_ptr<ui::MicrophoneMuteSwitchEventConverterEvdev> dev =
+ CreateDevice(ui::kPuffMicrophoneMuteSwitch);
+
+ EXPECT_FALSE(
+ ui::MicrophoneMuteSwitchMonitor::Get()->microphone_mute_switch_on());
+
+ struct input_event mock_mute_kernel_queue[] = {
+ {{0, 0}, EV_SW, SW_MUTE_DEVICE, 1},
+ {{0, 0}, EV_SYN, SYN_REPORT, 0},
+ };
+
+ for (auto& event : mock_mute_kernel_queue)
+ dev->ProcessEvent(event);
+
+ EXPECT_TRUE(
+ ui::MicrophoneMuteSwitchMonitor::Get()->microphone_mute_switch_on());
+ EXPECT_EQ(std::vector<bool>{true}, test_observer.GetAndResetObservedValues());
+
+ struct input_event mock_unmute_kernel_queue[] = {
+ {{0, 0}, EV_SW, SW_MUTE_DEVICE, 0},
+ {{0, 0}, EV_SYN, SYN_REPORT, 0},
+ };
+
+ for (auto& event : mock_unmute_kernel_queue)
+ dev->ProcessEvent(event);
+
+ EXPECT_EQ(std::vector<bool>{false},
+ test_observer.GetAndResetObservedValues());
+}
diff --git a/chromium/ui/events/ozone/evdev/switches.cc b/chromium/ui/events/ozone/evdev/switches.cc
new file mode 100644
index 00000000000..a83cb0c7a07
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/switches.cc
@@ -0,0 +1,14 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/ozone/evdev/switches.h"
+
+namespace ui {
+
+// Enables logic to detect microphone mute switch device state, which disables
+// internal audio input when toggled.
+constexpr char kEnableMicrophoneMuteSwitchDeviceSwitch[] =
+ "enable-microphone-mute-switch-device";
+
+} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/switches.h b/chromium/ui/events/ozone/evdev/switches.h
new file mode 100644
index 00000000000..40965055a14
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/switches.h
@@ -0,0 +1,17 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_OZONE_EVDEV_SWITCHES_H_
+#define UI_EVENTS_OZONE_EVDEV_SWITCHES_H_
+
+#include "base/component_export.h"
+
+namespace ui {
+
+COMPONENT_EXPORT(EVDEV)
+extern const char kEnableMicrophoneMuteSwitchDeviceSwitch[];
+
+} // namespace ui
+
+#endif // UI_EVENTS_OZONE_EVDEV_SWITCHES_H_
diff --git a/chromium/ui/events/ozone/evdev/tablet_event_converter_evdev.h b/chromium/ui/events/ozone/evdev/tablet_event_converter_evdev.h
index c7914cd7e2b..a1dcc4e9356 100644
--- a/chromium/ui/events/ozone/evdev/tablet_event_converter_evdev.h
+++ b/chromium/ui/events/ozone/evdev/tablet_event_converter_evdev.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_OZONE_TABLET_EVENT_CONVERTER_EVDEV_H_
-#define UI_EVENTS_OZONE_TABLET_EVENT_CONVERTER_EVDEV_H_
+#ifndef UI_EVENTS_OZONE_EVDEV_TABLET_EVENT_CONVERTER_EVDEV_H_
+#define UI_EVENTS_OZONE_EVDEV_TABLET_EVENT_CONVERTER_EVDEV_H_
#include "base/component_export.h"
#include "base/files/file_path.h"
@@ -95,4 +95,4 @@ class COMPONENT_EXPORT(EVDEV) TabletEventConverterEvdev
} // namespace ui
-#endif // UI_EVENTS_OZONE_TABLET_EVENT_CONVERTER_EVDEV_H_
+#endif // UI_EVENTS_OZONE_EVDEV_TABLET_EVENT_CONVERTER_EVDEV_H_
diff --git a/chromium/ui/events/ozone/evdev/touch_evdev_debug_buffer.h b/chromium/ui/events/ozone/evdev/touch_evdev_debug_buffer.h
index 1f17608e94d..ff4fdef95a3 100644
--- a/chromium/ui/events/ozone/evdev/touch_evdev_debug_buffer.h
+++ b/chromium/ui/events/ozone/evdev/touch_evdev_debug_buffer.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_OZONE_EVDEV_TOUCH_DEBUG_BUFFER_H_
-#define UI_EVENTS_OZONE_EVDEV_TOUCH_DEBUG_BUFFER_H_
+#ifndef UI_EVENTS_OZONE_EVDEV_TOUCH_EVDEV_DEBUG_BUFFER_H_
+#define UI_EVENTS_OZONE_EVDEV_TOUCH_EVDEV_DEBUG_BUFFER_H_
#include <linux/input.h>
#include <stddef.h>
@@ -58,4 +58,4 @@ class COMPONENT_EXPORT(EVDEV) TouchEventLogEvdev {
} // namespace ui
-#endif // UI_EVENTS_OZONE_EVDEV_TOUCH_EVDEV_BUFFER_H_
+#endif // UI_EVENTS_OZONE_EVDEV_TOUCH_EVDEV_DEBUG_BUFFER_H_
diff --git a/chromium/ui/events/ozone/evdev/touch_evdev_types.h b/chromium/ui/events/ozone/evdev/touch_evdev_types.h
index 97224442dfb..0719d76c2e5 100644
--- a/chromium/ui/events/ozone/evdev/touch_evdev_types.h
+++ b/chromium/ui/events/ozone/evdev/touch_evdev_types.h
@@ -63,6 +63,7 @@ struct COMPONENT_EXPORT(EVDEV) InProgressTouchEvdev {
float radius_y = 0;
float pressure = 0;
int tool_code = 0;
+ int orientation = 0;
float tilt_x = 0;
float tilt_y = 0;
ui::EventPointerType reported_tool_type = ui::EventPointerType::kTouch;
diff --git a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.cc b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.cc
index 3daca1f98bf..6db763c93bd 100644
--- a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.cc
@@ -24,7 +24,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "ui/events/devices/device_data_manager.h"
#include "ui/events/devices/device_util_linux.h"
@@ -183,6 +182,8 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) {
std::min<int>(info.GetAbsMaximum(ABS_MT_SLOT) + 1, kNumTouchEvdevSlots);
major_max_ = info.GetAbsMaximum(ABS_MT_TOUCH_MAJOR);
current_slot_ = info.GetAbsValue(ABS_MT_SLOT);
+ orientation_min_ = info.GetAbsMinimum(ABS_MT_ORIENTATION);
+ orientation_max_ = info.GetAbsMaximum(ABS_MT_ORIENTATION);
} else {
pressure_min_ = info.GetAbsMinimum(ABS_PRESSURE);
pressure_max_ = info.GetAbsMaximum(ABS_PRESSURE);
@@ -197,13 +198,17 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) {
tilt_x_range_ = info.GetAbsMaximum(ABS_TILT_X) - tilt_x_min_ + 1;
tilt_y_range_ = info.GetAbsMaximum(ABS_TILT_Y) - tilt_y_min_ + 1;
+ // No orientation without mt.
+ orientation_min_ = orientation_max_ = 0;
touch_points_ = 1;
major_max_ = 0;
current_slot_ = 0;
}
- touch_major_scale_ = GetFingerSizeScale(touch_major_res, x_res);
- touch_minor_scale_ = GetFingerSizeScale(touch_minor_res, y_res);
+ x_scale_ = GetFingerSizeScale(touch_major_res, x_res) / 2.0f;
+ y_scale_ = GetFingerSizeScale(touch_minor_res, y_res) / 2.0f;
+ rotated_x_scale_ = GetFingerSizeScale(touch_minor_res, x_res) / 2.0f;
+ rotated_y_scale_ = GetFingerSizeScale(touch_major_res, y_res) / 2.0f;
quirk_left_mouse_button_ =
!has_mt_ && !info.HasKeyEvent(BTN_TOUCH) && info.HasKeyEvent(BTN_LEFT);
@@ -230,8 +235,8 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) {
info.GetAbsMtSlotValueWithDefault(ABS_MT_TOUCH_MAJOR, i, 0);
int touch_minor =
info.GetAbsMtSlotValueWithDefault(ABS_MT_TOUCH_MINOR, i, 0);
- events_[i].radius_x = touch_major * touch_major_scale_ / 2.0f;
- events_[i].radius_y = touch_minor * touch_minor_scale_ / 2.0f;
+ events_[i].orientation =
+ info.GetAbsMtSlotValueWithDefault(ABS_MT_ORIENTATION, i, 0);
events_[i].pressure = ScalePressure(
info.GetAbsMtSlotValueWithDefault(ABS_MT_PRESSURE, i, 0));
int tool_type = info.GetAbsMtSlotValueWithDefault(ABS_MT_TOOL_TYPE, i,
@@ -253,6 +258,7 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) {
events_[0].slot = 0;
events_[0].radius_x = 0;
events_[0].radius_y = 0;
+ events_[0].orientation = 0;
events_[0].pressure = 0;
events_[0].tool_code = 0;
events_[0].tilt_x = 0;
@@ -419,16 +425,14 @@ void TouchEventConverterEvdev::ProcessKey(const input_event& input) {
void TouchEventConverterEvdev::ProcessAbs(const input_event& input) {
switch (input.code) {
case ABS_MT_TOUCH_MAJOR:
- // TODO(spang): If we have all of major, minor, and orientation,
- // we can scale the ellipse correctly. However on the Pixel we get
- // neither minor nor orientation, so this is all we can do.
- events_[current_slot_].radius_x = input.value * touch_major_scale_ / 2.0f;
events_[current_slot_].major = input.value;
break;
case ABS_MT_TOUCH_MINOR:
- events_[current_slot_].radius_y = input.value * touch_minor_scale_ / 2.0f;
events_[current_slot_].minor = input.value;
break;
+ case ABS_MT_ORIENTATION:
+ events_[current_slot_].orientation = input.value;
+ break;
case ABS_MT_POSITION_X:
events_[current_slot_].x = input.value;
break;
@@ -649,8 +653,10 @@ void TouchEventConverterEvdev::ProcessTouchEvent(InProgressTouchEvdev* event,
// The tool type is fixed with the touch pressed event and does not change.
if (event_type == ET_TOUCH_PRESSED)
event->reported_tool_type = GetEventPointerType(event->tool_code);
- if (event_type != ET_UNKNOWN)
+ if (event_type != ET_UNKNOWN) {
+ UpdateRadiusFromTouchWithOrientation(event);
ReportTouchEvent(*event, event_type, timestamp);
+ }
}
void TouchEventConverterEvdev::UpdateTrackingId(int slot, int tracking_id) {
@@ -688,6 +694,23 @@ float TouchEventConverterEvdev::ScalePressure(int32_t value) const {
return pressure;
}
+bool TouchEventConverterEvdev::SupportsOrientation() const {
+ // TODO(b/185318572): Support more complex orientation reports than the
+ // simplified 0/1.
+ return orientation_max_ == 1 && orientation_min_ == 0;
+}
+
+void TouchEventConverterEvdev::UpdateRadiusFromTouchWithOrientation(
+ InProgressTouchEvdev* event) const {
+ if (!SupportsOrientation() || event->orientation == 1) {
+ event->radius_x = event->major * x_scale_;
+ event->radius_y = event->minor * y_scale_;
+ } else {
+ event->radius_x = event->minor * rotated_x_scale_;
+ event->radius_y = event->major * rotated_y_scale_;
+ }
+}
+
int TouchEventConverterEvdev::NextTrackingId() {
return next_tracking_id_++ & kMaxTrackingId;
}
diff --git a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.h b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.h
index 276d71e2c9f..59062a43439 100644
--- a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.h
+++ b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.h
@@ -118,6 +118,9 @@ class COMPONENT_EXPORT(EVDEV) TouchEventConverterEvdev
// Normalize pressure value to [0, 1].
float ScalePressure(int32_t value) const;
+ bool SupportsOrientation() const;
+ void UpdateRadiusFromTouchWithOrientation(InProgressTouchEvdev* event) const;
+
int NextTrackingId();
// Input device file descriptor.
@@ -142,6 +145,10 @@ class COMPONENT_EXPORT(EVDEV) TouchEventConverterEvdev
int pressure_min_;
int pressure_max_; // Used to normalize pressure values.
+ // Orientation values.
+ int orientation_min_;
+ int orientation_max_;
+
// Input range for tilt.
int tilt_x_min_;
int tilt_x_range_;
@@ -159,8 +166,16 @@ class COMPONENT_EXPORT(EVDEV) TouchEventConverterEvdev
// The resolution of ABS_MT_TOUCH_MAJOR/MINOR might be different from the
// resolution of ABS_MT_POSITION_X/Y. As we use the (position range, display
// pixels) to resize touch event radius, we have to scale major/minor.
- float touch_major_scale_ = 1.0f;
- float touch_minor_scale_ = 1.0f;
+
+ // When the major axis is X, we precompute the scale for x_radius/y_radius
+ // from ABS_MT_TOUCH_MAJOR/ABS_MT_TOUCH_MINOR respectively.
+ float x_scale_ = 0.5f;
+ float y_scale_ = 0.5f;
+ // Since the x and y resolution can differ, we pre-compute the
+ // x_radius/y_radius scale from ABS_MT_TOUCH_MINOR/ABS_MT_TOUCH_MAJOR
+ // resolution respectively when ABS_MT_ORIENTATION is rotated.
+ float rotated_x_scale_ = 0.5f;
+ float rotated_y_scale_ = 0.5f;
// Number of touch points reported by driver
int touch_points_ = 0;
diff --git a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
index f105611663a..2c3f6b57514 100644
--- a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
@@ -159,6 +159,7 @@ class MockDeviceEventDispatcherEvdev : public DeviceEventDispatcherEvdev {
generic.touch = params;
callback_.Run(generic);
}
+ void DispatchMicrophoneMuteSwitchValueChanged(bool muted) override {}
void DispatchKeyboardDevicesUpdated(
const std::vector<InputDevice>& devices) override {}
@@ -238,7 +239,7 @@ class TouchEventConverterEvdevTest : public testing::Test {
void SetUp() override {
// By default, tests disable single-cancel and enable palm on touch_major ==
// major_max.
- scoped_feature_list_.reset(new base::test::ScopedFeatureList);
+ scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
scoped_feature_list_->InitWithFeatures(
{kEnablePalmOnMaxTouchMajor, kEnablePalmOnToolTypePalm},
{kEnableSingleCancelTouch});
@@ -741,7 +742,7 @@ TEST_F(TouchEventConverterEvdevTest, ShouldRemoveContactsWhenDisabled) {
TEST_F(TouchEventConverterEvdevTest, ToolTypePalmNotCancelTouch) {
// By default, we use TOOL_TYPE_PALM as a cancellation signal for all touches.
// We disable that behavior and want to see all touches registered as usual.
- scoped_feature_list_.reset(new base::test::ScopedFeatureList);
+ scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
scoped_feature_list_->InitWithFeatures(
{}, {kEnablePalmOnMaxTouchMajor, kEnablePalmOnToolTypePalm,
kEnableSingleCancelTouch});
@@ -837,7 +838,7 @@ TEST_F(TouchEventConverterEvdevTest, MaxMajorNotCancelTouch) {
// By default, tests disable single-cancel and enable palm on touch_major ==
// major_max. So we disable that behavior: and expect to see a RELEASED rather
// than cancelled.
- scoped_feature_list_.reset(new base::test::ScopedFeatureList);
+ scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
scoped_feature_list_->InitWithFeatures(
{}, {kEnablePalmOnMaxTouchMajor, kEnableSingleCancelTouch});
SetUpDevice();
@@ -1294,7 +1295,7 @@ TEST_F(TouchEventConverterEvdevTest, TrackingIdShouldNotResetCancelByPalm) {
TEST_F(TouchEventConverterEvdevTest,
TrackingIdShouldNotResetCancelByPalmSingleCancel) {
// Flip field to true.
- scoped_feature_list_.reset(new base::test::ScopedFeatureList);
+ scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
scoped_feature_list_->InitAndEnableFeature(kEnableSingleCancelTouch);
ui::MockTouchEventConverterEvdev* dev = device();
@@ -2211,6 +2212,52 @@ TEST_F(TouchEventConverterEvdevTest, HeldThenPalm) {
testing::ElementsAre(base::Bucket(4, 1)));
}
+TEST_F(TouchEventConverterEvdevTest, RotateRadius) {
+ EventDeviceInfo devinfo;
+ EXPECT_TRUE(CapabilitiesToDeviceInfo(kEveTouchScreen, &devinfo));
+ device()->Initialize(devinfo);
+ timeval time = {1507226211, 483601};
+ // Note the sneaky ordering of touch/orientation, since it's :
+ // 1. possible in reality.
+ // 2. Forces us to ensure that we handle this correctly.
+ struct input_event mock_kernel_queue[] = {
+ {time, EV_ABS, ABS_MT_TRACKING_ID, 461},
+ {time, EV_ABS, ABS_MT_POSITION_X, 1795},
+ {time, EV_ABS, ABS_MT_POSITION_Y, 5559},
+ {time, EV_ABS, ABS_MT_TOUCH_MAJOR, 20},
+ {time, EV_ABS, ABS_MT_ORIENTATION, 0},
+ {time, EV_ABS, ABS_MT_TOUCH_MINOR, 15},
+ {time, EV_ABS, ABS_MT_PRESSURE, 217},
+ {time, EV_KEY, BTN_TOUCH, 1},
+ {time, EV_ABS, ABS_X, 1795},
+ {time, EV_ABS, ABS_Y, 5559},
+ {time, EV_ABS, ABS_PRESSURE, 217},
+ {time, EV_MSC, MSC_TIMESTAMP, 0},
+ {time, EV_SYN, SYN_REPORT, 0},
+ };
+ device()->ConfigureReadMock(mock_kernel_queue, base::size(mock_kernel_queue),
+ 0);
+ device()->ReadNow();
+ // Update the items.
+ time.tv_usec += 8000;
+ UpdateTime(mock_kernel_queue, base::size(mock_kernel_queue), time);
+ mock_kernel_queue[3].value = 22;
+ mock_kernel_queue[4].value = 1;
+ mock_kernel_queue[5].value = 13;
+ device()->ConfigureReadMock(mock_kernel_queue, base::size(mock_kernel_queue),
+ 0);
+ device()->ReadNow();
+ ASSERT_EQ(2u, size());
+ // finger scale on an eve is 40. So radius is expected as touch * 40 / 2.
+ ui::TouchEventParams event = dispatched_touch_event(0);
+ EXPECT_FLOAT_EQ(300, event.pointer_details.radius_x);
+ EXPECT_FLOAT_EQ(400, event.pointer_details.radius_y);
+
+ event = dispatched_touch_event(1);
+ EXPECT_FLOAT_EQ(440, event.pointer_details.radius_x);
+ EXPECT_FLOAT_EQ(260, event.pointer_details.radius_y);
+}
+
TEST_F(TouchEventConverterEvdevTest, ScalePressure) {
EventDeviceInfo devinfo;
EXPECT_TRUE(CapabilitiesToDeviceInfo(kEveTouchScreen, &devinfo));
@@ -2263,6 +2310,7 @@ TEST_F(TouchEventConverterEvdevTest, FingerSizeWithResolution) {
{time, EV_ABS, ABS_MT_PRESSURE, 217},
{time, EV_ABS, ABS_MT_TOUCH_MAJOR, 14},
{time, EV_ABS, ABS_MT_TOUCH_MINOR, 11},
+ {time, EV_ABS, ABS_MT_ORIENTATION, 1},
{time, EV_KEY, BTN_TOUCH, 1},
{time, EV_ABS, ABS_X, 1795},
{time, EV_ABS, ABS_Y, 5559},
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/edge_touch_filter.cc b/chromium/ui/events/ozone/evdev/touch_filter/edge_touch_filter.cc
index 249515233d8..f3244b33764 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/edge_touch_filter.cc
+++ b/chromium/ui/events/ozone/evdev/touch_filter/edge_touch_filter.cc
@@ -10,7 +10,6 @@
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
-#include "base/strings/stringprintf.h"
#include "ui/gfx/geometry/insets.h"
namespace ui {
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc b/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc
index fae17a83570..b155c4c1031 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc
+++ b/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc
@@ -455,9 +455,9 @@ bool NeuralStylusPalmDetectionFilter::
// Check the switch string.
- base::Optional<base::Value> value =
+ absl::optional<base::Value> value =
base::JSONReader::Read(ozone_params_switch_string);
- if (value != base::nullopt && !ozone_params_switch_string.empty()) {
+ if (value != absl::nullopt && !ozone_params_switch_string.empty()) {
if (!value->is_dict()) {
return false;
}
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_unittest.cc b/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_unittest.cc
index 707a9e70b46..4f446dfbb69 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_unittest.cc
@@ -4,6 +4,7 @@
#include "ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h"
+#include <memory>
#include <utility>
#include <vector>
@@ -28,7 +29,7 @@ class NeuralStylusPalmDetectionFilterTest : public testing::Test {
public:
NeuralStylusPalmDetectionFilterTest() = default;
void SetUp() override {
- shared_palm_state.reset(new SharedPalmDetectionFilterState);
+ shared_palm_state = std::make_unique<SharedPalmDetectionFilterState>();
model_ = new testing::StrictMock<MockNeuralModel>;
model_config_.biggest_near_neighbor_count = 2;
model_config_.min_sample_count = 2;
@@ -43,10 +44,10 @@ class NeuralStylusPalmDetectionFilterTest : public testing::Test {
.WillRepeatedly(testing::ReturnRef(model_config_));
EXPECT_TRUE(
CapabilitiesToDeviceInfo(kNocturneTouchScreen, &nocturne_touchscreen_));
- palm_detection_filter_.reset(new NeuralStylusPalmDetectionFilter(
+ palm_detection_filter_ = std::make_unique<NeuralStylusPalmDetectionFilter>(
nocturne_touchscreen_,
std::unique_ptr<NeuralStylusPalmDetectionFilterModel>(model_),
- shared_palm_state.get()));
+ shared_palm_state.get());
touch_.resize(kNumTouchEvdevSlots);
for (size_t i = 0; i < touch_.size(); ++i) {
touch_[i].slot = i;
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_report_filter_unittest.cc b/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_report_filter_unittest.cc
index 6754617043f..d9531e2650a 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_report_filter_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_report_filter_unittest.cc
@@ -4,6 +4,8 @@
#include "ui/events/ozone/evdev/touch_filter/neural_stylus_palm_report_filter.h"
+#include <memory>
+
#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -21,8 +23,8 @@ class NeuralStylusReportFilterTest : public testing::Test {
void SetUp() override {
shared_palm_state = std::make_unique<SharedPalmDetectionFilterState>();
- palm_detection_filter_.reset(
- new NeuralStylusReportFilter(shared_palm_state.get()));
+ palm_detection_filter_ =
+ std::make_unique<NeuralStylusReportFilter>(shared_palm_state.get());
EXPECT_TRUE(CapabilitiesToDeviceInfo(kNocturneTouchScreen,
&nocturne_touchscreen_info_));
EXPECT_TRUE(
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/open_palm_detection_filter_unittest.cc b/chromium/ui/events/ozone/evdev/touch_filter/open_palm_detection_filter_unittest.cc
index 0d72b10ecd1..bbf6824fca6 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/open_palm_detection_filter_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/touch_filter/open_palm_detection_filter_unittest.cc
@@ -4,6 +4,8 @@
#include "ui/events/ozone/evdev/touch_filter/open_palm_detection_filter.h"
+#include <memory>
+
#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/ozone/evdev/touch_filter/palm_detection_filter.h"
@@ -17,8 +19,8 @@ class OpenPalmDetectionFilterTest : public testing::Test {
void SetUp() override {
shared_palm_state = std::make_unique<SharedPalmDetectionFilterState>();
- palm_detection_filter_.reset(
- new OpenPalmDetectionFilter(shared_palm_state.get()));
+ palm_detection_filter_ =
+ std::make_unique<OpenPalmDetectionFilter>(shared_palm_state.get());
}
protected:
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory.cc b/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory.cc
index 6fe5273585c..3f15986f7b8 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory.cc
+++ b/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory.cc
@@ -51,10 +51,10 @@ std::string FetchNeuralPalmRadiusPolynomial(const EventDeviceInfo& devinfo,
}
// look at the command line.
- base::Optional<base::Value> ozone_switch_value = base::JSONReader::Read(
+ absl::optional<base::Value> ozone_switch_value = base::JSONReader::Read(
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
kOzoneNNPalmSwitchName));
- if (ozone_switch_value != base::nullopt && ozone_switch_value->is_dict()) {
+ if (ozone_switch_value != absl::nullopt && ozone_switch_value->is_dict()) {
std::string* switch_string_value =
ozone_switch_value->FindStringKey(kOzoneNNPalmRadiusPolynomialProperty);
if (switch_string_value != nullptr) {
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.h b/chromium/ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.h
index 378243e9b96..83c46cbe629 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.h
+++ b/chromium/ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.h
@@ -31,4 +31,4 @@ struct SharedPalmDetectionFilterState {
} // namespace ui
-#endif
+#endif // UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_SHARED_PALM_DETECTION_FILTER_STATE_H_
diff --git a/chromium/ui/events/ozone/gamepad/gamepad_observer.h b/chromium/ui/events/ozone/gamepad/gamepad_observer.h
index 6d640f7618d..b527c4eb4e9 100644
--- a/chromium/ui/events/ozone/gamepad/gamepad_observer.h
+++ b/chromium/ui/events/ozone/gamepad/gamepad_observer.h
@@ -5,7 +5,6 @@
#ifndef UI_EVENTS_OZONE_GAMEPAD_GAMEPAD_OBSERVER_H_
#define UI_EVENTS_OZONE_GAMEPAD_GAMEPAD_OBSERVER_H_
-#include "base/time/time.h"
#include "ui/events/ozone/gamepad/gamepad_event.h"
namespace ui {
diff --git a/chromium/ui/events/ozone/gamepad/gamepad_provider_ozone.h b/chromium/ui/events/ozone/gamepad/gamepad_provider_ozone.h
index bcf2487ca85..2c1878cb65b 100644
--- a/chromium/ui/events/ozone/gamepad/gamepad_provider_ozone.h
+++ b/chromium/ui/events/ozone/gamepad/gamepad_provider_ozone.h
@@ -10,7 +10,6 @@
#include "base/component_export.h"
#include "base/macros.h"
#include "base/observer_list.h"
-#include "base/time/time.h"
#include "ui/events/devices/gamepad_device.h"
#include "ui/events/ozone/gamepad/gamepad_observer.h"
diff --git a/chromium/ui/events/ozone/keyboard/event_auto_repeat_handler.h b/chromium/ui/events/ozone/keyboard/event_auto_repeat_handler.h
index 39c3239c5b2..18e2954bcb9 100644
--- a/chromium/ui/events/ozone/keyboard/event_auto_repeat_handler.h
+++ b/chromium/ui/events/ozone/keyboard/event_auto_repeat_handler.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_OZONE_KEYBOARD_EVENT_AUTO_REPEAT_HANDLER_H
-#define UI_EVENTS_OZONE_KEYBOARD_EVENT_AUTO_REPEAT_HANDLER_H
+#ifndef UI_EVENTS_OZONE_KEYBOARD_EVENT_AUTO_REPEAT_HANDLER_H_
+#define UI_EVENTS_OZONE_KEYBOARD_EVENT_AUTO_REPEAT_HANDLER_H_
#include "base/callback.h"
#include "base/component_export.h"
@@ -72,4 +72,4 @@ class COMPONENT_EXPORT(EVENTS_OZONE) EventAutoRepeatHandler {
} // namespace ui
-#endif // UI_EVENTS_OZONE_KEYBOARD_EVENT_AUTO_REPEAT_HANDLER_H
+#endif // UI_EVENTS_OZONE_KEYBOARD_EVENT_AUTO_REPEAT_HANDLER_H_
diff --git a/chromium/ui/events/ozone/keyboard_hook_ozone.cc b/chromium/ui/events/ozone/keyboard_hook_ozone.cc
index f7853ef4a42..bb07560ceca 100644
--- a/chromium/ui/events/ozone/keyboard_hook_ozone.cc
+++ b/chromium/ui/events/ozone/keyboard_hook_ozone.cc
@@ -8,41 +8,41 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/platform_keyboard_hook.h"
namespace ui {
KeyboardHookOzone::KeyboardHookOzone(
- base::Optional<base::flat_set<DomCode>> dom_codes,
- KeyEventCallback callback)
- : KeyboardHookBase(std::move(dom_codes), std::move(callback)) {}
+ PlatformKeyboardHookTypes type,
+ KeyEventCallback callback,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
+ gfx::AcceleratedWidget widget) {
+ platform_keyboard_hook_ =
+ ui::OzonePlatform::GetInstance()->CreateKeyboardHook(
+ type, std::move(callback), std::move(dom_codes), widget);
+}
KeyboardHookOzone::~KeyboardHookOzone() = default;
-bool KeyboardHookOzone::RegisterHook() {
- // TODO(680809): Implement system-level keyboard lock feature for ozone.
- // Return true to enable browser-level keyboard lock for ozone platform.
- return true;
+bool KeyboardHookOzone::IsKeyLocked(DomCode dom_code) const {
+ return platform_keyboard_hook_->IsKeyLocked(dom_code);
}
#if !defined(OS_LINUX) && !defined(OS_CHROMEOS)
// static
std::unique_ptr<KeyboardHook> KeyboardHook::CreateModifierKeyboardHook(
- base::Optional<base::flat_set<DomCode>> dom_codes,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
gfx::AcceleratedWidget accelerated_widget,
KeyEventCallback callback) {
- std::unique_ptr<KeyboardHookOzone> keyboard_hook =
- std::make_unique<KeyboardHookOzone>(std::move(dom_codes),
- std::move(callback));
-
- if (!keyboard_hook->RegisterHook())
- return nullptr;
-
- return keyboard_hook;
+ return std::make_unique<KeyboardHookOzone>(
+ PlatformKeyboardHookTypes::kModifier, std::move(callback),
+ std::move(dom_codes), accelerated_widget);
}
// static
diff --git a/chromium/ui/events/ozone/keyboard_hook_ozone.h b/chromium/ui/events/ozone/keyboard_hook_ozone.h
index 5da0678b466..f74e2b7ed71 100644
--- a/chromium/ui/events/ozone/keyboard_hook_ozone.h
+++ b/chromium/ui/events/ozone/keyboard_hook_ozone.h
@@ -6,22 +6,34 @@
#define UI_EVENTS_OZONE_KEYBOARD_HOOK_OZONE_H_
#include "base/callback.h"
-#include "base/optional.h"
-#include "ui/events/keyboard_hook_base.h"
+#include "base/component_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/events/keyboard_hook.h"
namespace ui {
-// A default implementation for Ozone platform.
-class KeyboardHookOzone : public KeyboardHookBase {
+enum class PlatformKeyboardHookTypes;
+class PlatformKeyboardHook;
+
+// Ozone-specific implementation of the KeyboardHook interface.
+//
+// Wraps the platform implementation spawned by the current Ozone platform.
+class COMPONENT_EXPORT(KEYBOARD_HOOK) KeyboardHookOzone : public KeyboardHook {
public:
- KeyboardHookOzone(base::Optional<base::flat_set<DomCode>> dom_codes,
- KeyEventCallback callback);
+ KeyboardHookOzone(PlatformKeyboardHookTypes type,
+ KeyEventCallback callback,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
+ gfx::AcceleratedWidget widget);
KeyboardHookOzone(const KeyboardHookOzone&) = delete;
KeyboardHookOzone& operator=(const KeyboardHookOzone&) = delete;
~KeyboardHookOzone() override;
- // KeyboardHookBase:
- bool RegisterHook() override;
+ // KeyboardHook:
+ bool IsKeyLocked(DomCode dom_code) const override;
+
+ private:
+ // The platform implementation.
+ std::unique_ptr<PlatformKeyboardHook> platform_keyboard_hook_;
};
} // namespace ui
diff --git a/chromium/ui/events/ozone/layout/BUILD.gn b/chromium/ui/events/ozone/layout/BUILD.gn
index 987498b00cf..c7a5230b2dd 100644
--- a/chromium/ui/events/ozone/layout/BUILD.gn
+++ b/chromium/ui/events/ozone/layout/BUILD.gn
@@ -75,3 +75,17 @@ source_set("unittests") {
"//ui/events:dom_keycode_converter",
]
}
+
+source_set("test_support") {
+ testonly = true
+
+ sources = [
+ "keyboard_layout_engine_test_utils.cc",
+ "keyboard_layout_engine_test_utils.h", ]
+
+ deps = [
+ ":layout",
+ "//base",
+ "//ui/base:features",
+ ]
+}
diff --git a/chromium/ui/events/ozone/layout/keyboard_layout_engine.h b/chromium/ui/events/ozone/layout/keyboard_layout_engine.h
index 89d9e1fbfe0..295e33c13c2 100644
--- a/chromium/ui/events/ozone/layout/keyboard_layout_engine.h
+++ b/chromium/ui/events/ozone/layout/keyboard_layout_engine.h
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_OZONE_PUBLIC_KEYBOARD_LAYOUT_ENGINE_H_
-#define UI_OZONE_PUBLIC_KEYBOARD_LAYOUT_ENGINE_H_
+#ifndef UI_EVENTS_OZONE_LAYOUT_KEYBOARD_LAYOUT_ENGINE_H_
+#define UI_EVENTS_OZONE_LAYOUT_KEYBOARD_LAYOUT_ENGINE_H_
#include <string>
+#include "base/callback.h"
#include "base/component_export.h"
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/events/keycodes/keyboard_codes.h"
@@ -70,8 +71,13 @@ class COMPONENT_EXPORT(EVENTS_OZONE_LAYOUT) KeyboardLayoutEngine {
int event_flags,
DomKey* dom_key,
KeyboardCode* key_code) const = 0;
+
+ // Tests may need to wait for the keyboard layout to be fully initialised.
+ // The implementation should run |closure| when it is ready to handle calls to
+ // Lookup().
+ virtual void SetInitCallbackForTest(base::OnceClosure closure) = 0;
};
} // namespace ui
-#endif // UI_OZONE_PUBLIC_KEYBOARD_LAYOUT_ENGINE_H_
+#endif // UI_EVENTS_OZONE_LAYOUT_KEYBOARD_LAYOUT_ENGINE_H_
diff --git a/chromium/ui/events/ozone/layout/keyboard_layout_engine_manager.h b/chromium/ui/events/ozone/layout/keyboard_layout_engine_manager.h
index 5625dcaecd3..f60864a9322 100644
--- a/chromium/ui/events/ozone/layout/keyboard_layout_engine_manager.h
+++ b/chromium/ui/events/ozone/layout/keyboard_layout_engine_manager.h
@@ -2,10 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_OZONE_PUBLIC_KEYBOARD_LAYOUT_ENGINE_MANAGER_H_
-#define UI_OZONE_PUBLIC_KEYBOARD_LAYOUT_ENGINE_MANAGER_H_
+#ifndef UI_EVENTS_OZONE_LAYOUT_KEYBOARD_LAYOUT_ENGINE_MANAGER_H_
+#define UI_EVENTS_OZONE_LAYOUT_KEYBOARD_LAYOUT_ENGINE_MANAGER_H_
-#include <memory>
#include "base/check.h"
#include "base/component_export.h"
@@ -40,4 +39,4 @@ class COMPONENT_EXPORT(EVENTS_OZONE_LAYOUT) KeyboardLayoutEngineManager {
} // namespace ui
-#endif // UI_OZONE_PUBLIC_KEYBOARD_LAYOUT_ENGINE_MANAGER_H_
+#endif // UI_EVENTS_OZONE_LAYOUT_KEYBOARD_LAYOUT_ENGINE_MANAGER_H_
diff --git a/chromium/ui/events/ozone/layout/keyboard_layout_engine_test_utils.cc b/chromium/ui/events/ozone/layout/keyboard_layout_engine_test_utils.cc
new file mode 100644
index 00000000000..09c73baa212
--- /dev/null
+++ b/chromium/ui/events/ozone/layout/keyboard_layout_engine_test_utils.cc
@@ -0,0 +1,31 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/ozone/layout/keyboard_layout_engine_test_utils.h"
+
+#include "base/callback.h"
+#include "base/run_loop.h"
+#include "ui/base/ui_base_features.h"
+#include "ui/events/ozone/layout/keyboard_layout_engine.h"
+#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
+
+namespace ui {
+
+// TODO(crbug.com/1209477): Wayland bots use Weston with Headless backend that
+// sets up XkbKeyboardLayoutEngine differently. When that is fixed, remove the
+// workaround function below.
+void WaitUntilLayoutEngineIsReadyForTest() {
+ if (!features::IsUsingOzonePlatform())
+ return;
+ // The platform may set the keyboard layout asynchronously. We need the
+ // layout when handling key events, so wait until it is ready.
+ //
+ // See crbug.com/1186996
+ base::RunLoop loop;
+ ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine()
+ ->SetInitCallbackForTest(loop.QuitClosure());
+ loop.Run();
+}
+
+} // namespace ui
diff --git a/chromium/ui/events/ozone/layout/keyboard_layout_engine_test_utils.h b/chromium/ui/events/ozone/layout/keyboard_layout_engine_test_utils.h
new file mode 100644
index 00000000000..6a7245e2ceb
--- /dev/null
+++ b/chromium/ui/events/ozone/layout/keyboard_layout_engine_test_utils.h
@@ -0,0 +1,16 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_OZONE_LAYOUT_KEYBOARD_LAYOUT_ENGINE_TEST_UTILS_H_
+#define UI_EVENTS_OZONE_LAYOUT_KEYBOARD_LAYOUT_ENGINE_TEST_UTILS_H_
+
+namespace ui {
+
+// Helper for tests that require the layout to be ready when handling key
+// events.
+void WaitUntilLayoutEngineIsReadyForTest();
+
+} // namespace ui
+
+#endif // UI_EVENTS_OZONE_LAYOUT_KEYBOARD_LAYOUT_ENGINE_TEST_UTILS_H_
diff --git a/chromium/ui/events/ozone/layout/no/no_keyboard_layout_engine.cc b/chromium/ui/events/ozone/layout/no/no_keyboard_layout_engine.cc
index c3adea485e0..d2d999ade8e 100644
--- a/chromium/ui/events/ozone/layout/no/no_keyboard_layout_engine.cc
+++ b/chromium/ui/events/ozone/layout/no/no_keyboard_layout_engine.cc
@@ -35,4 +35,8 @@ bool NoKeyboardLayoutEngine::Lookup(DomCode dom_code,
return false;
}
+void NoKeyboardLayoutEngine::SetInitCallbackForTest(base::OnceClosure closure) {
+ std::move(closure).Run();
+}
+
} // namespace ui
diff --git a/chromium/ui/events/ozone/layout/no/no_keyboard_layout_engine.h b/chromium/ui/events/ozone/layout/no/no_keyboard_layout_engine.h
index 3b7ad273a28..d0490998e38 100644
--- a/chromium/ui/events/ozone/layout/no/no_keyboard_layout_engine.h
+++ b/chromium/ui/events/ozone/layout/no/no_keyboard_layout_engine.h
@@ -27,6 +27,7 @@ class COMPONENT_EXPORT(EVENTS_OZONE_LAYOUT) NoKeyboardLayoutEngine
int flags,
DomKey* dom_key,
KeyboardCode* key_code) const override;
+ void SetInitCallbackForTest(base::OnceClosure closure) override;
};
} // namespace ui
diff --git a/chromium/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.cc b/chromium/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.cc
index 069f83c2626..bcde64fd24c 100644
--- a/chromium/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.cc
+++ b/chromium/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.cc
@@ -48,4 +48,9 @@ bool StubKeyboardLayoutEngine::Lookup(DomCode dom_code,
return DomCodeToUsLayoutDomKey(dom_code, flags, out_dom_key, out_key_code);
}
+void StubKeyboardLayoutEngine::SetInitCallbackForTest(
+ base::OnceClosure closure) {
+ std::move(closure).Run();
+}
+
} // namespace ui
diff --git a/chromium/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h b/chromium/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h
index 4db623b1d93..3cfe7dd903d 100644
--- a/chromium/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h
+++ b/chromium/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h
@@ -27,6 +27,7 @@ class COMPONENT_EXPORT(EVENTS_OZONE_LAYOUT) StubKeyboardLayoutEngine
int flags,
DomKey* dom_key,
KeyboardCode* key_code) const override;
+ void SetInitCallbackForTest(base::OnceClosure closure) override;
};
} // namespace ui
diff --git a/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc b/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc
index 9b26c380d6e..2e2d67916f0 100644
--- a/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc
+++ b/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc
@@ -188,6 +188,7 @@ const PrintableSubEntry kU002F[] = {
{DomCode::BACKQUOTE, 0, 0, kAny, kAny, VKEY_OEM_7},
{DomCode::BACKSLASH, 0, 0, kAny, kAny, VKEY_OEM_5},
{DomCode::SLASH, 0, 0, kAny, kAny, VKEY_OEM_2},
+ {DomCode::CONTROL_RIGHT, 0, 0, kAny, kAny, VKEY_RCONTROL},
{DomCode::DIGIT3, 1, 0, 0x0033, kAny, VKEY_3}, // 3
{DomCode::DIGIT3, 1, 0, 0x003F, kAny, VKEY_OEM_2}, // ?
{DomCode::DIGIT0, 1, 0, 0x0030, kAny, VKEY_0}, // 0
@@ -807,6 +808,16 @@ bool XkbKeyboardLayoutEngine::Lookup(DomCode dom_code,
return true;
}
+void XkbKeyboardLayoutEngine::SetInitCallbackForTest(
+ base::OnceClosure closure) {
+ if (xkb_state_) {
+ std::move(closure).Run();
+ return;
+ }
+
+ keymap_init_closure_for_test_ = std::move(closure);
+}
+
bool XkbKeyboardLayoutEngine::SetCurrentLayoutFromBuffer(
const char* keymap_string,
size_t size) {
@@ -884,6 +895,9 @@ void XkbKeyboardLayoutEngine::SetKeymap(xkb_keymap* keymap) {
#endif
shift_mod_mask_ = EventFlagsToXkbFlags(ui::EF_SHIFT_DOWN);
altgr_mod_mask_ = EventFlagsToXkbFlags(ui::EF_ALTGR_DOWN);
+
+ if (keymap_init_closure_for_test_)
+ std::move(keymap_init_closure_for_test_).Run();
}
xkb_mod_mask_t XkbKeyboardLayoutEngine::EventFlagsToXkbFlags(
diff --git a/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h b/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h
index fd9948d2937..05d62643014 100644
--- a/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h
+++ b/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h
@@ -49,6 +49,8 @@ class COMPONENT_EXPORT(EVENTS_OZONE_LAYOUT) XkbKeyboardLayoutEngine
DomKey* dom_key,
KeyboardCode* key_code) const override;
+ void SetInitCallbackForTest(base::OnceClosure closure) override;
+
int UpdateModifiers(uint32_t depressed,
uint32_t latched,
uint32_t locked,
@@ -142,6 +144,8 @@ class COMPONENT_EXPORT(EVENTS_OZONE_LAYOUT) XkbKeyboardLayoutEngine
xkb_layout_index_t layout_index_ = 0;
+ base::OnceClosure keymap_init_closure_for_test_;
+
// Support weak pointers for attach & detach callbacks.
base::WeakPtrFactory<XkbKeyboardLayoutEngine> weak_ptr_factory_;
};
diff --git a/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc b/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc
index 803624e289c..4090eff3429 100644
--- a/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc
+++ b/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc
@@ -251,8 +251,8 @@ TEST_F(XkbLayoutEngineVkTest, KeyboardCodeForPrintable) {
// plus sign, *, *
/* 41 */ {{0x002B, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_PLUS},
// plus sign, *, *
- /* 42 */ {{0x002B, 0x2460, 0x2461, DomCode::BRACKET_RIGHT},
- VKEY_OEM_PLUS},
+ /* 42 */
+ {{0x002B, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_PLUS},
// plus sign, *, *
/* 43 */ {{0x002B, 0x2460, 0x2461, DomCode::DIGIT1}, VKEY_1},
// plus sign, *, *
@@ -333,433 +333,437 @@ TEST_F(XkbLayoutEngineVkTest, KeyboardCodeForPrintable) {
/* 81 */ {{0x002F, 0x2460, 0x2461, DomCode::MINUS}, VKEY_OEM_4},
// solidus, *, *
/* 82 */ {{0x002F, 0x2460, 0x2461, DomCode::SLASH}, VKEY_OEM_2},
+ // solidus, *, *
+ /* 83 */
+ {{0x002F, 0x2460, 0x2461, DomCode::CONTROL_RIGHT}, VKEY_RCONTROL},
// colon, *, *
- /* 83 */ {{0x003A, 0x2460, 0x2461, DomCode::DIGIT1}, VKEY_1},
+ /* 84 */ {{0x003A, 0x2460, 0x2461, DomCode::DIGIT1}, VKEY_1},
// colon, *, *
- /* 84 */ {{0x003A, 0x2460, 0x2461, DomCode::DIGIT5}, VKEY_5},
+ /* 85 */ {{0x003A, 0x2460, 0x2461, DomCode::DIGIT5}, VKEY_5},
// colon, *, *
- /* 85 */ {{0x003A, 0x2460, 0x2461, DomCode::DIGIT6}, VKEY_6},
+ /* 86 */ {{0x003A, 0x2460, 0x2461, DomCode::DIGIT6}, VKEY_6},
// colon, *, *
- /* 86 */ {{0x003A, 0x2460, 0x2461, DomCode::PERIOD}, VKEY_OEM_2},
+ /* 87 */ {{0x003A, 0x2460, 0x2461, DomCode::PERIOD}, VKEY_OEM_2},
// semicolon, *, *
- /* 87 */ {{0x003B, 0x2460, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_3},
+ /* 88 */ {{0x003B, 0x2460, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_3},
// semicolon, *, *
- /* 88 */ {{0x003B, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_1},
+ /* 89 */ {{0x003B, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_1},
// semicolon, *, *
- /* 89 */ {{0x003B, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
+ /* 90 */ {{0x003B, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
// semicolon, *, *
- /* 90 */ {{0x003B, 0x2460, 0x2461, DomCode::COMMA}, VKEY_OEM_PERIOD},
+ /* 91 */ {{0x003B, 0x2460, 0x2461, DomCode::COMMA}, VKEY_OEM_PERIOD},
// semicolon, *, *
- /* 91 */ {{0x003B, 0x2460, 0x2461, DomCode::DIGIT4}, VKEY_4},
+ /* 92 */ {{0x003B, 0x2460, 0x2461, DomCode::DIGIT4}, VKEY_4},
// semicolon, *, *
- /* 92 */ {{0x003B, 0x2460, 0x2461, DomCode::DIGIT8}, VKEY_8},
+ /* 93 */ {{0x003B, 0x2460, 0x2461, DomCode::DIGIT8}, VKEY_8},
// semicolon, *, *
- /* 93 */ {{0x003B, 0x2460, 0x2461, DomCode::US_Q}, VKEY_OEM_1},
+ /* 94 */ {{0x003B, 0x2460, 0x2461, DomCode::US_Q}, VKEY_OEM_1},
// semicolon, *, *
- /* 94 */ {{0x003B, 0x2460, 0x2461, DomCode::US_Z}, VKEY_OEM_1},
+ /* 95 */ {{0x003B, 0x2460, 0x2461, DomCode::US_Z}, VKEY_OEM_1},
// semicolon, *, *
- /* 95 */ {{0x003B, 0x2460, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_1},
+ /* 96 */ {{0x003B, 0x2460, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_1},
// semicolon, *, *
- /* 96 */ {{0x003B, 0x2460, 0x2461, DomCode::SLASH}, VKEY_OEM_2},
+ /* 97 */ {{0x003B, 0x2460, 0x2461, DomCode::SLASH}, VKEY_OEM_2},
// less-than sign, *, *
- /* 97 */ {{0x003C, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
+ /* 98 */ {{0x003C, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
// equals sign, percent sign, unmapped
- /* 98 */ {{0x003D, 0x0025, 0x2461, DomCode::MINUS}, VKEY_OEM_PLUS},
+ /* 99 */ {{0x003D, 0x0025, 0x2461, DomCode::MINUS}, VKEY_OEM_PLUS},
// equals sign, percent sign, hyphen-minus
- /* 99 */ {{0x003D, 0x0025, 0x002D, DomCode::MINUS}, VKEY_OEM_MINUS},
+ /* 100 */ {{0x003D, 0x0025, 0x002D, DomCode::MINUS}, VKEY_OEM_MINUS},
// equals sign, percent sign, *
- /* 100 */ {{0x003D, 0x0025, 0x2461, DomCode::SLASH}, VKEY_OEM_8},
+ /* 101 */ {{0x003D, 0x0025, 0x2461, DomCode::SLASH}, VKEY_OEM_8},
// equals sign, plus sign, *
- /* 101 */ {{0x003D, 0x002B, 0x2461, DomCode::SLASH}, VKEY_OEM_PLUS},
+ /* 102 */ {{0x003D, 0x002B, 0x2461, DomCode::SLASH}, VKEY_OEM_PLUS},
// equals sign, *, *
- /* 102 */ {{0x003D, 0x2460, 0x2461, DomCode::BRACKET_RIGHT},
- VKEY_OEM_PLUS},
+ /* 103 */
+ {{0x003D, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_PLUS},
// equals sign, *, *
- /* 103 */ {{0x003D, 0x2460, 0x2461, DomCode::DIGIT8}, VKEY_8},
+ /* 104 */ {{0x003D, 0x2460, 0x2461, DomCode::DIGIT8}, VKEY_8},
// equals sign, *, *
- /* 104 */ {{0x003D, 0x2460, 0x2461, DomCode::EQUAL}, VKEY_OEM_PLUS},
+ /* 105 */ {{0x003D, 0x2460, 0x2461, DomCode::EQUAL}, VKEY_OEM_PLUS},
// question mark, *, *
- /* 105 */ {{0x003F, 0x2460, 0x2461, DomCode::DIGIT2}, VKEY_2},
+ /* 106 */ {{0x003F, 0x2460, 0x2461, DomCode::DIGIT2}, VKEY_2},
// question mark, *, *
- /* 106 */ {{0x003F, 0x2460, 0x2461, DomCode::DIGIT7}, VKEY_7},
+ /* 107 */ {{0x003F, 0x2460, 0x2461, DomCode::DIGIT7}, VKEY_7},
// question mark, *, *
- /* 107 */ {{0x003F, 0x2460, 0x2461, DomCode::DIGIT8}, VKEY_8},
+ /* 108 */ {{0x003F, 0x2460, 0x2461, DomCode::DIGIT8}, VKEY_8},
// question mark, *, *
- /* 108 */ {{0x003F, 0x2460, 0x2461, DomCode::MINUS}, VKEY_OEM_PLUS},
+ /* 109 */ {{0x003F, 0x2460, 0x2461, DomCode::MINUS}, VKEY_OEM_PLUS},
// commercial at, *, *
- /* 109 */ {{0x0040, 0x2460, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_7},
+ /* 110 */ {{0x0040, 0x2460, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_7},
// commercial at, *, *
- /* 110 */ {{0x0040, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
+ /* 111 */ {{0x0040, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
// left square bracket, *, *
- /* 111 */ {{0x005B, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
+ /* 112 */ {{0x005B, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
// left square bracket, *, *
- /* 112 */ {{0x005B, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
+ /* 113 */ {{0x005B, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
// left square bracket, *, *
- /* 113 */ {{0x005B, 0x2460, 0x2461, DomCode::DIGIT1}, VKEY_OEM_4},
+ /* 114 */ {{0x005B, 0x2460, 0x2461, DomCode::DIGIT1}, VKEY_OEM_4},
// left square bracket, *, *
- /* 114 */ {{0x005B, 0x2460, 0x2461, DomCode::MINUS}, VKEY_OEM_4},
+ /* 115 */ {{0x005B, 0x2460, 0x2461, DomCode::MINUS}, VKEY_OEM_4},
// left square bracket, *, *
- /* 115 */ {{0x005B, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
+ /* 116 */ {{0x005B, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
// reverse solidus, solidus, *
- /* 116 */ {{0x005C, 0x002F, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_7},
+ /* 117 */ {{0x005C, 0x002F, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_7},
// reverse solidus, vertical line, digit one
- /* 117 */ {{0x005C, 0x007C, 0x0031, DomCode::BACKQUOTE}, VKEY_OEM_5},
+ /* 118 */ {{0x005C, 0x007C, 0x0031, DomCode::BACKQUOTE}, VKEY_OEM_5},
// reverse solidus, vertical line, N cedilla
- /* 118 */ {{0x005C, 0x007C, 0x0145, DomCode::BACKQUOTE}, VKEY_OEM_3},
+ /* 119 */ {{0x005C, 0x007C, 0x0145, DomCode::BACKQUOTE}, VKEY_OEM_3},
// reverse solidus, vertical line, *
- /* 119 */ {{0x005C, 0x007C, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_5},
+ /* 120 */ {{0x005C, 0x007C, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_5},
// reverse solidus, *, *
- /* 120 */ {{0x005C, 0x2460, 0x2461, DomCode::EQUAL}, VKEY_OEM_4},
+ /* 121 */ {{0x005C, 0x2460, 0x2461, DomCode::EQUAL}, VKEY_OEM_4},
// right square bracket, *, *
- /* 121 */ {{0x005D, 0x2460, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_3},
+ /* 122 */ {{0x005D, 0x2460, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_3},
// right square bracket, *, *
- /* 122 */ {{0x005D, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_5},
+ /* 123 */ {{0x005D, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_5},
// right square bracket, *, *
- /* 123 */ {{0x005D, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
+ /* 124 */ {{0x005D, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
// right square bracket, *, *
- /* 124 */ {{0x005D, 0x2460, 0x2461, DomCode::DIGIT2}, VKEY_OEM_6},
+ /* 125 */ {{0x005D, 0x2460, 0x2461, DomCode::DIGIT2}, VKEY_OEM_6},
// right square bracket, *, *
- /* 125 */ {{0x005D, 0x2460, 0x2461, DomCode::EQUAL}, VKEY_OEM_6},
+ /* 126 */ {{0x005D, 0x2460, 0x2461, DomCode::EQUAL}, VKEY_OEM_6},
// low line, *, *
- /* 126 */ {{0x005F, 0x2460, 0x2461, DomCode::DIGIT8}, VKEY_8},
+ /* 127 */ {{0x005F, 0x2460, 0x2461, DomCode::DIGIT8}, VKEY_8},
// low line, *, *
- /* 127 */ {{0x005F, 0x2460, 0x2461, DomCode::MINUS}, VKEY_OEM_MINUS},
+ /* 128 */ {{0x005F, 0x2460, 0x2461, DomCode::MINUS}, VKEY_OEM_MINUS},
// grave accent, unmapped, *
- /* 128 */ {{0x0060, 0x0000, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_3},
+ /* 129 */ {{0x0060, 0x0000, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_3},
// grave accent, tilde, unmapped
- /* 129 */ {{0x0060, 0x007E, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_3},
+ /* 130 */ {{0x0060, 0x007E, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_3},
// grave accent, tilde, digit one
- /* 130 */ {{0x0060, 0x007E, 0x0031, DomCode::BACKQUOTE}, VKEY_OEM_3},
+ /* 131 */ {{0x0060, 0x007E, 0x0031, DomCode::BACKQUOTE}, VKEY_OEM_3},
// grave accent, tilde, semicolon
- /* 131 */ {{0x0060, 0x007E, 0x003B, DomCode::BACKQUOTE}, VKEY_OEM_3},
+ /* 132 */ {{0x0060, 0x007E, 0x003B, DomCode::BACKQUOTE}, VKEY_OEM_3},
// grave accent, tilde, grave accent
- /* 132 */ {{0x0060, 0x007E, 0x0060, DomCode::BACKQUOTE}, VKEY_OEM_3},
+ /* 133 */ {{0x0060, 0x007E, 0x0060, DomCode::BACKQUOTE}, VKEY_OEM_3},
// grave accent, tilde, inverted question mark
- /* 133 */ {{0x0060, 0x007E, 0x00BF, DomCode::BACKQUOTE}, VKEY_OEM_3},
+ /* 134 */ {{0x0060, 0x007E, 0x00BF, DomCode::BACKQUOTE}, VKEY_OEM_3},
// grave accent, tilde, o double acute
- /* 134 */ {{0x0060, 0x007E, 0x0151, DomCode::BACKQUOTE}, VKEY_OEM_3},
+ /* 135 */ {{0x0060, 0x007E, 0x0151, DomCode::BACKQUOTE}, VKEY_OEM_3},
// grave accent, not sign, *
- /* 135 */ {{0x0060, 0x00AC, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_8},
+ /* 136 */ {{0x0060, 0x00AC, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_8},
// left curly bracket, *, *
- /* 136 */ {{0x007B, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_7},
+ /* 137 */ {{0x007B, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_7},
// vertical line, *, *
- /* 137 */ {{0x007C, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
+ /* 138 */ {{0x007C, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
// right curly bracket, *, *
- /* 138 */ {{0x007D, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_2},
+ /* 139 */ {{0x007D, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_2},
// tilde, *, *
- /* 139 */ {{0x007E, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
+ /* 140 */ {{0x007E, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
// inverted exclamation mark, *, *
- /* 140 */ {{0x00A1, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
+ /* 141 */ {{0x00A1, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
// section sign, degree sign, *
- /* 141 */ {{0x00A7, 0x00B0, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_2},
+ /* 142 */ {{0x00A7, 0x00B0, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_2},
// section sign, vulgar fraction one half, *
- /* 142 */ {{0x00A7, 0x00BD, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_5},
+ /* 143 */ {{0x00A7, 0x00BD, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_5},
// section sign, *, *
- /* 143 */ {{0x00A7, 0x2460, 0x2461, DomCode::DIGIT4}, VKEY_4},
+ /* 144 */ {{0x00A7, 0x2460, 0x2461, DomCode::DIGIT4}, VKEY_4},
// section sign, *, *
- /* 144 */ {{0x00A7, 0x2460, 0x2461, DomCode::DIGIT6}, VKEY_6},
+ /* 145 */ {{0x00A7, 0x2460, 0x2461, DomCode::DIGIT6}, VKEY_6},
// section sign, *, *
- /* 145 */ {{0x00A7, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
+ /* 146 */ {{0x00A7, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
// left-pointing double angle quotation mark, *, *
- /* 146 */ {{0x00AB, 0x2460, 0x2461, DomCode::DIGIT8}, VKEY_8},
+ /* 147 */ {{0x00AB, 0x2460, 0x2461, DomCode::DIGIT8}, VKEY_8},
// left-pointing double angle quotation mark, *, *
- /* 147 */ {{0x00AB, 0x2460, 0x2461, DomCode::EQUAL}, VKEY_OEM_6},
+ /* 148 */ {{0x00AB, 0x2460, 0x2461, DomCode::EQUAL}, VKEY_OEM_6},
// soft hyphen, *, *
- /* 148 */ {{0x00AD, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_3},
+ /* 149 */ {{0x00AD, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_3},
// degree sign, *, *
- /* 149 */ {{0x00B0, 0x2460, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_7},
+ /* 150 */ {{0x00B0, 0x2460, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_7},
// degree sign, *, *
- /* 150 */ {{0x00B0, 0x2460, 0x2461, DomCode::EQUAL}, VKEY_OEM_2},
+ /* 151 */ {{0x00B0, 0x2460, 0x2461, DomCode::EQUAL}, VKEY_OEM_2},
// superscript two, *, *
- /* 151 */ {{0x00B2, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_7},
+ /* 152 */ {{0x00B2, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_7},
// micro sign, *, *
- /* 152 */ {{0x00B5, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
+ /* 153 */ {{0x00B5, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
// masculine ordinal indicator, *, *
- /* 153 */ {{0x00BA, 0x2460, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_5},
+ /* 154 */ {{0x00BA, 0x2460, 0x2461, DomCode::BACKQUOTE}, VKEY_OEM_5},
// masculine ordinal indicator, *, *
- /* 154 */ {{0x00BA, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
+ /* 155 */ {{0x00BA, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
// right-pointing double angle quotation mark, *, *
- /* 155 */ {{0x00BB, 0x2460, 0x2461, DomCode::NONE}, VKEY_9},
+ /* 156 */ {{0x00BB, 0x2460, 0x2461, DomCode::NONE}, VKEY_9},
// vulgar fraction one half, *, *
- /* 156 */ {{0x00BD, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
+ /* 157 */ {{0x00BD, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
// inverted question mark, *, *
- /* 157 */ {{0x00BF, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
+ /* 158 */ {{0x00BF, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
// sharp s, *, *
- /* 158 */ {{0x00DF, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_4},
+ /* 159 */ {{0x00DF, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_4},
// a grave, degree sign, *
- /* 159 */ {{0x00E0, 0x00B0, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
+ /* 160 */ {{0x00E0, 0x00B0, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
// a grave, a diaeresis, *
- /* 160 */ {{0x00E0, 0x00E4, 0x2461, DomCode::QUOTE}, VKEY_OEM_5},
+ /* 161 */ {{0x00E0, 0x00E4, 0x2461, DomCode::QUOTE}, VKEY_OEM_5},
// a grave, *, *
- /* 161 */ {{0x00E0, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_5},
+ /* 162 */ {{0x00E0, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_5},
// a grave, *, *
- /* 162 */ {{0x00E0, 0x2460, 0x2461, DomCode::DIGIT0}, VKEY_0},
+ /* 163 */ {{0x00E0, 0x2460, 0x2461, DomCode::DIGIT0}, VKEY_0},
// a acute, *, *
- /* 163 */ {{0x00E1, 0x2460, 0x2461, DomCode::DIGIT8}, VKEY_8},
+ /* 164 */ {{0x00E1, 0x2460, 0x2461, DomCode::DIGIT8}, VKEY_8},
// a acute, *, *
- /* 164 */ {{0x00E1, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
+ /* 165 */ {{0x00E1, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
// a circumflex, *, *
- /* 165 */ {{0x00E2, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_5},
+ /* 166 */ {{0x00E2, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_5},
// a circumflex, *, *
- /* 166 */ {{0x00E2, 0x2460, 0x2461, DomCode::DIGIT2}, VKEY_2},
+ /* 167 */ {{0x00E2, 0x2460, 0x2461, DomCode::DIGIT2}, VKEY_2},
// a diaeresis, A diaeresis, unmapped
- /* 167 */ {{0x00E4, 0x00C4, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
+ /* 168 */ {{0x00E4, 0x00C4, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
// a diaeresis, A diaeresis, r caron
- /* 168 */ {{0x00E4, 0x00C4, 0x0159, DomCode::QUOTE}, VKEY_OEM_7},
+ /* 169 */ {{0x00E4, 0x00C4, 0x0159, DomCode::QUOTE}, VKEY_OEM_7},
// a diaeresis, A diaeresis, S acute
- /* 169 */ {{0x00E4, 0x00C4, 0x015A, DomCode::QUOTE}, VKEY_OEM_7},
+ /* 170 */ {{0x00E4, 0x00C4, 0x015A, DomCode::QUOTE}, VKEY_OEM_7},
// a diaeresis, a grave, *
- /* 170 */ {{0x00E4, 0x00E0, 0x2461, DomCode::QUOTE}, VKEY_OEM_5},
+ /* 171 */ {{0x00E4, 0x00E0, 0x2461, DomCode::QUOTE}, VKEY_OEM_5},
// a diaeresis, *, *
- /* 171 */ {{0x00E4, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
+ /* 172 */ {{0x00E4, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
// a ring above, *, *
- /* 172 */ {{0x00E5, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
+ /* 173 */ {{0x00E5, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
// ae, *, *
- /* 173 */ {{0x00E6, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
+ /* 174 */ {{0x00E6, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
// ae, *, *
- /* 174 */ {{0x00E6, 0x2460, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_3},
+ /* 175 */ {{0x00E6, 0x2460, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_3},
// c cedilla, C cedilla, unmapped
- /* 175 */ {{0x00E7, 0x00C7, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_1},
+ /* 176 */ {{0x00E7, 0x00C7, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_1},
// c cedilla, C cedilla, Thorn
- /* 176 */ {{0x00E7, 0x00C7, 0x00DE, DomCode::SEMICOLON}, VKEY_OEM_3},
+ /* 177 */ {{0x00E7, 0x00C7, 0x00DE, DomCode::SEMICOLON}, VKEY_OEM_3},
// c cedilla, *, *
- /* 177 */ {{0x00E7, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_2},
+ /* 178 */ {{0x00E7, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_2},
// c cedilla, *, *
- /* 178 */ {{0x00E7, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
+ /* 179 */ {{0x00E7, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
// c cedilla, *, *
- /* 179 */ {{0x00E7, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
+ /* 180 */ {{0x00E7, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
// c cedilla, *, *
- /* 180 */ {{0x00E7, 0x2460, 0x2461, DomCode::COMMA}, VKEY_OEM_COMMA},
+ /* 181 */ {{0x00E7, 0x2460, 0x2461, DomCode::COMMA}, VKEY_OEM_COMMA},
// c cedilla, *, *
- /* 181 */ {{0x00E7, 0x2460, 0x2461, DomCode::DIGIT9}, VKEY_9},
+ /* 182 */ {{0x00E7, 0x2460, 0x2461, DomCode::DIGIT9}, VKEY_9},
// c cedilla, *, *
- /* 182 */ {{0x00E7, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
+ /* 183 */ {{0x00E7, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
// e grave, *, *
- /* 183 */ {{0x00E8, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_1},
+ /* 184 */ {{0x00E8, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_1},
// e grave, *, *
- /* 184 */ {{0x00E8, 0x2460, 0x2461, DomCode::DIGIT7}, VKEY_7},
+ /* 185 */ {{0x00E8, 0x2460, 0x2461, DomCode::DIGIT7}, VKEY_7},
// e grave, *, *
- /* 185 */ {{0x00E8, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_3},
+ /* 186 */ {{0x00E8, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_3},
// e acute, E acute, *
- /* 186 */ {{0x00E9, 0x00C9, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_1},
+ /* 187 */ {{0x00E9, 0x00C9, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_1},
// e acute, o diaeresis, *
- /* 187 */ {{0x00E9, 0x00F6, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_7},
+ /* 188 */ {{0x00E9, 0x00F6, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_7},
// e acute, *, *
- /* 188 */ {{0x00E9, 0x2460, 0x2461, DomCode::DIGIT0}, VKEY_0},
+ /* 189 */ {{0x00E9, 0x2460, 0x2461, DomCode::DIGIT0}, VKEY_0},
// e acute, *, *
- /* 189 */ {{0x00E9, 0x2460, 0x2461, DomCode::DIGIT2}, VKEY_2},
+ /* 190 */ {{0x00E9, 0x2460, 0x2461, DomCode::DIGIT2}, VKEY_2},
// e acute, *, *
- /* 190 */ {{0x00E9, 0x2460, 0x2461, DomCode::SLASH}, VKEY_OEM_2},
+ /* 191 */ {{0x00E9, 0x2460, 0x2461, DomCode::SLASH}, VKEY_OEM_2},
// e circumflex, *, *
- /* 191 */ {{0x00EA, 0x2460, 0x2461, DomCode::NONE}, VKEY_3},
+ /* 192 */ {{0x00EA, 0x2460, 0x2461, DomCode::NONE}, VKEY_3},
// e diaeresis, *, *
- /* 192 */ {{0x00EB, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_1},
+ /* 193 */ {{0x00EB, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_1},
// i grave, *, *
- /* 193 */ {{0x00EC, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
+ /* 194 */ {{0x00EC, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
// i acute, *, *
- /* 194 */ {{0x00ED, 0x2460, 0x2461, DomCode::BACKQUOTE}, VKEY_0},
+ /* 195 */ {{0x00ED, 0x2460, 0x2461, DomCode::BACKQUOTE}, VKEY_0},
// i acute, *, *
- /* 195 */ {{0x00ED, 0x2460, 0x2461, DomCode::DIGIT9}, VKEY_9},
+ /* 196 */ {{0x00ED, 0x2460, 0x2461, DomCode::DIGIT9}, VKEY_9},
// i circumflex, *, *
- /* 196 */ {{0x00EE, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
+ /* 197 */ {{0x00EE, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
// eth, *, *
- /* 197 */ {{0x00F0, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_6},
+ /* 198 */ {{0x00F0, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_6},
// eth, *, *
- /* 198 */ {{0x00F0, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_1},
+ /* 199 */ {{0x00F0, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_1},
// n tilde, *, *
- /* 199 */ {{0x00F1, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_3},
+ /* 200 */ {{0x00F1, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_3},
// o grave, *, *
- /* 200 */ {{0x00F2, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_3},
+ /* 201 */ {{0x00F2, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_3},
// o acute, *, *
- /* 201 */ {{0x00F3, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_5},
+ /* 202 */ {{0x00F3, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_5},
// o acute, *, *
- /* 202 */ {{0x00F3, 0x2460, 0x2461, DomCode::EQUAL}, VKEY_OEM_PLUS},
+ /* 203 */ {{0x00F3, 0x2460, 0x2461, DomCode::EQUAL}, VKEY_OEM_PLUS},
// o circumflex, *, *
- /* 203 */ {{0x00F4, 0x2460, 0x2461, DomCode::DIGIT4}, VKEY_4},
+ /* 204 */ {{0x00F4, 0x2460, 0x2461, DomCode::DIGIT4}, VKEY_4},
// o circumflex, *, *
- /* 204 */ {{0x00F4, 0x2460, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_1},
+ /* 205 */ {{0x00F4, 0x2460, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_1},
// o tilde, *, *
- /* 205 */ {{0x00F5, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_4},
+ /* 206 */ {{0x00F5, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_4},
// o diaeresis, O diaeresis, unmapped
- /* 206 */ {{0x00F6, 0x00D6, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_3},
+ /* 207 */ {{0x00F6, 0x00D6, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_3},
// o diaeresis, O diaeresis, T cedilla
- /* 207 */ {{0x00F6, 0x00D6, 0x0162, DomCode::SEMICOLON}, VKEY_OEM_3},
+ /* 208 */ {{0x00F6, 0x00D6, 0x0162, DomCode::SEMICOLON}, VKEY_OEM_3},
// o diaeresis, e acute, *
- /* 208 */ {{0x00F6, 0x00E9, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_7},
+ /* 209 */ {{0x00F6, 0x00E9, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_7},
// o diaeresis, *, *
- /* 209 */ {{0x00F6, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
+ /* 210 */ {{0x00F6, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
// o diaeresis, *, *
- /* 210 */ {{0x00F6, 0x2460, 0x2461, DomCode::DIGIT0}, VKEY_OEM_3},
+ /* 211 */ {{0x00F6, 0x2460, 0x2461, DomCode::DIGIT0}, VKEY_OEM_3},
// o diaeresis, *, *
- /* 211 */ {{0x00F6, 0x2460, 0x2461, DomCode::MINUS}, VKEY_OEM_PLUS},
+ /* 212 */ {{0x00F6, 0x2460, 0x2461, DomCode::MINUS}, VKEY_OEM_PLUS},
// division sign, *, *
- /* 212 */ {{0x00F7, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
+ /* 213 */ {{0x00F7, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
// o stroke, *, *
- /* 213 */ {{0x00F8, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
+ /* 214 */ {{0x00F8, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
// o stroke, *, *
- /* 214 */ {{0x00F8, 0x2460, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_3},
+ /* 215 */ {{0x00F8, 0x2460, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_3},
// u grave, *, *
- /* 215 */ {{0x00F9, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_2},
+ /* 216 */ {{0x00F9, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_2},
// u grave, *, *
- /* 216 */ {{0x00F9, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_3},
+ /* 217 */ {{0x00F9, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_3},
// u acute, *, *
- /* 217 */ {{0x00FA, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
+ /* 218 */ {{0x00FA, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
// u acute, *, *
- /* 218 */ {{0x00FA, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
+ /* 219 */ {{0x00FA, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
// u diaeresis, U diaeresis, unmapped
- /* 219 */ {{0x00FC, 0x00DC, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_1},
+ /* 220 */ {{0x00FC, 0x00DC, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_1},
// u diaeresis, U diaeresis, unmapped
- /* 220 */ {{0x00FC, 0x00DC, 0x2461, DomCode::MINUS}, VKEY_OEM_2},
+ /* 221 */ {{0x00FC, 0x00DC, 0x2461, DomCode::MINUS}, VKEY_OEM_2},
// u diaeresis, U diaeresis, L stroke
- /* 221 */ {{0x00FC, 0x00DC, 0x0141, DomCode::BRACKET_LEFT}, VKEY_OEM_3},
+ /* 222 */ {{0x00FC, 0x00DC, 0x0141, DomCode::BRACKET_LEFT}, VKEY_OEM_3},
// u diaeresis, e grave, *
- /* 222 */ {{0x00FC, 0x00E8, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_1},
+ /* 223 */ {{0x00FC, 0x00E8, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_1},
// u diaeresis, *, *
- /* 223 */ {{0x00FC, 0x2460, 0x2461, DomCode::US_W}, VKEY_W},
+ /* 224 */ {{0x00FC, 0x2460, 0x2461, DomCode::US_W}, VKEY_W},
// y acute, *, *
- /* 224 */ {{0x00FD, 0x2460, 0x2461, DomCode::NONE}, VKEY_7},
+ /* 225 */ {{0x00FD, 0x2460, 0x2461, DomCode::NONE}, VKEY_7},
// thorn, *, *
- /* 225 */ {{0x00FE, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_MINUS},
+ /* 226 */ {{0x00FE, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_MINUS},
// a macron, *, *
- /* 226 */ {{0x0101, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_8},
+ /* 227 */ {{0x0101, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_8},
// a breve, *, *
- /* 227 */ {{0x0103, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
+ /* 228 */ {{0x0103, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
// a breve, *, *
- /* 228 */ {{0x0103, 0x2460, 0x2461, DomCode::DIGIT1}, VKEY_1},
+ /* 229 */ {{0x0103, 0x2460, 0x2461, DomCode::DIGIT1}, VKEY_1},
// a ogonek, *, *
- /* 229 */ {{0x0105, 0x2460, 0x2461, DomCode::DIGIT1}, VKEY_1},
+ /* 230 */ {{0x0105, 0x2460, 0x2461, DomCode::DIGIT1}, VKEY_1},
// a ogonek, *, *
- /* 230 */ {{0x0105, 0x2460, 0x2461, DomCode::US_Q}, VKEY_Q},
+ /* 231 */ {{0x0105, 0x2460, 0x2461, DomCode::US_Q}, VKEY_Q},
// a ogonek, *, *
- /* 231 */ {{0x0105, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
+ /* 232 */ {{0x0105, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
// c acute, *, *
- /* 232 */ {{0x0107, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_7},
+ /* 233 */ {{0x0107, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_7},
// c dot above, *, *
- /* 233 */ {{0x010B, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_3},
+ /* 234 */ {{0x010B, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_3},
// c caron, *, *
- /* 234 */ {{0x010D, 0x2460, 0x2461, DomCode::COMMA}, VKEY_OEM_COMMA},
+ /* 235 */ {{0x010D, 0x2460, 0x2461, DomCode::COMMA}, VKEY_OEM_COMMA},
// c caron, *, *
- /* 235 */ {{0x010D, 0x2460, 0x2461, DomCode::DIGIT2}, VKEY_2},
+ /* 236 */ {{0x010D, 0x2460, 0x2461, DomCode::DIGIT2}, VKEY_2},
// c caron, *, *
- /* 236 */ {{0x010D, 0x2460, 0x2461, DomCode::DIGIT4}, VKEY_4},
+ /* 237 */ {{0x010D, 0x2460, 0x2461, DomCode::DIGIT4}, VKEY_4},
// c caron, *, *
- /* 237 */ {{0x010D, 0x2460, 0x2461, DomCode::US_P}, VKEY_X},
+ /* 238 */ {{0x010D, 0x2460, 0x2461, DomCode::US_P}, VKEY_X},
// c caron, *, *
- /* 238 */ {{0x010D, 0x2460, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_1},
+ /* 239 */ {{0x010D, 0x2460, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_1},
// d stroke, *, *
- /* 239 */ {{0x0111, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
+ /* 240 */ {{0x0111, 0x2460, 0x2461, DomCode::BRACKET_RIGHT}, VKEY_OEM_6},
// d stroke, *, *
- /* 240 */ {{0x0111, 0x2460, 0x2461, DomCode::DIGIT0}, VKEY_0},
+ /* 241 */ {{0x0111, 0x2460, 0x2461, DomCode::DIGIT0}, VKEY_0},
// e macron, *, *
- /* 241 */ {{0x0113, 0x2460, 0x2461, DomCode::NONE}, VKEY_W},
+ /* 242 */ {{0x0113, 0x2460, 0x2461, DomCode::NONE}, VKEY_W},
// e dot above, *, *
- /* 242 */ {{0x0117, 0x2460, 0x2461, DomCode::DIGIT4}, VKEY_4},
+ /* 243 */ {{0x0117, 0x2460, 0x2461, DomCode::DIGIT4}, VKEY_4},
// e dot above, *, *
- /* 243 */ {{0x0117, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
+ /* 244 */ {{0x0117, 0x2460, 0x2461, DomCode::QUOTE}, VKEY_OEM_7},
// e ogonek, E ogonek, unmapped
- /* 244 */ {{0x0119, 0x0118, 0x2461, DomCode::SLASH}, VKEY_OEM_MINUS},
+ /* 245 */ {{0x0119, 0x0118, 0x2461, DomCode::SLASH}, VKEY_OEM_MINUS},
// e ogonek, E ogonek, n
- /* 245 */ {{0x0119, 0x0118, 0x006E, DomCode::SLASH}, VKEY_OEM_2},
+ /* 246 */ {{0x0119, 0x0118, 0x006E, DomCode::SLASH}, VKEY_OEM_2},
// e ogonek, *, *
- /* 246 */ {{0x0119, 0x2460, 0x2461, DomCode::DIGIT3}, VKEY_3},
+ /* 247 */ {{0x0119, 0x2460, 0x2461, DomCode::DIGIT3}, VKEY_3},
// e caron, *, *
- /* 247 */ {{0x011B, 0x2460, 0x2461, DomCode::NONE}, VKEY_2},
+ /* 248 */ {{0x011B, 0x2460, 0x2461, DomCode::NONE}, VKEY_2},
// g breve, *, *
- /* 248 */ {{0x011F, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
+ /* 249 */ {{0x011F, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
// g dot above, *, *
- /* 249 */ {{0x0121, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_4},
+ /* 250 */ {{0x0121, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_4},
// h stroke, *, *
- /* 250 */ {{0x0127, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
+ /* 251 */ {{0x0127, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
// i macron, *, *
- /* 251 */ {{0x012B, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
+ /* 252 */ {{0x012B, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
// i ogonek, I ogonek, unmapped
- /* 252 */ {{0x012F, 0x012E, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
+ /* 253 */ {{0x012F, 0x012E, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
// i ogonek, *, *
- /* 253 */ {{0x012F, 0x2460, 0x2461, DomCode::DIGIT5}, VKEY_5},
+ /* 254 */ {{0x012F, 0x2460, 0x2461, DomCode::DIGIT5}, VKEY_5},
// dotless i, *, *
- /* 254 */ {{0x0131, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_1},
+ /* 255 */ {{0x0131, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_1},
// k cedilla, *, *
- /* 255 */ {{0x0137, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
+ /* 256 */ {{0x0137, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
// l cedilla, *, *
- /* 256 */ {{0x013C, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_2},
+ /* 257 */ {{0x013C, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_2},
// l caron, *, *
- /* 257 */ {{0x013E, 0x2460, 0x2461, DomCode::NONE}, VKEY_2},
+ /* 258 */ {{0x013E, 0x2460, 0x2461, DomCode::NONE}, VKEY_2},
// l stroke, *, *
- /* 258 */ {{0x0142, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_2},
+ /* 259 */ {{0x0142, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_2},
// l stroke, *, *
- /* 259 */ {{0x0142, 0x2460, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_1},
+ /* 260 */ {{0x0142, 0x2460, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_1},
// n cedilla, *, *
- /* 260 */ {{0x0146, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_4},
+ /* 261 */ {{0x0146, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_4},
// n caron, *, *
- /* 261 */ {{0x0148, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
+ /* 262 */ {{0x0148, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
// o double acute, *, *
- /* 262 */ {{0x0151, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_4},
+ /* 263 */ {{0x0151, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_4},
// r caron, *, *
- /* 263 */ {{0x0159, 0x2460, 0x2461, DomCode::NONE}, VKEY_5},
+ /* 264 */ {{0x0159, 0x2460, 0x2461, DomCode::NONE}, VKEY_5},
// s cedilla, *, *
- /* 264 */ {{0x015F, 0x2460, 0x2461, DomCode::PERIOD}, VKEY_OEM_PERIOD},
+ /* 265 */ {{0x015F, 0x2460, 0x2461, DomCode::PERIOD}, VKEY_OEM_PERIOD},
// s cedilla, *, *
- /* 265 */ {{0x015F, 0x2460, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_1},
+ /* 266 */ {{0x015F, 0x2460, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_1},
// s caron, *, *
- /* 266 */ {{0x0161, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
+ /* 267 */ {{0x0161, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
// s caron, *, *
- /* 267 */ {{0x0161, 0x2460, 0x2461, DomCode::DIGIT3}, VKEY_3},
+ /* 268 */ {{0x0161, 0x2460, 0x2461, DomCode::DIGIT3}, VKEY_3},
// s caron, *, *
- /* 268 */ {{0x0161, 0x2460, 0x2461, DomCode::DIGIT6}, VKEY_6},
+ /* 269 */ {{0x0161, 0x2460, 0x2461, DomCode::DIGIT6}, VKEY_6},
// s caron, *, *
- /* 269 */ {{0x0161, 0x2460, 0x2461, DomCode::US_A}, VKEY_OEM_1},
+ /* 270 */ {{0x0161, 0x2460, 0x2461, DomCode::US_A}, VKEY_OEM_1},
// s caron, *, *
- /* 270 */ {{0x0161, 0x2460, 0x2461, DomCode::US_F}, VKEY_F},
+ /* 271 */ {{0x0161, 0x2460, 0x2461, DomCode::US_F}, VKEY_F},
// s caron, *, *
- /* 271 */ {{0x0161, 0x2460, 0x2461, DomCode::PERIOD}, VKEY_OEM_PERIOD},
+ /* 272 */ {{0x0161, 0x2460, 0x2461, DomCode::PERIOD}, VKEY_OEM_PERIOD},
// t cedilla, *, *
- /* 272 */ {{0x0163, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_7},
+ /* 273 */ {{0x0163, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_7},
// t caron, *, *
- /* 273 */ {{0x0165, 0x2460, 0x2461, DomCode::NONE}, VKEY_5},
+ /* 274 */ {{0x0165, 0x2460, 0x2461, DomCode::NONE}, VKEY_5},
// u macron, *, *
- /* 274 */ {{0x016B, 0x2460, 0x2461, DomCode::DIGIT8}, VKEY_8},
+ /* 275 */ {{0x016B, 0x2460, 0x2461, DomCode::DIGIT8}, VKEY_8},
// u macron, *, *
- /* 275 */ {{0x016B, 0x2460, 0x2461, DomCode::US_Q}, VKEY_Q},
+ /* 276 */ {{0x016B, 0x2460, 0x2461, DomCode::US_Q}, VKEY_Q},
// u macron, *, *
- /* 276 */ {{0x016B, 0x2460, 0x2461, DomCode::US_X}, VKEY_X},
+ /* 277 */ {{0x016B, 0x2460, 0x2461, DomCode::US_X}, VKEY_X},
// u ring above, *, *
- /* 277 */ {{0x016F, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_1},
+ /* 278 */ {{0x016F, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_1},
// u double acute, *, *
- /* 278 */ {{0x0171, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
+ /* 279 */ {{0x0171, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_5},
// u ogonek, U ogonek, unmapped
- /* 279 */ {{0x0173, 0x0172, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_3},
+ /* 280 */ {{0x0173, 0x0172, 0x2461, DomCode::SEMICOLON}, VKEY_OEM_3},
// u ogonek, U ogonek, T cedilla
- /* 280 */ {{0x0173, 0x0172, 0x0162, DomCode::SEMICOLON}, VKEY_OEM_1},
+ /* 281 */ {{0x0173, 0x0172, 0x0162, DomCode::SEMICOLON}, VKEY_OEM_1},
// u ogonek, *, *
- /* 281 */ {{0x0173, 0x2460, 0x2461, DomCode::DIGIT7}, VKEY_7},
+ /* 282 */ {{0x0173, 0x2460, 0x2461, DomCode::DIGIT7}, VKEY_7},
// z dot above, *, *
- /* 282 */ {{0x017C, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_5},
+ /* 283 */ {{0x017C, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_5},
// z dot above, *, *
- /* 283 */ {{0x017C, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
+ /* 284 */ {{0x017C, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_OEM_4},
// z caron, *, *
- /* 284 */ {{0x017E, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_5},
+ /* 285 */ {{0x017E, 0x2460, 0x2461, DomCode::BACKSLASH}, VKEY_OEM_5},
// z caron, *, *
- /* 285 */ {{0x017E, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_Y},
+ /* 286 */ {{0x017E, 0x2460, 0x2461, DomCode::BRACKET_LEFT}, VKEY_Y},
// z caron, *, *
- /* 286 */ {{0x017E, 0x2460, 0x2461, DomCode::DIGIT6}, VKEY_6},
+ /* 287 */ {{0x017E, 0x2460, 0x2461, DomCode::DIGIT6}, VKEY_6},
// z caron, *, *
- /* 287 */ {{0x017E, 0x2460, 0x2461, DomCode::EQUAL}, VKEY_OEM_PLUS},
+ /* 288 */ {{0x017E, 0x2460, 0x2461, DomCode::EQUAL}, VKEY_OEM_PLUS},
// z caron, *, *
- /* 288 */ {{0x017E, 0x2460, 0x2461, DomCode::US_W}, VKEY_W},
+ /* 289 */ {{0x017E, 0x2460, 0x2461, DomCode::US_W}, VKEY_W},
// o horn, *, *
- /* 289 */ {{0x01A1, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
+ /* 290 */ {{0x01A1, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
// u horn, *, *
- /* 290 */ {{0x01B0, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_4},
+ /* 291 */ {{0x01B0, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_4},
// z stroke, *, *
- /* 291 */ {{0x01B6, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
+ /* 292 */ {{0x01B6, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_6},
// schwa, *, *
- /* 292 */ {{0x0259, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_3},
+ /* 293 */ {{0x0259, 0x2460, 0x2461, DomCode::NONE}, VKEY_OEM_3},
// Simple alphanumeric cases.
- /* 293 */ {{'a', 'A', '?', DomCode::NONE}, VKEY_A},
- /* 294 */ {{'z', 'Z', '!', DomCode::NONE}, VKEY_Z},
- /* 295 */ {{'9', '(', '+', DomCode::NONE}, VKEY_9},
- /* 296 */ {{'0', ')', '-', DomCode::NONE}, VKEY_0},
+ /* 294 */ {{'a', 'A', '?', DomCode::NONE}, VKEY_A},
+ /* 295 */ {{'z', 'Z', '!', DomCode::NONE}, VKEY_Z},
+ /* 296 */ {{'9', '(', '+', DomCode::NONE}, VKEY_9},
+ /* 297 */ {{'0', ')', '-', DomCode::NONE}, VKEY_0},
+
};
for (size_t i = 0; i < base::size(kVkeyTestCase); ++i) {
diff --git a/chromium/ui/events/platform/platform_event_source.cc b/chromium/ui/events/platform/platform_event_source.cc
index adebfa68ad2..c80a92ebfe6 100644
--- a/chromium/ui/events/platform/platform_event_source.cc
+++ b/chromium/ui/events/platform/platform_event_source.cc
@@ -71,9 +71,6 @@ std::unique_ptr<ScopedEventDispatcher> PlatformEventSource::OverrideDispatcher(
dispatcher);
}
-void PlatformEventSource::StopCurrentEventStream() {
-}
-
void PlatformEventSource::AddPlatformEventObserver(
PlatformEventObserver* observer) {
CHECK(observer);
@@ -105,14 +102,6 @@ uint32_t PlatformEventSource::DispatchEvent(PlatformEvent platform_event) {
for (PlatformEventObserver& observer : observers_)
observer.DidProcessEvent(platform_event);
- // If an overridden dispatcher has been destroyed, then the platform
- // event-source should halt dispatching the current stream of events, and wait
- // until the next message-loop iteration for dispatching events. This lets any
- // nested message-loop to unwind correctly and any new dispatchers to receive
- // the correct sequence of events.
- if (overridden_dispatcher_restored_)
- StopCurrentEventStream();
-
overridden_dispatcher_restored_ = false;
return action;
diff --git a/chromium/ui/events/platform/platform_event_source.h b/chromium/ui/events/platform/platform_event_source.h
index 7bd60d08a46..9dd21baed59 100644
--- a/chromium/ui/events/platform/platform_event_source.h
+++ b/chromium/ui/events/platform/platform_event_source.h
@@ -67,11 +67,6 @@ class EVENTS_EXPORT PlatformEventSource {
std::unique_ptr<ScopedEventDispatcher> OverrideDispatcher(
PlatformEventDispatcher* dispatcher);
- // Called to indicate that the source should stop dispatching the current
- // stream of events and wait until the next iteration of the message-loop to
- // dispatch the rest of the events.
- virtual void StopCurrentEventStream();
-
void AddPlatformEventObserver(PlatformEventObserver* observer);
void RemovePlatformEventObserver(PlatformEventObserver* observer);
diff --git a/chromium/ui/events/platform/platform_event_source_unittest.cc b/chromium/ui/events/platform/platform_event_source_unittest.cc
index edfd0100d9d..65f936a82a4 100644
--- a/chromium/ui/events/platform/platform_event_source_unittest.cc
+++ b/chromium/ui/events/platform/platform_event_source_unittest.cc
@@ -50,32 +50,12 @@ void AddDispatcher(PlatformEventDispatcher* dispatcher) {
class TestPlatformEventSource : public PlatformEventSource {
public:
- TestPlatformEventSource()
- : stop_stream_(false) {
- }
- ~TestPlatformEventSource() override {}
+ TestPlatformEventSource() = default;
+ TestPlatformEventSource(const TestPlatformEventSource&) = delete;
+ TestPlatformEventSource& operator=(const TestPlatformEventSource&) = delete;
+ ~TestPlatformEventSource() override = default;
uint32_t Dispatch(const PlatformEvent& event) { return DispatchEvent(event); }
-
- // Dispatches the stream of events, and returns the number of events that are
- // dispatched before it is requested to stop.
- size_t DispatchEventStream(
- const std::vector<std::unique_ptr<PlatformEvent>>& events) {
- stop_stream_ = false;
- for (size_t count = 0; count < events.size(); ++count) {
- DispatchEvent(*events[count]);
- if (stop_stream_)
- return count + 1;
- }
- return events.size();
- }
-
- // PlatformEventSource:
- void StopCurrentEventStream() override { stop_stream_ = true; }
-
- private:
- bool stop_stream_;
- DISALLOW_COPY_AND_ASSIGN(TestPlatformEventSource);
};
class TestPlatformEventDispatcher : public PlatformEventDispatcher {
@@ -598,84 +578,6 @@ class DestroyScopedHandleDispatcher : public TestPlatformEventDispatcher {
DISALLOW_COPY_AND_ASSIGN(DestroyScopedHandleDispatcher);
};
-// Tests that resetting an overridden dispatcher causes the nested message-loop
-// iteration to stop and the rest of the events are dispatched in the next
-// iteration.
-class DestroyedNestedOverriddenDispatcherQuitsNestedLoopIteration
- : public PlatformEventTestWithMessageLoop {
- public:
- void NestedTask(std::vector<int>* list,
- TestPlatformEventDispatcher* dispatcher) {
- std::vector<std::unique_ptr<PlatformEvent>> events;
- events.push_back(CreatePlatformEvent());
- events.push_back(CreatePlatformEvent());
-
- // Attempt to dispatch a couple of events. Dispatching the first event will
- // have terminated the ScopedEventDispatcher object, which will terminate
- // the current iteration of the message-loop.
- size_t count = source()->DispatchEventStream(events);
- EXPECT_EQ(1u, count);
- ASSERT_EQ(2u, list->size());
- EXPECT_EQ(15, (*list)[0]);
- EXPECT_EQ(20, (*list)[1]);
- list->clear();
-
- ASSERT_LT(count, events.size());
- events.erase(events.begin(), events.begin() + count);
-
- count = source()->DispatchEventStream(events);
- EXPECT_EQ(1u, count);
- ASSERT_EQ(2u, list->size());
- EXPECT_EQ(15, (*list)[0]);
- EXPECT_EQ(10, (*list)[1]);
- list->clear();
-
- // Terminate the run loop.
- run_loop_.Quit();
- }
-
- // PlatformEventTestWithMessageLoop:
- void RunTestImpl() override {
- std::vector<int> list;
- TestPlatformEventDispatcher dispatcher(10, &list);
- TestPlatformEventObserver observer(15, &list);
-
- DestroyScopedHandleDispatcher overriding(20, &list);
- source()->RemovePlatformEventDispatcher(&overriding);
- std::unique_ptr<ScopedEventDispatcher> override_handle =
- source()->OverrideDispatcher(&overriding);
-
- std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
- source()->Dispatch(*event);
- ASSERT_EQ(2u, list.size());
- EXPECT_EQ(15, list[0]);
- EXPECT_EQ(20, list[1]);
- list.clear();
-
- overriding.SetScopedHandle(std::move(override_handle));
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(
- &DestroyedNestedOverriddenDispatcherQuitsNestedLoopIteration::
- NestedTask,
- base::Unretained(this), base::Unretained(&list),
- base::Unretained(&overriding)));
- run_loop_.Run();
-
- // Dispatching the event should now reach the default dispatcher.
- source()->Dispatch(*event);
- ASSERT_EQ(2u, list.size());
- EXPECT_EQ(15, list[0]);
- EXPECT_EQ(10, list[1]);
- }
-
- private:
- base::RunLoop run_loop_{base::RunLoop::Type::kNestableTasksAllowed};
-};
-
-RUN_TEST_IN_MESSAGE_LOOP(
- DestroyedNestedOverriddenDispatcherQuitsNestedLoopIteration)
-
// Tests that resetting an overridden dispatcher, and installing another
// overridden dispatcher before the nested message-loop completely unwinds
// function correctly.
diff --git a/chromium/ui/events/platform/x11/x11_event_source.cc b/chromium/ui/events/platform/x11/x11_event_source.cc
index 63f5fefdaf8..723a101d53c 100644
--- a/chromium/ui/events/platform/x11/x11_event_source.cc
+++ b/chromium/ui/events/platform/x11/x11_event_source.cc
@@ -148,14 +148,6 @@ X11EventSource* X11EventSource::GetInstance() {
////////////////////////////////////////////////////////////////////////////////
// X11EventSource, public
-void X11EventSource::DispatchXEvents() {
- continue_stream_ = true;
- do {
- connection_->Flush();
- connection_->ReadResponses();
- } while (connection_->Dispatch() && continue_stream_);
-}
-
x11::Time X11EventSource::GetCurrentServerTime() {
DCHECK(connection_);
@@ -217,11 +209,11 @@ x11::Time X11EventSource::GetTimestamp() {
return GetCurrentServerTime();
}
-base::Optional<gfx::Point>
+absl::optional<gfx::Point>
X11EventSource::GetRootCursorLocationFromCurrentEvent() const {
auto* event = connection_->dispatching_event();
if (!event)
- return base::nullopt;
+ return absl::nullopt;
auto* device = event->As<x11::Input::DeviceEvent>();
auto* crossing = event->As<x11::Input::CrossingEvent>();
@@ -244,7 +236,7 @@ X11EventSource::GetRootCursorLocationFromCurrentEvent() const {
if (is_valid_event)
return ui::EventSystemLocationFromXEvent(*event);
- return base::nullopt;
+ return absl::nullopt;
}
////////////////////////////////////////////////////////////////////////////////
@@ -300,10 +292,6 @@ void X11EventSource::OnEvent(const x11::Event& x11_event) {
}
}
-void X11EventSource::StopCurrentEventStream() {
- continue_stream_ = false;
-}
-
void X11EventSource::OnDispatcherListChanged() {
watcher_->StartWatching();
diff --git a/chromium/ui/events/platform/x11/x11_event_source.h b/chromium/ui/events/platform/x11/x11_event_source.h
index 1d12649d512..30eb759f8d6 100644
--- a/chromium/ui/events/platform/x11/x11_event_source.h
+++ b/chromium/ui/events/platform/x11/x11_event_source.h
@@ -12,7 +12,7 @@
#include "base/auto_reset.h"
#include "base/callback.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/events_export.h"
#include "ui/events/platform/platform_event_source.h"
#include "ui/gfx/x/connection.h"
@@ -61,10 +61,6 @@ class EVENTS_EXPORT X11EventSource : public PlatformEventSource,
static bool HasInstance();
static X11EventSource* GetInstance();
- // Called when there is a new XEvent available. Processes all (if any)
- // available X events.
- void DispatchXEvents();
-
x11::Connection* connection() { return connection_; }
// Returns the timestamp of the event currently being dispatched. Falls back
@@ -74,7 +70,7 @@ class EVENTS_EXPORT X11EventSource : public PlatformEventSource,
// Returns the root pointer location only if there is an event being
// dispatched that contains that information.
- base::Optional<gfx::Point> GetRootCursorLocationFromCurrentEvent() const;
+ absl::optional<gfx::Point> GetRootCursorLocationFromCurrentEvent() const;
// Explicitly asks the X11 server for the current timestamp, and updates
// |last_seen_server_time_| with this value.
@@ -85,7 +81,6 @@ class EVENTS_EXPORT X11EventSource : public PlatformEventSource,
void OnEvent(const x11::Event& event) override;
// PlatformEventSource:
- void StopCurrentEventStream() override;
void OnDispatcherListChanged() override;
std::unique_ptr<X11EventWatcher> watcher_;
@@ -99,10 +94,6 @@ class EVENTS_EXPORT X11EventSource : public PlatformEventSource,
x11::Atom dummy_atom_;
std::unique_ptr<x11::XScopedEventSelector> dummy_window_events_;
- // Keeps track of whether this source should continue to dispatch all the
- // available events.
- bool continue_stream_ = true;
-
std::unique_ptr<X11HotplugEventHandler> hotplug_event_handler_;
DISALLOW_COPY_AND_ASSIGN(X11EventSource);
diff --git a/chromium/ui/events/platform/x11/x11_event_watcher_fdwatch.cc b/chromium/ui/events/platform/x11/x11_event_watcher_fdwatch.cc
index 99fcfe2a0b9..8cbba218b44 100644
--- a/chromium/ui/events/platform/x11/x11_event_watcher_fdwatch.cc
+++ b/chromium/ui/events/platform/x11/x11_event_watcher_fdwatch.cc
@@ -36,7 +36,9 @@ void X11EventWatcherFdWatch::StopWatching() {
}
void X11EventWatcherFdWatch::OnFileCanReadWithoutBlocking(int fd) {
- event_source_->DispatchXEvents();
+ // We must dispatch all events, otherwise we may deadlock polling for new
+ // events when we already have events queued.
+ event_source_->connection()->DispatchAll();
}
void X11EventWatcherFdWatch::OnFileCanWriteWithoutBlocking(int fd) {
diff --git a/chromium/ui/events/platform/x11/x11_event_watcher_glib.cc b/chromium/ui/events/platform/x11/x11_event_watcher_glib.cc
index f523555ba14..e4099f72235 100644
--- a/chromium/ui/events/platform/x11/x11_event_watcher_glib.cc
+++ b/chromium/ui/events/platform/x11/x11_event_watcher_glib.cc
@@ -6,7 +6,6 @@
#include <glib.h>
-
namespace ui {
namespace {
@@ -19,28 +18,50 @@ struct GLibX11Source : public GSource {
};
gboolean XSourcePrepare(GSource* source, gint* timeout_ms) {
- GLibX11Source* gxsource = static_cast<GLibX11Source*>(source);
- gxsource->connection->Flush();
- gxsource->connection->ReadResponses();
- if (gxsource->connection->HasPendingResponses())
- return TRUE;
+ // Set an infinite timeout.
*timeout_ms = -1;
- return FALSE;
+
+ // This function is called before polling the FD, so a flush is mandatory
+ // in case:
+ // 1. This is the first message loop iteration and we have unflushed
+ // requests.
+ // 2. A request was made after XSourceDispatch() when running tasks from
+ // the task queue.
+ auto* connection = static_cast<GLibX11Source*>(source)->connection;
+ connection->Flush();
+
+ // Read a pre-buffered response if available to prevent a deadlock where we
+ // poll() for data that will never arrive since we already have data in our
+ // read buffer.
+ connection->ReadResponse(true);
+
+ // Return true if we can determine that event processing is necessary without
+ // polling the FD.
+ return connection->HasPendingResponses();
}
gboolean XSourceCheck(GSource* source) {
+ // Only read a response if poll() determined the FD is readable.
GLibX11Source* gxsource = static_cast<GLibX11Source*>(source);
- gxsource->connection->Flush();
- gxsource->connection->ReadResponses();
+ if (gxsource->poll_fd->revents & G_IO_IN)
+ gxsource->connection->ReadResponse(false);
return gxsource->connection->HasPendingResponses();
}
gboolean XSourceDispatch(GSource* source,
GSourceFunc unused_func,
gpointer data) {
- X11EventSource* x11_source = static_cast<X11EventSource*>(data);
- x11_source->DispatchXEvents();
- return TRUE;
+ auto* connection = static_cast<GLibX11Source*>(source)->connection;
+ connection->Dispatch();
+
+ // Flushing here is not strictly required, but when this function returns,
+ // tasks from the task queue will be run, which may take some time. Flushing
+ // now will ensure screen updates occur right away. Fortunately, this won't
+ // do any syscalls if it's not necessary.
+ connection->Flush();
+
+ // Don't remove the GLibX11Source from the main loop.
+ return G_SOURCE_CONTINUE;
}
GSourceFuncs XSourceFuncs = {XSourcePrepare, XSourceCheck, XSourceDispatch,
diff --git a/chromium/ui/events/pointer_details.cc b/chromium/ui/events/pointer_details.cc
index b83926f7988..3d51033520a 100644
--- a/chromium/ui/events/pointer_details.cc
+++ b/chromium/ui/events/pointer_details.cc
@@ -5,6 +5,7 @@
#include "ui/events/pointer_details.h"
#include <cmath>
+#include <sstream>
namespace ui {
@@ -55,4 +56,13 @@ bool PointerDetails::operator==(const PointerDetails& other) const {
twist == other.twist && id == other.id && offset == other.offset;
}
+std::string PointerDetails::ToString() const {
+ std::ostringstream ss;
+
+ ss << "radius x/y: " << radius_x << "/" << radius_y << std::endl;
+ ss << "force/twist: " << force << "/" << twist << std::endl;
+ ss << "tilt x/y: " << tilt_x << "/" << tilt_y << std::endl;
+ return ss.str();
+}
+
} // namespace ui
diff --git a/chromium/ui/events/pointer_details.h b/chromium/ui/events/pointer_details.h
index d03db11d10e..131dfaa7117 100644
--- a/chromium/ui/events/pointer_details.h
+++ b/chromium/ui/events/pointer_details.h
@@ -44,6 +44,8 @@ struct EVENTS_BASE_EXPORT PointerDetails {
bool operator==(const PointerDetails& other) const;
+ std::string ToString() const;
+
// The type of pointer device.
EventPointerType pointer_type = EventPointerType::kUnknown;
diff --git a/chromium/ui/events/scoped_target_handler.h b/chromium/ui/events/scoped_target_handler.h
index 917fa4a6c83..2927103bcd3 100644
--- a/chromium/ui/events/scoped_target_handler.h
+++ b/chromium/ui/events/scoped_target_handler.h
@@ -50,4 +50,4 @@ class EVENTS_EXPORT ScopedTargetHandler : public EventHandler {
} // namespace ui
-#endif // UI_EVENTsS_SCOPED_TARGET_HANDLER_H_
+#endif // UI_EVENTS_SCOPED_TARGET_HANDLER_H_
diff --git a/chromium/ui/events/win/events_win.cc b/chromium/ui/events/win/events_win.cc
index 18a361f6219..e65cb88c50e 100644
--- a/chromium/ui/events/win/events_win.cc
+++ b/chromium/ui/events/win/events_win.cc
@@ -17,9 +17,19 @@ int EventFlagsFromNative(const MSG& native_event) {
}
base::TimeTicks EventTimeFromNative(const MSG& native_event) {
+ // Note EventTimeFromMSG actually returns a time based on the current clock
+ // tick, ignoring MSG. See the comments in that function (which is in
+ // events_win_utils.cc) for the reason.
return EventTimeFromMSG(native_event);
}
+base::TimeTicks EventLatencyTimeFromNative(const MSG& native_event,
+ base::TimeTicks current_time) {
+ // For latency calculations use the real timestamp, rather than the one
+ // returned from EventTimeFromMSG.
+ return EventLatencyTimeFromTickClock(native_event.time, current_time);
+}
+
gfx::PointF EventLocationFromNative(const MSG& native_event) {
return gfx::PointF(EventLocationFromMSG(native_event));
}
diff --git a/chromium/ui/events/win/events_win_utils.cc b/chromium/ui/events/win/events_win_utils.cc
index 655e113dd4e..ce5b9011d3b 100644
--- a/chromium/ui/events/win/events_win_utils.cc
+++ b/chromium/ui/events/win/events_win_utils.cc
@@ -5,9 +5,12 @@
#include <stdint.h>
#include "base/check.h"
+#include "base/no_destructor.h"
#include "base/notreached.h"
+#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "base/win/windowsx_shim.h"
+#include "ui/events/base_event_utils.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
@@ -153,6 +156,19 @@ int MouseStateFlags(const MSG& native_event) {
return flags;
}
+class GetTickCountClock : public base::TickClock {
+ public:
+ GetTickCountClock() = default;
+ ~GetTickCountClock() override = default;
+
+ base::TimeTicks NowTicks() const override {
+ return base::TimeTicks() +
+ base::TimeDelta::FromMilliseconds(::GetTickCount());
+ }
+};
+
+const base::TickClock* g_tick_count_clock = nullptr;
+
} // namespace
EventType EventTypeFromMSG(const MSG& native_event) {
@@ -242,6 +258,47 @@ base::TimeTicks EventTimeFromMSG(const MSG& native_event) {
return EventTimeForNow();
}
+base::TimeTicks EventLatencyTimeFromTickClock(DWORD event_time,
+ base::TimeTicks current_time) {
+ static const base::NoDestructor<GetTickCountClock> default_tick_count_clock;
+ if (!g_tick_count_clock)
+ g_tick_count_clock = default_tick_count_clock.get();
+
+ base::TimeTicks time_stamp =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(event_time);
+
+ base::TimeTicks current_tick_count = g_tick_count_clock->NowTicks();
+ // Check if the 32-bit tick count wrapped around after the event.
+ if (current_tick_count < time_stamp) {
+ // ::GetTickCount returns an unsigned 32-bit value, which will fit into the
+ // signed 64-bit base::TimeTicks.
+ current_tick_count +=
+ base::TimeDelta::FromMilliseconds(std::numeric_limits<DWORD>::max());
+ }
+
+ // |time_stamp| is from the GetTickCount clock, which has a different 0-point
+ // from |current_time| (which uses either the high-resolution timer or
+ // timeGetTime). Adjust it to be compatible.
+ //
+ // This offset will vary by up to ~16 msec because it depends on when exactly
+ // we sample the high-resolution clock. It would be more consistent to
+ // calculate one offset at the start of the program and apply it every time,
+ // but that consistency isn't needed for jank investigations and then we
+ // would have to adjust for clock drift.
+ const base::TimeDelta time_source_offset = current_time - current_tick_count;
+ time_stamp += time_source_offset;
+
+ ValidateEventTimeClock(&time_stamp);
+ return time_stamp;
+}
+
+base::TimeTicks EventLatencyTimeFromPerformanceCounter(UINT64 event_time) {
+ DCHECK(base::TimeTicks::IsHighResolution());
+ base::TimeTicks time_stamp = base::TimeTicks::FromQPCValue(event_time);
+ ValidateEventTimeClock(&time_stamp);
+ return time_stamp;
+}
+
gfx::Point EventLocationFromMSG(const MSG& native_event) {
// This code may use GetCursorPos() to get a mouse location. This may
// fail in certain situations (see
@@ -493,4 +550,8 @@ MouseWheelEvent MouseWheelEventFromMSG(const MSG& msg) {
changed_button_flags);
}
+void SetEventLatencyTickClockForTesting(const base::TickClock* clock) {
+ g_tick_count_clock = clock;
+}
+
} // namespace ui
diff --git a/chromium/ui/events/win/events_win_utils.h b/chromium/ui/events/win/events_win_utils.h
index 503fb5ee0e4..4fb1550639f 100644
--- a/chromium/ui/events/win/events_win_utils.h
+++ b/chromium/ui/events/win/events_win_utils.h
@@ -8,8 +8,6 @@
#include <stdint.h>
#include <windows.h>
-#include <memory>
-#include <string>
#include "build/build_config.h"
#include "ui/display/display.h"
@@ -27,6 +25,7 @@ class Vector2d;
} // namespace gfx
namespace base {
+class TickClock;
class TimeTicks;
}
@@ -36,70 +35,94 @@ namespace ui {
enum class DomCode;
// Get the EventType from a native event.
-EventType EventTypeFromMSG(const MSG& native_event);
+EVENTS_EXPORT EventType EventTypeFromMSG(const MSG& native_event);
// Get the EventFlags from a native event.
-int EventFlagsFromMSG(const MSG& native_event);
+EVENTS_EXPORT int EventFlagsFromMSG(const MSG& native_event);
// Get the timestamp from a native event.
// Note: This is not a pure function meaning that multiple applications on the
// same native event may return different values.
-base::TimeTicks EventTimeFromMSG(const MSG& native_event);
+EVENTS_EXPORT base::TimeTicks EventTimeFromMSG(const MSG& native_event);
+
+// Convert |event_time|, a count of milliseconds from the clock used by
+// ::GetTickCount(), to a value comparable to the base::TimeTicks clock.
+// |current_time| is a value returned in the recent past by EventTimeForNow,
+// which will be compared to the current result of ::GetTickCount() for
+// calibration.
+EVENTS_EXPORT base::TimeTicks EventLatencyTimeFromTickClock(
+ DWORD event_time,
+ base::TimeTicks current_time);
+
+// Convert |event_time|, a timestamp from the clock used by
+// ::QueryPerformanceCounter(), to a value comparable to the base::TimeTicks
+// clock. Must not be called if base::TimeTicks::IsHighResolution() returns
+// false.
+EVENTS_EXPORT base::TimeTicks EventLatencyTimeFromPerformanceCounter(
+ UINT64 event_time);
// Get the location from a native event. The coordinate system of the resultant
// |Point| has the origin at top-left of the "root window". The nature of
// this "root window" and how it maps to platform-specific drawing surfaces is
// defined in ui/aura/root_window.* and ui/aura/window_tree_host*.
-gfx::Point EventLocationFromMSG(const MSG& native_event);
+EVENTS_EXPORT gfx::Point EventLocationFromMSG(const MSG& native_event);
// Gets the location in native system coordinate space.
-gfx::Point EventSystemLocationFromMSG(const MSG& native_event);
+EVENTS_EXPORT gfx::Point EventSystemLocationFromMSG(const MSG& native_event);
// Returns the KeyboardCode from a native event.
-KeyboardCode KeyboardCodeFromMSG(const MSG& native_event);
+EVENTS_EXPORT KeyboardCode KeyboardCodeFromMSG(const MSG& native_event);
// Returns the DOM KeyboardEvent code (physical location in the
// keyboard) from a native event.
-DomCode CodeFromMSG(const MSG& native_event);
+EVENTS_EXPORT DomCode CodeFromMSG(const MSG& native_event);
// Returns true if the keyboard event is a character event rather than
// a keystroke event.
-bool IsCharFromMSG(const MSG& native_event);
+EVENTS_EXPORT bool IsCharFromMSG(const MSG& native_event);
// Returns the flags of the button that changed during a press/release.
-int GetChangedMouseButtonFlagsFromMSG(const MSG& native_event);
+EVENTS_EXPORT int GetChangedMouseButtonFlagsFromMSG(const MSG& native_event);
// Returns the detailed pointer information for mouse events.
-PointerDetails GetMousePointerDetailsFromMSG(const MSG& native_event);
+EVENTS_EXPORT PointerDetails
+GetMousePointerDetailsFromMSG(const MSG& native_event);
// Gets the mouse wheel offsets from a native event.
-gfx::Vector2d GetMouseWheelOffsetFromMSG(const MSG& native_event);
+EVENTS_EXPORT gfx::Vector2d GetMouseWheelOffsetFromMSG(const MSG& native_event);
// Returns a copy of |native_event|. Depending on the platform, this copy may
// need to be deleted with ReleaseCopiedMSGEvent().
-MSG CopyMSGEvent(const MSG& native_event);
+EVENTS_EXPORT MSG CopyMSGEvent(const MSG& native_event);
// Delete a |native_event| previously created by CopyMSGEvent().
-void ReleaseCopiedMSGEvent(const MSG& native_event);
+EVENTS_EXPORT void ReleaseCopiedMSGEvent(const MSG& native_event);
// Returns the detailed pointer information for touch events.
-PointerDetails GetTouchPointerDetailsFromMSG(const MSG& native_event);
+EVENTS_EXPORT PointerDetails
+GetTouchPointerDetailsFromMSG(const MSG& native_event);
// Clear the touch id from bookkeeping if it is a release/cancel event.
-void ClearTouchIdIfReleased(const MSG& native_event);
+EVENTS_EXPORT void ClearTouchIdIfReleased(const MSG& native_event);
// Gets the fling velocity from a native event. is_cancel is set to true if
// this was a tap down, intended to stop an ongoing fling.
-bool GetFlingData(const MSG& native_event,
- float* vx,
- float* vy,
- float* vx_ordinal,
- float* vy_ordinal,
- bool* is_cancel);
+EVENTS_EXPORT bool GetFlingData(const MSG& native_event,
+ float* vx,
+ float* vy,
+ float* vx_ordinal,
+ float* vy_ordinal,
+ bool* is_cancel);
// Returns whether this is a scroll event and optionally gets the amount to be
// scrolled.
-bool GetScrollOffsetsFromMSG(const MSG& native_event);
+EVENTS_EXPORT bool GetScrollOffsetsFromMSG(const MSG& native_event);
+
+// Makes EventLatencyTimeFromTickClock call the given |clock| to find the
+// current time ticks. If |clock| is nullptr, it will call ::GetTickCount(),
+// which is the default.
+EVENTS_EXPORT void SetEventLatencyTickClockForTesting(
+ const base::TickClock* clock);
} // namespace ui
diff --git a/chromium/ui/events/win/keyboard_hook_monitor.h b/chromium/ui/events/win/keyboard_hook_monitor.h
index 2e9bc9dc504..8fe3a50f5ed 100644
--- a/chromium/ui/events/win/keyboard_hook_monitor.h
+++ b/chromium/ui/events/win/keyboard_hook_monitor.h
@@ -5,7 +5,7 @@
#ifndef UI_EVENTS_WIN_KEYBOARD_HOOK_MONITOR_H_
#define UI_EVENTS_WIN_KEYBOARD_HOOK_MONITOR_H_
-#include "ui/events/events_export.h"
+#include "base/component_export.h"
namespace ui {
@@ -16,7 +16,7 @@ class KeyboardHookObserver;
// Note that the KeyboardHookMonitor impl is bound to the thread which creates
// it. In the browser process, this will be the UI thread. All methods should
// be called on that thread and all observer methods will be run on that thread.
-class EVENTS_EXPORT KeyboardHookMonitor {
+class COMPONENT_EXPORT(KEYBOARD_HOOK) KeyboardHookMonitor {
public:
static KeyboardHookMonitor* GetInstance();
diff --git a/chromium/ui/events/win/keyboard_hook_monitor_impl.h b/chromium/ui/events/win/keyboard_hook_monitor_impl.h
index 53b87b56235..c86424c096b 100644
--- a/chromium/ui/events/win/keyboard_hook_monitor_impl.h
+++ b/chromium/ui/events/win/keyboard_hook_monitor_impl.h
@@ -5,10 +5,10 @@
#ifndef UI_EVENTS_WIN_KEYBOARD_HOOK_MONITOR_IMPL_H_
#define UI_EVENTS_WIN_KEYBOARD_HOOK_MONITOR_IMPL_H_
+#include "base/component_export.h"
#include "base/no_destructor.h"
#include "base/observer_list_threadsafe.h"
#include "base/threading/thread_checker.h"
-#include "ui/events/events_export.h"
#include "ui/events/win/keyboard_hook_monitor.h"
#include "ui/events/win/keyboard_hook_observer.h"
@@ -19,7 +19,8 @@ namespace ui {
// Note that this class is bound to the thread which creates it. In the browser
// process, this will be the UI thread. All methods should be called on that
// thread and all observer methods will be run on that thread.
-class EVENTS_EXPORT KeyboardHookMonitorImpl : public KeyboardHookMonitor {
+class COMPONENT_EXPORT(KEYBOARD_HOOK) KeyboardHookMonitorImpl
+ : public KeyboardHookMonitor {
public:
static KeyboardHookMonitorImpl* GetInstance();
diff --git a/chromium/ui/events/win/keyboard_hook_observer.h b/chromium/ui/events/win/keyboard_hook_observer.h
index abdc3224574..449bcd0d387 100644
--- a/chromium/ui/events/win/keyboard_hook_observer.h
+++ b/chromium/ui/events/win/keyboard_hook_observer.h
@@ -5,13 +5,14 @@
#ifndef UI_EVENTS_WIN_KEYBOARD_HOOK_OBSERVER_H_
#define UI_EVENTS_WIN_KEYBOARD_HOOK_OBSERVER_H_
-#include "ui/events/events_export.h"
+#include "base/component_export.h"
namespace ui {
// Used in conjunction with the KeyboardHookMonitor class to receive
// notifications when a low-level keyboard hook is registered or unregistered.
-class EVENTS_EXPORT KeyboardHookObserver : public base::CheckedObserver {
+class COMPONENT_EXPORT(KEYBOARD_HOOK) KeyboardHookObserver
+ : public base::CheckedObserver {
public:
// Called when a low-level keyboard hook is registered.
virtual void OnHookRegistered() {}
diff --git a/chromium/ui/events/win/keyboard_hook_win_base.cc b/chromium/ui/events/win/keyboard_hook_win_base.cc
index 985460707f2..dbe1d97e1d4 100644
--- a/chromium/ui/events/win/keyboard_hook_win_base.cc
+++ b/chromium/ui/events/win/keyboard_hook_win_base.cc
@@ -9,7 +9,7 @@
namespace ui {
KeyboardHookWinBase::KeyboardHookWinBase(
- base::Optional<base::flat_set<DomCode>> dom_codes,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
KeyEventCallback callback,
bool enable_hook_registration)
: KeyboardHookBase(std::move(dom_codes), std::move(callback)),
diff --git a/chromium/ui/events/win/keyboard_hook_win_base.h b/chromium/ui/events/win/keyboard_hook_win_base.h
index cf55d1e5a31..f4ad2a15ccd 100644
--- a/chromium/ui/events/win/keyboard_hook_win_base.h
+++ b/chromium/ui/events/win/keyboard_hook_win_base.h
@@ -10,12 +10,12 @@
#include <windows.h>
#include "base/check.h"
+#include "base/component_export.h"
#include "base/containers/flat_set.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/event.h"
-#include "ui/events/events_export.h"
#include "ui/events/keyboard_hook_base.h"
#include "ui/events/keycodes/dom/dom_code.h"
@@ -25,9 +25,10 @@ namespace ui {
// it key event data. This method is used by both the low-level keyboard hook
// and by unit tests which simulate the hooked behavior w/o actually installing
// a hook (doing so would cause problems with test parallelization).
-class EVENTS_EXPORT KeyboardHookWinBase : public KeyboardHookBase {
+class COMPONENT_EXPORT(KEYBOARD_HOOK) KeyboardHookWinBase
+ : public KeyboardHookBase {
public:
- KeyboardHookWinBase(base::Optional<base::flat_set<DomCode>> dom_codes,
+ KeyboardHookWinBase(absl::optional<base::flat_set<DomCode>> dom_codes,
KeyEventCallback callback,
bool enable_hook_registration);
~KeyboardHookWinBase() override;
@@ -36,7 +37,7 @@ class EVENTS_EXPORT KeyboardHookWinBase : public KeyboardHookBase {
// low-level hook and captures modifier keys.
static std::unique_ptr<KeyboardHookWinBase>
CreateModifierKeyboardHookForTesting(
- base::Optional<base::flat_set<DomCode>> dom_codes,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
KeyEventCallback callback);
// Create a KeyboardHookWinBase instance which does not register a
diff --git a/chromium/ui/events/win/media_keyboard_hook_win.cc b/chromium/ui/events/win/media_keyboard_hook_win.cc
index 141ac572cd7..ea9200df0db 100644
--- a/chromium/ui/events/win/media_keyboard_hook_win.cc
+++ b/chromium/ui/events/win/media_keyboard_hook_win.cc
@@ -52,7 +52,7 @@ MediaKeyboardHookWinImpl::MediaKeyboardHookWinImpl(
KeyEventCallback callback,
bool enable_hook_registration)
: KeyboardHookWinBase(
- base::Optional<base::flat_set<DomCode>>(
+ absl::optional<base::flat_set<DomCode>>(
{DomCode::MEDIA_PLAY_PAUSE, DomCode::MEDIA_STOP,
DomCode::MEDIA_TRACK_NEXT, DomCode::MEDIA_TRACK_PREVIOUS}),
std::move(callback),
diff --git a/chromium/ui/events/win/modifier_keyboard_hook_win.cc b/chromium/ui/events/win/modifier_keyboard_hook_win.cc
index 7277f39ae43..e8b91e19b4d 100644
--- a/chromium/ui/events/win/modifier_keyboard_hook_win.cc
+++ b/chromium/ui/events/win/modifier_keyboard_hook_win.cc
@@ -8,7 +8,7 @@
#include "base/logging.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/dom/dom_code.h"
@@ -110,7 +110,7 @@ bool IsModifierKey(DWORD vk) {
class ModifierKeyboardHookWinImpl : public KeyboardHookWinBase {
public:
- ModifierKeyboardHookWinImpl(base::Optional<base::flat_set<DomCode>> dom_codes,
+ ModifierKeyboardHookWinImpl(absl::optional<base::flat_set<DomCode>> dom_codes,
KeyEventCallback callback,
bool enable_hook_registration);
~ModifierKeyboardHookWinImpl() override;
@@ -153,7 +153,7 @@ class ModifierKeyboardHookWinImpl : public KeyboardHookWinBase {
ModifierKeyboardHookWinImpl* ModifierKeyboardHookWinImpl::instance_ = nullptr;
ModifierKeyboardHookWinImpl::ModifierKeyboardHookWinImpl(
- base::Optional<base::flat_set<DomCode>> dom_codes,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
KeyEventCallback callback,
bool enable_hook_registration)
: KeyboardHookWinBase(std::move(dom_codes),
@@ -313,7 +313,7 @@ LRESULT CALLBACK ModifierKeyboardHookWinImpl::ProcessKeyEvent(int code,
// static
std::unique_ptr<KeyboardHook> KeyboardHook::CreateModifierKeyboardHook(
- base::Optional<base::flat_set<DomCode>> dom_codes,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
gfx::AcceleratedWidget accelerated_widget,
KeyEventCallback callback) {
std::unique_ptr<ModifierKeyboardHookWinImpl> keyboard_hook =
@@ -330,7 +330,7 @@ std::unique_ptr<KeyboardHook> KeyboardHook::CreateModifierKeyboardHook(
// static
std::unique_ptr<KeyboardHookWinBase>
KeyboardHookWinBase::CreateModifierKeyboardHookForTesting(
- base::Optional<base::flat_set<DomCode>> dom_codes,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
KeyEventCallback callback) {
return std::make_unique<ModifierKeyboardHookWinImpl>(
std::move(dom_codes), std::move(callback),
diff --git a/chromium/ui/events/win/modifier_keyboard_hook_win_unittest.cc b/chromium/ui/events/win/modifier_keyboard_hook_win_unittest.cc
index 71bd3f0c2ef..fdcb9084719 100644
--- a/chromium/ui/events/win/modifier_keyboard_hook_win_unittest.cc
+++ b/chromium/ui/events/win/modifier_keyboard_hook_win_unittest.cc
@@ -7,8 +7,8 @@
#include "base/bind.h"
#include "base/containers/flat_set.h"
-#include "base/optional.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/event.h"
#include "ui/events/keyboard_hook.h"
#include "ui/events/keycodes/dom/dom_code.h"
@@ -60,7 +60,7 @@ ModifierKeyboardHookWinTest::~ModifierKeyboardHookWinTest() = default;
void ModifierKeyboardHookWinTest::SetUp() {
keyboard_hook_ = KeyboardHookWinBase::CreateModifierKeyboardHookForTesting(
- base::Optional<base::flat_set<DomCode>>(),
+ absl::optional<base::flat_set<DomCode>>(),
base::BindRepeating(&ModifierKeyboardHookWinTest::HandleKeyPress,
base::Unretained(this)));
diff --git a/chromium/ui/events/x/events_x_utils.h b/chromium/ui/events/x/events_x_utils.h
index 2a6e48d0b8e..9888a89333e 100644
--- a/chromium/ui/events/x/events_x_utils.h
+++ b/chromium/ui/events/x/events_x_utils.h
@@ -7,7 +7,6 @@
#include <stdint.h>
-#include <memory>
#include "base/time/tick_clock.h"
#include "base/time/time.h"
diff --git a/chromium/ui/events/x/keyboard_hook_x11.cc b/chromium/ui/events/x/keyboard_hook_x11.cc
index 60f0348c2a5..641a940d040 100644
--- a/chromium/ui/events/x/keyboard_hook_x11.cc
+++ b/chromium/ui/events/x/keyboard_hook_x11.cc
@@ -4,124 +4,19 @@
#include "ui/events/x/keyboard_hook_x11.h"
-#include <memory>
-#include <utility>
-
-#include "base/callback.h"
-#include "base/check_op.h"
-#include "base/containers/flat_set.h"
-#include "base/stl_util.h"
-#include "ui/events/event.h"
-#include "ui/events/keycodes/dom/dom_code.h"
-#include "ui/events/keycodes/dom/keycode_converter.h"
-#include "ui/gfx/x/future.h"
-#include "ui/gfx/x/xproto.h"
-
namespace ui {
-namespace {
-
-static KeyboardHookX11* g_instance = nullptr;
-
-// XGrabKey essentially requires the modifier mask to explicitly be specified.
-// You can specify 'AnyModifier' however doing so means the call to XGrabKey
-// will fail if that key has been grabbed with any combination of modifiers.
-// A common practice is to call XGrabKey with each individual modifier mask to
-// avoid that problem.
-const x11::ModMask kModifierMasks[] = {
- {}, // No additional modifier.
- x11::ModMask::c_2, // Num lock
- x11::ModMask::Lock, // Caps lock
- x11::ModMask::c_5, // Scroll lock
- x11::ModMask::c_2 | x11::ModMask::Lock,
- x11::ModMask::c_2 | x11::ModMask::c_5,
- x11::ModMask::Lock | x11::ModMask::c_5,
- x11::ModMask::c_2 | x11::ModMask::Lock | x11::ModMask::c_5};
-
-// This is the set of keys to lock when the website requests that all keys be
-// locked.
-const DomCode kDomCodesForLockAllKeys[] = {
- DomCode::ESCAPE, DomCode::CONTEXT_MENU, DomCode::CONTROL_LEFT,
- DomCode::SHIFT_LEFT, DomCode::ALT_LEFT, DomCode::META_LEFT,
- DomCode::CONTROL_RIGHT, DomCode::SHIFT_RIGHT, DomCode::ALT_RIGHT,
- DomCode::META_RIGHT};
-
-} // namespace
-
KeyboardHookX11::KeyboardHookX11(
- base::Optional<base::flat_set<DomCode>> dom_codes,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
gfx::AcceleratedWidget accelerated_widget,
- KeyEventCallback callback)
+ KeyboardHookBase::KeyEventCallback callback)
: KeyboardHookBase(std::move(dom_codes), std::move(callback)),
- connection_(x11::Connection::Get()),
- x_window_(static_cast<x11::Window>(accelerated_widget)) {}
-
-KeyboardHookX11::~KeyboardHookX11() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ XKeyboardHook(accelerated_widget) {}
- DCHECK_EQ(g_instance, this);
- g_instance = nullptr;
-
- // Use UngrabKey for each key that has been grabbed. UngrabKeyboard
- // purportedly releases all keys when called and would not require the nested
- // loops, however in practice the keys are not actually released.
- for (int native_key_code : grabbed_keys_) {
- for (auto modifier : kModifierMasks) {
- connection_->UngrabKey(
- {static_cast<x11::KeyCode>(native_key_code), x_window_, modifier});
- }
- }
-}
+KeyboardHookX11::~KeyboardHookX11() = default;
bool KeyboardHookX11::RegisterHook() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
- // Only one instance of this class can be registered at a time.
- DCHECK(!g_instance);
- g_instance = this;
-
- if (dom_codes().has_value())
- CaptureSpecificKeys();
- else
- CaptureAllKeys();
-
- return true;
-}
-
-void KeyboardHookX11::CaptureAllKeys() {
- // We could have used the XGrabKeyboard API here instead of calling XGrabKeys
- // on a hard-coded set of shortcut keys. Calling XGrabKeyboard would make
- // this work much simpler, however it has side-effects which prevents its use.
- // An example side-effect is that it prevents the lock screen from starting as
- // the screensaver process also calls XGrabKeyboard but will receive an error
- // since it was already grabbed by the window with KeyboardLock.
- for (auto kDomCodesForLockAllKey : kDomCodesForLockAllKeys)
- CaptureKeyForDomCode(kDomCodesForLockAllKey);
-}
-
-void KeyboardHookX11::CaptureSpecificKeys() {
- for (DomCode dom_code : dom_codes().value()) {
- CaptureKeyForDomCode(dom_code);
- }
-}
-
-void KeyboardHookX11::CaptureKeyForDomCode(DomCode dom_code) {
- int native_key_code = KeycodeConverter::DomCodeToNativeKeycode(dom_code);
- if (native_key_code == KeycodeConverter::InvalidNativeKeycode())
- return;
-
- for (auto modifier : kModifierMasks) {
- connection_->GrabKey({
- .owner_events = false,
- .grab_window = x_window_,
- .modifiers = modifier,
- .key = static_cast<x11::KeyCode>(native_key_code),
- .pointer_mode = x11::GrabMode::Async,
- .keyboard_mode = x11::GrabMode::Async,
- });
- }
-
- grabbed_keys_.push_back(native_key_code);
+ return XKeyboardHook::RegisterHook(dom_codes());
}
} // namespace ui
diff --git a/chromium/ui/events/x/keyboard_hook_x11.h b/chromium/ui/events/x/keyboard_hook_x11.h
index b46384b20c3..580d4e6eb32 100644
--- a/chromium/ui/events/x/keyboard_hook_x11.h
+++ b/chromium/ui/events/x/keyboard_hook_x11.h
@@ -5,10 +5,9 @@
#ifndef UI_EVENTS_X_KEYBOARD_HOOK_X11_H_
#define UI_EVENTS_X_KEYBOARD_HOOK_X11_H_
-#include <vector>
-
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/base/x/x11_keyboard_hook.h"
#include "ui/events/keyboard_hook_base.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/x/connection.h"
@@ -16,32 +15,17 @@
namespace ui {
// A default implementation for the X11 platform.
-class KeyboardHookX11 : public KeyboardHookBase {
+class KeyboardHookX11 : public KeyboardHookBase, public XKeyboardHook {
public:
- KeyboardHookX11(base::Optional<base::flat_set<DomCode>> dom_codes,
+ KeyboardHookX11(absl::optional<base::flat_set<DomCode>> dom_codes,
gfx::AcceleratedWidget accelerated_widget,
- KeyEventCallback callback);
+ KeyboardHookBase::KeyEventCallback callback);
KeyboardHookX11(const KeyboardHookX11&) = delete;
KeyboardHookX11& operator=(const KeyboardHookX11&) = delete;
~KeyboardHookX11() override;
// KeyboardHookBase:
bool RegisterHook() override;
-
- private:
- // Helper methods for setting up key event capture.
- void CaptureAllKeys();
- void CaptureSpecificKeys();
- void CaptureKeyForDomCode(DomCode dom_code);
-
- THREAD_CHECKER(thread_checker_);
-
- // The x11 default connection and the owner's native window.
- x11::Connection* const connection_ = nullptr;
- const x11::Window x_window_ = x11::Window::None;
-
- // Tracks the keys that were grabbed.
- std::vector<int> grabbed_keys_;
};
} // namespace ui
diff --git a/chromium/ui/file_manager/BUILD.gn b/chromium/ui/file_manager/BUILD.gn
index ab2966fcb9c..bd472362f9c 100644
--- a/chromium/ui/file_manager/BUILD.gn
+++ b/chromium/ui/file_manager/BUILD.gn
@@ -39,7 +39,6 @@ group("closure_compile") {
"audio_player/js:closure_compile",
"file_manager/background/js:closure_compile",
"file_manager/common/js:closure_compile",
- "file_manager/cws_widget:closure_compile",
"file_manager/foreground/elements:closure_compile",
"file_manager/foreground/js:closure_compile",
"file_manager/foreground/js/metadata:closure_compile",
@@ -81,13 +80,20 @@ preprocess_if_expr("preprocess_static") {
out_manifest = "$target_gen_dir/manifest_preprocess_static.json"
in_files = [
+ # Audio Player:
"audio_player/js/main.m.js",
"audio_player/js/main_background.m.js",
+
+ # Files app:
"file_manager/background/js/main_background.m.js",
"file_manager/foreground/js/deferred_elements.m.js",
"file_manager/foreground/js/elements_importer.m.js",
"file_manager/foreground/js/main.m.js",
+
+ # Image Loader:
"image_loader/background.m.js",
+
+ # Video Player:
"video_player/js/main.m.js",
"video_player/js/main_background.m.js",
]
@@ -117,11 +123,11 @@ preprocess_if_expr("preprocess_generated") {
"audio_player/js/background.m.js",
"audio_player/js/audio_player.m.js",
"audio_player/js/metadata_worker.m.js",
- "audio_player/elements/audio_player.m.js",
- "audio_player/elements/track_info_panel.m.js",
- "audio_player/elements/track_list.m.js",
- "audio_player/elements/control_panel.m.js",
- "audio_player/elements/repeat_button.m.js",
+ "audio_player/elements/audio_player.js",
+ "audio_player/elements/track_info_panel.js",
+ "audio_player/elements/track_list.js",
+ "audio_player/elements/control_panel.js",
+ "audio_player/elements/repeat_button.js",
# Common:
"file_manager/common/js/app_util.m.js",
@@ -187,7 +193,6 @@ preprocess_if_expr("preprocess_generated") {
"file_manager/background/js/file_operation_util.m.js",
"file_manager/background/js/import_history.m.js",
"file_manager/background/js/launcher.m.js",
- "file_manager/background/js/launcher_search.m.js",
"file_manager/background/js/media_import_handler.m.js",
"file_manager/background/js/media_scanner.m.js",
"file_manager/background/js/metadata_proxy.m.js",
@@ -257,12 +262,11 @@ preprocess_if_expr("preprocess_generated") {
"file_manager/foreground/js/task_history.m.js",
"file_manager/foreground/js/thumbnail_loader.m.js",
"file_manager/foreground/js/toolbar_controller.m.js",
- "file_manager/foreground/js/web_store_utils.m.js",
"file_manager/foreground/js/webui_command_extender.m.js",
# Files app Elements:
"file_manager/foreground/elements/icons.m.js",
- "file_manager/foreground/elements/files_format_dialog.m.js",
+ "file_manager/foreground/elements/files_format_dialog.js",
"file_manager/foreground/elements/files_icon_button.m.js",
"file_manager/foreground/elements/files_message.m.js",
"file_manager/foreground/elements/files_metadata_box.m.js",
@@ -322,13 +326,6 @@ preprocess_if_expr("preprocess_generated") {
"file_manager/foreground/js/ui/table/table_list.m.js",
"file_manager/foreground/js/ui/table/table_splitter.m.js",
- # CWS:
- "file_manager/cws_widget/app_installer.m.js",
- "file_manager/cws_widget/cws_webview_client.m.js",
- "file_manager/cws_widget/cws_widget_container.m.js",
- "file_manager/cws_widget/cws_widget_container_error_dialog.m.js",
- "file_manager/cws_widget/cws_widget_container_platform_delegate.m.js",
-
# Image Loader:
"image_loader/cache.m.js",
"image_loader/image_loader.m.js",
@@ -373,16 +370,16 @@ preprocess_if_expr("preprocess_generated") {
]
deps = [
- "//ui/file_manager/audio_player/elements:elements",
+ "//ui/file_manager/audio_player/elements:web_components",
"//ui/file_manager/audio_player/js:modulize",
"//ui/file_manager/file_manager:gen_main_html",
"//ui/file_manager/file_manager/background/js:modulize",
"//ui/file_manager/file_manager/common/js:modulize",
- "//ui/file_manager/file_manager/cws_widget:modulize",
"//ui/file_manager/file_manager/externs:modulize",
"//ui/file_manager/file_manager/externs/background:modulize",
"//ui/file_manager/file_manager/foreground/elements:elements",
"//ui/file_manager/file_manager/foreground/elements:modulize",
+ "//ui/file_manager/file_manager/foreground/elements:web_components",
"//ui/file_manager/file_manager/foreground/js:modulize",
"//ui/file_manager/file_manager/foreground/js/metadata:modulize",
"//ui/file_manager/file_manager/foreground/js/ui:modulize",
diff --git a/chromium/ui/file_manager/audio_player/elements/BUILD.gn b/chromium/ui/file_manager/audio_player/elements/BUILD.gn
index 24316d2fe7c..41338901fac 100644
--- a/chromium/ui/file_manager/audio_player/elements/BUILD.gn
+++ b/chromium/ui/file_manager/audio_player/elements/BUILD.gn
@@ -3,33 +3,15 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
-import("//tools/polymer/polymer.gni")
+import("//tools/polymer/html_to_js.gni")
-group("elements") {
- public_deps = [
- "//ui/file_manager/audio_player/elements:audio_player_module",
- "//ui/file_manager/audio_player/elements:control_panel_module",
- "//ui/file_manager/audio_player/elements:repeat_button_module",
- "//ui/file_manager/audio_player/elements:track_info_panel_module",
- "//ui/file_manager/audio_player/elements:track_list_module",
- ]
-}
-
-group("closure_compile") {
- deps = [
- ":closure_compile_internal",
- ":closure_compile_jsmodules",
- ]
-}
-
-js_type_check("closure_compile_internal") {
- uses_legacy_modules = true
- deps = [
- ":audio_player",
- ":control_panel",
- ":repeat_button",
- ":track_info_panel",
- ":track_list",
+html_to_js("web_components") {
+ js_files = [
+ "audio_player.js",
+ "control_panel.js",
+ "track_info_panel.js",
+ "track_list.js",
+ "repeat_button.js",
]
}
@@ -38,152 +20,51 @@ js_library("audio_player") {
":control_panel",
":track_info_panel",
":track_list",
- ]
-}
-
-polymer_modulizer("audio_player") {
- js_file = "audio_player.js"
- html_file = "audio_player.html"
- html_type = "dom-module"
- preserve_url_scheme = true
-
- auto_imports = [
- "ui/file_manager/audio_player/elements/control_panel.html|AriaLabels",
- "ui/file_manager/audio_player/elements/track_list.html|TrackInfo",
- "third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-control-state.html|IronControlState",
- ]
-}
-
-js_library("audio_player.m") {
- sources = [
- "$root_gen_dir/ui/file_manager/audio_player/elements/audio_player.m.js",
- ]
- deps = [
- ":control_panel.m",
- ":track_info_panel.m",
- ":track_list.m",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
]
- extra_deps = [ ":audio_player_module" ]
}
js_library("control_panel") {
deps = [
":repeat_button",
- "//ui/webui/resources/cr_elements/cr_slider:cr_slider",
- "//ui/webui/resources/js:assert",
- ]
-}
-
-polymer_modulizer("control_panel") {
- js_file = "control_panel.js"
- html_file = "control_panel.html"
- html_type = "dom-module"
- preserve_url_scheme = true
-
- auto_imports = [ "ui/webui/resources/html/assert.html|assert" ]
-}
-
-js_library("control_panel.m") {
- sources = [
- "$root_gen_dir/ui/file_manager/audio_player/elements/control_panel.m.js",
- ]
- deps = [
- ":repeat_button.m",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/file_manager/file_manager/foreground/elements:files_icon_button.m",
"//ui/webui/resources/cr_elements/cr_slider:cr_slider.m",
"//ui/webui/resources/js:assert.m",
]
- extra_deps = [ ":control_panel_module" ]
-}
-
-js_library("repeat_button") {
- deps = [
- "//third_party/polymer/v1_0/components-chromium/iron-behaviors:iron-button-state-extracted",
- "//third_party/polymer/v1_0/components-chromium/iron-behaviors:iron-control-state-extracted",
- ]
}
js_library("track_info_panel") {
-}
-
-polymer_modulizer("track_info_panel") {
- js_file = "track_info_panel.js"
- html_file = "track_info_panel.html"
- html_type = "dom-module"
- preserve_url_scheme = true
-}
-
-js_library("track_info_panel.m") {
- sources = [
- "$root_gen_dir/ui/file_manager/audio_player/elements/track_info_panel.m.js",
- ]
deps = [
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/cr_elements/cr_button:cr_button.m",
]
- extra_deps = [ ":track_info_panel_module" ]
}
js_library("track_list") {
-}
-
-polymer_modulizer("track_list") {
- js_file = "track_list.js"
- html_file = "track_list.html"
- html_type = "dom-module"
- preserve_url_scheme = true
-}
-
-js_library("track_list.m") {
- sources =
- [ "$root_gen_dir/ui/file_manager/audio_player/elements/track_list.m.js" ]
deps = [
"//third_party/polymer/v3_0/components-chromium/paper-ripple:paper-ripple",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
]
- extra_deps = [ ":track_list_module" ]
-}
-
-polymer_modulizer("repeat_button") {
- js_file = "repeat_button.js"
- html_file = "repeat_button.html"
- html_type = "dom-module"
- preserve_url_scheme = true
-
- namespace_rewrites = [
- "Polymer.IronButtonState|IronButtonState",
- "Polymer.IronControlState|IronControlState",
- ]
-
- auto_imports = [
- "third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-button-state.html|IronButtonState",
- "third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-control-state.html|IronControlState",
- ]
}
-js_library("repeat_button.m") {
- sources = [
- "$root_gen_dir/ui/file_manager/audio_player/elements/repeat_button.m.js",
- ]
+js_library("repeat_button") {
deps = [
"//third_party/polymer/v3_0/components-chromium/iron-behaviors:iron-button-state",
"//third_party/polymer/v3_0/components-chromium/iron-behaviors:iron-control-state",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/file_manager/file_manager/foreground/elements:files_toggle_ripple.m",
]
- extra_deps = [ ":repeat_button_module" ]
}
-js_type_check("closure_compile_jsmodules") {
+js_type_check("closure_compile") {
is_polymer3 = true
closure_flags = default_closure_args + [ "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=../../ui/file_manager/file_manager/\"" ]
deps = [
- ":audio_player.m",
- ":control_panel.m",
- ":repeat_button.m",
- ":track_info_panel.m",
- ":track_list.m",
+ ":audio_player",
+ ":control_panel",
+ ":repeat_button",
+ ":track_info_panel",
+ ":track_list",
]
}
diff --git a/chromium/ui/file_manager/audio_player/js/BUILD.gn b/chromium/ui/file_manager/audio_player/js/BUILD.gn
index 1f293830555..62751992007 100644
--- a/chromium/ui/file_manager/audio_player/js/BUILD.gn
+++ b/chromium/ui/file_manager/audio_player/js/BUILD.gn
@@ -10,22 +10,10 @@ group("closure_compile") {
testonly = true
deps = [
":closure_compile_jsmodules",
- ":closure_compile_legacy",
":closure_compile_polymer",
]
}
-js_type_check("closure_compile_legacy") {
- uses_legacy_modules = true
- deps = [
- ":audio_player",
- ":background",
- ":closure_compile_externs",
- ":error_util",
- ":metadata_worker",
- ]
-}
-
js_type_check("closure_compile_jsmodules") {
deps = [
":background.m",
@@ -76,7 +64,7 @@ js_library("audio_player.m") {
[ "$root_gen_dir/ui/file_manager/audio_player/js/audio_player.m.js" ]
deps = [
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
- "//ui/file_manager/audio_player/elements:audio_player.m",
+ "//ui/file_manager/audio_player/elements:audio_player",
"//ui/file_manager/file_manager/common/js:app_util.m",
"//ui/file_manager/file_manager/common/js:async_util.m",
"//ui/file_manager/file_manager/common/js:filtered_volume_manager.m",
@@ -178,6 +166,8 @@ js_modulizer("modulize") {
"Polymer.CaseMap.dashToCamelCase|dashToCamelCase",
]
+
+ preserve_offsets = [ "True" ]
}
preprocess_folder =
diff --git a/chromium/ui/file_manager/file_manager/BUILD.gn b/chromium/ui/file_manager/file_manager/BUILD.gn
index 88000807f62..d2e3a596076 100644
--- a/chromium/ui/file_manager/file_manager/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/BUILD.gn
@@ -43,7 +43,6 @@ generate_grd("build_static_grdp") {
input_files = [
# CSS:
- "cws_widget/cws_widget_container.css",
"foreground/css/combobutton.css",
"foreground/css/common.css",
"foreground/css/file_manager.css",
diff --git a/chromium/ui/file_manager/file_manager/background/js/BUILD.gn b/chromium/ui/file_manager/file_manager/background/js/BUILD.gn
index d1328dc499b..c6ef5950a31 100644
--- a/chromium/ui/file_manager/file_manager/background/js/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/background/js/BUILD.gn
@@ -54,7 +54,6 @@ js_type_check("closure_compile_module") {
":file_operation_util",
":import_history",
":launcher",
- ":launcher_search",
":media_import_handler",
":media_scanner",
":metadata_proxy",
@@ -87,7 +86,6 @@ js_type_check("closure_compile_jsmodules") {
":file_operation_util.m",
":import_history.m",
":launcher.m",
- ":launcher_search.m",
":media_import_handler.m",
":media_scanner.m",
":metadata_proxy.m",
@@ -163,7 +161,6 @@ js_library("closure_compile_externs") {
"//ui/file_manager/file_manager/externs/background_window.js",
"//ui/file_manager/file_manager/externs/css_rule.js",
"//ui/file_manager/file_manager/externs/drive_dialog_controller.js",
- "//ui/file_manager/file_manager/externs/launcher_search_provider.js",
"//ui/file_manager/file_manager/externs/platform.js",
"//ui/file_manager/file_manager/externs/progress_center_panel.js",
"//ui/file_manager/file_manager/externs/background/task_queue.js",
@@ -216,7 +213,6 @@ js_library("background") {
":file_operation_manager",
":import_history",
":launcher",
- ":launcher_search",
":media_import_handler",
":mount_metrics",
":progress_center",
@@ -243,7 +239,6 @@ js_library("background.m") {
":file_operation_util.m",
":import_history.m",
":launcher.m",
- ":launcher_search.m",
":media_import_handler.m",
":media_scanner.m",
":mount_metrics.m",
@@ -763,30 +758,6 @@ js_library("launcher.m") {
extra_deps = [ ":modulize" ]
}
-js_library("launcher_search") {
- deps = [
- ":launcher",
- ":volume_manager_factory",
- "//ui/file_manager/file_manager/common/js:file_type",
- "//ui/file_manager/file_manager/common/js:util",
- ]
-}
-
-js_library("launcher_search.m") {
- sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/launcher_search.m.js" ]
- deps = [
- ":launcher.m",
- ":volume_manager_factory.m",
- "//ui/file_manager/file_manager/common/js:file_type.m",
- "//ui/file_manager/file_manager/common/js:util.m",
- ]
-
- externs_list =
- [ "//ui/file_manager/file_manager/externs/launcher_search_provider.js" ]
-
- extra_deps = [ ":modulize" ]
-}
-
js_library("media_import_handler") {
deps = [
":drive_sync_handler",
@@ -1366,11 +1337,12 @@ js_modulizer("modulize") {
"progress_center.js",
"device_handler.js",
"launcher.js",
- "launcher_search.js",
"background.js",
]
namespace_rewrites = cr_namespace_rewrites
+
+ preserve_offsets = [ "True" ]
}
preprocess_folder =
diff --git a/chromium/ui/file_manager/file_manager/common/js/BUILD.gn b/chromium/ui/file_manager/file_manager/common/js/BUILD.gn
index a5f6cd92b4f..022c67cae4a 100644
--- a/chromium/ui/file_manager/file_manager/common/js/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/common/js/BUILD.gn
@@ -650,4 +650,6 @@ js_modulizer("modulize") {
]
namespace_rewrites = cr_namespace_rewrites
+
+ preserve_offsets = [ "True" ]
}
diff --git a/chromium/ui/file_manager/file_manager/cws_widget/BUILD.gn b/chromium/ui/file_manager/file_manager/cws_widget/BUILD.gn
deleted file mode 100644
index 53c334d5939..00000000000
--- a/chromium/ui/file_manager/file_manager/cws_widget/BUILD.gn
+++ /dev/null
@@ -1,134 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-import("//ui/webui/resources/js/cr.gni")
-import("//ui/webui/resources/tools/js_modulizer.gni")
-
-group("closure_compile") {
- testonly = true
- deps = [
- ":closure_compile_jsmodules",
- ":closure_compile_module",
- ]
-}
-
-js_type_check("closure_compile_jsmodules") {
- deps = [
- ":app_installer.m",
- ":cws_webview_client.m",
- ":cws_widget_container.m",
- ":cws_widget_container_error_dialog.m",
- ":cws_widget_container_platform_delegate.m",
- ]
-}
-
-js_type_check("closure_compile_module") {
- uses_legacy_modules = true
- deps = [
- ":app_installer",
- ":cws_webview_client",
- ":cws_widget_container",
- ":cws_widget_container_error_dialog",
- ":cws_widget_container_platform_delegate",
- ]
-}
-
-js_library("app_installer") {
- deps = [ ":cws_widget_container_platform_delegate" ]
-}
-
-js_library("app_installer.m") {
- sources = [
- "$root_gen_dir/ui/file_manager/file_manager/cws_widget/app_installer.m.js",
- ]
- deps = [ ":cws_widget_container_platform_delegate.m" ]
-
- extra_deps = [ ":modulize" ]
-}
-
-js_library("cws_widget_container") {
- deps = [
- ":app_installer",
- ":cws_webview_client",
- ":cws_widget_container_error_dialog",
- ]
-}
-
-js_library("cws_widget_container.m") {
- sources = [ "$root_gen_dir/ui/file_manager/file_manager/cws_widget/cws_widget_container.m.js" ]
- deps = [
- ":app_installer.m",
- ":cws_webview_client.m",
- ":cws_widget_container_error_dialog.m",
- ":cws_widget_container_platform_delegate.m",
- "//ui/webui/resources/js:assert.m",
- ]
- externs_list = [ "$externs_path/webview_tag.js" ]
-
- extra_deps = [ ":modulize" ]
-}
-
-js_library("cws_widget_container_error_dialog") {
- deps = [
- "../common/js:util",
- "//ui/webui/resources/js/cr/ui:dialogs",
- ]
-}
-
-js_library("cws_widget_container_error_dialog.m") {
- sources = [ "$root_gen_dir/ui/file_manager/file_manager/cws_widget/cws_widget_container_error_dialog.m.js" ]
-
- deps = [
- "../common/js:util.m",
- "//ui/webui/resources/js/cr/ui:dialogs.m",
- ]
-
- extra_deps = [ ":modulize" ]
-}
-
-js_library("cws_widget_container_platform_delegate") {
-}
-
-js_library("cws_widget_container_platform_delegate.m") {
- sources = [ "$root_gen_dir/ui/file_manager/file_manager/cws_widget/cws_widget_container_platform_delegate.m.js" ]
-
- extra_deps = [ ":modulize" ]
-}
-
-js_library("cws_webview_client") {
- deps = [
- ":cws_widget_container_platform_delegate",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js/cr:event_target",
- ]
- externs_list = [
- "$externs_path/chrome_extensions.js",
- "$externs_path/webview_tag.js",
- ]
-}
-
-js_library("cws_webview_client.m") {
- sources = [ "$root_gen_dir/ui/file_manager/file_manager/cws_widget/cws_webview_client.m.js" ]
- deps = [
- ":cws_widget_container_platform_delegate.m",
- "//ui/webui/resources/js:cr.m",
- "//ui/webui/resources/js/cr:event_target.m",
- ]
- externs_list = [ "$externs_path/webview_tag.js" ]
-
- extra_deps = [ ":modulize" ]
-}
-
-js_modulizer("modulize") {
- input_files = [
- "cws_widget_container_error_dialog.js",
- "cws_widget_container.js",
- "cws_webview_client.js",
- "app_installer.js",
- "cws_widget_container_platform_delegate.js",
- ]
-
- namespace_rewrites = cr_namespace_rewrites
-}
diff --git a/chromium/ui/file_manager/file_manager/externs/BUILD.gn b/chromium/ui/file_manager/file_manager/externs/BUILD.gn
index 010dd7268f9..d5c1fe6e318 100644
--- a/chromium/ui/file_manager/file_manager/externs/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/externs/BUILD.gn
@@ -190,4 +190,6 @@ js_modulizer("modulize") {
"volume_info_list.js",
"volume_manager.js",
]
+
+ preserve_offsets = [ "True" ]
}
diff --git a/chromium/ui/file_manager/file_manager/externs/background/BUILD.gn b/chromium/ui/file_manager/file_manager/externs/background/BUILD.gn
index 48f665011c6..6666df13407 100644
--- a/chromium/ui/file_manager/file_manager/externs/background/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/externs/background/BUILD.gn
@@ -144,4 +144,6 @@ js_modulizer("modulize") {
"progress_center.js",
"task_queue.js",
]
+
+ preserve_offsets = [ "True" ]
}
diff --git a/chromium/ui/file_manager/file_manager/foreground/elements/BUILD.gn b/chromium/ui/file_manager/file_manager/foreground/elements/BUILD.gn
index ba36c51a64d..c43eef6f1cf 100644
--- a/chromium/ui/file_manager/file_manager/foreground/elements/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/foreground/elements/BUILD.gn
@@ -4,6 +4,7 @@
import("//third_party/closure_compiler/compile_js.gni")
import("//third_party/closure_compiler/js_unit_tests.gni")
+import("//tools/polymer/html_to_js.gni")
import("//tools/polymer/polymer.gni")
import("//ui/file_manager/base/gn/js_test_gen_html.gni")
import("//ui/webui/resources/tools/js_modulizer.gni")
@@ -13,7 +14,6 @@ visibility = [ "//ui/file_manager/file_manager/foreground/*" ]
group("elements") {
visibility += [ "//ui/file_manager/*" ]
public_deps = [
- "//ui/file_manager/file_manager/foreground/elements:files_format_dialog_module",
"//ui/file_manager/file_manager/foreground/elements:files_icon_button_module",
"//ui/file_manager/file_manager/foreground/elements:files_metadata_box_module",
"//ui/file_manager/file_manager/foreground/elements:files_metadata_entry_module",
@@ -32,40 +32,19 @@ group("closure_compile") {
testonly = true
visibility += [ "//ui/file_manager:closure_compile" ]
deps = [
- ":closure_compile_internal",
":closure_compile_jsmodules",
":js_test_gen_html_modules_type_check_auto",
]
}
-js_type_check("closure_compile_internal") {
- uses_legacy_modules = true
- deps = [
- ":files_format_dialog",
- ":files_icon_button",
- ":files_message",
- ":files_metadata_box",
- ":files_metadata_entry",
- ":files_password_dialog",
- ":files_quick_view",
- ":files_ripple",
- ":files_safe_media",
- ":files_safe_media_webview_content",
- ":files_spinner",
- ":files_toast",
- ":files_toggle_ripple",
- ":files_tooltip",
- ":xf_button",
- ":xf_circular_progress",
- ":xf_display_panel",
- ":xf_panel_item",
- ]
-}
-
js_type_check("closure_compile_jsmodules") {
is_polymer3 = true
+ closure_flags = default_closure_args + [
+ "js_module_root=gen/ui/file_manager/",
+ "js_module_root=../../ui/file_manager/",
+ ]
deps = [
- ":files_format_dialog.m",
+ ":files_format_dialog",
":files_icon_button.m",
":files_message.m",
":files_metadata_box.m",
@@ -85,33 +64,12 @@ js_type_check("closure_compile_jsmodules") {
]
}
-js_library("files_format_dialog") {
- deps = [
- "//ui/file_manager/file_manager/common/js:util",
- "//ui/webui/resources/cr_elements/cr_button:cr_button",
- "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
- "//ui/webui/resources/cr_elements/cr_input:cr_input",
- "//ui/webui/resources/js:i18n_behavior",
- ]
-}
-
-polymer_modulizer("files_format_dialog") {
- js_file = "files_format_dialog.js"
- html_file = "files_format_dialog.html"
- html_type = "dom-module"
- preserve_url_scheme = true
-
- auto_imports = [
- "ui/file_manager/file_manager/common/js/util.html|util",
- "ui/file_manager/file_manager/common/js/files_app_entry_types.html|EntryList,VolumeEntry",
- "ui/file_manager/file_manager/common/js/volume_manager_types.html|VolumeManagerCommon",
- "ui/file_manager/file_manager/externs/volume_info.html|VolumeInfo",
- ]
+html_to_js("web_components") {
+ js_files = [ "files_format_dialog.js" ]
}
-js_library("files_format_dialog.m") {
+js_library("files_format_dialog") {
visibility += [ "//ui/file_manager/audio_player/*" ]
- sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/elements/files_format_dialog.m.js" ]
deps = [
"//third_party/polymer/v3_0/components-chromium/iron-icon:iron-icon",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
@@ -124,7 +82,6 @@ js_library("files_format_dialog.m") {
"//ui/webui/resources/cr_elements/cr_input:cr_input.m",
"//ui/webui/resources/js:i18n_behavior.m",
]
- extra_deps = [ ":files_format_dialog_module" ]
}
js_library("files_icon_button") {
@@ -503,6 +460,8 @@ js_modulizer("modulize") {
"xf_panel_item.js",
"xf_display_panel.js",
]
+
+ preserve_offsets = [ "True" ]
}
js_test_gen_html("js_test_gen_html_modules") {
diff --git a/chromium/ui/file_manager/file_manager/foreground/js/BUILD.gn b/chromium/ui/file_manager/file_manager/foreground/js/BUILD.gn
index de71fe932a9..01b67562f1b 100644
--- a/chromium/ui/file_manager/file_manager/foreground/js/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -20,9 +20,7 @@ group("closure_compile") {
visibility += [ "//ui/file_manager:closure_compile" ]
deps = [
":closure_compile_jsmodules",
- ":closure_compile_module",
":js_test_gen_html_modules_type_check_auto",
- ":test_support_type_check",
]
}
@@ -30,6 +28,7 @@ js_type_check("closure_compile_jsmodules") {
is_polymer3 = true
closure_flags = default_closure_args + [
"js_module_root=gen/ui/file_manager/",
+ "js_module_root=../../ui/file_manager/",
"browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"",
"browser_resolver_prefix_replacements=\"chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/=./image_loader/\"",
]
@@ -95,117 +94,10 @@ js_type_check("closure_compile_jsmodules") {
":task_history.m",
":thumbnail_loader.m",
":toolbar_controller.m",
- ":web_store_utils.m",
":webui_command_extender.m",
]
}
-js_type_check("closure_compile_module") {
- uses_legacy_modules = true
- deps = [
- ":actions_controller",
- ":actions_model",
- ":android_app_list_model",
- ":app_state_controller",
- ":closure_compile_externs",
- ":column_visibility_controller",
- ":constants",
- ":crossover_search_utils",
- ":crostini_controller",
- ":dialog_action_controller",
- ":dialog_type",
- ":directory_contents",
- ":directory_model",
- ":directory_tree_naming_controller",
- ":drive_dialog_controller",
- ":drop_effect_and_label",
- ":elements_importer",
- ":empty_folder_controller",
- ":file_list_model",
- ":file_manager",
- ":file_manager_commands",
- ":file_selection",
- ":file_tasks",
- ":file_transfer_controller",
- ":file_type_filters_controller",
- ":file_watcher",
- ":folder_shortcuts_data_model",
- ":gear_menu_controller",
- ":import_controller",
- ":last_modified_controller",
- ":launch_param",
- ":list_thumbnail_loader",
- ":main",
- ":main_window_component",
- ":metadata_box_controller",
- ":metadata_update_controller",
- ":metrics_start",
- ":naming_controller",
- ":navigation_list_model",
- ":navigation_uma",
- ":path_component",
- ":providers_model",
- ":quick_view_controller",
- ":quick_view_model",
- ":quick_view_uma",
- ":scan_controller",
- ":search_controller",
- ":selection_menu_controller",
- ":sort_menu_controller",
- ":spinner_controller",
- ":task_controller",
- ":task_history",
- ":thumbnail_loader",
- ":toolbar_controller",
- ":web_store_utils",
- ":webui_command_extender",
- ]
-}
-
-js_library("closure_compile_externs") {
- sources = []
- externs_list = [
- "$externs_path/command_line_private.js",
- "$externs_path/metrics_private.js",
- "//ui/file_manager/file_manager/externs/background/crostini.js",
- "//ui/file_manager/file_manager/externs/background/drive_sync_handler.js",
- "//ui/file_manager/file_manager/externs/background/background_base.js",
- "//ui/file_manager/file_manager/externs/background/file_browser_background_full.js",
- "//ui/file_manager/file_manager/externs/background/file_operation_manager.js",
- "//ui/file_manager/file_manager/externs/background/media_import_handler.js",
- "//ui/file_manager/file_manager/externs/background/task_queue.js",
- "//ui/file_manager/file_manager/externs/background/duplicate_finder.js",
- "//ui/file_manager/file_manager/externs/background/media_scanner.js",
- "//ui/file_manager/file_manager/externs/background/progress_center.js",
- "//ui/file_manager/file_manager/externs/background_window.js",
- "//ui/file_manager/file_manager/externs/chrome_echo_private.js",
- "//ui/file_manager/file_manager/externs/chrome_webstore_widget_private.js",
- "//ui/file_manager/file_manager/externs/command_handler_deps.js",
- "//ui/file_manager/file_manager/externs/css_rule.js",
- "//ui/file_manager/file_manager/externs/directory_change_event.js",
- "//ui/file_manager/file_manager/externs/drive_dialog_controller.js",
- "//ui/file_manager/file_manager/externs/entries_changed_event.js",
- "//ui/file_manager/file_manager/externs/gallery_foreground.js",
- "//ui/file_manager/file_manager/externs/menu_item_update_event.js",
- "//ui/file_manager/file_manager/externs/paper_elements.js",
- "//ui/file_manager/file_manager/externs/platform.js",
- "//ui/file_manager/file_manager/externs/search_item.js",
- ]
-}
-
-js_type_check("test_support_type_check") {
- uses_legacy_modules = true
- testonly = true
- deps = [
- ":fake_android_app_list_model",
- ":mock_actions_model",
- ":mock_directory_model",
- ":mock_folder_shortcut_data_model",
- ":mock_navigation_list_model",
- ":mock_thumbnail_loader",
- ]
-}
-
js_library("actions_controller") {
deps = [
":actions_model",
@@ -737,7 +629,7 @@ js_library("elements_importer.m") {
js_library("deferred_elements.m") {
visibility += [ "//ui/file_manager:*" ]
deps = [
- "//ui/file_manager/file_manager/foreground/elements:files_format_dialog.m",
+ "//ui/file_manager/file_manager/foreground/elements:files_format_dialog",
"//ui/file_manager/file_manager/foreground/elements:files_message.m",
"//ui/file_manager/file_manager/foreground/elements:files_password_dialog.m",
"//ui/file_manager/file_manager/foreground/elements:files_ripple.m",
@@ -993,7 +885,7 @@ js_library("file_manager_commands.m") {
"//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m",
"//ui/file_manager/file_manager/externs:volume_info.m",
"//ui/file_manager/file_manager/externs:volume_manager.m",
- "//ui/file_manager/file_manager/foreground/elements:files_format_dialog.m",
+ "//ui/file_manager/file_manager/foreground/elements:files_format_dialog",
"//ui/webui/resources/js:assert.m",
"//ui/webui/resources/js/cr/ui:command.m",
"//ui/webui/resources/js/cr/ui:context_menu_handler.m",
@@ -1076,7 +968,6 @@ js_library("file_tasks.m") {
":file_transfer_controller.m",
":naming_controller.m",
":task_history.m",
- ":web_store_utils.m",
"metadata:metadata_model.m",
"ui:combobutton.m",
"ui:default_task_dialog.m",
@@ -1319,7 +1210,6 @@ js_library("holding_space_util") {
deps = [
"//ui/file_manager/file_manager/common/js:volume_manager_types",
"//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:load_time_data",
]
}
@@ -2055,17 +1945,6 @@ js_library("toolbar_controller.m") {
extra_deps = [ ":modulize" ]
}
-js_library("web_store_utils") {
- deps = [ ":constants" ]
-}
-
-js_library("web_store_utils.m") {
- sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/web_store_utils.m.js" ]
- deps = [ ":constants.m" ]
-
- extra_deps = [ ":modulize" ]
-}
-
js_library("webui_command_extender") {
deps = [
"//ui/webui/resources/js:cr",
@@ -2177,7 +2056,6 @@ js_modulizer("modulize") {
"task_history.js",
"thumbnail_loader.js",
"toolbar_controller.js",
- "web_store_utils.js",
"webui_command_extender.js",
]
@@ -2187,6 +2065,8 @@ js_modulizer("modulize") {
"cr.ui.ComboButton|ComboButton",
"cr.filebrowser.DefaultTaskDialog|DefaultTaskDialog",
]
+
+ preserve_offsets = [ "True" ]
}
preprocess_folder =
diff --git a/chromium/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn b/chromium/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn
index 70e8512424b..8489715f563 100644
--- a/chromium/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn
@@ -502,6 +502,7 @@ js_library("multi_metadata_provider") {
":external_metadata_provider",
":file_system_metadata_provider",
":metadata_provider",
+ "//ui/file_manager/file_manager/common/js:util",
"//ui/file_manager/file_manager/externs:volume_manager",
]
}
@@ -615,4 +616,6 @@ js_modulizer("modulize") {
]
namespace_rewrites = cr_namespace_rewrites
+
+ preserve_offsets = [ "True" ]
}
diff --git a/chromium/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn b/chromium/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
index d8662c3bc18..e5dff30b982 100644
--- a/chromium/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
@@ -15,7 +15,6 @@ group("closure_compile") {
visibility += [ "//ui/file_manager:closure_compile" ]
deps = [
":closure_compile_jsmodules",
- ":closure_compile_module",
":js_test_gen_html_modules_type_check_auto",
]
}
@@ -72,75 +71,6 @@ js_type_check("closure_compile_jsmodules") {
]
}
-js_type_check("closure_compile_module") {
- uses_legacy_modules = true
- deps = [
- ":action_model_ui",
- ":actions_submenu",
- ":banners",
- ":breadcrumb",
- ":closure_compile_externs",
- ":combobutton",
- ":commandbutton",
- ":default_task_dialog",
- ":dialog_footer",
- ":directory_tree",
- ":drag_selector",
- ":empty_folder",
- ":file_grid",
- ":file_list_selection_model",
- ":file_manager_dialog_base",
- ":file_manager_ui",
- ":file_metadata_formatter",
- ":file_table",
- ":file_table_list",
- ":file_tap_handler",
- ":files_alert_dialog",
- ":files_confirm_dialog",
- ":files_menu",
- ":gear_menu",
- ":import_crostini_image_dialog",
- ":install_linux_package_dialog",
- ":list_container",
- ":location_line",
- ":multi_menu",
- ":multi_menu_button",
- ":progress_center_panel",
- ":providers_menu",
- ":search_box",
- "table:table",
- "table:table_column",
- "table:table_column_model",
- "table:table_header",
- "table:table_list",
- "table:table_splitter",
- ]
-}
-
-js_library("closure_compile_externs") {
- sources = []
- externs_list = [
- "$externs_path/metrics_private.js",
- "//ui/file_manager/file_manager/externs/background/crostini.js",
- "//ui/file_manager/file_manager/externs/background/drive_sync_handler.js",
- "//ui/file_manager/file_manager/externs/background/background_base.js",
- "//ui/file_manager/file_manager/externs/background/file_operation_manager.js",
- "//ui/file_manager/file_manager/externs/background/import_history.js",
- "//ui/file_manager/file_manager/externs/background_window.js",
- "//ui/file_manager/file_manager/externs/chrome_echo_private.js",
- "//ui/file_manager/file_manager/externs/chrome_webstore_widget_private.js",
- "//ui/file_manager/file_manager/externs/css_rule.js",
- "//ui/file_manager/file_manager/externs/drag_target.js",
- "//ui/file_manager/file_manager/externs/drive_dialog_controller.js",
- "//ui/file_manager/file_manager/externs/entries_changed_event.js",
- "//ui/file_manager/file_manager/externs/gallery_foreground.js",
- "//ui/file_manager/file_manager/externs/menu_item_update_event.js",
- "//ui/file_manager/file_manager/externs/paper_elements.js",
- "//ui/file_manager/file_manager/externs/platform.js",
- "//ui/file_manager/file_manager/externs/search_item.js",
- ]
-}
-
js_library("a11y_announce") {
}
@@ -1199,4 +1129,6 @@ js_modulizer("modulize") {
"cr.filebrowser.InstallLinuxPackageDialog|InstallLinuxPackageDialog",
"cr.filebrowser.ImportCrostiniImageDialog|ImportCrostiniImageDialog",
]
+
+ preserve_offsets = [ "True" ]
}
diff --git a/chromium/ui/file_manager/file_manager/foreground/js/ui/table/BUILD.gn b/chromium/ui/file_manager/file_manager/foreground/js/ui/table/BUILD.gn
index 062336829e7..0ebcc5ce9e9 100644
--- a/chromium/ui/file_manager/file_manager/foreground/js/ui/table/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/foreground/js/ui/table/BUILD.gn
@@ -134,4 +134,6 @@ js_modulizer("modulize") {
]
namespace_rewrites = cr_namespace_rewrites + [ "cr.ui.table.Table|Table" ]
+
+ preserve_offsets = [ "True" ]
}
diff --git a/chromium/ui/file_manager/image_loader/BUILD.gn b/chromium/ui/file_manager/image_loader/BUILD.gn
index fe3ac7da91b..2b8daaf645e 100644
--- a/chromium/ui/file_manager/image_loader/BUILD.gn
+++ b/chromium/ui/file_manager/image_loader/BUILD.gn
@@ -265,6 +265,8 @@ js_modulizer("modulize") {
"image_request_task.js",
"image_loader.js",
]
+
+ preserve_offsets = [ "True" ]
}
preprocess_folder =
diff --git a/chromium/ui/file_manager/integration_tests/file_manager/BUILD.gn b/chromium/ui/file_manager/integration_tests/file_manager/BUILD.gn
index 7f963c8a048..958ac37b367 100644
--- a/chromium/ui/file_manager/integration_tests/file_manager/BUILD.gn
+++ b/chromium/ui/file_manager/integration_tests/file_manager/BUILD.gn
@@ -28,12 +28,11 @@ js_type_check("closure_compile") {
":grid_view",
":install_linux_package_dialog",
":keyboard_operations",
- ":launcher_search",
":metadata",
":metrics",
":my_files",
":open_audio_files",
- ":open_image_files",
+ ":open_image_media_app",
":open_video_files",
":providers",
":quick_view",
@@ -157,11 +156,6 @@ js_library("keyboard_operations") {
deps = []
}
-js_library("launcher_search") {
- testonly = true
- deps = []
-}
-
js_library("metadata") {
testonly = true
deps = []
@@ -182,7 +176,7 @@ js_library("open_audio_files") {
deps = []
}
-js_library("open_image_files") {
+js_library("open_image_media_app") {
testonly = true
deps = []
}
diff --git a/chromium/ui/file_manager/video_player/js/BUILD.gn b/chromium/ui/file_manager/video_player/js/BUILD.gn
index 179d4d920ec..a21139411b4 100644
--- a/chromium/ui/file_manager/video_player/js/BUILD.gn
+++ b/chromium/ui/file_manager/video_player/js/BUILD.gn
@@ -218,6 +218,8 @@ js_modulizer("modulize") {
"background.js",
"video_player.js",
]
+
+ preserve_offsets = [ "True" ]
}
preprocess_folder =
diff --git a/chromium/ui/gfx/BUILD.gn b/chromium/ui/gfx/BUILD.gn
index 181c0c58918..ffd44dc7946 100644
--- a/chromium/ui/gfx/BUILD.gn
+++ b/chromium/ui/gfx/BUILD.gn
@@ -148,6 +148,9 @@ component("gfx") {
"ui_gfx_exports.cc",
"utf16_indexing.cc",
"utf16_indexing.h",
+ "vector_icon_types.h",
+ "vector_icon_utils.cc",
+ "vector_icon_utils.h",
"video_types.h",
"vsync_provider.cc",
"vsync_provider.h",
@@ -377,7 +380,6 @@ component("gfx") {
"render_text_harfbuzz.cc",
"render_text_harfbuzz.h",
"text_utils_skia.cc",
- "vector_icon_types.h",
]
}
@@ -437,6 +439,8 @@ component("color_space") {
"color_space_export.h",
"display_color_spaces.cc",
"display_color_spaces.h",
+ "hdr_static_metadata.cc",
+ "hdr_static_metadata.h",
"icc_profile.cc",
"icc_profile.h",
"skia_color_space_util.cc",
@@ -744,6 +748,7 @@ test("gfx_unittests") {
"platform_font_mac_unittest.mm",
"range/range_mac_unittest.mm",
]
+ frameworks = [ "IOSurface.framework" ]
}
if (is_win) {
sources += [ "font_fallback_win_unittest.cc" ]
diff --git a/chromium/ui/gfx/android/android_surface_control_compat.cc b/chromium/ui/gfx/android/android_surface_control_compat.cc
index fea4bd261ed..d840a0487a8 100644
--- a/chromium/ui/gfx/android/android_surface_control_compat.cc
+++ b/chromium/ui/gfx/android/android_surface_control_compat.cc
@@ -10,6 +10,7 @@
#include "base/android/build_info.h"
#include "base/atomic_sequence_num.h"
#include "base/bind.h"
+#include "base/bind_post_task.h"
#include "base/debug/crash_logging.h"
#include "base/hash/md5_constexpr.h"
#include "base/logging.h"
@@ -24,6 +25,8 @@ extern "C" {
typedef struct ASurfaceTransactionStats ASurfaceTransactionStats;
typedef void (*ASurfaceTransaction_OnComplete)(void* context,
ASurfaceTransactionStats* stats);
+typedef void (*ASurfaceTransaction_OnCommit)(void* context,
+ ASurfaceTransactionStats* stats);
// ASurface
using pASurfaceControl_createFromWindow =
@@ -51,6 +54,9 @@ using pASurfaceTransaction_delete = void (*)(ASurfaceTransaction*);
using pASurfaceTransaction_apply = int64_t (*)(ASurfaceTransaction*);
using pASurfaceTransaction_setOnComplete =
void (*)(ASurfaceTransaction*, void* ctx, ASurfaceTransaction_OnComplete);
+using pASurfaceTransaction_setOnCommit = void (*)(ASurfaceTransaction*,
+ void* ctx,
+ ASurfaceTransaction_OnCommit);
using pASurfaceTransaction_setVisibility = void (*)(ASurfaceTransaction*,
ASurfaceControl*,
int8_t visibility);
@@ -147,6 +153,7 @@ struct SurfaceControlMethods {
LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_delete);
LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_apply);
LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setOnComplete);
+ LOAD_FUNCTION_MAYBE(main_dl_handle, ASurfaceTransaction_setOnCommit);
LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_reparent);
LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setVisibility);
LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setZOrder);
@@ -179,6 +186,7 @@ struct SurfaceControlMethods {
pASurfaceTransaction_delete ASurfaceTransaction_deleteFn;
pASurfaceTransaction_apply ASurfaceTransaction_applyFn;
pASurfaceTransaction_setOnComplete ASurfaceTransaction_setOnCompleteFn;
+ pASurfaceTransaction_setOnCommit ASurfaceTransaction_setOnCommitFn;
pASurfaceTransaction_reparent ASurfaceTransaction_reparentFn;
pASurfaceTransaction_setVisibility ASurfaceTransaction_setVisibilityFn;
pASurfaceTransaction_setZOrder ASurfaceTransaction_setZOrderFn;
@@ -283,8 +291,8 @@ SurfaceControl::TransactionStats ToTransactionStats(
struct TransactionAckCtx {
int id = 0;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner;
SurfaceControl::Transaction::OnCompleteCb callback;
+ SurfaceControl::Transaction::OnCommitCb latch_callback;
};
uint64_t GetTraceIdForTransaction(int transaction_id) {
@@ -294,7 +302,7 @@ uint64_t GetTraceIdForTransaction(int transaction_id) {
}
// Note that the framework API states that this callback can be dispatched on
-// any thread (in practice it should be the binder thread).
+// any thread (in practice it should be a binder thread).
void OnTransactionCompletedOnAnyThread(void* context,
ASurfaceTransactionStats* stats) {
auto* ack_ctx = static_cast<TransactionAckCtx*>(context);
@@ -305,14 +313,19 @@ void OnTransactionCompletedOnAnyThread(void* context,
"toplevel.flow", "gfx::SurfaceControlTransaction completed",
GetTraceIdForTransaction(ack_ctx->id), TRACE_EVENT_FLAG_FLOW_IN);
- if (ack_ctx->task_runner) {
- ack_ctx->task_runner->PostTask(
- FROM_HERE, base::BindOnce(std::move(ack_ctx->callback),
- std::move(transaction_stats)));
- } else {
- std::move(ack_ctx->callback).Run(std::move(transaction_stats));
- }
+ std::move(ack_ctx->callback).Run(std::move(transaction_stats));
+ delete ack_ctx;
+}
+// Note that the framework API states that this callback can be dispatched on
+// any thread (in practice it should be a binder thread).
+void OnTransactiOnCommittedOnAnyThread(void* context,
+ ASurfaceTransactionStats* stats) {
+ auto* ack_ctx = static_cast<TransactionAckCtx*>(context);
+ TRACE_EVENT_INSTANT0("gpu,benchmark", "SurfaceControlTransaction committed",
+ TRACE_EVENT_SCOPE_THREAD);
+
+ std::move(ack_ctx->latch_callback).Run();
delete ack_ctx;
}
@@ -355,29 +368,46 @@ bool SurfaceControl::SupportsSetFrameRate() {
nullptr;
}
+bool SurfaceControl::SupportsOnCommit() {
+ return IsSupported() &&
+ SurfaceControlMethods::Get().ASurfaceTransaction_setOnCommitFn !=
+ nullptr;
+}
+
void SurfaceControl::ApplyTransaction(ASurfaceTransaction* transaction) {
SurfaceControlMethods::Get().ASurfaceTransaction_applyFn(transaction);
}
+scoped_refptr<SurfaceControl::Surface> SurfaceControl::Surface::WrapUnowned(
+ ASurfaceControl* surface) {
+ scoped_refptr<SurfaceControl::Surface> result =
+ base::MakeRefCounted<SurfaceControl::Surface>();
+ result->surface_ = surface;
+ return result;
+}
+
SurfaceControl::Surface::Surface() = default;
SurfaceControl::Surface::Surface(const Surface& parent, const char* name) {
- surface_ = SurfaceControlMethods::Get().ASurfaceControl_createFn(
+ owned_surface_ = SurfaceControlMethods::Get().ASurfaceControl_createFn(
parent.surface(), name);
- if (!surface_)
+ if (!owned_surface_)
LOG(ERROR) << "Failed to create ASurfaceControl : " << name;
+ surface_ = owned_surface_;
}
SurfaceControl::Surface::Surface(ANativeWindow* parent, const char* name) {
- surface_ = SurfaceControlMethods::Get().ASurfaceControl_createFromWindowFn(
- parent, name);
- if (!surface_)
+ owned_surface_ =
+ SurfaceControlMethods::Get().ASurfaceControl_createFromWindowFn(parent,
+ name);
+ if (!owned_surface_)
LOG(ERROR) << "Failed to create ASurfaceControl : " << name;
+ surface_ = owned_surface_;
}
SurfaceControl::Surface::~Surface() {
- if (surface_)
- SurfaceControlMethods::Get().ASurfaceControl_releaseFn(surface_);
+ if (owned_surface_)
+ SurfaceControlMethods::Get().ASurfaceControl_releaseFn(owned_surface_);
}
SurfaceControl::SurfaceStats::SurfaceStats() = default;
@@ -407,7 +437,10 @@ SurfaceControl::Transaction::~Transaction() {
}
SurfaceControl::Transaction::Transaction(Transaction&& other)
- : id_(other.id_), transaction_(other.transaction_) {
+ : id_(other.id_),
+ transaction_(other.transaction_),
+ on_commit_cb_(std::move(other.on_commit_cb_)),
+ on_complete_cb_(std::move(other.on_complete_cb_)) {
other.transaction_ = nullptr;
other.id_ = 0;
}
@@ -419,6 +452,8 @@ SurfaceControl::Transaction& SurfaceControl::Transaction::operator=(
transaction_ = other.transaction_;
id_ = other.id_;
+ on_commit_cb_ = std::move(other.on_commit_cb_);
+ on_complete_cb_ = std::move(other.on_complete_cb_);
other.transaction_ = nullptr;
other.id_ = 0;
@@ -508,18 +543,39 @@ void SurfaceControl::Transaction::SetOnCompleteCb(
TRACE_EVENT_WITH_FLOW0(
"toplevel.flow", "gfx::SurfaceControl::Transaction::SetOnCompleteCb",
GetTraceIdForTransaction(id_), TRACE_EVENT_FLAG_FLOW_OUT);
- TransactionAckCtx* ack_ctx = new TransactionAckCtx;
- ack_ctx->callback = std::move(cb);
- ack_ctx->task_runner = std::move(task_runner);
- ack_ctx->id = id_;
- SurfaceControlMethods::Get().ASurfaceTransaction_setOnCompleteFn(
- transaction_, ack_ctx, &OnTransactionCompletedOnAnyThread);
+ DCHECK(!on_complete_cb_);
+ on_complete_cb_ = base::BindPostTask(std::move(task_runner), std::move(cb));
+}
+
+void SurfaceControl::Transaction::SetOnCommitCb(
+ OnCommitCb cb,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ DCHECK(!on_commit_cb_);
+ on_commit_cb_ = base::BindPostTask(std::move(task_runner), std::move(cb));
}
void SurfaceControl::Transaction::Apply() {
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("gpu,benchmark",
"SurfaceControlTransaction", id_);
+ if (on_commit_cb_) {
+ TransactionAckCtx* ack_ctx = new TransactionAckCtx;
+ ack_ctx->latch_callback = std::move(on_commit_cb_);
+ ack_ctx->id = id_;
+
+ SurfaceControlMethods::Get().ASurfaceTransaction_setOnCommitFn(
+ transaction_, ack_ctx, &OnTransactiOnCommittedOnAnyThread);
+ }
+
+ if (on_complete_cb_) {
+ TransactionAckCtx* ack_ctx = new TransactionAckCtx;
+ ack_ctx->callback = std::move(on_complete_cb_);
+ ack_ctx->id = id_;
+
+ SurfaceControlMethods::Get().ASurfaceTransaction_setOnCompleteFn(
+ transaction_, ack_ctx, &OnTransactionCompletedOnAnyThread);
+ }
+
SurfaceControlMethods::Get().ASurfaceTransaction_applyFn(transaction_);
}
diff --git a/chromium/ui/gfx/android/android_surface_control_compat.h b/chromium/ui/gfx/android/android_surface_control_compat.h
index 4dc22573195..e4d8fb52377 100644
--- a/chromium/ui/gfx/android/android_surface_control_compat.h
+++ b/chromium/ui/gfx/android/android_surface_control_compat.h
@@ -47,6 +47,9 @@ class GFX_EXPORT SurfaceControl {
// Returns true if tagging a surface with a frame rate value is supported.
static bool SupportsSetFrameRate();
+ // Returns true if OnCommit callback is supported.
+ static bool SupportsOnCommit();
+
// Applies transaction. Used to emulate webview functor interface, where we
// pass raw ASurfaceTransaction object. For use inside Chromium use
// Transaction class below instead.
@@ -54,6 +57,10 @@ class GFX_EXPORT SurfaceControl {
class GFX_EXPORT Surface : public base::RefCounted<Surface> {
public:
+ // Wraps ASurfaceControl, but doesn't transfer ownership. Will not release
+ // in dtor.
+ static scoped_refptr<Surface> WrapUnowned(ASurfaceControl* surface);
+
Surface();
Surface(const Surface& parent, const char* name);
Surface(ANativeWindow* parent, const char* name);
@@ -65,6 +72,7 @@ class GFX_EXPORT SurfaceControl {
~Surface();
ASurfaceControl* surface_ = nullptr;
+ ASurfaceControl* owned_surface_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(Surface);
};
@@ -134,11 +142,18 @@ class GFX_EXPORT SurfaceControl {
OnCompleteCb cb,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ using OnCommitCb = base::OnceClosure;
+ void SetOnCommitCb(OnCommitCb cb,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
void Apply();
+ ASurfaceTransaction* transaction() { return transaction_; }
private:
int id_;
ASurfaceTransaction* transaction_;
+ OnCommitCb on_commit_cb_;
+ OnCompleteCb on_complete_cb_;
DISALLOW_COPY_AND_ASSIGN(Transaction);
};
diff --git a/chromium/ui/gfx/animation/animation.cc b/chromium/ui/gfx/animation/animation.cc
index 1056018cffa..c07fb280929 100644
--- a/chromium/ui/gfx/animation/animation.cc
+++ b/chromium/ui/gfx/animation/animation.cc
@@ -22,7 +22,7 @@ Animation::RichAnimationRenderMode Animation::rich_animation_rendering_mode_ =
RichAnimationRenderMode::PLATFORM;
// static
-base::Optional<bool> Animation::prefers_reduced_motion_;
+absl::optional<bool> Animation::prefers_reduced_motion_;
Animation::Animation(base::TimeDelta timer_interval)
: timer_interval_(timer_interval),
diff --git a/chromium/ui/gfx/animation/animation.h b/chromium/ui/gfx/animation/animation.h
index 238be58a85c..a2225de11f3 100644
--- a/chromium/ui/gfx/animation/animation.h
+++ b/chromium/ui/gfx/animation/animation.h
@@ -8,8 +8,8 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/animation/animation_container_element.h"
#include "ui/gfx/animation/animation_export.h"
@@ -135,7 +135,7 @@ class ANIMATION_EXPORT Animation : public AnimationContainerElement {
// Obtaining the PrefersReducedMotion system setting can be expensive, so it
// is cached in this boolean.
- static base::Optional<bool> prefers_reduced_motion_;
+ static absl::optional<bool> prefers_reduced_motion_;
DISALLOW_COPY_AND_ASSIGN(Animation);
};
diff --git a/chromium/ui/gfx/animation/keyframe/animation_curve.h b/chromium/ui/gfx/animation/keyframe/animation_curve.h
index bffb4c727b4..e15f40311dd 100644
--- a/chromium/ui/gfx/animation/keyframe/animation_curve.h
+++ b/chromium/ui/gfx/animation/keyframe/animation_curve.h
@@ -81,6 +81,9 @@ class GFX_KEYFRAME_ANIMATION_EXPORT AnimationCurve {
int Type() const override; \
const char* TypeName() const override; \
\
+ protected: \
+ Target* target() const { return target_; } \
+ \
private: \
Target* target_ = nullptr;
diff --git a/chromium/ui/gfx/animation/keyframe/keyframe_animation_unittest.cc b/chromium/ui/gfx/animation/keyframe/keyframe_animation_unittest.cc
index 7646d94f99f..90158df3c37 100644
--- a/chromium/ui/gfx/animation/keyframe/keyframe_animation_unittest.cc
+++ b/chromium/ui/gfx/animation/keyframe/keyframe_animation_unittest.cc
@@ -7,6 +7,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/animation/keyframe/animation_curve.h"
+#include "ui/gfx/animation/keyframe/keyframed_animation_curve.h"
#include "ui/gfx/animation/keyframe/test/animation_utils.h"
#include "ui/gfx/geometry/test/size_test_util.h"
#include "ui/gfx/test/gfx_util.h"
@@ -17,16 +18,18 @@ static constexpr float kNoise = 1e-6f;
static constexpr float kEpsilon = 1e-5f;
// Tests client-specific property ids.
-static constexpr int kLayoutOffsetPropertId = 19;
-static constexpr int kBackgroundColorPropertId = 20;
-static constexpr int kOpacityPropertId = 21;
-static constexpr int kBoundsPropertId = 22;
-static constexpr int kTransformPropertId = 23;
+static constexpr int kLayoutOffsetPropertyId = 19;
+static constexpr int kBackgroundColorPropertyId = 20;
+static constexpr int kOpacityPropertyId = 21;
+static constexpr int kBoundsPropertyId = 22;
+static constexpr int kTransformPropertyId = 23;
+static constexpr int kRectPropertyId = 24;
class TestAnimationTarget : public SizeAnimationCurve::Target,
public TransformAnimationCurve::Target,
public FloatAnimationCurve::Target,
- public ColorAnimationCurve::Target {
+ public ColorAnimationCurve::Target,
+ public RectAnimationCurve::Target {
public:
TestAnimationTarget() {
layout_offset_.AppendTranslate(0, 0, 0);
@@ -40,6 +43,7 @@ class TestAnimationTarget : public SizeAnimationCurve::Target,
const TransformOperations& layout_offset() const { return layout_offset_; }
float opacity() const { return opacity_; }
SkColor background_color() const { return background_color_; }
+ Rect rect() const { return rect_; }
void OnSizeAnimated(const SizeF& size,
int target_property_id,
@@ -50,7 +54,7 @@ class TestAnimationTarget : public SizeAnimationCurve::Target,
void OnTransformAnimated(const TransformOperations& operations,
int target_property_id,
KeyframeModel* keyframe_model) override {
- if (target_property_id == kLayoutOffsetPropertId) {
+ if (target_property_id == kLayoutOffsetPropertyId) {
layout_offset_ = operations;
} else {
operations_ = operations;
@@ -69,12 +73,19 @@ class TestAnimationTarget : public SizeAnimationCurve::Target,
background_color_ = color;
}
+ void OnRectAnimated(const Rect& rect,
+ int target_property_id,
+ KeyframeModel* keyframe_model) override {
+ rect_ = rect;
+ }
+
private:
TransformOperations layout_offset_;
TransformOperations operations_;
SizeF size_ = {10.0f, 10.0f};
float opacity_ = 1.0f;
SkColor background_color_ = SK_ColorRED;
+ Rect rect_;
};
TEST(KeyframeAnimationTest, AddRemoveKeyframeModels) {
@@ -82,34 +93,34 @@ TEST(KeyframeAnimationTest, AddRemoveKeyframeModels) {
EXPECT_TRUE(animator.keyframe_models().empty());
TestAnimationTarget target;
- animator.AddKeyframeModel(CreateSizeAnimation(&target, 1, kBoundsPropertId,
+ animator.AddKeyframeModel(CreateSizeAnimation(&target, 1, kBoundsPropertyId,
SizeF(10, 100), SizeF(20, 200),
MicrosecondsToDelta(10000)));
EXPECT_EQ(1ul, animator.keyframe_models().size());
- EXPECT_EQ(kBoundsPropertId, animator.keyframe_models()[0]->TargetProperty());
+ EXPECT_EQ(kBoundsPropertyId, animator.keyframe_models()[0]->TargetProperty());
TransformOperations from_operations;
from_operations.AppendTranslate(10, 100, 1000);
TransformOperations to_operations;
to_operations.AppendTranslate(20, 200, 2000);
- animator.AddKeyframeModel(
- CreateTransformAnimation(&target, 2, kTransformPropertId, from_operations,
- to_operations, MicrosecondsToDelta(10000)));
+ animator.AddKeyframeModel(CreateTransformAnimation(
+ &target, 2, kTransformPropertyId, from_operations, to_operations,
+ MicrosecondsToDelta(10000)));
EXPECT_EQ(2ul, animator.keyframe_models().size());
- EXPECT_EQ(kTransformPropertId,
+ EXPECT_EQ(kTransformPropertyId,
animator.keyframe_models()[1]->TargetProperty());
- animator.AddKeyframeModel(
- CreateTransformAnimation(&target, 3, kTransformPropertId, from_operations,
- to_operations, MicrosecondsToDelta(10000)));
+ animator.AddKeyframeModel(CreateTransformAnimation(
+ &target, 3, kTransformPropertyId, from_operations, to_operations,
+ MicrosecondsToDelta(10000)));
EXPECT_EQ(3ul, animator.keyframe_models().size());
- EXPECT_EQ(kTransformPropertId,
+ EXPECT_EQ(kTransformPropertyId,
animator.keyframe_models()[2]->TargetProperty());
- animator.RemoveKeyframeModels(kTransformPropertId);
+ animator.RemoveKeyframeModels(kTransformPropertyId);
EXPECT_EQ(1ul, animator.keyframe_models().size());
- EXPECT_EQ(kBoundsPropertId, animator.keyframe_models()[0]->TargetProperty());
+ EXPECT_EQ(kBoundsPropertyId, animator.keyframe_models()[0]->TargetProperty());
animator.RemoveKeyframeModel(animator.keyframe_models()[0]->id());
EXPECT_TRUE(animator.keyframe_models().empty());
@@ -119,11 +130,11 @@ TEST(KeyframeAnimationTest, AnimationLifecycle) {
TestAnimationTarget target;
KeyframeEffect animator;
- animator.AddKeyframeModel(CreateSizeAnimation(&target, 1, kBoundsPropertId,
+ animator.AddKeyframeModel(CreateSizeAnimation(&target, 1, kBoundsPropertyId,
SizeF(10, 100), SizeF(20, 200),
MicrosecondsToDelta(10000)));
EXPECT_EQ(1ul, animator.keyframe_models().size());
- EXPECT_EQ(kBoundsPropertId, animator.keyframe_models()[0]->TargetProperty());
+ EXPECT_EQ(kBoundsPropertyId, animator.keyframe_models()[0]->TargetProperty());
EXPECT_EQ(KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY,
animator.keyframe_models()[0]->run_state());
@@ -146,11 +157,11 @@ TEST(KeyframeAnimationTest, AnimationQueue) {
TestAnimationTarget target;
KeyframeEffect animator;
- animator.AddKeyframeModel(CreateSizeAnimation(&target, 1, kBoundsPropertId,
+ animator.AddKeyframeModel(CreateSizeAnimation(&target, 1, kBoundsPropertyId,
SizeF(10, 100), SizeF(20, 200),
MicrosecondsToDelta(10000)));
EXPECT_EQ(1ul, animator.keyframe_models().size());
- EXPECT_EQ(kBoundsPropertId, animator.keyframe_models()[0]->TargetProperty());
+ EXPECT_EQ(kBoundsPropertyId, animator.keyframe_models()[0]->TargetProperty());
EXPECT_EQ(KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY,
animator.keyframe_models()[0]->run_state());
@@ -159,7 +170,7 @@ TEST(KeyframeAnimationTest, AnimationQueue) {
EXPECT_EQ(KeyframeModel::RUNNING, animator.keyframe_models()[0]->run_state());
EXPECT_SIZEF_EQ(SizeF(10, 100), target.size());
- animator.AddKeyframeModel(CreateSizeAnimation(&target, 2, kBoundsPropertId,
+ animator.AddKeyframeModel(CreateSizeAnimation(&target, 2, kBoundsPropertyId,
SizeF(10, 100), SizeF(20, 200),
MicrosecondsToDelta(10000)));
@@ -167,13 +178,13 @@ TEST(KeyframeAnimationTest, AnimationQueue) {
from_operations.AppendTranslate(10, 100, 1000);
TransformOperations to_operations;
to_operations.AppendTranslate(20, 200, 2000);
- animator.AddKeyframeModel(
- CreateTransformAnimation(&target, 3, kTransformPropertId, from_operations,
- to_operations, MicrosecondsToDelta(10000)));
+ animator.AddKeyframeModel(CreateTransformAnimation(
+ &target, 3, kTransformPropertyId, from_operations, to_operations,
+ MicrosecondsToDelta(10000)));
EXPECT_EQ(3ul, animator.keyframe_models().size());
- EXPECT_EQ(kBoundsPropertId, animator.keyframe_models()[1]->TargetProperty());
- EXPECT_EQ(kTransformPropertId,
+ EXPECT_EQ(kBoundsPropertyId, animator.keyframe_models()[1]->TargetProperty());
+ EXPECT_EQ(kTransformPropertyId,
animator.keyframe_models()[2]->TargetProperty());
int id1 = animator.keyframe_models()[1]->id();
@@ -202,7 +213,7 @@ TEST(KeyframeAnimationTest, FinishedTransition) {
TestAnimationTarget target;
KeyframeEffect animator;
Transition transition;
- transition.target_properties = {kOpacityPropertId};
+ transition.target_properties = {kOpacityPropertyId};
transition.duration = MsToDelta(10);
animator.set_transition(transition);
@@ -211,7 +222,7 @@ TEST(KeyframeAnimationTest, FinishedTransition) {
float from = 1.0f;
float to = 0.0f;
- animator.TransitionFloatTo(&target, start_time, kOpacityPropertId, from, to);
+ animator.TransitionFloatTo(&target, start_time, kOpacityPropertyId, from, to);
animator.Tick(start_time);
EXPECT_EQ(from, target.opacity());
@@ -220,7 +231,7 @@ TEST(KeyframeAnimationTest, FinishedTransition) {
// may have been hidden). If this happens, the unticked transition must still
// be treated as having finished.
animator.TransitionFloatTo(&target, start_time + MsToDelta(1000),
- kOpacityPropertId, target.opacity(), 1.0f);
+ kOpacityPropertyId, target.opacity(), 1.0f);
animator.Tick(start_time + MsToDelta(1000));
EXPECT_EQ(to, target.opacity());
@@ -230,7 +241,7 @@ TEST(KeyframeAnimationTest, OpacityTransitions) {
TestAnimationTarget target;
KeyframeEffect animator;
Transition transition;
- transition.target_properties = {kOpacityPropertId};
+ transition.target_properties = {kOpacityPropertyId};
transition.duration = MicrosecondsToDelta(10000);
animator.set_transition(transition);
@@ -239,7 +250,7 @@ TEST(KeyframeAnimationTest, OpacityTransitions) {
float from = 1.0f;
float to = 0.5f;
- animator.TransitionFloatTo(&target, start_time, kOpacityPropertId, from, to);
+ animator.TransitionFloatTo(&target, start_time, kOpacityPropertyId, from, to);
EXPECT_EQ(from, target.opacity());
animator.Tick(start_time);
@@ -247,7 +258,7 @@ TEST(KeyframeAnimationTest, OpacityTransitions) {
// Scheduling a redundant, approximately equal transition should be ignored.
int keyframe_model_id = animator.keyframe_models().front()->id();
float nearby = to + kNoise;
- animator.TransitionFloatTo(&target, start_time, kOpacityPropertId, from,
+ animator.TransitionFloatTo(&target, start_time, kOpacityPropertyId, from,
nearby);
EXPECT_EQ(keyframe_model_id, animator.keyframe_models().front()->id());
@@ -263,7 +274,7 @@ TEST(KeyframeAnimationTest, ReversedOpacityTransitions) {
TestAnimationTarget target;
KeyframeEffect animator;
Transition transition;
- transition.target_properties = {kOpacityPropertId};
+ transition.target_properties = {kOpacityPropertyId};
transition.duration = MicrosecondsToDelta(10000);
animator.set_transition(transition);
@@ -272,7 +283,7 @@ TEST(KeyframeAnimationTest, ReversedOpacityTransitions) {
float from = 1.0f;
float to = 0.5f;
- animator.TransitionFloatTo(&target, start_time, kOpacityPropertId, from, to);
+ animator.TransitionFloatTo(&target, start_time, kOpacityPropertyId, from, to);
EXPECT_EQ(from, target.opacity());
animator.Tick(start_time);
@@ -283,7 +294,7 @@ TEST(KeyframeAnimationTest, ReversedOpacityTransitions) {
EXPECT_LT(to, value_before_reversing);
animator.TransitionFloatTo(&target, start_time + MicrosecondsToDelta(1000),
- kOpacityPropertId, target.opacity(), from);
+ kOpacityPropertyId, target.opacity(), from);
animator.Tick(start_time + MicrosecondsToDelta(1000));
EXPECT_FLOAT_EQ(value_before_reversing, target.opacity());
@@ -291,13 +302,73 @@ TEST(KeyframeAnimationTest, ReversedOpacityTransitions) {
EXPECT_EQ(from, target.opacity());
}
+TEST(KeyframeAnimationTest, RetargetOpacityTransition) {
+ TestAnimationTarget target;
+ KeyframeEffect animator;
+
+ std::unique_ptr<KeyframedFloatAnimationCurve> curve(
+ gfx::KeyframedFloatAnimationCurve::Create());
+ curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 1.0f, nullptr));
+ curve->AddKeyframe(
+ FloatKeyframe::Create(MicrosecondsToDelta(10000), 0.0f, nullptr));
+ curve->set_target(&target);
+ animator.AddKeyframeModel(KeyframeModel::Create(
+ std::move(curve), KeyframeEffect::GetNextKeyframeModelId(),
+ kOpacityPropertyId));
+
+ base::TimeTicks start_time = MicrosecondsToTicks(1000000);
+ animator.Tick(start_time);
+ EXPECT_EQ(1.f, target.opacity());
+ animator.Tick(start_time + MicrosecondsToDelta(5000));
+ EXPECT_FLOAT_EQ(0.5f, target.opacity());
+
+ animator.GetKeyframeModel(kOpacityPropertyId)
+ ->Retarget(start_time + MicrosecondsToDelta(5000), kOpacityPropertyId,
+ 1.f);
+ animator.Tick(start_time + MicrosecondsToDelta(5000));
+ EXPECT_FLOAT_EQ(0.5f, target.opacity());
+
+ animator.Tick(start_time + MicrosecondsToDelta(7500));
+ EXPECT_FLOAT_EQ(0.75f, target.opacity());
+}
+
+TEST(KeyframeAnimationTest, RetargetTransitionBeforeLastKeyframe) {
+ TestAnimationTarget target;
+ KeyframeEffect animator;
+
+ std::unique_ptr<KeyframedFloatAnimationCurve> curve(
+ gfx::KeyframedFloatAnimationCurve::Create());
+ curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 1.0f, nullptr));
+ curve->AddKeyframe(
+ FloatKeyframe::Create(MicrosecondsToDelta(5000), 0.5f, nullptr));
+ curve->AddKeyframe(
+ FloatKeyframe::Create(MicrosecondsToDelta(10000), 0.0f, nullptr));
+ curve->set_target(&target);
+ animator.AddKeyframeModel(KeyframeModel::Create(
+ std::move(curve), KeyframeEffect::GetNextKeyframeModelId(),
+ kOpacityPropertyId));
+
+ base::TimeTicks start_time = MicrosecondsToTicks(1000000);
+ animator.Tick(start_time);
+ EXPECT_EQ(1.f, target.opacity());
+
+ animator.GetKeyframeModel(kOpacityPropertyId)
+ ->Retarget(start_time + MicrosecondsToDelta(4000), kOpacityPropertyId,
+ 0.1f);
+ animator.Tick(start_time + MicrosecondsToDelta(5000));
+ EXPECT_FLOAT_EQ(0.5f, target.opacity());
+
+ animator.Tick(start_time + MicrosecondsToDelta(7500));
+ EXPECT_FLOAT_EQ(0.3f, target.opacity());
+}
+
TEST(KeyframeAnimationTest, LayoutOffsetTransitions) {
// In this test, we do expect exact equality.
float tolerance = 0.0f;
TestAnimationTarget target;
KeyframeEffect animator;
Transition transition;
- transition.target_properties = {kLayoutOffsetPropertId};
+ transition.target_properties = {kLayoutOffsetPropertyId};
transition.duration = MicrosecondsToDelta(10000);
animator.set_transition(transition);
base::TimeTicks start_time = MicrosecondsToTicks(1000000);
@@ -309,7 +380,7 @@ TEST(KeyframeAnimationTest, LayoutOffsetTransitions) {
to.AppendTranslate(8, 0, 0);
animator.TransitionTransformOperationsTo(&target, start_time,
- kLayoutOffsetPropertId, from, to);
+ kLayoutOffsetPropertyId, from, to);
EXPECT_TRUE(from.ApproximatelyEqual(target.layout_offset(), tolerance));
animator.Tick(start_time);
@@ -319,7 +390,7 @@ TEST(KeyframeAnimationTest, LayoutOffsetTransitions) {
TransformOperations nearby = to;
nearby.at(0).translate.x += kNoise;
animator.TransitionTransformOperationsTo(
- &target, start_time, kLayoutOffsetPropertId, from, nearby);
+ &target, start_time, kLayoutOffsetPropertyId, from, nearby);
EXPECT_EQ(keyframe_model_id, animator.keyframe_models().front()->id());
animator.Tick(start_time + MicrosecondsToDelta(5000));
@@ -336,7 +407,7 @@ TEST(KeyframeAnimationTest, TransformTransitions) {
TestAnimationTarget target;
KeyframeEffect animator;
Transition transition;
- transition.target_properties = {kTransformPropertId};
+ transition.target_properties = {kTransformPropertyId};
transition.duration = MicrosecondsToDelta(10000);
animator.set_transition(transition);
base::TimeTicks start_time = MicrosecondsToTicks(1000000);
@@ -350,7 +421,7 @@ TEST(KeyframeAnimationTest, TransformTransitions) {
to.AppendScale(1, 1, 1);
animator.TransitionTransformOperationsTo(&target, start_time,
- kTransformPropertId, from, to);
+ kTransformPropertyId, from, to);
EXPECT_TRUE(from.ApproximatelyEqual(target.operations(), tolerance));
animator.Tick(start_time);
@@ -360,7 +431,7 @@ TEST(KeyframeAnimationTest, TransformTransitions) {
TransformOperations nearby = to;
nearby.at(0).translate.x += kNoise;
animator.TransitionTransformOperationsTo(&target, start_time,
- kTransformPropertId, from, nearby);
+ kTransformPropertyId, from, nearby);
EXPECT_EQ(keyframe_model_id, animator.keyframe_models().front()->id());
animator.Tick(start_time + MicrosecondsToDelta(5000));
@@ -377,7 +448,7 @@ TEST(KeyframeAnimationTest, ReversedTransformTransitions) {
TestAnimationTarget target;
KeyframeEffect animator;
Transition transition;
- transition.target_properties = {kTransformPropertId};
+ transition.target_properties = {kTransformPropertyId};
transition.duration = MicrosecondsToDelta(10000);
animator.set_transition(transition);
base::TimeTicks start_time = MicrosecondsToTicks(1000000);
@@ -391,7 +462,7 @@ TEST(KeyframeAnimationTest, ReversedTransformTransitions) {
to.AppendScale(1, 1, 1);
animator.TransitionTransformOperationsTo(&target, start_time,
- kTransformPropertId, from, to);
+ kTransformPropertyId, from, to);
EXPECT_TRUE(from.ApproximatelyEqual(target.operations(), tolerance));
animator.Tick(start_time);
@@ -402,7 +473,7 @@ TEST(KeyframeAnimationTest, ReversedTransformTransitions) {
EXPECT_GT(to.at(0).translate.x, target.operations().at(0).translate.x);
animator.TransitionTransformOperationsTo(
- &target, start_time + MicrosecondsToDelta(1000), kTransformPropertId,
+ &target, start_time + MicrosecondsToDelta(1000), kTransformPropertyId,
target.operations(), from);
animator.Tick(start_time + MicrosecondsToDelta(1000));
EXPECT_TRUE(value_before_reversing.ApproximatelyEqual(target.operations(),
@@ -412,11 +483,58 @@ TEST(KeyframeAnimationTest, ReversedTransformTransitions) {
EXPECT_TRUE(from.ApproximatelyEqual(target.operations(), tolerance));
}
+TEST(KeyframeAnimationTest, RetargetTransformTransition) {
+ float tolerance = 0.0f;
+ TestAnimationTarget target;
+ KeyframeEffect animator;
+
+ TransformOperations from;
+ from.AppendScale(1, 1, 1);
+ from.AppendTranslate(0, 0, 0);
+ TransformOperations to;
+ to.AppendScale(11, 11, 11);
+ to.AppendTranslate(-10, -10, -10);
+
+ std::unique_ptr<KeyframedTransformAnimationCurve> curve(
+ gfx::KeyframedTransformAnimationCurve::Create());
+ curve->AddKeyframe(
+ TransformKeyframe::Create(base::TimeDelta(), from, nullptr));
+ curve->AddKeyframe(
+ TransformKeyframe::Create(MicrosecondsToDelta(10000), to, nullptr));
+ curve->set_target(&target);
+ animator.AddKeyframeModel(KeyframeModel::Create(
+ std::move(curve), KeyframeEffect::GetNextKeyframeModelId(),
+ kTransformPropertyId));
+
+ base::TimeTicks start_time = MicrosecondsToTicks(1000000);
+ animator.Tick(start_time);
+ EXPECT_TRUE(from.ApproximatelyEqual(target.operations(), tolerance));
+ animator.Tick(start_time + MicrosecondsToDelta(5000));
+
+ EXPECT_FLOAT_EQ(6.f, target.operations().at(0).scale.x);
+ EXPECT_FLOAT_EQ(-5.f, target.operations().at(1).translate.x);
+
+ TransformOperations new_to;
+ new_to.AppendScale(110, 110, 110);
+ new_to.AppendTranslate(-101, -101, -101);
+
+ animator.GetKeyframeModel(kTransformPropertyId)
+ ->Retarget(start_time + MicrosecondsToDelta(5000), kTransformPropertyId,
+ new_to);
+ animator.Tick(start_time + MicrosecondsToDelta(5000));
+ EXPECT_FLOAT_EQ(6.f, target.operations().at(0).scale.x);
+ EXPECT_FLOAT_EQ(-5.f, target.operations().at(1).translate.x);
+
+ animator.Tick(start_time + MicrosecondsToDelta(7500));
+ EXPECT_FLOAT_EQ(58.f, target.operations().at(0).scale.x);
+ EXPECT_FLOAT_EQ(-53.f, target.operations().at(1).translate.x);
+}
+
TEST(KeyframeAnimationTest, BoundsTransitions) {
TestAnimationTarget target;
KeyframeEffect animator;
Transition transition;
- transition.target_properties = {kBoundsPropertId};
+ transition.target_properties = {kBoundsPropertyId};
transition.duration = MicrosecondsToDelta(10000);
animator.set_transition(transition);
base::TimeTicks start_time = MicrosecondsToTicks(1000000);
@@ -425,7 +543,7 @@ TEST(KeyframeAnimationTest, BoundsTransitions) {
SizeF from = target.size();
SizeF to(20.0f, 20.0f);
- animator.TransitionSizeTo(&target, start_time, kBoundsPropertId, from, to);
+ animator.TransitionSizeTo(&target, start_time, kBoundsPropertyId, from, to);
EXPECT_FLOAT_SIZE_EQ(from, target.size());
animator.Tick(start_time);
@@ -434,7 +552,7 @@ TEST(KeyframeAnimationTest, BoundsTransitions) {
int keyframe_model_id = animator.keyframe_models().front()->id();
SizeF nearby = to;
nearby.set_width(to.width() + kNoise);
- animator.TransitionSizeTo(&target, start_time, kBoundsPropertId, from,
+ animator.TransitionSizeTo(&target, start_time, kBoundsPropertyId, from,
nearby);
EXPECT_EQ(keyframe_model_id, animator.keyframe_models().front()->id());
@@ -448,11 +566,47 @@ TEST(KeyframeAnimationTest, BoundsTransitions) {
EXPECT_FLOAT_SIZE_EQ(to, target.size());
}
+TEST(KeyframeAnimationTest, RetargetSizeTransition) {
+ TestAnimationTarget target;
+ KeyframeEffect animator;
+
+ SizeF from(1, 2);
+ SizeF to(11, 22);
+
+ std::unique_ptr<KeyframedSizeAnimationCurve> curve(
+ gfx::KeyframedSizeAnimationCurve::Create());
+ curve->AddKeyframe(SizeKeyframe::Create(base::TimeDelta(), from, nullptr));
+ curve->AddKeyframe(
+ SizeKeyframe::Create(MicrosecondsToDelta(10000), to, nullptr));
+ curve->set_target(&target);
+ animator.AddKeyframeModel(KeyframeModel::Create(
+ std::move(curve), KeyframeEffect::GetNextKeyframeModelId(),
+ kBoundsPropertyId));
+
+ base::TimeTicks start_time = MicrosecondsToTicks(1000000);
+ animator.Tick(start_time);
+ EXPECT_EQ(from, target.size());
+ animator.Tick(start_time + MicrosecondsToDelta(5000));
+
+ EXPECT_FLOAT_SIZE_EQ(SizeF(6, 12), target.size());
+
+ SizeF new_to(600, 1200);
+
+ animator.GetKeyframeModel(kBoundsPropertyId)
+ ->Retarget(start_time + MicrosecondsToDelta(5000), kRectPropertyId,
+ new_to);
+ animator.Tick(start_time + MicrosecondsToDelta(5000));
+ EXPECT_FLOAT_SIZE_EQ(SizeF(6, 12), target.size());
+
+ animator.Tick(start_time + MicrosecondsToDelta(7500));
+ EXPECT_FLOAT_SIZE_EQ(SizeF(303, 606), target.size());
+}
+
TEST(KeyframeAnimationTest, ReversedBoundsTransitions) {
TestAnimationTarget target;
KeyframeEffect animator;
Transition transition;
- transition.target_properties = {kBoundsPropertId};
+ transition.target_properties = {kBoundsPropertyId};
transition.duration = MicrosecondsToDelta(10000);
animator.set_transition(transition);
base::TimeTicks start_time = MicrosecondsToTicks(1000000);
@@ -461,7 +615,7 @@ TEST(KeyframeAnimationTest, ReversedBoundsTransitions) {
SizeF from = target.size();
SizeF to(20.0f, 20.0f);
- animator.TransitionSizeTo(&target, start_time, kBoundsPropertId, from, to);
+ animator.TransitionSizeTo(&target, start_time, kBoundsPropertyId, from, to);
EXPECT_FLOAT_SIZE_EQ(from, target.size());
animator.Tick(start_time);
@@ -474,7 +628,7 @@ TEST(KeyframeAnimationTest, ReversedBoundsTransitions) {
EXPECT_GT(to.height(), target.size().height());
animator.TransitionSizeTo(&target, start_time + MicrosecondsToDelta(1000),
- kBoundsPropertId, target.size(), from);
+ kBoundsPropertyId, target.size(), from);
animator.Tick(start_time + MicrosecondsToDelta(1000));
EXPECT_FLOAT_SIZE_EQ(value_before_reversing, target.size());
@@ -486,7 +640,7 @@ TEST(KeyframeAnimationTest, BackgroundColorTransitions) {
TestAnimationTarget target;
KeyframeEffect animator;
Transition transition;
- transition.target_properties = {kBackgroundColorPropertId};
+ transition.target_properties = {kBackgroundColorPropertyId};
transition.duration = MicrosecondsToDelta(10000);
animator.set_transition(transition);
base::TimeTicks start_time = MicrosecondsToTicks(1000000);
@@ -495,7 +649,7 @@ TEST(KeyframeAnimationTest, BackgroundColorTransitions) {
SkColor from = SK_ColorRED;
SkColor to = SK_ColorGREEN;
- animator.TransitionColorTo(&target, start_time, kBackgroundColorPropertId,
+ animator.TransitionColorTo(&target, start_time, kBackgroundColorPropertyId,
from, to);
EXPECT_EQ(from, target.background_color());
@@ -517,7 +671,7 @@ TEST(KeyframeAnimationTest, ReversedBackgroundColorTransitions) {
TestAnimationTarget target;
KeyframeEffect animator;
Transition transition;
- transition.target_properties = {kBackgroundColorPropertId};
+ transition.target_properties = {kBackgroundColorPropertyId};
transition.duration = MicrosecondsToDelta(10000);
animator.set_transition(transition);
base::TimeTicks start_time = MicrosecondsToTicks(1000000);
@@ -526,7 +680,7 @@ TEST(KeyframeAnimationTest, ReversedBackgroundColorTransitions) {
SkColor from = SK_ColorRED;
SkColor to = SK_ColorGREEN;
- animator.TransitionColorTo(&target, start_time, kBackgroundColorPropertId,
+ animator.TransitionColorTo(&target, start_time, kBackgroundColorPropertyId,
from, to);
EXPECT_EQ(from, target.background_color());
@@ -542,7 +696,7 @@ TEST(KeyframeAnimationTest, ReversedBackgroundColorTransitions) {
EXPECT_EQ(255u, SkColorGetA(target.background_color()));
animator.TransitionColorTo(&target, start_time + MicrosecondsToDelta(1000),
- kBackgroundColorPropertId,
+ kBackgroundColorPropertyId,
target.background_color(), from);
animator.Tick(start_time + MicrosecondsToDelta(1000));
EXPECT_EQ(value_before_reversing, target.background_color());
@@ -551,11 +705,47 @@ TEST(KeyframeAnimationTest, ReversedBackgroundColorTransitions) {
EXPECT_EQ(from, target.background_color());
}
+TEST(KeyframeAnimationTest, RetargetColorTransition) {
+ TestAnimationTarget target;
+ KeyframeEffect animator;
+
+ SkColor from = SkColorSetRGB(0, 0, 0);
+ SkColor to = SkColorSetRGB(10, 10, 10);
+
+ std::unique_ptr<KeyframedColorAnimationCurve> curve(
+ gfx::KeyframedColorAnimationCurve::Create());
+ curve->AddKeyframe(ColorKeyframe::Create(base::TimeDelta(), from, nullptr));
+ curve->AddKeyframe(
+ ColorKeyframe::Create(MicrosecondsToDelta(10000), to, nullptr));
+ curve->set_target(&target);
+ animator.AddKeyframeModel(KeyframeModel::Create(
+ std::move(curve), KeyframeEffect::GetNextKeyframeModelId(),
+ kBackgroundColorPropertyId));
+
+ base::TimeTicks start_time = MicrosecondsToTicks(1000000);
+ animator.Tick(start_time);
+ EXPECT_EQ(from, target.background_color());
+ animator.Tick(start_time + MicrosecondsToDelta(5000));
+
+ EXPECT_EQ(5u, SkColorGetR(target.background_color()));
+
+ SkColor new_to = SkColorSetRGB(101, 101, 101);
+
+ animator.GetKeyframeModel(kBackgroundColorPropertyId)
+ ->Retarget(start_time + MicrosecondsToDelta(5000), kRectPropertyId,
+ new_to);
+ animator.Tick(start_time + MicrosecondsToDelta(5000));
+ EXPECT_EQ(5u, SkColorGetR(target.background_color()));
+
+ animator.Tick(start_time + MicrosecondsToDelta(7500));
+ EXPECT_EQ(53u, SkColorGetR(target.background_color()));
+}
+
TEST(KeyframeAnimationTest, DoubleReversedTransitions) {
TestAnimationTarget target;
KeyframeEffect animator;
Transition transition;
- transition.target_properties = {kOpacityPropertId};
+ transition.target_properties = {kOpacityPropertyId};
transition.duration = MicrosecondsToDelta(10000);
animator.set_transition(transition);
@@ -564,7 +754,7 @@ TEST(KeyframeAnimationTest, DoubleReversedTransitions) {
float from = 1.0f;
float to = 0.5f;
- animator.TransitionFloatTo(&target, start_time, kOpacityPropertId, from, to);
+ animator.TransitionFloatTo(&target, start_time, kOpacityPropertyId, from, to);
EXPECT_EQ(from, target.opacity());
animator.Tick(start_time);
@@ -575,7 +765,7 @@ TEST(KeyframeAnimationTest, DoubleReversedTransitions) {
EXPECT_LT(to, value_before_reversing);
animator.TransitionFloatTo(&target, start_time + MicrosecondsToDelta(1000),
- kOpacityPropertId, target.opacity(), from);
+ kOpacityPropertyId, target.opacity(), from);
animator.Tick(start_time + MicrosecondsToDelta(1000));
EXPECT_FLOAT_EQ(value_before_reversing, target.opacity());
@@ -584,7 +774,7 @@ TEST(KeyframeAnimationTest, DoubleReversedTransitions) {
// If the code for reversing transitions does not account for an existing time
// offset, then reversing a second time will give incorrect values.
animator.TransitionFloatTo(&target, start_time + MicrosecondsToDelta(1500),
- kOpacityPropertId, target.opacity(), to);
+ kOpacityPropertyId, target.opacity(), to);
animator.Tick(start_time + MicrosecondsToDelta(1500));
EXPECT_FLOAT_EQ(value_before_reversing, target.opacity());
}
@@ -593,7 +783,7 @@ TEST(KeyframeAnimationTest, RedundantTransition) {
TestAnimationTarget target;
KeyframeEffect animator;
Transition transition;
- transition.target_properties = {kOpacityPropertId};
+ transition.target_properties = {kOpacityPropertyId};
transition.duration = MicrosecondsToDelta(10000);
animator.set_transition(transition);
@@ -602,7 +792,7 @@ TEST(KeyframeAnimationTest, RedundantTransition) {
float from = 1.0f;
float to = 0.5f;
- animator.TransitionFloatTo(&target, start_time, kOpacityPropertId, from, to);
+ animator.TransitionFloatTo(&target, start_time, kOpacityPropertyId, from, to);
EXPECT_EQ(from, target.opacity());
animator.Tick(start_time);
@@ -612,7 +802,7 @@ TEST(KeyframeAnimationTest, RedundantTransition) {
// While an existing transition is in progress to the same value, we should
// not start a new transition.
- animator.TransitionFloatTo(&target, start_time, kOpacityPropertId,
+ animator.TransitionFloatTo(&target, start_time, kOpacityPropertyId,
target.opacity(), to);
EXPECT_EQ(1lu, animator.keyframe_models().size());
@@ -623,7 +813,7 @@ TEST(KeyframeAnimationTest, TransitionToSameValue) {
TestAnimationTarget target;
KeyframeEffect animator;
Transition transition;
- transition.target_properties = {kOpacityPropertId};
+ transition.target_properties = {kOpacityPropertyId};
transition.duration = MicrosecondsToDelta(10000);
animator.set_transition(transition);
@@ -633,7 +823,7 @@ TEST(KeyframeAnimationTest, TransitionToSameValue) {
// Transitioning to the same value should be a no-op.
float from = 1.0f;
float to = 1.0f;
- animator.TransitionFloatTo(&target, start_time, kOpacityPropertId, from, to);
+ animator.TransitionFloatTo(&target, start_time, kOpacityPropertyId, from, to);
EXPECT_EQ(from, target.opacity());
EXPECT_TRUE(animator.keyframe_models().empty());
}
@@ -656,40 +846,77 @@ TEST(KeyframeAnimationTest, CorrectTargetValue) {
// Verify the default value is returned if there's no running animations.
EXPECT_EQ(from_opacity,
- animator.GetTargetFloatValue(kOpacityPropertId, from_opacity));
+ animator.GetTargetFloatValue(kOpacityPropertyId, from_opacity));
EXPECT_SIZEF_EQ(from_bounds,
- animator.GetTargetSizeValue(kBoundsPropertId, from_bounds));
- EXPECT_EQ(from_color, animator.GetTargetColorValue(kBackgroundColorPropertId,
+ animator.GetTargetSizeValue(kBoundsPropertyId, from_bounds));
+ EXPECT_EQ(from_color, animator.GetTargetColorValue(kBackgroundColorPropertyId,
from_color));
EXPECT_TRUE(from_transform.ApproximatelyEqual(
- animator.GetTargetTransformOperationsValue(kTransformPropertId,
+ animator.GetTargetTransformOperationsValue(kTransformPropertyId,
from_transform),
kEpsilon));
// Add keyframe_models.
animator.AddKeyframeModel(CreateFloatAnimation(
- &target, 2, kOpacityPropertId, from_opacity, to_opacity, duration));
+ &target, 2, kOpacityPropertyId, from_opacity, to_opacity, duration));
animator.AddKeyframeModel(CreateSizeAnimation(
- &target, 1, kBoundsPropertId, from_bounds, to_bounds, duration));
+ &target, 1, kBoundsPropertyId, from_bounds, to_bounds, duration));
animator.AddKeyframeModel(CreateColorAnimation(
- &target, 3, kBackgroundColorPropertId, from_color, to_color, duration));
- animator.AddKeyframeModel(CreateTransformAnimation(
- &target, 4, kTransformPropertId, from_transform, to_transform, duration));
+ &target, 3, kBackgroundColorPropertyId, from_color, to_color, duration));
+ animator.AddKeyframeModel(
+ CreateTransformAnimation(&target, 4, kTransformPropertyId, from_transform,
+ to_transform, duration));
base::TimeTicks start_time = MicrosecondsToTicks(1000000);
animator.Tick(start_time);
// Verify target value.
EXPECT_EQ(to_opacity,
- animator.GetTargetFloatValue(kOpacityPropertId, from_opacity));
+ animator.GetTargetFloatValue(kOpacityPropertyId, from_opacity));
EXPECT_SIZEF_EQ(to_bounds,
- animator.GetTargetSizeValue(kBoundsPropertId, from_bounds));
- EXPECT_EQ(to_color, animator.GetTargetColorValue(kBackgroundColorPropertId,
+ animator.GetTargetSizeValue(kBoundsPropertyId, from_bounds));
+ EXPECT_EQ(to_color, animator.GetTargetColorValue(kBackgroundColorPropertyId,
from_color));
EXPECT_TRUE(to_transform.ApproximatelyEqual(
- animator.GetTargetTransformOperationsValue(kTransformPropertId,
+ animator.GetTargetTransformOperationsValue(kTransformPropertyId,
from_transform),
kEpsilon));
}
+TEST(KeyframeAnimationTest, RetargetRectTransition) {
+ TestAnimationTarget target;
+ KeyframeEffect animator;
+
+ Rect from(1, 2, 3, 4);
+ Rect to(11, 22, 33, 44);
+
+ std::unique_ptr<KeyframedRectAnimationCurve> curve(
+ gfx::KeyframedRectAnimationCurve::Create());
+ curve->AddKeyframe(RectKeyframe::Create(base::TimeDelta(), from, nullptr));
+ curve->AddKeyframe(
+ RectKeyframe::Create(MicrosecondsToDelta(10000), to, nullptr));
+ curve->set_target(&target);
+ animator.AddKeyframeModel(KeyframeModel::Create(
+ std::move(curve), KeyframeEffect::GetNextKeyframeModelId(),
+ kRectPropertyId));
+
+ base::TimeTicks start_time = MicrosecondsToTicks(1000000);
+ animator.Tick(start_time);
+ EXPECT_EQ(from, target.rect());
+ animator.Tick(start_time + MicrosecondsToDelta(5000));
+
+ EXPECT_EQ(Rect(6, 12, 18, 24), target.rect());
+
+ Rect new_to(600, 1200, 1800, 2400);
+
+ animator.GetKeyframeModel(kRectPropertyId)
+ ->Retarget(start_time + MicrosecondsToDelta(5000), kRectPropertyId,
+ new_to);
+ animator.Tick(start_time + MicrosecondsToDelta(5000));
+ EXPECT_EQ(Rect(6, 12, 18, 24), target.rect());
+
+ animator.Tick(start_time + MicrosecondsToDelta(7500));
+ EXPECT_EQ(Rect(303, 606, 909, 1212), target.rect());
+}
+
} // namespace gfx
diff --git a/chromium/ui/gfx/animation/keyframe/keyframe_effect.cc b/chromium/ui/gfx/animation/keyframe/keyframe_effect.cc
index 53bdb43d332..ba8edd7ffd9 100644
--- a/chromium/ui/gfx/animation/keyframe/keyframe_effect.cc
+++ b/chromium/ui/gfx/animation/keyframe/keyframe_effect.cc
@@ -15,8 +15,6 @@ namespace gfx {
namespace {
-static constexpr float kTolerance = 1e-5f;
-
static int s_next_keyframe_model_id = 1;
static int s_next_group_id = 1;
@@ -84,52 +82,6 @@ base::TimeDelta GetEndTime(KeyframeModel* keyframe_model) {
return keyframe_model->curve()->Duration();
}
-bool SufficientlyEqual(float lhs, float rhs) {
- return base::IsApproximatelyEqual(lhs, rhs, kTolerance);
-}
-
-bool SufficientlyEqual(const gfx::TransformOperations& lhs,
- const gfx::TransformOperations& rhs) {
- return lhs.ApproximatelyEqual(rhs, kTolerance);
-}
-
-bool SufficientlyEqual(const gfx::SizeF& lhs, const gfx::SizeF& rhs) {
- return base::IsApproximatelyEqual(lhs.width(), rhs.width(), kTolerance) &&
- base::IsApproximatelyEqual(lhs.height(), rhs.height(), kTolerance);
-}
-
-bool SufficientlyEqual(SkColor lhs, SkColor rhs) {
- return lhs == rhs;
-}
-
-template <typename T>
-struct AnimationTraits {};
-
-#define DEFINE_ANIMATION_TRAITS(value_type, name) \
- template <> \
- struct AnimationTraits<value_type> { \
- typedef value_type ValueType; \
- typedef name##AnimationCurve::Target TargetType; \
- typedef name##AnimationCurve CurveType; \
- typedef Keyframed##name##AnimationCurve KeyframedCurveType; \
- typedef name##Keyframe KeyframeType; \
- static const CurveType* ToDerivedCurve(const AnimationCurve* curve) { \
- return name##AnimationCurve::To##name##AnimationCurve(curve); \
- } \
- static void OnValueAnimated(name##AnimationCurve::Target* target, \
- const ValueType& target_value, \
- int target_property) { \
- target->On##name##Animated(target_value, target_property, nullptr); \
- } \
- }
-
-DEFINE_ANIMATION_TRAITS(float, Float);
-DEFINE_ANIMATION_TRAITS(gfx::TransformOperations, Transform);
-DEFINE_ANIMATION_TRAITS(gfx::SizeF, Size);
-DEFINE_ANIMATION_TRAITS(SkColor, Color);
-
-#undef DEFINE_ANIMATION_TRAITS
-
template <typename ValueType>
void TransitionValueTo(KeyframeEffect* animator,
typename AnimationTraits<ValueType>::TargetType* target,
@@ -199,8 +151,9 @@ int KeyframeEffect::GetNextGroupId() {
return s_next_group_id++;
}
-KeyframeEffect::KeyframeEffect() {}
-KeyframeEffect::~KeyframeEffect() {}
+KeyframeEffect::KeyframeEffect() = default;
+KeyframeEffect::KeyframeEffect(KeyframeEffect&&) = default;
+KeyframeEffect::~KeyframeEffect() = default;
void KeyframeEffect::AddKeyframeModel(
std::unique_ptr<KeyframeModel> keyframe_model) {
diff --git a/chromium/ui/gfx/animation/keyframe/keyframe_effect.h b/chromium/ui/gfx/animation/keyframe/keyframe_effect.h
index 416055403e9..818dce77b1e 100644
--- a/chromium/ui/gfx/animation/keyframe/keyframe_effect.h
+++ b/chromium/ui/gfx/animation/keyframe/keyframe_effect.h
@@ -40,7 +40,10 @@ class GFX_KEYFRAME_ANIMATION_EXPORT KeyframeEffect {
KeyframeEffect();
~KeyframeEffect();
+ KeyframeEffect(KeyframeEffect&&);
KeyframeEffect(const KeyframeEffect&) = delete;
+
+ KeyframeEffect& operator=(KeyframeEffect&&) = default;
KeyframeEffect& operator=(const KeyframeEffect&) = delete;
virtual void AddKeyframeModel(std::unique_ptr<KeyframeModel> keyframe_model);
diff --git a/chromium/ui/gfx/animation/keyframe/keyframe_model.cc b/chromium/ui/gfx/animation/keyframe/keyframe_model.cc
index 1b20c082fd8..e395eb4150e 100644
--- a/chromium/ui/gfx/animation/keyframe/keyframe_model.cc
+++ b/chromium/ui/gfx/animation/keyframe/keyframe_model.cc
@@ -118,7 +118,7 @@ KeyframeModel::Phase KeyframeModel::CalculatePhase(
return KeyframeModel::Phase::ACTIVE;
}
-base::Optional<base::TimeDelta> KeyframeModel::CalculateActiveTime(
+absl::optional<base::TimeDelta> KeyframeModel::CalculateActiveTime(
base::TimeTicks monotonic_time) const {
base::TimeDelta local_time = ConvertMonotonicTimeToLocalTime(monotonic_time);
KeyframeModel::Phase phase = CalculatePhase(local_time);
@@ -127,7 +127,7 @@ base::Optional<base::TimeDelta> KeyframeModel::CalculateActiveTime(
case KeyframeModel::Phase::BEFORE:
if (fill_mode_ == FillMode::BACKWARDS || fill_mode_ == FillMode::BOTH)
return std::max(local_time + time_offset_, base::TimeDelta());
- return base::nullopt;
+ return absl::nullopt;
case KeyframeModel::Phase::ACTIVE:
return local_time + time_offset_;
case KeyframeModel::Phase::AFTER:
@@ -138,10 +138,10 @@ base::Optional<base::TimeDelta> KeyframeModel::CalculateActiveTime(
return std::max(std::min(local_time + time_offset_, active_duration),
base::TimeDelta());
}
- return base::nullopt;
+ return absl::nullopt;
default:
NOTREACHED();
- return base::nullopt;
+ return absl::nullopt;
}
}
diff --git a/chromium/ui/gfx/animation/keyframe/keyframe_model.h b/chromium/ui/gfx/animation/keyframe/keyframe_model.h
index 92f9c07547a..3cb053b8136 100644
--- a/chromium/ui/gfx/animation/keyframe/keyframe_model.h
+++ b/chromium/ui/gfx/animation/keyframe/keyframe_model.h
@@ -7,8 +7,10 @@
#include <string>
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/animation/keyframe/animation_curve.h"
#include "ui/gfx/animation/keyframe/keyframe_animation_export.h"
+#include "ui/gfx/animation/keyframe/keyframed_animation_curve.h"
namespace gfx {
@@ -121,6 +123,21 @@ class GFX_KEYFRAME_ANIMATION_EXPORT KeyframeModel {
bool HasActiveTime(base::TimeTicks monotonic_time) const;
+ template <typename T>
+ void Retarget(base::TimeTicks now,
+ int property_id,
+ const T& new_target_value) {
+ if (!curve_)
+ return;
+ base::TimeDelta now_delta = TrimTimeToCurrentIteration(now);
+
+ DCHECK_EQ(CalculatePhase(now_delta), KeyframeModel::Phase::ACTIVE);
+ auto* keyframed_curve = AnimationTraits<T>::ToKeyframedCurve(curve_.get());
+ DCHECK(keyframed_curve);
+ if (auto new_curve = keyframed_curve->Retarget(now_delta, new_target_value))
+ curve_ = std::move(new_curve);
+ }
+
// Some clients may run threaded animations and may need to defer starting
// until the animation on the other thread has been started.
virtual bool StartShouldBeDeferred() const;
@@ -139,7 +156,7 @@ class GFX_KEYFRAME_ANIMATION_EXPORT KeyframeModel {
int target_property_id);
void ForceRunState(RunState run_state) { run_state_ = run_state; }
- base::Optional<base::TimeDelta> CalculateActiveTime(
+ absl::optional<base::TimeDelta> CalculateActiveTime(
base::TimeTicks monotonic_time) const;
private:
diff --git a/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.cc b/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.cc
index 90671be1822..3aba6cf916d 100644
--- a/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.cc
+++ b/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.cc
@@ -11,11 +11,78 @@
#include <utility>
#include "base/memory/ptr_util.h"
+#include "base/numerics/ranges.h"
+#include "base/time/time.h"
#include "ui/gfx/animation/keyframe/keyframed_animation_curve-inl.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/geometry/box_f.h"
namespace gfx {
+namespace {
+
+static constexpr float kTolerance = 1e-5f;
+
+template <typename KeyframeType, typename ValueType, typename TargetType>
+std::unique_ptr<AnimationCurve> RetargettedCurve(
+ std::vector<std::unique_ptr<KeyframeType>>& keyframes,
+ base::TimeDelta t,
+ const ValueType& value_at_t,
+ const ValueType& new_target_value,
+ double scaled_duration,
+ TargetType* target,
+ const TimingFunction* timing_function) {
+ if (SufficientlyEqual(keyframes.back()->Value(), new_target_value))
+ return nullptr;
+
+ DCHECK_GE(keyframes.size(), 2u);
+ DCHECK_GT(scaled_duration, 0.f);
+
+ // If we haven't progressed to animating between the last 2 keyframes, simply
+ // clobber the value for the last keyframe.
+ const bool at_last_keyframe =
+ (keyframes[keyframes.size() - 2]->Time() * scaled_duration) <= t;
+ if (!at_last_keyframe) {
+ auto& last_keyframe = keyframes.back();
+ auto* keyframe_timing_function = last_keyframe->timing_function();
+ last_keyframe = KeyframeType::Create(
+ last_keyframe->Time(), new_target_value,
+ keyframe_timing_function ? keyframe_timing_function->Clone() : nullptr);
+ return nullptr;
+ }
+
+ // Ensure that `t` happens between the last two keyframes.
+ DCHECK_GE(keyframes[keyframes.size() - 1]->Time() * scaled_duration, t);
+
+ // TODO(crbug.com/1198305): This can be changed to a different / special
+ // interpolation curve type to maintain c2 continuity.
+ auto curve = AnimationTraits<ValueType>::KeyframedCurveType::Create();
+ curve->set_scaled_duration(scaled_duration);
+ curve->set_target(target);
+
+ auto generate_timing_function =
+ [timing_function]() -> std::unique_ptr<gfx::TimingFunction> {
+ if (timing_function)
+ return timing_function->Clone();
+ return nullptr;
+ };
+
+ // Keep the curve duration the same by adding the same first frame.
+ curve->AddKeyframe(KeyframeType::Create(keyframes.front()->Time(),
+ keyframes.front()->Value(),
+ generate_timing_function()));
+
+ // Snap the current value at `t` so that the current value stays the same.
+ curve->AddKeyframe(KeyframeType::Create(t / scaled_duration, value_at_t,
+ generate_timing_function()));
+
+ // Add a new target at the same time as the last frame.
+ curve->AddKeyframe(KeyframeType::Create(
+ keyframes.back()->Time(), new_target_value, generate_timing_function()));
+
+ return curve;
+}
+
+} // namespace
Keyframe::Keyframe(base::TimeDelta time,
std::unique_ptr<TimingFunction> timing_function)
@@ -213,6 +280,14 @@ SkColor KeyframedColorAnimationCurve::GetValue(base::TimeDelta t) const {
keyframes_[i + 1]->Value());
}
+std::unique_ptr<AnimationCurve> KeyframedColorAnimationCurve::Retarget(
+ base::TimeDelta t,
+ SkColor new_target) {
+ DCHECK(!keyframes_.empty());
+ return RetargettedCurve(keyframes_, t, GetValue(t), new_target,
+ scaled_duration(), target(), timing_function_.get());
+}
+
std::unique_ptr<KeyframedFloatAnimationCurve>
KeyframedFloatAnimationCurve::Create() {
return base::WrapUnique(new KeyframedFloatAnimationCurve);
@@ -251,6 +326,14 @@ std::unique_ptr<AnimationCurve> KeyframedFloatAnimationCurve::Clone() const {
return std::move(to_return);
}
+std::unique_ptr<AnimationCurve> KeyframedFloatAnimationCurve::Retarget(
+ base::TimeDelta t,
+ float new_target) {
+ DCHECK(!keyframes_.empty());
+ return RetargettedCurve(keyframes_, t, GetValue(t), new_target,
+ scaled_duration(), target(), timing_function_.get());
+}
+
float KeyframedFloatAnimationCurve::GetValue(base::TimeDelta t) const {
if (t <= (keyframes_.front()->Time() * scaled_duration()))
return keyframes_.front()->Value();
@@ -344,6 +427,14 @@ bool KeyframedTransformAnimationCurve::MaximumScale(float* max_scale) const {
return *max_scale > 0.f;
}
+std::unique_ptr<AnimationCurve> KeyframedTransformAnimationCurve::Retarget(
+ base::TimeDelta t,
+ const gfx::TransformOperations& new_target) {
+ DCHECK(!keyframes_.empty());
+ return RetargettedCurve(keyframes_, t, GetValue(t), new_target,
+ scaled_duration(), target(), timing_function_.get());
+}
+
std::unique_ptr<KeyframedSizeAnimationCurve>
KeyframedSizeAnimationCurve::Create() {
return base::WrapUnique(new KeyframedSizeAnimationCurve);
@@ -399,6 +490,14 @@ gfx::SizeF KeyframedSizeAnimationCurve::GetValue(base::TimeDelta t) const {
keyframes_[i + 1]->Value());
}
+std::unique_ptr<AnimationCurve> KeyframedSizeAnimationCurve::Retarget(
+ base::TimeDelta t,
+ const gfx::SizeF& new_target) {
+ DCHECK(!keyframes_.empty());
+ return RetargettedCurve(keyframes_, t, GetValue(t), new_target,
+ scaled_duration(), target(), timing_function_.get());
+}
+
std::unique_ptr<KeyframedRectAnimationCurve>
KeyframedRectAnimationCurve::Create() {
return base::WrapUnique(new KeyframedRectAnimationCurve);
@@ -454,4 +553,34 @@ gfx::Rect KeyframedRectAnimationCurve::GetValue(base::TimeDelta t) const {
keyframes_[i + 1]->Value());
}
+std::unique_ptr<AnimationCurve> KeyframedRectAnimationCurve::Retarget(
+ base::TimeDelta t,
+ const gfx::Rect& new_target) {
+ DCHECK(!keyframes_.empty());
+ return RetargettedCurve(keyframes_, t, GetValue(t), new_target,
+ scaled_duration(), target(), timing_function_.get());
+}
+
+bool SufficientlyEqual(float lhs, float rhs) {
+ return base::IsApproximatelyEqual(lhs, rhs, kTolerance);
+}
+
+bool SufficientlyEqual(const TransformOperations& lhs,
+ const TransformOperations& rhs) {
+ return lhs.ApproximatelyEqual(rhs, kTolerance);
+}
+
+bool SufficientlyEqual(const SizeF& lhs, const SizeF& rhs) {
+ return base::IsApproximatelyEqual(lhs.width(), rhs.width(), kTolerance) &&
+ base::IsApproximatelyEqual(lhs.height(), rhs.height(), kTolerance);
+}
+
+bool SufficientlyEqual(SkColor lhs, SkColor rhs) {
+ return lhs == rhs;
+}
+
+bool SufficientlyEqual(const Rect& lhs, const Rect& rhs) {
+ return lhs == rhs;
+}
+
} // namespace gfx
diff --git a/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.h b/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.h
index cf35b9e2d95..1fd1886b7a7 100644
--- a/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.h
+++ b/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.h
@@ -168,6 +168,9 @@ class GFX_KEYFRAME_ANIMATION_EXPORT KeyframedColorAnimationCurve
// BackgrounColorAnimationCurve implementation
SkColor GetValue(base::TimeDelta t) const override;
+ std::unique_ptr<AnimationCurve> Retarget(base::TimeDelta t,
+ SkColor new_target);
+
using Keyframes = std::vector<std::unique_ptr<ColorKeyframe>>;
const Keyframes& keyframes_for_testing() const { return keyframes_; }
@@ -214,6 +217,8 @@ class GFX_KEYFRAME_ANIMATION_EXPORT KeyframedFloatAnimationCurve
// FloatAnimationCurve implementation
float GetValue(base::TimeDelta t) const override;
+ std::unique_ptr<AnimationCurve> Retarget(base::TimeDelta t, float new_target);
+
using Keyframes = std::vector<std::unique_ptr<FloatKeyframe>>;
const Keyframes& keyframes_for_testing() const { return keyframes_; }
@@ -259,6 +264,10 @@ class GFX_KEYFRAME_ANIMATION_EXPORT KeyframedTransformAnimationCurve
bool PreservesAxisAlignment() const override;
bool MaximumScale(float* max_scale) const override;
+ std::unique_ptr<AnimationCurve> Retarget(
+ base::TimeDelta t,
+ const gfx::TransformOperations& new_target);
+
private:
KeyframedTransformAnimationCurve();
@@ -298,6 +307,9 @@ class GFX_KEYFRAME_ANIMATION_EXPORT KeyframedSizeAnimationCurve
// SizeAnimationCurve implementation
gfx::SizeF GetValue(base::TimeDelta t) const override;
+ std::unique_ptr<AnimationCurve> Retarget(base::TimeDelta t,
+ const gfx::SizeF& new_target);
+
private:
KeyframedSizeAnimationCurve();
@@ -337,6 +349,9 @@ class GFX_KEYFRAME_ANIMATION_EXPORT KeyframedRectAnimationCurve
// RectAnimationCurve implementation
gfx::Rect GetValue(base::TimeDelta t) const override;
+ std::unique_ptr<AnimationCurve> Retarget(base::TimeDelta t,
+ const gfx::Rect& new_target);
+
private:
KeyframedRectAnimationCurve();
@@ -347,6 +362,52 @@ class GFX_KEYFRAME_ANIMATION_EXPORT KeyframedRectAnimationCurve
double scaled_duration_ = 0.;
};
+template <typename T>
+struct AnimationTraits {};
+
+#define DEFINE_ANIMATION_TRAITS(value_type, name) \
+ template <> \
+ struct AnimationTraits<value_type> { \
+ typedef value_type ValueType; \
+ typedef name##AnimationCurve::Target TargetType; \
+ typedef name##AnimationCurve CurveType; \
+ typedef Keyframed##name##AnimationCurve KeyframedCurveType; \
+ typedef name##Keyframe KeyframeType; \
+ static const CurveType* ToDerivedCurve(const AnimationCurve* curve) { \
+ return name##AnimationCurve::To##name##AnimationCurve(curve); \
+ } \
+ static CurveType* ToDerivedCurve(AnimationCurve* curve) { \
+ return name##AnimationCurve::To##name##AnimationCurve(curve); \
+ } \
+ static const KeyframedCurveType* ToKeyframedCurve( \
+ const AnimationCurve* curve) { \
+ return static_cast<const KeyframedCurveType*>(ToDerivedCurve(curve)); \
+ } \
+ static KeyframedCurveType* ToKeyframedCurve(AnimationCurve* curve) { \
+ return static_cast<KeyframedCurveType*>(ToDerivedCurve(curve)); \
+ } \
+ static void OnValueAnimated(name##AnimationCurve::Target* target, \
+ const ValueType& target_value, \
+ int target_property) { \
+ target->On##name##Animated(target_value, target_property, nullptr); \
+ } \
+ }
+
+DEFINE_ANIMATION_TRAITS(float, Float);
+DEFINE_ANIMATION_TRAITS(TransformOperations, Transform);
+DEFINE_ANIMATION_TRAITS(SizeF, Size);
+DEFINE_ANIMATION_TRAITS(SkColor, Color);
+DEFINE_ANIMATION_TRAITS(Rect, Rect);
+
+#undef DEFINE_ANIMATION_TRAITS
+
+bool SufficientlyEqual(float lhs, float rhs);
+bool SufficientlyEqual(const TransformOperations& lhs,
+ const TransformOperations& rhs);
+bool SufficientlyEqual(const SizeF& lhs, const SizeF& rhs);
+bool SufficientlyEqual(SkColor lhs, SkColor rhs);
+bool SufficientlyEqual(const Rect& lhs, const Rect& rhs);
+
} // namespace gfx
#endif // UI_GFX_ANIMATION_KEYFRAME_KEYFRAMED_ANIMATION_CURVE_H_
diff --git a/chromium/ui/gfx/animation/keyframe/transition.cc b/chromium/ui/gfx/animation/keyframe/transition.cc
index 05ce53da634..cd548ec04c4 100644
--- a/chromium/ui/gfx/animation/keyframe/transition.cc
+++ b/chromium/ui/gfx/animation/keyframe/transition.cc
@@ -14,6 +14,8 @@ Transition::Transition()
: duration(
base::TimeDelta::FromMilliseconds(kDefaultTransitionDurationMs)) {}
-Transition::~Transition() {}
+Transition::Transition(const Transition&) = default;
+Transition::Transition(Transition&&) = default;
+Transition::~Transition() = default;
} // namespace gfx
diff --git a/chromium/ui/gfx/animation/keyframe/transition.h b/chromium/ui/gfx/animation/keyframe/transition.h
index a43b606eafb..d902f918cee 100644
--- a/chromium/ui/gfx/animation/keyframe/transition.h
+++ b/chromium/ui/gfx/animation/keyframe/transition.h
@@ -14,8 +14,13 @@ namespace gfx {
struct GFX_KEYFRAME_ANIMATION_EXPORT Transition {
Transition();
+ Transition(const Transition&);
+ Transition(Transition&&);
~Transition();
+ Transition& operator=(const Transition&) = default;
+ Transition& operator=(Transition&&) = default;
+
base::TimeDelta duration;
std::set<int> target_properties;
};
diff --git a/chromium/ui/gfx/animation/linear_animation.h b/chromium/ui/gfx/animation/linear_animation.h
index 82af66f455a..629778c1bfd 100644
--- a/chromium/ui/gfx/animation/linear_animation.h
+++ b/chromium/ui/gfx/animation/linear_animation.h
@@ -86,4 +86,4 @@ class ANIMATION_EXPORT LinearAnimation : public Animation {
} // namespace gfx
-#endif // APP_LINEAR_ANIMATION_H_
+#endif // UI_GFX_ANIMATION_LINEAR_ANIMATION_H_
diff --git a/chromium/ui/gfx/animation/slide_animation.cc b/chromium/ui/gfx/animation/slide_animation.cc
index 4119168bb94..2659802bfda 100644
--- a/chromium/ui/gfx/animation/slide_animation.cc
+++ b/chromium/ui/gfx/animation/slide_animation.cc
@@ -17,7 +17,7 @@ SlideAnimation::SlideAnimation(AnimationDelegate* target)
SlideAnimation::~SlideAnimation() = default;
void SlideAnimation::Reset(double value) {
- direction_ = base::nullopt;
+ direction_ = absl::nullopt;
value_current_ = value;
Stop();
}
@@ -75,7 +75,7 @@ void SlideAnimation::AnimateToState(double state) {
state =
Tween::CalculateValue(tween_type_, base::ClampToRange(state, 0.0, 1.0));
if (state == 1.0)
- direction_ = base::nullopt;
+ direction_ = absl::nullopt;
value_current_ = value_start_ + (value_end_ - value_start_) * state;
diff --git a/chromium/ui/gfx/animation/slide_animation.h b/chromium/ui/gfx/animation/slide_animation.h
index 94846fbfae5..5b5bea53aa2 100644
--- a/chromium/ui/gfx/animation/slide_animation.h
+++ b/chromium/ui/gfx/animation/slide_animation.h
@@ -6,7 +6,7 @@
#define UI_GFX_ANIMATION_SLIDE_ANIMATION_H_
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/animation/linear_animation.h"
#include "ui/gfx/animation/tween.h"
@@ -109,7 +109,7 @@ class ANIMATION_EXPORT SlideAnimation : public LinearAnimation {
Tween::Type tween_type_ = Tween::EASE_OUT;
// Current animation direction, or nullopt if not animating.
- base::Optional<Direction> direction_;
+ absl::optional<Direction> direction_;
// Animation values. These are a layer on top of Animation::state_ to
// provide the reversability.
diff --git a/chromium/ui/gfx/bidi_line_iterator_unittest.cc b/chromium/ui/gfx/bidi_line_iterator_unittest.cc
index d8dbc51cfd6..73032f2d730 100644
--- a/chromium/ui/gfx/bidi_line_iterator_unittest.cc
+++ b/chromium/ui/gfx/bidi_line_iterator_unittest.cc
@@ -121,9 +121,10 @@ TEST_P(BiDiLineIteratorTest, Mixed) {
TEST_P(BiDiLineIteratorTest, RTLPunctuationNoCustomBehavior) {
// This string features Hebrew characters interleaved with ASCII punctuation.
- iterator()->Open(base::UTF8ToUTF16("א!ב\"ג#ד$ה%ו&ז'ח(ט)י*ך+כ,ל-ם.מ/"
- "ן:נ;ס<ע=ף>פ?ץ@צ[ק\\ר]ש^ת_א`ב{ג|ד}ה~ו"),
- GetParam());
+ iterator()->Open(
+ u"א!ב\"ג#ד$ה%ו&ז'ח(ט)י*ך+כ,ל-ם.מ/"
+ u"ן:נ;ס<ע=ף>פ?ץ@צ[ק\\ר]ש^ת_א`ב{ג|ד}ה~ו",
+ GetParam());
// Expect a single RTL run.
ASSERT_EQ(1, iterator()->CountRuns());
diff --git a/chromium/ui/gfx/buffer_format_util.cc b/chromium/ui/gfx/buffer_format_util.cc
index 85d13030ad4..fac442e87c9 100644
--- a/chromium/ui/gfx/buffer_format_util.cc
+++ b/chromium/ui/gfx/buffer_format_util.cc
@@ -8,6 +8,7 @@
#include "base/notreached.h"
#include "base/numerics/safe_math.h"
#include "base/stl_util.h"
+#include "ui/gfx/switches.h"
namespace gfx {
namespace {
@@ -170,7 +171,7 @@ bool RowSizeForBufferFormatChecked(size_t width,
*size_in_bytes = checked_size.ValueOrDie();
return true;
case BufferFormat::YVU_420:
- DCHECK_EQ(0u, width % 2);
+ DCHECK_EQ(width % 2, 0u);
*size_in_bytes = width / SubsamplingFactorForBufferFormat(format, plane);
return true;
case BufferFormat::YUV_420_BIPLANAR:
@@ -295,4 +296,27 @@ const char* BufferFormatToString(BufferFormat format) {
return "Invalid Format";
}
+const char* BufferPlaneToString(BufferPlane format) {
+ switch (format) {
+ case BufferPlane::DEFAULT:
+ return "DEFAULT";
+ case BufferPlane::Y:
+ return "Y";
+ case BufferPlane::UV:
+ return "UV";
+ case BufferPlane::U:
+ return "U";
+ case BufferPlane::V:
+ return "V";
+ }
+ NOTREACHED() << "Invalid BufferPlane: "
+ << static_cast<typename std::underlying_type<BufferPlane>::type>(
+ format);
+ return "Invalid Plane";
+}
+
+bool AllowOddHeightMultiPlanarBuffers() {
+ return base::FeatureList::IsEnabled(features::kOddHeightMultiPlanarBuffers);
+}
+
} // namespace gfx
diff --git a/chromium/ui/gfx/buffer_format_util.h b/chromium/ui/gfx/buffer_format_util.h
index 14f775bd0c3..a73b264b2fb 100644
--- a/chromium/ui/gfx/buffer_format_util.h
+++ b/chromium/ui/gfx/buffer_format_util.h
@@ -55,6 +55,15 @@ GFX_EXPORT size_t BufferOffsetForBufferFormat(const Size& size,
// Returns the name of |format| as a string.
GFX_EXPORT const char* BufferFormatToString(BufferFormat format);
+// Returns the name of |plane| as a string.
+GFX_EXPORT const char* BufferPlaneToString(BufferPlane plane);
+
+// Multiplanar buffer formats (e.g, YUV_420_BIPLANAR, YVU_420, P010) can be
+// tricky when the size of the primary plane is odd, because the subsampled
+// planes will have a size that is not a divisor of the primary plane's size.
+// This indicates that odd height multiplanar formats are supported.
+GFX_EXPORT bool AllowOddHeightMultiPlanarBuffers();
+
} // namespace gfx
#endif // UI_GFX_BUFFER_FORMAT_UTIL_H_
diff --git a/chromium/ui/gfx/buffer_types.h b/chromium/ui/gfx/buffer_types.h
index fc7e33dcb25..1ae77fc757b 100644
--- a/chromium/ui/gfx/buffer_types.h
+++ b/chromium/ui/gfx/buffer_types.h
@@ -5,6 +5,8 @@
#ifndef UI_GFX_BUFFER_TYPES_H_
#define UI_GFX_BUFFER_TYPES_H_
+#include <stdint.h>
+
#include <tuple>
namespace gfx {
@@ -72,6 +74,26 @@ struct BufferUsageAndFormat {
BufferFormat format;
};
+// Used to identify the plane of a GpuMemoryBuffer to use when creating a
+// SharedImage.
+enum class BufferPlane {
+ // For single-plane GpuMemoryBuffer, this refers to that single plane. For
+ // YUV_420, YUV_420_BIPLANAR, and P010 GpuMemoryBuffers, this refers to an
+ // RGB representation of the planes (either bound directly as a texture or
+ // created through an extra copy).
+ DEFAULT,
+ // The Y plane for YUV_420, YUV_420_BIPLANAR, and P010.
+ Y,
+ // The UV plane for YUV_420_BIPLANAR and P010.
+ UV,
+ // The U plane for YUV_420.
+ U,
+ // The V plane for YUV_420.
+ V,
+
+ LAST = V
+};
+
} // namespace gfx
#endif // UI_GFX_BUFFER_TYPES_H_
diff --git a/chromium/ui/gfx/canvas.cc b/chromium/ui/gfx/canvas.cc
index 0f3e5df81a6..0eb1ba84a5a 100644
--- a/chromium/ui/gfx/canvas.cc
+++ b/chromium/ui/gfx/canvas.cc
@@ -12,6 +12,7 @@
#include "base/numerics/safe_conversions.h"
#include "cc/paint/paint_flags.h"
#include "cc/paint/paint_shader.h"
+#include "cc/paint/skottie_wrapper.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkRefCnt.h"
diff --git a/chromium/ui/gfx/canvas.h b/chromium/ui/gfx/canvas.h
index 16acd944ad4..259d7d3794f 100644
--- a/chromium/ui/gfx/canvas.h
+++ b/chromium/ui/gfx/canvas.h
@@ -12,10 +12,10 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "cc/paint/paint_canvas.h"
#include "cc/paint/paint_flags.h"
#include "cc/paint/skia_paint_canvas.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/text_constants.h"
@@ -457,8 +457,8 @@ class GFX_EXPORT Canvas {
// in which case bitmap_ and owned_canvas_ will be set. Other times we are
// just borrowing someone else's canvas, in which case canvas_ will point
// there but bitmap_ and owned_canvas_ will not exist.
- base::Optional<SkBitmap> bitmap_;
- base::Optional<cc::SkiaPaintCanvas> owned_canvas_;
+ absl::optional<SkBitmap> bitmap_;
+ absl::optional<cc::SkiaPaintCanvas> owned_canvas_;
cc::PaintCanvas* canvas_;
DISALLOW_COPY_AND_ASSIGN(Canvas);
diff --git a/chromium/ui/gfx/codec/vector_wstream.h b/chromium/ui/gfx/codec/vector_wstream.h
index 56f9712a6d6..b740e7e4dfe 100644
--- a/chromium/ui/gfx/codec/vector_wstream.h
+++ b/chromium/ui/gfx/codec/vector_wstream.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_GFX_VECTOR_WSTREAM_CODEC_H_
-#define UI_GFX_VECTOR_WSTREAM_CODEC_H_
+#ifndef UI_GFX_CODEC_VECTOR_WSTREAM_H_
+#define UI_GFX_CODEC_VECTOR_WSTREAM_H_
#include <stddef.h>
@@ -33,4 +33,4 @@ class VectorWStream : public SkWStream {
} // namespace gfx
-#endif // UI_GFX_VECTOR_WSTREAM_H_
+#endif // UI_GFX_CODEC_VECTOR_WSTREAM_H_
diff --git a/chromium/ui/gfx/color_analysis.cc b/chromium/ui/gfx/color_analysis.cc
index 5033a77232e..e317841032c 100644
--- a/chromium/ui/gfx/color_analysis.cc
+++ b/chromium/ui/gfx/color_analysis.cc
@@ -345,7 +345,7 @@ std::vector<Swatch> CalculateProminentColors(
const SkBitmap& bitmap,
const std::vector<ColorBracket>& color_brackets,
const gfx::Rect& region,
- base::Optional<ColorSwatchFilter> filter) {
+ absl::optional<ColorSwatchFilter> filter) {
DCHECK(!bitmap.empty());
DCHECK(!bitmap.isNull());
@@ -679,7 +679,7 @@ std::vector<Swatch> CalculateColorSwatches(
const SkBitmap& bitmap,
size_t max_swatches,
const gfx::Rect& region,
- base::Optional<ColorSwatchFilter> filter) {
+ absl::optional<ColorSwatchFilter> filter) {
DCHECK(!bitmap.empty());
DCHECK(!bitmap.isNull());
DCHECK(!region.IsEmpty());
diff --git a/chromium/ui/gfx/color_analysis.h b/chromium/ui/gfx/color_analysis.h
index 92c185fa43c..fdaa8f35dea 100644
--- a/chromium/ui/gfx/color_analysis.h
+++ b/chromium/ui/gfx/color_analysis.h
@@ -178,7 +178,7 @@ GFX_EXPORT std::vector<Swatch> CalculateColorSwatches(
const SkBitmap& bitmap,
size_t max_swatches,
const gfx::Rect& region,
- base::Optional<ColorSwatchFilter> filter);
+ absl::optional<ColorSwatchFilter> filter);
// Returns a vector of RGB colors that represents the bitmap based on the
// |color_profiles| provided. For each value, if a value is succesfully
diff --git a/chromium/ui/gfx/color_analysis_unittest.cc b/chromium/ui/gfx/color_analysis_unittest.cc
index 8da4aba8e87..bbf1e877d58 100644
--- a/chromium/ui/gfx/color_analysis_unittest.cc
+++ b/chromium/ui/gfx/color_analysis_unittest.cc
@@ -566,7 +566,7 @@ TEST_F(ColorAnalysisTest, ComputeColorSwatches) {
{
std::vector<Swatch> colors =
- CalculateColorSwatches(bitmap, 10, gfx::Rect(100, 100), base::nullopt);
+ CalculateColorSwatches(bitmap, 10, gfx::Rect(100, 100), absl::nullopt);
EXPECT_EQ(3u, colors.size());
EXPECT_EQ(kGreenSwatch, colors[0]);
EXPECT_EQ(kMagentaSwatch, colors[1]);
@@ -575,7 +575,7 @@ TEST_F(ColorAnalysisTest, ComputeColorSwatches) {
{
std::vector<Swatch> colors = CalculateColorSwatches(
- bitmap, 10, gfx::Rect(10, 10, 80, 80), base::nullopt);
+ bitmap, 10, gfx::Rect(10, 10, 80, 80), absl::nullopt);
EXPECT_EQ(2u, colors.size());
EXPECT_EQ(kGreenSwatch, colors[0]);
EXPECT_EQ(kYellowSwatch, colors[1]);
@@ -609,7 +609,7 @@ TEST_F(ColorAnalysisTest, ComputeColorSwatches_Filter) {
{
std::vector<Swatch> colors =
- CalculateColorSwatches(bitmap, 10, gfx::Rect(100, 100), base::nullopt);
+ CalculateColorSwatches(bitmap, 10, gfx::Rect(100, 100), absl::nullopt);
EXPECT_EQ(3u, colors.size());
EXPECT_EQ(kBlackSwatch, colors[0]);
EXPECT_EQ(kMagentaSwatch, colors[1]);
diff --git a/chromium/ui/gfx/color_space.h b/chromium/ui/gfx/color_space.h
index 464b747579d..6b43b903cf6 100644
--- a/chromium/ui/gfx/color_space.h
+++ b/chromium/ui/gfx/color_space.h
@@ -7,18 +7,20 @@
#include <stdint.h>
-#include <ostream>
+#include <iosfwd>
#include <string>
-#include <vector>
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "build/build_config.h"
-#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkImageInfo.h"
-#include "third_party/skia/include/core/SkMatrix44.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
#include "ui/gfx/color_space_export.h"
+struct skcms_Matrix3x3;
+struct skcms_TransferFunction;
+class SkColorSpace;
+class SkMatrix44;
+
// These forward declarations are used to give IPC code friend access to private
// fields of gfx::ColorSpace for the purpose of serialization and
// deserialization.
diff --git a/chromium/ui/gfx/color_space_win.h b/chromium/ui/gfx/color_space_win.h
index 734ab3d5e07..1c718915e17 100644
--- a/chromium/ui/gfx/color_space_win.h
+++ b/chromium/ui/gfx/color_space_win.h
@@ -44,4 +44,4 @@ class COLOR_SPACE_EXPORT ColorSpaceWin {
};
} // namespace gfx
-#endif
+#endif // UI_GFX_COLOR_SPACE_WIN_H_
diff --git a/chromium/ui/gfx/color_transform_unittest.cc b/chromium/ui/gfx/color_transform_unittest.cc
index f576087850e..23d6a6f347c 100644
--- a/chromium/ui/gfx/color_transform_unittest.cc
+++ b/chromium/ui/gfx/color_transform_unittest.cc
@@ -562,11 +562,9 @@ TEST(SimpleColorSpace, CanParseSkShaderSource) {
auto transform = ColorTransform::NewColorTransform(
src, dst, ColorTransform::Intent::INTENT_PERCEPTUAL);
std::string source =
- "uniform shader child;\n"
- "half4 main() {\n"
- " half4 color = sample(child);\n" +
+ "half4 main(half4 color) {\n" +
transform->GetSkShaderSource() + " return color; }";
- SkRuntimeEffect::Result result = SkRuntimeEffect::Make(
+ SkRuntimeEffect::Result result = SkRuntimeEffect::MakeForColorFilter(
SkString(source.c_str(), source.length()), /*options=*/{});
EXPECT_NE(result.effect, nullptr);
EXPECT_STREQ(result.errorText.c_str(), "");
diff --git a/chromium/ui/gfx/color_utils.cc b/chromium/ui/gfx/color_utils.cc
index c4e41658b4e..98494103346 100644
--- a/chromium/ui/gfx/color_utils.cc
+++ b/chromium/ui/gfx/color_utils.cc
@@ -234,28 +234,6 @@ SkColor HSLShift(SkColor color, const HSL& shift) {
base::ClampRound<U8CPU>(g), base::ClampRound<U8CPU>(b));
}
-void BuildLumaHistogram(const SkBitmap& bitmap, int histogram[256]) {
- DCHECK_EQ(kN32_SkColorType, bitmap.colorType());
-
- int pixel_width = bitmap.width();
- int pixel_height = bitmap.height();
- for (int y = 0; y < pixel_height; ++y) {
- for (int x = 0; x < pixel_width; ++x)
- ++histogram[GetLuma(bitmap.getColor(x, y))];
- }
-}
-
-double CalculateBoringScore(const SkBitmap& bitmap) {
- if (bitmap.isNull() || bitmap.empty())
- return 1.0;
- int histogram[256] = {0};
- BuildLumaHistogram(bitmap, histogram);
-
- int color_count = *std::max_element(histogram, histogram + 256);
- int pixel_count = bitmap.width() * bitmap.height();
- return static_cast<double>(color_count) / pixel_count;
-}
-
SkColor AlphaBlend(SkColor foreground, SkColor background, SkAlpha alpha) {
return AlphaBlend(foreground, background, alpha / 255.0f);
}
@@ -329,7 +307,7 @@ SkColor PickContrastingColor(SkColor foreground1,
BlendResult BlendForMinContrast(
SkColor default_foreground,
SkColor background,
- base::Optional<SkColor> high_contrast_foreground,
+ absl::optional<SkColor> high_contrast_foreground,
float contrast_ratio) {
DCHECK_EQ(SkColorGetA(background), SK_AlphaOPAQUE);
default_foreground = GetResultingPaintColor(default_foreground, background);
diff --git a/chromium/ui/gfx/color_utils.h b/chromium/ui/gfx/color_utils.h
index 94ab366f157..64031d8e247 100644
--- a/chromium/ui/gfx/color_utils.h
+++ b/chromium/ui/gfx/color_utils.h
@@ -8,12 +8,10 @@
#include <string>
#include <tuple>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/gfx_export.h"
-class SkBitmap;
-
namespace color_utils {
// Represents an HSL color.
@@ -98,15 +96,6 @@ GFX_EXPORT bool IsHSLShiftMeaningful(const HSL& hsl);
// 1 = full lightness (make all pixels white).
GFX_EXPORT SkColor HSLShift(SkColor color, const HSL& shift);
-// Builds a histogram based on the Y' of the Y'UV representation of this image.
-GFX_EXPORT void BuildLumaHistogram(const SkBitmap& bitmap, int histogram[256]);
-
-// Calculates how "boring" an image is. The boring score is the
-// 0,1 ranged percentage of pixels that are the most common
-// luma. Higher boring scores indicate that a higher percentage of a
-// bitmap are all the same brightness.
-GFX_EXPORT double CalculateBoringScore(const SkBitmap& bitmap);
-
// Returns a blend of the supplied colors, ranging from |background| (for
// |alpha| == 0) to |foreground| (for |alpha| == 255). The alpha channels of
// the supplied colors are also taken into account, so the returned color may
@@ -156,7 +145,7 @@ GFX_EXPORT SkColor PickContrastingColor(SkColor foreground1,
GFX_EXPORT BlendResult BlendForMinContrast(
SkColor default_foreground,
SkColor background,
- base::Optional<SkColor> high_contrast_foreground = base::nullopt,
+ absl::optional<SkColor> high_contrast_foreground = absl::nullopt,
float contrast_ratio = kMinimumReadableContrastRatio);
// Invert a color.
diff --git a/chromium/ui/gfx/color_utils_unittest.cc b/chromium/ui/gfx/color_utils_unittest.cc
index 8159ab3d69f..446a77256f0 100644
--- a/chromium/ui/gfx/color_utils_unittest.cc
+++ b/chromium/ui/gfx/color_utils_unittest.cc
@@ -144,39 +144,6 @@ TEST(ColorUtils, ColorToHSLRegisterSpill) {
EXPECT_EQ(SkColorGetB(input), SkColorGetB(result));
}
-TEST(ColorUtils, CalculateBoringScore_Empty) {
- SkBitmap bitmap;
- EXPECT_DOUBLE_EQ(1.0, CalculateBoringScore(bitmap));
-}
-
-TEST(ColorUtils, CalculateBoringScore_SingleColor) {
- const gfx::Size kSize(20, 10);
- gfx::Canvas canvas(kSize, 1.0f, true);
- // Fill all pixels in black.
- canvas.FillRect(gfx::Rect(kSize), SK_ColorBLACK);
-
- SkBitmap bitmap = canvas.GetBitmap();
- // The thumbnail should deserve the highest boring score.
- EXPECT_DOUBLE_EQ(1.0, CalculateBoringScore(bitmap));
-}
-
-TEST(ColorUtils, CalculateBoringScore_TwoColors) {
- const gfx::Size kSize(20, 10);
-
- gfx::Canvas canvas(kSize, 1.0f, true);
- // Fill all pixels in black.
- canvas.FillRect(gfx::Rect(kSize), SK_ColorBLACK);
- // Fill the left half pixels in white.
- canvas.FillRect(gfx::Rect(0, 0, kSize.width() / 2, kSize.height()),
- SK_ColorWHITE);
-
- SkBitmap bitmap = canvas.GetBitmap();
- ASSERT_EQ(kSize.width(), bitmap.width());
- ASSERT_EQ(kSize.height(), bitmap.height());
- // The thumbnail should be less boring because two colors are used.
- EXPECT_DOUBLE_EQ(0.5, CalculateBoringScore(bitmap));
-}
-
TEST(ColorUtils, AlphaBlend) {
SkColor fore = SkColorSetARGB(255, 200, 200, 200);
SkColor back = SkColorSetARGB(255, 100, 100, 100);
diff --git a/chromium/ui/gfx/display_color_spaces.h b/chromium/ui/gfx/display_color_spaces.h
index 0df06e17965..9b443ef5623 100644
--- a/chromium/ui/gfx/display_color_spaces.h
+++ b/chromium/ui/gfx/display_color_spaces.h
@@ -6,6 +6,7 @@
#define UI_GFX_DISPLAY_COLOR_SPACES_H_
#include <string>
+#include <vector>
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/color_space.h"
diff --git a/chromium/ui/gfx/font_fallback_mac.mm b/chromium/ui/gfx/font_fallback_mac.mm
index 2dedccc7069..aee22499ca2 100644
--- a/chromium/ui/gfx/font_fallback_mac.mm
+++ b/chromium/ui/gfx/font_fallback_mac.mm
@@ -88,7 +88,7 @@ bool GetFallbackFont(const Font& font,
// font handles and is not guaranteed to result in the correct typeface, see
// https://crbug.com/1003829
*result = Font(PlatformFont::CreateFromSkTypeface(
- std::move(fallback_typeface), font.GetFontSize(), base::nullopt));
+ std::move(fallback_typeface), font.GetFontSize(), absl::nullopt));
return true;
}
diff --git a/chromium/ui/gfx/font_fallback_skia.cc b/chromium/ui/gfx/font_fallback_skia.cc
index 8215122a507..29a5cc0216c 100644
--- a/chromium/ui/gfx/font_fallback_skia.cc
+++ b/chromium/ui/gfx/font_fallback_skia.cc
@@ -7,10 +7,10 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/font.h"
#include "ui/gfx/font_fallback_skia_impl.h"
#include "ui/gfx/font_render_params.h"
@@ -42,7 +42,7 @@ bool GetFallbackFont(const Font& font,
// font handles and is not guaranteed to result in the correct typeface, see
// https://crbug.com/1003829
*result = Font(PlatformFont::CreateFromSkTypeface(
- std::move(fallback_typeface), font.GetFontSize(), base::nullopt));
+ std::move(fallback_typeface), font.GetFontSize(), absl::nullopt));
return true;
}
diff --git a/chromium/ui/gfx/font_fallback_win.cc b/chromium/ui/gfx/font_fallback_win.cc
index b07343805a0..4674258aee6 100644
--- a/chromium/ui/gfx/font_fallback_win.cc
+++ b/chromium/ui/gfx/font_fallback_win.cc
@@ -11,7 +11,6 @@
#include "base/memory/singleton.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/current_thread.h"
#include "base/trace_event/trace_event.h"
@@ -239,7 +238,7 @@ bool GetFallbackFont(const Font& font,
// font handles and is not guaranteed to result in the correct typeface, see
// https://crbug.com/1003829
*result = Font(PlatformFont::CreateFromSkTypeface(
- std::move(fallback_typeface), font.GetFontSize(), base::nullopt));
+ std::move(fallback_typeface), font.GetFontSize(), absl::nullopt));
return true;
}
diff --git a/chromium/ui/gfx/font_list.h b/chromium/ui/gfx/font_list.h
index e2c30725e2f..a0d96fae610 100644
--- a/chromium/ui/gfx/font_list.h
+++ b/chromium/ui/gfx/font_list.h
@@ -83,6 +83,10 @@ class GFX_EXPORT FontList {
//
// ui::ResourceBundle may call this function more than once when UI language
// is changed.
+ //
+ // Unit Tests should use ScopedDefaultFontDescription instead of calling this
+ // directly, to avoid leaving the default font description in an unexpected
+ // state for tests that run in the same process.
static void SetDefaultFontDescription(const std::string& font_description);
// Returns a new FontList with the same font names but resized and the given
diff --git a/chromium/ui/gfx/font_names_testing.h b/chromium/ui/gfx/font_names_testing.h
index 85a66c3323e..b4f7a9a69f8 100644
--- a/chromium/ui/gfx/font_names_testing.h
+++ b/chromium/ui/gfx/font_names_testing.h
@@ -13,4 +13,4 @@ extern const char kCJKFontName[];
} // end namespace gfx
-#endif
+#endif // UI_GFX_FONT_NAMES_TESTING_H_
diff --git a/chromium/ui/gfx/font_render_params_linux.cc b/chromium/ui/gfx/font_render_params_linux.cc
index 3ab8b2ed3ee..7e42a2e0e2b 100644
--- a/chromium/ui/gfx/font_render_params_linux.cc
+++ b/chromium/ui/gfx/font_render_params_linux.cc
@@ -12,7 +12,6 @@
#include "base/command_line.h"
#include "base/containers/mru_cache.h"
-#include "base/hash/hash.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
@@ -90,7 +89,7 @@ struct QueryResult {
// Keyed by hashes of FontRenderParamQuery structs from
// HashFontRenderParamsQuery().
-typedef base::MRUCache<uint32_t, QueryResult> Cache;
+typedef base::HashingMRUCache<std::string, QueryResult> Cache;
// A cache and the lock that must be held while accessing it.
// GetFontRenderParams() is called by both the UI thread and the sandbox IPC
@@ -173,14 +172,12 @@ bool QueryFontconfig(const FontRenderParamsQuery& query,
return true;
}
-// Serialize |query| into a string and hash it to a value suitable for use as a
-// cache key.
-uint32_t HashFontRenderParamsQuery(const FontRenderParamsQuery& query) {
- return base::Hash(base::StringPrintf(
+// Serialize |query| into a string value suitable for use as a cache key.
+std::string GetFontRenderParamsQueryKey(const FontRenderParamsQuery& query) {
+ return base::StringPrintf(
"%d|%d|%d|%d|%s|%f", query.pixel_size, query.point_size, query.style,
static_cast<int>(query.weight),
- base::JoinString(query.families, ",").c_str(),
- query.device_scale_factor));
+ base::JoinString(query.families, ",").c_str(), query.device_scale_factor);
}
} // namespace
@@ -193,15 +190,15 @@ FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query,
if (actual_query.device_scale_factor == 0)
actual_query.device_scale_factor = device_scale_factor_;
- const uint32_t hash = HashFontRenderParamsQuery(actual_query);
+ std::string query_key = GetFontRenderParamsQueryKey(actual_query);
SynchronizedCache* synchronized_cache = g_synchronized_cache.Pointer();
{
// Try to find a cached result so Fontconfig doesn't need to be queried.
base::AutoLock lock(synchronized_cache->lock);
- Cache::const_iterator it = synchronized_cache->cache.Get(hash);
+ Cache::const_iterator it = synchronized_cache->cache.Get(query_key);
if (it != synchronized_cache->cache.end()) {
- DVLOG(1) << "Returning cached params for " << hash;
+ DVLOG(1) << "Returning cached params for " << query_key;
const QueryResult& result = it->second;
if (family_out)
*family_out = result.family;
@@ -209,7 +206,7 @@ FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query,
}
}
- DVLOG(1) << "Computing params for " << hash;
+ DVLOG(1) << "Computing params for " << query_key;
if (family_out)
family_out->clear();
@@ -251,7 +248,8 @@ FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query,
// Store the result. It's fine if this overwrites a result that was cached
// by a different thread in the meantime; the values should be identical.
base::AutoLock lock(synchronized_cache->lock);
- synchronized_cache->cache.Put(hash,
+ synchronized_cache->cache.Put(
+ query_key,
QueryResult(params, family_out ? *family_out : std::string()));
}
diff --git a/chromium/ui/gfx/gdi_util.h b/chromium/ui/gfx/gdi_util.h
index e8e8f0e7bae..5b9af51bcf5 100644
--- a/chromium/ui/gfx/gdi_util.h
+++ b/chromium/ui/gfx/gdi_util.h
@@ -6,7 +6,6 @@
#define UI_GFX_GDI_UTIL_H_
#include <windows.h>
-#include <vector>
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/gfx_export.h"
diff --git a/chromium/ui/gfx/geometry/axis_transform2d.cc b/chromium/ui/gfx/geometry/axis_transform2d.cc
index 5b7d86a4507..fb2bb423401 100644
--- a/chromium/ui/gfx/geometry/axis_transform2d.cc
+++ b/chromium/ui/gfx/geometry/axis_transform2d.cc
@@ -9,7 +9,7 @@
namespace gfx {
std::string AxisTransform2d::ToString() const {
- return base::StringPrintf("[%f, %s]", scale_,
+ return base::StringPrintf("[%s, %s]", scale_.ToString().c_str(),
translation_.ToString().c_str());
}
diff --git a/chromium/ui/gfx/geometry/axis_transform2d.h b/chromium/ui/gfx/geometry/axis_transform2d.h
index 57b45ac9d22..3e74fca46eb 100644
--- a/chromium/ui/gfx/geometry/axis_transform2d.h
+++ b/chromium/ui/gfx/geometry/axis_transform2d.h
@@ -5,6 +5,7 @@
#ifndef UI_GFX_GEOMETRY_AXIS_TRANSFORM2D_H_
#define UI_GFX_GEOMETRY_AXIS_TRANSFORM2D_H_
+#include "base/check_op.h"
#include "ui/gfx/geometry/geometry_export.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
@@ -13,13 +14,16 @@ namespace gfx {
// This class implements the subset of 2D linear transforms that only
// translation and uniform scaling are allowed.
-// Internally this is stored as a scalar pre-scale factor, and a vector
+// Internally this is stored as a vector for pre-scale, and another vector
// for post-translation. The class constructor and member accessor follows
-// the same convention.
+// the same convention, but a scalar scale factor is also accepted.
class GEOMETRY_EXPORT AxisTransform2d {
public:
constexpr AxisTransform2d() = default;
constexpr AxisTransform2d(float scale, const Vector2dF& translation)
+ : scale_(scale, scale), translation_(translation) {}
+ constexpr AxisTransform2d(const Vector2dF& scale,
+ const Vector2dF& translation)
: scale_(scale), translation_(translation) {}
bool operator==(const AxisTransform2d& other) const {
@@ -29,13 +33,13 @@ class GEOMETRY_EXPORT AxisTransform2d {
return !(*this == other);
}
- void PreScale(float scale) { scale_ *= scale; }
- void PostScale(float scale) {
- scale_ *= scale;
- translation_.Scale(scale);
+ void PreScale(const Vector2dF& scale) { scale_.Scale(scale.x(), scale.y()); }
+ void PostScale(const Vector2dF& scale) {
+ scale_.Scale(scale.x(), scale.y());
+ translation_.Scale(scale.x(), scale.y());
}
void PreTranslate(const Vector2dF& translation) {
- translation_ += ScaleVector2d(translation, scale_);
+ translation_ += ScaleVector2d(translation, scale_.x(), scale_.y());
}
void PostTranslate(const Vector2dF& translation) {
translation_ += translation;
@@ -51,28 +55,31 @@ class GEOMETRY_EXPORT AxisTransform2d {
}
void Invert() {
- DCHECK(scale_);
- scale_ = 1.f / scale_;
- translation_.Scale(-scale_);
+ DCHECK(scale_.x());
+ DCHECK(scale_.y());
+ scale_ = Vector2dF(1.f / scale_.x(), 1.f / scale_.y());
+ translation_.Scale(-scale_.x(), -scale_.y());
}
PointF MapPoint(const PointF& p) const {
- return ScalePoint(p, scale_) + translation_;
+ return ScalePoint(p, scale_.x(), scale_.y()) + translation_;
}
PointF InverseMapPoint(const PointF& p) const {
- return ScalePoint(p - translation_, 1.f / scale_);
+ return ScalePoint(p - translation_, 1.f / scale_.x(), 1.f / scale_.y());
}
RectF MapRect(const RectF& r) const {
- DCHECK(scale_ >= 0.f);
- return ScaleRect(r, scale_) + translation_;
+ DCHECK_GE(scale_.x(), 0.f);
+ DCHECK_GE(scale_.y(), 0.f);
+ return ScaleRect(r, scale_.x(), scale_.y()) + translation_;
}
RectF InverseMapRect(const RectF& r) const {
- DCHECK(scale_ > 0.f);
- return ScaleRect(r - translation_, 1.f / scale_);
+ DCHECK_GT(scale_.x(), 0.f);
+ DCHECK_GT(scale_.y(), 0.f);
+ return ScaleRect(r - translation_, 1.f / scale_.x(), 1.f / scale_.y());
}
- float scale() const { return scale_; }
+ const Vector2dF& scale() const { return scale_; }
const Vector2dF& translation() const { return translation_; }
std::string ToString() const;
@@ -80,21 +87,21 @@ class GEOMETRY_EXPORT AxisTransform2d {
private:
// Scale is applied before translation, i.e.
// this->Transform(p) == scale_ * p + translation_
- float scale_ = 1.f;
+ Vector2dF scale_{1.f, 1.f};
Vector2dF translation_;
};
inline AxisTransform2d PreScaleAxisTransform2d(const AxisTransform2d& t,
float scale) {
AxisTransform2d result(t);
- result.PreScale(scale);
+ result.PreScale(Vector2dF(scale, scale));
return result;
}
inline AxisTransform2d PostScaleAxisTransform2d(const AxisTransform2d& t,
float scale) {
AxisTransform2d result(t);
- result.PostScale(scale);
+ result.PostScale(Vector2dF(scale, scale));
return result;
}
diff --git a/chromium/ui/gfx/geometry/axis_transform2d_unittest.cc b/chromium/ui/gfx/geometry/axis_transform2d_unittest.cc
index b132c69635f..6bee3da50a4 100644
--- a/chromium/ui/gfx/geometry/axis_transform2d_unittest.cc
+++ b/chromium/ui/gfx/geometry/axis_transform2d_unittest.cc
@@ -27,7 +27,7 @@ TEST(AxisTransform2dTest, Scaling) {
AxisTransform2d t(1.25f, Vector2dF(3.75f, 55.f));
EXPECT_EQ(AxisTransform2d(1.5625f, Vector2dF(3.75f, 55.f)),
PreScaleAxisTransform2d(t, 1.25));
- t.PreScale(1.25);
+ t.PreScale(Vector2dF(1.25f, 1.25f));
EXPECT_EQ(AxisTransform2d(1.5625f, Vector2dF(3.75f, 55.f)), t);
}
@@ -35,7 +35,7 @@ TEST(AxisTransform2dTest, Scaling) {
AxisTransform2d t(1.25f, Vector2dF(3.75f, 55.f));
EXPECT_EQ(AxisTransform2d(1.5625f, Vector2dF(4.6875f, 68.75f)),
PostScaleAxisTransform2d(t, 1.25));
- t.PostScale(1.25);
+ t.PostScale(Vector2dF(1.25f, 1.25f));
EXPECT_EQ(AxisTransform2d(1.5625f, Vector2dF(4.6875f, 68.75f)), t);
}
}
diff --git a/chromium/ui/gfx/geometry/mojom/geometry.mojom b/chromium/ui/gfx/geometry/mojom/geometry.mojom
index 30c19923797..a21cc11158c 100644
--- a/chromium/ui/gfx/geometry/mojom/geometry.mojom
+++ b/chromium/ui/gfx/geometry/mojom/geometry.mojom
@@ -48,6 +48,7 @@ struct RectF {
float height;
};
+[Stable]
struct Insets {
int32 top;
int32 left;
diff --git a/chromium/ui/gfx/geometry/point.cc b/chromium/ui/gfx/geometry/point.cc
index 0307b2fa885..1d2c19687be 100644
--- a/chromium/ui/gfx/geometry/point.cc
+++ b/chromium/ui/gfx/geometry/point.cc
@@ -13,7 +13,7 @@
#include <windows.h>
#elif defined(OS_IOS)
#include <CoreGraphics/CoreGraphics.h>
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
#include <ApplicationServices/ApplicationServices.h>
#endif
diff --git a/chromium/ui/gfx/geometry/quaternion.h b/chromium/ui/gfx/geometry/quaternion.h
index d7789568145..8081881f0a3 100644
--- a/chromium/ui/gfx/geometry/quaternion.h
+++ b/chromium/ui/gfx/geometry/quaternion.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_GFX_GEOMETRY_QUATERNION_
-#define UI_GFX_GEOMETRY_QUATERNION_
+#ifndef UI_GFX_GEOMETRY_QUATERNION_H_
+#define UI_GFX_GEOMETRY_QUATERNION_H_
#include <string>
@@ -92,6 +92,18 @@ inline Quaternion operator/(const Quaternion& q, double s) {
return q * inv;
}
+// Returns true if the x, y, z, w values of |lhs| and |rhs| are equal. Note that
+// two quaternions can represent the same orientation with different values.
+// This operator will return false in that scenario.
+inline bool operator==(const Quaternion& lhs, const Quaternion& rhs) {
+ return lhs.x() == rhs.x() && lhs.y() == rhs.y() && lhs.z() == rhs.z() &&
+ lhs.w() == rhs.w();
+}
+
+inline bool operator!=(const Quaternion& lhs, const Quaternion& rhs) {
+ return !(lhs == rhs);
+}
+
} // namespace gfx
-#endif // UI_GFX_GEOMETRY_QUATERNION_
+#endif // UI_GFX_GEOMETRY_QUATERNION_H_
diff --git a/chromium/ui/gfx/geometry/quaternion_unittest.cc b/chromium/ui/gfx/geometry/quaternion_unittest.cc
index 1e43d2aaeb2..ecacaf1346f 100644
--- a/chromium/ui/gfx/geometry/quaternion_unittest.cc
+++ b/chromium/ui/gfx/geometry/quaternion_unittest.cc
@@ -213,4 +213,25 @@ TEST(QuatTest, SlerpObtuseAngle) {
EXPECT_QUATERNION(expected, interpolated);
}
+TEST(QuatTest, Equals) {
+ EXPECT_TRUE(Quaternion() == Quaternion());
+ EXPECT_TRUE(Quaternion() == Quaternion(0, 0, 0, 1));
+ EXPECT_TRUE(Quaternion(1, 5.2, -8.5, 222.2) ==
+ Quaternion(1, 5.2, -8.5, 222.2));
+ EXPECT_FALSE(Quaternion() == Quaternion(1, 0, 0, 0));
+ EXPECT_FALSE(Quaternion() == Quaternion(0, 1, 0, 0));
+ EXPECT_FALSE(Quaternion() == Quaternion(0, 0, 1, 0));
+ EXPECT_FALSE(Quaternion() == Quaternion(1, 0, 0, 1));
+}
+
+TEST(QuatTest, NotEquals) {
+ EXPECT_FALSE(Quaternion() != Quaternion());
+ EXPECT_FALSE(Quaternion(1, 5.2, -8.5, 222.2) !=
+ Quaternion(1, 5.2, -8.5, 222.2));
+ EXPECT_TRUE(Quaternion() != Quaternion(1, 0, 0, 0));
+ EXPECT_TRUE(Quaternion() != Quaternion(0, 1, 0, 0));
+ EXPECT_TRUE(Quaternion() != Quaternion(0, 0, 1, 0));
+ EXPECT_TRUE(Quaternion() != Quaternion(1, 0, 0, 1));
+}
+
} // namespace gfx
diff --git a/chromium/ui/gfx/geometry/rect.cc b/chromium/ui/gfx/geometry/rect.cc
index 370fe34565e..c28a2260936 100644
--- a/chromium/ui/gfx/geometry/rect.cc
+++ b/chromium/ui/gfx/geometry/rect.cc
@@ -10,7 +10,7 @@
#include <windows.h>
#elif defined(OS_IOS)
#include <CoreGraphics/CoreGraphics.h>
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
#include <ApplicationServices/ApplicationServices.h>
#endif
diff --git a/chromium/ui/gfx/geometry/rect_f.cc b/chromium/ui/gfx/geometry/rect_f.cc
index 0250709923a..c8dafe2ed54 100644
--- a/chromium/ui/gfx/geometry/rect_f.cc
+++ b/chromium/ui/gfx/geometry/rect_f.cc
@@ -15,7 +15,7 @@
#if defined(OS_IOS)
#include <CoreGraphics/CoreGraphics.h>
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
#include <ApplicationServices/ApplicationServices.h>
#endif
diff --git a/chromium/ui/gfx/geometry/size.cc b/chromium/ui/gfx/geometry/size.cc
index bebcd33eedd..a7e330cd353 100644
--- a/chromium/ui/gfx/geometry/size.cc
+++ b/chromium/ui/gfx/geometry/size.cc
@@ -8,7 +8,7 @@
#include <windows.h>
#elif defined(OS_IOS)
#include <CoreGraphics/CoreGraphics.h>
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
#include <ApplicationServices/ApplicationServices.h>
#endif
diff --git a/chromium/ui/gfx/gpu_extra_info.h b/chromium/ui/gfx/gpu_extra_info.h
index 98234d2f2e0..c8951450003 100644
--- a/chromium/ui/gfx/gpu_extra_info.h
+++ b/chromium/ui/gfx/gpu_extra_info.h
@@ -66,9 +66,6 @@ struct GFX_EXPORT GpuExtraInfo {
ANGLEFeatures angle_features;
#if defined(USE_X11) || defined(USE_OZONE_PLATFORM_X11)
- x11::VisualId system_visual{};
- x11::VisualId rgba_visual{};
-
std::vector<gfx::BufferUsageAndFormat> gpu_memory_buffer_support_x11;
#endif
};
diff --git a/chromium/ui/gfx/gpu_fence.h b/chromium/ui/gfx/gpu_fence.h
index 7401b48d91c..682a717f24e 100644
--- a/chromium/ui/gfx/gpu_fence.h
+++ b/chromium/ui/gfx/gpu_fence.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_GL_GPU_FENCE_H_
-#define UI_GL_GPU_FENCE_H_
+#ifndef UI_GFX_GPU_FENCE_H_
+#define UI_GFX_GPU_FENCE_H_
#include "base/macros.h"
#include "build/build_config.h"
@@ -54,4 +54,4 @@ class GFX_EXPORT GpuFence {
} // namespace gfx
-#endif // UI_GL_GPU_FENCE_H_
+#endif // UI_GFX_GPU_FENCE_H_
diff --git a/chromium/ui/gfx/gpu_fence_handle.cc b/chromium/ui/gfx/gpu_fence_handle.cc
index c8d719bf004..85a6e5b98ff 100644
--- a/chromium/ui/gfx/gpu_fence_handle.cc
+++ b/chromium/ui/gfx/gpu_fence_handle.cc
@@ -45,6 +45,9 @@ bool GpuFenceHandle::is_null() const {
}
GpuFenceHandle GpuFenceHandle::Clone() const {
+ if (is_null())
+ return GpuFenceHandle();
+
gfx::GpuFenceHandle handle;
#if defined(OS_POSIX)
const int duped_handle = HANDLE_EINTR(dup(owned_fd.get()));
diff --git a/chromium/ui/gfx/gpu_memory_buffer.cc b/chromium/ui/gfx/gpu_memory_buffer.cc
index 44b2667960d..6eb367451dc 100644
--- a/chromium/ui/gfx/gpu_memory_buffer.cc
+++ b/chromium/ui/gfx/gpu_memory_buffer.cc
@@ -65,6 +65,18 @@ GpuMemoryBufferHandle GpuMemoryBufferHandle::Clone() const {
return handle;
}
+Size GpuMemoryBuffer::GetSizeOfPlane(gfx::BufferPlane plane) const {
+ switch (plane) {
+ case gfx::BufferPlane::DEFAULT:
+ case gfx::BufferPlane::Y:
+ return GetSize();
+ case gfx::BufferPlane::UV:
+ case gfx::BufferPlane::U:
+ case gfx::BufferPlane::V:
+ return ScaleToFlooredSize(GetSize(), 0.5);
+ }
+}
+
void GpuMemoryBuffer::SetColorSpace(const ColorSpace& color_space) {}
void GpuMemoryBuffer::SetHDRMetadata(const HDRMetadata& hdr_metadata) {}
diff --git a/chromium/ui/gfx/gpu_memory_buffer.h b/chromium/ui/gfx/gpu_memory_buffer.h
index c3a1f813ca3..9cf5f37e874 100644
--- a/chromium/ui/gfx/gpu_memory_buffer.h
+++ b/chromium/ui/gfx/gpu_memory_buffer.h
@@ -102,12 +102,15 @@ class GFX_EXPORT GpuMemoryBuffer {
// after this has been called.
virtual void Unmap() = 0;
- // Returns the size for the buffer.
+ // Returns the size in pixels of the first plane of the buffer.
virtual Size GetSize() const = 0;
// Returns the format for the buffer.
virtual BufferFormat GetFormat() const = 0;
+ // Returns the size in pixels of the specified plane.
+ Size GetSizeOfPlane(gfx::BufferPlane plane) const;
+
// Fills the stride in bytes for each plane of the buffer. The stride of
// plane K is stored at index K-1 of the |stride| array.
virtual int stride(size_t plane) const = 0;
diff --git a/chromium/ui/gfx/half_float.h b/chromium/ui/gfx/half_float.h
index f0492d6e4ec..c5e48ce7b92 100644
--- a/chromium/ui/gfx/half_float.h
+++ b/chromium/ui/gfx/half_float.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_GFX_COLOR_HALF_FLOAT_H_
-#define UI_GFX_COLOR_HALF_FLOAT_H_
+#ifndef UI_GFX_HALF_FLOAT_H_
+#define UI_GFX_HALF_FLOAT_H_
#include <stdint.h>
#include <stdlib.h>
@@ -20,4 +20,4 @@ GFX_EXPORT void FloatToHalfFloat(const float* input,
size_t num);
} // namespace gfx
-#endif
+#endif // UI_GFX_HALF_FLOAT_H_
diff --git a/chromium/ui/gfx/hdr_static_metadata.cc b/chromium/ui/gfx/hdr_static_metadata.cc
new file mode 100644
index 00000000000..50b0e08ef93
--- /dev/null
+++ b/chromium/ui/gfx/hdr_static_metadata.cc
@@ -0,0 +1,14 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/hdr_static_metadata.h"
+
+namespace gfx {
+
+HDRStaticMetadata::HDRStaticMetadata() = default;
+HDRStaticMetadata::HDRStaticMetadata(double max, double max_avg, double min)
+ : max(max), max_avg(max_avg), min(min) {}
+HDRStaticMetadata::HDRStaticMetadata(const HDRStaticMetadata& rhs) = default;
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/hdr_static_metadata.h b/chromium/ui/gfx/hdr_static_metadata.h
new file mode 100644
index 00000000000..e27068ea920
--- /dev/null
+++ b/chromium/ui/gfx/hdr_static_metadata.h
@@ -0,0 +1,40 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_HDR_STATIC_METADATA_H_
+#define UI_GFX_HDR_STATIC_METADATA_H_
+
+#include "ui/gfx/color_space_export.h"
+
+namespace gfx {
+
+// This structure is used to define the HDR static capabilities of a display.
+// Reflects CEA 861.G-2018, Sec.7.5.13, "HDR Static Metadata Data Block"
+// A value of 0.0 in any of the fields means that it's not indicated.
+struct COLOR_SPACE_EXPORT HDRStaticMetadata {
+ public:
+ // "Desired Content Max Luminance Data. This is the content’s absolute peak
+ // luminance (in cd/m2) (likely only in a small area of the screen) that the
+ // display prefers for optimal content rendering."
+ double max;
+ // "Desired Content Max Frame-average Luminance. This is the content’s max
+ // frame-average luminance (in cd/m2) that the display prefers for optimal
+ // content rendering."
+ double max_avg;
+ // "Desired Content Min Luminance. This is the minimum value of the content
+ // (in cd/m2) that the display prefers for optimal content rendering."
+ double min;
+
+ HDRStaticMetadata();
+ HDRStaticMetadata(double max, double max_avg, double min);
+ HDRStaticMetadata(const HDRStaticMetadata& rhs);
+
+ bool operator==(const HDRStaticMetadata& rhs) const {
+ return ((max == rhs.max) && (max_avg == rhs.max_avg) && (min == rhs.min));
+ }
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_HDR_STATIC_METADATA_H_
diff --git a/chromium/ui/gfx/image/image.cc b/chromium/ui/gfx/image/image.cc
index bfc36b69db9..2c3ac634159 100644
--- a/chromium/ui/gfx/image/image.cc
+++ b/chromium/ui/gfx/image/image.cc
@@ -22,7 +22,7 @@
#if defined(OS_IOS)
#include "base/mac/foundation_util.h"
#include "ui/gfx/image/image_skia_util_ios.h"
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
#include "base/mac/foundation_util.h"
#include "base/mac/mac_util.h"
#include "ui/gfx/image/image_skia_util_mac.h"
@@ -84,7 +84,7 @@ class ImageRep {
return const_cast<ImageRepCocoaTouch*>(
static_cast<const ImageRep*>(this)->AsImageRepCocoaTouch());
}
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
const ImageRepCocoa* AsImageRepCocoa() const {
CHECK_EQ(type_, Image::kImageRepCocoa);
return reinterpret_cast<const ImageRepCocoa*>(this);
@@ -140,7 +140,7 @@ class ImageRepPNG : public ImageRep {
std::vector<ImagePNGRep> image_png_reps_;
// Cached to avoid having to parse the raw data multiple times.
- mutable base::Optional<gfx::Size> size_cache_;
+ mutable absl::optional<gfx::Size> size_cache_;
DISALLOW_COPY_AND_ASSIGN(ImageRepPNG);
};
@@ -195,7 +195,7 @@ class ImageRepCocoaTouch : public ImageRep {
DISALLOW_COPY_AND_ASSIGN(ImageRepCocoaTouch);
};
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
class ImageRepCocoa : public ImageRep {
public:
explicit ImageRepCocoa(NSImage* image)
@@ -223,7 +223,7 @@ class ImageRepCocoa : public ImageRep {
DISALLOW_COPY_AND_ASSIGN(ImageRepCocoa);
};
-#endif // defined(OS_APPLE)
+#endif // defined(OS_MAC)
// The Storage class acts similarly to the pixels in a SkBitmap: the Image
// class holds a refptr instance of Storage, which in turn holds all the
@@ -352,7 +352,7 @@ Image::Image(UIImage* image) {
AddRepresentation(std::make_unique<internal::ImageRepCocoaTouch>(image));
}
}
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
Image::Image(NSImage* image) {
if (image) {
storage_ = new internal::ImageStorage(Image::kImageRepCocoa);
@@ -428,7 +428,7 @@ const ImageSkia* Image::ToImageSkia() const {
ImageSkia(ImageSkiaFromUIImage(native_rep->image())));
break;
}
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
case kImageRepCocoa: {
const internal::ImageRepCocoa* native_rep =
GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa();
@@ -474,7 +474,7 @@ UIImage* Image::ToUIImage() const {
}
return rep->AsImageRepCocoaTouch()->image();
}
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
NSImage* Image::ToNSImage() const {
const internal::ImageRep* rep = GetRepresentation(kImageRepCocoa, false);
if (!rep) {
@@ -535,7 +535,7 @@ scoped_refptr<base::RefCountedMemory> Image::As1xPNGBytes() const {
cocoa_touch_rep->image());
break;
}
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
case kImageRepCocoa: {
const internal::ImageRepCocoa* cocoa_rep =
GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa();
diff --git a/chromium/ui/gfx/image/image.h b/chromium/ui/gfx/image/image.h
index 466b7bf5e98..52ad9fd2067 100644
--- a/chromium/ui/gfx/image/image.h
+++ b/chromium/ui/gfx/image/image.h
@@ -70,7 +70,7 @@ class GFX_EXPORT Image {
#if defined(OS_IOS)
// Retains |image|.
explicit Image(UIImage* image);
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
// Retains |image|.
explicit Image(NSImage* image);
#endif
@@ -120,7 +120,7 @@ class GFX_EXPORT Image {
const ImageSkia* ToImageSkia() const;
#if defined(OS_IOS)
UIImage* ToUIImage() const;
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
NSImage* ToNSImage() const;
#endif
diff --git a/chromium/ui/gfx/image/image_platform.h b/chromium/ui/gfx/image/image_platform.h
index 610e8561a88..3e37e8cdfe7 100644
--- a/chromium/ui/gfx/image/image_platform.h
+++ b/chromium/ui/gfx/image/image_platform.h
@@ -24,7 +24,7 @@
#if defined(OS_IOS)
#include "base/mac/foundation_util.h"
#include "ui/gfx/image/image_skia_util_ios.h"
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
#include "base/mac/foundation_util.h"
#include "base/mac/mac_util.h"
#include "ui/gfx/image/image_skia_util_mac.h"
@@ -38,13 +38,13 @@ scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromUIImage(
UIImage* uiimage);
UIImage* UIImageFromPNG(const std::vector<ImagePNGRep>& image_png_reps);
gfx::Size UIImageSize(UIImage* image);
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromNSImage(
NSImage* nsimage);
NSImage* NSImageFromPNG(const std::vector<ImagePNGRep>& image_png_reps,
CGColorSpaceRef color_space);
gfx::Size NSImageSize(NSImage* image);
-#endif // defined(OS_APPLE)
+#endif // defined(OS_MAC)
ImageSkia ImageSkiaFromPNG(const std::vector<ImagePNGRep>& image_png_reps);
scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
diff --git a/chromium/ui/gfx/image/image_skia_source.h b/chromium/ui/gfx/image/image_skia_source.h
index 9c50760edb6..9ffc135f546 100644
--- a/chromium/ui/gfx/image/image_skia_source.h
+++ b/chromium/ui/gfx/image/image_skia_source.h
@@ -5,7 +5,6 @@
#ifndef UI_GFX_IMAGE_IMAGE_SKIA_SOURCE_H_
#define UI_GFX_IMAGE_IMAGE_SKIA_SOURCE_H_
-#include <vector>
#include "ui/gfx/gfx_export.h"
diff --git a/chromium/ui/gfx/image/image_skia_unittest.cc b/chromium/ui/gfx/image/image_skia_unittest.cc
index 854a0638726..792186844e6 100644
--- a/chromium/ui/gfx/image/image_skia_unittest.cc
+++ b/chromium/ui/gfx/image/image_skia_unittest.cc
@@ -316,7 +316,7 @@ TEST_F(ImageSkiaTest, GetBitmap) {
ImageSkia image_skia(std::make_unique<DynamicSource>(Size(100, 200)),
Size(100, 200));
const SkBitmap* bitmap = image_skia.bitmap();
- EXPECT_NE(static_cast<SkBitmap*>(NULL), bitmap);
+ ASSERT_NE(nullptr, bitmap);
EXPECT_FALSE(bitmap->isNull());
}
@@ -330,7 +330,7 @@ TEST_F(ImageSkiaTest, GetBitmapFromEmpty) {
// Check that ImageSkia::bitmap() still returns a valid SkBitmap pointer for
// the image and all its copies.
const SkBitmap* bitmap = empty_image_copy.bitmap();
- ASSERT_NE(static_cast<SkBitmap*>(NULL), bitmap);
+ ASSERT_NE(nullptr, bitmap);
EXPECT_TRUE(bitmap->isNull());
EXPECT_TRUE(bitmap->empty());
}
diff --git a/chromium/ui/gfx/image/image_unittest.cc b/chromium/ui/gfx/image/image_unittest.cc
index 2f4f27693ce..94fea8be97c 100644
--- a/chromium/ui/gfx/image/image_unittest.cc
+++ b/chromium/ui/gfx/image/image_unittest.cc
@@ -18,7 +18,7 @@
#if defined(OS_IOS)
#include "base/mac/foundation_util.h"
#include "skia/ext/skia_utils_ios.h"
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
#include "base/mac/foundation_util.h"
#include "skia/ext/skia_utils_mac.h"
#endif
diff --git a/chromium/ui/gfx/image/image_unittest_util.cc b/chromium/ui/gfx/image/image_unittest_util.cc
index 9d6f74492c1..37f3b833f93 100644
--- a/chromium/ui/gfx/image/image_unittest_util.cc
+++ b/chromium/ui/gfx/image/image_unittest_util.cc
@@ -21,7 +21,7 @@
#if defined(OS_IOS)
#include "base/mac/scoped_cftyperef.h"
#include "skia/ext/skia_utils_ios.h"
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
#include "base/mac/mac_util.h"
#include "skia/ext/skia_utils_mac.h"
#endif
@@ -218,7 +218,7 @@ PlatformImage CreatePlatformImage() {
UIImage* image =
skia::SkBitmapToUIImageWithColorSpace(bitmap, scale, color_space);
return image;
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
NSImage* image = skia::SkBitmapToNSImageWithColorSpace(
bitmap, base::mac::GetGenericRGBColorSpace());
return image;
@@ -230,7 +230,7 @@ PlatformImage CreatePlatformImage() {
gfx::Image::RepresentationType GetPlatformRepresentationType() {
#if defined(OS_IOS)
return gfx::Image::kImageRepCocoaTouch;
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
return gfx::Image::kImageRepCocoa;
#else
return gfx::Image::kImageRepSkia;
@@ -240,7 +240,7 @@ gfx::Image::RepresentationType GetPlatformRepresentationType() {
PlatformImage ToPlatformType(const gfx::Image& image) {
#if defined(OS_IOS)
return image.ToUIImage();
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
return image.ToNSImage();
#else
return image.AsImageSkia();
@@ -250,7 +250,7 @@ PlatformImage ToPlatformType(const gfx::Image& image) {
gfx::Image CopyViaPlatformType(const gfx::Image& image) {
#if defined(OS_IOS)
return gfx::Image(image.ToUIImage());
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
return gfx::Image(image.ToNSImage());
#else
return gfx::Image(image.AsImageSkia());
diff --git a/chromium/ui/gfx/image/image_unittest_util.h b/chromium/ui/gfx/image/image_unittest_util.h
index 2680a241db3..51e5a52cc51 100644
--- a/chromium/ui/gfx/image/image_unittest_util.h
+++ b/chromium/ui/gfx/image/image_unittest_util.h
@@ -20,7 +20,7 @@ namespace test {
#if defined(OS_IOS)
typedef UIImage* PlatformImage;
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
typedef NSImage* PlatformImage;
#else
typedef gfx::ImageSkia PlatformImage;
diff --git a/chromium/ui/gfx/image/image_util.cc b/chromium/ui/gfx/image/image_util.cc
index a1a30a52872..91b6bcbc23c 100644
--- a/chromium/ui/gfx/image/image_util.cc
+++ b/chromium/ui/gfx/image/image_util.cc
@@ -52,13 +52,13 @@ Image ResizedImageForSearchByImage(const Image& image) {
}
// The MacOS implementation of this function is in image_utils_mac.mm.
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
bool JPEG1xEncodedDataFromImage(const Image& image,
int quality,
std::vector<unsigned char>* dst) {
return JPEG1xEncodedDataFromSkiaRepresentation(image, quality, dst);
}
-#endif // !defined(OS_APPLE)
+#endif // !defined(OS_MAC)
bool JPEG1xEncodedDataFromSkiaRepresentation(const Image& image,
int quality,
diff --git a/chromium/ui/gfx/ios/NSString+CrStringDrawing.h b/chromium/ui/gfx/ios/NSString+CrStringDrawing.h
index 3c766ca09d6..d7c6c49ecdf 100644
--- a/chromium/ui/gfx/ios/NSString+CrStringDrawing.h
+++ b/chromium/ui/gfx/ios/NSString+CrStringDrawing.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_GFX_IOS_NSSTRING_CR_STRING_DRAWING_H_
-#define UI_GFX_IOS_NSSTRING_CR_STRING_DRAWING_H_
+#ifndef UI_GFX_IOS_NSSTRING_CRSTRINGDRAWING_H_
+#define UI_GFX_IOS_NSSTRING_CRSTRINGDRAWING_H_
#import <UIKit/UIKit.h>
@@ -62,4 +62,4 @@
@end
-#endif // UI_GFX_IOS_NSSTRING_CR_STRING_DRAWING_H_
+#endif // UI_GFX_IOS_NSSTRING_CRSTRINGDRAWING_H_
diff --git a/chromium/ui/gfx/ipc/buffer_types/gfx_param_traits.cc b/chromium/ui/gfx/ipc/buffer_types/gfx_param_traits.cc
index 483342692bb..507b1e7e7fe 100644
--- a/chromium/ui/gfx/ipc/buffer_types/gfx_param_traits.cc
+++ b/chromium/ui/gfx/ipc/buffer_types/gfx_param_traits.cc
@@ -9,6 +9,8 @@
#include <string>
+#include "base/strings/stringprintf.h"
+
namespace IPC {
void ParamTraits<gfx::BufferUsageAndFormat>::Write(
diff --git a/chromium/ui/gfx/ipc/buffer_types/gfx_param_traits_macros.h b/chromium/ui/gfx/ipc/buffer_types/gfx_param_traits_macros.h
index 5e7f4043582..502a4f1a8fe 100644
--- a/chromium/ui/gfx/ipc/buffer_types/gfx_param_traits_macros.h
+++ b/chromium/ui/gfx/ipc/buffer_types/gfx_param_traits_macros.h
@@ -19,6 +19,8 @@ IPC_ENUM_TRAITS_MAX_VALUE(gfx::BufferFormat, gfx::BufferFormat::LAST)
IPC_ENUM_TRAITS_MAX_VALUE(gfx::BufferUsage, gfx::BufferUsage::LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(gfx::BufferPlane, gfx::BufferPlane::LAST)
+
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT
diff --git a/chromium/ui/gfx/ipc/geometry/gfx_param_traits.cc b/chromium/ui/gfx/ipc/geometry/gfx_param_traits.cc
index 27cef90e5f1..6672a5743d9 100644
--- a/chromium/ui/gfx/ipc/geometry/gfx_param_traits.cc
+++ b/chromium/ui/gfx/ipc/geometry/gfx_param_traits.cc
@@ -9,6 +9,7 @@
#include <string>
+#include "base/strings/stringprintf.h"
#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
diff --git a/chromium/ui/gfx/ipc/gfx_param_traits.cc b/chromium/ui/gfx/ipc/gfx_param_traits.cc
index 0c4600d7e95..49e2135524d 100644
--- a/chromium/ui/gfx/ipc/gfx_param_traits.cc
+++ b/chromium/ui/gfx/ipc/gfx_param_traits.cc
@@ -9,6 +9,7 @@
#include <string>
+#include "base/strings/stringprintf.h"
#include "ui/gfx/ipc/geometry/gfx_param_traits.h"
#include "ui/gfx/range/range.h"
diff --git a/chromium/ui/gfx/linux/client_native_pixmap_dmabuf.cc b/chromium/ui/gfx/linux/client_native_pixmap_dmabuf.cc
index 2afa1ca9bba..a6e747c5789 100644
--- a/chromium/ui/gfx/linux/client_native_pixmap_dmabuf.cc
+++ b/chromium/ui/gfx/linux/client_native_pixmap_dmabuf.cc
@@ -20,7 +20,6 @@
#include "base/posix/eintr_wrapper.h"
#include "base/process/memory.h"
#include "base/process/process_metrics.h"
-#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "build/chromecast_buildflags.h"
diff --git a/chromium/ui/gfx/mac/io_surface.cc b/chromium/ui/gfx/mac/io_surface.cc
index e5fd0a36f83..de7aa569413 100644
--- a/chromium/ui/gfx/mac/io_surface.cc
+++ b/chromium/ui/gfx/mac/io_surface.cc
@@ -240,8 +240,8 @@ IOSurfaceRef CreateIOSurface(const gfx::Size& size,
for (size_t plane = 0; plane < num_planes; ++plane) {
const size_t factor =
gfx::SubsamplingFactorForBufferFormat(format, plane);
- const size_t plane_width = size.width() / factor;
- const size_t plane_height = size.height() / factor;
+ const size_t plane_width = (size.width() + factor - 1) / factor;
+ const size_t plane_height = (size.height() + factor - 1) / factor;
const size_t plane_bytes_per_element = BytesPerElement(format, plane);
const size_t plane_bytes_per_row = IOSurfaceAlignProperty(
kIOSurfacePlaneBytesPerRow, plane_width * plane_bytes_per_element);
diff --git a/chromium/ui/gfx/mac/io_surface_unittest.cc b/chromium/ui/gfx/mac/io_surface_unittest.cc
index fff1dcbfab4..b35c69ccc4a 100644
--- a/chromium/ui/gfx/mac/io_surface_unittest.cc
+++ b/chromium/ui/gfx/mac/io_surface_unittest.cc
@@ -33,6 +33,16 @@ TEST(IOSurface, HDRMetadata) {
EXPECT_EQ(in, out);
}
+TEST(IOSurface, OddSizeMultiPlanar) {
+ base::ScopedCFTypeRef<IOSurfaceRef> io_surface(
+ CreateIOSurface(gfx::Size(101, 99), gfx::BufferFormat::YUV_420_BIPLANAR));
+ DCHECK(io_surface);
+ // Plane sizes are rounded up.
+ // https://crbug.com/1226056
+ EXPECT_EQ(IOSurfaceGetWidthOfPlane(io_surface, 1), 51u);
+ EXPECT_EQ(IOSurfaceGetHeightOfPlane(io_surface, 1), 50u);
+}
+
} // namespace
} // namespace gfx
diff --git a/chromium/ui/gfx/mojom/BUILD.gn b/chromium/ui/gfx/mojom/BUILD.gn
index 07b61c87c7c..68a24931a1c 100644
--- a/chromium/ui/gfx/mojom/BUILD.gn
+++ b/chromium/ui/gfx/mojom/BUILD.gn
@@ -14,6 +14,7 @@ mojom("mojom") {
"color_space.mojom",
"delegated_ink_metadata.mojom",
"delegated_ink_point.mojom",
+ "delegated_ink_point_renderer.mojom",
"display_color_spaces.mojom",
"font_render_params.mojom",
"gpu_extra_info.mojom",
@@ -57,6 +58,10 @@ mojom("mojom") {
cpp = "::gfx::BufferUsageAndFormat"
},
{
+ mojom = "gfx.mojom.BufferPlane"
+ cpp = "::gfx::BufferPlane"
+ },
+ {
mojom = "gfx.mojom.GpuMemoryBufferHandle"
cpp = "::gfx::GpuMemoryBufferHandle"
move_only = true
diff --git a/chromium/ui/gfx/mojom/buffer_types.mojom b/chromium/ui/gfx/mojom/buffer_types.mojom
index ac5ea1cb625..461620a8abd 100644
--- a/chromium/ui/gfx/mojom/buffer_types.mojom
+++ b/chromium/ui/gfx/mojom/buffer_types.mojom
@@ -45,6 +45,14 @@ struct BufferUsageAndFormat {
BufferFormat format;
};
+enum BufferPlane {
+ DEFAULT,
+ Y,
+ UV,
+ U,
+ V,
+};
+
// gfx::GpuMemoryBufferId
struct GpuMemoryBufferId {
int32 id;
diff --git a/chromium/ui/gfx/mojom/buffer_types_mojom_traits.h b/chromium/ui/gfx/mojom/buffer_types_mojom_traits.h
index 0a0e79a02da..5ed27e0f5f1 100644
--- a/chromium/ui/gfx/mojom/buffer_types_mojom_traits.h
+++ b/chromium/ui/gfx/mojom/buffer_types_mojom_traits.h
@@ -5,7 +5,6 @@
#ifndef UI_GFX_MOJOM_BUFFER_TYPES_MOJOM_TRAITS_H_
#define UI_GFX_MOJOM_BUFFER_TYPES_MOJOM_TRAITS_H_
-#include <vector>
#include "base/component_export.h"
#include "build/build_config.h"
@@ -235,6 +234,49 @@ struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS)
gfx::GpuMemoryBufferHandle* handle);
};
+template <>
+struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS)
+ EnumTraits<gfx::mojom::BufferPlane, gfx::BufferPlane> {
+ static gfx::mojom::BufferPlane ToMojom(gfx::BufferPlane format) {
+ switch (format) {
+ case gfx::BufferPlane::DEFAULT:
+ return gfx::mojom::BufferPlane::DEFAULT;
+ case gfx::BufferPlane::Y:
+ return gfx::mojom::BufferPlane::Y;
+ case gfx::BufferPlane::UV:
+ return gfx::mojom::BufferPlane::UV;
+ case gfx::BufferPlane::U:
+ return gfx::mojom::BufferPlane::U;
+ case gfx::BufferPlane::V:
+ return gfx::mojom::BufferPlane::V;
+ }
+ NOTREACHED();
+ return gfx::mojom::BufferPlane::kMinValue;
+ }
+
+ static bool FromMojom(gfx::mojom::BufferPlane input, gfx::BufferPlane* out) {
+ switch (input) {
+ case gfx::mojom::BufferPlane::DEFAULT:
+ *out = gfx::BufferPlane::DEFAULT;
+ return true;
+ case gfx::mojom::BufferPlane::Y:
+ *out = gfx::BufferPlane::Y;
+ return true;
+ case gfx::mojom::BufferPlane::UV:
+ *out = gfx::BufferPlane::UV;
+ return true;
+ case gfx::mojom::BufferPlane::U:
+ *out = gfx::BufferPlane::U;
+ return true;
+ case gfx::mojom::BufferPlane::V:
+ *out = gfx::BufferPlane::V;
+ return true;
+ }
+ NOTREACHED();
+ return false;
+ }
+};
+
} // namespace mojo
#endif // UI_GFX_MOJOM_BUFFER_TYPES_MOJOM_TRAITS_H_
diff --git a/chromium/ui/gfx/mojom/delegated_ink_point_renderer.mojom b/chromium/ui/gfx/mojom/delegated_ink_point_renderer.mojom
new file mode 100644
index 00000000000..223f343afcd
--- /dev/null
+++ b/chromium/ui/gfx/mojom/delegated_ink_point_renderer.mojom
@@ -0,0 +1,25 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module gfx.mojom;
+
+import "ui/gfx/mojom/delegated_ink_point.mojom";
+
+// This interface is used to connect the browser process to viz to support
+// delegated ink trails. A delegated ink point will be produced in the
+// browser process and sent to viz to be held until DrawAndSwap occurs, at
+// which point any delegated ink points that arrived may be used to draw the
+// ink trail. When the browser detects the end of the trail, it will call
+// ResetPrediction() so that viz does not predict any points further than what
+// the user is expecting.
+interface DelegatedInkPointRenderer {
+ // Used to send the DelegatedInkPoint that was created in the browser process
+ // to viz in order to be drawn as part of the delegated ink trail.
+ StoreDelegatedInkPoint(DelegatedInkPoint point);
+
+ // Used to reset prediction and prediction metrics that have been generated
+ // by previously received points. Used by the browser process when a delegated
+ // ink trail should end.
+ ResetPrediction();
+}; \ No newline at end of file
diff --git a/chromium/ui/gfx/mojom/gpu_extra_info.mojom b/chromium/ui/gfx/mojom/gpu_extra_info.mojom
index 705cc6839fc..1b7b023fa90 100644
--- a/chromium/ui/gfx/mojom/gpu_extra_info.mojom
+++ b/chromium/ui/gfx/mojom/gpu_extra_info.mojom
@@ -23,9 +23,5 @@ struct GpuExtraInfo {
array<ANGLEFeature> angle_features;
[EnableIf=enable_x11_params]
- uint64 system_visual;
- [EnableIf=enable_x11_params]
- uint64 rgba_visual;
- [EnableIf=enable_x11_params]
array<gfx.mojom.BufferUsageAndFormat> gpu_memory_buffer_support_x11;
};
diff --git a/chromium/ui/gfx/mojom/gpu_extra_info_mojom_traits.cc b/chromium/ui/gfx/mojom/gpu_extra_info_mojom_traits.cc
index 6b7ff134e8a..c40726b360b 100644
--- a/chromium/ui/gfx/mojom/gpu_extra_info_mojom_traits.cc
+++ b/chromium/ui/gfx/mojom/gpu_extra_info_mojom_traits.cc
@@ -25,14 +25,6 @@ bool StructTraits<gfx::mojom::GpuExtraInfoDataView, gfx::GpuExtraInfo>::Read(
if (!data.ReadAngleFeatures(&out->angle_features))
return false;
#if defined(USE_OZONE_PLATFORM_X11) || defined(USE_X11)
- // These visuals below are obtained via methods of gl::GLVisualPickerGLX class
- // and consumed by ui::XVisualManager::UpdateVisualsOnGpuInfoChanged(); should
- // bad visuals come there, the GPU process will be shut down.
- //
- // See content::GpuDataManagerVisualProxyOzoneLinux and the ShutdownGpuOnIO()
- // function there.
- out->system_visual = static_cast<x11::VisualId>(data.system_visual());
- out->rgba_visual = static_cast<x11::VisualId>(data.rgba_visual());
if (!data.ReadGpuMemoryBufferSupportX11(&out->gpu_memory_buffer_support_x11))
return false;
#endif
diff --git a/chromium/ui/gfx/mojom/gpu_extra_info_mojom_traits.h b/chromium/ui/gfx/mojom/gpu_extra_info_mojom_traits.h
index 40a1114cb15..dd6b118c8b0 100644
--- a/chromium/ui/gfx/mojom/gpu_extra_info_mojom_traits.h
+++ b/chromium/ui/gfx/mojom/gpu_extra_info_mojom_traits.h
@@ -62,14 +62,6 @@ struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS)
}
#if defined(USE_OZONE_PLATFORM_X11) || defined(USE_X11)
- static uint64_t system_visual(const gfx::GpuExtraInfo& input) {
- return static_cast<uint64_t>(input.system_visual);
- }
-
- static uint64_t rgba_visual(const gfx::GpuExtraInfo& input) {
- return static_cast<uint64_t>(input.rgba_visual);
- }
-
static const std::vector<gfx::BufferUsageAndFormat>&
gpu_memory_buffer_support_x11(const gfx::GpuExtraInfo& input) {
return input.gpu_memory_buffer_support_x11;
diff --git a/chromium/ui/gfx/mojom/mask_filter_info_mojom_traits.h b/chromium/ui/gfx/mojom/mask_filter_info_mojom_traits.h
index 0cc30b34570..31045a43e4e 100644
--- a/chromium/ui/gfx/mojom/mask_filter_info_mojom_traits.h
+++ b/chromium/ui/gfx/mojom/mask_filter_info_mojom_traits.h
@@ -22,4 +22,4 @@ struct StructTraits<gfx::mojom::MaskFilterInfoDataView, gfx::MaskFilterInfo> {
};
} // namespace mojo
-#endif // UI_GFX_MOJOM_LINEAR_GRADIENT_MOJOM_TRAITS_H_
+#endif // UI_GFX_MOJOM_MASK_FILTER_INFO_MOJOM_TRAITS_H_
diff --git a/chromium/ui/gfx/mojom/native_handle_types.mojom b/chromium/ui/gfx/mojom/native_handle_types.mojom
index 5b7be0a2123..e81dd83d3e7 100644
--- a/chromium/ui/gfx/mojom/native_handle_types.mojom
+++ b/chromium/ui/gfx/mojom/native_handle_types.mojom
@@ -25,7 +25,7 @@ struct NativePixmapHandle {
[EnableIf=is_linux]
uint64 modifier;
- [EnableIf=is_chromeos]
+ [EnableIf=is_chromeos_ash]
uint64 modifier;
[EnableIf=is_fuchsia]
diff --git a/chromium/ui/gfx/mojom/native_handle_types_mojom_traits.h b/chromium/ui/gfx/mojom/native_handle_types_mojom_traits.h
index 6e9ed3d64ed..67aafb34caa 100644
--- a/chromium/ui/gfx/mojom/native_handle_types_mojom_traits.h
+++ b/chromium/ui/gfx/mojom/native_handle_types_mojom_traits.h
@@ -55,7 +55,7 @@ struct COMPONENT_EXPORT(GFX_NATIVE_HANDLE_TYPES_SHARED_MOJOM_TRAITS)
#endif
#if defined(OS_FUCHSIA)
- static const base::Optional<base::UnguessableToken>& buffer_collection_id(
+ static const absl::optional<base::UnguessableToken>& buffer_collection_id(
const gfx::NativePixmapHandle& pixmap_handle) {
return pixmap_handle.buffer_collection_id;
}
diff --git a/chromium/ui/gfx/mojom/presentation_feedback.mojom b/chromium/ui/gfx/mojom/presentation_feedback.mojom
index d91fe6a4be6..2ddc6618224 100644
--- a/chromium/ui/gfx/mojom/presentation_feedback.mojom
+++ b/chromium/ui/gfx/mojom/presentation_feedback.mojom
@@ -15,4 +15,5 @@ struct PresentationFeedback {
mojo_base.mojom.TimeTicks available_timestamp;
mojo_base.mojom.TimeTicks ready_timestamp;
mojo_base.mojom.TimeTicks latch_timestamp;
+ mojo_base.mojom.TimeTicks writes_done_timestamp;
};
diff --git a/chromium/ui/gfx/mojom/presentation_feedback_mojom_traits.h b/chromium/ui/gfx/mojom/presentation_feedback_mojom_traits.h
index 26b0f2e7fe9..bee9e788c2f 100644
--- a/chromium/ui/gfx/mojom/presentation_feedback_mojom_traits.h
+++ b/chromium/ui/gfx/mojom/presentation_feedback_mojom_traits.h
@@ -42,6 +42,11 @@ struct StructTraits<gfx::mojom::PresentationFeedbackDataView,
return input.latch_timestamp;
}
+ static base::TimeTicks writes_done_timestamp(
+ const gfx::PresentationFeedback& input) {
+ return input.writes_done_timestamp;
+ }
+
static bool Read(gfx::mojom::PresentationFeedbackDataView data,
gfx::PresentationFeedback* out) {
out->flags = data.flags();
@@ -49,7 +54,8 @@ struct StructTraits<gfx::mojom::PresentationFeedbackDataView,
data.ReadInterval(&out->interval) &&
data.ReadAvailableTimestamp(&out->available_timestamp) &&
data.ReadReadyTimestamp(&out->ready_timestamp) &&
- data.ReadLatchTimestamp(&out->latch_timestamp);
+ data.ReadLatchTimestamp(&out->latch_timestamp) &&
+ data.ReadWritesDoneTimestamp(&out->writes_done_timestamp);
}
};
diff --git a/chromium/ui/gfx/native_pixmap_handle.h b/chromium/ui/gfx/native_pixmap_handle.h
index 1748dd32f7a..13f07f29e84 100644
--- a/chromium/ui/gfx/native_pixmap_handle.h
+++ b/chromium/ui/gfx/native_pixmap_handle.h
@@ -10,9 +10,9 @@
#include <vector>
-#include "base/optional.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/gfx_export.h"
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
@@ -90,7 +90,7 @@ struct GFX_EXPORT NativePixmapHandle {
#endif
#if defined(OS_FUCHSIA)
- base::Optional<SysmemBufferCollectionId> buffer_collection_id;
+ absl::optional<SysmemBufferCollectionId> buffer_collection_id;
uint32_t buffer_index = 0;
// Set to true for sysmem buffers which are initialized with RAM coherency
diff --git a/chromium/ui/gfx/paint_throbber.cc b/chromium/ui/gfx/paint_throbber.cc
index e6f6f2082d0..e7131745769 100644
--- a/chromium/ui/gfx/paint_throbber.cc
+++ b/chromium/ui/gfx/paint_throbber.cc
@@ -35,7 +35,7 @@ void PaintArc(Canvas* canvas,
SkColor color,
SkScalar start_angle,
SkScalar sweep,
- base::Optional<SkScalar> stroke_width) {
+ absl::optional<SkScalar> stroke_width) {
if (!stroke_width) {
// Stroke width depends on size.
// . For size < 28: 3 - (28 - size) / 16
@@ -91,7 +91,7 @@ void PaintThrobberSpinningWithStartAngle(
SkColor color,
const base::TimeDelta& elapsed_time,
int64_t start_angle,
- base::Optional<SkScalar> stroke_width) {
+ absl::optional<SkScalar> stroke_width) {
// The sweep angle ranges from -270 to 270 over 1333ms. CSS
// animation timing functions apply in between key frames, so we have to
// break up the 1333ms into two keyframes (-270 to 0, then 0 to 270).
@@ -128,7 +128,7 @@ void PaintThrobberSpinning(Canvas* canvas,
const Rect& bounds,
SkColor color,
const base::TimeDelta& elapsed_time,
- base::Optional<SkScalar> stroke_width) {
+ absl::optional<SkScalar> stroke_width) {
const int64_t start_angle =
270 + base::ClampRound<int64_t>(elapsed_time / kRotationTime * 360);
PaintThrobberSpinningWithStartAngle(canvas, bounds, color, elapsed_time,
@@ -139,7 +139,7 @@ void PaintThrobberWaiting(Canvas* canvas,
const Rect& bounds,
SkColor color,
const base::TimeDelta& elapsed_time,
- base::Optional<SkScalar> stroke_width) {
+ absl::optional<SkScalar> stroke_width) {
int64_t start_angle = 0, sweep = 0;
CalculateWaitingAngles(elapsed_time, &start_angle, &sweep);
PaintArc(canvas, bounds, color, start_angle, sweep, stroke_width);
@@ -150,7 +150,7 @@ void PaintThrobberSpinningAfterWaiting(Canvas* canvas,
SkColor color,
const base::TimeDelta& elapsed_time,
ThrobberWaitingState* waiting_state,
- base::Optional<SkScalar> stroke_width) {
+ absl::optional<SkScalar> stroke_width) {
int64_t waiting_start_angle = 0, waiting_sweep = 0;
CalculateWaitingAngles(waiting_state->elapsed_time, &waiting_start_angle,
&waiting_sweep);
diff --git a/chromium/ui/gfx/paint_throbber.h b/chromium/ui/gfx/paint_throbber.h
index c5370c40452..8d659fcbdac 100644
--- a/chromium/ui/gfx/paint_throbber.h
+++ b/chromium/ui/gfx/paint_throbber.h
@@ -7,8 +7,8 @@
#include <stdint.h>
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/gfx_export.h"
@@ -39,7 +39,7 @@ GFX_EXPORT void PaintThrobberSpinning(
const Rect& bounds,
SkColor color,
const base::TimeDelta& elapsed_time,
- base::Optional<SkScalar> stroke_width = base::nullopt);
+ absl::optional<SkScalar> stroke_width = absl::nullopt);
// Paints a throbber in the "waiting" state. Used when waiting on a network
// response, for example.
@@ -48,7 +48,7 @@ GFX_EXPORT void PaintThrobberWaiting(
const Rect& bounds,
SkColor color,
const base::TimeDelta& elapsed_time,
- base::Optional<SkScalar> stroke_width = base::nullopt);
+ absl::optional<SkScalar> stroke_width = absl::nullopt);
// Paint a throbber in the "spinning" state, smoothly transitioning from a
// previous "waiting" state described by |waiting_state|, which is an in-out
@@ -59,7 +59,7 @@ GFX_EXPORT void PaintThrobberSpinningAfterWaiting(
SkColor color,
const base::TimeDelta& elapsed_time,
ThrobberWaitingState* waiting_state,
- base::Optional<SkScalar> stroke_width = base::nullopt);
+ absl::optional<SkScalar> stroke_width = absl::nullopt);
// Paints a throbber in the "waiting" state (bouncing back and forth). Used when
// waiting on a network response, for example.
diff --git a/chromium/ui/gfx/paint_vector_icon.cc b/chromium/ui/gfx/paint_vector_icon.cc
index eff2ad62ac3..e0193491485 100644
--- a/chromium/ui/gfx/paint_vector_icon.cc
+++ b/chromium/ui/gfx/paint_vector_icon.cc
@@ -24,6 +24,7 @@
#include "ui/gfx/image/canvas_image_source.h"
#include "ui/gfx/scoped_canvas.h"
#include "ui/gfx/vector_icon_types.h"
+#include "ui/gfx/vector_icon_utils.h"
namespace gfx {
@@ -598,16 +599,4 @@ ImageSkia CreateVectorIconFromSource(const std::string& source,
color);
}
-int GetDefaultSizeOfVectorIcon(const VectorIcon& icon) {
- if (icon.is_empty())
- return kEmptyIconSize;
- DCHECK_EQ(icon.reps[icon.reps_size - 1].path[0].command, CANVAS_DIMENSIONS)
- << " " << icon.name
- << " has no size in its icon definition, and it seems unlikely you want "
- "to display at the default of 48dip. Please specify a size in "
- "CreateVectorIcon().";
- const PathElement* default_icon_path = icon.reps[icon.reps_size - 1].path;
- return GetCanvasDimensions(default_icon_path);
-}
-
} // namespace gfx
diff --git a/chromium/ui/gfx/paint_vector_icon.h b/chromium/ui/gfx/paint_vector_icon.h
index 4388461544c..c005bfab2a1 100644
--- a/chromium/ui/gfx/paint_vector_icon.h
+++ b/chromium/ui/gfx/paint_vector_icon.h
@@ -81,10 +81,6 @@ GFX_EXPORT ImageSkia CreateVectorIconFromSource(const std::string& source,
SkColor color);
#endif
-// Calculates the size that will be default for |icon|, in dip. This will be the
-// smallest icon size |icon| contains.
-GFX_EXPORT int GetDefaultSizeOfVectorIcon(const gfx::VectorIcon& icon);
-
} // namespace gfx
#endif // UI_GFX_PAINT_VECTOR_ICON_H_
diff --git a/chromium/ui/gfx/platform_font.h b/chromium/ui/gfx/platform_font.h
index 10dcc7ea900..6b0025ca3d6 100644
--- a/chromium/ui/gfx/platform_font.h
+++ b/chromium/ui/gfx/platform_font.h
@@ -8,8 +8,8 @@
#include <string>
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "ui/gfx/font.h"
@@ -49,7 +49,7 @@ class GFX_EXPORT PlatformFont : public base::RefCounted<PlatformFont> {
static PlatformFont* CreateFromSkTypeface(
sk_sp<SkTypeface> typeface,
int font_size,
- const base::Optional<FontRenderParams>& params);
+ const absl::optional<FontRenderParams>& params);
// Returns a new Font derived from the existing font.
// |size_delta| is the size in pixels to add to the current font.
diff --git a/chromium/ui/gfx/platform_font_mac.h b/chromium/ui/gfx/platform_font_mac.h
index 667b8dbaa22..baf3ea96f2a 100644
--- a/chromium/ui/gfx/platform_font_mac.h
+++ b/chromium/ui/gfx/platform_font_mac.h
@@ -8,7 +8,7 @@
#include "base/compiler_specific.h"
#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/font_render_params.h"
#include "ui/gfx/platform_font.h"
@@ -43,7 +43,7 @@ class GFX_EXPORT PlatformFontMac : public PlatformFont {
// font; use the |SystemFontType| constructor for that.
PlatformFontMac(sk_sp<SkTypeface> typeface,
int font_size_pixels,
- const base::Optional<FontRenderParams>& params);
+ const absl::optional<FontRenderParams>& params);
// Overridden from PlatformFont:
Font DeriveFont(int size_delta,
@@ -74,10 +74,10 @@ class GFX_EXPORT PlatformFontMac : public PlatformFont {
};
PlatformFontMac(NativeFont font,
- base::Optional<SystemFontType> system_font_type);
+ absl::optional<SystemFontType> system_font_type);
PlatformFontMac(NativeFont font,
- base::Optional<SystemFontType> system_font_type,
+ absl::optional<SystemFontType> system_font_type,
FontSpec spec);
~PlatformFontMac() override;
@@ -95,7 +95,7 @@ class GFX_EXPORT PlatformFontMac : public PlatformFont {
base::scoped_nsobject<NSFont> native_font_;
// If the font is a system font, and if so, what kind.
- const base::Optional<SystemFontType> system_font_type_;
+ const absl::optional<SystemFontType> system_font_type_;
// The name/size/style/weight quartet that specify the font. Initialized in
// the constructors.
diff --git a/chromium/ui/gfx/platform_font_mac.mm b/chromium/ui/gfx/platform_font_mac.mm
index bc8aeaade05..932212892c0 100644
--- a/chromium/ui/gfx/platform_font_mac.mm
+++ b/chromium/ui/gfx/platform_font_mac.mm
@@ -213,7 +213,7 @@ NSFont* SystemFontForConstructorOfType(PlatformFontMac::SystemFontType type) {
}
}
-base::Optional<PlatformFontMac::SystemFontType>
+absl::optional<PlatformFontMac::SystemFontType>
SystemFontTypeFromUndocumentedCTFontRefInternals(CTFontRef font) {
// The macOS APIs can't reliably derive one font from another. That's why for
// non-system fonts PlatformFontMac::DeriveFont() uses the family name of the
@@ -237,7 +237,7 @@ SystemFontTypeFromUndocumentedCTFontRefInternals(CTFontRef font) {
// enough.
return PlatformFontMac::SystemFontType::kGeneral;
} else {
- return base::nullopt;
+ return absl::nullopt;
}
}
@@ -269,19 +269,19 @@ PlatformFontMac::PlatformFontMac(SystemFontType system_font_type)
system_font_type) {}
PlatformFontMac::PlatformFontMac(NativeFont native_font)
- : PlatformFontMac(native_font, base::nullopt) {
+ : PlatformFontMac(native_font, absl::nullopt) {
DCHECK(native_font); // nil should not be passed to this constructor.
}
PlatformFontMac::PlatformFontMac(const std::string& font_name, int font_size)
: PlatformFontMac(
NSFontWithSpec({font_name, font_size, Font::NORMAL, Weight::NORMAL}),
- base::nullopt,
+ absl::nullopt,
{font_name, font_size, Font::NORMAL, Weight::NORMAL}) {}
PlatformFontMac::PlatformFontMac(sk_sp<SkTypeface> typeface,
int font_size_pixels,
- const base::Optional<FontRenderParams>& params)
+ const absl::optional<FontRenderParams>& params)
: PlatformFontMac(
base::mac::CFToNSCast(SkTypeface_GetCTFontRef(typeface.get())),
SystemFontTypeFromUndocumentedCTFontRefInternals(
@@ -343,7 +343,7 @@ Font PlatformFontMac::DeriveFont(int size_delta,
NSFont* derived = NSFontWithSpec(
{font_spec_.name, font_spec_.size + size_delta, style, weight});
return Font(new PlatformFontMac(
- derived, base::nullopt,
+ derived, absl::nullopt,
{font_spec_.name, font_spec_.size + size_delta, style, weight}));
}
}
@@ -419,7 +419,7 @@ Weight PlatformFontMac::GetFontWeightFromNSFontForTesting(NSFont* font) {
PlatformFontMac::PlatformFontMac(
NativeFont font,
- base::Optional<SystemFontType> system_font_type)
+ absl::optional<SystemFontType> system_font_type)
: PlatformFontMac(
font,
system_font_type,
@@ -428,7 +428,7 @@ PlatformFontMac::PlatformFontMac(
PlatformFontMac::PlatformFontMac(
NativeFont font,
- base::Optional<SystemFontType> system_font_type,
+ absl::optional<SystemFontType> system_font_type,
FontSpec spec)
: native_font_([font retain]),
system_font_type_(system_font_type),
@@ -545,7 +545,7 @@ PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name,
PlatformFont* PlatformFont::CreateFromSkTypeface(
sk_sp<SkTypeface> typeface,
int font_size_pixels,
- const base::Optional<FontRenderParams>& params) {
+ const absl::optional<FontRenderParams>& params) {
return new PlatformFontMac(typeface, font_size_pixels, params);
}
diff --git a/chromium/ui/gfx/platform_font_skia.cc b/chromium/ui/gfx/platform_font_skia.cc
index 00361316bbe..fe80a2c138f 100644
--- a/chromium/ui/gfx/platform_font_skia.cc
+++ b/chromium/ui/gfx/platform_font_skia.cc
@@ -37,9 +37,9 @@ namespace {
// GNOME/KDE is a non-scalable one. The name should be listed in the
// IsFallbackFontAllowed function in skia/ext/SkFontHost_fontconfig_direct.cpp.
#if defined(OS_ANDROID)
-const char* kFallbackFontFamilyName = "serif";
+const char kFallbackFontFamilyName[] = "serif";
#else
-const char* kFallbackFontFamilyName = "sans";
+const char kFallbackFontFamilyName[] = "sans";
#endif
constexpr SkGlyphID kUnsupportedGlyph = 0;
@@ -112,7 +112,7 @@ PlatformFontSkia::PlatformFontSkia(const std::string& font_name,
PlatformFontSkia::PlatformFontSkia(
sk_sp<SkTypeface> typeface,
int font_size_pixels,
- const base::Optional<FontRenderParams>& params) {
+ const absl::optional<FontRenderParams>& params) {
DCHECK(typeface);
SkString family_name;
@@ -461,7 +461,7 @@ PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name,
PlatformFont* PlatformFont::CreateFromSkTypeface(
sk_sp<SkTypeface> typeface,
int font_size_pixels,
- const base::Optional<FontRenderParams>& params) {
+ const absl::optional<FontRenderParams>& params) {
TRACE_EVENT0("fonts", "PlatformFont::CreateFromSkTypeface");
return new PlatformFontSkia(typeface, font_size_pixels, params);
}
diff --git a/chromium/ui/gfx/platform_font_skia.h b/chromium/ui/gfx/platform_font_skia.h
index 06b5cd77d55..3a1643aee0a 100644
--- a/chromium/ui/gfx/platform_font_skia.h
+++ b/chromium/ui/gfx/platform_font_skia.h
@@ -28,7 +28,7 @@ class GFX_EXPORT PlatformFontSkia : public PlatformFont {
// Wraps the provided SkTypeface without triggering a font rematch.
PlatformFontSkia(sk_sp<SkTypeface> typeface,
int font_size_pixels,
- const base::Optional<FontRenderParams>& params);
+ const absl::optional<FontRenderParams>& params);
// Initials the default PlatformFont. Returns true if this is successful, or
// false if fonts resources are not available. If this returns false, the
diff --git a/chromium/ui/gfx/presentation_feedback.h b/chromium/ui/gfx/presentation_feedback.h
index 8e6e2ad03d2..d1b95025537 100644
--- a/chromium/ui/gfx/presentation_feedback.h
+++ b/chromium/ui/gfx/presentation_feedback.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_GFX_PRESENTAION_FEEDBACK_H_
-#define UI_GFX_PRESENTAION_FEEDBACK_H_
+#ifndef UI_GFX_PRESENTATION_FEEDBACK_H_
+#define UI_GFX_PRESENTATION_FEEDBACK_H_
#include <stdint.h>
@@ -82,6 +82,10 @@ struct PresentationFeedback {
// next rendering update. On Android this corresponds to the SurfaceFlinger
// latch time.
base::TimeTicks latch_timestamp;
+
+ // The time when write operations have completed, corresponding to the time
+ // when rendering on the GPU finished.
+ base::TimeTicks writes_done_timestamp;
};
inline bool operator==(const PresentationFeedback& lhs,
@@ -90,7 +94,8 @@ inline bool operator==(const PresentationFeedback& lhs,
lhs.flags == rhs.flags &&
lhs.available_timestamp == rhs.available_timestamp &&
lhs.ready_timestamp == rhs.ready_timestamp &&
- lhs.latch_timestamp == rhs.latch_timestamp;
+ lhs.latch_timestamp == rhs.latch_timestamp &&
+ lhs.writes_done_timestamp == rhs.writes_done_timestamp;
}
inline bool operator!=(const PresentationFeedback& lhs,
@@ -100,4 +105,4 @@ inline bool operator!=(const PresentationFeedback& lhs,
} // namespace gfx
-#endif // UI_GFX_PRESENTAION_FEEDBACK_H_
+#endif // UI_GFX_PRESENTATION_FEEDBACK_H_
diff --git a/chromium/ui/gfx/range/gfx_range_export.h b/chromium/ui/gfx/range/gfx_range_export.h
index 5634c49770d..dafcefdf9d5 100644
--- a/chromium/ui/gfx/range/gfx_range_export.h
+++ b/chromium/ui/gfx/range/gfx_range_export.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef GFX_RANGE_EXPORT_H_
-#define GFX_RANGE_EXPORT_H_
+#ifndef UI_GFX_RANGE_GFX_RANGE_EXPORT_H_
+#define UI_GFX_RANGE_GFX_RANGE_EXPORT_H_
#if defined(COMPONENT_BUILD)
#if defined(WIN32)
@@ -26,4 +26,4 @@
#define GFX_RANGE_EXPORT
#endif
-#endif // GFX_RANGE_EXPORT_H_
+#endif // UI_GFX_RANGE_GFX_RANGE_EXPORT_H_
diff --git a/chromium/ui/gfx/render_text.cc b/chromium/ui/gfx/render_text.cc
index c80c92f0841..fbefbf00726 100644
--- a/chromium/ui/gfx/render_text.cc
+++ b/chromium/ui/gfx/render_text.cc
@@ -435,8 +435,6 @@ void ApplyRenderParams(const FontRenderParams& params,
// static
constexpr char16_t RenderText::kPasswordReplacementChar;
constexpr bool RenderText::kDragToEndIfOutsideVerticalBounds;
-constexpr SkColor RenderText::kDefaultColor;
-constexpr SkColor RenderText::kDefaultSelectionBackgroundColor;
constexpr int RenderText::kInvalidBaseline;
constexpr SkScalar RenderText::kLineThicknessFactor;
@@ -616,7 +614,7 @@ void RenderText::SetElideBehavior(ElideBehavior elide_behavior) {
}
}
-void RenderText::SetWhitespaceElision(base::Optional<bool> whitespace_elision) {
+void RenderText::SetWhitespaceElision(absl::optional<bool> whitespace_elision) {
if (whitespace_elision_ != whitespace_elision) {
whitespace_elision_ = whitespace_elision;
OnDisplayTextAttributeChanged();
diff --git a/chromium/ui/gfx/render_text.h b/chromium/ui/gfx/render_text.h
index b4e825ddfb6..36811695d23 100644
--- a/chromium/ui/gfx/render_text.h
+++ b/chromium/ui/gfx/render_text.h
@@ -24,6 +24,7 @@
#include "third_party/skia/include/core/SkFont.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "ui/gfx/break_list.h"
+#include "ui/gfx/color_palette.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/font_render_params.h"
#include "ui/gfx/geometry/point.h"
@@ -58,6 +59,8 @@ class TextRunList;
class GFX_EXPORT SkiaTextRenderer {
public:
explicit SkiaTextRenderer(Canvas* canvas);
+ SkiaTextRenderer(const SkiaTextRenderer&) = delete;
+ SkiaTextRenderer& operator=(const SkiaTextRenderer&) = delete;
virtual ~SkiaTextRenderer();
void SetDrawLooper(sk_sp<SkDrawLooper> draw_looper);
@@ -81,8 +84,6 @@ class GFX_EXPORT SkiaTextRenderer {
cc::PaintCanvas* canvas_skia_;
cc::PaintFlags flags_;
SkFont font_;
-
- DISALLOW_COPY_AND_ASSIGN(SkiaTextRenderer);
};
struct TextToDisplayIndex {
@@ -221,12 +222,6 @@ class GFX_EXPORT RenderText {
static constexpr bool kSelectionIsAlwaysDirected = true;
#endif
- // Default color used for the text and cursor.
- static constexpr SkColor kDefaultColor = SK_ColorBLACK;
-
- // Default color used for drawing selection background.
- static constexpr SkColor kDefaultSelectionBackgroundColor = SK_ColorGRAY;
-
// Invalid value of baseline. Assigning this value to |baseline_| causes
// re-calculation of baseline.
static constexpr int kInvalidBaseline = INT_MAX;
@@ -239,6 +234,8 @@ class GFX_EXPORT RenderText {
// with a vector glyph.
static constexpr char16_t kPasswordReplacementChar = 0x2022;
+ RenderText(const RenderText&) = delete;
+ RenderText& operator=(const RenderText&) = delete;
virtual ~RenderText();
// Creates a RenderText instance.
@@ -338,10 +335,10 @@ class GFX_EXPORT RenderText {
ElideBehavior elide_behavior() const { return elide_behavior_; }
// When display text is elided, determines how whitespace is handled.
- // If base::nullopt is specified, the default elision for the current elide
+ // If absl::nullopt is specified, the default elision for the current elide
// behavior will be applied.
- void SetWhitespaceElision(base::Optional<bool> elide_whitespace);
- base::Optional<bool> whitespace_elision() const {
+ void SetWhitespaceElision(absl::optional<bool> elide_whitespace);
+ absl::optional<bool> whitespace_elision() const {
return whitespace_elision_;
}
@@ -818,7 +815,7 @@ class GFX_EXPORT RenderText {
void reset_cached_cursor_x() { cached_cursor_x_.reset(); }
void set_cached_cursor_x(int x) { cached_cursor_x_ = x; }
- base::Optional<int> cached_cursor_x() const { return cached_cursor_x_; }
+ absl::optional<int> cached_cursor_x() const { return cached_cursor_x_; }
// Fixed width of glyphs. This should only be set in test environments.
float glyph_width_for_test_ = 0;
@@ -927,11 +924,10 @@ class GFX_EXPORT RenderText {
bool has_directed_selection_ = kSelectionIsAlwaysDirected;
// The color used for drawing selected text.
- SkColor selection_color_ = kDefaultColor;
+ SkColor selection_color_ = kPlaceholderColor;
// The background color used for drawing the selection when focused.
- SkColor selection_background_focused_color_ =
- kDefaultSelectionBackgroundColor;
+ SkColor selection_background_focused_color_ = kPlaceholderColor;
// Whether the selection visual bounds should be expanded vertically to be
// vertically symmetric with respect to the display rect. Note this flag has
@@ -947,7 +943,7 @@ class GFX_EXPORT RenderText {
// Color, baseline, and style breaks, used to modify ranges of text.
// BreakList positions are stored with text indices, not display indices.
// TODO(msw): Expand to support cursor, selection, background, etc. colors.
- BreakList<SkColor> colors_{kDefaultColor};
+ BreakList<SkColor> colors_{kPlaceholderColor};
BreakList<BaselineStyle> baselines_{NORMAL_BASELINE};
BreakList<int> font_size_overrides_{0};
BreakList<Font::Weight> weights_{Font::Weight::NORMAL};
@@ -986,7 +982,7 @@ class GFX_EXPORT RenderText {
ElideBehavior elide_behavior_ = NO_ELIDE;
// The behavior for eliding whitespace when eliding or truncating.
- base::Optional<bool> whitespace_elision_;
+ absl::optional<bool> whitespace_elision_;
// True if the text is elided given the current behavior and display area.
bool text_elided_ = false;
@@ -1048,12 +1044,10 @@ class GFX_EXPORT RenderText {
int obscured_glyph_spacing_ = 0;
// The cursor position in view space, used to traverse lines of varied widths.
- base::Optional<int> cached_cursor_x_;
+ absl::optional<int> cached_cursor_x_;
// Tell whether or not the |layout_text_| needs an update or is up to date.
mutable bool layout_text_up_to_date_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(RenderText);
};
} // namespace gfx
diff --git a/chromium/ui/gfx/render_text_harfbuzz.cc b/chromium/ui/gfx/render_text_harfbuzz.cc
index 17b28559427..c731b008771 100644
--- a/chromium/ui/gfx/render_text_harfbuzz.cc
+++ b/chromium/ui/gfx/render_text_harfbuzz.cc
@@ -17,6 +17,7 @@
#include "base/i18n/break_iterator.h"
#include "base/i18n/char_iterator.h"
#include "base/i18n/rtl.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
@@ -24,7 +25,6 @@
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/current_thread.h"
#include "base/trace_event/trace_event.h"
diff --git a/chromium/ui/gfx/render_text_unittest.cc b/chromium/ui/gfx/render_text_unittest.cc
index 1e71a0d8b60..140cd7a5441 100644
--- a/chromium/ui/gfx/render_text_unittest.cc
+++ b/chromium/ui/gfx/render_text_unittest.cc
@@ -28,11 +28,13 @@
#include "cc/paint/paint_recorder.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkFontStyle.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "ui/gfx/break_list.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/decorated_text.h"
#include "ui/gfx/font.h"
@@ -58,22 +60,18 @@
#include "base/mac/mac_util.h"
#endif
-using base::ASCIIToUTF16;
-using base::UTF8ToUTF16;
-using base::WideToUTF16;
-
namespace gfx {
namespace {
// Various weak, LTR, RTL, and Bidi string cases with three characters each.
-const char kWeak[] = " . ";
-const char kLtr[] = "abc";
-const char kRtl[] = "\u05d0\u05d1\u05d2";
-const char kLtrRtl[] = "a\u05d0\u05d1";
-const char kLtrRtlLtr[] = "a\u05d1b";
-const char kRtlLtr[] = "\u05d0\u05d1a";
-const char kRtlLtrRtl[] = "\u05d0a\u05d1";
+const char16_t kWeak[] = u" . ";
+const char16_t kLtr[] = u"abc";
+const char16_t kRtl[] = u"אבג";
+const char16_t kLtrRtl[] = u"aאב";
+const char16_t kLtrRtlLtr[] = u"aבb";
+const char16_t kRtlLtr[] = u"אבa";
+const char16_t kRtlLtrRtl[] = u"אaב";
constexpr bool kUseWordWrap = true;
constexpr bool kUseObscuredText = true;
@@ -255,15 +253,6 @@ std::u16string GetObscuredString(size_t length) {
return std::u16string(length, RenderText::kPasswordReplacementChar);
}
-// Converts a vector of UTF8 literals into a vector of (UTF16) string16.
-std::vector<std::u16string> ToString16Vec(
- const std::vector<const char*>& utf8_literals) {
- std::vector<std::u16string> vec;
- for (auto* const literal : utf8_literals)
- vec.push_back(UTF8ToUTF16(literal));
- return vec;
-}
-
// Returns the combined character range from all text runs on |line|.
Range LineCharRange(const internal::Line& line) {
if (line.segments.empty())
@@ -280,7 +269,7 @@ Range LineCharRange(const internal::Line& line) {
struct GlyphCountAndColor {
size_t glyph_count = 0;
- SkColor color = SK_ColorBLACK;
+ SkColor color = kPlaceholderColor;
};
class TextLog {
@@ -674,26 +663,26 @@ TEST_F(RenderTextTest, DefaultStyles) {
// Check the default styles applied to new instances and adjusted text.
RenderText* render_text = GetRenderText();
EXPECT_TRUE(render_text->text().empty());
- const char* const cases[] = {kWeak, kLtr, "Hello", kRtl, "", ""};
+ const char16_t* const cases[] = {kWeak, kLtr, u"Hello", kRtl, u"", u""};
for (size_t i = 0; i < base::size(cases); ++i) {
- EXPECT_TRUE(test_api()->colors().EqualsValueForTesting(SK_ColorBLACK));
+ EXPECT_TRUE(test_api()->colors().EqualsValueForTesting(kPlaceholderColor));
EXPECT_TRUE(test_api()->baselines().EqualsValueForTesting(NORMAL_BASELINE));
EXPECT_TRUE(test_api()->font_size_overrides().EqualsValueForTesting(0));
for (size_t style = 0; style < static_cast<int>(TEXT_STYLE_COUNT); ++style)
EXPECT_TRUE(test_api()->styles()[style].EqualsValueForTesting(false));
- render_text->SetText(UTF8ToUTF16(cases[i]));
+ render_text->SetText(cases[i]);
}
}
TEST_F(RenderTextTest, SetStyles) {
// Ensure custom default styles persist across setting and clearing text.
RenderText* render_text = GetRenderText();
- const SkColor color = SK_ColorRED;
+ const SkColor color = SK_ColorGREEN;
render_text->SetColor(color);
render_text->SetBaselineStyle(SUPERSCRIPT);
render_text->SetWeight(Font::Weight::BOLD);
render_text->SetStyle(TEXT_STYLE_UNDERLINE, false);
- const char* const cases[] = {kWeak, kLtr, "Hello", kRtl, "", ""};
+ const char16_t* const cases[] = {kWeak, kLtr, u"Hello", kRtl, u"", u""};
for (size_t i = 0; i < base::size(cases); ++i) {
EXPECT_TRUE(test_api()->colors().EqualsValueForTesting(color));
EXPECT_TRUE(test_api()->baselines().EqualsValueForTesting(SUPERSCRIPT));
@@ -702,7 +691,7 @@ TEST_F(RenderTextTest, SetStyles) {
EXPECT_TRUE(
test_api()->styles()[TEXT_STYLE_UNDERLINE].EqualsValueForTesting(
false));
- render_text->SetText(UTF8ToUTF16(cases[i]));
+ render_text->SetText(cases[i]);
// Ensure custom default styles can be applied after text has been set.
if (i == 1)
@@ -720,13 +709,13 @@ TEST_F(RenderTextTest, ApplyStyles) {
constexpr int kTestFontSizeOverride = 20;
// Apply a ranged color and style and check the resulting breaks.
- render_text->ApplyColor(SK_ColorRED, Range(1, 4));
+ render_text->ApplyColor(SK_ColorGREEN, Range(1, 4));
render_text->ApplyBaselineStyle(SUPERIOR, Range(2, 4));
render_text->ApplyWeight(Font::Weight::BOLD, Range(2, 5));
render_text->ApplyFontSizeOverride(kTestFontSizeOverride, Range(5, 7));
EXPECT_TRUE(test_api()->colors().EqualsForTesting(
- {{0, SK_ColorBLACK}, {1, SK_ColorRED}, {4, SK_ColorBLACK}}));
+ {{0, kPlaceholderColor}, {1, SK_ColorGREEN}, {4, kPlaceholderColor}}));
EXPECT_TRUE(test_api()->baselines().EqualsForTesting(
{{0, NORMAL_BASELINE}, {2, SUPERIOR}, {4, NORMAL_BASELINE}}));
@@ -751,11 +740,11 @@ TEST_F(RenderTextTest, ApplyStyles) {
// Apply a value over the text end and check the resulting breaks (INT_MAX
// should be used instead of the text length for the range end)
const size_t text_length = render_text->text().length();
- render_text->ApplyColor(SK_ColorRED, Range(0, text_length));
+ render_text->ApplyColor(SK_ColorGREEN, Range(0, text_length));
render_text->ApplyBaselineStyle(SUPERIOR, Range(0, text_length));
render_text->ApplyWeight(Font::Weight::BOLD, Range(2, text_length));
- EXPECT_TRUE(test_api()->colors().EqualsForTesting({{0, SK_ColorRED}}));
+ EXPECT_TRUE(test_api()->colors().EqualsForTesting({{0, SK_ColorGREEN}}));
EXPECT_TRUE(test_api()->baselines().EqualsForTesting({{0, SUPERIOR}}));
EXPECT_TRUE(test_api()->weights().EqualsForTesting(
{{0, Font::Weight::NORMAL}, {2, Font::Weight::BOLD}}));
@@ -790,7 +779,7 @@ TEST_F(RenderTextTest, ApplyStyles) {
// Styles mid-grapheme should work. Style of first character of the grapheme
// is used.
- render_text->SetText(UTF8ToUTF16("0\u0915\u093f1\u0915\u093f2"));
+ render_text->SetText(u"0\u0915\u093f1\u0915\u093f2");
render_text->ApplyStyle(TEXT_STYLE_UNDERLINE, true, Range(2, 5));
EXPECT_TRUE(test_api()->styles()[TEXT_STYLE_UNDERLINE].EqualsForTesting(
{{0, false}, {2, true}, {5, false}}));
@@ -804,13 +793,13 @@ TEST_F(RenderTextTest, ApplyStyleSurrogatePair) {
gfx::Range range(2, 3);
render_text->ApplyWeight(gfx::Font::Weight::BOLD, range);
render_text->ApplyStyle(TEXT_STYLE_ITALIC, true, range);
- render_text->ApplyColor(SK_ColorRED, range);
+ render_text->ApplyColor(SK_ColorGREEN, range);
render_text->Draw(canvas());
EXPECT_TRUE(test_api()->styles()[TEXT_STYLE_ITALIC].EqualsForTesting(
{{0, false}, {2, true}, {3, false}}));
EXPECT_TRUE(test_api()->colors().EqualsForTesting(
- {{0, SK_ColorBLACK}, {2, SK_ColorRED}, {3, SK_ColorBLACK}}));
+ {{0, kPlaceholderColor}, {2, SK_ColorGREEN}, {3, kPlaceholderColor}}));
EXPECT_TRUE(
test_api()->weights().EqualsForTesting({{0, Font::Weight::NORMAL},
{2, Font::Weight::BOLD},
@@ -819,7 +808,7 @@ TEST_F(RenderTextTest, ApplyStyleSurrogatePair) {
TEST_F(RenderTextTest, ApplyStyleGrapheme) {
RenderText* render_text = GetRenderText();
- render_text->SetText(UTF8ToUTF16("\u0065\u0301"));
+ render_text->SetText(u"e\u0301");
render_text->ApplyStyle(TEXT_STYLE_ITALIC, true, gfx::Range(1, 2));
render_text->ApplyStyle(TEXT_STYLE_UNDERLINE, true, gfx::Range(0, 1));
Draw();
@@ -830,7 +819,7 @@ TEST_F(RenderTextTest, ApplyStyleGrapheme) {
TEST_F(RenderTextTest, ApplyStyleMultipleGraphemes) {
RenderText* render_text = GetRenderText();
- render_text->SetText(UTF8ToUTF16("xx\u0065\u0301x"));
+ render_text->SetText(u"xxe\u0301x");
// Apply the style in the middle of a grapheme.
gfx::Range range(1, 3);
render_text->ApplyStyle(TEXT_STYLE_ITALIC, true, range);
@@ -846,7 +835,7 @@ TEST_F(RenderTextTest, ApplyStyleMultipleGraphemes) {
TEST_F(RenderTextTest, ApplyColorSurrogatePair) {
RenderText* render_text = GetRenderText();
render_text->SetText(u"x\U0001F601x");
- render_text->ApplyColor(SK_ColorRED, Range(2, 3));
+ render_text->ApplyColor(SK_ColorGREEN, Range(2, 3));
Draw();
// Ensures that the color is not applied since it is in the middle of a
@@ -869,14 +858,14 @@ TEST_F(RenderTextTest, ApplyColorLongEmoji) {
render_text->AppendText(kLongEmoji);
render_text->AppendText(kLongEmoji);
- render_text->ApplyColor(SK_ColorRED, Range(0, 2));
+ render_text->ApplyColor(SK_ColorGREEN, Range(0, 2));
render_text->ApplyColor(SK_ColorBLUE, Range(8, 13));
Draw();
// Ensures that the color of the emoji is the color at its first character.
ASSERT_EQ(3u, text_log().size());
- EXPECT_EQ(SK_ColorRED, text_log()[0].color());
- EXPECT_EQ(SK_ColorBLACK, text_log()[1].color());
+ EXPECT_EQ(SK_ColorGREEN, text_log()[0].color());
+ EXPECT_EQ(kPlaceholderColor, text_log()[1].color());
EXPECT_EQ(SK_ColorBLUE, text_log()[2].color());
// Reset the color.
@@ -892,11 +881,11 @@ TEST_F(RenderTextTest, ApplyColorLongEmoji) {
TEST_F(RenderTextTest, ApplyColorObscuredEmoji) {
RenderText* render_text = GetRenderText();
render_text->SetText(u"\U0001F628\U0001F628\U0001F628");
- render_text->ApplyColor(SK_ColorRED, Range(0, 2));
+ render_text->ApplyColor(SK_ColorGREEN, Range(0, 2));
render_text->ApplyColor(SK_ColorBLUE, Range(4, 5));
- const std::vector<GlyphCountAndColor> kExpectedTextLog =
- {{1, SK_ColorRED}, {1, SK_ColorBLACK}, {1, SK_ColorBLUE}};
+ const std::vector<GlyphCountAndColor> kExpectedTextLog = {
+ {1, SK_ColorGREEN}, {1, kPlaceholderColor}, {1, SK_ColorBLUE}};
// Ensures that colors are applied.
Draw();
@@ -925,13 +914,13 @@ TEST_F(RenderTextTest, ApplyColorArabicDiacritics) {
// Render an Arabic character with two diacritics. The color should be taken
// from the base character.
RenderText* render_text = GetRenderText();
- render_text->SetText(UTF8ToUTF16("\u0628\u0651\u0650"));
- render_text->ApplyColor(SK_ColorRED, Range(0, 1));
+ render_text->SetText(u"\u0628\u0651\u0650");
+ render_text->ApplyColor(SK_ColorGREEN, Range(0, 1));
render_text->ApplyColor(SK_ColorBLACK, Range(1, 2));
render_text->ApplyColor(SK_ColorBLUE, Range(2, 3));
Draw();
ASSERT_EQ(1u, text_log().size());
- EXPECT_EQ(SK_ColorRED, text_log()[0].color());
+ EXPECT_EQ(SK_ColorGREEN, text_log()[0].color());
}
TEST_F(RenderTextTest, ApplyColorArabicLigature) {
@@ -941,14 +930,14 @@ TEST_F(RenderTextTest, ApplyColorArabicLigature) {
// Render the isolated form of the first glyph.
RenderText* render_text = GetRenderText();
- render_text->SetText(UTF8ToUTF16("\u0628"));
+ render_text->SetText(u"ب");
Draw();
ASSERT_EQ(1u, text_log().size());
ASSERT_EQ(1u, text_log()[0].glyphs().size());
uint16_t isolated_first_glyph = text_log()[0].glyphs()[0];
// Render a pair of glyphs (initial form and final form).
- render_text->SetText(UTF8ToUTF16("\u0628\u0645"));
+ render_text->SetText(u"بم");
Draw();
ASSERT_EQ(1u, text_log().size());
ASSERT_LE(2u, text_log()[0].glyphs().size());
@@ -964,7 +953,7 @@ TEST_F(RenderTextTest, ApplyColorArabicLigature) {
// Applying color should not break the ligature.
// see: https://w3c.github.io/alreq/#h_styling_individual_letters
- render_text->ApplyColor(SK_ColorRED, Range(0, 1));
+ render_text->ApplyColor(SK_ColorGREEN, Range(0, 1));
render_text->ApplyColor(SK_ColorBLACK, Range(1, 2));
Draw();
ASSERT_EQ(2u, text_log().size());
@@ -978,7 +967,7 @@ TEST_F(RenderTextTest, ApplyColorArabicLigature) {
EXPECT_EQ(final_second_glyph, colored_second_glyph);
// Colors should be applied.
- EXPECT_EQ(SK_ColorRED, text_log()[0].color());
+ EXPECT_EQ(SK_ColorGREEN, text_log()[0].color());
EXPECT_EQ(SK_ColorBLACK, text_log()[1].color());
}
@@ -986,13 +975,13 @@ TEST_F(RenderTextTest, AppendTextKeepsStyles) {
RenderText* render_text = GetRenderText();
// Setup basic functionality.
render_text->SetText(u"abcd");
- render_text->ApplyColor(SK_ColorRED, Range(0, 1));
+ render_text->ApplyColor(SK_ColorGREEN, Range(0, 1));
render_text->ApplyBaselineStyle(SUPERSCRIPT, Range(1, 2));
render_text->ApplyStyle(TEXT_STYLE_UNDERLINE, true, Range(2, 3));
render_text->ApplyFontSizeOverride(20, Range(3, 4));
// Verify basic functionality.
const std::vector<std::pair<size_t, SkColor>> expected_color = {
- {0, SK_ColorRED}, {1, SK_ColorBLACK}};
+ {0, SK_ColorGREEN}, {1, kPlaceholderColor}};
EXPECT_TRUE(test_api()->colors().EqualsForTesting(expected_color));
const std::vector<std::pair<size_t, BaselineStyle>> expected_baseline = {
{0, NORMAL_BASELINE}, {1, SUPERSCRIPT}, {2, NORMAL_BASELINE}};
@@ -1019,7 +1008,7 @@ TEST_F(RenderTextTest, AppendTextKeepsStyles) {
TEST_F(RenderTextTest, SetSelection) {
RenderText* render_text = GetRenderText();
- render_text->set_selection_color(SK_ColorRED);
+ render_text->set_selection_color(SK_ColorGREEN);
render_text->SetText(u"abcdef");
render_text->set_focused(true);
@@ -1027,13 +1016,13 @@ TEST_F(RenderTextTest, SetSelection) {
render_text->SetSelection(
{{{4, 100}}, LogicalCursorDirection::CURSOR_FORWARD});
Draw();
- ExpectTextLog({{4}, {2, SK_ColorRED}});
+ ExpectTextLog({{4}, {2, SK_ColorGREEN}});
// Multiple selections
render_text->SetSelection(
{{{0, 1}, {4, 100}}, LogicalCursorDirection::CURSOR_FORWARD});
Draw();
- ExpectTextLog({{1, SK_ColorRED}, {3}, {2, SK_ColorRED}});
+ ExpectTextLog({{1, SK_ColorGREEN}, {3}, {2, SK_ColorGREEN}});
render_text->ClearSelection();
Draw();
@@ -1044,20 +1033,20 @@ TEST_F(RenderTextTest, SelectRangeColored) {
RenderText* render_text = GetRenderText();
render_text->SetText(u"abcdef");
render_text->SetColor(SK_ColorBLACK);
- render_text->set_selection_color(SK_ColorRED);
+ render_text->set_selection_color(SK_ColorGREEN);
render_text->set_focused(true);
render_text->SelectRange(Range(0, 1));
Draw();
- ExpectTextLog({{1, SK_ColorRED}, {5, SK_ColorBLACK}});
+ ExpectTextLog({{1, SK_ColorGREEN}, {5, SK_ColorBLACK}});
render_text->SelectRange(Range(1, 3));
Draw();
- ExpectTextLog({{1, SK_ColorBLACK}, {2, SK_ColorRED}, {3, SK_ColorBLACK}});
+ ExpectTextLog({{1, SK_ColorBLACK}, {2, SK_ColorGREEN}, {3, SK_ColorBLACK}});
render_text->ClearSelection();
Draw();
- ExpectTextLog({{6}});
+ ExpectTextLog({{6, SK_ColorBLACK}});
}
// Tests that when a selection is made and the selection background is
@@ -1066,7 +1055,8 @@ TEST_F(RenderTextTest, SelectWithTranslucentBackground) {
constexpr float kGlyphWidth = 5.5f;
constexpr Size kCanvasSize(300, 50);
constexpr SkColor kTranslucentBlue = SkColorSetARGB(0x7F, 0x00, 0x00, 0xFF);
- const char* kTestString{"A B C D"};
+ const char* const kTestString{"A B C D"};
+ const char16_t* const kTestString16{u"A B C D"};
SkBitmap bitmap;
bitmap.allocPixels(
@@ -1080,7 +1070,7 @@ TEST_F(RenderTextTest, SelectWithTranslucentBackground) {
render_text->set_selection_background_focused_color(kTranslucentBlue);
render_text->set_focused(true);
- render_text->SetText(UTF8ToUTF16(kTestString));
+ render_text->SetText(kTestString16);
render_text->SelectRange(Range(0, 7));
const Rect text_rect = Rect(render_text->GetStringSize());
render_text->SetDisplayRect(text_rect);
@@ -1096,31 +1086,31 @@ TEST_F(RenderTextTest, SelectWithTranslucentBackground) {
TEST_F(RenderTextTest, SelectRangeColoredGrapheme) {
RenderText* render_text = GetRenderText();
- render_text->SetText(UTF8ToUTF16("x\u0065\u0301y"));
+ render_text->SetText(u"xe\u0301y");
render_text->SetColor(SK_ColorBLACK);
- render_text->set_selection_color(SK_ColorRED);
+ render_text->set_selection_color(SK_ColorGREEN);
render_text->set_focused(true);
render_text->SelectRange(Range(0, 1));
Draw();
- ExpectTextLog({{1, SK_ColorRED}, {2, SK_ColorBLACK}});
+ ExpectTextLog({{1, SK_ColorGREEN}, {2, SK_ColorBLACK}});
render_text->SelectRange(Range(1, 2));
Draw();
- ExpectTextLog({{1, SK_ColorBLACK}, {1, SK_ColorRED}, {1, SK_ColorBLACK}});
+ ExpectTextLog({{1, SK_ColorBLACK}, {1, SK_ColorGREEN}, {1, SK_ColorBLACK}});
render_text->SelectRange(Range(2, 3));
Draw();
- ExpectTextLog({{1, SK_ColorBLACK}, {1, SK_ColorRED}, {1, SK_ColorBLACK}});
+ ExpectTextLog({{1, SK_ColorBLACK}, {1, SK_ColorGREEN}, {1, SK_ColorBLACK}});
render_text->SelectRange(Range(2, 4));
Draw();
- ExpectTextLog({{1, SK_ColorBLACK}, {2, SK_ColorRED}});
+ ExpectTextLog({{1, SK_ColorBLACK}, {2, SK_ColorGREEN}});
}
TEST_F(RenderTextTest, SelectRangeMultiple) {
RenderText* render_text = GetRenderText();
- render_text->set_selection_color(SK_ColorRED);
+ render_text->set_selection_color(SK_ColorGREEN);
render_text->SetText(u"abcdef");
render_text->set_focused(true);
@@ -1128,12 +1118,12 @@ TEST_F(RenderTextTest, SelectRangeMultiple) {
render_text->SelectRange(Range(0, 1));
render_text->SelectRange(Range(4, 2), false);
Draw();
- ExpectTextLog({{1, SK_ColorRED}, {1}, {2, SK_ColorRED}, {2}});
+ ExpectTextLog({{1, SK_ColorGREEN}, {1}, {2, SK_ColorGREEN}, {2}});
// Setting a primary selection should override secondary selections
render_text->SelectRange(Range(5, 6));
Draw();
- ExpectTextLog({{5}, {1, SK_ColorRED}});
+ ExpectTextLog({{5}, {1, SK_ColorGREEN}});
render_text->ClearSelection();
Draw();
@@ -1159,7 +1149,7 @@ TEST_F(RenderTextTest, SetCompositionRangeColored) {
TEST_F(RenderTextTest, SetCompositionRangeColoredGrapheme) {
RenderText* render_text = GetRenderText();
- render_text->SetText(UTF8ToUTF16("x\u0065\u0301y"));
+ render_text->SetText(u"xe\u0301y");
render_text->SetCompositionRange(Range(0, 1));
Draw();
@@ -1261,15 +1251,16 @@ TEST_F(RenderTextTest, ObscuredText) {
std::ceil(render_text->GetCursorSpan({0, 2}).length()));
// Cursoring is independent of underlying characters when text is obscured.
- const char* const texts[] = {
- kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, kRtlLtr, kRtlLtrRtl,
- "hop on pop", // Check LTR word boundaries.
- "\u05d0\u05d1 \u05d0\u05d2 \u05d1\u05d2", // Check RTL word boundaries.
+ const char16_t* const texts[] = {
+ kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, kRtlLtr, kRtlLtrRtl,
+ u"hop on pop", // Check LTR word boundaries.
+ u"אב אג בג", // Check RTL word boundaries.
};
for (size_t i = 0; i < base::size(texts); ++i) {
- std::u16string text = UTF8ToUTF16(texts[i]);
- TestVisualCursorMotionInObscuredField(render_text, text, SELECTION_NONE);
- TestVisualCursorMotionInObscuredField(render_text, text, SELECTION_RETAIN);
+ TestVisualCursorMotionInObscuredField(render_text, texts[i],
+ SELECTION_NONE);
+ TestVisualCursorMotionInObscuredField(render_text, texts[i],
+ SELECTION_RETAIN);
}
}
@@ -1346,8 +1337,7 @@ TEST_F(RenderTextTest, RevealObscuredText) {
// Text with invalid surrogates (surrogates low 0xDC00 and high 0xD800).
// Invalid surrogates are replaced by replacement character (e.g. 0xFFFD).
- const char16_t invalid_surrogates[] = {0xDC00, 0xD800, 'h', 'o', 'p', 0};
- render_text->SetText(invalid_surrogates);
+ render_text->SetText(u"\xDC00\xD800hop");
EXPECT_EQ(GetObscuredString(5), render_text->GetDisplayText());
render_text->RenderText::SetObscuredRevealIndex(0);
EXPECT_EQ(GetObscuredString(5, 0, 0xFFFD), render_text->GetDisplayText());
@@ -1357,9 +1347,7 @@ TEST_F(RenderTextTest, RevealObscuredText) {
EXPECT_EQ(GetObscuredString(5, 2, 'h'), render_text->GetDisplayText());
// Text with valid surrogates before and after the reveal index.
- const char16_t valid_surrogates[] = {0xD800, 0xDC00, 'h', 'o',
- 'p', 0xD800, 0xDC00, 0};
- render_text->SetText(valid_surrogates);
+ render_text->SetText(u"\xD800\xDC00hop\xD800\xDC00");
EXPECT_EQ(GetObscuredString(5), render_text->GetDisplayText());
render_text->RenderText::SetObscuredRevealIndex(0);
const char16_t valid_expect_0_and_1[] = {0xD800,
@@ -1392,12 +1380,11 @@ TEST_F(RenderTextTest, ObscuredEmoji) {
RenderText* render_text = GetRenderText();
render_text->SetObscured(true);
// Test U+1F601 😁 "Grinning face with smiling eyes", followed by 'y'.
- // Windows requires wide strings for \Unnnnnnnn universal character names.
- render_text->SetText(u"\U0001F601y");
+ render_text->SetText(u"😁y");
render_text->Draw(canvas());
- // Emoji codepoints are replaced by bullets (e.g. "\u2022\u2022").
- EXPECT_EQ(UTF8ToUTF16("\u2022\u2022"), render_text->GetDisplayText());
+ // Emoji codepoints are replaced by bullets.
+ EXPECT_EQ(u"••", render_text->GetDisplayText());
EXPECT_EQ(0U, test_api()->TextIndexToDisplayIndex(0U));
EXPECT_EQ(0U, test_api()->TextIndexToDisplayIndex(1U));
EXPECT_EQ(1U, test_api()->TextIndexToDisplayIndex(2U));
@@ -1410,12 +1397,11 @@ TEST_F(RenderTextTest, ObscuredEmoji) {
EXPECT_EQ(3U, test_api()->DisplayIndexToTextIndex(2U));
// Test two U+1F4F7 📷 "Camera" characters in a row.
- // Windows requires wide strings for \Unnnnnnnn universal character names.
- render_text->SetText(u"\U0001F4F7\U0001F4F7");
+ render_text->SetText(u"📷📷");
render_text->Draw(canvas());
- // Emoji codepoints are replaced by bullets (e.g. "\u2022\u2022").
- EXPECT_EQ(UTF8ToUTF16("\u2022\u2022"), render_text->GetDisplayText());
+ // Emoji codepoints are replaced by bullets.
+ EXPECT_EQ(u"••", render_text->GetDisplayText());
EXPECT_EQ(0U, test_api()->TextIndexToDisplayIndex(0U));
EXPECT_EQ(0U, test_api()->TextIndexToDisplayIndex(1U));
EXPECT_EQ(1U, test_api()->TextIndexToDisplayIndex(2U));
@@ -1428,7 +1414,7 @@ TEST_F(RenderTextTest, ObscuredEmoji) {
render_text->SetObscuredRevealIndex(0);
render_text->Draw(canvas());
- EXPECT_EQ(u"\U0001F4F7\u2022", render_text->GetDisplayText());
+ EXPECT_EQ(u"📷•", render_text->GetDisplayText());
EXPECT_EQ(0U, test_api()->TextIndexToDisplayIndex(0U));
EXPECT_EQ(0U, test_api()->TextIndexToDisplayIndex(1U));
EXPECT_EQ(2U, test_api()->TextIndexToDisplayIndex(2U));
@@ -1442,7 +1428,7 @@ TEST_F(RenderTextTest, ObscuredEmoji) {
TEST_F(RenderTextTest, ObscuredEmojiRevealed) {
RenderText* render_text = GetRenderText();
- std::u16string text = u"123\U0001F4F7\U0001F4F7x\U0001F601-";
+ std::u16string text = u"123📷📷x😁-";
for (size_t i = 0; i < text.length(); ++i) {
render_text->SetText(text);
render_text->SetObscured(true);
@@ -1453,7 +1439,7 @@ TEST_F(RenderTextTest, ObscuredEmojiRevealed) {
struct TextIndexConversionCase {
const char* test_name;
- const wchar_t* text;
+ const char16_t* text;
};
using TextIndexConversionParam =
@@ -1479,7 +1465,7 @@ TEST_P(RenderTextTestWithTextIndexConversionCase, TextIndexConversion) {
size_t reveal_index = std::get<2>(GetParam());
RenderText* render_text = GetRenderText();
- render_text->SetText(WideToUTF16(param.text));
+ render_text->SetText(param.text);
render_text->SetObscured(obscured);
render_text->SetObscuredRevealIndex(reveal_index);
render_text->Draw(canvas());
@@ -1507,15 +1493,15 @@ TEST_P(RenderTextTestWithTextIndexConversionCase, TextIndexConversion) {
}
const TextIndexConversionCase kTextIndexConversionCases[] = {
- {"simple", L"abc"},
- {"simple_obscured1", L"abc"},
- {"simple_obscured2", L"abc"},
- {"emoji_asc", L"\U0001F6281234"},
- {"emoji_asc_obscured0", L"\U0001F6281234"},
- {"emoji_asc_obscured2", L"\U0001F6281234"},
- {"picto_title", L"x☛"},
- {"simple_mixed", L"aaڭڭcc"},
- {"simple_rtl", L"أسكي"},
+ {"simple", u"abc"},
+ {"simple_obscured1", u"abc"},
+ {"simple_obscured2", u"abc"},
+ {"emoji_asc", u"😨1234"},
+ {"emoji_asc_obscured0", u"😨1234"},
+ {"emoji_asc_obscured2", u"😨1234"},
+ {"picto_title", u"xx☛"},
+ {"simple_mixed", u"aaڭڭcc"},
+ {"simple_rtl", u"أسكي"},
};
// Validate that conversion text and between display text indexes are consistent
@@ -1525,12 +1511,12 @@ INSTANTIATE_TEST_SUITE_P(
RenderTextTestWithTextIndexConversionCase,
::testing::Combine(::testing::ValuesIn(kTextIndexConversionCases),
testing::Values(false, true),
- testing::Values(0, 1, 4)),
+ testing::Values(0, 1, 3)),
RenderTextTestWithTextIndexConversionCase::ParamInfoToString);
struct RunListCase {
const char* test_name;
- const wchar_t* text;
+ const char16_t* text;
const char* expected;
const bool multiline = false;
};
@@ -1549,40 +1535,39 @@ TEST_P(RenderTextTestWithRunListCase, ItemizeTextToRuns) {
RunListCase param = GetParam();
RenderTextHarfBuzz* render_text = GetRenderText();
render_text->SetMultiline(param.multiline);
- render_text->SetText(WideToUTF16(param.text));
+ render_text->SetText(param.text);
EXPECT_EQ(param.expected, GetRunListStructureString());
}
const RunListCase kBasicsRunListCases[] = {
- {"simpleLTR", L"abc", "[0->2]"},
- {"simpleRTL", L"ښڛڜ", "[2<-0]"},
- {"asc_arb", L"abcښڛڜdef", "[0->2][5<-3][6->8]"},
- {"asc_dev_asc", L"abcऔकखdefڜ", "[0->2][3->5][6->8][9]"},
- {"phone", L"1-(800)-xxx-xxxx", "[0][1][2][3->5][6][7][8->10][11][12->15]"},
- {"dev_ZWS", L"क\u200Bख", "[0][1][2]"},
- {"numeric", L"1 2 3 4", "[0][1][2][3][4][5][6]"},
- {"joiners1", L"1\u200C2\u200C3\u200C4", "[0->6]"},
- {"joiners2", L"\u060F\u200C\u060F", "[0->2]"},
- {"combining_accents1", L"a\u0300e\u0301", "[0->3]"},
- {"combining_accents2", L"\u0065\u0308\u0435\u0308", "[0->1][2->3]"},
- {"picto_title", L"☞☛test☚☜", "[0->1][2->5][6->7]"},
- {"picto_LTR", L"☺☺☺!", "[0->2][3]"},
- {"picto_RTL", L"☺☺☺ښ", "[3][2<-0]"},
- {"paren_picto", L"(☾☹☽)", "[0][1][2][3][4]"},
- {"emoji_asc", L"\U0001F6281234",
- "[0->1][2->5]"}, // http://crbug.com/530021
- {"emoji_title", L"▶Feel goods",
+ {"simpleLTR", u"abc", "[0->2]"},
+ {"simpleRTL", u"ښڛڜ", "[2<-0]"},
+ {"asc_arb", u"abcښڛڜdef", "[0->2][5<-3][6->8]"},
+ {"asc_dev_asc", u"abcऔकखdefڜ", "[0->2][3->5][6->8][9]"},
+ {"phone", u"1-(800)-xxx-xxxx", "[0][1][2][3->5][6][7][8->10][11][12->15]"},
+ {"dev_ZWS", u"क\u200Bख", "[0][1][2]"},
+ {"numeric", u"1 2 3 4", "[0][1][2][3][4][5][6]"},
+ {"joiners1", u"1\u200C2\u200C3\u200C4", "[0->6]"},
+ {"joiners2", u"؏\u200C؏", "[0->2]"},
+ {"combining_accents1", u"àé", "[0->3]"},
+ {"combining_accents2", u"ëё", "[0->1][2->3]"},
+ {"picto_title", u"☞☛test☚☜", "[0->1][2->5][6->7]"},
+ {"picto_LTR", u"☺☺☺!", "[0->2][3]"},
+ {"picto_RTL", u"☺☺☺ښ", "[3][2<-0]"},
+ {"paren_picto", u"(☾☹☽)", "[0][1][2][3][4]"},
+ {"emoji_asc", u"😨1234", "[0->1][2->5]"}, // http://crbug.com/530021
+ {"emoji_title", u"▶Feel goods",
"[0][1->4][5][6->10]"}, // http://crbug.com/278913
- {"jap_paren1", L"ぬ「シ」ほ",
+ {"jap_paren1", u"ぬ「シ」ほ",
"[0][1][2][3][4]"}, // http://crbug.com/396776
- {"jap_paren2", L"國哲(c)1",
+ {"jap_paren2", u"國哲(c)1",
"[0->1][2][3][4][5]"}, // http://crbug.com/125792
- {"newline1", L"\n\n", "[0->1]"},
- {"newline2", L"\r\n\r\n", "[0->3]"},
- {"newline3", L"\r\r\n", "[0->2]"},
- {"multiline_newline1", L"\n\n", "[0][1]", true},
- {"multiline_newline2", L"\r\n\r\n", "[0->1][2->3]", true},
- {"multiline_newline3", L"\r\r\n", "[0][1->2]", true},
+ {"newline1", u"\n\n", "[0->1]"},
+ {"newline2", u"\r\n\r\n", "[0->3]"},
+ {"newline3", u"\r\r\n", "[0->2]"},
+ {"multiline_newline1", u"\n\n", "[0][1]", true},
+ {"multiline_newline2", u"\r\n\r\n", "[0->1][2->3]", true},
+ {"multiline_newline3", u"\r\r\n", "[0][1->2]", true},
};
INSTANTIATE_TEST_SUITE_P(ItemizeTextToRunsBasics,
@@ -1592,38 +1577,38 @@ INSTANTIATE_TEST_SUITE_P(ItemizeTextToRunsBasics,
// see 'Unicode Bidirectional Algorithm': http://unicode.org/reports/tr9/
const RunListCase kBidiRunListCases[] = {
- {"simple_ltr", L"ascii", "[0->4]"},
- {"simple_rtl", L"أسكي", "[3<-0]"},
- {"simple_mixed", L"aaڭڭcc", "[0->1][3<-2][4->5]"},
- {"simple_mixed_LRE", L"\u202Aaaڭڭcc\u202C", "[0][1->2][4<-3][5->6][7]"},
- {"simple_mixed_RLE", L"\u202Baaڭڭcc\u202C", "[7][5->6][4<-3][0][1->2]"},
- {"sequence_RLE", L"\u202Baa\u202C\u202Bbb\u202C",
+ {"simple_ltr", u"ascii", "[0->4]"},
+ {"simple_rtl", u"أسكي", "[3<-0]"},
+ {"simple_mixed", u"aaڭڭcc", "[0->1][3<-2][4->5]"},
+ {"simple_mixed_LRE", u"\u202Aaaڭڭcc\u202C", "[0][1->2][4<-3][5->6][7]"},
+ {"simple_mixed_RLE", u"\u202Baaڭڭcc\u202C", "[7][5->6][4<-3][0][1->2]"},
+ {"sequence_RLE", u"\u202Baa\u202C\u202Bbb\u202C",
"[7][0][1->2][3->4][5->6]"},
- {"simple_mixed_LRI", L"\u2066aaڭڭcc\u2069", "[0][1->2][4<-3][5->6][7]"},
- {"simple_mixed_RLI", L"\u2067aaڭڭcc\u2069", "[0][5->6][4<-3][1->2][7]"},
- {"sequence_RLI", L"\u2067aa\u2069\u2067bb\u2069",
+ {"simple_mixed_LRI", u"\u2066aaڭڭcc\u2069", "[0][1->2][4<-3][5->6][7]"},
+ {"simple_mixed_RLI", u"\u2067aaڭڭcc\u2069", "[0][5->6][4<-3][1->2][7]"},
+ {"sequence_RLI", u"\u2067aa\u2069\u2067bb\u2069",
"[0][1->2][3->4][5->6][7]"},
- {"override_ltr_RLO", L"\u202Eaaa\u202C", "[4][3<-1][0]"},
- {"override_rtl_LRO", L"\u202Dڭڭڭ\u202C", "[0][1->3][4]"},
- {"neutral_strong_ltr", L"a!!a", "[0][1->2][3]"},
- {"neutral_strong_rtl", L"ڭ!!ڭ", "[3][2<-1][0]"},
- {"neutral_strong_both", L"a a ڭ ڭ", "[0][1][2][3][6][5][4]"},
- {"neutral_strong_both_RLE", L"\u202Ba a ڭ ڭ\u202C",
+ {"override_ltr_RLO", u"\u202Eaaa\u202C", "[4][3<-1][0]"},
+ {"override_rtl_LRO", u"\u202Dڭڭڭ\u202C", "[0][1->3][4]"},
+ {"neutral_strong_ltr", u"a!!a", "[0][1->2][3]"},
+ {"neutral_strong_rtl", u"ڭ!!ڭ", "[3][2<-1][0]"},
+ {"neutral_strong_both", u"a a ڭ ڭ", "[0][1][2][3][6][5][4]"},
+ {"neutral_strong_both_RLE", u"\u202Ba a ڭ ڭ\u202C",
"[8][7][6][5][4][0][1][2][3]"},
- {"weak_numbers", L"one ڭ222ڭ", "[0->2][3][8][5->7][4]"},
- {"not_weak_letters", L"one ڭabcڭ", "[0->2][3][4][5->7][8]"},
- {"weak_arabic_numbers", L"one ڭ١٢٣ڭ", "[0->2][3][8][5->7][4]"},
- {"neutral_LRM_pre", L"\u200E\u2026\u2026", "[0->2]"},
- {"neutral_LRM_post", L"\u2026\u2026\u200E", "[0->2]"},
- {"neutral_RLM_pre", L"\u200F\u2026\u2026", "[2<-0]"},
- {"neutral_RLM_post", L"\u2026\u2026\u200F", "[2<-0]"},
- {"brackets_ltr", L"aa(ڭڭ)\u2026\u2026", "[0->1][2][4<-3][5][6->7]"},
- {"brackets_rtl", L"ڭڭ(aa)\u2026\u2026", "[7<-6][5][3->4][2][1<-0]"},
- {"mixed_with_punct", L"aa \"ڭڭ!\", aa",
+ {"weak_numbers", u"one ڭ222ڭ", "[0->2][3][8][5->7][4]"},
+ {"not_weak_letters", u"one ڭabcڭ", "[0->2][3][4][5->7][8]"},
+ {"weak_arabic_numbers", u"one ڭ١٢٣ڭ", "[0->2][3][8][5->7][4]"},
+ {"neutral_LRM_pre", u"\u200E……", "[0->2]"},
+ {"neutral_LRM_post", u"……\u200E", "[0->2]"},
+ {"neutral_RLM_pre", u"\u200F……", "[2<-0]"},
+ {"neutral_RLM_post", u"……\u200F", "[2<-0]"},
+ {"brackets_ltr", u"aa(ڭڭ)……", "[0->1][2][4<-3][5][6->7]"},
+ {"brackets_rtl", u"ڭڭ(aa)……", "[7<-6][5][3->4][2][1<-0]"},
+ {"mixed_with_punct", u"aa \"ڭڭ!\", aa",
"[0->1][2][3][5<-4][6->8][9][10->11]"},
- {"mixed_with_punct_RLI", L"aa \"\u2067ڭڭ!\u2069\", aa",
+ {"mixed_with_punct_RLI", u"aa \"\u2067ڭڭ!\u2069\", aa",
"[0->1][2][3][4][7][6<-5][8][9->10][11][12->13]"},
- {"mixed_with_punct_RLM", L"aa \"ڭڭ!\u200F\", aa",
+ {"mixed_with_punct_RLM", u"aa \"ڭڭ!\u200F\", aa",
"[0->1][2][3][7][6][5<-4][8->9][10][11->12]"},
};
@@ -1633,18 +1618,17 @@ INSTANTIATE_TEST_SUITE_P(ItemizeTextToRunsBidi,
RenderTextTestWithRunListCase::ParamInfoToString);
const RunListCase kBracketsRunListCases[] = {
- {"matched_parens", L"(a)", "[0][1][2]"},
- {"double_matched_parens", L"((a))", "[0->1][2][3->4]"},
- {"double_matched_parens2", L"((aaa))", "[0->1][2->4][5->6]"},
- {"square_brackets", L"[...]x", "[0][1->3][4][5]"},
- {"curly_brackets", L"{}x{}", "[0->1][2][3->4]"},
- {"style_brackets", L"\u300c...\u300dx", "[0][1->3][4][5]"},
- {"tibetan_brackets", L"\u0f3a\u0f3b\u0f20\u0f20\u0f3c\u0f3d",
- "[0->1][2->3][4->5]"},
- {"angle_brackets", L"\u3008\u3007\u3007\u3009", "[0][1->2][3]"},
- {"double_angle_brackets", L"\u300A\u3007\u3007\u300B", "[0][1->2][3]"},
- {"corner_angle_brackets", L"\u300C\u3007\u3007\u300D", "[0][1->2][3]"},
- {"fullwidth_parens", L"\uff08\uff01\uff09", "[0][1][2]"},
+ {"matched_parens", u"(a)", "[0][1][2]"},
+ {"double_matched_parens", u"((a))", "[0->1][2][3->4]"},
+ {"double_matched_parens2", u"((aaa))", "[0->1][2->4][5->6]"},
+ {"square_brackets", u"[...]x", "[0][1->3][4][5]"},
+ {"curly_brackets", u"{}x{}", "[0->1][2][3->4]"},
+ {"style_brackets", u"「...」x", "[0][1->3][4][5]"},
+ {"tibetan_brackets", u"༺༻༠༠༼༽", "[0->1][2->3][4->5]"},
+ {"angle_brackets", u"〈〇〇〉", "[0][1->2][3]"},
+ {"double_angle_brackets", u"《〇〇》", "[0][1->2][3]"},
+ {"corner_angle_brackets", u"「〇〇」", "[0][1->2][3]"},
+ {"fullwidth_parens", u"(!)", "[0][1][2]"},
};
INSTANTIATE_TEST_SUITE_P(ItemizeTextToRunsBrackets,
@@ -1656,15 +1640,15 @@ INSTANTIATE_TEST_SUITE_P(ItemizeTextToRunsBrackets,
// account while performing the text itemization.
// See table 7 from http://www.unicode.org/reports/tr24/tr24-29.html
const RunListCase kScriptExtensionRunListCases[] = {
- {"implicit_com_inherited", L"a\u0301", "[0->1]"},
- {"explicit_lat", L"\u0061d", "[0->1]"},
- {"explicit_inherited_lat", L"x\u0363d", "[0->2]"},
- {"explicit_inherited_dev", L"क\u1CD1क", "[0->2]"},
- {"multi_explicit_hira", L"は\u30FCz", "[0->1][2]"},
- {"multi_explicit_kana", L"ハ\u30FCz", "[0->1][2]"},
- {"multi_explicit_lat", L"a\u30FCz", "[0][1][2]"},
- {"multi_explicit_impl_dev", L"क\u1CD0z", "[0->1][2]"},
- {"multi_explicit_expl_dev", L"क\u096Fz", "[0->1][2]"},
+ {"implicit_com_inherited", u"a\u0301", "[0->1]"},
+ {"explicit_lat", u"\u0061d", "[0->1]"},
+ {"explicit_inherited_lat", u"x\u0363d", "[0->2]"},
+ {"explicit_inherited_dev", u"क\u1CD1क", "[0->2]"},
+ {"multi_explicit_hira", u"は\u30FCz", "[0->1][2]"},
+ {"multi_explicit_kana", u"ハ\u30FCz", "[0->1][2]"},
+ {"multi_explicit_lat", u"a\u30FCz", "[0][1][2]"},
+ {"multi_explicit_impl_dev", u"क\u1CD0z", "[0->1][2]"},
+ {"multi_explicit_expl_dev", u"क\u096Fz", "[0->1][2]"},
};
INSTANTIATE_TEST_SUITE_P(ItemizeTextToRunsScriptExtension,
@@ -1677,111 +1661,111 @@ INSTANTIATE_TEST_SUITE_P(ItemizeTextToRunsScriptExtension,
// See ScriptExtensions.txt and Scripts.txt from
// http://www.unicode.org/reports/tr24/tr24-29.html
const RunListCase kScriptsRunListCases[] = {
- {"lat", L"abc", "[0->2]"},
- {"lat_diac", L"e\u0308f", "[0->2]"},
+ {"lat", u"abc", "[0->2]"},
+ {"lat_diac", u"e\u0308f", "[0->2]"},
// Indic Fraction codepoints have large set of script extensions.
- {"indic_fraction", L"\uA830\uA832\uA834\uA835", "[0->3]"},
+ {"indic_fraction", u"\uA830\uA832\uA834\uA835", "[0->3]"},
// Devanagari Danda codepoints have large set of script extensions.
- {"dev_danda", L"\u0964\u0965", "[0->1]"},
+ {"dev_danda", u"\u0964\u0965", "[0->1]"},
// Combining Diacritical Marks (inherited) should only merge with preceding.
- {"diac_lat", L"\u0308fg", "[0][1->2]"},
- {"diac_dev", L"क\u0308f", "[0->1][2]"},
+ {"diac_lat", u"\u0308fg", "[0][1->2]"},
+ {"diac_dev", u"क\u0308f", "[0->1][2]"},
// ZWJW has the inherited script.
- {"lat_ZWNJ", L"ab\u200Ccd", "[0->4]"},
- {"dev_ZWNJ", L"क\u200Cक", "[0->2]"},
- {"lat_dev_ZWNJ", L"a\u200Cक", "[0->1][2]"},
+ {"lat_ZWNJ", u"ab\u200Ccd", "[0->4]"},
+ {"dev_ZWNJ", u"क\u200Cक", "[0->2]"},
+ {"lat_dev_ZWNJ", u"a\u200Cक", "[0->1][2]"},
// Invalid codepoints.
- {"invalid_cp", L"\uFFFE", "[0]"},
- {"invalid_cps", L"\uFFFE\uFFFF", "[0->1]"},
- {"unknown", L"a\u243Fb", "[0][1][2]"},
+ {"invalid_cp", u"\uFFFE", "[0]"},
+ {"invalid_cps", u"\uFFFE\uFFFF", "[0->1]"},
+ {"unknown", u"a\u243Fb", "[0][1][2]"},
// Codepoints from different code block should be in same run when part of
// the same script.
- {"blocks_lat", L"aɒɠƉĚÑ", "[0->5]"},
- {"blocks_lat_paren", L"([_!_])", "[0->1][2->4][5->6]"},
- {"blocks_lat_sub", L"ₐₑaeꬱ", "[0->4]"},
- {"blocks_lat_smallcap", L"ꟺM", "[0->1]"},
- {"blocks_lat_small_letter", L"ᶓᶍᶓᴔᴟ", "[0->4]"},
- {"blocks_lat_acc", L"eéěĕȩɇḕẻếⱻꞫ", "[0->10]"},
- {"blocks_com", L"⟦ℳ¥¾⟾⁸⟧Ⓔ", "[0][1][2->3][4][5][6][7]"},
+ {"blocks_lat", u"aɒɠƉĚÑ", "[0->5]"},
+ {"blocks_lat_paren", u"([_!_])", "[0->1][2->4][5->6]"},
+ {"blocks_lat_sub", u"ₐₑaeꬱ", "[0->4]"},
+ {"blocks_lat_smallcap", u"ꟺM", "[0->1]"},
+ {"blocks_lat_small_letter", u"ᶓᶍᶓᴔᴟ", "[0->4]"},
+ {"blocks_lat_acc", u"eéěĕȩɇḕẻếⱻꞫ", "[0->10]"},
+ {"blocks_com", u"⟦ℳ¥¾⟾⁸⟧Ⓔ", "[0][1][2->3][4][5][6][7]"},
// Latin script.
- {"latin_numbers", L"a1b2c3", "[0][1][2][3][4][5]"},
- {"latin_puncts1", L"a,b,c.", "[0][1][2][3][4][5]"},
- {"latin_puncts2", L"aa,bb,cc!!", "[0->1][2][3->4][5][6->7][8->9]"},
- {"latin_diac_multi", L"a\u0300e\u0352i", "[0->4]"},
+ {"latin_numbers", u"a1b2c3", "[0][1][2][3][4][5]"},
+ {"latin_puncts1", u"a,b,c.", "[0][1][2][3][4][5]"},
+ {"latin_puncts2", u"aa,bb,cc!!", "[0->1][2][3->4][5][6->7][8->9]"},
+ {"latin_diac_multi", u"a\u0300e\u0352i", "[0->4]"},
// Common script.
- {"common_tm", L"•bug™", "[0][1->3][4]"},
- {"common_copyright", L"chromium©", "[0->7][8]"},
- {"common_math1", L"ℳ: ¬ƒ(x)=½×¾", "[0][1][2][3][4][5][6][7][8][9->11]"},
- {"common_math2", L"𝟏×𝟑", "[0->1][2][3->4]"},
- {"common_numbers", L"🄀𝟭𝟐⒓¹²", "[0->1][2->5][6][7->8]"},
- {"common_puncts", L",.\u0083!", "[0->1][2][3]"},
+ {"common_tm", u"•bug™", "[0][1->3][4]"},
+ {"common_copyright", u"chromium©", "[0->7][8]"},
+ {"common_math1", u"ℳ: ¬ƒ(x)=½×¾", "[0][1][2][3][4][5][6][7][8][9->11]"},
+ {"common_math2", u"𝟏×𝟑", "[0->1][2][3->4]"},
+ {"common_numbers", u"🄀𝟭𝟐⒓¹²", "[0->1][2->5][6][7->8]"},
+ {"common_puncts", u",.\u0083!", "[0->1][2][3]"},
// Arabic script.
- {"arabic", L"\u0633\u069b\u0763\u077f\u08A2\uFB53", "[5<-0]"},
- {"arabic_lat", L"\u0633\u069b\u0763\u077f\u08A2\uFB53abc", "[6->8][5<-0]"},
- {"arabic_word_ligatures", L"\uFDFD\uFDF3", "[1<-0]"},
- {"arabic_diac", L"\u069D\u0300", "[1<-0]"},
- {"arabic_diac_lat", L"\u069D\u0300abc", "[2->4][1<-0]"},
- {"arabic_diac_lat2", L"abc\u069D\u0300abc", "[0->2][4<-3][5->7]"},
- {"arabic_lyd", L"\U00010935\U00010930\u06B0\u06B1", "[5<-4][3<-0]"},
- {"arabic_numbers", L"12\u06D034", "[3->4][2][0->1]"},
- {"arabic_letters", L"ab\u06D0cd", "[0->1][2][3->4]"},
- {"arabic_mixed", L"a1\u06D02d", "[0][1][3][2][4]"},
- {"arabic_coptic1", L"\u06D0\U000102E2\u2CB2", "[1->3][0]"},
- {"arabic_coptic2", L"\u2CB2\U000102E2\u06D0", "[0->2][3]"},
+ {"arabic", u"\u0633\u069b\u0763\u077f\u08A2\uFB53", "[5<-0]"},
+ {"arabic_lat", u"\u0633\u069b\u0763\u077f\u08A2\uFB53abc", "[6->8][5<-0]"},
+ {"arabic_word_ligatures", u"\uFDFD\uFDF3", "[1<-0]"},
+ {"arabic_diac", u"\u069D\u0300", "[1<-0]"},
+ {"arabic_diac_lat", u"\u069D\u0300abc", "[2->4][1<-0]"},
+ {"arabic_diac_lat2", u"abc\u069D\u0300abc", "[0->2][4<-3][5->7]"},
+ {"arabic_lyd", u"\U00010935\U00010930\u06B0\u06B1", "[5<-4][3<-0]"},
+ {"arabic_numbers", u"12\u06D034", "[3->4][2][0->1]"},
+ {"arabic_letters", u"ab\u06D0cd", "[0->1][2][3->4]"},
+ {"arabic_mixed", u"a1\u06D02d", "[0][1][3][2][4]"},
+ {"arabic_coptic1", u"\u06D0\U000102E2\u2CB2", "[1->3][0]"},
+ {"arabic_coptic2", u"\u2CB2\U000102E2\u06D0", "[0->2][3]"},
// Devanagari script.
- {"devanagari1", L"ञटठडढणतथ", "[0->7]"},
- {"devanagari2", L"ढ꣸ꣴ", "[0->2]"},
- {"devanagari_vowels", L"\u0915\u093F\u0915\u094C", "[0->3]"},
- {"devanagari_consonants", L"\u0915\u094D\u0937", "[0->2]"},
+ {"devanagari1", u"ञटठडढणतथ", "[0->7]"},
+ {"devanagari2", u"ढ꣸ꣴ", "[0->2]"},
+ {"devanagari_vowels", u"\u0915\u093F\u0915\u094C", "[0->3]"},
+ {"devanagari_consonants", u"\u0915\u094D\u0937", "[0->2]"},
// Ethiopic script.
- {"ethiopic", L"መጩጪᎅⶹⶼꬣꬦ", "[0->7]"},
- {"ethiopic_numbers", L"1ቨቤ2", "[0][1->2][3]"},
- {"ethiopic_mixed1", L"abቨቤ12", "[0->1][2->3][4->5]"},
- {"ethiopic_mixed2", L"a1ቨቤb2", "[0][1][2->3][4][5]"},
+ {"ethiopic", u"መጩጪᎅⶹⶼꬣꬦ", "[0->7]"},
+ {"ethiopic_numbers", u"1ቨቤ2", "[0][1->2][3]"},
+ {"ethiopic_mixed1", u"abቨቤ12", "[0->1][2->3][4->5]"},
+ {"ethiopic_mixed2", u"a1ቨቤb2", "[0][1][2->3][4][5]"},
// Georgian script.
- {"georgian1", L"ႼႽႾႿჀჁჂჳჴჵ", "[0->9]"},
- {"georgian2", L"ლⴊⴅ", "[0->2]"},
- {"georgian_numbers", L"1ლⴊⴅ2", "[0][1->3][4]"},
- {"georgian_mixed", L"a1ლⴊⴅb2", "[0][1][2->4][5][6]"},
+ {"georgian1", u"ႼႽႾႿჀჁჂჳჴჵ", "[0->9]"},
+ {"georgian2", u"ლⴊⴅ", "[0->2]"},
+ {"georgian_numbers", u"1ლⴊⴅ2", "[0][1->3][4]"},
+ {"georgian_mixed", u"a1ლⴊⴅb2", "[0][1][2->4][5][6]"},
// Telugu script.
- {"telugu_lat", L"aaఉయ!", "[0->1][2->3][4]"},
- {"telugu_numbers", L"123౦౧౨456౩౪౫", "[0->2][3->5][6->8][9->11]"},
- {"telugu_puncts", L"కురుచ, చిఱుత, చేరువ, చెఱువు!",
+ {"telugu_lat", u"aaఉయ!", "[0->1][2->3][4]"},
+ {"telugu_numbers", u"123౦౧౨456౩౪౫", "[0->2][3->5][6->8][9->11]"},
+ {"telugu_puncts", u"కురుచ, చిఱుత, చేరువ, చెఱువు!",
"[0->4][5][6][7->11][12][13][14->18][19][20][21->26][27]"},
// Control Pictures.
- {"control_pictures", L"␑␒␓␔␕␖␗␘␙␚␛", "[0->10]"},
- {"control_pictures_rewrite", L"␑\t␛", "[0->2]"},
+ {"control_pictures", u"␑␒␓␔␕␖␗␘␙␚␛", "[0->10]"},
+ {"control_pictures_rewrite", u"␑\t␛", "[0->2]"},
// Unicode art.
- {"unicode_emoticon1", L"(▀̿ĺ̯▀̿ ̿)", "[0][1->2][3->4][5->6][7->8][9]"},
- {"unicode_emoticon2", L"▀̿̿Ĺ̯̿▀̿ ", "[0->2][3->5][6->7][8]"},
- {"unicode_emoticon3", L"( ͡° ͜ʖ ͡°)", "[0][1->2][3][4->5][6][7->8][9][10]"},
- {"unicode_emoticon4", L"✩·͙*̩̩͙˚̩̥̩̥( ͡ᵔ ͜ʖ ͡ᵔ )*̩̩͙✩·͙˚̩̥̩̥.",
+ {"unicode_emoticon1", u"(▀̿ĺ̯▀̿ ̿)", "[0][1->2][3->4][5->6][7->8][9]"},
+ {"unicode_emoticon2", u"▀̿̿Ĺ̯̿▀̿ ", "[0->2][3->5][6->7][8]"},
+ {"unicode_emoticon3", u"( ͡° ͜ʖ ͡°)", "[0][1->2][3][4->5][6][7->8][9][10]"},
+ {"unicode_emoticon4", u"✩·͙*̩̩͙˚̩̥̩̥( ͡ᵔ ͜ʖ ͡ᵔ )*̩̩͙✩·͙˚̩̥̩̥.",
"[0][1->2][3->6][7->11][12][13->14][15][16->17][18][19->20][21][22][23]["
"24->27][28][29->30][31->35][36]"},
- {"unicode_emoticon5", L"ヽ(͡◕ ͜ʖ ͡◕)ノ",
+ {"unicode_emoticon5", u"ヽ(͡◕ ͜ʖ ͡◕)ノ",
"[0][1->2][3][4->5][6][7->8][9][10][11]"},
- {"unicode_art1", L"꧁༒✧ Great ✧༒꧂", "[0][1][2][3][4->8][9][10][11][12]"},
- {"unicode_art2", L"t͎e͎s͎t͎", "[0->7]"},
+ {"unicode_art1", u"꧁༒✧ Great ✧༒꧂", "[0][1][2][3][4->8][9][10][11][12]"},
+ {"unicode_art2", u"t͎e͎s͎t͎", "[0->7]"},
// Combining diacritical sequences.
- {"unicode_diac1", L"\u2123\u0336", "[0->1]"},
- {"unicode_diac2", L"\u273c\u0325", "[0->1]"},
- {"unicode_diac3", L"\u2580\u033f", "[0->1]"},
- {"unicode_diac4", L"\u2022\u0325\u0329", "[0->2]"},
- {"unicode_diac5", L"\u2022\u0325", "[0->1]"},
- {"unicode_diac6", L"\u00b7\u0359\u0325", "[0->2]"},
- {"unicode_diac7", L"\u2027\u0329\u0325", "[0->2]"},
- {"unicode_diac8", L"\u0332\u0305\u03c1", "[0->1][2]"},
+ {"unicode_diac1", u"\u2123\u0336", "[0->1]"},
+ {"unicode_diac2", u"\u273c\u0325", "[0->1]"},
+ {"unicode_diac3", u"\u2580\u033f", "[0->1]"},
+ {"unicode_diac4", u"\u2022\u0325\u0329", "[0->2]"},
+ {"unicode_diac5", u"\u2022\u0325", "[0->1]"},
+ {"unicode_diac6", u"\u00b7\u0359\u0325", "[0->2]"},
+ {"unicode_diac7", u"\u2027\u0329\u0325", "[0->2]"},
+ {"unicode_diac8", u"\u0332\u0305\u03c1", "[0->1][2]"},
};
INSTANTIATE_TEST_SUITE_P(ItemizeTextToRunsScripts,
@@ -1795,96 +1779,96 @@ INSTANTIATE_TEST_SUITE_P(ItemizeTextToRunsScripts,
const RunListCase kEmojiRunListCases[] = {
// Samples from
// https://www.unicode.org/Public/emoji/12.0/emoji-data.txt
- {"number_sign", L"\u0023", "[0]"},
- {"keyboard", L"\u2328", "[0]"},
- {"aries", L"\u2648", "[0]"},
- {"candle", L"\U0001F56F", "[0->1]"},
- {"anchor", L"\u2693", "[0]"},
- {"grinning_face", L"\U0001F600", "[0->1]"},
- {"face_with_monocle", L"\U0001F9D0", "[0->1]"},
- {"light_skin_tone", L"\U0001F3FB", "[0->1]"},
- {"index_pointing_up", L"\u261D", "[0]"},
- {"horse_racing", L"\U0001F3C7", "[0->1]"},
- {"kiss", L"\U0001F48F", "[0->1]"},
- {"couple_with_heart", L"\U0001F491", "[0->1]"},
- {"people_wrestling", L"\U0001F93C", "[0->1]"},
- {"eject_button", L"\u23CF", "[0]"},
+ {"number_sign", u"\u0023", "[0]"},
+ {"keyboard", u"\u2328", "[0]"},
+ {"aries", u"\u2648", "[0]"},
+ {"candle", u"\U0001F56F", "[0->1]"},
+ {"anchor", u"\u2693", "[0]"},
+ {"grinning_face", u"\U0001F600", "[0->1]"},
+ {"face_with_monocle", u"\U0001F9D0", "[0->1]"},
+ {"light_skin_tone", u"\U0001F3FB", "[0->1]"},
+ {"index_pointing_up", u"\u261D", "[0]"},
+ {"horse_racing", u"\U0001F3C7", "[0->1]"},
+ {"kiss", u"\U0001F48F", "[0->1]"},
+ {"couple_with_heart", u"\U0001F491", "[0->1]"},
+ {"people_wrestling", u"\U0001F93C", "[0->1]"},
+ {"eject_button", u"\u23CF", "[0]"},
// Samples from
// https://unicode.org/Public/emoji/12.0/emoji-sequences.txt
- {"watch", L"\u231A", "[0]"},
- {"cross_mark", L"\u274C", "[0]"},
- {"copyright", L"\u00A9\uFE0F", "[0->1]"},
- {"stop_button", L"\u23F9\uFE0F", "[0->1]"},
- {"passenger_ship", L"\U0001F6F3\uFE0F", "[0->2]"},
- {"keycap_star", L"\u002A\uFE0F\u20E3", "[0->2]"},
- {"keycap_6", L"\u0036\uFE0F\u20E3", "[0->2]"},
- {"flag_andorra", L"\U0001F1E6\U0001F1E9", "[0->3]"},
- {"flag_egypt", L"\U0001F1EA\U0001F1EC", "[0->3]"},
+ {"watch", u"\u231A", "[0]"},
+ {"cross_mark", u"\u274C", "[0]"},
+ {"copyright", u"\u00A9\uFE0F", "[0->1]"},
+ {"stop_button", u"\u23F9\uFE0F", "[0->1]"},
+ {"passenger_ship", u"\U0001F6F3\uFE0F", "[0->2]"},
+ {"keycap_star", u"\u002A\uFE0F\u20E3", "[0->2]"},
+ {"keycap_6", u"\u0036\uFE0F\u20E3", "[0->2]"},
+ {"flag_andorra", u"\U0001F1E6\U0001F1E9", "[0->3]"},
+ {"flag_egypt", u"\U0001F1EA\U0001F1EC", "[0->3]"},
{"flag_england",
- L"\U0001F3F4\U000E0067\U000E0062\U000E0065\U000E006E\U000E0067\U000E007F",
+ u"\U0001F3F4\U000E0067\U000E0062\U000E0065\U000E006E\U000E0067\U000E007F",
"[0->13]"},
- {"index_up_light", L"\u261D\U0001F3FB", "[0->2]"},
- {"person_bouncing_ball_light", L"\u26F9\U0001F3FC", "[0->2]"},
- {"victory_hand_med_light", L"\u270C\U0001F3FC", "[0->2]"},
- {"horse_racing_med_dark", L"\U0001F3C7\U0001F3FE", "[0->3]"},
- {"woman_man_hands_light", L"\U0001F46B\U0001F3FB", "[0->3]"},
- {"person_haircut_med_light", L"\U0001F487\U0001F3FC", "[0->3]"},
- {"pinching_hand_light", L"\U0001F90F\U0001F3FB", "[0->3]"},
- {"love_you_light", L"\U0001F91F\U0001F3FB", "[0->3]"},
- {"leg_dark", L"\U0001F9B5\U0001F3FF", "[0->3]"},
+ {"index_up_light", u"\u261D\U0001F3FB", "[0->2]"},
+ {"person_bouncing_ball_light", u"\u26F9\U0001F3FC", "[0->2]"},
+ {"victory_hand_med_light", u"\u270C\U0001F3FC", "[0->2]"},
+ {"horse_racing_med_dark", u"\U0001F3C7\U0001F3FE", "[0->3]"},
+ {"woman_man_hands_light", u"\U0001F46B\U0001F3FB", "[0->3]"},
+ {"person_haircut_med_light", u"\U0001F487\U0001F3FC", "[0->3]"},
+ {"pinching_hand_light", u"\U0001F90F\U0001F3FB", "[0->3]"},
+ {"love_you_light", u"\U0001F91F\U0001F3FB", "[0->3]"},
+ {"leg_dark", u"\U0001F9B5\U0001F3FF", "[0->3]"},
// Samples from
// https://unicode.org/Public/emoji/12.0/emoji-variation-sequences.txt
- {"number_sign_text", L"\u0023\uFE0E", "[0->1]"},
- {"number_sign_emoji", L"\u0023\uFE0F", "[0->1]"},
- {"digit_eight_text", L"\u0038\uFE0E", "[0->1]"},
- {"digit_eight_emoji", L"\u0038\uFE0F", "[0->1]"},
- {"up_down_arrow_text", L"\u2195\uFE0E", "[0->1]"},
- {"up_down_arrow_emoji", L"\u2195\uFE0F", "[0->1]"},
- {"stopwatch_text", L"\u23F1\uFE0E", "[0->1]"},
- {"stopwatch_emoji", L"\u23F1\uFE0F", "[0->1]"},
- {"thermometer_text", L"\U0001F321\uFE0E", "[0->2]"},
- {"thermometer_emoji", L"\U0001F321\uFE0F", "[0->2]"},
- {"thumbs_up_text", L"\U0001F44D\uFE0E", "[0->2]"},
- {"thumbs_up_emoji", L"\U0001F44D\uFE0F", "[0->2]"},
- {"hole_text", L"\U0001F573\uFE0E", "[0->2]"},
- {"hole_emoji", L"\U0001F573\uFE0F", "[0->2]"},
+ {"number_sign_text", u"\u0023\uFE0E", "[0->1]"},
+ {"number_sign_emoji", u"\u0023\uFE0F", "[0->1]"},
+ {"digit_eight_text", u"\u0038\uFE0E", "[0->1]"},
+ {"digit_eight_emoji", u"\u0038\uFE0F", "[0->1]"},
+ {"up_down_arrow_text", u"\u2195\uFE0E", "[0->1]"},
+ {"up_down_arrow_emoji", u"\u2195\uFE0F", "[0->1]"},
+ {"stopwatch_text", u"\u23F1\uFE0E", "[0->1]"},
+ {"stopwatch_emoji", u"\u23F1\uFE0F", "[0->1]"},
+ {"thermometer_text", u"\U0001F321\uFE0E", "[0->2]"},
+ {"thermometer_emoji", u"\U0001F321\uFE0F", "[0->2]"},
+ {"thumbs_up_text", u"\U0001F44D\uFE0E", "[0->2]"},
+ {"thumbs_up_emoji", u"\U0001F44D\uFE0F", "[0->2]"},
+ {"hole_text", u"\U0001F573\uFE0E", "[0->2]"},
+ {"hole_emoji", u"\U0001F573\uFE0F", "[0->2]"},
// Samples from
// https://unicode.org/Public/emoji/12.0/emoji-zwj-sequences.txt
- {"couple_man_man", L"\U0001F468\u200D\u2764\uFE0F\u200D\U0001F468",
+ {"couple_man_man", u"\U0001F468\u200D\u2764\uFE0F\u200D\U0001F468",
"[0->7]"},
{"kiss_man_man",
- L"\U0001F468\u200D\u2764\uFE0F\u200D\U0001F48B\u200D\U0001F468",
+ u"\U0001F468\u200D\u2764\uFE0F\u200D\U0001F48B\u200D\U0001F468",
"[0->10]"},
{"family_man_woman_girl_boy",
- L"\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466", "[0->10]"},
+ u"\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466", "[0->10]"},
{"men_hands_dark_medium",
- L"\U0001F468\U0001F3FF\u200D\U0001F91D\u200D\U0001F468\U0001F3FD",
+ u"\U0001F468\U0001F3FF\u200D\U0001F91D\u200D\U0001F468\U0001F3FD",
"[0->11]"},
{"people_hands_dark",
- L"\U0001F9D1\U0001F3FF\u200D\U0001F91D\u200D\U0001F9D1\U0001F3FF",
+ u"\U0001F9D1\U0001F3FF\u200D\U0001F91D\u200D\U0001F9D1\U0001F3FF",
"[0->11]"},
- {"man_pilot", L"\U0001F468\u200D\u2708\uFE0F", "[0->4]"},
- {"man_scientist", L"\U0001F468\u200D\U0001F52C", "[0->4]"},
- {"man_mechanic_light", L"\U0001F468\U0001F3FB\u200D\U0001F527", "[0->6]"},
- {"man_judge_medium", L"\U0001F468\U0001F3FD\u200D\u2696\uFE0F", "[0->6]"},
- {"woman_cane_dark", L"\U0001F469\U0001F3FF\u200D\U0001F9AF", "[0->6]"},
- {"woman_ball_light", L"\u26F9\U0001F3FB\u200D\u2640\uFE0F", "[0->5]"},
- {"woman_running", L"\U0001F3C3\u200D\u2640\uFE0F", "[0->4]"},
- {"woman_running_dark", L"\U0001F3C3\U0001F3FF\u200D\u2640\uFE0F", "[0->6]"},
- {"woman_turban", L"\U0001F473\u200D\u2640\uFE0F", "[0->4]"},
- {"woman_detective", L"\U0001F575\uFE0F\u200D\u2640\uFE0F", "[0->5]"},
- {"man_facepalming", L"\U0001F926\u200D\u2642\uFE0F", "[0->4]"},
- {"man_red_hair", L"\U0001F468\u200D\U0001F9B0", "[0->4]"},
- {"man_medium_curly", L"\U0001F468\U0001F3FD\u200D\U0001F9B1", "[0->6]"},
- {"woman_dark_white_hair", L"\U0001F469\U0001F3FF\u200D\U0001F9B3",
+ {"man_pilot", u"\U0001F468\u200D\u2708\uFE0F", "[0->4]"},
+ {"man_scientist", u"\U0001F468\u200D\U0001F52C", "[0->4]"},
+ {"man_mechanic_light", u"\U0001F468\U0001F3FB\u200D\U0001F527", "[0->6]"},
+ {"man_judge_medium", u"\U0001F468\U0001F3FD\u200D\u2696\uFE0F", "[0->6]"},
+ {"woman_cane_dark", u"\U0001F469\U0001F3FF\u200D\U0001F9AF", "[0->6]"},
+ {"woman_ball_light", u"\u26F9\U0001F3FB\u200D\u2640\uFE0F", "[0->5]"},
+ {"woman_running", u"\U0001F3C3\u200D\u2640\uFE0F", "[0->4]"},
+ {"woman_running_dark", u"\U0001F3C3\U0001F3FF\u200D\u2640\uFE0F", "[0->6]"},
+ {"woman_turban", u"\U0001F473\u200D\u2640\uFE0F", "[0->4]"},
+ {"woman_detective", u"\U0001F575\uFE0F\u200D\u2640\uFE0F", "[0->5]"},
+ {"man_facepalming", u"\U0001F926\u200D\u2642\uFE0F", "[0->4]"},
+ {"man_red_hair", u"\U0001F468\u200D\U0001F9B0", "[0->4]"},
+ {"man_medium_curly", u"\U0001F468\U0001F3FD\u200D\U0001F9B1", "[0->6]"},
+ {"woman_dark_white_hair", u"\U0001F469\U0001F3FF\u200D\U0001F9B3",
"[0->6]"},
- {"rainbow_flag", L"\U0001F3F3\uFE0F\u200D\U0001F308", "[0->5]"},
- {"pirate_flag", L"\U0001F3F4\u200D\u2620\uFE0F", "[0->4]"},
- {"service_dog", L"\U0001F415\u200D\U0001F9BA", "[0->4]"},
- {"eye_bubble", L"\U0001F441\uFE0F\u200D\U0001F5E8\uFE0F", "[0->6]"},
+ {"rainbow_flag", u"\U0001F3F3\uFE0F\u200D\U0001F308", "[0->5]"},
+ {"pirate_flag", u"\U0001F3F4\u200D\u2620\uFE0F", "[0->4]"},
+ {"service_dog", u"\U0001F415\u200D\U0001F9BA", "[0->4]"},
+ {"eye_bubble", u"\U0001F441\uFE0F\u200D\U0001F5E8\uFE0F", "[0->6]"},
};
INSTANTIATE_TEST_SUITE_P(ItemizeTextToRunsEmoji,
@@ -1901,15 +1885,15 @@ const bool kForceWhitespaceElision = true;
struct ElideTextCase {
const char* test_name;
- const wchar_t* text;
- const wchar_t* display_text;
+ const char16_t* text;
+ const char16_t* display_text;
// The available width, specified as a number of fixed-width glyphs. If no
// value is specified, the width of the resulting |display_text| is used. This
// helps test available widths larger than the resulting test; e.g. "a b"
- // should yield "a\u2026" even if 3 glyph widths are available, when
+ // should yield "a…" even if 3 glyph widths are available, when
// whitespace elision is enabled.
- const base::Optional<size_t> available_width_as_glyph_count = base::nullopt;
- const base::Optional<bool> whitespace_elision = base::nullopt;
+ const absl::optional<size_t> available_width_as_glyph_count = absl::nullopt;
+ const absl::optional<bool> whitespace_elision = absl::nullopt;
};
using ElideTextCaseParam = std::tuple<ElideTextTestOptions, ElideTextCase>;
@@ -1931,8 +1915,8 @@ TEST_P(RenderTextTestWithElideTextCase, ElideText) {
const ElideTextTestOptions options = std::get<0>(GetParam());
const ElideTextCase param = std::get<1>(GetParam());
- const std::u16string text = WideToUTF16(param.text);
- const std::u16string display_text = WideToUTF16(param.display_text);
+ const std::u16string text = param.text;
+ const std::u16string display_text = param.display_text;
// Retrieve the display_text width without eliding.
RenderTextHarfBuzz* render_text = GetRenderText();
@@ -1968,68 +1952,64 @@ TEST_P(RenderTextTestWithElideTextCase, ElideText) {
}
const ElideTextCase kElideHeadTextCases[] = {
- {"empty", L"", L""},
- {"letter_m_tail0", L"M", L""},
- {"letter_m_tail1", L"M", L"M"},
- {"no_eliding", L"012ab", L"012ab"},
- {"ltr_3", L"abc", L"abc"},
- {"ltr_2", L"abc", L"\u2026c"},
- {"ltr_1", L"abc", L"\u2026"},
- {"ltr_0", L"abc", L""},
- {"rtl_3", L"\u05d0\u05d1\u05d2", L"\u05d0\u05d1\u05d2"},
- {"rtl_2", L"\u05d0\u05d1\u05d2", L"\u2026\u05d2"},
- {"rtl_1", L"\u05d0\u05d1\u05d2", L"\u2026"},
- {"rtl_0", L"\u05d0\u05d1\u05d2", L""},
- {"ltr_rtl_5", L"abc\u05d0\u05d1\u05d2", L"\u2026c\u05d0\u05d1\u05d2"},
- {"ltr_rtl_4", L"abc\u05d0\u05d1\u05d2", L"\u2026\u05d0\u05d1\u05d2"},
- {"ltr_rtl_3", L"abc\u05d0\u05d1\u05d2", L"\u2026\u05d1\u05d2"},
- {"rtl_ltr_5", L"\u05d0\u05d1\u05d2abc", L"\u2026\u05d2abc"},
- {"rtl_ltr_4", L"\u05d0\u05d1\u05d2abc", L"\u2026abc"},
- {"rtl_ltr_3", L"\u05d0\u05d1\u05d2abc", L"\u2026bc"},
- {"bidi_1", L"a\u05d1b\u05d1c012", L"\u2026b\u05d1c012"},
- {"bidi_2", L"a\u05d1b\u05d1c012", L"\u2026\u05d1c012"},
- {"bidi_3", L"a\u05d1b\u05d1c012", L"\u2026c012"},
+ {"empty", u"", u""},
+ {"letter_m_tail0", u"M", u""},
+ {"letter_m_tail1", u"M", u"M"},
+ {"no_eliding", u"012ab", u"012ab"},
+ {"ltr_3", u"abc", u"abc"},
+ {"ltr_2", u"abc", u"…c"},
+ {"ltr_1", u"abc", u"…"},
+ {"ltr_0", u"abc", u""},
+ {"rtl_3", u"אבג", u"אבג"},
+ {"rtl_2", u"אבג", u"…ג"},
+ {"rtl_1", u"אבג", u"…"},
+ {"rtl_0", u"אבג", u""},
+ {"ltr_rtl_5", u"abcאבג", u"…cאבג"},
+ {"ltr_rtl_4", u"abcאבג", u"…אבג"},
+ {"ltr_rtl_3", u"abcאבג", u"…בג"},
+ {"rtl_ltr_5", u"אבגabc", u"…גabc"},
+ {"rtl_ltr_4", u"אבגabc", u"…abc"},
+ {"rtl_ltr_3", u"אבגabc", u"…bc"},
+ {"bidi_1", u"aבbבc012", u"…bבc012"},
+ {"bidi_2", u"aבbבc012", u"…בc012"},
+ {"bidi_3", u"aבbבc012", u"…c012"},
// Test surrogate pairs. No surrogate pair should be partially elided.
- {"surrogate1", L"abc\U0001D11E\U0001D122x", L"\u2026\U0001D11E\U0001D122x"},
- {"surrogate2", L"abc\U0001D11E\U0001D122x", L"\u2026\U0001D122x"},
- {"surrogate3", L"abc\U0001D11E\U0001D122x", L"\u2026x"},
+ {"surrogate1", u"abc\U0001D11E\U0001D122x", u"…\U0001D11E\U0001D122x"},
+ {"surrogate2", u"abc\U0001D11E\U0001D122x", u"…\U0001D122x"},
+ {"surrogate3", u"abc\U0001D11E\U0001D122x", u"…x"},
// Test combining character sequences. U+0915 U+093F forms a compound
// glyph, as does U+0915 U+0942. No combining sequence should be partially
// elided.
- {"combining1", L"0123\u0915\u093f\u0915\u0942456",
- L"\u2026\u0915\u0942456"},
- {"combining2", L"0123\u0915\u093f\u0915\u0942456", L"\u2026456"},
+ {"combining1", u"0123\u0915\u093f\u0915\u0942456", u"…\u0915\u0942456"},
+ {"combining2", u"0123\u0915\u093f\u0915\u0942456", u"…456"},
// 𝄞 (U+1D11E, MUSICAL SYMBOL G CLEF) should be fully elided.
- {"emoji1", L"012\U0001D11Ex", L"\u2026\U0001D11Ex"},
- {"emoji2", L"012\U0001D11Ex", L"\u2026x"},
+ {"emoji1", u"012\U0001D11Ex", u"…\U0001D11Ex"},
+ {"emoji2", u"012\U0001D11Ex", u"…x"},
// Whitespace elision tests.
- {"empty_no_elision", L"", L"", 0, kForceNoWhitespaceElision},
- {"empty_elision", L"", L"", 0, kForceWhitespaceElision},
- {"xyz_no_elision", L" x xyz", L"\u2026 xyz", 5,
- kForceNoWhitespaceElision},
- {"xyz_elision", L" x xyz", L"\u2026xyz", 5, kForceWhitespaceElision},
- {"ltr_rtl_elision3", L"x \u05d1 y \u05d2", L"\u2026\u05d2", 3,
+ {"empty_no_elision", u"", u"", 0, kForceNoWhitespaceElision},
+ {"empty_elision", u"", u"", 0, kForceWhitespaceElision},
+ {"xyz_no_elision", u" x xyz", u"… xyz", 5, kForceNoWhitespaceElision},
+ {"xyz_elision", u" x xyz", u"…xyz", 5, kForceWhitespaceElision},
+ {"ltr_rtl_elision3", u"x ב y ג", u"…ג", 3, kForceWhitespaceElision},
+ {"ltr_rtl_elision6", u"x ב y ג", u"…ג", 6, kForceWhitespaceElision},
+ {"ltr_rtl_elision7", u"x ב y ג", u"…y ג", 7,
kForceWhitespaceElision},
- {"ltr_rtl_elision6", L"x \u05d1 y \u05d2", L"\u2026\u05d2", 6,
+ {"ltr_rtl_elision10", u"x ב y ג", u"…ב y ג", 10,
kForceWhitespaceElision},
- {"ltr_rtl_elision7", L"x \u05d1 y \u05d2", L"\u2026y \u05d2", 7,
+ {"ltr_rtl_elision11", u"x ב y ג", u"…ב y ג", 11,
kForceWhitespaceElision},
- {"ltr_rtl_elision10", L"x \u05d1 y \u05d2",
- L"\u2026\u05d1 y \u05d2", 10, kForceWhitespaceElision},
- {"ltr_rtl_elision11", L"x \u05d1 y \u05d2",
- L"\u2026\u05d1 y \u05d2", 11, kForceWhitespaceElision},
// Emoji U+1F601 and emoji U+1F321 U+FE0E are graphemes that result in
// one glyph each. Eliding a glyph must remove the whole grapheme. It is
// invalid to break a grapheme in pieces.
- {"graphemes_elision3", L" \U0001F601 \U0001F321\uFE0E ", L"\u2026", 3,
+ {"graphemes_elision3", u" \U0001F601 \U0001F321\uFE0E ", u"…", 3,
kForceWhitespaceElision},
- {"graphemes_elision4", L" \U0001F601 \U0001F321\uFE0E ",
- L"\u2026\U0001F321\uFE0E ", 4, kForceWhitespaceElision},
- {"graphemes_elision6", L" \U0001F601 \U0001F321\uFE0E ",
- L"\u2026\U0001F321\uFE0E ", 6, kForceWhitespaceElision},
- {"graphemes_elision7", L" \U0001F601 \U0001F321\uFE0E ",
- L"\u2026\U0001F601 \U0001F321\uFE0E ", 7, kForceWhitespaceElision},
+ {"graphemes_elision4", u" \U0001F601 \U0001F321\uFE0E ",
+ u"…\U0001F321\uFE0E ", 4, kForceWhitespaceElision},
+ {"graphemes_elision6", u" \U0001F601 \U0001F321\uFE0E ",
+ u"…\U0001F321\uFE0E ", 6, kForceWhitespaceElision},
+ {"graphemes_elision7", u" \U0001F601 \U0001F321\uFE0E ",
+ u"…\U0001F601 \U0001F321\uFE0E ", 7, kForceWhitespaceElision},
};
INSTANTIATE_TEST_SUITE_P(
@@ -2040,75 +2020,71 @@ INSTANTIATE_TEST_SUITE_P(
RenderTextTestWithElideTextCase::ParamInfoToString);
const ElideTextCase kElideTailTextCases[] = {
- {"empty", L"", L""},
- {"letter_m_tail0", L"M", L""},
- {"letter_m_tail1", L"M", L"M"},
- {"letter_weak_3", L" . ", L" . "},
- {"letter_weak_2", L" . ", L"\u2026"},
- {"no_eliding", L"012ab", L"012ab"},
- {"ltr_3", L"abc", L"abc"},
- {"ltr_2", L"abc", L"a\u2026"},
- {"ltr_1", L"abc", L"\u2026"},
- {"ltr_0", L"abc", L""},
- {"rtl_3", L"\u05d0\u05d1\u05d2", L"\u05d0\u05d1\u05d2"},
- {"rtl_2", L"\u05d0\u05d1\u05d2", L"\u05d0\u2026"},
- {"rtl_1", L"\u05d0\u05d1\u05d2", L"\u2026"},
- {"rtl_0", L"\u05d0\u05d1\u05d2", L""},
- {"ltr_rtl_5", L"abc\u05d0\u05d1\u05d2", L"abc\u05d0\u2026\u200F"},
- {"ltr_rtl_4", L"abc\u05d0\u05d1\u05d2", L"abc\u2026"},
- {"ltr_rtl_3", L"abc\u05d0\u05d1\u05d2", L"ab\u2026"},
- {"rtl_ltr_5", L"\u05d0\u05d1\u05d2abc", L"\u05d0\u05d1\u05d2a\u2026\u200E"},
- {"rtl_ltr_4", L"\u05d0\u05d1\u05d2abc", L"\u05d0\u05d1\u05d2\u2026"},
- {"rtl_ltr_3", L"\u05d0\u05d1\u05d2abc", L"\u05d0\u05d1\u2026"},
- {"bidi_1", L"012a\u05d1b\u05d1c", L"012a\u2026"},
- {"bidi_2", L"012a\u05d1b\u05d1c", L"012a\u05d1\u2026\u200F"},
- {"bidi_3", L"012a\u05d1b\u05d1c", L"012a\u05d1b\u2026"},
+ {"empty", u"", u""},
+ {"letter_m_tail0", u"M", u""},
+ {"letter_m_tail1", u"M", u"M"},
+ {"letter_weak_3", u" . ", u" . "},
+ {"letter_weak_2", u" . ", u"…"},
+ {"no_eliding", u"012ab", u"012ab"},
+ {"ltr_3", u"abc", u"abc"},
+ {"ltr_2", u"abc", u"a…"},
+ {"ltr_1", u"abc", u"…"},
+ {"ltr_0", u"abc", u""},
+ {"rtl_3", u"אבג", u"אבג"},
+ {"rtl_2", u"אבג", u"א…"},
+ {"rtl_1", u"אבג", u"…"},
+ {"rtl_0", u"אבג", u""},
+ {"ltr_rtl_5", u"abcאבג", u"abcא…\u200F"},
+ {"ltr_rtl_4", u"abcאבג", u"abc…"},
+ {"ltr_rtl_3", u"abcאבג", u"ab…"},
+ {"rtl_ltr_5", u"אבגabc", u"אבגa…\u200E"},
+ {"rtl_ltr_4", u"אבגabc", u"אבג…"},
+ {"rtl_ltr_3", u"אבגabc", u"אב…"},
+ {"bidi_1", u"012aבbבc", u"012a…"},
+ {"bidi_2", u"012aבbבc", u"012aב…\u200F"},
+ {"bidi_3", u"012aבbבc", u"012aבb…"},
// No RLM marker added as digits (012) have weak directionality.
- {"no_rlm", L"01\u05d0\u05d1\u05d2", L"01\u05d0\u2026"},
+ {"no_rlm", u"01אבג", u"01א…"},
// RLM marker added as "ab" have strong LTR directionality.
- {"with_rlm", L"ab\u05d0\u05d1\u05d2cd", L"ab\u05d0\u05d1\u2026\u200f"},
+ {"with_rlm", u"abאבגcd", u"abאב…\u200f"},
// Test surrogate pairs. The first pair 𝄞 'MUSICAL SYMBOL G CLEF' U+1D11E
// should be kept, and the second pair 𝄢 'MUSICAL SYMBOL F CLEF' U+1D122
// should be removed. No surrogate pair should be partially elided.
- {"surrogate", L"0123\U0001D11E\U0001D122x", L"0123\U0001D11E\u2026"},
+ {"surrogate", u"0123\U0001D11E\U0001D122x", u"0123\U0001D11E…"},
// Test combining character sequences. U+0915 U+093F forms a compound
// glyph, as does U+0915 U+0942. The first should be kept; the second
// removed. No combining sequence should be partially elided.
- {"combining", L"0123\u0915\u093f\u0915\u0942456",
- L"0123\u0915\u093f\u2026"},
+ {"combining", u"0123\u0915\u093f\u0915\u0942456", u"0123\u0915\u093f…"},
// U+05E9 U+05BC U+05C1 U+05B8 forms a four-character compound glyph.
// It should be either fully elided, or not elided at all. If completely
// elided, an LTR Mark (U+200E) should be added.
- {"grapheme1", L"0\u05e9\u05bc\u05c1\u05b8", L"0\u05e9\u05bc\u05c1\u05b8"},
- {"grapheme2", L"0\u05e9\u05bc\u05c1\u05b8abc", L"0\u2026\u200E"},
- {"grapheme3", L"01\u05e9\u05bc\u05c1\u05b8abc", L"01\u2026\u200E"},
- {"grapheme4", L"012\u05e9\u05bc\u05c1\u05b8abc", L"012\u2026\u200E"},
+ {"grapheme1", u"0\u05e9\u05bc\u05c1\u05b8", u"0\u05e9\u05bc\u05c1\u05b8"},
+ {"grapheme2", u"0\u05e9\u05bc\u05c1\u05b8abc", u"0…\u200E"},
+ {"grapheme3", u"01\u05e9\u05bc\u05c1\u05b8abc", u"01…\u200E"},
+ {"grapheme4", u"012\u05e9\u05bc\u05c1\u05b8abc", u"012…\u200E"},
// 𝄞 (U+1D11E, MUSICAL SYMBOL G CLEF) should be fully elided.
- {"emoji", L"012\U0001D11Ex", L"012\u2026"},
+ {"emoji", u"012\U0001D11Ex", u"012…"},
// Whitespace elision tests.
- {"empty_no_elision", L"", L"", 0, kForceNoWhitespaceElision},
- {"empty_elision", L"", L"", 0, kForceWhitespaceElision},
- {"letter_weak_2_no_elision", L" . ", L" \u2026", 2,
- kForceNoWhitespaceElision},
- {"xyz_no_elision", L" x xyz", L" x \u2026", 5,
- kForceNoWhitespaceElision},
- {"xyz_elision", L" x xyz", L" x\u2026", 5, kForceWhitespaceElision},
- {"ltr_rtl_elision4", L"x \u05d1 y \u05d2", L"x\u2026", 4,
- kForceWhitespaceElision},
- {"ltr_rtl_elision5", L"x \u05d1 y \u05d2", L"x \u05d1\u2026\u200F", 5,
+ {"empty_no_elision", u"", u"", 0, kForceNoWhitespaceElision},
+ {"empty_elision", u"", u"", 0, kForceWhitespaceElision},
+ {"letter_weak_2_no_elision", u" . ", u" …", 2, kForceNoWhitespaceElision},
+ {"xyz_no_elision", u" x xyz", u" x …", 5, kForceNoWhitespaceElision},
+ {"xyz_elision", u" x xyz", u" x…", 5, kForceWhitespaceElision},
+ {"ltr_rtl_elision4", u"x ב y ג", u"x…", 4, kForceWhitespaceElision},
+ {"ltr_rtl_elision5", u"x ב y ג", u"x ב…\u200F", 5,
kForceWhitespaceElision},
- {"ltr_rtl_elision9", L"x \u05d1 y \u05d2", L"x \u05d1 y\u2026", 9,
+ {"ltr_rtl_elision9", u"x ב y ג", u"x ב y…", 9,
kForceWhitespaceElision},
// Emoji U+1F601 and emoji U+1F321 U+FE0E are graphemes that result in
// one glyph each. Eliding a glyph must remove the whole grapheme. It is
// invalid to break a grapheme in pieces.
- {"graphemes_elision3", L" \U0001F601 \U0001F321\uFE0E ", L"\u2026", 3,
+ {"graphemes_elision3", u" \U0001F601 \U0001F321\uFE0E ", u"…", 3,
kForceWhitespaceElision},
- {"graphemes_elision6", L" \U0001F601 \U0001F321\uFE0E ",
- L" \U0001F601\u2026", 6, kForceWhitespaceElision},
- {"graphemes_elision7", L" \U0001F601 \U0001F321\uFE0E ",
- L" \U0001F601 \U0001F321\uFE0E\u2026", 7, kForceWhitespaceElision},
+ {"graphemes_elision6", u" \U0001F601 \U0001F321\uFE0E ",
+ u" \U0001F601…", 6, kForceWhitespaceElision},
+ {"graphemes_elision7", u" \U0001F601 \U0001F321\uFE0E ",
+ u" \U0001F601 \U0001F321\uFE0E…", 7, kForceWhitespaceElision},
};
INSTANTIATE_TEST_SUITE_P(
@@ -2119,70 +2095,67 @@ INSTANTIATE_TEST_SUITE_P(
RenderTextTestWithElideTextCase::ParamInfoToString);
const ElideTextCase kElideTruncateTextCases[] = {
- {"empty", L"", L""},
- {"letter_m_tail0", L"M", L""},
- {"letter_m_tail1", L"M", L"M"},
- {"no_eliding", L"012ab", L"012ab"},
- {"ltr_3", L"abc", L"abc"},
- {"ltr_2", L"abc", L"ab"},
- {"ltr_1", L"abc", L"a"},
- {"ltr_0", L"abc", L""},
- {"rtl_3", L"\u05d0\u05d1\u05d2", L"\u05d0\u05d1\u05d2"},
- {"rtl_2", L"\u05d0\u05d1\u05d2", L"\u05d0\u05d1"},
- {"rtl_1", L"\u05d0\u05d1\u05d2", L"\u05d0"},
- {"rtl_0", L"\u05d0\u05d1\u05d2", L""},
- {"ltr_rtl_5", L"abc\u05d0\u05d1\u05d2", L"abc\u05d0\u05d1"},
- {"ltr_rtl_4", L"abc\u05d0\u05d1\u05d2", L"abc\u05d0"},
- {"ltr_rtl_3", L"abc\u05d0\u05d1\u05d2", L"abc"},
- {"ltr_rtl_2", L"abc\u05d0\u05d1\u05d2", L"ab"},
- {"rtl_ltr_5", L"\u05d0\u05d1\u05d2abc", L"\u05d0\u05d1\u05d2ab"},
- {"rtl_ltr_4", L"\u05d0\u05d1\u05d2abc", L"\u05d0\u05d1\u05d2a"},
- {"rtl_ltr_3", L"\u05d0\u05d1\u05d2abc", L"\u05d0\u05d1\u05d2"},
- {"rtl_ltr_2", L"\u05d0\u05d1\u05d2abc", L"\u05d0\u05d1"},
- {"bidi_1", L"012a\u05d1b\u05d1c", L"012a\u05d1b\u05d1"},
- {"bidi_2", L"012a\u05d1b\u05d1c", L"012a\u05d1b"},
- {"bidi_3", L"012a\u05d1b\u05d1c", L"012a\u05d1"},
- {"bidi_4", L"012a\u05d1b\u05d1c", L"012a\u05d1"},
+ {"empty", u"", u""},
+ {"letter_m_tail0", u"M", u""},
+ {"letter_m_tail1", u"M", u"M"},
+ {"no_eliding", u"012ab", u"012ab"},
+ {"ltr_3", u"abc", u"abc"},
+ {"ltr_2", u"abc", u"ab"},
+ {"ltr_1", u"abc", u"a"},
+ {"ltr_0", u"abc", u""},
+ {"rtl_3", u"אבג", u"אבג"},
+ {"rtl_2", u"אבג", u"אב"},
+ {"rtl_1", u"אבג", u"א"},
+ {"rtl_0", u"אבג", u""},
+ {"ltr_rtl_5", u"abcאבג", u"abcאב"},
+ {"ltr_rtl_4", u"abcאבג", u"abcא"},
+ {"ltr_rtl_3", u"abcאבג", u"abc"},
+ {"ltr_rtl_2", u"abcאבג", u"ab"},
+ {"rtl_ltr_5", u"אבגabc", u"אבגab"},
+ {"rtl_ltr_4", u"אבגabc", u"אבגa"},
+ {"rtl_ltr_3", u"אבגabc", u"אבג"},
+ {"rtl_ltr_2", u"אבגabc", u"אב"},
+ {"bidi_1", u"012aבbבc", u"012aבbב"},
+ {"bidi_2", u"012aבbבc", u"012aבb"},
+ {"bidi_3", u"012aבbבc", u"012aב"},
+ {"bidi_4", u"012aבbבc", u"012aב"},
// Test surrogate pairs. The first pair 𝄞 'MUSICAL SYMBOL G CLEF' U+1D11E
// should be kept, and the second pair 𝄢 'MUSICAL SYMBOL F CLEF' U+1D122
// should be removed. No surrogate pair should be partially elided.
- {"surrogate1", L"0123\U0001D11E\U0001D122x", L"0123\U0001D11E\U0001D122"},
- {"surrogate2", L"0123\U0001D11E\U0001D122x", L"0123\U0001D11E"},
- {"surrogate3", L"0123\U0001D11E\U0001D122x", L"0123"},
+ {"surrogate1", u"0123\U0001D11E\U0001D122x", u"0123\U0001D11E\U0001D122"},
+ {"surrogate2", u"0123\U0001D11E\U0001D122x", u"0123\U0001D11E"},
+ {"surrogate3", u"0123\U0001D11E\U0001D122x", u"0123"},
// Test combining character sequences. U+0915 U+093F forms a compound
// glyph, as does U+0915 U+0942. The first should be kept; the second
// removed. No combining sequence should be partially elided.
- {"combining", L"0123\u0915\u093f\u0915\u0942456", L"0123\u0915\u093f"},
+ {"combining", u"0123\u0915\u093f\u0915\u0942456", u"0123\u0915\u093f"},
// 𝄞 (U+1D11E, MUSICAL SYMBOL G CLEF) should be fully elided.
- {"emoji1", L"012\U0001D11Ex", L"012\U0001D11E"},
- {"emoji2", L"012\U0001D11Ex", L"012"},
+ {"emoji1", u"012\U0001D11Ex", u"012\U0001D11E"},
+ {"emoji2", u"012\U0001D11Ex", u"012"},
// Whitespace elision tests.
- {"empty_no_elision", L"", L"", 0, kForceNoWhitespaceElision},
- {"empty_elision", L"", L"", 0, kForceWhitespaceElision},
- {"xyz_no_elision", L" x xyz", L" x ", 5, kForceNoWhitespaceElision},
- {"xyz_elision", L" x xyz", L" x", 5, kForceWhitespaceElision},
- {"ltr_rtl_elision3", L"x \u05d1 y \u05d2", L"x", 3,
- kForceWhitespaceElision},
- {"ltr_rtl_elision4", L"x \u05d1 y \u05d2", L"x \u05d1", 4,
- kForceWhitespaceElision},
- {"ltr_rtl_elision5", L"x \u05d1 y \u05d2", L"x \u05d1", 5,
- kForceWhitespaceElision},
- {"ltr_rtl_elision9", L"x \u05d1 y \u05d2", L"x \u05d1 y", 9,
+ {"empty_no_elision", u"", u"", 0, kForceNoWhitespaceElision},
+ {"empty_elision", u"", u"", 0, kForceWhitespaceElision},
+ {"xyz_no_elision", u" x xyz", u" x ", 5, kForceNoWhitespaceElision},
+ {"xyz_elision", u" x xyz", u" x", 5, kForceWhitespaceElision},
+ {"ltr_rtl_elision3", u"x ב y ג", u"x", 3, kForceWhitespaceElision},
+ {"ltr_rtl_elision4", u"x ב y ג", u"x ב", 4, kForceWhitespaceElision},
+ {"ltr_rtl_elision5", u"x ב y ג", u"x ב", 5, kForceWhitespaceElision},
+ {"ltr_rtl_elision9", u"x ב y ג", u"x ב y", 9,
kForceWhitespaceElision},
// Emoji U+1F601 and emoji U+1F321 U+FE0E are graphemes that result in
// one glyph each. Eliding a glyph must remove the whole grapheme. It is
// invalid to break a grapheme in pieces.
- {"graphemes_elision2", L" \U0001F601 \U0001F321\uFE0E ", L"", 2,
+ {"graphemes_elision2", u" \U0001F601 \U0001F321\uFE0E ", u"", 2,
kForceWhitespaceElision},
- {"graphemes_elision3", L" \U0001F601 \U0001F321\uFE0E ", L" \U0001F601",
+ {"graphemes_elision3", u" \U0001F601 \U0001F321\uFE0E ", u" \U0001F601",
3, kForceWhitespaceElision},
- {"graphemes_elision5", L" \U0001F601 \U0001F321\uFE0E ", L" \U0001F601",
+ {"graphemes_elision5", u" \U0001F601 \U0001F321\uFE0E ", u" \U0001F601",
5, kForceWhitespaceElision},
- {"graphemes_elision6", L" \U0001F601 \U0001F321\uFE0E ",
- L" \U0001F601 \U0001F321\uFE0E", 6, kForceWhitespaceElision},
- {"graphemes_elision7", L" \U0001F601 \U0001F321\uFE0E ",
- L" \U0001F601 \U0001F321\uFE0E", 7, kForceWhitespaceElision},
+ {"graphemes_elision6", u" \U0001F601 \U0001F321\uFE0E ",
+ u" \U0001F601 \U0001F321\uFE0E", 6, kForceWhitespaceElision},
+ {"graphemes_elision7", u" \U0001F601 \U0001F321\uFE0E ",
+ u" \U0001F601 \U0001F321\uFE0E", 7, kForceWhitespaceElision},
};
INSTANTIATE_TEST_SUITE_P(
@@ -2194,44 +2167,44 @@ INSTANTIATE_TEST_SUITE_P(
const ElideTextCase kElideEmailTextCases[] = {
// Invalid email text.
- {"empty", L"", L""},
- {"invalid_char1", L"x", L""},
- {"invalid_char3", L"xyz", L"x\u2026"},
- {"invalid_amp", L"@", L""},
- {"invalid_no_prefix0", L"@y", L""},
- {"invalid_no_prefix1", L"@y", L"\u2026"},
- {"invalid_no_prefix2", L"@xyz", L"@x\u2026"},
- {"invalid_no_suffix0", L"x@", L""},
- {"invalid_no_suffix1", L"x@", L"\u2026"},
- {"invalid_no_suffix2", L"xyz@", L"x\u2026@"},
-
- {"at1", L"@", L"@"},
- {"at2", L"@@", L"\u2026", 1},
- {"at3", L"@@@", L"\u2026", 2},
- {"at4", L"@@@@", L"@\u2026@", 3},
-
- {"small1", L"a@b", L"\u2026", 1},
- {"small2", L"a@b", L"\u2026", 2},
- {"small3", L"a@b", L"a@b", 3},
- {"small_username3", L"xyz@b", L"\u2026", 3},
- {"small_username4", L"xyz@b", L"x\u2026@b", 4},
- {"small_username5", L"xyz@b", L"xyz@b", 5},
- {"small_domain3", L"a@xyz", L"\u2026", 3},
- {"small_domain4", L"a@xyz", L"a@x\u2026", 4},
- {"small_domain5", L"a@xyz", L"a@xyz", 5},
+ {"empty", u"", u""},
+ {"invalid_char1", u"x", u""},
+ {"invalid_char3", u"xyz", u"x…"},
+ {"invalid_amp", u"@", u""},
+ {"invalid_no_prefix0", u"@y", u""},
+ {"invalid_no_prefix1", u"@y", u"…"},
+ {"invalid_no_prefix2", u"@xyz", u"@x…"},
+ {"invalid_no_suffix0", u"x@", u""},
+ {"invalid_no_suffix1", u"x@", u"…"},
+ {"invalid_no_suffix2", u"xyz@", u"x…@"},
+
+ {"at1", u"@", u"@"},
+ {"at2", u"@@", u"…", 1},
+ {"at3", u"@@@", u"…", 2},
+ {"at4", u"@@@@", u"@…@", 3},
+
+ {"small1", u"a@b", u"…", 1},
+ {"small2", u"a@b", u"…", 2},
+ {"small3", u"a@b", u"a@b", 3},
+ {"small_username3", u"xyz@b", u"…", 3},
+ {"small_username4", u"xyz@b", u"x…@b", 4},
+ {"small_username5", u"xyz@b", u"xyz@b", 5},
+ {"small_domain3", u"a@xyz", u"…", 3},
+ {"small_domain4", u"a@xyz", u"a@x…", 4},
+ {"small_domain5", u"a@xyz", u"a@xyz", 5},
// Valid email.
- {"email_small", L"a@b.com", L"\u2026"},
- {"email_nobody3", L"nobody@gmail.com", L"\u2026", 3},
- {"email_nobody4", L"nobody@gmail.com", L"\u2026", 4},
- {"email_nobody5", L"nobody@gmail.com", L"n\u2026@g\u2026", 5},
- {"email_nobody6", L"nobody@gmail.com", L"no\u2026@g\u2026", 6},
- {"email_nobody7", L"nobody@gmail.com", L"no\u2026@g\u2026m", 7},
- {"email_nobody8", L"nobody@gmail.com", L"nob\u2026@g\u2026m", 8},
- {"email_nobody9", L"nobody@gmail.com", L"nob\u2026@gm\u2026m", 9},
- {"email_nobody10", L"nobody@gmail.com", L"nobo\u2026@gm\u2026m", 10},
- {"email_root", L"root@localhost", L"r\u2026@l\u2026", 5},
- {"email_myself", L"myself@127.0.0.1", L"my\u2026@1\u2026", 6},
+ {"email_small", u"a@b.com", u"…"},
+ {"email_nobody3", u"nobody@gmail.com", u"…", 3},
+ {"email_nobody4", u"nobody@gmail.com", u"…", 4},
+ {"email_nobody5", u"nobody@gmail.com", u"n…@g…", 5},
+ {"email_nobody6", u"nobody@gmail.com", u"no…@g…", 6},
+ {"email_nobody7", u"nobody@gmail.com", u"no…@g…m", 7},
+ {"email_nobody8", u"nobody@gmail.com", u"nob…@g…m", 8},
+ {"email_nobody9", u"nobody@gmail.com", u"nob…@gm…m", 9},
+ {"email_nobody10", u"nobody@gmail.com", u"nobo…@gm…m", 10},
+ {"email_root", u"root@localhost", u"r…@l…", 5},
+ {"email_myself", u"myself@127.0.0.1", u"my…@1…", 6},
};
INSTANTIATE_TEST_SUITE_P(
@@ -2256,9 +2229,8 @@ TEST_F(RenderTextTest, ElidedText_NoTrimWhitespace) {
// [ ...]
// and not like:
// [... ]
- constexpr char kInputString[] = " foo";
- const std::u16string input = ASCIIToUTF16(kInputString);
- render_text->SetText(input);
+ constexpr char16_t kInputString[] = u" foo";
+ render_text->SetText(kInputString);
// Choose a width based on being able to display 12 characters (one of which
// will be the trailing ellipsis).
@@ -2267,12 +2239,13 @@ TEST_F(RenderTextTest, ElidedText_NoTrimWhitespace) {
render_text->SetDisplayRect(Rect(0, 0, kRequiredWidth, 100));
// Verify this doesn't change the full text.
- EXPECT_EQ(input, render_text->text());
+ EXPECT_EQ(kInputString, render_text->text());
// Verify that the string is truncated to |kDesiredChars| with the ellipsis.
const std::u16string result = render_text->GetDisplayText();
const std::u16string expected =
- input.substr(0, kDesiredChars - 1) + kEllipsisUTF16[0];
+ std::u16string(kInputString).substr(0, kDesiredChars - 1) +
+ kEllipsisUTF16[0];
EXPECT_EQ(expected, result);
}
@@ -2286,11 +2259,11 @@ TEST_F(RenderTextTest, SetElideBehavior) {
render_text->SetCursorEnabled(false);
render_text->SetDisplayRect(Rect(0, 0, 3 * kGlyphWidth, 100));
render_text->SetElideBehavior(ELIDE_TAIL);
- EXPECT_EQ(u"ab\u2026", render_text->GetDisplayText());
+ EXPECT_EQ(u"ab…", render_text->GetDisplayText());
// Setting a different eliding behavior must trigger a relayout.
render_text->SetElideBehavior(ELIDE_HEAD);
- EXPECT_EQ(u"\u2026ef", render_text->GetDisplayText());
+ EXPECT_EQ(u"…ef", render_text->GetDisplayText());
}
TEST_F(RenderTextTest, SetWhitespaceElision) {
@@ -2304,11 +2277,11 @@ TEST_F(RenderTextTest, SetWhitespaceElision) {
render_text->SetDisplayRect(Rect(0, 0, 3 * kGlyphWidth, 100));
render_text->SetElideBehavior(ELIDE_TAIL);
render_text->SetWhitespaceElision(false);
- EXPECT_EQ(u"a \u2026", render_text->GetDisplayText());
+ EXPECT_EQ(u"a …", render_text->GetDisplayText());
// Setting a different whitespace elision must trigger a relayout.
render_text->SetWhitespaceElision(true);
- EXPECT_EQ(u"a\u2026", render_text->GetDisplayText());
+ EXPECT_EQ(u"a…", render_text->GetDisplayText());
}
TEST_F(RenderTextTest, ElidedObscuredText) {
@@ -2525,7 +2498,7 @@ TEST_F(RenderTextTest, MultilineElideBiDi) {
RenderText* render_text = GetRenderText();
SetGlyphWidth(5);
- std::u16string input_text(UTF8ToUTF16("אa\nbcdבגדהefg\nhו"));
+ std::u16string input_text(u"אa\nbcdבגדהefg\nhו");
render_text->SetText(input_text);
render_text->SetCursorEnabled(false);
render_text->SetMultiline(true);
@@ -2535,7 +2508,7 @@ TEST_F(RenderTextTest, MultilineElideBiDi) {
test_api()->EnsureLayout();
EXPECT_EQ(render_text->GetDisplayText(),
- UTF8ToUTF16("אa\nbcdבג") + std::u16string(kEllipsisUTF16));
+ u"אa\nbcdבג" + std::u16string(kEllipsisUTF16));
EXPECT_EQ(render_text->GetNumLines(), 2U);
}
@@ -2558,23 +2531,22 @@ TEST_F(RenderTextTest, MultilineElideLinebreak) {
}
TEST_F(RenderTextTest, ElidedStyledTextRtl) {
- static const char* kInputTexts[] = {
- "http://ar.wikipedia.com/فحص",
- "testحص,",
- "حص,test",
- "…",
- "…test",
- "test…",
- "حص,test…",
- "ٱ",
- "\uFEFF", // BOM: Byte Order Marker
- "…\u200F", // Right to left marker.
+ static const char16_t* kInputTexts[] = {
+ u"http://ar.wikipedia.com/فحص",
+ u"testحص,",
+ u"حص,test",
+ u"…",
+ u"…test",
+ u"test…",
+ u"حص,test…",
+ u"ٱ",
+ u"\uFEFF", // BOM: Byte Order Marker
+ u"…\u200F", // Right to left marker.
};
for (const auto* raw_text : kInputTexts) {
- SCOPED_TRACE(
- base::StringPrintf("ElidedStyledTextRtl text = %s", raw_text));
- std::u16string input_text(UTF8ToUTF16(raw_text));
+ std::u16string input_text(raw_text);
+ SCOPED_TRACE(u"ElidedStyledTextRtl text = " + input_text);
RenderText* render_text = GetRenderText();
render_text->SetText(input_text);
@@ -2612,61 +2584,61 @@ TEST_F(RenderTextTest, ElidedEmail) {
TEST_F(RenderTextTest, TruncatedText) {
struct {
- const wchar_t* text;
- const wchar_t* display_text;
+ const char16_t* text;
+ const char16_t* display_text;
} cases[] = {
// Strings shorter than the truncation length should be laid out in full.
- {L"", L""},
- {L" . ", L" . "}, // a wide kWeak
- {L"abc", L"abc"}, // a wide kLtr
- {L"\u05d0\u05d1\u05d2", L"\u05d0\u05d1\u05d2"}, // a wide kRtl
- {L"a\u05d0\u05d1", L"a\u05d0\u05d1"}, // a wide kLtrRtl
- {L"a\u05d1b", L"a\u05d1b"}, // a wide kLtrRtlLtr
- {L"\u05d0\u05d1a", L"\u05d0\u05d1a"}, // a wide kRtlLtr
- {L"\u05d0a\u05d1", L"\u05d0a\u05d1"}, // a wide kRtlLtrRtl
- {L"01234", L"01234"},
+ {u"", u""},
+ {u" . ", u" . "}, // a wide kWeak
+ {u"abc", u"abc"}, // a wide kLtr
+ {u"אבג", u"אבג"}, // a wide kRtl
+ {u"aאב", u"aאב"}, // a wide kLtrRtl
+ {u"aבb", u"aבb"}, // a wide kLtrRtlLtr
+ {u"אבa", u"אבa"}, // a wide kRtlLtr
+ {u"אaב", u"אaב"}, // a wide kRtlLtrRtl
+ {u"01234", u"01234"},
// Long strings should be truncated with an ellipsis appended at the end.
- {L"012345", L"0123\u2026"},
- {L"012 . ", L"012 \u2026"},
- {L"012abc", L"012a\u2026"},
- {L"012a\u05d0\u05d1", L"012a\u2026"},
- {L"012a\u05d1b", L"012a\u2026"},
- {L"012\u05d0\u05d1\u05d2", L"012\u05d0\u2026"},
- {L"012\u05d0\u05d1a", L"012\u05d0\u2026"},
- {L"012\u05d0a\u05d1", L"012\u05d0\u2026"},
+ {u"012345", u"0123…"},
+ {u"012 . ", u"012 …"},
+ {u"012abc", u"012a…"},
+ {u"012aאב", u"012a…"},
+ {u"012aבb", u"012a…"},
+ {u"012אבג", u"012א…"},
+ {u"012אבa", u"012א…"},
+ {u"012אaב", u"012א…"},
// Surrogate pairs should be truncated reasonably enough.
- {L"0123\u0915\u093f", L"0123\u2026"},
- {L"\u05e9\u05bc\u05c1\u05b8", L"\u05e9\u05bc\u05c1\u05b8"},
- {L"0\u05e9\u05bc\u05c1\u05b8", L"0\u05e9\u05bc\u05c1\u05b8"},
- {L"01\u05e9\u05bc\u05c1\u05b8", L"01\u2026"},
- {L"012\u05e9\u05bc\u05c1\u05b8", L"012\u2026"},
+ {u"0123\u0915\u093f", u"0123…"},
+ {u"\u05e9\u05bc\u05c1\u05b8", u"\u05e9\u05bc\u05c1\u05b8"},
+ {u"0\u05e9\u05bc\u05c1\u05b8", u"0\u05e9\u05bc\u05c1\u05b8"},
+ {u"01\u05e9\u05bc\u05c1\u05b8", u"01…"},
+ {u"012\u05e9\u05bc\u05c1\u05b8", u"012…"},
// Codepoint U+0001D11E is using 2x 16-bit characters.
- {L"0\U0001D11Eaaa", L"0\U0001D11Ea\u2026"},
- {L"01\U0001D11Eaaa", L"01\U0001D11E\u2026"},
- {L"012\U0001D11Eaaa", L"012\u2026"},
- {L"0123\U0001D11Eaaa", L"0123\u2026"},
- {L"01234\U0001D11Eaaa", L"0123\u2026"},
+ {u"0\U0001D11Eaaa", u"0\U0001D11Ea…"},
+ {u"01\U0001D11Eaaa", u"01\U0001D11E…"},
+ {u"012\U0001D11Eaaa", u"012…"},
+ {u"0123\U0001D11Eaaa", u"0123…"},
+ {u"01234\U0001D11Eaaa", u"0123…"},
// Combining codepoint should stay together.
// (Letter 'e' U+0065 and acute accent U+0301).
- {L"0e\u0301aaa", L"0e\u0301a\u2026"},
- {L"01e\u0301aaa", L"01e\u0301\u2026"},
- {L"012e\u0301aaa", L"012\u2026"},
+ {u"0e\u0301aaa", u"0e\u0301a…"},
+ {u"01e\u0301aaa", u"01e\u0301…"},
+ {u"012e\u0301aaa", u"012…"},
// Emoji 'keycap letter 6'.
- {L"\u0036\uFE0F\u20E3aaa", L"\u0036\uFE0F\u20E3a\u2026"},
- {L"0\u0036\uFE0F\u20E3aaa", L"0\u0036\uFE0F\u20E3\u2026"},
- {L"01\u0036\uFE0F\u20E3aaa", L"01\u2026"},
+ {u"\u0036\uFE0F\u20E3aaa", u"\u0036\uFE0F\u20E3a…"},
+ {u"0\u0036\uFE0F\u20E3aaa", u"0\u0036\uFE0F\u20E3…"},
+ {u"01\u0036\uFE0F\u20E3aaa", u"01…"},
// Emoji 'pilot'.
- {L"\U0001F468\u200D\u2708\uFE0F", L"\U0001F468\u200D\u2708\uFE0F"},
- {L"\U0001F468\u200D\u2708\uFE0F0", L"\u2026"},
- {L"0\U0001F468\u200D\u2708\uFE0F", L"0\u2026"},
+ {u"\U0001F468\u200D\u2708\uFE0F", u"\U0001F468\u200D\u2708\uFE0F"},
+ {u"\U0001F468\u200D\u2708\uFE0F0", u"…"},
+ {u"0\U0001F468\u200D\u2708\uFE0F", u"0…"},
};
RenderText* render_text = GetRenderText();
render_text->set_truncate_length(5);
for (size_t i = 0; i < base::size(cases); i++) {
- render_text->SetText(WideToUTF16(cases[i].text));
- EXPECT_EQ(WideToUTF16(cases[i].text), render_text->text());
- EXPECT_EQ(WideToUTF16(cases[i].display_text), render_text->GetDisplayText())
+ render_text->SetText(cases[i].text);
+ EXPECT_EQ(cases[i].text, render_text->text());
+ EXPECT_EQ(cases[i].display_text, render_text->GetDisplayText())
<< "For case " << i << ": " << cases[i].text;
}
}
@@ -2689,13 +2661,13 @@ TEST_F(RenderTextTest, TruncatedObscuredTextWithGraphemes) {
EXPECT_EQ(GetObscuredString(3), render_text->GetDisplayText());
render_text->SetObscuredRevealIndex(0);
- EXPECT_EQ(UTF8ToUTF16("e\u0301\u2026"), render_text->GetDisplayText());
+ EXPECT_EQ(u"e\u0301…", render_text->GetDisplayText());
render_text->SetObscuredRevealIndex(2);
- EXPECT_EQ(UTF8ToUTF16("\u2022\u2026"), render_text->GetDisplayText());
+ EXPECT_EQ(u"\u2022…", render_text->GetDisplayText());
render_text->SetObscuredRevealIndex(7);
- EXPECT_EQ(UTF8ToUTF16("\u2022\u2022\u2026"), render_text->GetDisplayText());
+ EXPECT_EQ(u"\u2022\u2022…", render_text->GetDisplayText());
}
TEST_F(RenderTextTest, TruncatedCursorMovementLTR) {
@@ -2729,7 +2701,7 @@ TEST_F(RenderTextTest, TruncatedCursorMovementLTR) {
TEST_F(RenderTextTest, TruncatedCursorMovementRTL) {
RenderText* render_text = GetRenderText();
render_text->set_truncate_length(2);
- render_text->SetText(UTF8ToUTF16("\u05d0\u05d1\u05d2\u05d3"));
+ render_text->SetText(u"אבגד");
EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model());
render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, SELECTION_NONE);
@@ -3095,8 +3067,7 @@ TEST_F(RenderTextTest, MoveCursor_UpDown) {
std::vector<size_t> expected_lines;
std::vector<Range> expected_range;
- for (auto text :
- {ASCIIToUTF16("123 456 123 456 "), UTF8ToUTF16("אבג דהו זחט זחט ")}) {
+ for (auto* text : {u"123 456 123 456 ", u"אבג דהו זחט זחט "}) {
render_text->SetText(text);
EXPECT_EQ(2U, render_text->GetNumLines());
@@ -3252,18 +3223,18 @@ TEST_F(RenderTextTest, GetTextDirectionInvalidation) {
render_text->SetText(u"a");
EXPECT_EQ(base::i18n::LEFT_TO_RIGHT, render_text->GetTextDirection());
- render_text->SetText(UTF8ToUTF16("\u05d0"));
+ render_text->SetText(u"א");
EXPECT_EQ(base::i18n::RIGHT_TO_LEFT, render_text->GetTextDirection());
// The codepoints u+2026 (ellipsis) has no strong direction.
- render_text->SetText(UTF8ToUTF16("\u2026"));
+ render_text->SetText(u"…");
EXPECT_EQ(original_text_direction, render_text->GetTextDirection());
render_text->AppendText(u"a");
EXPECT_EQ(base::i18n::LEFT_TO_RIGHT, render_text->GetTextDirection());
- render_text->SetText(UTF8ToUTF16("\u2026"));
+ render_text->SetText(u"…");
EXPECT_EQ(original_text_direction, render_text->GetTextDirection());
- render_text->AppendText(UTF8ToUTF16("\u05d0"));
+ render_text->AppendText(u"א");
EXPECT_EQ(base::i18n::RIGHT_TO_LEFT, render_text->GetTextDirection());
}
@@ -3277,18 +3248,18 @@ TEST_F(RenderTextTest, GetDisplayTextDirectionInvalidation) {
render_text->SetText(u"a");
EXPECT_EQ(base::i18n::LEFT_TO_RIGHT, render_text->GetDisplayTextDirection());
- render_text->SetText(UTF8ToUTF16("\u05d0"));
+ render_text->SetText(u"א");
EXPECT_EQ(base::i18n::RIGHT_TO_LEFT, render_text->GetDisplayTextDirection());
// The codepoints u+2026 (ellipsis) has no strong direction.
- render_text->SetText(UTF8ToUTF16("\u2026"));
+ render_text->SetText(u"…");
EXPECT_EQ(original_text_direction, render_text->GetDisplayTextDirection());
render_text->AppendText(u"a");
EXPECT_EQ(base::i18n::LEFT_TO_RIGHT, render_text->GetDisplayTextDirection());
- render_text->SetText(UTF8ToUTF16("\u2026"));
+ render_text->SetText(u"…");
EXPECT_EQ(original_text_direction, render_text->GetDisplayTextDirection());
- render_text->AppendText(UTF8ToUTF16("\u05d0"));
+ render_text->AppendText(u"א");
EXPECT_EQ(base::i18n::RIGHT_TO_LEFT, render_text->GetDisplayTextDirection());
}
@@ -3297,13 +3268,13 @@ TEST_F(RenderTextTest, GetTextDirectionWithDifferentDirection) {
RenderText* render_text = GetRenderText();
ASSERT_EQ(render_text->directionality_mode(), DIRECTIONALITY_FROM_TEXT);
render_text->SetWhitespaceElision(false);
- render_text->SetText(UTF8ToUTF16("123\u0638xyz"));
+ render_text->SetText(u"123\u0638xyz");
render_text->SetElideBehavior(ELIDE_HEAD);
render_text->SetDisplayRect(Rect(25, 100));
// The elided text is an ellipsis with neutral directionality, and a 'z' with
// a strong LTR directionality.
- EXPECT_EQ(UTF8ToUTF16("\u2026z"), render_text->GetDisplayText());
+ EXPECT_EQ(u"…z", render_text->GetDisplayText());
EXPECT_EQ(base::i18n::RIGHT_TO_LEFT, render_text->GetTextDirection());
EXPECT_EQ(base::i18n::LEFT_TO_RIGHT, render_text->GetDisplayTextDirection());
}
@@ -3313,7 +3284,7 @@ TEST_F(RenderTextTest, DirectionalityInvalidation) {
ASSERT_EQ(render_text->directionality_mode(), DIRECTIONALITY_FROM_TEXT);
// The codepoints u+2026 (ellipsis) has weak directionality.
- render_text->SetText(UTF8ToUTF16("\u2026"));
+ render_text->SetText(u"…");
const base::i18n::TextDirection original_text_direction =
render_text->GetTextDirection();
@@ -3337,11 +3308,11 @@ TEST_F(RenderTextTest, MoveCursor_UpDown_Scroll) {
render_text->SetVerticalAlignment(ALIGN_TOP);
const size_t kLineSize = 50;
- std::string text;
+ std::u16string text;
for (size_t i = 0; i < kLineSize - 1; ++i)
- text += "a\n";
+ text += u"a\n";
- render_text->SetText(ASCIIToUTF16(text));
+ render_text->SetText(text);
EXPECT_EQ(kLineSize, render_text->GetNumLines());
// Move cursor down with scroll.
@@ -3382,11 +3353,11 @@ TEST_F(RenderTextTest, MoveCursor_UpDown_Scroll) {
TEST_F(RenderTextTest, GetDisplayTextDirection) {
struct {
- const char* text;
+ const char16_t* text;
const base::i18n::TextDirection text_direction;
} cases[] = {
// Blank strings and those with no/weak directionality default to LTR.
- {"", base::i18n::LEFT_TO_RIGHT},
+ {u"", base::i18n::LEFT_TO_RIGHT},
{kWeak, base::i18n::LEFT_TO_RIGHT},
// Strings that begin with strong LTR characters.
{kLtr, base::i18n::LEFT_TO_RIGHT},
@@ -3409,7 +3380,7 @@ TEST_F(RenderTextTest, GetDisplayTextDirection) {
// Ensure that directionality modes yield the correct text directions.
for (size_t j = 0; j < base::size(cases); j++) {
- render_text->SetText(UTF8ToUTF16(cases[j].text));
+ render_text->SetText(cases[j].text);
render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_TEXT);
EXPECT_EQ(render_text->GetDisplayTextDirection(),cases[j].text_direction);
render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_UI);
@@ -3430,15 +3401,15 @@ TEST_F(RenderTextTest, GetDisplayTextDirection) {
// Ensure that text changes update the direction for DIRECTIONALITY_FROM_TEXT.
render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_TEXT);
- render_text->SetText(UTF8ToUTF16(kLtr));
+ render_text->SetText(kLtr);
EXPECT_EQ(render_text->GetDisplayTextDirection(), base::i18n::LEFT_TO_RIGHT);
- render_text->SetText(UTF8ToUTF16(kRtl));
+ render_text->SetText(kRtl);
EXPECT_EQ(render_text->GetDisplayTextDirection(), base::i18n::RIGHT_TO_LEFT);
}
struct GetTextIndexOfLineCase {
const char* test_name;
- const wchar_t* const text;
+ const char16_t* const text;
const std::vector<size_t> line_breaks;
const bool set_word_wrap = false;
const bool set_obscured = false;
@@ -3464,60 +3435,60 @@ TEST_P(RenderTextTestWithGetTextIndexOfLineCase, GetTextIndexOfLine) {
render_text->SetWordWrapBehavior(WRAP_LONG_WORDS);
}
render_text->SetObscured(param.set_obscured);
- render_text->SetText(base::WideToUTF16(param.text));
+ render_text->SetText(param.text);
for (size_t i = 0; i < param.line_breaks.size(); ++i) {
EXPECT_EQ(param.line_breaks[i], render_text->GetTextIndexOfLine(i));
}
}
const GetTextIndexOfLineCase kGetTextIndexOfLineCases[] = {
- {"emptyString", L"", {0}},
+ {"emptyString", u"", {0}},
// The following test strings are three character strings.
// The word wrap makes each character fall on a new line.
- {"kWeak_minWidth", L" . ", {0, 1, 2}, kUseWordWrap},
- {"kLtr_minWidth", L"abc", {0, 1, 2}, kUseWordWrap},
- {"kLtrRtl_minWidth", L"a\u05d0\u05d1", {0, 1, 2}, kUseWordWrap},
- {"kLtrRtlLtr_minWidth", L"a\u05d1b", {0, 1, 2}, kUseWordWrap},
- {"kRtl_minWidth", L"\u05d0\u05d1\u05d2", {0, 1, 2}, kUseWordWrap},
- {"kRtlLtr_minWidth", L"\u05d0\u05d1a", {0, 1, 2}, kUseWordWrap},
- {"kRtlLtrRtl_minWidth", L"\u05d0a\u05d1", {0, 1, 2}, kUseWordWrap},
+ {"kWeak_minWidth", u" . ", {0, 1, 2}, kUseWordWrap},
+ {"kLtr_minWidth", u"abc", {0, 1, 2}, kUseWordWrap},
+ {"kLtrRtl_minWidth", u"aאב", {0, 1, 2}, kUseWordWrap},
+ {"kLtrRtlLtr_minWidth", u"aבb", {0, 1, 2}, kUseWordWrap},
+ {"kRtl_minWidth", u"אבג", {0, 1, 2}, kUseWordWrap},
+ {"kRtlLtr_minWidth", u"אבa", {0, 1, 2}, kUseWordWrap},
+ {"kRtlLtrRtl_minWidth", u"אaב", {0, 1, 2}, kUseWordWrap},
// The following test strings have 2 graphemes separated by a newline.
// The obscured text replace each grapheme by a single codepoint.
{"grapheme_unobscured",
- L"\U0001F601\n\U0001F468\u200D\u2708\uFE0F\nx",
+ u"\U0001F601\n\U0001F468\u200D\u2708\uFE0F\nx",
{0, 3, 9}},
{"grapheme_obscured",
- L"\U0001F601\n\U0001F468\u200D\u2708\uFE0F\nx",
+ u"\U0001F601\n\U0001F468\u200D\u2708\uFE0F\nx",
{0, 3, 9},
!kUseWordWrap,
kUseObscuredText},
// The following test strings have a new line character.
- {"basic_newLine", L"abc\ndef", {0, 4}},
- {"basic_newLineWindows", L"abc\r\ndef", {0, 5}},
- {"spaces_newLine", L"a \n b ", {0, 3}},
- {"spaces_newLineWindows", L"a \r\n b ", {0, 4}},
- {"double_newLine", L"a\n\nb", {0, 2, 3}},
- {"double_newLineWindows", L"a\r\n\r\nb", {0, 3, 5}},
- {"start_newLine", L"\nab", {0, 1}},
- {"start_newLineWindows", L"\r\nab", {0, 2}},
- {"end_newLine", L"ab\n", {0}},
- {"end_newLineWindows", L"ab\r\n", {0}},
- {"isolated_newLine", L"\n", {0}},
- {"isolated_newLineWindows", L"\r\n", {0}},
- {"isolatedDouble_newLine", L"\n\n", {0, 1}},
- {"isolatedDouble_newLineWindows", L"\r\n\r\n", {0, 2}},
+ {"basic_newLine", u"abc\ndef", {0, 4}},
+ {"basic_newLineWindows", u"abc\r\ndef", {0, 5}},
+ {"spaces_newLine", u"a \n b ", {0, 3}},
+ {"spaces_newLineWindows", u"a \r\n b ", {0, 4}},
+ {"double_newLine", u"a\n\nb", {0, 2, 3}},
+ {"double_newLineWindows", u"a\r\n\r\nb", {0, 3, 5}},
+ {"start_newLine", u"\nab", {0, 1}},
+ {"start_newLineWindows", u"\r\nab", {0, 2}},
+ {"end_newLine", u"ab\n", {0}},
+ {"end_newLineWindows", u"ab\r\n", {0}},
+ {"isolated_newLine", u"\n", {0}},
+ {"isolated_newLineWindows", u"\r\n", {0}},
+ {"isolatedDouble_newLine", u"\n\n", {0, 1}},
+ {"isolatedDouble_newLineWindows", u"\r\n\r\n", {0, 2}},
// The following test strings have unicode characters.
- {"playSymbol_unicode", L"x\n\u25B6\ny", {0, 2, 4}},
- {"emoji_unicode", L"x\n\U0001F601\ny\n\u2728\nz", {0, 2, 5, 7, 9}},
- {"flag_unicode", L"🇬🇧\n🇯🇵", {0, 5}, false, false},
+ {"playSymbol_unicode", u"x\n\u25B6\ny", {0, 2, 4}},
+ {"emoji_unicode", u"x\n\U0001F601\ny\n\u2728\nz", {0, 2, 5, 7, 9}},
+ {"flag_unicode", u"🇬🇧\n🇯🇵", {0, 5}, false, false},
// The following cases test that GetTextIndexOfLine returns the length of
// the text when passed a line index larger than the number of lines.
- {"basic_outsideRange", L"abc", {0, 1, 2, 3, 3}, kUseWordWrap},
- {"emptyString_outsideRange", L"", {0, 0, 0}},
- {"newLine_outsideRange", L"\n", {0, 1, 1}},
- {"newLineWindows_outsideRange", L"\r\n", {0, 2, 2, 2}},
- {"doubleNewLine_outsideRange", L"\n\n", {0, 1, 2, 2}},
- {"doubleNewLineWindows_outsideRange", L"\r\n\r\n", {0, 2, 4, 4}},
+ {"basic_outsideRange", u"abc", {0, 1, 2, 3, 3}, kUseWordWrap},
+ {"emptyString_outsideRange", u"", {0, 0, 0}},
+ {"newLine_outsideRange", u"\n", {0, 1, 1}},
+ {"newLineWindows_outsideRange", u"\r\n", {0, 2, 2, 2}},
+ {"doubleNewLine_outsideRange", u"\n\n", {0, 1, 2, 2}},
+ {"doubleNewLineWindows_outsideRange", u"\r\n\r\n", {0, 2, 4, 4}},
};
INSTANTIATE_TEST_SUITE_P(
@@ -3552,7 +3523,7 @@ TEST_F(RenderTextTest, MoveCursorLeftRightInLtr) {
TEST_F(RenderTextTest, MoveCursorLeftRightInLtrRtl) {
RenderText* render_text = GetRenderText();
// LTR-RTL
- render_text->SetText(UTF8ToUTF16("abc\u05d0\u05d1\u05d2"));
+ render_text->SetText(u"abcאבג");
// The last one is the expected END position.
std::vector<SelectionModel> expected;
expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
@@ -3580,7 +3551,7 @@ TEST_F(RenderTextTest, MoveCursorLeftRightInLtrRtl) {
TEST_F(RenderTextTest, MoveCursorLeftRightInLtrRtlLtr) {
RenderText* render_text = GetRenderText();
// LTR-RTL-LTR.
- render_text->SetText(UTF8ToUTF16("a\u05d1b"));
+ render_text->SetText(u"aבb");
std::vector<SelectionModel> expected;
expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
@@ -3601,7 +3572,7 @@ TEST_F(RenderTextTest, MoveCursorLeftRightInLtrRtlLtr) {
TEST_F(RenderTextTest, MoveCursorLeftRightInRtl) {
RenderText* render_text = GetRenderText();
// Pure RTL.
- render_text->SetText(UTF8ToUTF16("\u05d0\u05d1\u05d2"));
+ render_text->SetText(u"אבג");
render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, SELECTION_NONE);
std::vector<SelectionModel> expected;
@@ -3625,7 +3596,7 @@ TEST_F(RenderTextTest, MoveCursorLeftRightInRtl) {
TEST_F(RenderTextTest, MoveCursorLeftRightInRtlLtr) {
RenderText* render_text = GetRenderText();
// RTL-LTR
- render_text->SetText(UTF8ToUTF16("\u05d0\u05d1\u05d2abc"));
+ render_text->SetText(u"אבגabc");
render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, SELECTION_NONE);
std::vector<SelectionModel> expected;
expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
@@ -3653,7 +3624,7 @@ TEST_F(RenderTextTest, MoveCursorLeftRightInRtlLtr) {
TEST_F(RenderTextTest, MoveCursorLeftRightInRtlLtrRtl) {
RenderText* render_text = GetRenderText();
// RTL-LTR-RTL.
- render_text->SetText(UTF8ToUTF16("\u05d0a\u05d1"));
+ render_text->SetText(u"אaב");
render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, SELECTION_NONE);
std::vector<SelectionModel> expected;
expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
@@ -3674,7 +3645,7 @@ TEST_F(RenderTextTest, MoveCursorLeftRightInRtlLtrRtl) {
TEST_F(RenderTextTest, MoveCursorLeftRight_ComplexScript) {
RenderText* render_text = GetRenderText();
- render_text->SetText(UTF8ToUTF16("\u0915\u093f\u0915\u094d\u0915"));
+ render_text->SetText(u"\u0915\u093f\u0915\u094d\u0915");
EXPECT_EQ(0U, render_text->cursor_position());
render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, SELECTION_NONE);
EXPECT_EQ(2U, render_text->cursor_position());
@@ -3717,7 +3688,7 @@ TEST_F(RenderTextTest, MoveCursorLeftRight_MeiryoUILigatures) {
TEST_F(RenderTextTest, GraphemeIterator) {
RenderText* render_text = GetRenderText();
- render_text->SetText(UTF8ToUTF16("a\u0065\u0301b"));
+ render_text->SetText(u"a\u0065\u0301b");
internal::GraphemeIterator iterator =
render_text->GetGraphemeIteratorAtTextIndex(0);
@@ -3762,7 +3733,7 @@ TEST_F(RenderTextTest, GraphemeIterator) {
iterator = render_text->GetGraphemeIteratorAtDisplayTextIndex(3);
EXPECT_EQ(3U, render_text->GetDisplayTextIndex(iterator));
- render_text->SetText(UTF8ToUTF16("e\u0301b"));
+ render_text->SetText(u"e\u0301b");
render_text->SetObscured(true);
iterator = render_text->GetGraphemeIteratorAtDisplayTextIndex(0);
EXPECT_EQ(0U, render_text->GetTextIndex(iterator));
@@ -3788,7 +3759,7 @@ TEST_F(RenderTextTest, GraphemeIterator) {
EXPECT_EQ(3U, render_text->GetTextIndex(iterator));
EXPECT_EQ(2U, render_text->GetDisplayTextIndex(iterator));
- render_text->SetText(UTF8ToUTF16("\U0001F468\u200D\u2708\uFE0Fx"));
+ render_text->SetText(u"\U0001F468\u200D\u2708\uFE0Fx");
render_text->SetObscured(true);
iterator = render_text->GetGraphemeIteratorAtDisplayTextIndex(0);
EXPECT_EQ(0U, render_text->GetTextIndex(iterator));
@@ -3856,10 +3827,10 @@ TEST_F(RenderTextTest, GraphemeBoundaries) {
TEST_F(RenderTextTest, GraphemePositions) {
// LTR कि (DEVANAGARI KA with VOWEL I) (2-char grapheme), LTR abc, and LTR कि.
- const std::u16string kText1 = UTF8ToUTF16("\u0915\u093fabc\u0915\u093f");
+ const std::u16string kText1 = u"\u0915\u093fabc\u0915\u093f";
// LTR ab, LTR कि (DEVANAGARI KA with VOWEL I) (2-char grapheme), LTR cd.
- const std::u16string kText2 = UTF8ToUTF16("ab\u0915\u093fcd");
+ const std::u16string kText2 = u"ab\u0915\u093fcd";
// LTR ab, 𝄞 'MUSICAL SYMBOL G CLEF' U+1D11E (surrogate pair), LTR cd.
// Windows requires wide strings for \Unnnnnnnn universal character names.
@@ -3923,8 +3894,8 @@ TEST_F(RenderTextTest, GraphemePositions) {
TEST_F(RenderTextTest, MidGraphemeSelectionBounds) {
// Test that selection bounds may be set amid multi-character graphemes.
- const std::u16string kHindi = UTF8ToUTF16("\u0915\u093f");
- const std::u16string kThai = UTF8ToUTF16("\u0e08\u0e33");
+ const std::u16string kHindi = u"\u0915\u093f";
+ const std::u16string kThai = u"\u0e08\u0e33";
const std::u16string cases[] = {kHindi, kThai};
RenderText* render_text = GetRenderText();
@@ -3955,12 +3926,12 @@ TEST_F(RenderTextTest, MidGraphemeSelectionBounds) {
}
TEST_F(RenderTextTest, FindCursorPosition) {
- const char* kTestStrings[] = {kLtrRtl, kLtrRtlLtr, kRtlLtr, kRtlLtrRtl};
+ const char16_t* kTestStrings[] = {kLtrRtl, kLtrRtlLtr, kRtlLtr, kRtlLtrRtl};
RenderText* render_text = GetRenderText();
render_text->SetDisplayRect(Rect(0, 0, 100, 20));
for (size_t i = 0; i < base::size(kTestStrings); ++i) {
SCOPED_TRACE(base::StringPrintf("Testing case[%" PRIuS "]", i));
- render_text->SetText(UTF8ToUTF16(kTestStrings[i]));
+ render_text->SetText(kTestStrings[i]);
for (size_t j = 0; j < render_text->text().length(); ++j) {
gfx::RangeF cursor_span = render_text->GetCursorSpan(Range(j, j + 1));
// Test a point just inside the leading edge of the glyph bounds.
@@ -3973,8 +3944,7 @@ TEST_F(RenderTextTest, FindCursorPosition) {
// Tests that FindCursorPosition behaves correctly for multi-line text.
TEST_F(RenderTextTest, FindCursorPositionMultiline) {
- const char* kTestStrings[] = {"abc def",
- "\u05d0\u05d1\u05d2 \u05d3\u05d4\u05d5"};
+ const char16_t* kTestStrings[] = {u"abc def", u"אבג דהו"};
SetGlyphWidth(5);
RenderText* render_text = GetRenderText();
@@ -3982,7 +3952,7 @@ TEST_F(RenderTextTest, FindCursorPositionMultiline) {
render_text->SetMultiline(true);
for (size_t i = 0; i < base::size(kTestStrings); i++) {
- render_text->SetText(UTF8ToUTF16(kTestStrings[i]));
+ render_text->SetText(kTestStrings[i]);
EXPECT_EQ(2u, render_text->GetNumLines());
const bool is_ltr =
@@ -4013,9 +3983,9 @@ TEST_F(RenderTextTest, FindCursorPosition_GraphemeBoundaries) {
std::set<size_t> expected_cursor_positions;
} cases[] = {
// LTR कि (DEVANAGARI KA with VOWEL I) (2-char grapheme), LTR abc, LTR कि.
- {UTF8ToUTF16("\u0915\u093fabc\u0915\u093f"), {0, 2, 3, 4, 5, 7}},
+ {u"\u0915\u093fabc\u0915\u093f", {0, 2, 3, 4, 5, 7}},
// LTR ab, LTR कि (DEVANAGARI KA with VOWEL I) (2-char grapheme), LTR cd.
- {UTF8ToUTF16("ab\u0915\u093fcd"), {0, 1, 2, 4, 5, 6}},
+ {u"ab\u0915\u093fcd", {0, 1, 2, 4, 5, 6}},
// LTR ab, surrogate pair composed of two 16 bit characters, LTR cd.
// Windows requires wide strings for \Unnnnnnnn universal character names.
{u"ab\U0001D11Ecd", {0, 1, 2, 4, 5, 6}}};
@@ -4038,13 +4008,13 @@ TEST_F(RenderTextTest, EdgeSelectionModels) {
// Simple Latin text.
const std::u16string kLatin = u"abc";
// LTR कि (DEVANAGARI KA with VOWEL I).
- const std::u16string kLTRGrapheme = UTF8ToUTF16("\u0915\u093f");
+ const std::u16string kLTRGrapheme = u"\u0915\u093f";
// LTR कि (DEVANAGARI KA with VOWEL I), LTR a, LTR कि.
- const std::u16string kHindiLatin = UTF8ToUTF16("\u0915\u093fa\u0915\u093f");
+ const std::u16string kHindiLatin = u"\u0915\u093fa\u0915\u093f";
// RTL נָ (Hebrew letter NUN and point QAMATS).
- const std::u16string kRTLGrapheme = UTF8ToUTF16("\u05e0\u05b8");
+ const std::u16string kRTLGrapheme = u"\u05e0\u05b8";
// RTL נָ (Hebrew letter NUN and point QAMATS), LTR a, RTL נָ.
- const std::u16string kHebrewLatin = UTF8ToUTF16("\u05e0\u05b8a\u05e0\u05b8");
+ const std::u16string kHebrewLatin = u"\u05e0\u05b8a\u05e0\u05b8";
struct {
std::u16string text;
@@ -4074,8 +4044,8 @@ TEST_F(RenderTextTest, EdgeSelectionModels) {
}
TEST_F(RenderTextTest, SelectAll) {
- const char* const cases[] = {kWeak, kLtr, kLtrRtl, kLtrRtlLtr,
- kRtl, kRtlLtr, kRtlLtrRtl};
+ const char16_t* const cases[] = {kWeak, kLtr, kLtrRtl, kLtrRtlLtr,
+ kRtl, kRtlLtr, kRtlLtrRtl};
// Ensure that SelectAll respects the |reversed| argument regardless of
// application locale and text content directionality.
@@ -4092,7 +4062,7 @@ TEST_F(RenderTextTest, SelectAll) {
// Test the weak, LTR, RTL, and Bidi string cases.
for (size_t j = 0; j < base::size(cases); j++) {
- render_text->SetText(UTF8ToUTF16(cases[j]));
+ render_text->SetText(cases[j]);
render_text->SelectAll(false);
EXPECT_EQ(render_text->selection_model(), expected_forwards);
render_text->SelectAll(true);
@@ -4105,7 +4075,7 @@ TEST_F(RenderTextTest, SelectAll) {
TEST_F(RenderTextTest, MoveCursorLeftRightWithSelection) {
RenderText* render_text = GetRenderText();
- render_text->SetText(UTF8ToUTF16("abc\u05d0\u05d1\u05d2"));
+ render_text->SetText(u"abcאבג");
// Left arrow on select ranging (6, 4).
render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, SELECTION_NONE);
EXPECT_EQ(Range(6), render_text->selection());
@@ -4269,9 +4239,9 @@ TEST_F(RenderTextTest, CenteredDisplayOffset) {
render_text->GetUpdatedCursorBounds().right());
}
-void MoveLeftRightByWordVerifier(RenderText* render_text, const char* str) {
+void MoveLeftRightByWordVerifier(RenderText* render_text, const char16_t* str) {
SCOPED_TRACE(str);
- const std::u16string str16(UTF8ToUTF16(str));
+ const std::u16string str16(str);
render_text->SetText(str16);
// Test moving by word from left to right.
@@ -4343,37 +4313,37 @@ void MoveLeftRightByWordVerifier(RenderText* render_text, const char* str) {
TEST_F(RenderTextTest, MAYBE_MoveLeftRightByWordInBidiText) {
RenderText* render_text = GetRenderText();
// For testing simplicity, each word is a 3-character word.
- std::vector<const char*> test;
- test.push_back("abc");
- test.push_back("abc def");
- test.push_back("\u05E1\u05E2\u05E3");
- test.push_back("\u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6");
- test.push_back("abc \u05E1\u05E2\u05E3");
- test.push_back("abc def \u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6");
+ std::vector<const char16_t*> test;
+ test.push_back(u"abc");
+ test.push_back(u"abc def");
+ test.push_back(u"\u05E1\u05E2\u05E3");
+ test.push_back(u"\u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6");
+ test.push_back(u"abc \u05E1\u05E2\u05E3");
+ test.push_back(u"abc def \u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6");
test.push_back(
- "abc def hij \u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6"
- " \u05E7\u05E8\u05E9");
+ u"abc def hij \u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6"
+ u" \u05E7\u05E8\u05E9");
- test.push_back("abc \u05E1\u05E2\u05E3 hij");
- test.push_back("abc def \u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6 hij opq");
+ test.push_back(u"abc \u05E1\u05E2\u05E3 hij");
+ test.push_back(u"abc def \u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6 hij opq");
test.push_back(
- "abc def hij \u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6"
- " \u05E7\u05E8\u05E9 opq rst uvw");
+ u"abc def hij \u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6"
+ u" \u05E7\u05E8\u05E9 opq rst uvw");
- test.push_back("\u05E1\u05E2\u05E3 abc");
- test.push_back("\u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6 abc def");
+ test.push_back(u"\u05E1\u05E2\u05E3 abc");
+ test.push_back(u"\u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6 abc def");
test.push_back(
- "\u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6 \u05E7\u05E8\u05E9"
- " abc def hij");
+ u"\u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6 \u05E7\u05E8\u05E9"
+ u" abc def hij");
- test.push_back("\u05D1\u05D2\u05D3 abc \u05E1\u05E2\u05E3");
+ test.push_back(u"בגד abc \u05E1\u05E2\u05E3");
test.push_back(
- "\u05D1\u05D2\u05D3 \u05D4\u05D5\u05D6 abc def"
- " \u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6");
+ u"בגד הוז abc def"
+ u" \u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6");
test.push_back(
- "\u05D1\u05D2\u05D3 \u05D4\u05D5\u05D6 \u05D7\u05D8\u05D9"
- " abc def hij \u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6"
- " \u05E7\u05E8\u05E9");
+ u"בגד הוז חטי"
+ u" abc def hij \u05E1\u05E2\u05E3 \u05E4\u05E5\u05E6"
+ u" \u05E7\u05E8\u05E9");
for (size_t i = 0; i < test.size(); ++i)
MoveLeftRightByWordVerifier(render_text, test[i]);
@@ -4382,7 +4352,7 @@ TEST_F(RenderTextTest, MAYBE_MoveLeftRightByWordInBidiText) {
TEST_F(RenderTextTest, MoveLeftRightByWordInBidiText_TestEndOfText) {
RenderText* render_text = GetRenderText();
- render_text->SetText(UTF8ToUTF16("ab\u05E1"));
+ render_text->SetText(u"ab\u05E1");
// Moving the cursor by word from "abC|" to the left should return "|abC".
// But since end of text is always treated as a word break, it returns
// position "ab|C".
@@ -4396,7 +4366,7 @@ TEST_F(RenderTextTest, MoveLeftRightByWordInBidiText_TestEndOfText) {
render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, SELECTION_NONE);
EXPECT_EQ(SelectionModel(3, CURSOR_FORWARD), render_text->selection_model());
- render_text->SetText(UTF8ToUTF16("\u05E1\u05E2a"));
+ render_text->SetText(u"\u05E1\u05E2a");
// For logical text "BCa", moving the cursor by word from "aCB|" to the left
// returns "|aCB".
render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, SELECTION_NONE);
@@ -4459,7 +4429,7 @@ TEST_F(RenderTextTest, MoveLeftRightByWordInThaiText) {
TEST_F(RenderTextTest, MoveLeftRightByWordInChineseText) {
RenderText* render_text = GetRenderText();
// zh-Hans-CN: 我们去公园玩, broken to 我们|去|公园|玩.
- render_text->SetText(UTF8ToUTF16("\u6211\u4EEC\u53BB\u516C\u56ED\u73A9"));
+ render_text->SetText(u"\u6211\u4EEC\u53BB\u516C\u56ED\u73A9");
render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, SELECTION_NONE);
EXPECT_EQ(0U, render_text->cursor_position());
render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, SELECTION_NONE);
@@ -4710,15 +4680,13 @@ TEST_F(RenderTextTest, StringSizeRespectsFontListMetrics) {
Font cjk_font(kCJKFontName, 16);
ASSERT_EQ(base::ToLowerASCII(kCJKFontName),
base::ToLowerASCII(cjk_font.GetActualFontName()));
+ Font smaller_font = test_font;
+ Font larger_font = cjk_font;
// "a" should be rendered with the test font, not with the CJK font.
- const char* test_font_text = "a";
+ const char16_t* smaller_font_text = u"a";
// "円" (U+5168 Han character YEN) should render with the CJK font, not
// the test font.
- const char* cjk_font_text = "\u5168";
- Font smaller_font = test_font;
- Font larger_font = cjk_font;
- const char* smaller_font_text = test_font_text;
- const char* larger_font_text = cjk_font_text;
+ const char16_t* larger_font_text = u"\u5168";
if (cjk_font.GetHeight() < test_font.GetHeight() &&
cjk_font.GetBaseline() < test_font.GetBaseline()) {
std::swap(smaller_font, larger_font);
@@ -4729,7 +4697,7 @@ TEST_F(RenderTextTest, StringSizeRespectsFontListMetrics) {
// Check |smaller_font_text| is rendered with the smaller font.
RenderText* render_text = GetRenderText();
- render_text->SetText(UTF8ToUTF16(smaller_font_text));
+ render_text->SetText(smaller_font_text);
render_text->SetFontList(FontList(smaller_font));
render_text->SetDisplayRect(Rect(0, 0, 0,
render_text->font_list().GetHeight()));
@@ -4839,7 +4807,7 @@ TEST_F(RenderTextTest, TextSize) {
RenderText* render_text = GetRenderText();
for (size_t text_length = 0; text_length < 10; ++text_length) {
- render_text->SetText(ASCIIToUTF16(std::string(text_length, 'x')));
+ render_text->SetText(std::u16string(text_length, u'x'));
// Ensures that conversion from float to integer ceils the values.
const float expected_width = text_length * kGlyphWidth;
@@ -4880,7 +4848,7 @@ TEST_F(RenderTextTest, TextSizeMultiline) {
if (line != 0)
render_text->AppendText(u"\n");
const int text_length = line;
- render_text->AppendText(ASCIIToUTF16(std::string(text_length, 'x')));
+ render_text->AppendText(std::u16string(text_length, u'x'));
// Ensures that conversion from float to integer ceils the values.
const float expected_width = text_length * kGlyphWidth;
@@ -4944,7 +4912,7 @@ TEST_F(RenderTextTest, TextPosition) {
const int kGlyphCount = 3;
RenderText* render_text = GetRenderText();
- render_text->SetText(ASCIIToUTF16(std::string(kGlyphCount, 'x')));
+ render_text->SetText(std::u16string(kGlyphCount, u'x'));
render_text->SetDisplayRect(Rect(1, 1, 25, 12));
render_text->SetCursorEnabled(false);
render_text->SetVerticalAlignment(ALIGN_TOP);
@@ -5021,10 +4989,10 @@ TEST_F(RenderTextTest, StringSizeBoldWidth) {
TEST_F(RenderTextTest, StringSizeHeight) {
std::u16string cases[] = {
- u"Hello World!", // English
- UTF8ToUTF16("\u6328\u62f6"), // Japanese 挨拶 (characters press & near)
- UTF8ToUTF16("\u0915\u093f"), // Hindi कि (letter KA with vowel I)
- UTF8ToUTF16("\u05e0\u05b8"), // Hebrew נָ (letter NUN and point QAMATS)
+ u"Hello World!", // English
+ u"\u6328\u62f6", // Japanese 挨拶 (characters press & near)
+ u"\u0915\u093f", // Hindi कि (letter KA with vowel I)
+ u"\u05e0\u05b8", // Hebrew נָ (letter NUN and point QAMATS)
};
const FontList default_font_list;
@@ -5341,25 +5309,25 @@ TEST_F(RenderTextTest, SameFontForParentheses) {
{u"Hello World(a)Hello World"},
// Japanese(English)
- {UTF8ToUTF16("\u6328\u62f6(a)")},
+ {u"\u6328\u62f6(a)"},
// Japanese(English)Japanese
- {UTF8ToUTF16("\u6328\u62f6(a)\u6328\u62f6")},
+ {u"\u6328\u62f6(a)\u6328\u62f6"},
// English(Japanese)English
- {UTF8ToUTF16("Hello World(\u6328\u62f6)Hello World")},
+ {u"Hello World(\u6328\u62f6)Hello World"},
// Hindi(English)
- {UTF8ToUTF16("\u0915\u093f(a)")},
+ {u"\u0915\u093f(a)"},
// Hindi(English)Hindi
- {UTF8ToUTF16("\u0915\u093f(a)\u0915\u093f")},
+ {u"\u0915\u093f(a)\u0915\u093f"},
// English(Hindi)English
- {UTF8ToUTF16("Hello World(\u0915\u093f)Hello World")},
+ {u"Hello World(\u0915\u093f)Hello World"},
// Hebrew(English)
- {UTF8ToUTF16("\u05e0\u05b8(a)")},
+ {u"\u05e0\u05b8(a)"},
// Hebrew(English)Hebrew
- {UTF8ToUTF16("\u05e0\u05b8(a)\u05e0\u05b8")},
+ {u"\u05e0\u05b8(a)\u05e0\u05b8"},
// English(Hebrew)English
- {UTF8ToUTF16("Hello World(\u05e0\u05b8)Hello World")},
+ {u"Hello World(\u05e0\u05b8)Hello World"},
};
RenderText* render_text = GetRenderText();
@@ -5443,18 +5411,18 @@ TEST_F(RenderTextTest, SelectWord) {
// Make sure the last word is selected when the cursor is at text.length().
TEST_F(RenderTextTest, LastWordSelected) {
- const std::string kTestURL1 = "http://www.google.com";
- const std::string kTestURL2 = "http://www.google.com/something/";
+ const std::u16string kTestURL1 = u"http://www.google.com";
+ const std::u16string kTestURL2 = u"http://www.google.com/something/";
RenderText* render_text = GetRenderText();
- render_text->SetText(ASCIIToUTF16(kTestURL1));
+ render_text->SetText(kTestURL1);
render_text->SetCursorPosition(kTestURL1.length());
render_text->SelectWord();
EXPECT_EQ(u"com", GetSelectedText(render_text));
EXPECT_FALSE(render_text->selection().is_reversed());
- render_text->SetText(ASCIIToUTF16(kTestURL2));
+ render_text->SetText(kTestURL2);
render_text->SetCursorPosition(kTestURL2.length());
render_text->SelectWord();
EXPECT_EQ(u"/", GetSelectedText(render_text));
@@ -5464,11 +5432,11 @@ TEST_F(RenderTextTest, LastWordSelected) {
// When given a non-empty selection, SelectWord should expand the selection to
// nearest word boundaries.
TEST_F(RenderTextTest, SelectMultipleWords) {
- const std::string kTestURL = "http://www.google.com";
+ const std::u16string kTestURL = u"http://www.google.com";
RenderText* render_text = GetRenderText();
- render_text->SetText(ASCIIToUTF16(kTestURL));
+ render_text->SetText(kTestURL);
render_text->SelectRange(Range(16, 20));
render_text->SelectWord();
EXPECT_EQ(u"google.com", GetSelectedText(render_text));
@@ -5510,9 +5478,7 @@ TEST_F(RenderTextTest, DisplayRectShowsCursorLTR) {
EXPECT_EQ(width, render_text->GetUpdatedCursorBounds().x());
// Repeat the test with RTL text.
- render_text->SetText(
- UTF8ToUTF16("\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7"
- "\u05d8\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df"));
+ render_text->SetText(u"אבגדהוזחטיךכלםמן");
render_text->SetCursorPosition(0);
width = render_text->GetStringSize().width();
ASSERT_GT(width, 10);
@@ -5568,9 +5534,7 @@ TEST_F(RenderTextTest, DisplayRectShowsCursorRTL) {
render_text->GetUpdatedCursorBounds().x());
// Repeat the test with RTL text.
- render_text->SetText(
- UTF8ToUTF16("\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7"
- "\u05d8\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df"));
+ render_text->SetText(u"אבגדהוזחטיךכלםמן");
render_text->SetCursorPosition(render_text->text().length());
width = render_text->GetStringSize().width();
ASSERT_GT(width, 10);
@@ -5600,12 +5564,12 @@ TEST_F(RenderTextTest, DisplayRectShowsCursorRTL) {
// Changing colors between or inside ligated glyphs should not break shaping.
TEST_F(RenderTextTest, SelectionKeepsLigatures) {
- const char* kTestStrings[] = {"\u0644\u0623", "\u0633\u0627"};
+ const char16_t* const kTestStrings[] = {u"\u0644\u0623", u"\u0633\u0627"};
RenderText* render_text = GetRenderText();
- render_text->set_selection_color(SK_ColorRED);
+ render_text->set_selection_color(SK_ColorGREEN);
for (size_t i = 0; i < base::size(kTestStrings); ++i) {
- render_text->SetText(UTF8ToUTF16(kTestStrings[i]));
+ render_text->SetText(kTestStrings[i]);
const int expected_width = render_text->GetStringSize().width();
render_text->SelectRange({0, 1});
EXPECT_EQ(expected_width, render_text->GetStringSize().width());
@@ -5632,7 +5596,8 @@ TEST_F(RenderTextTest, ScriptExtensionsDoNotBreak) {
EXPECT_EQ(std::vector<std::u16string>({ramen_katakana}),
RunsFor(ramen_katakana));
- EXPECT_EQ(ToString16Vec({"らあ", "メン"}), RunsFor(ramen_mixed));
+ EXPECT_EQ(std::vector<std::u16string>({u"らあ", u"メン"}),
+ RunsFor(ramen_mixed));
}
// Test that whitespace breaks runs of text. E.g. this can permit better fonts
@@ -5648,18 +5613,20 @@ TEST_F(RenderTextTest, WhitespaceDoesBreak) {
// This says "thank you very much" with a full-width non-ascii space (U+3000).
const std::u16string full_width_space = u"ども ありがと";
- EXPECT_EQ(ToString16Vec({"סיבית", " ", "–", " ", "ויקיפדיה"}),
- RunsFor(ascii_space_he));
- EXPECT_EQ(ToString16Vec({"Bit", " ", "-", " ", "Wikipedia"}),
- RunsFor(ascii_space_en));
- EXPECT_EQ(ToString16Vec({"ども", " ", "ありがと"}),
+ EXPECT_EQ(
+ std::vector<std::u16string>({u"סיבית", u" ", u"–", u" ", u"ויקיפדיה"}),
+ RunsFor(ascii_space_he));
+ EXPECT_EQ(
+ std::vector<std::u16string>({u"Bit", u" ", u"-", u" ", u"Wikipedia"}),
+ RunsFor(ascii_space_en));
+ EXPECT_EQ(std::vector<std::u16string>({u"ども", u" ", u"ありがと"}),
RunsFor(full_width_space));
}
// Ensure strings wrap onto multiple lines for a small available width.
TEST_F(RenderTextTest, Multiline_MinWidth) {
- const char* kTestStrings[] = {kWeak, kLtr, kLtrRtl, kLtrRtlLtr,
- kRtl, kRtlLtr, kRtlLtrRtl};
+ const char16_t* kTestStrings[] = {kWeak, kLtr, kLtrRtl, kLtrRtlLtr,
+ kRtl, kRtlLtr, kRtlLtrRtl};
RenderText* render_text = GetRenderText();
render_text->SetDisplayRect(Rect(1, 1000));
@@ -5668,7 +5635,7 @@ TEST_F(RenderTextTest, Multiline_MinWidth) {
for (size_t i = 0; i < base::size(kTestStrings); ++i) {
SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
- render_text->SetText(UTF8ToUTF16(kTestStrings[i]));
+ render_text->SetText(kTestStrings[i]);
render_text->Draw(canvas());
EXPECT_GT(test_api()->lines().size(), 1U);
}
@@ -5679,7 +5646,7 @@ TEST_F(RenderTextTest, Multiline_NormalWidth) {
// Should RenderText suppress drawing whitespace at the end of a line?
// Currently it does not.
const struct {
- const char* const text;
+ const char16_t* const text;
const Range first_line_char_range;
const Range second_line_char_range;
@@ -5691,22 +5658,20 @@ TEST_F(RenderTextTest, Multiline_NormalWidth) {
bool is_ltr;
} kTestStrings[] = {
- {"abc defg hijkl", Range(0, 9), Range(9, 14), {3, 1, 4, 1, 5}, 4, true},
- {"qwertyzxcvbn", Range(0, 10), Range(10, 12), {10, 2}, 1, true},
+ {u"abc defg hijkl", Range(0, 9), Range(9, 14), {3, 1, 4, 1, 5}, 4, true},
+ {u"qwertyzxcvbn", Range(0, 10), Range(10, 12), {10, 2}, 1, true},
// RTL: should render left-to-right as "<space>43210 \n cba9876".
// Note this used to say "Arabic language", in Arabic, but the last
// character in the string (\u0629) got fancy in an updated Mac font, so
// now the penultimate character repeats. (See "NOTE" below).
- {"\u0627\u0644\u0644\u063A\u0629 "
- "\u0627\u0644\u0639\u0631\u0628\u064A\u064A",
+ {u"اللغة العربيي",
Range(0, 6),
Range(6, 13),
{1 /* space first */, 5, 7},
2,
false},
// RTL: should render left-to-right as "<space>3210 \n cba98765".
- {"\u062A\u0641\u0627\u062D \u05EA\u05E4\u05D5\u05D6\u05D9"
- "\u05DA\u05DB\u05DD",
+ {u"تفاح תפוזיךכם",
Range(0, 5),
Range(5, 13),
{1 /* space first */, 5, 8},
@@ -5725,7 +5690,7 @@ TEST_F(RenderTextTest, Multiline_NormalWidth) {
for (size_t i = 0; i < base::size(kTestStrings); ++i) {
SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
- render_text->SetText(UTF8ToUTF16(kTestStrings[i].text));
+ render_text->SetText(kTestStrings[i].text);
DrawVisualText();
ASSERT_EQ(2U, test_api()->lines().size());
@@ -5759,8 +5724,14 @@ TEST_F(RenderTextTest, Multiline_NormalWidth) {
// Ensure strings don't wrap onto multiple lines for a sufficient available
// width.
TEST_F(RenderTextTest, Multiline_SufficientWidth) {
- const char* kTestStrings[] = {"", " ", ".", " . ", "abc", "a b c",
- "\u062E\u0628\u0632", "\u062E \u0628 \u0632"};
+ const char16_t* kTestStrings[] = {u"",
+ u" ",
+ u".",
+ u" . ",
+ u"abc",
+ u"a b c",
+ u"\u062E\u0628\u0632",
+ u"\u062E \u0628 \u0632"};
RenderText* render_text = GetRenderText();
render_text->SetDisplayRect(Rect(1000, 1000));
@@ -5768,7 +5739,7 @@ TEST_F(RenderTextTest, Multiline_SufficientWidth) {
for (size_t i = 0; i < base::size(kTestStrings); ++i) {
SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
- render_text->SetText(UTF8ToUTF16(kTestStrings[i]));
+ render_text->SetText(kTestStrings[i]);
render_text->Draw(canvas());
EXPECT_EQ(1U, test_api()->lines().size());
}
@@ -5776,17 +5747,17 @@ TEST_F(RenderTextTest, Multiline_SufficientWidth) {
TEST_F(RenderTextTest, Multiline_Newline) {
const struct {
- const char* const text;
+ const char16_t* const text;
const size_t lines_count;
// Ranges of the characters on each line.
const Range line_char_ranges[3];
} kTestStrings[] = {
- {"abc\ndef", 2ul, {Range(0, 4), Range(4, 7), Range::InvalidRange()}},
- {"a \n b ", 2ul, {Range(0, 3), Range(3, 6), Range::InvalidRange()}},
- {"ab\n", 2ul, {Range(0, 3), Range(), Range::InvalidRange()}},
- {"a\n\nb", 3ul, {Range(0, 2), Range(2, 3), Range(3, 4)}},
- {"\nab", 2ul, {Range(0, 1), Range(1, 3), Range::InvalidRange()}},
- {"\n", 2ul, {Range(0, 1), Range(), Range::InvalidRange()}},
+ {u"abc\ndef", 2ul, {Range(0, 4), Range(4, 7), Range::InvalidRange()}},
+ {u"a \n b ", 2ul, {Range(0, 3), Range(3, 6), Range::InvalidRange()}},
+ {u"ab\n", 2ul, {Range(0, 3), Range(), Range::InvalidRange()}},
+ {u"a\n\nb", 3ul, {Range(0, 2), Range(2, 3), Range(3, 4)}},
+ {u"\nab", 2ul, {Range(0, 1), Range(1, 3), Range::InvalidRange()}},
+ {u"\n", 2ul, {Range(0, 1), Range(), Range::InvalidRange()}},
};
RenderText* render_text = GetRenderText();
@@ -5795,7 +5766,7 @@ TEST_F(RenderTextTest, Multiline_Newline) {
for (size_t i = 0; i < base::size(kTestStrings); ++i) {
SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
- render_text->SetText(UTF8ToUTF16(kTestStrings[i].text));
+ render_text->SetText(kTestStrings[i].text);
render_text->Draw(canvas());
EXPECT_EQ(kTestStrings[i].lines_count, test_api()->lines().size());
if (kTestStrings[i].lines_count != test_api()->lines().size())
@@ -5818,25 +5789,22 @@ TEST_F(RenderTextTest, Multiline_Newline) {
// Make sure that multiline mode ignores elide behavior.
TEST_F(RenderTextTest, Multiline_IgnoreElide) {
- const char kTestString[] =
- "very very very long string xxxxxxxxxxxxxxxxxxxxxxxxxx";
- const char kEllipsis[] = "\u2026";
+ const char16_t kTestString[] =
+ u"very very very long string xxxxxxxxxxxxxxxxxxxxxxxxxx";
RenderText* render_text = GetRenderText();
render_text->SetElideBehavior(ELIDE_TAIL);
render_text->SetDisplayRect(Rect(20, 1000));
- render_text->SetText(base::ASCIIToUTF16(kTestString));
- EXPECT_NE(std::u16string::npos,
- render_text->GetDisplayText().find(base::UTF8ToUTF16(kEllipsis)));
+ render_text->SetText(kTestString);
+ EXPECT_NE(std::u16string::npos, render_text->GetDisplayText().find(u"…"));
render_text->SetMultiline(true);
- EXPECT_EQ(std::u16string::npos,
- render_text->GetDisplayText().find(base::UTF8ToUTF16(kEllipsis)));
+ EXPECT_EQ(std::u16string::npos, render_text->GetDisplayText().find(u"…"));
}
TEST_F(RenderTextTest, Multiline_NewlineCharacterReplacement) {
- const char* kTestStrings[] = {
- "abc\ndef", "a \n b ", "ab\n", "a\n\nb", "\nab", "\n",
+ const char16_t* kTestStrings[] = {
+ u"abc\ndef", u"a \n b ", u"ab\n", u"a\n\nb", u"\nab", u"\n",
};
for (size_t i = 0; i < base::size(kTestStrings); ++i) {
@@ -5844,49 +5812,45 @@ TEST_F(RenderTextTest, Multiline_NewlineCharacterReplacement) {
ResetRenderTextInstance();
RenderText* render_text = GetRenderText();
render_text->SetDisplayRect(Rect(200, 1000));
- render_text->SetText(ASCIIToUTF16(kTestStrings[i]));
+ render_text->SetText(kTestStrings[i]);
std::u16string display_text = render_text->GetDisplayText();
// If RenderText is not multiline, the newline characters are replaced
// by symbols, therefore the character should be changed.
- EXPECT_NE(ASCIIToUTF16(kTestStrings[i]), render_text->GetDisplayText());
+ EXPECT_NE(kTestStrings[i], render_text->GetDisplayText());
// Setting multiline will fix this, the newline characters will be back
// to the original text.
render_text->SetMultiline(true);
- EXPECT_EQ(ASCIIToUTF16(kTestStrings[i]), render_text->GetDisplayText());
+ EXPECT_EQ(kTestStrings[i], render_text->GetDisplayText());
}
}
// Ensure horizontal alignment works in multiline mode.
TEST_F(RenderTextTest, Multiline_HorizontalAlignment) {
constexpr struct {
- const char* const text;
+ const char16_t* const text;
const HorizontalAlignment alignment;
const base::i18n::TextDirection display_text_direction;
} kTestStrings[] = {
- {"abcdefghi\nhijk", ALIGN_LEFT, base::i18n::LEFT_TO_RIGHT},
- {"nhij\nabcdefghi", ALIGN_LEFT, base::i18n::LEFT_TO_RIGHT},
+ {u"abcdefghi\nhijk", ALIGN_LEFT, base::i18n::LEFT_TO_RIGHT},
+ {u"nhij\nabcdefghi", ALIGN_LEFT, base::i18n::LEFT_TO_RIGHT},
// Hebrew, 2nd line shorter
- {"\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\n"
- "\u05d0\u05d1\u05d2\u05d3",
- ALIGN_RIGHT,
- base::i18n::RIGHT_TO_LEFT},
+ {u"אבגדהוזח\n"
+ u"אבגד",
+ ALIGN_RIGHT, base::i18n::RIGHT_TO_LEFT},
// Hebrew, 2nd line longer
- {"\u05d0\u05d1\u05d2\u05d3\n"
- "\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7",
- ALIGN_RIGHT,
- base::i18n::RIGHT_TO_LEFT},
+ {u"אבגד\n"
+ u"אבגדהוזח",
+ ALIGN_RIGHT, base::i18n::RIGHT_TO_LEFT},
// Arabic, 2nd line shorter.
- {"\u0627\u0627\u0627\u0627\u0627\u0627\u0627\u0627\n"
- "\u0627\u0644\u0644\u063A",
- ALIGN_RIGHT,
- base::i18n::RIGHT_TO_LEFT},
+ {u"\u0627\u0627\u0627\u0627\u0627\u0627\u0627\u0627\n"
+ u"\u0627\u0644\u0644\u063A",
+ ALIGN_RIGHT, base::i18n::RIGHT_TO_LEFT},
// Arabic, 2nd line longer.
- {"\u0627\u0644\u0644\u063A\n"
- "\u0627\u0627\u0627\u0627\u0627\u0627\u0627\u0627",
- ALIGN_RIGHT,
- base::i18n::RIGHT_TO_LEFT},
+ {u"\u0627\u0644\u0644\u063A\n"
+ u"\u0627\u0627\u0627\u0627\u0627\u0627\u0627\u0627",
+ ALIGN_RIGHT, base::i18n::RIGHT_TO_LEFT},
};
const int kGlyphSize = 5;
RenderTextHarfBuzz* render_text = GetRenderText();
@@ -5898,7 +5862,7 @@ TEST_F(RenderTextTest, Multiline_HorizontalAlignment) {
for (size_t i = 0; i < base::size(kTestStrings); ++i) {
SCOPED_TRACE(testing::Message("kTestStrings[")
<< i << "] = " << kTestStrings[i].text);
- render_text->SetText(UTF8ToUTF16(kTestStrings[i].text));
+ render_text->SetText(kTestStrings[i].text);
EXPECT_EQ(kTestStrings[i].display_text_direction,
render_text->GetDisplayTextDirection());
render_text->Draw(canvas());
@@ -5907,9 +5871,9 @@ TEST_F(RenderTextTest, Multiline_HorizontalAlignment) {
EXPECT_EQ(0, test_api()->GetAlignmentOffset(0).x());
EXPECT_EQ(0, test_api()->GetAlignmentOffset(1).x());
} else {
- std::vector<std::u16string> lines = base::SplitString(
- base::UTF8ToUTF16(kTestStrings[i].text), std::u16string(1, '\n'),
- base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ std::vector<std::u16string> lines =
+ base::SplitString(kTestStrings[i].text, std::u16string(1, '\n'),
+ base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
ASSERT_EQ(2u, lines.size());
// Sanity check the input string lengths match the glyph lengths.
@@ -5969,36 +5933,46 @@ TEST_F(RenderTextTest, Multiline_WordWrapBehavior) {
TEST_F(RenderTextTest, Multiline_LineBreakerBehavior) {
const int kGlyphSize = 5;
const struct {
- const char* const text;
+ const char16_t* const text;
const WordWrapBehavior behavior;
const Range char_ranges[3];
} kTestScenarios[] = {
- {"a single run",
+ {u"a single run",
IGNORE_LONG_WORDS,
{Range(0, 2), Range(2, 9), Range(9, 12)}},
// 3 words: "That's ", ""good". ", "aaa" and 7 runs: "That", "'", "s ",
// """, "good", "". ", "aaa". They all mixed together.
- {"That's \"good\". aaa", IGNORE_LONG_WORDS,
+ {u"That's \"good\". aaa",
+ IGNORE_LONG_WORDS,
{Range(0, 7), Range(7, 15), Range(15, 18)}},
// Test "\"" should be put into a new line correctly.
- {"a \"good\" one.", IGNORE_LONG_WORDS,
+ {u"a \"good\" one.",
+ IGNORE_LONG_WORDS,
{Range(0, 2), Range(2, 9), Range(9, 13)}},
// Test for full-width space.
- {"That's\u3000good.\u3000yyy", IGNORE_LONG_WORDS,
+ {u"That's\u3000good.\u3000yyy",
+ IGNORE_LONG_WORDS,
{Range(0, 7), Range(7, 13), Range(13, 16)}},
- {"a single run", TRUNCATE_LONG_WORDS,
+ {u"a single run",
+ TRUNCATE_LONG_WORDS,
{Range(0, 2), Range(2, 6), Range(9, 12)}},
- {"That's \"good\". aaa", TRUNCATE_LONG_WORDS,
+ {u"That's \"good\". aaa",
+ TRUNCATE_LONG_WORDS,
{Range(0, 4), Range(7, 11), Range(15, 18)}},
- {"That's good. aaa", TRUNCATE_LONG_WORDS,
+ {u"That's good. aaa",
+ TRUNCATE_LONG_WORDS,
{Range(0, 4), Range(7, 11), Range(13, 16)}},
- {"a \"good\" one.", TRUNCATE_LONG_WORDS,
+ {u"a \"good\" one.",
+ TRUNCATE_LONG_WORDS,
{Range(0, 2), Range(2, 6), Range(9, 13)}},
- {"asingleword", WRAP_LONG_WORDS,
+ {u"asingleword",
+ WRAP_LONG_WORDS,
{Range(0, 4), Range(4, 8), Range(8, 11)}},
- {"That's good", WRAP_LONG_WORDS,
+ {u"That's good",
+ WRAP_LONG_WORDS,
{Range(0, 4), Range(4, 7), Range(7, 11)}},
- {"That's \"g\".", WRAP_LONG_WORDS,
+ {u"That's \"g\".",
+ WRAP_LONG_WORDS,
{Range(0, 4), Range(4, 7), Range(7, 11)}},
};
@@ -6009,7 +5983,7 @@ TEST_F(RenderTextTest, Multiline_LineBreakerBehavior) {
for (size_t i = 0; i < base::size(kTestScenarios); ++i) {
SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
- render_text->SetText(UTF8ToUTF16(kTestScenarios[i].text));
+ render_text->SetText(kTestScenarios[i].text);
render_text->SetWordWrapBehavior(kTestScenarios[i].behavior);
render_text->Draw(canvas());
@@ -6093,10 +6067,8 @@ TEST_F(RenderTextTest, Multiline_ZeroWidthChars) {
render_text->SetMultiline(true);
render_text->SetWordWrapBehavior(WRAP_LONG_WORDS);
- const char16_t kZeroWidthSpace = {0x200B};
- const std::u16string text(ASCIIToUTF16("test") + kZeroWidthSpace +
- ASCIIToUTF16("\n") + kZeroWidthSpace +
- ASCIIToUTF16("test."));
+ // U+200B is Zero Width Space.
+ const std::u16string text = u"test\u200B\n\u200Btest.";
const int kTestWidth = GetStringWidth(u"test", render_text->font_list());
const Range char_ranges[3] = {Range(0, 6), Range(6, 11), Range(11, 12)};
@@ -6161,8 +6133,8 @@ TEST_F(RenderTextTest, Multiline_GetLineContainingCaret) {
render_text->SetMultiline(true);
render_text->SetVerticalAlignment(ALIGN_TOP);
- for (auto text : {ASCIIToUTF16("\n123 456 789\n\n123"),
- UTF8ToUTF16("\nשנב גקכ עין\n\nחלך")}) {
+ for (const char16_t* text :
+ {u"\n123 456 789\n\n123", u"\nשנב גקכ עין\n\nחלך"}) {
for (const auto& sample : cases) {
SCOPED_TRACE(testing::Message()
<< "Testing " << (text[1] == '1' ? "LTR" : "RTL")
@@ -6181,8 +6153,8 @@ TEST_F(RenderTextTest, Multiline_GetLineContainingCaret) {
}
TEST_F(RenderTextTest, NewlineWithoutMultilineFlag) {
- const char* kTestStrings[] = {
- "abc\ndef", "a \n b ", "ab\n", "a\n\nb", "\nab", "\n",
+ const char16_t* kTestStrings[] = {
+ u"abc\ndef", u"a \n b ", u"ab\n", u"a\n\nb", u"\nab", u"\n",
};
RenderText* render_text = GetRenderText();
@@ -6190,7 +6162,7 @@ TEST_F(RenderTextTest, NewlineWithoutMultilineFlag) {
for (size_t i = 0; i < base::size(kTestStrings); ++i) {
SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
- render_text->SetText(ASCIIToUTF16(kTestStrings[i]));
+ render_text->SetText(kTestStrings[i]);
render_text->Draw(canvas());
EXPECT_EQ(1U, test_api()->lines().size());
@@ -6198,10 +6170,10 @@ TEST_F(RenderTextTest, NewlineWithoutMultilineFlag) {
}
TEST_F(RenderTextTest, ControlCharacterReplacement) {
- static const char kTextWithControlCharacters[] = "\b\r\a\t\n\v\f";
+ static const char16_t kTextWithControlCharacters[] = u"\b\r\a\t\n\v\f";
RenderText* render_text = GetRenderText();
- render_text->SetText(ASCIIToUTF16(kTextWithControlCharacters));
+ render_text->SetText(kTextWithControlCharacters);
// The control characters should have been replaced by their symbols.
EXPECT_EQ(u"␈␍␇␉␊␋␌", render_text->GetDisplayText());
@@ -6212,8 +6184,8 @@ TEST_F(RenderTextTest, ControlCharacterReplacement) {
// The generic control characters should have been replaced by the replacement
// codepoints.
- render_text->SetText(UTF8ToUTF16("\u008f\u0080"));
- EXPECT_EQ(UTF8ToUTF16("\ufffd\ufffd"), render_text->GetDisplayText());
+ render_text->SetText(u"\u008f\u0080");
+ EXPECT_EQ(u"\ufffd\ufffd", render_text->GetDisplayText());
}
TEST_F(RenderTextTest, PrivateUseCharacterReplacement) {
@@ -6222,13 +6194,12 @@ TEST_F(RenderTextTest, PrivateUseCharacterReplacement) {
// The private use characters should have been replaced. If the code point is
// a surrogate pair, it needs to be replaced by two characters.
- EXPECT_EQ(UTF8ToUTF16("xx\ufffd\ufffda\ufffdz"),
- render_text->GetDisplayText());
+ EXPECT_EQ(u"xx\ufffd\ufffda\ufffdz", render_text->GetDisplayText());
// The private use characters from Area-B must be replaced. The rewrite step
// replaced 2 characters by 1 character.
render_text->SetText(u"x\U00100000\U00100001\U00100002");
- EXPECT_EQ(UTF8ToUTF16("x\ufffd\ufffd\ufffd"), render_text->GetDisplayText());
+ EXPECT_EQ(u"x\ufffd\ufffd\ufffd", render_text->GetDisplayText());
}
TEST_F(RenderTextTest, AppleSpecificPrivateUseCharacterReplacement) {
@@ -6236,9 +6207,9 @@ TEST_F(RenderTextTest, AppleSpecificPrivateUseCharacterReplacement) {
RenderText* render_text = GetRenderText();
render_text->SetText(u"\uf8ff");
#if defined(OS_APPLE)
- EXPECT_EQ(UTF8ToUTF16("\uf8ff"), render_text->GetDisplayText());
+ EXPECT_EQ(u"\uf8ff", render_text->GetDisplayText());
#else
- EXPECT_EQ(UTF8ToUTF16("\ufffd"), render_text->GetDisplayText());
+ EXPECT_EQ(u"\ufffd", render_text->GetDisplayText());
#endif
}
@@ -6246,25 +6217,25 @@ TEST_F(RenderTextTest, InvalidSurrogateCharacterReplacement) {
// Text with invalid surrogates (surrogates low 0xDC00 and high 0xD800).
RenderText* render_text = GetRenderText();
render_text->SetText(u"\xDC00\xD800");
- EXPECT_EQ(UTF8ToUTF16("\ufffd\ufffd"), render_text->GetDisplayText());
+ EXPECT_EQ(u"\ufffd\ufffd", render_text->GetDisplayText());
}
// Make sure the horizontal positions of runs in a line (left-to-right for
// LTR languages and right-to-left for RTL languages).
TEST_F(RenderTextTest, HarfBuzz_HorizontalPositions) {
const struct {
- const char* const text;
+ const char16_t* const text;
const char* expected_runs;
} kTestStrings[] = {
- {"abc\u3042\u3044\u3046\u3048\u304A", "[0->2][3->7]"},
- {"\u062A\u0641\u0627\u062D\u05EA\u05E4\u05D5\u05D6", "[7<-4][3<-0]"},
+ {u"abc\u3042\u3044\u3046\u3048\u304A", "[0->2][3->7]"},
+ {u"\u062A\u0641\u0627\u062D\u05EA\u05E4וז", "[7<-4][3<-0]"},
};
RenderTextHarfBuzz* render_text = GetRenderText();
for (size_t i = 0; i < base::size(kTestStrings); ++i) {
SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
- render_text->SetText(UTF8ToUTF16(kTestStrings[i].text));
+ render_text->SetText(kTestStrings[i].text);
EXPECT_EQ(kTestStrings[i].expected_runs, GetRunListStructureString());
@@ -6357,13 +6328,13 @@ TEST_F(RenderTextTest, HarfBuzz_NoCrashOnTextRunGetClusterAt) {
// Ensure that graphemes with multiple code points do not get split.
TEST_F(RenderTextTest, HarfBuzz_SubglyphGraphemeCases) {
- const char* cases[] = {
+ const char16_t* cases[] = {
// Ä (A with combining umlaut), followed by a "B".
- "A\u0308B",
+ u"A\u0308B",
// कि (Devangari letter KA with vowel I), followed by an "a".
- "\u0915\u093f\u0905",
- // จำ (Thai charcters CHO CHAN and SARA AM, followed by Thai digit 0.
- "\u0e08\u0e33\u0E50",
+ u"\u0915\u093f\u0905",
+ // จำ (Thai characters CHO CHAN and SARA AM, followed by Thai digit 0.
+ u"\u0e08\u0e33\u0E50",
};
RenderTextHarfBuzz* render_text = GetRenderText();
@@ -6371,7 +6342,7 @@ TEST_F(RenderTextTest, HarfBuzz_SubglyphGraphemeCases) {
for (size_t i = 0; i < base::size(cases); ++i) {
SCOPED_TRACE(base::StringPrintf("Case %" PRIuS, i));
- std::u16string text = UTF8ToUTF16(cases[i]);
+ std::u16string text = cases[i];
render_text->SetText(text);
const internal::TextRunList* run_list = GetHarfBuzzRunList();
ASSERT_EQ(1U, run_list->size());
@@ -6441,7 +6412,7 @@ TEST_F(RenderTextTest, HarfBuzz_SubglyphGraphemePartition) {
TEST_F(RenderTextTest, HarfBuzz_RunDirection) {
RenderTextHarfBuzz* render_text = GetRenderText();
- const std::u16string mixed = UTF8ToUTF16("\u05D0\u05D11234\u05D2\u05D3abc");
+ const std::u16string mixed = u"אב1234גדabc";
render_text->SetText(mixed);
// Get the run list for both display directions.
@@ -6456,9 +6427,9 @@ TEST_F(RenderTextTest, HarfBuzz_RunDirection_URLs) {
RenderTextHarfBuzz* render_text = GetRenderText();
// This string, unescaped (logical order):
// ‭www.אב.גד/הוabc/def?זח=טי‬
- const std::u16string mixed = UTF8ToUTF16(
- "www.\u05D0\u05D1.\u05D2\u05D3/\u05D4\u05D5"
- "abc/def?\u05D6\u05D7=\u05D8\u05D9");
+ const std::u16string mixed =
+ u"www.אב.גד/הו"
+ u"abc/def?זח=טי";
render_text->SetText(mixed);
// Normal LTR text should treat URL syntax as weak (as per the normal Bidi
@@ -6483,12 +6454,14 @@ TEST_F(RenderTextTest, HarfBuzz_BreakRunsByUnicodeBlocks) {
RenderTextHarfBuzz* render_text = GetRenderText();
// The ▶ (U+25B6) "play character" should break runs. http://crbug.com/278913
- render_text->SetText(UTF8ToUTF16("x\u25B6y"));
- EXPECT_EQ(ToString16Vec({"x", "▶", "y"}), GetRunListStrings());
+ render_text->SetText(u"x\u25B6y");
+ EXPECT_EQ(std::vector<std::u16string>({u"x", u"▶", u"y"}),
+ GetRunListStrings());
EXPECT_EQ("[0][1][2]", GetRunListStructureString());
- render_text->SetText(UTF8ToUTF16("x \u25B6 y"));
- EXPECT_EQ(ToString16Vec({"x", " ", "▶", " ", "y"}), GetRunListStrings());
+ render_text->SetText(u"x \u25B6 y");
+ EXPECT_EQ(std::vector<std::u16string>({u"x", u" ", u"▶", u" ", u"y"}),
+ GetRunListStrings());
EXPECT_EQ("[0][1][2][3][4]", GetRunListStructureString());
}
@@ -6499,13 +6472,15 @@ TEST_F(RenderTextTest, HarfBuzz_BreakRunsByEmoji) {
// drawn with color emoji fonts, so runs should be separated. crbug.com/448909
// Windows requires wide strings for \Unnnnnnnn universal character names.
render_text->SetText(u"x\U0001F601y\u2728");
- EXPECT_EQ(ToString16Vec({"x", "😁", "y", "✨"}), GetRunListStrings());
+ EXPECT_EQ(std::vector<std::u16string>({u"x", u"😁", u"y", u"✨"}),
+ GetRunListStrings());
// U+1F601 is represented as a surrogate pair in UTF-16.
EXPECT_EQ("[0][1->2][3][4]", GetRunListStructureString());
// Ensure non-latin 「foo」 brackets around Emoji correctly break runs.
render_text->SetText(u"「🦋」「");
- EXPECT_EQ(ToString16Vec({"「", "🦋", "」「"}), GetRunListStrings());
+ EXPECT_EQ(std::vector<std::u16string>({u"「", u"🦋", u"」「"}),
+ GetRunListStrings());
// Note 🦋 is a surrogate pair [1->2].
EXPECT_EQ("[0][1->2][3->4]", GetRunListStructureString());
}
@@ -6514,7 +6489,8 @@ TEST_F(RenderTextTest, HarfBuzz_BreakRunsByNewline) {
RenderText* render_text = GetRenderText();
render_text->SetMultiline(true);
render_text->SetText(u"x\ny");
- EXPECT_EQ(ToString16Vec({"x", "\n", "y"}), GetRunListStrings());
+ EXPECT_EQ(std::vector<std::u16string>({u"x", u"\n", u"y"}),
+ GetRunListStrings());
EXPECT_EQ("[0][1][2]", GetRunListStructureString());
// Validate that the character newline is an unknown glyph
@@ -6547,9 +6523,10 @@ TEST_F(RenderTextTest, HarfBuzz_BreakRunsByEmojiVariationSelectors) {
// ☎ (U+260E BLACK TELEPHONE) and U+FE0F (a variation selector) combine to
// form (on some platforms), ☎️, a red (or blue) telephone. The run can
// not break between the codepoints, or the incorrect glyph will be chosen.
- render_text->SetText(UTF8ToUTF16("z\u260E\uFE0Fy"));
+ render_text->SetText(u"z\u260E\uFE0Fy");
render_text->SetDisplayRect(Rect(1000, 50));
- EXPECT_EQ(ToString16Vec({"z", "☎\uFE0F", "y"}), GetRunListStrings());
+ EXPECT_EQ(std::vector<std::u16string>({u"z", u"☎\uFE0F", u"y"}),
+ GetRunListStrings());
EXPECT_EQ("[0][1->2][3]", GetRunListStructureString());
// Also test moving the cursor across the telephone.
@@ -6589,8 +6566,8 @@ TEST_F(RenderTextTest, HarfBuzz_OrphanedVariationSelector) {
// It should never happen in normal usage, but a variation selector can appear
// by itself. In this case, it can form its own text run, with no glyphs.
- render_text->SetText(UTF8ToUTF16("\uFE0F"));
- EXPECT_EQ(ToString16Vec({"\uFE0F"}), GetRunListStrings());
+ render_text->SetText(u"\uFE0F");
+ EXPECT_EQ(std::vector<std::u16string>({u"\uFE0F"}), GetRunListStrings());
EXPECT_EQ("[0]", GetRunListStructureString());
CheckBoundsForCursorPositions();
}
@@ -6605,8 +6582,8 @@ TEST_F(RenderTextTest, HarfBuzz_AsciiVariationSelector) {
// A variation selector doesn't have to appear with Emoji. It will probably
// cause the typesetter to render tofu in this case, but it should not break
// a text run.
- render_text->SetText(UTF8ToUTF16("z\uFE0Fy"));
- EXPECT_EQ(ToString16Vec({"z\uFE0Fy"}), GetRunListStrings());
+ render_text->SetText(u"z\uFE0Fy");
+ EXPECT_EQ(std::vector<std::u16string>({u"z\uFE0Fy"}), GetRunListStrings());
EXPECT_EQ("[0->2]", GetRunListStructureString());
CheckBoundsForCursorPositions();
}
@@ -6616,8 +6593,9 @@ TEST_F(RenderTextTest, HarfBuzz_LeadingVariationSelector) {
// When a variation selector appears either side of an emoji, ensure the one
// after is in the same run.
- render_text->SetText(UTF8ToUTF16("\uFE0F\u260E\uFE0Fy"));
- EXPECT_EQ(ToString16Vec({"\uFE0F", "☎\uFE0F", "y"}), GetRunListStrings());
+ render_text->SetText(u"\uFE0F\u260E\uFE0Fy");
+ EXPECT_EQ(std::vector<std::u16string>({u"\uFE0F", u"☎\uFE0F", u"y"}),
+ GetRunListStrings());
EXPECT_EQ("[0][1->2][3]", GetRunListStructureString());
CheckBoundsForCursorPositions();
}
@@ -6629,8 +6607,9 @@ TEST_F(RenderTextTest, HarfBuzz_TrailingVariationSelector) {
// merged into the emoji run. Usually there should be no effect. That's
// ultimately up to the typeface but, however it choses, cursor and glyph
// positions should behave.
- render_text->SetText(UTF8ToUTF16("z\u260E\uFE0F\uFE0Fy"));
- EXPECT_EQ(ToString16Vec({"z", "☎\uFE0F\uFE0F", "y"}), GetRunListStrings());
+ render_text->SetText(u"z\u260E\uFE0F\uFE0Fy");
+ EXPECT_EQ(std::vector<std::u16string>({u"z", u"☎\uFE0F\uFE0F", u"y"}),
+ GetRunListStrings());
EXPECT_EQ("[0][1->3][4]", GetRunListStructureString());
CheckBoundsForCursorPositions();
}
@@ -6640,8 +6619,9 @@ TEST_F(RenderTextTest, HarfBuzz_MultipleVariationSelectorEmoji) {
// Two emoji with variation selectors appearing in a correct sequence should
// be in the same run.
- render_text->SetText(UTF8ToUTF16("z\u260E\uFE0F\u260E\uFE0Fy"));
- EXPECT_EQ(ToString16Vec({"z", "☎\uFE0F☎\uFE0F", "y"}), GetRunListStrings());
+ render_text->SetText(u"z\u260E\uFE0F\u260E\uFE0Fy");
+ EXPECT_EQ(std::vector<std::u16string>({u"z", u"☎\uFE0F☎\uFE0F", u"y"}),
+ GetRunListStrings());
EXPECT_EQ("[0][1->4][5]", GetRunListStructureString());
CheckBoundsForCursorPositions();
}
@@ -6652,26 +6632,26 @@ TEST_F(RenderTextTest, HarfBuzz_BreakRunsByAscii) {
// ▶ (U+25B6, Geometric Shapes) and an ascii character should have
// different runs.
render_text->SetText(u"▶z");
- EXPECT_EQ(ToString16Vec({"▶", "z"}), GetRunListStrings());
+ EXPECT_EQ(std::vector<std::u16string>({u"▶", u"z"}), GetRunListStrings());
EXPECT_EQ("[0][1]", GetRunListStructureString());
// ★ (U+2605, Miscellaneous Symbols) and an ascii character should have
// different runs.
render_text->SetText(u"★1");
- EXPECT_EQ(ToString16Vec({"★", "1"}), GetRunListStrings());
+ EXPECT_EQ(std::vector<std::u16string>({u"★", u"1"}), GetRunListStrings());
EXPECT_EQ("[0][1]", GetRunListStructureString());
// 🐱 (U+1F431, a cat face, Miscellaneous Symbols and Pictographs) and an
// ASCII period should have separate runs.
render_text->SetText(u"🐱.");
- EXPECT_EQ(ToString16Vec({"🐱", "."}), GetRunListStrings());
+ EXPECT_EQ(std::vector<std::u16string>({u"🐱", u"."}), GetRunListStrings());
// U+1F431 is represented as a surrogate pair in UTF-16.
EXPECT_EQ("[0->1][2]", GetRunListStructureString());
// 🥴 (U+1f974, Supplemental Symbols and Pictographs) and an ascii character
// should have different runs.
render_text->SetText(u"🥴$");
- EXPECT_EQ(ToString16Vec({"🥴", "$"}), GetRunListStrings());
+ EXPECT_EQ(std::vector<std::u16string>({u"🥴", u"$"}), GetRunListStrings());
EXPECT_EQ("[0->1][2]", GetRunListStructureString());
}
@@ -6712,8 +6692,7 @@ TEST_F(RenderTextTest, HarfBuzz_ShapeRunsWithMultipleFonts) {
// 3) u+1F308 u+20E0 u+20E0 (Segoe UI Symbol)
// The three runs are shape in the same group but are mapped with three
// different fonts.
- render_text->SetText(
- UTF8ToUTF16(u8"\U0001F3F3\U0000FE0F\U00000020\U0001F308\U000020E0"));
+ render_text->SetText(u"\U0001F3F3\U0000FE0F\U00000020\U0001F308\U000020E0");
std::vector<std::u16string> expected;
expected.push_back(u"\U0001F3F3\U0000FE0F");
expected.push_back(u" ");
@@ -6736,12 +6715,12 @@ TEST_F(RenderTextTest, HarfBuzz_ShapeRunsWithMultipleFonts) {
}
TEST_F(RenderTextTest, GlyphBounds) {
- const char* kTestStrings[] = {"asdf 1234 qwer", "\u0647\u0654",
- "\u0645\u0631\u062D\u0628\u0627"};
+ const char16_t* kTestStrings[] = {u"asdf 1234 qwer", u"\u0647\u0654",
+ u"\u0645\u0631\u062D\u0628\u0627"};
RenderText* render_text = GetRenderText();
for (size_t i = 0; i < base::size(kTestStrings); ++i) {
- render_text->SetText(UTF8ToUTF16(kTestStrings[i]));
+ render_text->SetText(kTestStrings[i]);
for (size_t j = 0; j < render_text->text().length(); ++j)
EXPECT_FALSE(render_text->GetCursorSpan(Range(j, j + 1)).is_empty());
@@ -6780,7 +6759,7 @@ TEST_F(RenderTextTest, HarfBuzz_EmptyRun) {
// actual size. See http://crbug.com/470073
TEST_F(RenderTextTest, HarfBuzz_WordWidthWithDiacritics) {
RenderTextHarfBuzz* render_text = GetRenderText();
- const std::u16string kWord = UTF8ToUTF16("\u0906\u092A\u0915\u0947 ");
+ const std::u16string kWord = u"\u0906\u092A\u0915\u0947 ";
render_text->SetText(kWord);
const SizeF text_size = render_text->GetStringSizeF();
@@ -6827,7 +6806,7 @@ TEST_F(RenderTextTest, HarfBuzz_FontListFallback) {
// falling back to some other font that's present on the system.
RenderTextHarfBuzz* render_text = GetRenderText();
render_text->SetFontList(font_list);
- render_text->SetText(UTF8ToUTF16("\u2295"));
+ render_text->SetText(u"\u2295");
const std::vector<FontSpan> spans = GetFontSpans();
ASSERT_EQ(static_cast<size_t>(1), spans.size());
EXPECT_EQ(kSymbolFontName, spans[0].first.GetFontName());
@@ -6844,7 +6823,7 @@ TEST_F(RenderTextTest, HarfBuzz_UnicodeFallback) {
render_text->SetFontList(FontList("Arial, 12px"));
// An invalid Unicode character that somehow yields Korean character "han".
- render_text->SetText(UTF8ToUTF16("\ud55c"));
+ render_text->SetText(u"\ud55c");
const internal::TextRunList* run_list = GetHarfBuzzRunList();
ASSERT_EQ(1U, run_list->size());
EXPECT_EQ(0U, run_list->runs()[0]->CountMissingGlyphs());
@@ -6855,13 +6834,13 @@ TEST_F(RenderTextTest, HarfBuzz_UnicodeFallback) {
// for different languages.
TEST_F(RenderTextTest, HarfBuzz_FallbackFontsSupportGlyphs) {
// The word 'test' in different languages.
- static const wchar_t* kLanguageTests[] = {
- L"test", L"اختبار", L"Δοκιμή", L"परीक्षा", L"تست", L"Փորձարկում",
+ static const char16_t* kLanguageTests[] = {
+ u"test", u"اختبار", u"Δοκιμή", u"परीक्षा", u"تست", u"Փորձարկում",
};
- for (const wchar_t* text : kLanguageTests) {
+ for (const auto* text : kLanguageTests) {
RenderTextHarfBuzz* render_text = GetRenderText();
- render_text->SetText(WideToUTF16(text));
+ render_text->SetText(text);
const internal::TextRunList* run_list = GetHarfBuzzRunList();
ASSERT_EQ(1U, run_list->size());
@@ -6876,15 +6855,15 @@ TEST_F(RenderTextTest, HarfBuzz_FallbackFontsSupportGlyphs) {
// Ensure that the fallback fonts offered by GetFallbackFont() support glyphs
// for different languages.
TEST_F(RenderTextTest, HarfBuzz_MultiRunsSupportGlyphs) {
- static const wchar_t* kLanguageTests[] = {
- L"www.اختبار.com",
- L"(اختبار)",
- L"/ זה (מבחן) /",
+ static const char16_t* kLanguageTests[] = {
+ u"www.اختبار.com",
+ u"(اختبار)",
+ u"/ זה (מבחן) /",
};
- for (const wchar_t* text : kLanguageTests) {
+ for (const auto* text : kLanguageTests) {
RenderTextHarfBuzz* render_text = GetRenderText();
- render_text->SetText(WideToUTF16(text));
+ render_text->SetText(text);
int missing_glyphs = 0;
const internal::TextRunList* run_list = GetHarfBuzzRunList();
@@ -6900,7 +6879,7 @@ TEST_F(RenderTextTest, HarfBuzz_MultiRunsSupportGlyphs) {
struct FallbackFontCase {
const char* test_name;
- const wchar_t* text;
+ const char16_t* text;
};
class RenderTextTestWithFallbackFontCase
@@ -6916,7 +6895,7 @@ class RenderTextTestWithFallbackFontCase
TEST_P(RenderTextTestWithFallbackFontCase, FallbackFont) {
FallbackFontCase param = GetParam();
RenderTextHarfBuzz* render_text = GetRenderText();
- render_text->SetText(WideToUTF16(param.text));
+ render_text->SetText(param.text);
int missing_glyphs = 0;
const internal::TextRunList* run_list = GetHarfBuzzRunList();
@@ -6928,17 +6907,17 @@ TEST_P(RenderTextTestWithFallbackFontCase, FallbackFont) {
const FallbackFontCase kUnicodeDecomposeCases[] = {
// Decompose to "\u0041\u0300".
- {"letter_A_with_grave", L"\u00c0"},
+ {"letter_A_with_grave", u"\u00c0"},
// Decompose to "\u004f\u0328\u0304".
- {"letter_O_with_ogonek_macron", L"\u01ec"},
+ {"letter_O_with_ogonek_macron", u"\u01ec"},
// Decompose to "\u0041\u030a".
- {"angstrom_sign", L"\u212b"},
+ {"angstrom_sign", u"\u212b"},
// Decompose to "\u1100\u1164\u11b6".
- {"hangul_syllable_gyaelh", L"\uac63"},
+ {"hangul_syllable_gyaelh", u"\uac63"},
// Decompose to "\u1107\u1170\u11af".
- {"hangul_syllable_bwel", L"\ubdc0"},
+ {"hangul_syllable_bwel", u"\ubdc0"},
// Decompose to "\U00044039".
- {"cjk_ideograph_fad4", L"\ufad4"},
+ {"cjk_ideograph_fad4", u"\ufad4"},
};
INSTANTIATE_TEST_SUITE_P(FallbackFontUnicodeDecompose,
@@ -6950,64 +6929,64 @@ INSTANTIATE_TEST_SUITE_P(FallbackFontUnicodeDecompose,
// codepoint can be rendered by the font. An error here can be by an incorrect
// ItemizeText(...) leading to an invalid fallback font.
const FallbackFontCase kComplexTextCases[] = {
- {"simple1", L"test"},
- {"simple2", L"اختبار"},
- {"simple3", L"Δοκιμή"},
- {"simple4", L"परीक्षा"},
- {"simple5", L"تست"},
- {"simple6", L"Փորձարկում"},
- {"mixed1", L"www.اختبار.com"},
- {"mixed2", L"(اختبار)"},
- {"mixed3", L"/ זה (מבחן) /"},
+ {"simple1", u"test"},
+ {"simple2", u"اختبار"},
+ {"simple3", u"Δοκιμή"},
+ {"simple4", u"परीक्षा"},
+ {"simple5", u"تست"},
+ {"simple6", u"Փորձարկում"},
+ {"mixed1", u"www.اختبار.com"},
+ {"mixed2", u"(اختبار)"},
+ {"mixed3", u"/ זה (מבחן) /"},
#if defined(OS_WIN)
- {"asc_arb", L"abcښڛڜdef"},
- {"devanagari", L"ञटठडढणतथ"},
- {"ethiopic", L"መጩጪᎅⶹⶼ"},
- {"greek", L"ξοπρς"},
- {"kannada", L"ಠಡಢಣತಥ"},
- {"lao", L"ປຝພຟມ"},
- {"oriya", L"ଔକଖଗଘଙ"},
- {"telugu_lat", L"aaఉయ!"},
- {"common_math", L"ℳ: ¬ƒ(x)=½×¾"},
- {"picto_title", L"☞☛test☚☜"},
- {"common_numbers", L"𝟭𝟐⒓¹²"},
- {"common_puncts", L",.!"},
- {"common_space_math1", L" 𝓐"},
- {"common_space_math2", L" 𝓉"},
- {"common_split_spaces", L"♬ 𝓐"},
- {"common_mixed", L"\U0001d4c9\u24d4\U0001d42c"},
- {"arrows", L"↰↱↲↳↴↵⇚⇛⇜⇝⇞⇟"},
- {"arrows_space", L"↰ ↱ ↲ ↳ ↴ ↵ ⇚ ⇛ ⇜ ⇝ ⇞ ⇟"},
- {"emoji_title", L"▶Feel goods"},
- {"enclosed_alpha", L"ⒶⒷⒸⒹⒺⒻⒼ"},
- {"shapes", L" ▶▷▸▹►▻◀◁◂◃◄◅"},
- {"symbols", L"☂☎☏☝☫☬☭☮☯"},
- {"symbols_space", L"☂ ☎ ☏ ☝ ☫ ☬ ☭ ☮ ☯"},
- {"dingbats", L"✂✃✄✆✇✈"},
- {"cjk_compatibility_ideographs", L"賈滑串句龜"},
- {"lat_dev_ZWNJ", L"a\u200Cक"},
- {"paren_picto", L"(☾☹☽)"},
- {"emoji1", L"This is 💩!"},
- {"emoji2", L"Look [🔝]"},
- {"strange1", L"💔♬ 𝓐 𝓉ⓔ𝐬т FỖ𝕣 c卄尺𝕆ᵐ€ ♘👹"},
- {"strange2", L"˜”*°•.˜”*°• A test for chrome •°*”˜.•°*”˜"},
- {"strange3", L"𝐭єⓢт fσ𝐑 𝔠ʰ𝕣ό𝐌𝔢"},
- {"strange4", L"тẸⓈ𝔱 𝔽𝕠ᖇ 𝕔𝐡ŕ𝔬ⓜẸ"},
- {"url1", L"http://www.google.com"},
- {"url2", L"http://www.nowhere.com/Lörick.html"},
- {"url3", L"http://www.nowhere.com/تسجيل الدخول"},
- {"url4", L"https://xyz.com:8080/تس(1)جيل الدخول"},
- {"url5", L"http://www.script.com/test.php?abc=42&cde=12&f=%20%20"},
- {"punct1", L"This‐is‑a‒test–for—punctuations"},
- {"punct2", L"⁅All ‷magic‴ comes with a ‶price″⁆"},
- {"punct3", L"⍟ Complete my sentence… †"},
- {"parens", L"❝This❞ 「test」 has ((a)) 【lot】 [{of}] 〚parentheses〛"},
- {"games", L"Let play: ♗♘⚀⚁♠♣"},
- {"braille", L"⠞⠑⠎⠞ ⠋⠕⠗ ⠉⠓⠗⠕⠍⠑"},
- {"emoticon1", L"¯\\_(ツ)_/¯"},
- {"emoticon2", L"٩(⁎❛ᴗ❛⁎)۶"},
- {"emoticon3", L"(͡° ͜ʖ ͡°)"},
- {"emoticon4", L"[̲̅$̲̅(̲̅5̲̅)̲̅$̲̅]"},
+ {"asc_arb", u"abcښڛڜdef"},
+ {"devanagari", u"ञटठडढणतथ"},
+ {"ethiopic", u"መጩጪᎅⶹⶼ"},
+ {"greek", u"ξοπρς"},
+ {"kannada", u"ಠಡಢಣತಥ"},
+ {"lao", u"ປຝພຟມ"},
+ {"oriya", u"ଔକଖଗଘଙ"},
+ {"telugu_lat", u"aaఉయ!"},
+ {"common_math", u"ℳ: ¬ƒ(x)=½×¾"},
+ {"picto_title", u"☞☛test☚☜"},
+ {"common_numbers", u"𝟭𝟐⒓¹²"},
+ {"common_puncts", u",.!"},
+ {"common_space_math1", u" 𝓐"},
+ {"common_space_math2", u" 𝓉"},
+ {"common_split_spaces", u"♬ 𝓐"},
+ {"common_mixed", u"\U0001d4c9\u24d4\U0001d42c"},
+ {"arrows", u"↰↱↲↳↴↵⇚⇛⇜⇝⇞⇟"},
+ {"arrows_space", u"↰ ↱ ↲ ↳ ↴ ↵ ⇚ ⇛ ⇜ ⇝ ⇞ ⇟"},
+ {"emoji_title", u"▶Feel goods"},
+ {"enclosed_alpha", u"ⒶⒷⒸⒹⒺⒻⒼ"},
+ {"shapes", u" ▶▷▸▹►▻◀◁◂◃◄◅"},
+ {"symbols", u"☂☎☏☝☫☬☭☮☯"},
+ {"symbols_space", u"☂ ☎ ☏ ☝ ☫ ☬ ☭ ☮ ☯"},
+ {"dingbats", u"✂✃✄✆✇✈"},
+ {"cjk_compatibility_ideographs", u"賈滑串句龜"},
+ {"lat_dev_ZWNJ", u"a\u200Cक"},
+ {"paren_picto", u"(☾☹☽)"},
+ {"emoji1", u"This is 💩!"},
+ {"emoji2", u"Look [🔝]"},
+ {"strange1", u"💔♬ 𝓐 𝓉ⓔ𝐬т FỖ𝕣 c卄尺𝕆ᵐ€ ♘👹"},
+ {"strange2", u"˜”*°•.˜”*°• A test for chrome •°*”˜.•°*”˜"},
+ {"strange3", u"𝐭єⓢт fσ𝐑 𝔠ʰ𝕣ό𝐌𝔢"},
+ {"strange4", u"тẸⓈ𝔱 𝔽𝕠ᖇ 𝕔𝐡ŕ𝔬ⓜẸ"},
+ {"url1", u"http://www.google.com"},
+ {"url2", u"http://www.nowhere.com/Lörick.html"},
+ {"url3", u"http://www.nowhere.com/تسجيل الدخول"},
+ {"url4", u"https://xyz.com:8080/تس(1)جيل الدخول"},
+ {"url5", u"http://www.script.com/test.php?abc=42&cde=12&f=%20%20"},
+ {"punct1", u"This‐is‑a‒test–for—punctuations"},
+ {"punct2", u"⁅All ‷magic‴ comes with a ‶price″⁆"},
+ {"punct3", u"⍟ Complete my sentence… †"},
+ {"parens", u"❝This❞ 「test」 has ((a)) 【lot】 [{of}] 〚parentheses〛"},
+ {"games", u"Let play: ♗♘⚀⚁♠♣"},
+ {"braille", u"⠞⠑⠎⠞ ⠋⠕⠗ ⠉⠓⠗⠕⠍⠑"},
+ {"emoticon1", u"¯\\_(ツ)_/¯"},
+ {"emoticon2", u"٩(⁎❛ᴗ❛⁎)۶"},
+ {"emoticon3", u"(͡° ͜ʖ ͡°)"},
+ {"emoticon4", u"[̲̅$̲̅(̲̅5̲̅)̲̅$̲̅]"},
#endif
};
@@ -7022,110 +7001,110 @@ INSTANTIATE_TEST_SUITE_P(FallbackFontComplexTextCases,
const FallbackFontCase kCommonScriptCases[] = {
#if defined(OS_WIN)
// The following tests are made to work on win7 and win10.
- {"common00", L"\u237b\u2ac1\u24f5\u259f\u2a87\u23ea\u25d4\u2220"},
- {"common01", L"\u2303\u2074\u2988\u32b6\u26a2\u24e5\u2a53\u2219"},
- {"common02", L"\u29b2\u25fc\u2366\u24ae\u2647\u258e\u2654\u25fe"},
- {"common03", L"\u21ea\u22b4\u29b0\u2a84\u0008\u2657\u2731\u2697"},
- {"common04", L"\u2b3c\u2932\u21c8\u23cf\u20a1\u2aa2\u2344\u0011"},
- {"common05", L"\u22c3\u2a56\u2340\u21b7\u26ba\u2798\u220f\u2404"},
- {"common06", L"\u21f9\u25fd\u008e\u21e6\u2686\u21e4\u259f\u29ee"},
- {"common07", L"\u231e\ufe39\u0008\u2349\u2262\u2270\uff09\u2b3b"},
- {"common08", L"\u24a3\u236e\u29b2\u2259\u26ea\u2705\u00ae\u2a23"},
- {"common09", L"\u33bd\u235e\u2018\u32ba\u2973\u02c1\u20b9\u25b4"},
- {"common10", L"\u2245\u2a4d\uff19\u2042\u2aa9\u2658\u276e\uff40"},
- {"common11", L"\u0007\u21b4\u23c9\u2593\u21ba\u00a0\u258f\u23b3"},
- {"common12", L"\u2938\u250c\u2240\u2676\u2297\u2b07\u237e\u2a04"},
- {"common13", L"\u2520\u233a\u20a5\u2744\u2445\u268a\u2716\ufe62"},
- {"common14", L"\ufe4d\u25d5\u2ae1\u2a35\u2323\u273c\u26be\u2a3b"},
- {"common15", L"\u2aa2\u0000\ufe65\u2962\u2573\u21f8\u2651\u02d2"},
- {"common16", L"\u225c\u2283\u2960\u4de7\uff12\uffe1\u0016\u2905"},
- {"common17", L"\uff07\u25aa\u2076\u259e\u226c\u2568\u0026\u2691"},
- {"common18", L"\u2388\u21c2\u208d\u2a7f\u22d0\u2583\u2ad5\u240f"},
- {"common19", L"\u230a\u27ac\u001e\u261e\u259d\u25c3\u33a5\u0011"},
- {"common20", L"\ufe54\u29c7\u2477\u21ed\u2069\u4dfc\u2ae2\u21e8"},
- {"common21", L"\u2131\u2ab7\u23b9\u2660\u2083\u24c7\u228d\u2a01"},
- {"common22", L"\u2587\u2572\u21df\uff3c\u02cd\ufffd\u2404\u22b3"},
- {"common23", L"\u4dc3\u02fe\uff09\u25a3\ufe14\u255c\u2128\u2698"},
- {"common24", L"\u2b36\u3382\u02f6\u2752\uff16\u22cf\u00b0\u21d6"},
- {"common25", L"\u2561\u23db\u2958\u2782\u22af\u2621\u24a3\u29ae"},
- {"common26", L"\u2693\u22e2\u2988\u2987\u33ba\u2a94\u298e\u2328"},
- {"common27", L"\u266c\u2aa5\u2405\uffeb\uff5c\u2902\u291e\u02e6"},
- {"common28", L"\u2634\u32b2\u3385\u2032\u33be\u2366\u2ac7\u23cf"},
- {"common29", L"\u2981\ua721\u25a9\u2320\u21cf\u295a\u2273\u2ac2"},
- {"common30", L"\u22d9\u2465\u2347\u2a94\u4dca\u2389\u23b0\u208d"},
- {"common31", L"\u21cc\u2af8\u2912\u23a4\u2271\u2303\u241e\u33a1"},
+ {"common00", u"\u237b\u2ac1\u24f5\u259f\u2a87\u23ea\u25d4\u2220"},
+ {"common01", u"\u2303\u2074\u2988\u32b6\u26a2\u24e5\u2a53\u2219"},
+ {"common02", u"\u29b2\u25fc\u2366\u24ae\u2647\u258e\u2654\u25fe"},
+ {"common03", u"\u21ea\u22b4\u29b0\u2a84\u0008\u2657\u2731\u2697"},
+ {"common04", u"\u2b3c\u2932\u21c8\u23cf\u20a1\u2aa2\u2344\u0011"},
+ {"common05", u"\u22c3\u2a56\u2340\u21b7\u26ba\u2798\u220f\u2404"},
+ {"common06", u"\u21f9\u25fd\u008e\u21e6\u2686\u21e4\u259f\u29ee"},
+ {"common07", u"\u231e\ufe39\u0008\u2349\u2262\u2270\uff09\u2b3b"},
+ {"common08", u"\u24a3\u236e\u29b2\u2259\u26ea\u2705\u00ae\u2a23"},
+ {"common09", u"\u33bd\u235e\u2018\u32ba\u2973\u02c1\u20b9\u25b4"},
+ {"common10", u"\u2245\u2a4d\uff19\u2042\u2aa9\u2658\u276e\uff40"},
+ {"common11", u"\u0007\u21b4\u23c9\u2593\u21ba\u00a0\u258f\u23b3"},
+ {"common12", u"\u2938\u250c\u2240\u2676\u2297\u2b07\u237e\u2a04"},
+ {"common13", u"\u2520\u233a\u20a5\u2744\u2445\u268a\u2716\ufe62"},
+ {"common14", u"\ufe4d\u25d5\u2ae1\u2a35\u2323\u273c\u26be\u2a3b"},
+ {"common15", u"\u2aa2\u0000\ufe65\u2962\u2573\u21f8\u2651\u02d2"},
+ {"common16", u"\u225c\u2283\u2960\u4de7\uff12\uffe1\u0016\u2905"},
+ {"common17", u"\uff07\u25aa\u2076\u259e\u226c\u2568\u0026\u2691"},
+ {"common18", u"\u2388\u21c2\u208d\u2a7f\u22d0\u2583\u2ad5\u240f"},
+ {"common19", u"\u230a\u27ac\u001e\u261e\u259d\u25c3\u33a5\u0011"},
+ {"common20", u"\ufe54\u29c7\u2477\u21ed\u2069\u4dfc\u2ae2\u21e8"},
+ {"common21", u"\u2131\u2ab7\u23b9\u2660\u2083\u24c7\u228d\u2a01"},
+ {"common22", u"\u2587\u2572\u21df\uff3c\u02cd\ufffd\u2404\u22b3"},
+ {"common23", u"\u4dc3\u02fe\uff09\u25a3\ufe14\u255c\u2128\u2698"},
+ {"common24", u"\u2b36\u3382\u02f6\u2752\uff16\u22cf\u00b0\u21d6"},
+ {"common25", u"\u2561\u23db\u2958\u2782\u22af\u2621\u24a3\u29ae"},
+ {"common26", u"\u2693\u22e2\u2988\u2987\u33ba\u2a94\u298e\u2328"},
+ {"common27", u"\u266c\u2aa5\u2405\uffeb\uff5c\u2902\u291e\u02e6"},
+ {"common28", u"\u2634\u32b2\u3385\u2032\u33be\u2366\u2ac7\u23cf"},
+ {"common29", u"\u2981\ua721\u25a9\u2320\u21cf\u295a\u2273\u2ac2"},
+ {"common30", u"\u22d9\u2465\u2347\u2a94\u4dca\u2389\u23b0\u208d"},
+ {"common31", u"\u21cc\u2af8\u2912\u23a4\u2271\u2303\u241e\u33a1"},
#elif defined(OS_ANDROID)
- {"common00", L"\u2497\uff04\u277c\u21b6\u2076\u21e4\u2068\u21b3"},
- {"common01", L"\u2663\u2466\u338e\u226b\u2734\u21be\u3389\u00ab"},
- {"common02", L"\u2062\u2197\u3392\u2681\u33be\u206d\ufe10\ufe34"},
- {"common03", L"\u02db\u00b0\u02d3\u2745\u33d1\u21e4\u24e4\u33d6"},
- {"common04", L"\u21da\u261f\u26a1\u2586\u27af\u2560\u21cd\u25c6"},
- {"common05", L"\ufe51\uff17\u0027\u21fd\u24de\uff5e\u2606\u251f"},
- {"common06", L"\u2493\u2466\u21fc\u226f\u202d\u21a9\u0040\u265d"},
- {"common07", L"\u2103\u255a\u2153\u26be\u27ac\u222e\u2490\u21a4"},
- {"common08", L"\u270b\u2486\u246b\u263c\u27b6\u21d9\u219d\u25a9"},
- {"common09", L"\u002d\u2494\u25fd\u2321\u2111\u2511\u00d7\u2535"},
- {"common10", L"\u2523\u203e\u25b2\ufe18\u2499\u2229\ufd3e\ufe16"},
- {"common11", L"\u2133\u2716\u273f\u2064\u2248\u005c\u265f\u21e6"},
- {"common12", L"\u2060\u246a\u231b\u2726\u25bd\ufe40\u002e\u25ca"},
- {"common13", L"\ufe39\u24a2\ufe18\u254b\u249c\u3396\ua71f\u2466"},
- {"common14", L"\u21b8\u2236\u251a\uff11\u2077\u0035\u27bd\u2013"},
- {"common15", L"\u2668\u2551\u221a\u02bc\u2741\u2649\u2192\u00a1"},
- {"common16", L"\u2211\u21ca\u24dc\u2536\u201b\u21c8\u2530\u25fb"},
- {"common17", L"\u231a\u33d8\u2934\u27bb\u2109\u23ec\u20a9\u3000"},
- {"common18", L"\u2069\u205f\u33d3\u2466\u24a1\u24dd\u21ac\u21e3"},
- {"common19", L"\u2737\u219a\u21f1\u2285\u226a\u00b0\u27b2\u2746"},
- {"common20", L"\u264f\u2539\u2202\u264e\u2548\u2530\u2111\u2007"},
- {"common21", L"\u2799\u0035\u25e4\u265b\u24e2\u2044\u222b\u0021"},
- {"common22", L"\u2728\u00a2\u2533\ufe43\u33c9\u27a2\u02f9\u005d"},
- {"common23", L"\ufe68\u256c\u25b6\u276c\u2771\u33c4\u2712\u24b3"},
- {"common24", L"\ufe5d\ufe31\ufe3d\u205e\u2512\u33b8\u272b\ufe4f"},
- {"common25", L"\u24e7\u25fc\u2582\u2743\u2010\u2474\u2262\u251a"},
- {"common26", L"\u2020\u211c\u24b4\u33c7\u2007\uff0f\u267f\u00b4"},
- {"common27", L"\u266c\u3399\u2570\u33a4\u276e\u00a8\u2506\u24dc"},
- {"common28", L"\u2202\ufe43\u2511\u2191\u339a\u33b0\u02d7\u2473"},
- {"common29", L"\u2517\u2297\u2762\u2460\u25bd\u24a9\u21a7\ufe64"},
- {"common30", L"\u2105\u2722\u275d\u249c\u21a2\u2590\u2260\uff5d"},
- {"common31", L"\u33ba\u21c6\u2706\u02cb\ufe64\u02e6\u0374\u2493"},
+ {"common00", u"\u2497\uff04\u277c\u21b6\u2076\u21e4\u2068\u21b3"},
+ {"common01", u"\u2663\u2466\u338e\u226b\u2734\u21be\u3389\u00ab"},
+ {"common02", u"\u2062\u2197\u3392\u2681\u33be\u206d\ufe10\ufe34"},
+ {"common03", u"\u02db\u00b0\u02d3\u2745\u33d1\u21e4\u24e4\u33d6"},
+ {"common04", u"\u21da\u261f\u26a1\u2586\u27af\u2560\u21cd\u25c6"},
+ {"common05", u"\ufe51\uff17\u0027\u21fd\u24de\uff5e\u2606\u251f"},
+ {"common06", u"\u2493\u2466\u21fc\u226f\u202d\u21a9\u0040\u265d"},
+ {"common07", u"\u2103\u255a\u2153\u26be\u27ac\u222e\u2490\u21a4"},
+ {"common08", u"\u270b\u2486\u246b\u263c\u27b6\u21d9\u219d\u25a9"},
+ {"common09", u"\u002d\u2494\u25fd\u2321\u2111\u2511\u00d7\u2535"},
+ {"common10", u"\u2523\u203e\u25b2\ufe18\u2499\u2229\ufd3e\ufe16"},
+ {"common11", u"\u2133\u2716\u273f\u2064\u2248\u005c\u265f\u21e6"},
+ {"common12", u"\u2060\u246a\u231b\u2726\u25bd\ufe40\u002e\u25ca"},
+ {"common13", u"\ufe39\u24a2\ufe18\u254b\u249c\u3396\ua71f\u2466"},
+ {"common14", u"\u21b8\u2236\u251a\uff11\u2077\u0035\u27bd\u2013"},
+ {"common15", u"\u2668\u2551\u221a\u02bc\u2741\u2649\u2192\u00a1"},
+ {"common16", u"\u2211\u21ca\u24dc\u2536\u201b\u21c8\u2530\u25fb"},
+ {"common17", u"\u231a\u33d8\u2934\u27bb\u2109\u23ec\u20a9\u3000"},
+ {"common18", u"\u2069\u205f\u33d3\u2466\u24a1\u24dd\u21ac\u21e3"},
+ {"common19", u"\u2737\u219a\u21f1\u2285\u226a\u00b0\u27b2\u2746"},
+ {"common20", u"\u264f\u2539\u2202\u264e\u2548\u2530\u2111\u2007"},
+ {"common21", u"\u2799\u0035\u25e4\u265b\u24e2\u2044\u222b\u0021"},
+ {"common22", u"\u2728\u00a2\u2533\ufe43\u33c9\u27a2\u02f9\u005d"},
+ {"common23", u"\ufe68\u256c\u25b6\u276c\u2771\u33c4\u2712\u24b3"},
+ {"common24", u"\ufe5d\ufe31\ufe3d\u205e\u2512\u33b8\u272b\ufe4f"},
+ {"common25", u"\u24e7\u25fc\u2582\u2743\u2010\u2474\u2262\u251a"},
+ {"common26", u"\u2020\u211c\u24b4\u33c7\u2007\uff0f\u267f\u00b4"},
+ {"common27", u"\u266c\u3399\u2570\u33a4\u276e\u00a8\u2506\u24dc"},
+ {"common28", u"\u2202\ufe43\u2511\u2191\u339a\u33b0\u02d7\u2473"},
+ {"common29", u"\u2517\u2297\u2762\u2460\u25bd\u24a9\u21a7\ufe64"},
+ {"common30", u"\u2105\u2722\u275d\u249c\u21a2\u2590\u2260\uff5d"},
+ {"common31", u"\u33ba\u21c6\u2706\u02cb\ufe64\u02e6\u0374\u2493"},
#elif defined(OS_APPLE)
- {"common00", L"\u2153\u24e0\u2109\u02f0\u2a8f\u25ed\u02c5\u2716"},
- {"common01", L"\u02f0\u208c\u2203\u2518\u2067\u2270\u21f1\ufe66"},
- {"common02", L"\u2686\u2585\u2b15\u246f\u23e3\u21b4\u2394\ufe31"},
- {"common03", L"\u23c1\u2a97\u201e\u2200\u3389\u25d3\u02c2\u259d"},
+ {"common00", u"\u2153\u24e0\u2109\u02f0\u2a8f\u25ed\u02c5\u2716"},
+ {"common01", u"\u02f0\u208c\u2203\u2518\u2067\u2270\u21f1\ufe66"},
+ {"common02", u"\u2686\u2585\u2b15\u246f\u23e3\u21b4\u2394\ufe31"},
+ {"common03", u"\u23c1\u2a97\u201e\u2200\u3389\u25d3\u02c2\u259d"},
#else
// The following tests are made for the mock fonts (see test_fonts).
- {"common00", L"\u2153\u24e0\u2109\u02f0\u2a8f\u25ed\u02c5\u2716"},
- {"common01", L"\u02f0\u208c\u2203\u2518\u2067\u2270\u21f1\ufe66"},
- {"common02", L"\u2686\u2585\u2b15\u246f\u23e3\u21b4\u2394\ufe31"},
- {"common03", L"\u23c1\u2a97\u201e\u2200\u3389\u25d3\u02c2\u259d"},
- {"common04", L"\u2075\u4dec\u252a\uff15\u4df6\u2668\u27fa\ufe17"},
- {"common05", L"\u260b\u2049\u3036\u2a85\u2b15\u23c7\u230a\u2374"},
- {"common06", L"\u2771\u27fa\u255d\uff0b\u2213\u3396\u2a85\u2276"},
- {"common07", L"\u211e\u2b06\u2255\u2727\u26c3\u33cf\u267d\u2ab2"},
- {"common08", L"\u2373\u20b3\u22b8\u2a0f\u02fd\u2585\u3036\ufe48"},
- {"common09", L"\u256d\u2940\u21d8\u4dde\u23a1\u226b\u3374\u2a99"},
- {"common10", L"\u270f\u24e5\u26c1\u2131\u21f5\u25af\u230f\u27fe"},
- {"common11", L"\u27aa\u23a2\u02ef\u2373\u2257\u2749\u2496\ufe31"},
- {"common12", L"\u230a\u25fb\u2117\u3386\u32cc\u21c5\u24c4\u207e"},
- {"common13", L"\u2467\u2791\u3393\u33bb\u02ca\u25de\ua788\u278f"},
- {"common14", L"\ua719\u25ed\u20a8\u20a1\u4dd8\u2295\u24eb\u02c8"},
- {"common15", L"\u22b6\u2520\u2036\uffee\u21df\u002d\u277a\u2b24"},
- {"common16", L"\u21f8\u211b\u22a0\u25b6\u263e\u2704\u221a\u2758"},
- {"common17", L"\ufe10\u2060\u24ac\u3385\u27a1\u2059\u2689\u2278"},
- {"common18", L"\u269b\u211b\u33a4\ufe36\u239e\u267f\u2423\u24a2"},
- {"common19", L"\u4ded\u262d\u225e\u248b\u21df\u279d\u2518\u21ba"},
- {"common20", L"\u225a\uff16\u21d4\u21c6\u02ba\u2545\u23aa\u005e"},
- {"common21", L"\u20a5\u265e\u3395\u2a6a\u2555\u22a4\u2086\u23aa"},
- {"common22", L"\u203f\u3250\u2240\u24e9\u21cb\u258f\u24b1\u3259"},
- {"common23", L"\u27bd\u263b\uff1f\u2199\u2547\u258d\u201f\u2507"},
- {"common24", L"\u2482\u2548\u02dc\u231f\u24cd\u2198\u220e\u20ad"},
- {"common25", L"\u2ff7\u2540\ufe48\u2197\u276b\u2574\u2062\u3398"},
- {"common26", L"\u2663\u21cd\u263f\u23e5\u22d7\u2518\u21b9\u2628"},
- {"common27", L"\u21fa\ufe66\u2739\u2051\u21f4\u3399\u2599\u25f7"},
- {"common28", L"\u29d3\u25ec\u27a6\u24e0\u2735\u25b4\u2737\u25db"},
- {"common29", L"\u2622\u22e8\u33d2\u21d3\u2502\u2153\u2669\u25f2"},
- {"common30", L"\u2121\u21af\u2729\u203c\u337a\u2464\u2b08\u2e24"},
- {"common31", L"\u33cd\u007b\u02d2\u22cc\u32be\u2ffa\u2787\u02e9"},
+ {"common00", u"\u2153\u24e0\u2109\u02f0\u2a8f\u25ed\u02c5\u2716"},
+ {"common01", u"\u02f0\u208c\u2203\u2518\u2067\u2270\u21f1\ufe66"},
+ {"common02", u"\u2686\u2585\u2b15\u246f\u23e3\u21b4\u2394\ufe31"},
+ {"common03", u"\u23c1\u2a97\u201e\u2200\u3389\u25d3\u02c2\u259d"},
+ {"common04", u"\u2075\u4dec\u252a\uff15\u4df6\u2668\u27fa\ufe17"},
+ {"common05", u"\u260b\u2049\u3036\u2a85\u2b15\u23c7\u230a\u2374"},
+ {"common06", u"\u2771\u27fa\u255d\uff0b\u2213\u3396\u2a85\u2276"},
+ {"common07", u"\u211e\u2b06\u2255\u2727\u26c3\u33cf\u267d\u2ab2"},
+ {"common08", u"\u2373\u20b3\u22b8\u2a0f\u02fd\u2585\u3036\ufe48"},
+ {"common09", u"\u256d\u2940\u21d8\u4dde\u23a1\u226b\u3374\u2a99"},
+ {"common10", u"\u270f\u24e5\u26c1\u2131\u21f5\u25af\u230f\u27fe"},
+ {"common11", u"\u27aa\u23a2\u02ef\u2373\u2257\u2749\u2496\ufe31"},
+ {"common12", u"\u230a\u25fb\u2117\u3386\u32cc\u21c5\u24c4\u207e"},
+ {"common13", u"\u2467\u2791\u3393\u33bb\u02ca\u25de\ua788\u278f"},
+ {"common14", u"\ua719\u25ed\u20a8\u20a1\u4dd8\u2295\u24eb\u02c8"},
+ {"common15", u"\u22b6\u2520\u2036\uffee\u21df\u002d\u277a\u2b24"},
+ {"common16", u"\u21f8\u211b\u22a0\u25b6\u263e\u2704\u221a\u2758"},
+ {"common17", u"\ufe10\u2060\u24ac\u3385\u27a1\u2059\u2689\u2278"},
+ {"common18", u"\u269b\u211b\u33a4\ufe36\u239e\u267f\u2423\u24a2"},
+ {"common19", u"\u4ded\u262d\u225e\u248b\u21df\u279d\u2518\u21ba"},
+ {"common20", u"\u225a\uff16\u21d4\u21c6\u02ba\u2545\u23aa\u005e"},
+ {"common21", u"\u20a5\u265e\u3395\u2a6a\u2555\u22a4\u2086\u23aa"},
+ {"common22", u"\u203f\u3250\u2240\u24e9\u21cb\u258f\u24b1\u3259"},
+ {"common23", u"\u27bd\u263b\uff1f\u2199\u2547\u258d\u201f\u2507"},
+ {"common24", u"\u2482\u2548\u02dc\u231f\u24cd\u2198\u220e\u20ad"},
+ {"common25", u"\u2ff7\u2540\ufe48\u2197\u276b\u2574\u2062\u3398"},
+ {"common26", u"\u2663\u21cd\u263f\u23e5\u22d7\u2518\u21b9\u2628"},
+ {"common27", u"\u21fa\ufe66\u2739\u2051\u21f4\u3399\u2599\u25f7"},
+ {"common28", u"\u29d3\u25ec\u27a6\u24e0\u2735\u25b4\u2737\u25db"},
+ {"common29", u"\u2622\u22e8\u33d2\u21d3\u2502\u2153\u2669\u25f2"},
+ {"common30", u"\u2121\u21af\u2729\u203c\u337a\u2464\u2b08\u2e24"},
+ {"common31", u"\u33cd\u007b\u02d2\u22cc\u32be\u2ffa\u2787\u02e9"},
#endif
};
@@ -7162,12 +7141,12 @@ TEST_F(RenderTextTest, CJKFontWithLocale) {
TEST_F(RenderTextTest, SameFontAccrossIgnorableCodepoints) {
RenderText* render_text = GetRenderText();
- render_text->SetText(UTF8ToUTF16("\u060F"));
+ render_text->SetText(u"\u060F");
const std::vector<FontSpan> spans1 = GetFontSpans();
ASSERT_EQ(1u, spans1.size());
Font font1 = spans1[0].first;
- render_text->SetText(UTF8ToUTF16("\u060F\u200C\u060F"));
+ render_text->SetText(u"\u060F\u200C\u060F");
const std::vector<FontSpan> spans2 = GetFontSpans();
ASSERT_EQ(1u, spans2.size());
Font font2 = spans2[0].first;
@@ -7178,16 +7157,16 @@ TEST_F(RenderTextTest, SameFontAccrossIgnorableCodepoints) {
}
TEST_F(RenderTextTest, ZeroWidthCharacters) {
- static const wchar_t* kEmptyText[] = {
- L"\u200C", // ZERO WIDTH NON-JOINER
- L"\u200D", // ZERO WIDTH JOINER
- L"\u200B", // ZERO WIDTH SPACE
- L"\uFEFF", // ZERO WIDTH NO-BREAK SPACE
+ static const char16_t* kEmptyText[] = {
+ u"\u200C", // ZERO WIDTH NON-JOINER
+ u"\u200D", // ZERO WIDTH JOINER
+ u"\u200B", // ZERO WIDTH SPACE
+ u"\uFEFF", // ZERO WIDTH NO-BREAK SPACE
};
- for (const wchar_t* text : kEmptyText) {
+ for (const auto* text : kEmptyText) {
RenderTextHarfBuzz* render_text = GetRenderText();
- render_text->SetText(WideToUTF16(text));
+ render_text->SetText(text);
const internal::TextRunList* run_list = GetHarfBuzzRunList();
EXPECT_EQ(0, run_list->width());
@@ -7205,10 +7184,8 @@ TEST_F(RenderTextTest, DISABLED_TextDoesntClip) {
// crbug.com/459812. This appears to be a preexisting issue that wasn't
// revealed by the prior unit tests.
// "TEST_______",
- "TEST some stuff", "WWWWWWWWWW", "gAXAXAXAXAXAXA",
- "g\u00C5X\u00C5X\u00C5X\u00C5X\u00C5X\u00C5X\u00C5",
- ("\u0647\u0654\u0647\u0654\u0647\u0654\u0647\u0654\u0645\u0631\u062D"
- "\u0628\u0627")};
+ "TEST some stuff", "WWWWWWWWWW", "gAXAXAXAXAXAXA", "gÅXÅXÅXÅXÅXÅXÅ",
+ "هٔهٔهٔهٔمرحبا"};
const Size kCanvasSize(300, 50);
const int kTestSize = 10;
@@ -7223,7 +7200,7 @@ TEST_F(RenderTextTest, DISABLED_TextDoesntClip) {
for (auto* string : kTestStrings) {
paint_canvas.clear(SK_ColorWHITE);
- render_text->SetText(UTF8ToUTF16(string));
+ render_text->SetText(base::UTF8ToUTF16(string));
render_text->ApplyBaselineStyle(SUPERSCRIPT, Range(1, 2));
render_text->ApplyBaselineStyle(SUPERIOR, Range(3, 4));
render_text->ApplyBaselineStyle(INFERIOR, Range(5, 6));
@@ -7294,7 +7271,7 @@ TEST_F(RenderTextTest, DISABLED_TextDoesClip) {
for (auto* string : kTestStrings) {
paint_canvas.clear(SK_ColorWHITE);
- render_text->SetText(UTF8ToUTF16(string));
+ render_text->SetText(base::UTF8ToUTF16(string));
const Size string_size = render_text->GetStringSize();
int fake_width = string_size.width() / 2;
int fake_height = string_size.height() / 2;
@@ -7336,11 +7313,11 @@ TEST_F(RenderTextTest, ColorChange) {
RenderText* render_text = GetRenderText();
render_text->SetText(u"x");
Draw();
- ExpectTextLog({{1, SK_ColorBLACK}});
+ ExpectTextLog({{1, kPlaceholderColor}});
- render_text->SetColor(SK_ColorRED);
+ render_text->SetColor(SK_ColorGREEN);
Draw();
- ExpectTextLog({{1, SK_ColorRED}});
+ ExpectTextLog({{1, SK_ColorGREEN}});
}
// Ensure style information propagates to the typeface on the text renderer.
@@ -7548,7 +7525,7 @@ TEST_F(RenderTextTest, GetWordLookupDataAtPoint_RTL) {
// TODO(crbug.com/1111044): this shouldn't be necessary once RenderText keeps
// float precision through GetCursorBounds().
SetGlyphWidth(5);
- const std::u16string rtl = UTF8ToUTF16(" \u0634\u0632 \u0634");
+ const std::u16string rtl = u" \u0634\u0632 \u0634";
const int kWordOneStartIndex = 1;
const int kWordTwoStartIndex = 5;
@@ -7565,7 +7542,7 @@ TEST_F(RenderTextTest, GetWordLookupDataAtPoint_RTL) {
// Create expected decorated text instance.
DecoratedText expected_word_1;
- expected_word_1.text = UTF8ToUTF16("\u0634\u0632");
+ expected_word_1.text = u"\u0634\u0632";
// Attributes for characters at logical indices 1 and 2.
expected_word_1.attributes.push_back(CreateRangedAttribute(
font_spans, 0, kWordOneStartIndex, Font::Weight::NORMAL, ITALIC_MASK));
@@ -7577,7 +7554,7 @@ TEST_F(RenderTextTest, GetWordLookupDataAtPoint_RTL) {
SelectionModel(kWordOneStartIndex + 1, CURSOR_FORWARD), false);
DecoratedText expected_word_2;
- expected_word_2.text = UTF8ToUTF16("\u0634");
+ expected_word_2.text = u"\u0634";
// Attributes for character at logical index |kWordTwoStartIndex|.
expected_word_2.attributes.push_back(CreateRangedAttribute(
font_spans, 0, kWordTwoStartIndex, Font::Weight::NORMAL, UNDERLINE_MASK));
@@ -7801,37 +7778,37 @@ TEST_F(RenderTextTest, GetLookupDataAtRange_Multiline) {
// Tests text selection made at end points of individual lines of multiline
// text.
TEST_F(RenderTextTest, LineEndSelections) {
- const char* const ltr = "abc\n\ndef";
- const char* const rtl = "שנב\n\nגקכ";
- const char* const ltr_single = "abc def ghi";
- const char* const rtl_single = "שנב גקכ עין";
+ const char16_t* const ltr = u"abc\n\ndef";
+ const char16_t* const rtl = u"שנב\n\nגקכ";
+ const char16_t* const ltr_single = u"abc def ghi";
+ const char16_t* const rtl_single = u"שנב גקכ עין";
const int left_x = -100;
const int right_x = 200;
struct {
- const char* const text;
+ const char16_t* const text;
const int line_num;
const int x;
- const char* const selected_text;
+ const char16_t* const selected_text;
} cases[] = {
- {ltr, 1, left_x, "abc\n"},
- {ltr, 1, right_x, "abc\n"},
- {ltr, 2, left_x, "abc\n\n"},
+ {ltr, 1, left_x, u"abc\n"},
+ {ltr, 1, right_x, u"abc\n"},
+ {ltr, 2, left_x, u"abc\n\n"},
{ltr, 2, right_x, ltr},
- {rtl, 1, left_x, "שנב\n"},
- {rtl, 1, right_x, "שנב\n"},
+ {rtl, 1, left_x, u"שנב\n"},
+ {rtl, 1, right_x, u"שנב\n"},
{rtl, 2, left_x, rtl},
- {rtl, 2, right_x, "שנב\n\n"},
+ {rtl, 2, right_x, u"שנב\n\n"},
- {ltr_single, 1, left_x, "abc "},
- {ltr_single, 1, right_x, "abc def "},
- {ltr_single, 2, left_x, "abc def "},
+ {ltr_single, 1, left_x, u"abc "},
+ {ltr_single, 1, right_x, u"abc def "},
+ {ltr_single, 2, left_x, u"abc def "},
{ltr_single, 2, right_x, ltr_single},
- {rtl_single, 1, left_x, "שנב גקכ "},
- {rtl_single, 1, right_x, "שנב "},
+ {rtl_single, 1, left_x, u"שנב גקכ "},
+ {rtl_single, 1, right_x, u"שנב "},
{rtl_single, 2, left_x, rtl_single},
- {rtl_single, 2, right_x, "שנב גקכ "},
+ {rtl_single, 2, right_x, u"שנב גקכ "},
};
SetGlyphWidth(5);
@@ -7841,7 +7818,7 @@ TEST_F(RenderTextTest, LineEndSelections) {
for (size_t i = 0; i < base::size(cases); i++) {
SCOPED_TRACE(base::StringPrintf("Testing case %" PRIuS "", i));
- render_text->SetText(UTF8ToUTF16(cases[i].text));
+ render_text->SetText(cases[i].text);
EXPECT_EQ(3u, render_text->GetNumLines());
// Position the cursor at the logical beginning of text.
@@ -7849,8 +7826,7 @@ TEST_F(RenderTextTest, LineEndSelections) {
render_text->MoveCursorToPoint(
Point(cases[i].x, GetCursorYForTesting(cases[i].line_num)), true);
- EXPECT_EQ(UTF8ToUTF16(cases[i].selected_text),
- GetSelectedText(render_text));
+ EXPECT_EQ(cases[i].selected_text, GetSelectedText(render_text));
}
}
@@ -8266,7 +8242,8 @@ TEST_F(RenderTextTest, FontSizeOverride) {
const int test_font_size_override = default_font_size + 5;
render_text->SetText(u"0123456789");
render_text->ApplyFontSizeOverride(test_font_size_override, gfx::Range(3, 7));
- EXPECT_EQ(ToString16Vec({"012", "3456", "789"}), GetRunListStrings());
+ EXPECT_EQ(std::vector<std::u16string>({u"012", u"3456", u"789"}),
+ GetRunListStrings());
const internal::TextRunList* run_list = GetHarfBuzzRunList();
ASSERT_EQ(3U, run_list->size());
@@ -8283,31 +8260,32 @@ TEST_F(RenderTextTest, DrawVisualText_WithSelection) {
RenderText* render_text = GetRenderText();
render_text->SetText(u"TheRedElephantIsEatingMyPumpkin");
// Ensure selected text is drawn differently than unselected text.
- render_text->set_selection_color(SK_ColorRED);
+ render_text->set_selection_color(SK_ColorGREEN);
DrawVisualText({{3, 14}});
- ExpectTextLog({{3, SK_ColorBLACK}, {11, SK_ColorRED}, {17, SK_ColorBLACK}});
+ ExpectTextLog(
+ {{3, kPlaceholderColor}, {11, SK_ColorGREEN}, {17, kPlaceholderColor}});
}
TEST_F(RenderTextTest, DrawVisualText_WithSelectionOnObcuredEmoji) {
RenderText* render_text = GetRenderText();
render_text->SetText(u"\U0001F628\U0001F628\U0001F628");
render_text->SetObscured(true);
- render_text->set_selection_color(SK_ColorRED);
+ render_text->set_selection_color(SK_ColorGREEN);
DrawVisualText({{4, 6}});
- ExpectTextLog({{2, SK_ColorBLACK}, {1, SK_ColorRED}});
+ ExpectTextLog({{2, kPlaceholderColor}, {1, SK_ColorGREEN}});
}
TEST_F(RenderTextTest, DrawSelectAll) {
const std::vector<GlyphCountAndColor> kUnselected = {
{4, SK_ColorBLACK}};
- const std::vector<GlyphCountAndColor> kSelected = {
- {4, SK_ColorRED}};
+ const std::vector<GlyphCountAndColor> kSelected = {{4, SK_ColorGREEN}};
const std::vector<GlyphCountAndColor> kFocused = {
- {1, SK_ColorBLACK}, {2, SK_ColorRED}, {1, SK_ColorBLACK}};
+ {1, SK_ColorBLACK}, {2, SK_ColorGREEN}, {1, SK_ColorBLACK}};
RenderText* render_text = GetRenderText();
render_text->SetText(u"Test");
- render_text->set_selection_color(SK_ColorRED);
+ render_text->SetColor(SK_ColorBLACK);
+ render_text->set_selection_color(SK_ColorGREEN);
render_text->SelectRange(Range(1, 3));
Draw(false);
diff --git a/chromium/ui/gfx/rrect_f.cc b/chromium/ui/gfx/rrect_f.cc
index 8a8d3c37cca..c0332d4234f 100644
--- a/chromium/ui/gfx/rrect_f.cc
+++ b/chromium/ui/gfx/rrect_f.cc
@@ -8,7 +8,6 @@
#include <iostream>
#include <sstream>
-#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "third_party/skia/include/core/SkMatrix.h"
diff --git a/chromium/ui/gfx/shadow_value.cc b/chromium/ui/gfx/shadow_value.cc
index 87e2ecb1b54..d71ecfd78d0 100644
--- a/chromium/ui/gfx/shadow_value.cc
+++ b/chromium/ui/gfx/shadow_value.cc
@@ -8,6 +8,7 @@
#include <algorithm>
+#include "base/check_op.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/stringprintf.h"
#include "ui/gfx/color_palette.h"
@@ -71,8 +72,9 @@ Insets ShadowValue::GetBlurRegion(const ShadowValues& shadows) {
}
// static
-ShadowValues ShadowValue::MakeRefreshShadowValues(int elevation,
- SkColor color) {
+ShadowValues ShadowValue::MakeShadowValues(int elevation,
+ SkColor key_shadow_color,
+ SkColor ambient_shadow_color) {
// Refresh uses hand-tweaked shadows corresponding to a small set of
// elevations. Use the Refresh spec and designer input to add missing shadow
// values.
@@ -84,21 +86,22 @@ ShadowValues ShadowValue::MakeRefreshShadowValues(int elevation,
switch (elevation) {
case 3: {
- ShadowValue key = {Vector2d(0, 1), 12, SkColorSetA(color, 0x66)};
- ShadowValue ambient = {Vector2d(0, 4), 64, SkColorSetA(color, 0x40)};
+ ShadowValue key = {Vector2d(0, 1), 12, key_shadow_color};
+ ShadowValue ambient = {Vector2d(0, 4), 64, ambient_shadow_color};
return {key, ambient};
}
case 16: {
ShadowValue key = {Vector2d(0, 0), kBlurCorrection * 16,
- SkColorSetA(color, 0x1a)};
+ key_shadow_color};
ShadowValue ambient = {Vector2d(0, 12), kBlurCorrection * 16,
- SkColorSetA(color, 0x3d)};
+ ambient_shadow_color};
return {key, ambient};
}
default:
// This surface has not been updated for Refresh. Fall back to the
// deprecated style.
- return MakeMdShadowValues(elevation, color);
+ DCHECK_EQ(key_shadow_color, ambient_shadow_color);
+ return MakeMdShadowValues(elevation, key_shadow_color);
}
}
diff --git a/chromium/ui/gfx/shadow_value.h b/chromium/ui/gfx/shadow_value.h
index 3466de36d07..fdb8175ed38 100644
--- a/chromium/ui/gfx/shadow_value.h
+++ b/chromium/ui/gfx/shadow_value.h
@@ -54,9 +54,16 @@ class GFX_EXPORT ShadowValue {
// a uniform color.
static Insets GetBlurRegion(const ShadowValues& shadows);
- // Makes ShadowValues matching MD or Refresh shadows for the given elevation
- // and color.
- static ShadowValues MakeRefreshShadowValues(int elevation, SkColor color);
+ // Makes ShadowValues for the given elevation and color. Calls to
+ // MakeShadowValues that expect to fallback to MakeMdShadowValues should pass
+ // in the same base color for |key_shadow_color| and |ambient_shadow_color|
+ // until MakeMdShadowValues is refactored to remove SkColorSetA calls and also
+ // take in its own |key_shadow_color| and |ambient_shadow_color|.
+ // TODO(elainechien): crbug.com/1056950.
+ static ShadowValues MakeShadowValues(int elevation,
+ SkColor key_shadow_color,
+ SkColor ambient_shadow_color);
+ // Makes ShadowValues for MD shadows. This style is deprecated.
static ShadowValues MakeMdShadowValues(int elevation,
SkColor color = SK_ColorBLACK);
diff --git a/chromium/ui/gfx/skia_paint_util.h b/chromium/ui/gfx/skia_paint_util.h
index d334afe7aba..7a00067ea61 100644
--- a/chromium/ui/gfx/skia_paint_util.h
+++ b/chromium/ui/gfx/skia_paint_util.h
@@ -55,4 +55,4 @@ GFX_EXPORT sk_sp<SkDrawLooper> CreateShadowDrawLooper(
} // namespace gfx
-#endif // UI_GFX_SKIA_UTIL_H_
+#endif // UI_GFX_SKIA_PAINT_UTIL_H_
diff --git a/chromium/ui/gfx/skia_util.h b/chromium/ui/gfx/skia_util.h
index b73ff46146e..33bab22dc0e 100644
--- a/chromium/ui/gfx/skia_util.h
+++ b/chromium/ui/gfx/skia_util.h
@@ -5,8 +5,6 @@
#ifndef UI_GFX_SKIA_UTIL_H_
#define UI_GFX_SKIA_UTIL_H_
-#include <string>
-#include <vector>
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkRect.h"
diff --git a/chromium/ui/gfx/swap_result.cc b/chromium/ui/gfx/swap_result.cc
index f5c91451939..9d600c7438f 100644
--- a/chromium/ui/gfx/swap_result.cc
+++ b/chromium/ui/gfx/swap_result.cc
@@ -12,10 +12,9 @@ namespace gfx {
SwapCompletionResult::SwapCompletionResult(gfx::SwapResult swap_result)
: swap_result(swap_result) {}
-SwapCompletionResult::SwapCompletionResult(
- gfx::SwapResult swap_result,
- std::unique_ptr<gfx::GpuFence> gpu_fence)
- : swap_result(swap_result), gpu_fence(std::move(gpu_fence)) {}
+SwapCompletionResult::SwapCompletionResult(gfx::SwapResult swap_result,
+ gfx::GpuFenceHandle release_fence)
+ : swap_result(swap_result), release_fence(std::move(release_fence)) {}
SwapCompletionResult::SwapCompletionResult(
gfx::SwapResult swap_result,
diff --git a/chromium/ui/gfx/swap_result.h b/chromium/ui/gfx/swap_result.h
index 65e01be8046..8d6bbc0ae08 100644
--- a/chromium/ui/gfx/swap_result.h
+++ b/chromium/ui/gfx/swap_result.h
@@ -9,11 +9,11 @@
#include "base/time/time.h"
#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/gpu_fence_handle.h"
namespace gfx {
struct CALayerParams;
-class GpuFence;
enum class SwapResult {
SWAP_ACK,
@@ -70,7 +70,7 @@ struct SwapResponse {
struct GFX_EXPORT SwapCompletionResult {
explicit SwapCompletionResult(gfx::SwapResult swap_result);
SwapCompletionResult(gfx::SwapResult swap_result,
- std::unique_ptr<gfx::GpuFence> gpu_fence);
+ gfx::GpuFenceHandle release_fence);
SwapCompletionResult(gfx::SwapResult swap_result,
std::unique_ptr<gfx::CALayerParams> ca_layer_params);
SwapCompletionResult(SwapCompletionResult&& other);
@@ -80,7 +80,7 @@ struct GFX_EXPORT SwapCompletionResult {
SwapCompletionResult& operator=(const SwapCompletionResult other) = delete;
gfx::SwapResult swap_result = SwapResult::SWAP_FAILED;
- std::unique_ptr<GpuFence> gpu_fence;
+ gfx::GpuFenceHandle release_fence;
std::unique_ptr<CALayerParams> ca_layer_params;
};
diff --git a/chromium/ui/gfx/switches.cc b/chromium/ui/gfx/switches.cc
index 0f746ead72a..6733cbef7f7 100644
--- a/chromium/ui/gfx/switches.cc
+++ b/chromium/ui/gfx/switches.cc
@@ -27,3 +27,16 @@ const char kForcePrefersReducedMotion[] = "force-prefers-reduced-motion";
const char kHeadless[] = "headless";
} // namespace switches
+
+namespace features {
+
+const base::Feature kOddHeightMultiPlanarBuffers {
+ "OddHeightMultiPlanarBuffers",
+#if defined(OS_MAC)
+ base::FEATURE_ENABLED_BY_DEFAULT
+#else
+ base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+};
+
+} // namespace features
diff --git a/chromium/ui/gfx/switches.h b/chromium/ui/gfx/switches.h
index f8fc7fe6a54..afb36f3e9ae 100644
--- a/chromium/ui/gfx/switches.h
+++ b/chromium/ui/gfx/switches.h
@@ -5,6 +5,7 @@
#ifndef UI_GFX_SWITCHES_H_
#define UI_GFX_SWITCHES_H_
+#include "base/feature_list.h"
#include "build/build_config.h"
#include "ui/gfx/switches_export.h"
@@ -17,4 +18,8 @@ GFX_SWITCHES_EXPORT extern const char kForcePrefersReducedMotion[];
GFX_SWITCHES_EXPORT extern const char kHeadless[];
} // namespace switches
+namespace features {
+GFX_SWITCHES_EXPORT extern const base::Feature kOddHeightMultiPlanarBuffers;
+} // namespace features
+
#endif // UI_GFX_SWITCHES_H_
diff --git a/chromium/ui/gfx/text_elider.cc b/chromium/ui/gfx/text_elider.cc
index 1ebdfb46b7a..01b0d8dfe31 100644
--- a/chromium/ui/gfx/text_elider.cc
+++ b/chromium/ui/gfx/text_elider.cc
@@ -122,7 +122,7 @@ StringSlicer::StringSlicer(const std::u16string& text,
const std::u16string& ellipsis,
bool elide_in_middle,
bool elide_at_beginning,
- base::Optional<bool> elide_whitespace)
+ absl::optional<bool> elide_whitespace)
: text_(text),
ellipsis_(ellipsis),
elide_in_middle_(elide_in_middle),
diff --git a/chromium/ui/gfx/text_elider.h b/chromium/ui/gfx/text_elider.h
index 845666bdc3e..c3774db6c9b 100644
--- a/chromium/ui/gfx/text_elider.h
+++ b/chromium/ui/gfx/text_elider.h
@@ -13,8 +13,8 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/gfx_export.h"
#include "ui/gfx/text_constants.h"
@@ -36,7 +36,7 @@ class GFX_EXPORT StringSlicer {
// Warning: Retains a reference to |text| and |ellipsis|. They must have a
// longer lifetime than the StringSlicer.
//
- // Note: if |elide_whitespace| is base::nullopt, the default whitespace
+ // Note: if |elide_whitespace| is absl::nullopt, the default whitespace
// elision strategy for the type of elision being done will be chosen.
// Defaults are to trim for beginning and end elision; no trimming for middle
// elision.
@@ -44,7 +44,7 @@ class GFX_EXPORT StringSlicer {
const std::u16string& ellipsis,
bool elide_in_middle,
bool elide_at_beginning,
- base::Optional<bool> elide_whitespace = base::nullopt);
+ absl::optional<bool> elide_whitespace = absl::nullopt);
// Cuts |text_| to be at most |length| UTF-16 code units long. If
// |elide_in_middle_| is true, the middle of the string is removed to leave
diff --git a/chromium/ui/gfx/text_elider_unittest.cc b/chromium/ui/gfx/text_elider_unittest.cc
index 608406246f9..4df71502c9d 100644
--- a/chromium/ui/gfx/text_elider_unittest.cc
+++ b/chromium/ui/gfx/text_elider_unittest.cc
@@ -27,44 +27,26 @@
#include "ui/gfx/font_render_params.h"
#include "ui/gfx/text_utils.h"
-using base::ASCIIToUTF16;
-using base::UTF16ToUTF8;
-using base::UTF16ToWide;
-using base::UTF8ToUTF16;
-
namespace gfx {
namespace {
-struct Testcase {
- const std::string input;
- const std::string output;
-};
-
struct FileTestcase {
const base::FilePath::StringType input;
- const std::string output;
+ const std::u16string output;
// If this value is specified, we will try to cut the path down to the render
// width of this string; if not specified, output will be used.
- const std::string using_width_of = std::string();
+ const std::u16string using_width_of = std::u16string();
};
-struct UTF16Testcase {
+struct Testcase {
const std::u16string input;
const std::u16string output;
};
-struct TestData {
- const std::string a;
- const std::string b;
- const int compare_result;
-};
-
} // namespace
TEST(TextEliderTest, ElideEmail) {
- const std::string kEllipsisStr(kEllipsis);
-
// Test emails and their expected elided forms (from which the available
// widths will be derived).
// For elided forms in which both the username and domain must be elided:
@@ -72,48 +54,43 @@ TEST(TextEliderTest, ElideEmail) {
// dependent. To avoid this, the username is prefixed with the characters
// expected to remain in the domain.
Testcase testcases[] = {
- {"g@g.c", "g@g.c"},
- {"g@g.c", kEllipsisStr},
- {"ga@co.ca", "ga@c" + kEllipsisStr + "a"},
- {"short@small.com", "s" + kEllipsisStr + "@s" + kEllipsisStr},
- {"short@small.com", "s" + kEllipsisStr + "@small.com"},
- {"short@longbutlotsofspace.com", "short@longbutlotsofspace.com"},
- {"short@longbutnotverymuchspace.com",
- "short@long" + kEllipsisStr + ".com"},
- {"la_short@longbutverytightspace.ca",
- "la" + kEllipsisStr + "@l" + kEllipsisStr + "a"},
- {"longusername@gmail.com", "long" + kEllipsisStr + "@gmail.com"},
- {"elidetothemax@justfits.com", "e" + kEllipsisStr + "@justfits.com"},
- {"thatom_somelongemail@thatdoesntfit.com",
- "thatom" + kEllipsisStr + "@tha" + kEllipsisStr + "om"},
- {"namefits@butthedomaindoesnt.com",
- "namefits@butthedo" + kEllipsisStr + "snt.com"},
- {"widthtootight@nospace.com", kEllipsisStr},
- {"nospaceforusername@l", kEllipsisStr},
- {"little@littlespace.com", "l" + kEllipsisStr + "@l" + kEllipsisStr},
- {"l@llllllllllllllllllllllll.com", "l@lllll" + kEllipsisStr + ".com"},
- {"messed\"up@whyanat\"++@notgoogley.com",
- "messed\"up@whyanat\"++@notgoogley.com"},
- {"messed\"up@whyanat\"++@notgoogley.com",
- "messed\"up@why" + kEllipsisStr + "@notgoogley.com"},
- {"noca_messed\"up@whyanat\"++@notgoogley.ca",
- "noca" + kEllipsisStr + "@no" + kEllipsisStr + "ca"},
- {"at\"@@@@@@@@@...@@.@.@.@@@\"@madness.com",
- "at\"@@@@@@@@@...@@.@." + kEllipsisStr + "@madness.com"},
+ {u"g@g.c", u"g@g.c"},
+ {u"g@g.c", u"…"},
+ {u"ga@co.ca", u"ga@c…a"},
+ {u"short@small.com", u"s…@s…"},
+ {u"short@small.com", u"s…@small.com"},
+ {u"short@longbutlotsofspace.com", u"short@longbutlotsofspace.com"},
+ {u"short@longbutnotverymuchspace.com", u"short@long….com"},
+ {u"la_short@longbutverytightspace.ca", u"la…@l…a"},
+ {u"longusername@gmail.com", u"long…@gmail.com"},
+ {u"elidetothemax@justfits.com", u"e…@justfits.com"},
+ {u"thatom_somelongemail@thatdoesntfit.com", u"thatom…@tha…om"},
+ {u"namefits@butthedomaindoesnt.com", u"namefits@butthedo…snt.com"},
+ {u"widthtootight@nospace.com", u"…"},
+ {u"nospaceforusername@l", u"…"},
+ {u"little@littlespace.com", u"l…@l…"},
+ {u"l@llllllllllllllllllllllll.com", u"l@lllll….com"},
+ {u"messed\"up@whyanat\"++@notgoogley.com",
+ u"messed\"up@whyanat\"++@notgoogley.com"},
+ {u"messed\"up@whyanat\"++@notgoogley.com",
+ u"messed\"up@why…@notgoogley.com"},
+ {u"noca_messed\"up@whyanat\"++@notgoogley.ca", u"noca…@no…ca"},
+ {u"at\"@@@@@@@@@...@@.@.@.@@@\"@madness.com",
+ u"at\"@@@@@@@@@...@@.@.…@madness.com"},
// Special case: "m..." takes more than half of the available width; thus
// the domain must elide to "l..." and not "l...l" as it must allow enough
// space for the minimal username elision although its half of the
// available width would normally allow it to elide to "l...l".
- {"mmmmm@llllllllll", "m" + kEllipsisStr + "@l" + kEllipsisStr},
+ {u"mmmmm@llllllllll", u"m…@l…"},
};
const FontList font_list;
for (size_t i = 0; i < base::size(testcases); ++i) {
- const std::u16string expected_output = UTF8ToUTF16(testcases[i].output);
- EXPECT_EQ(expected_output,
- ElideText(UTF8ToUTF16(testcases[i].input), font_list,
- GetStringWidthF(expected_output, font_list),
- ELIDE_EMAIL));
+ const std::u16string expected_output = testcases[i].output;
+ EXPECT_EQ(
+ expected_output,
+ ElideText(testcases[i].input, font_list,
+ GetStringWidthF(expected_output, font_list), ELIDE_EMAIL));
}
}
@@ -121,74 +98,69 @@ TEST(TextEliderTest, ElideEmailMoreSpace) {
const int test_widths_extra_spaces[] = {
10,
1000,
- 100000,
+ 100'000,
};
- const char* test_emails[] = {
- "a@c",
- "test@email.com",
- "short@verysuperdupperlongdomain.com",
- "supermegalongusername@withasuperlonnnggggdomain.gouv.qc.ca",
+ const char16_t* const test_emails[] = {
+ u"a@c",
+ u"test@email.com",
+ u"short@verysuperdupperlongdomain.com",
+ u"supermegalongusername@withasuperlonnnggggdomain.gouv.qc.ca",
};
const FontList font_list;
for (const auto* test_email : test_emails) {
- const std::u16string test_email16 = UTF8ToUTF16(test_email);
- const int mimimum_width = GetStringWidth(test_email16, font_list);
+ const int mimimum_width = GetStringWidth(test_email, font_list);
for (int extra_space : test_widths_extra_spaces) {
// Extra space is available: the email should not be elided.
- EXPECT_EQ(test_email16,
- ElideText(test_email16, font_list, mimimum_width + extra_space,
+ EXPECT_EQ(test_email,
+ ElideText(test_email, font_list, mimimum_width + extra_space,
ELIDE_EMAIL));
}
}
}
TEST(TextEliderTest, TestFilenameEliding) {
- const std::string kEllipsisStr(kEllipsis);
const base::FilePath::StringType kPathSeparator =
base::FilePath::StringType().append(1, base::FilePath::kSeparators[0]);
FileTestcase testcases[] = {
- {FILE_PATH_LITERAL(""), ""},
- {FILE_PATH_LITERAL("."), "."},
- {FILE_PATH_LITERAL("filename.exe"), "filename.exe"},
- {FILE_PATH_LITERAL(".longext"), ".longext"},
- {FILE_PATH_LITERAL("pie"), "pie"},
+ {FILE_PATH_LITERAL(""), u""},
+ {FILE_PATH_LITERAL("."), u"."},
+ {FILE_PATH_LITERAL("filename.exe"), u"filename.exe"},
+ {FILE_PATH_LITERAL(".longext"), u".longext"},
+ {FILE_PATH_LITERAL("pie"), u"pie"},
{FILE_PATH_LITERAL("c:") + kPathSeparator + FILE_PATH_LITERAL("path") +
kPathSeparator + FILE_PATH_LITERAL("filename.pie"),
- "filename.pie"},
+ u"filename.pie"},
{FILE_PATH_LITERAL("c:") + kPathSeparator + FILE_PATH_LITERAL("path") +
kPathSeparator + FILE_PATH_LITERAL("longfilename.pie"),
- "long" + kEllipsisStr + ".pie"},
- {FILE_PATH_LITERAL("http://path.com/filename.pie"), "filename.pie"},
- {FILE_PATH_LITERAL("http://path.com/longfilename.pie"),
- "long" + kEllipsisStr + ".pie"},
- {FILE_PATH_LITERAL("piesmashingtacularpants"), "pie" + kEllipsisStr},
- {FILE_PATH_LITERAL(".piesmashingtacularpants"), ".pie" + kEllipsisStr},
- {FILE_PATH_LITERAL("cheese."), "cheese."},
- {FILE_PATH_LITERAL("file name.longext"),
- "file" + kEllipsisStr + ".longext"},
- {FILE_PATH_LITERAL("fil ename.longext"),
- "fil" + kEllipsisStr + ".longext", "fil " + kEllipsisStr + ".longext"},
- {FILE_PATH_LITERAL("filename.longext"),
- "file" + kEllipsisStr + ".longext"},
+ u"long….pie"},
+ {FILE_PATH_LITERAL("http://path.com/filename.pie"), u"filename.pie"},
+ {FILE_PATH_LITERAL("http://path.com/longfilename.pie"), u"long….pie"},
+ {FILE_PATH_LITERAL("piesmashingtacularpants"), u"pie…"},
+ {FILE_PATH_LITERAL(".piesmashingtacularpants"), u".pie…"},
+ {FILE_PATH_LITERAL("cheese."), u"cheese."},
+ {FILE_PATH_LITERAL("file name.longext"), u"file….longext"},
+ {FILE_PATH_LITERAL("fil ename.longext"), u"fil….longext",
+ u"fil ….longext"},
+ {FILE_PATH_LITERAL("filename.longext"), u"file….longext"},
{FILE_PATH_LITERAL("filename.middleext.longext"),
- "filename.mid" + kEllipsisStr + ".longext"},
+ u"filename.mid….longext"},
{FILE_PATH_LITERAL("filename.superduperextremelylongext"),
- "filename.sup" + kEllipsisStr + "emelylongext"},
+ u"filename.sup…emelylongext"},
{FILE_PATH_LITERAL("filenamereallylongtext.superdeduperextremelylongext"),
- "filenamereall" + kEllipsisStr + "emelylongext"},
+ u"filenamereall…emelylongext"},
{FILE_PATH_LITERAL(
"file.name.really.long.text.superduperextremelylongext"),
- "file.name.re" + kEllipsisStr + "emelylongext"}};
+ u"file.name.re…emelylongext"}};
static const FontList font_list;
for (size_t i = 0; i < base::size(testcases); ++i) {
base::FilePath filepath(testcases[i].input);
- std::u16string expected = UTF8ToUTF16(testcases[i].output);
- std::u16string using_width_of = UTF8ToUTF16(
- testcases[i].using_width_of.empty() ? testcases[i].output
- : testcases[i].using_width_of);
+ std::u16string expected = testcases[i].output;
+ std::u16string using_width_of = testcases[i].using_width_of.empty()
+ ? testcases[i].output
+ : testcases[i].using_width_of;
expected = base::i18n::GetDisplayStringInLTRDirectionality(expected);
EXPECT_EQ(expected,
ElideFilename(filepath, font_list,
@@ -200,76 +172,71 @@ TEST(TextEliderTest, ElideTextTruncate) {
const FontList font_list;
const float kTestWidth = GetStringWidthF(u"Test", font_list);
struct TestData {
- const char* input;
+ const char16_t* input;
float width;
- const char* output;
+ const char16_t* output;
} cases[] = {
- { "", 0, "" },
- { "Test", 0, "" },
- { "", kTestWidth, "" },
- { "Tes", kTestWidth, "Tes" },
- { "Test", kTestWidth, "Test" },
- { "Tests", kTestWidth, "Test" },
+ {u"", 0, u""},
+ {u"Test", 0, u""},
+ {u"", kTestWidth, u""},
+ {u"Tes", kTestWidth, u"Tes"},
+ {u"Test", kTestWidth, u"Test"},
+ {u"Tests", kTestWidth, u"Test"},
};
for (size_t i = 0; i < base::size(cases); ++i) {
- std::u16string result = ElideText(UTF8ToUTF16(cases[i].input), font_list,
- cases[i].width, TRUNCATE);
- EXPECT_EQ(cases[i].output, UTF16ToUTF8(result));
+ std::u16string result =
+ ElideText(cases[i].input, font_list, cases[i].width, TRUNCATE);
+ EXPECT_EQ(cases[i].output, result);
}
}
TEST(TextEliderTest, ElideTextEllipsis) {
const FontList font_list;
const float kTestWidth = GetStringWidthF(u"Test", font_list);
- const char* kEllipsis = "\xE2\x80\xA6";
- const float kEllipsisWidth =
- GetStringWidthF(UTF8ToUTF16(kEllipsis), font_list);
+ const float kEllipsisWidth = GetStringWidthF(u"…", font_list);
struct TestData {
- const char* input;
+ const char16_t* input;
float width;
- const char* output;
+ const char16_t* output;
} cases[] = {
- { "", 0, "" },
- { "Test", 0, "" },
- { "Test", kEllipsisWidth, kEllipsis },
- { "", kTestWidth, "" },
- { "Tes", kTestWidth, "Tes" },
- { "Test", kTestWidth, "Test" },
+ {u"", 0, u""},
+ {u"Test", 0, u""},
+ {u"Test", kEllipsisWidth, u"…"},
+ {u"", kTestWidth, u""},
+ {u"Tes", kTestWidth, u"Tes"},
+ {u"Test", kTestWidth, u"Test"},
};
for (size_t i = 0; i < base::size(cases); ++i) {
- std::u16string result = ElideText(UTF8ToUTF16(cases[i].input), font_list,
- cases[i].width, ELIDE_TAIL);
- EXPECT_EQ(cases[i].output, UTF16ToUTF8(result));
+ std::u16string result =
+ ElideText(cases[i].input, font_list, cases[i].width, ELIDE_TAIL);
+ EXPECT_EQ(cases[i].output, result);
}
}
TEST(TextEliderTest, ElideTextEllipsisFront) {
const FontList font_list;
const float kTestWidth = GetStringWidthF(u"Test", font_list);
- const std::string kEllipsisStr(kEllipsis);
- const float kEllipsisWidth =
- GetStringWidthF(UTF8ToUTF16(kEllipsis), font_list);
- const float kEllipsis23Width =
- GetStringWidthF(UTF8ToUTF16(kEllipsisStr + "23"), font_list);
+ const float kEllipsisWidth = GetStringWidthF(u"…", font_list);
+ const float kEllipsis23Width = GetStringWidthF(u"…23", font_list);
struct TestData {
- const char* input;
+ const char16_t* input;
float width;
const std::u16string output;
} cases[] = {
- {"", 0, std::u16string()},
- {"Test", 0, std::u16string()},
- {"Test", kEllipsisWidth, UTF8ToUTF16(kEllipsisStr)},
- {"", kTestWidth, std::u16string()},
- {"Tes", kTestWidth, u"Tes"},
- {"Test", kTestWidth, u"Test"},
- {"Test123", kEllipsis23Width, UTF8ToUTF16(kEllipsisStr + "23")},
+ {u"", 0, std::u16string()},
+ {u"Test", 0, std::u16string()},
+ {u"Test", kEllipsisWidth, u"…"},
+ {u"", kTestWidth, std::u16string()},
+ {u"Tes", kTestWidth, u"Tes"},
+ {u"Test", kTestWidth, u"Test"},
+ {u"Test123", kEllipsis23Width, u"…23"},
};
for (size_t i = 0; i < base::size(cases); ++i) {
- std::u16string result = ElideText(UTF8ToUTF16(cases[i].input), font_list,
- cases[i].width, ELIDE_HEAD);
+ std::u16string result =
+ ElideText(cases[i].input, font_list, cases[i].width, ELIDE_HEAD);
EXPECT_EQ(cases[i].output, result);
}
}
@@ -298,20 +265,18 @@ TEST(TextEliderTest, ElideTextAtomicSequences) {
base::test::SingleThreadTaskEnvironment::MainThreadType::UI);
#endif
const FontList font_list;
+ std::vector<std::u16string> pairs;
// The below is 'MUSICAL SYMBOL G CLEF' (U+1D11E), which is represented in
// UTF-16 as two code units forming a surrogate pair: 0xD834 0xDD1E.
- const char16_t kSurrogate[] = {0xD834, 0xDD1E, 0};
+ pairs.push_back(u"\U0001d11e");
// The below is a Devanagari two-character combining sequence U+0921 U+093F.
// The sequence forms a single display character and should not be separated.
- const char16_t kCombiningSequence[] = {0x921, 0x93F, 0};
- std::vector<std::u16string> pairs;
- pairs.push_back(kSurrogate);
- pairs.push_back(kCombiningSequence);
+ pairs.push_back(u"\u0921\u093f");
for (const std::u16string& pair : pairs) {
char16_t first_char = pair[0];
char16_t second_char = pair[1];
- std::u16string test_string = pair + UTF8ToUTF16("x") + pair;
+ std::u16string test_string = pair + u"x" + pair;
SCOPED_TRACE(test_string);
const float test_string_width = GetStringWidthF(test_string, font_list);
std::u16string result;
@@ -335,34 +300,33 @@ TEST(TextEliderTest, ElideTextAtomicSequences) {
}
TEST(TextEliderTest, ElideTextLongStrings) {
- const std::u16string kEllipsisStr = UTF8ToUTF16(kEllipsis);
- std::u16string data_scheme(UTF8ToUTF16("data:text/plain,"));
+ std::u16string data_scheme(u"data:text/plain,");
size_t data_scheme_length = data_scheme.length();
std::u16string ten_a(10, 'a');
std::u16string hundred_a(100, 'a');
std::u16string thousand_a(1000, 'a');
- std::u16string ten_thousand_a(10000, 'a');
- std::u16string hundred_thousand_a(100000, 'a');
- std::u16string million_a(1000000, 'a');
+ std::u16string ten_thousand_a(10'000, 'a');
+ std::u16string hundred_thousand_a(100'000, 'a');
+ std::u16string million_a(1'000'000, 'a');
// TODO(gbillock): Improve these tests by adding more string diversity and
// doing string compares instead of length compares. See bug 338836.
size_t number_of_as = 156;
- std::u16string long_string_end(
- data_scheme + std::u16string(number_of_as, 'a') + kEllipsisStr);
- UTF16Testcase testcases_end[] = {
- { data_scheme + ten_a, data_scheme + ten_a },
- { data_scheme + hundred_a, data_scheme + hundred_a },
- { data_scheme + thousand_a, long_string_end },
- { data_scheme + ten_thousand_a, long_string_end },
- { data_scheme + hundred_thousand_a, long_string_end },
- { data_scheme + million_a, long_string_end },
+ std::u16string long_string_end(data_scheme +
+ std::u16string(number_of_as, 'a') + u"…");
+ Testcase testcases_end[] = {
+ {data_scheme + ten_a, data_scheme + ten_a},
+ {data_scheme + hundred_a, data_scheme + hundred_a},
+ {data_scheme + thousand_a, long_string_end},
+ {data_scheme + ten_thousand_a, long_string_end},
+ {data_scheme + hundred_thousand_a, long_string_end},
+ {data_scheme + million_a, long_string_end},
};
const FontList font_list;
- float ellipsis_width = GetStringWidthF(kEllipsisStr, font_list);
+ float ellipsis_width = GetStringWidthF(u"…", font_list);
for (size_t i = 0; i < base::size(testcases_end); ++i) {
// Compare sizes rather than actual contents because if the test fails,
// output is rather long.
@@ -370,20 +334,19 @@ TEST(TextEliderTest, ElideTextLongStrings) {
ElideText(testcases_end[i].input, font_list,
GetStringWidthF(testcases_end[i].output, font_list),
ELIDE_TAIL).size());
- EXPECT_EQ(kEllipsisStr,
- ElideText(testcases_end[i].input, font_list, ellipsis_width,
- ELIDE_TAIL));
+ EXPECT_EQ(u"…", ElideText(testcases_end[i].input, font_list, ellipsis_width,
+ ELIDE_TAIL));
}
size_t number_of_trailing_as = (data_scheme_length + number_of_as) / 2;
std::u16string long_string_middle(
data_scheme + std::u16string(number_of_as - number_of_trailing_as, 'a') +
- kEllipsisStr + std::u16string(number_of_trailing_as, 'a'));
+ u"…" + std::u16string(number_of_trailing_as, 'a'));
#if !defined(OS_IOS)
- long_string_middle += kEllipsisStr;
+ long_string_middle += u"…";
#endif
- UTF16Testcase testcases_middle[] = {
+ Testcase testcases_middle[] = {
{data_scheme + ten_a, data_scheme + ten_a},
{data_scheme + hundred_a, data_scheme + hundred_a},
{data_scheme + thousand_a, long_string_middle},
@@ -400,17 +363,17 @@ TEST(TextEliderTest, ElideTextLongStrings) {
GetStringWidthF(testcases_middle[i].output, font_list),
ELIDE_MIDDLE)
.size());
- EXPECT_EQ(kEllipsisStr, ElideText(testcases_middle[i].input, font_list,
- ellipsis_width, ELIDE_MIDDLE));
+ EXPECT_EQ(u"…", ElideText(testcases_middle[i].input, font_list,
+ ellipsis_width, ELIDE_MIDDLE));
}
- std::u16string long_string_beginning(kEllipsisStr +
+ std::u16string long_string_beginning(u"…" +
std::u16string(number_of_as, 'a'));
#if !defined(OS_IOS)
- long_string_beginning += kEllipsisStr;
+ long_string_beginning += u"…";
#endif
- UTF16Testcase testcases_beginning[] = {
+ Testcase testcases_beginning[] = {
{data_scheme + ten_a, data_scheme + ten_a},
{data_scheme + hundred_a, data_scheme + hundred_a},
{data_scheme + thousand_a, long_string_beginning},
@@ -424,8 +387,8 @@ TEST(TextEliderTest, ElideTextLongStrings) {
testcases_beginning[i].input, font_list,
GetStringWidthF(testcases_beginning[i].output, font_list),
ELIDE_HEAD).size());
- EXPECT_EQ(kEllipsisStr, ElideText(testcases_beginning[i].input, font_list,
- ellipsis_width, ELIDE_HEAD));
+ EXPECT_EQ(u"…", ElideText(testcases_beginning[i].input, font_list,
+ ellipsis_width, ELIDE_HEAD));
}
}
@@ -434,223 +397,180 @@ TEST(TextEliderTest, ElideTextLongStrings) {
TEST(TextEliderTest, StringSlicerBasicTest) {
// Must store strings in variables (StringSlicer retains a reference to them).
- std::u16string text(UTF8ToUTF16("Hello, world!"));
- std::u16string ellipsis(kEllipsisUTF16);
+ std::u16string text(u"Hello, world!");
+ std::u16string ellipsis(u"…");
StringSlicer slicer(text, ellipsis, false, false);
- EXPECT_EQ(UTF8ToUTF16(""), slicer.CutString(0, false));
- EXPECT_EQ(std::u16string(kEllipsisUTF16), slicer.CutString(0, true));
+ EXPECT_EQ(u"", slicer.CutString(0, false));
+ EXPECT_EQ(u"…", slicer.CutString(0, true));
- EXPECT_EQ(UTF8ToUTF16("Hell"), slicer.CutString(4, false));
- EXPECT_EQ(UTF8ToUTF16("Hell") + kEllipsisUTF16, slicer.CutString(4, true));
+ EXPECT_EQ(u"Hell", slicer.CutString(4, false));
+ EXPECT_EQ(u"Hell…", slicer.CutString(4, true));
EXPECT_EQ(text, slicer.CutString(text.length(), false));
- EXPECT_EQ(text + kEllipsisUTF16, slicer.CutString(text.length(), true));
+ EXPECT_EQ(text + u"…", slicer.CutString(text.length(), true));
StringSlicer slicer_begin(text, ellipsis, false, true);
- EXPECT_EQ(UTF8ToUTF16("rld!"), slicer_begin.CutString(4, false));
- EXPECT_EQ(kEllipsisUTF16 + UTF8ToUTF16("rld!"),
- slicer_begin.CutString(4, true));
+ EXPECT_EQ(u"rld!", slicer_begin.CutString(4, false));
+ EXPECT_EQ(u"…rld!", slicer_begin.CutString(4, true));
StringSlicer slicer_mid(text, ellipsis, true, false);
- EXPECT_EQ(UTF8ToUTF16("Held!"), slicer_mid.CutString(5, false));
- EXPECT_EQ(UTF8ToUTF16("Hel") + kEllipsisUTF16 + UTF8ToUTF16("d!"),
- slicer_mid.CutString(5, true));
+ EXPECT_EQ(u"Held!", slicer_mid.CutString(5, false));
+ EXPECT_EQ(u"Hel…d!", slicer_mid.CutString(5, true));
}
TEST(TextEliderTest, StringSlicerWhitespace_UseDefault) {
// Must store strings in variables (StringSlicer retains a reference to them).
- std::u16string text(UTF8ToUTF16("Hello, world!"));
- std::u16string ellipsis(kEllipsisUTF16);
+ std::u16string text(u"Hello, world!");
+ std::u16string ellipsis(u"…");
// Eliding the end of a string should result in whitespace being removed
// before the ellipsis by default.
StringSlicer slicer_end(text, ellipsis, false, false);
- EXPECT_EQ(UTF8ToUTF16("Hello,") + kEllipsisUTF16,
- slicer_end.CutString(6, true));
- EXPECT_EQ(UTF8ToUTF16("Hello,") + kEllipsisUTF16,
- slicer_end.CutString(7, true));
- EXPECT_EQ(UTF8ToUTF16("Hello, w") + kEllipsisUTF16,
- slicer_end.CutString(8, true));
+ EXPECT_EQ(u"Hello,…", slicer_end.CutString(6, true));
+ EXPECT_EQ(u"Hello,…", slicer_end.CutString(7, true));
+ EXPECT_EQ(u"Hello, w…", slicer_end.CutString(8, true));
// Eliding the start of a string should result in whitespace being removed
// after the ellipsis by default.
StringSlicer slicer_begin(text, ellipsis, false, true);
- EXPECT_EQ(kEllipsisUTF16 + UTF8ToUTF16("world!"),
- slicer_begin.CutString(6, true));
- EXPECT_EQ(kEllipsisUTF16 + UTF8ToUTF16("world!"),
- slicer_begin.CutString(7, true));
- EXPECT_EQ(kEllipsisUTF16 + UTF8ToUTF16(", world!"),
- slicer_begin.CutString(8, true));
+ EXPECT_EQ(u"…world!", slicer_begin.CutString(6, true));
+ EXPECT_EQ(u"…world!", slicer_begin.CutString(7, true));
+ EXPECT_EQ(u"…, world!", slicer_begin.CutString(8, true));
// Eliding the middle of a string should *NOT* result in whitespace being
// removed around the ellipsis by default.
StringSlicer slicer_mid(text, ellipsis, true, false);
- text = UTF8ToUTF16("Hey world!");
- EXPECT_EQ(UTF8ToUTF16("Hey") + kEllipsisUTF16 + UTF8ToUTF16("ld!"),
- slicer_mid.CutString(6, true));
- EXPECT_EQ(UTF8ToUTF16("Hey ") + kEllipsisUTF16 + UTF8ToUTF16("ld!"),
- slicer_mid.CutString(7, true));
- EXPECT_EQ(UTF8ToUTF16("Hey ") + kEllipsisUTF16 + UTF8ToUTF16("rld!"),
- slicer_mid.CutString(8, true));
+ text = u"Hey world!";
+ EXPECT_EQ(u"Hey…ld!", slicer_mid.CutString(6, true));
+ EXPECT_EQ(u"Hey …ld!", slicer_mid.CutString(7, true));
+ EXPECT_EQ(u"Hey …rld!", slicer_mid.CutString(8, true));
}
TEST(TextEliderTest, StringSlicerWhitespace_NoTrim) {
// Must store strings in variables (StringSlicer retains a reference to them).
- std::u16string text(UTF8ToUTF16("Hello, world!"));
- std::u16string ellipsis(kEllipsisUTF16);
+ std::u16string text(u"Hello, world!");
+ std::u16string ellipsis(u"…");
// Eliding the end of a string should not result in whitespace being removed
// before the ellipsis in no-trim mode.
StringSlicer slicer_end(text, ellipsis, false, false, false);
- EXPECT_EQ(UTF8ToUTF16("Hello,") + kEllipsisUTF16,
- slicer_end.CutString(6, true));
- EXPECT_EQ(UTF8ToUTF16("Hello, ") + kEllipsisUTF16,
- slicer_end.CutString(7, true));
- EXPECT_EQ(UTF8ToUTF16("Hello, w") + kEllipsisUTF16,
- slicer_end.CutString(8, true));
+ EXPECT_EQ(u"Hello,…", slicer_end.CutString(6, true));
+ EXPECT_EQ(u"Hello, …", slicer_end.CutString(7, true));
+ EXPECT_EQ(u"Hello, w…", slicer_end.CutString(8, true));
// Eliding the start of a string should not result in whitespace being removed
// after the ellipsis in no-trim mode.
StringSlicer slicer_begin(text, ellipsis, false, true, false);
- EXPECT_EQ(kEllipsisUTF16 + UTF8ToUTF16("world!"),
- slicer_begin.CutString(6, true));
- EXPECT_EQ(kEllipsisUTF16 + UTF8ToUTF16(" world!"),
- slicer_begin.CutString(7, true));
- EXPECT_EQ(kEllipsisUTF16 + UTF8ToUTF16(", world!"),
- slicer_begin.CutString(8, true));
+ EXPECT_EQ(u"…world!", slicer_begin.CutString(6, true));
+ EXPECT_EQ(u"… world!", slicer_begin.CutString(7, true));
+ EXPECT_EQ(u"…, world!", slicer_begin.CutString(8, true));
// Eliding the middle of a string should *NOT* result in whitespace being
// removed around the ellipsis in no-trim mode.
StringSlicer slicer_mid(text, ellipsis, true, false, false);
- text = UTF8ToUTF16("Hey world!");
- EXPECT_EQ(UTF8ToUTF16("Hey") + kEllipsisUTF16 + UTF8ToUTF16("ld!"),
- slicer_mid.CutString(6, true));
- EXPECT_EQ(UTF8ToUTF16("Hey ") + kEllipsisUTF16 + UTF8ToUTF16("ld!"),
- slicer_mid.CutString(7, true));
- EXPECT_EQ(UTF8ToUTF16("Hey ") + kEllipsisUTF16 + UTF8ToUTF16("rld!"),
- slicer_mid.CutString(8, true));
+ text = u"Hey world!";
+ EXPECT_EQ(u"Hey…ld!", slicer_mid.CutString(6, true));
+ EXPECT_EQ(u"Hey …ld!", slicer_mid.CutString(7, true));
+ EXPECT_EQ(u"Hey …rld!", slicer_mid.CutString(8, true));
}
TEST(TextEliderTest, StringSlicerWhitespace_Trim) {
// Must store strings in variables (StringSlicer retains a reference to them).
- std::u16string text(UTF8ToUTF16("Hello, world!"));
- std::u16string ellipsis(kEllipsisUTF16);
+ std::u16string text(u"Hello, world!");
+ std::u16string ellipsis(u"…");
// Eliding the end of a string should result in whitespace being removed
// before the ellipsis in trim mode.
StringSlicer slicer_end(text, ellipsis, false, false, true);
- EXPECT_EQ(UTF8ToUTF16("Hello,") + kEllipsisUTF16,
- slicer_end.CutString(6, true));
- EXPECT_EQ(UTF8ToUTF16("Hello,") + kEllipsisUTF16,
- slicer_end.CutString(7, true));
- EXPECT_EQ(UTF8ToUTF16("Hello, w") + kEllipsisUTF16,
- slicer_end.CutString(8, true));
+ EXPECT_EQ(u"Hello,…", slicer_end.CutString(6, true));
+ EXPECT_EQ(u"Hello,…", slicer_end.CutString(7, true));
+ EXPECT_EQ(u"Hello, w…", slicer_end.CutString(8, true));
// Eliding the start of a string should result in whitespace being removed
// after the ellipsis in trim mode.
StringSlicer slicer_begin(text, ellipsis, false, true, true);
- EXPECT_EQ(kEllipsisUTF16 + UTF8ToUTF16("world!"),
- slicer_begin.CutString(6, true));
- EXPECT_EQ(kEllipsisUTF16 + UTF8ToUTF16("world!"),
- slicer_begin.CutString(7, true));
- EXPECT_EQ(kEllipsisUTF16 + UTF8ToUTF16(", world!"),
- slicer_begin.CutString(8, true));
+ EXPECT_EQ(u"…world!", slicer_begin.CutString(6, true));
+ EXPECT_EQ(u"…world!", slicer_begin.CutString(7, true));
+ EXPECT_EQ(u"…, world!", slicer_begin.CutString(8, true));
// Eliding the middle of a string *should* result in whitespace being removed
// around the ellipsis in trim mode.
StringSlicer slicer_mid(text, ellipsis, true, false, true);
- text = UTF8ToUTF16("Hey world!");
- EXPECT_EQ(UTF8ToUTF16("Hey") + kEllipsisUTF16 + UTF8ToUTF16("ld!"),
- slicer_mid.CutString(6, true));
- EXPECT_EQ(UTF8ToUTF16("Hey") + kEllipsisUTF16 + UTF8ToUTF16("ld!"),
- slicer_mid.CutString(7, true));
- EXPECT_EQ(UTF8ToUTF16("Hey") + kEllipsisUTF16 + UTF8ToUTF16("rld!"),
- slicer_mid.CutString(8, true));
+ text = u"Hey world!";
+ EXPECT_EQ(u"Hey…ld!", slicer_mid.CutString(6, true));
+ EXPECT_EQ(u"Hey…ld!", slicer_mid.CutString(7, true));
+ EXPECT_EQ(u"Hey…rld!", slicer_mid.CutString(8, true));
}
TEST(TextEliderTest, StringSlicer_ElideMiddle_MultipleWhitespace) {
// Must store strings in variables (StringSlicer retains a reference to them).
- std::u16string text(UTF8ToUTF16("Hello world!"));
- std::u16string ellipsis(kEllipsisUTF16);
+ std::u16string text(u"Hello world!");
+ std::u16string ellipsis(u"…");
// Eliding the middle of a string should not result in whitespace being
// removed around the ellipsis in default whitespace mode.
StringSlicer slicer_default(text, ellipsis, true, false);
- text = UTF8ToUTF16("Hey U man");
- EXPECT_EQ(UTF8ToUTF16("Hey") + kEllipsisUTF16 + UTF8ToUTF16("man"),
- slicer_default.CutString(6, true));
- EXPECT_EQ(UTF8ToUTF16("Hey ") + kEllipsisUTF16 + UTF8ToUTF16("man"),
- slicer_default.CutString(7, true));
- EXPECT_EQ(UTF8ToUTF16("Hey ") + kEllipsisUTF16 + UTF8ToUTF16(" man"),
- slicer_default.CutString(8, true));
- EXPECT_EQ(UTF8ToUTF16("Hey ") + kEllipsisUTF16 + UTF8ToUTF16(" man"),
- slicer_default.CutString(9, true));
- EXPECT_EQ(UTF8ToUTF16("Hey ") + kEllipsisUTF16 + UTF8ToUTF16(" man"),
- slicer_default.CutString(10, true));
+ text = u"Hey U man";
+ EXPECT_EQ(u"Hey…man", slicer_default.CutString(6, true));
+ EXPECT_EQ(u"Hey …man", slicer_default.CutString(7, true));
+ EXPECT_EQ(u"Hey … man", slicer_default.CutString(8, true));
+ EXPECT_EQ(u"Hey … man", slicer_default.CutString(9, true));
+ EXPECT_EQ(u"Hey … man", slicer_default.CutString(10, true));
// Eliding the middle of a string should not result in whitespace being
// removed around the ellipsis in no-trim mode.
StringSlicer slicer_notrim(text, ellipsis, true, false, false);
- text = UTF8ToUTF16("Hey U man");
- EXPECT_EQ(UTF8ToUTF16("Hey") + kEllipsisUTF16 + UTF8ToUTF16("man"),
- slicer_notrim.CutString(6, true));
- EXPECT_EQ(UTF8ToUTF16("Hey ") + kEllipsisUTF16 + UTF8ToUTF16("man"),
- slicer_notrim.CutString(7, true));
- EXPECT_EQ(UTF8ToUTF16("Hey ") + kEllipsisUTF16 + UTF8ToUTF16(" man"),
- slicer_notrim.CutString(8, true));
- EXPECT_EQ(UTF8ToUTF16("Hey ") + kEllipsisUTF16 + UTF8ToUTF16(" man"),
- slicer_notrim.CutString(9, true));
- EXPECT_EQ(UTF8ToUTF16("Hey ") + kEllipsisUTF16 + UTF8ToUTF16(" man"),
- slicer_notrim.CutString(10, true));
+ text = u"Hey U man";
+ EXPECT_EQ(u"Hey…man", slicer_notrim.CutString(6, true));
+ EXPECT_EQ(u"Hey …man", slicer_notrim.CutString(7, true));
+ EXPECT_EQ(u"Hey … man", slicer_notrim.CutString(8, true));
+ EXPECT_EQ(u"Hey … man", slicer_notrim.CutString(9, true));
+ EXPECT_EQ(u"Hey … man", slicer_notrim.CutString(10, true));
// Eliding the middle of a string *should* result in whitespace being removed
// around the ellipsis in trim mode.
StringSlicer slicer_trim(text, ellipsis, true, false, true);
- text = UTF8ToUTF16("Hey U man");
- EXPECT_EQ(UTF8ToUTF16("Hey") + kEllipsisUTF16 + UTF8ToUTF16("man"),
- slicer_trim.CutString(6, true));
- EXPECT_EQ(UTF8ToUTF16("Hey") + kEllipsisUTF16 + UTF8ToUTF16("man"),
- slicer_trim.CutString(7, true));
- EXPECT_EQ(UTF8ToUTF16("Hey") + kEllipsisUTF16 + UTF8ToUTF16("man"),
- slicer_trim.CutString(8, true));
- EXPECT_EQ(UTF8ToUTF16("Hey") + kEllipsisUTF16 + UTF8ToUTF16("man"),
- slicer_trim.CutString(9, true));
- EXPECT_EQ(UTF8ToUTF16("Hey") + kEllipsisUTF16 + UTF8ToUTF16("man"),
- slicer_trim.CutString(10, true));
+ text = u"Hey U man";
+ EXPECT_EQ(u"Hey…man", slicer_trim.CutString(6, true));
+ EXPECT_EQ(u"Hey…man", slicer_trim.CutString(7, true));
+ EXPECT_EQ(u"Hey…man", slicer_trim.CutString(8, true));
+ EXPECT_EQ(u"Hey…man", slicer_trim.CutString(9, true));
+ EXPECT_EQ(u"Hey…man", slicer_trim.CutString(10, true));
}
TEST(TextEliderTest, StringSlicerSurrogate) {
// The below is 'MUSICAL SYMBOL G CLEF' (U+1D11E), which is represented in
// UTF-16 as two code units forming a surrogate pair: 0xD834 0xDD1E.
- const char16_t kSurrogate[] = {0xD834, 0xDD1E, 0};
- std::u16string text(UTF8ToUTF16("abc") + kSurrogate + UTF8ToUTF16("xyz"));
- std::u16string ellipsis(kEllipsisUTF16);
+ const std::u16string kSurrogate = u"\U0001d11e";
+ ASSERT_EQ(2u, kSurrogate.size());
+ ASSERT_EQ(u'\xD834', kSurrogate[0]);
+ ASSERT_EQ(u'\xDD1E', kSurrogate[1]);
+
+ std::u16string text(u"abc" + kSurrogate + u"xyz");
+ std::u16string ellipsis(u"…");
StringSlicer slicer(text, ellipsis, false, false);
// Cut surrogate on the right. Should round left and exclude the surrogate.
- EXPECT_EQ(std::u16string(kEllipsisUTF16), slicer.CutString(0, true));
- EXPECT_EQ(UTF8ToUTF16("abc") + kEllipsisUTF16, slicer.CutString(4, true));
- EXPECT_EQ(text + kEllipsisUTF16, slicer.CutString(text.length(), true));
+ EXPECT_EQ(u"…", slicer.CutString(0, true));
+ EXPECT_EQ(u"abc…", slicer.CutString(4, true));
+ EXPECT_EQ(text + u"…", slicer.CutString(text.length(), true));
// Cut surrogate on the left. Should round right and exclude the surrogate.
StringSlicer slicer_begin(text, ellipsis, false, true);
- EXPECT_EQ(std::u16string(kEllipsisUTF16) + UTF8ToUTF16("xyz"),
- slicer_begin.CutString(4, true));
+ EXPECT_EQ(u"…xyz", slicer_begin.CutString(4, true));
// Cut surrogate in the middle. Should round right and exclude the surrogate.
- std::u16string short_text(UTF8ToUTF16("abc") + kSurrogate);
+ std::u16string short_text(u"abc" + kSurrogate);
StringSlicer slicer_mid(short_text, ellipsis, true, false);
- EXPECT_EQ(UTF8ToUTF16("a") + kEllipsisUTF16, slicer_mid.CutString(2, true));
+ EXPECT_EQ(u"a…", slicer_mid.CutString(2, true));
// String that starts with a dangling trailing surrogate.
- char16_t dangling_trailing_chars[] = {kSurrogate[1], 0};
- std::u16string dangling_trailing_text(dangling_trailing_chars);
+ std::u16string dangling_trailing_text = kSurrogate.substr(1);
StringSlicer slicer_dangling_trailing(dangling_trailing_text, ellipsis, false,
false);
- EXPECT_EQ(std::u16string(kEllipsisUTF16),
- slicer_dangling_trailing.CutString(0, true));
- EXPECT_EQ(dangling_trailing_text + kEllipsisUTF16,
+ EXPECT_EQ(u"…", slicer_dangling_trailing.CutString(0, true));
+ EXPECT_EQ(dangling_trailing_text + u"…",
slicer_dangling_trailing.CutString(1, true));
}
@@ -660,10 +580,8 @@ TEST(TextEliderTest, StringSlicerCombining) {
// LATIN SMALL LETTER E + COMBINING ACUTE ACCENT + COMBINING CEDILLA
// LATIN SMALL LETTER X + COMBINING ENCLOSING KEYCAP
// DEVANAGARI LETTER DDA + DEVANAGARI VOWEL SIGN I
- const char16_t kText[] = {'e', 0x301, 0x327, ' ', 'x',
- 0x20E3, ' ', 0x921, 0x93F, 0};
- std::u16string text(kText);
- std::u16string ellipsis(kEllipsisUTF16);
+ std::u16string text(u"e\u0301\u0327 x\u20e3 \u0921\u093f");
+ std::u16string ellipsis(u"…");
StringSlicer slicer(text, ellipsis, false, false);
// Attempt to cut the string for all lengths. When a combining sequence is
@@ -671,33 +589,31 @@ TEST(TextEliderTest, StringSlicerCombining) {
// Whitespace is also cut adjacent to the ellipsis.
// First sequence:
- EXPECT_EQ(std::u16string(kEllipsisUTF16), slicer.CutString(0, true));
- EXPECT_EQ(std::u16string(kEllipsisUTF16), slicer.CutString(1, true));
- EXPECT_EQ(std::u16string(kEllipsisUTF16), slicer.CutString(2, true));
- EXPECT_EQ(text.substr(0, 3) + kEllipsisUTF16, slicer.CutString(3, true));
+ EXPECT_EQ(u"…", slicer.CutString(0, true));
+ EXPECT_EQ(u"…", slicer.CutString(1, true));
+ EXPECT_EQ(u"…", slicer.CutString(2, true));
+ EXPECT_EQ(text.substr(0, 3) + u"…", slicer.CutString(3, true));
// Second sequence:
- EXPECT_EQ(text.substr(0, 3) + kEllipsisUTF16, slicer.CutString(4, true));
- EXPECT_EQ(text.substr(0, 3) + kEllipsisUTF16, slicer.CutString(5, true));
- EXPECT_EQ(text.substr(0, 6) + kEllipsisUTF16, slicer.CutString(6, true));
+ EXPECT_EQ(text.substr(0, 3) + u"…", slicer.CutString(4, true));
+ EXPECT_EQ(text.substr(0, 3) + u"…", slicer.CutString(5, true));
+ EXPECT_EQ(text.substr(0, 6) + u"…", slicer.CutString(6, true));
// Third sequence:
- EXPECT_EQ(text.substr(0, 6) + kEllipsisUTF16, slicer.CutString(7, true));
- EXPECT_EQ(text.substr(0, 6) + kEllipsisUTF16, slicer.CutString(8, true));
- EXPECT_EQ(text + kEllipsisUTF16, slicer.CutString(9, true));
+ EXPECT_EQ(text.substr(0, 6) + u"…", slicer.CutString(7, true));
+ EXPECT_EQ(text.substr(0, 6) + u"…", slicer.CutString(8, true));
+ EXPECT_EQ(text + u"…", slicer.CutString(9, true));
// Cut string in the middle, splitting the second sequence in half. Should
// round both left and right, excluding the second sequence.
StringSlicer slicer_mid(text, ellipsis, true, false);
- EXPECT_EQ(text.substr(0, 4) + kEllipsisUTF16 + text.substr(6),
+ EXPECT_EQ(text.substr(0, 4) + u"…" + text.substr(6),
slicer_mid.CutString(9, true));
// String that starts with a dangling combining mark.
char16_t dangling_mark_chars[] = {text[1], 0};
std::u16string dangling_mark_text(dangling_mark_chars);
StringSlicer slicer_dangling_mark(dangling_mark_text, ellipsis, false, false);
- EXPECT_EQ(std::u16string(kEllipsisUTF16),
- slicer_dangling_mark.CutString(0, true));
- EXPECT_EQ(dangling_mark_text + kEllipsisUTF16,
- slicer_dangling_mark.CutString(1, true));
+ EXPECT_EQ(u"…", slicer_dangling_mark.CutString(0, true));
+ EXPECT_EQ(dangling_mark_text + u"…", slicer_dangling_mark.CutString(1, true));
}
TEST(TextEliderTest, StringSlicerCombiningSurrogate) {
@@ -705,49 +621,46 @@ TEST(TextEliderTest, StringSlicerCombiningSurrogate) {
// The following string contains a single combining character sequence:
// MUSICAL SYMBOL G CLEF (U+1D11E) + MUSICAL SYMBOL COMBINING FLAG-1 (U+1D16E)
// Represented as four UTF-16 code units.
- const char16_t kText[] = {0xD834, 0xDD1E, 0xD834, 0xDD6E, 0};
- std::u16string text(kText);
- std::u16string ellipsis(kEllipsisUTF16);
+ std::u16string text(u"\U0001d11e\U0001d16e");
+ std::u16string ellipsis(u"…");
StringSlicer slicer(text, ellipsis, false, false);
// Attempt to cut the string for all lengths. Should always round left and
// exclude the combining sequence.
- EXPECT_EQ(std::u16string(kEllipsisUTF16), slicer.CutString(0, true));
- EXPECT_EQ(std::u16string(kEllipsisUTF16), slicer.CutString(1, true));
- EXPECT_EQ(std::u16string(kEllipsisUTF16), slicer.CutString(2, true));
- EXPECT_EQ(std::u16string(kEllipsisUTF16), slicer.CutString(3, true));
- EXPECT_EQ(text + kEllipsisUTF16, slicer.CutString(4, true));
+ EXPECT_EQ(u"…", slicer.CutString(0, true));
+ EXPECT_EQ(u"…", slicer.CutString(1, true));
+ EXPECT_EQ(u"…", slicer.CutString(2, true));
+ EXPECT_EQ(u"…", slicer.CutString(3, true));
+ EXPECT_EQ(text + u"…", slicer.CutString(4, true));
// Cut string in the middle. Should exclude the sequence.
StringSlicer slicer_mid(text, ellipsis, true, false);
- EXPECT_EQ(std::u16string(kEllipsisUTF16), slicer_mid.CutString(4, true));
+ EXPECT_EQ(u"…", slicer_mid.CutString(4, true));
}
TEST(TextEliderTest, ElideString) {
struct TestData {
- const char* input;
+ const char16_t* input;
size_t max_len;
bool result;
- const char* output;
+ const char16_t* output;
} cases[] = {
- { "Hello", 0, true, "" },
- { "", 0, false, "" },
- { "Hello, my name is Tom", 1, true, "H" },
- { "Hello, my name is Tom", 2, true, "He" },
- { "Hello, my name is Tom", 3, true, "H.m" },
- { "Hello, my name is Tom", 4, true, "H..m" },
- { "Hello, my name is Tom", 5, true, "H...m" },
- { "Hello, my name is Tom", 6, true, "He...m" },
- { "Hello, my name is Tom", 7, true, "He...om" },
- { "Hello, my name is Tom", 10, true, "Hell...Tom" },
- { "Hello, my name is Tom", 100, false, "Hello, my name is Tom" }
- };
+ {u"Hello", 0, true, u""},
+ {u"", 0, false, u""},
+ {u"Hello, my name is Tom", 1, true, u"H"},
+ {u"Hello, my name is Tom", 2, true, u"He"},
+ {u"Hello, my name is Tom", 3, true, u"H.m"},
+ {u"Hello, my name is Tom", 4, true, u"H..m"},
+ {u"Hello, my name is Tom", 5, true, u"H...m"},
+ {u"Hello, my name is Tom", 6, true, u"He...m"},
+ {u"Hello, my name is Tom", 7, true, u"He...om"},
+ {u"Hello, my name is Tom", 10, true, u"Hell...Tom"},
+ {u"Hello, my name is Tom", 100, false, u"Hello, my name is Tom"}};
for (size_t i = 0; i < base::size(cases); ++i) {
std::u16string output;
EXPECT_EQ(cases[i].result,
- ElideString(UTF8ToUTF16(cases[i].input),
- cases[i].max_len, &output));
- EXPECT_EQ(cases[i].output, UTF16ToUTF8(output));
+ ElideString(cases[i].input, cases[i].max_len, &output));
+ EXPECT_EQ(cases[i].output, output);
}
}
@@ -757,50 +670,51 @@ TEST(TextEliderTest, ElideRectangleText) {
const float test_width = GetStringWidthF(u"Test", font_list);
struct TestData {
- const char* input;
+ const char16_t* input;
float available_pixel_width;
int available_pixel_height;
bool truncated_y;
- const char* output;
+ const char16_t* output;
} cases[] = {
- {"", 0, 0, false, nullptr},
- {"", 1, 1, false, nullptr},
- {"Test", test_width, 0, true, nullptr},
- {"Test", test_width, 1, false, "Test"},
- {"Test", test_width, line_height, false, "Test"},
- {"Test Test", test_width, line_height, true, "Test"},
- {"Test Test", test_width, line_height + 1, false, "Test|Test"},
- {"Test Test", test_width, line_height * 2, false, "Test|Test"},
- {"Test Test", test_width, line_height * 3, false, "Test|Test"},
- {"Test Test", test_width * 2, line_height * 2, false, "Test|Test"},
- {"Test Test", test_width * 3, line_height, false, "Test Test"},
- {"Test\nTest", test_width * 3, line_height * 2, false, "Test|Test"},
- {"Te\nst Te", test_width, line_height * 3, false, "Te|st|Te"},
- {"\nTest", test_width, line_height * 2, false, "|Test"},
- {"\nTest", test_width, line_height, true, ""},
- {"\n\nTest", test_width, line_height * 3, false, "||Test"},
- {"\n\nTest", test_width, line_height * 2, true, "|"},
- {"Test\n", 2 * test_width, line_height * 5, false, "Test|"},
- {"Test\n\n", 2 * test_width, line_height * 5, false, "Test||"},
- {"Test\n\n\n", 2 * test_width, line_height * 5, false, "Test|||"},
- {"Test\nTest\n\n", 2 * test_width, line_height * 5, false, "Test|Test||"},
- {"Test\n\nTest\n", 2 * test_width, line_height * 5, false, "Test||Test|"},
- {"Test\n\n\nTest", 2 * test_width, line_height * 5, false, "Test|||Test"},
- {"Te ", test_width, line_height, false, "Te"},
- {"Te Te Test", test_width, 3 * line_height, false, "Te|Te|Test"},
+ {u"", 0, 0, false, nullptr},
+ {u"", 1, 1, false, nullptr},
+ {u"Test", test_width, 0, true, nullptr},
+ {u"Test", test_width, 1, false, u"Test"},
+ {u"Test", test_width, line_height, false, u"Test"},
+ {u"Test Test", test_width, line_height, true, u"Test"},
+ {u"Test Test", test_width, line_height + 1, false, u"Test|Test"},
+ {u"Test Test", test_width, line_height * 2, false, u"Test|Test"},
+ {u"Test Test", test_width, line_height * 3, false, u"Test|Test"},
+ {u"Test Test", test_width * 2, line_height * 2, false, u"Test|Test"},
+ {u"Test Test", test_width * 3, line_height, false, u"Test Test"},
+ {u"Test\nTest", test_width * 3, line_height * 2, false, u"Test|Test"},
+ {u"Te\nst Te", test_width, line_height * 3, false, u"Te|st|Te"},
+ {u"\nTest", test_width, line_height * 2, false, u"|Test"},
+ {u"\nTest", test_width, line_height, true, u""},
+ {u"\n\nTest", test_width, line_height * 3, false, u"||Test"},
+ {u"\n\nTest", test_width, line_height * 2, true, u"|"},
+ {u"Test\n", 2 * test_width, line_height * 5, false, u"Test|"},
+ {u"Test\n\n", 2 * test_width, line_height * 5, false, u"Test||"},
+ {u"Test\n\n\n", 2 * test_width, line_height * 5, false, u"Test|||"},
+ {u"Test\nTest\n\n", 2 * test_width, line_height * 5, false,
+ u"Test|Test||"},
+ {u"Test\n\nTest\n", 2 * test_width, line_height * 5, false,
+ u"Test||Test|"},
+ {u"Test\n\n\nTest", 2 * test_width, line_height * 5, false,
+ u"Test|||Test"},
+ {u"Te ", test_width, line_height, false, u"Te"},
+ {u"Te Te Test", test_width, 3 * line_height, false, u"Te|Te|Test"},
};
for (size_t i = 0; i < base::size(cases); ++i) {
std::vector<std::u16string> lines;
EXPECT_EQ(cases[i].truncated_y ? INSUFFICIENT_SPACE_VERTICAL : 0,
- ElideRectangleText(UTF8ToUTF16(cases[i].input),
- font_list,
+ ElideRectangleText(cases[i].input, font_list,
cases[i].available_pixel_width,
cases[i].available_pixel_height,
- TRUNCATE_LONG_WORDS,
- &lines));
+ TRUNCATE_LONG_WORDS, &lines));
if (cases[i].output) {
- const std::string result = UTF16ToUTF8(base::JoinString(lines, u"|"));
+ const std::u16string result = base::JoinString(lines, u"|");
EXPECT_EQ(cases[i].output, result) << "Case " << i << " failed!";
} else {
EXPECT_TRUE(lines.empty()) << "Case " << i << " failed!";
@@ -817,27 +731,27 @@ TEST(TextEliderTest, ElideRectangleTextFirstWordTruncated) {
std::vector<std::u16string> lines;
- auto result_for_width = [&](const char* input, float width) {
+ auto result_for_width = [&](const char16_t* input, float width) {
lines.clear();
- return ElideRectangleText(ASCIIToUTF16(input), font_list, width,
- line_height * 4, WRAP_LONG_WORDS, &lines);
+ return ElideRectangleText(input, font_list, width, line_height * 4,
+ WRAP_LONG_WORDS, &lines);
};
// Test base case.
- EXPECT_EQ(0, result_for_width("Test", test_width));
+ EXPECT_EQ(0, result_for_width(u"Test", test_width));
EXPECT_EQ(1u, lines.size());
EXPECT_EQ(u"Test", lines[0]);
// First word truncated.
EXPECT_EQ(INSUFFICIENT_SPACE_FOR_FIRST_WORD,
- result_for_width("Test", tes_width));
+ result_for_width(u"Test", tes_width));
EXPECT_EQ(2u, lines.size());
EXPECT_EQ(u"Tes", lines[0]);
EXPECT_EQ(u"t", lines[1]);
// Two words truncated.
EXPECT_EQ(INSUFFICIENT_SPACE_FOR_FIRST_WORD,
- result_for_width("Test\nTest", tes_width));
+ result_for_width(u"Test\nTest", tes_width));
EXPECT_EQ(4u, lines.size());
EXPECT_EQ(u"Tes", lines[0]);
EXPECT_EQ(u"t", lines[1]);
@@ -845,14 +759,14 @@ TEST(TextEliderTest, ElideRectangleTextFirstWordTruncated) {
EXPECT_EQ(u"t", lines[3]);
// Word truncated, but not the first.
- EXPECT_EQ(0, result_for_width("T Test", tes_width));
+ EXPECT_EQ(0, result_for_width(u"T Test", tes_width));
EXPECT_EQ(3u, lines.size());
EXPECT_EQ(u"T", lines[0]);
EXPECT_EQ(u"Tes", lines[1]);
EXPECT_EQ(u"t", lines[2]);
// Leading \n.
- EXPECT_EQ(0, result_for_width("\nTest", tes_width));
+ EXPECT_EQ(0, result_for_width(u"\nTest", tes_width));
EXPECT_EQ(3u, lines.size());
EXPECT_EQ(u"", lines[0]);
EXPECT_EQ(u"Tes", lines[1]);
@@ -868,17 +782,17 @@ TEST(TextEliderTest, ElideRectangleTextPunctuation) {
INSUFFICIENT_SPACE_HORIZONTAL | INSUFFICIENT_SPACE_VERTICAL;
struct TestData {
- const char* input;
+ const char16_t* input;
float available_pixel_width;
int available_pixel_height;
bool wrap_words;
bool truncated_x;
- const char* output;
+ const char16_t* output;
} cases[] = {
- { "Test T.", test_t_width, line_height * 2, false, false, "Test|T." },
- { "Test T ?", test_t_width, line_height * 2, false, false, "Test|T ?" },
- { "Test. Test", test_width, line_height * 3, false, true, "Test|Test" },
- { "Test. Test", test_width, line_height * 3, true, false, "Test|.|Test" },
+ {u"Test T.", test_t_width, line_height * 2, false, false, u"Test|T."},
+ {u"Test T ?", test_t_width, line_height * 2, false, false, u"Test|T ?"},
+ {u"Test. Test", test_width, line_height * 3, false, true, u"Test|Test"},
+ {u"Test. Test", test_width, line_height * 3, true, false, u"Test|.|Test"},
};
for (size_t i = 0; i < base::size(cases); ++i) {
@@ -886,13 +800,12 @@ TEST(TextEliderTest, ElideRectangleTextPunctuation) {
const WordWrapBehavior wrap_behavior =
(cases[i].wrap_words ? WRAP_LONG_WORDS : TRUNCATE_LONG_WORDS);
EXPECT_EQ(cases[i].truncated_x ? INSUFFICIENT_SPACE_HORIZONTAL : 0,
- ElideRectangleText(UTF8ToUTF16(cases[i].input), font_list,
- cases[i].available_pixel_width,
- cases[i].available_pixel_height, wrap_behavior,
- &lines) &
+ ElideRectangleText(
+ cases[i].input, font_list, cases[i].available_pixel_width,
+ cases[i].available_pixel_height, wrap_behavior, &lines) &
kResultMask);
if (cases[i].output) {
- const std::string result = UTF16ToUTF8(base::JoinString(lines, u"|"));
+ const std::u16string result = base::JoinString(lines, u"|");
EXPECT_EQ(cases[i].output, result) << "Case " << i << " failed!";
} else {
EXPECT_TRUE(lines.empty()) << "Case " << i << " failed!";
@@ -903,60 +816,58 @@ TEST(TextEliderTest, ElideRectangleTextPunctuation) {
TEST(TextEliderTest, ElideRectangleTextLongWords) {
const FontList font_list;
const int kAvailableHeight = 1000;
- const std::u16string kElidedTesting =
- UTF8ToUTF16(std::string("Tes") + kEllipsis);
+ const std::u16string kElidedTesting = u"Tes…";
const float elided_width = GetStringWidthF(kElidedTesting, font_list);
const float test_width = GetStringWidthF(u"Test", font_list);
constexpr int kResultMask =
INSUFFICIENT_SPACE_HORIZONTAL | INSUFFICIENT_SPACE_VERTICAL;
struct TestData {
- const char* input;
+ const char16_t* input;
float available_pixel_width;
WordWrapBehavior wrap_behavior;
bool truncated_x;
- const char* output;
+ const char16_t* output;
} cases[] = {
- { "Testing", test_width, IGNORE_LONG_WORDS, false, "Testing" },
- { "X Testing", test_width, IGNORE_LONG_WORDS, false, "X|Testing" },
- { "Test Testing", test_width, IGNORE_LONG_WORDS, false, "Test|Testing" },
- { "Test\nTesting", test_width, IGNORE_LONG_WORDS, false, "Test|Testing" },
- { "Test Tests ", test_width, IGNORE_LONG_WORDS, false, "Test|Tests" },
- { "Test Tests T", test_width, IGNORE_LONG_WORDS, false, "Test|Tests|T" },
-
- { "Testing", elided_width, ELIDE_LONG_WORDS, true, "Tes..." },
- { "X Testing", elided_width, ELIDE_LONG_WORDS, true, "X|Tes..." },
- { "Test Testing", elided_width, ELIDE_LONG_WORDS, true, "Test|Tes..." },
- { "Test\nTesting", elided_width, ELIDE_LONG_WORDS, true, "Test|Tes..." },
-
- { "Testing", test_width, TRUNCATE_LONG_WORDS, true, "Test" },
- { "X Testing", test_width, TRUNCATE_LONG_WORDS, true, "X|Test" },
- { "Test Testing", test_width, TRUNCATE_LONG_WORDS, true, "Test|Test" },
- { "Test\nTesting", test_width, TRUNCATE_LONG_WORDS, true, "Test|Test" },
- { "Test Tests ", test_width, TRUNCATE_LONG_WORDS, true, "Test|Test" },
- { "Test Tests T", test_width, TRUNCATE_LONG_WORDS, true, "Test|Test|T" },
-
- { "Testing", test_width, WRAP_LONG_WORDS, false, "Test|ing" },
- { "X Testing", test_width, WRAP_LONG_WORDS, false, "X|Test|ing" },
- { "Test Testing", test_width, WRAP_LONG_WORDS, false, "Test|Test|ing" },
- { "Test\nTesting", test_width, WRAP_LONG_WORDS, false, "Test|Test|ing" },
- { "Test Tests ", test_width, WRAP_LONG_WORDS, false, "Test|Test|s" },
- { "Test Tests T", test_width, WRAP_LONG_WORDS, false, "Test|Test|s T" },
- { "TestTestTest", test_width, WRAP_LONG_WORDS, false, "Test|Test|Test" },
- { "TestTestTestT", test_width, WRAP_LONG_WORDS, false, "Test|Test|Test|T" },
+ {u"Testing", test_width, IGNORE_LONG_WORDS, false, u"Testing"},
+ {u"X Testing", test_width, IGNORE_LONG_WORDS, false, u"X|Testing"},
+ {u"Test Testing", test_width, IGNORE_LONG_WORDS, false, u"Test|Testing"},
+ {u"Test\nTesting", test_width, IGNORE_LONG_WORDS, false, u"Test|Testing"},
+ {u"Test Tests ", test_width, IGNORE_LONG_WORDS, false, u"Test|Tests"},
+ {u"Test Tests T", test_width, IGNORE_LONG_WORDS, false, u"Test|Tests|T"},
+
+ {u"Testing", elided_width, ELIDE_LONG_WORDS, true, u"Tes…"},
+ {u"X Testing", elided_width, ELIDE_LONG_WORDS, true, u"X|Tes…"},
+ {u"Test Testing", elided_width, ELIDE_LONG_WORDS, true, u"Test|Tes…"},
+ {u"Test\nTesting", elided_width, ELIDE_LONG_WORDS, true, u"Test|Tes…"},
+
+ {u"Testing", test_width, TRUNCATE_LONG_WORDS, true, u"Test"},
+ {u"X Testing", test_width, TRUNCATE_LONG_WORDS, true, u"X|Test"},
+ {u"Test Testing", test_width, TRUNCATE_LONG_WORDS, true, u"Test|Test"},
+ {u"Test\nTesting", test_width, TRUNCATE_LONG_WORDS, true, u"Test|Test"},
+ {u"Test Tests ", test_width, TRUNCATE_LONG_WORDS, true, u"Test|Test"},
+ {u"Test Tests T", test_width, TRUNCATE_LONG_WORDS, true, u"Test|Test|T"},
+
+ {u"Testing", test_width, WRAP_LONG_WORDS, false, u"Test|ing"},
+ {u"X Testing", test_width, WRAP_LONG_WORDS, false, u"X|Test|ing"},
+ {u"Test Testing", test_width, WRAP_LONG_WORDS, false, u"Test|Test|ing"},
+ {u"Test\nTesting", test_width, WRAP_LONG_WORDS, false, u"Test|Test|ing"},
+ {u"Test Tests ", test_width, WRAP_LONG_WORDS, false, u"Test|Test|s"},
+ {u"Test Tests T", test_width, WRAP_LONG_WORDS, false, u"Test|Test|s T"},
+ {u"TestTestTest", test_width, WRAP_LONG_WORDS, false, u"Test|Test|Test"},
+ {u"TestTestTestT", test_width, WRAP_LONG_WORDS, false,
+ u"Test|Test|Test|T"},
};
for (size_t i = 0; i < base::size(cases); ++i) {
std::vector<std::u16string> lines;
- EXPECT_EQ(
- cases[i].truncated_x ? INSUFFICIENT_SPACE_HORIZONTAL : 0,
- ElideRectangleText(UTF8ToUTF16(cases[i].input), font_list,
- cases[i].available_pixel_width, kAvailableHeight,
- cases[i].wrap_behavior, &lines) &
- kResultMask);
- std::string expected_output(cases[i].output);
- base::ReplaceSubstringsAfterOffset(&expected_output, 0, "...", kEllipsis);
- const std::string result = UTF16ToUTF8(base::JoinString(lines, u"|"));
+ EXPECT_EQ(cases[i].truncated_x ? INSUFFICIENT_SPACE_HORIZONTAL : 0,
+ ElideRectangleText(
+ cases[i].input, font_list, cases[i].available_pixel_width,
+ kAvailableHeight, cases[i].wrap_behavior, &lines) &
+ kResultMask);
+ std::u16string expected_output(cases[i].output);
+ const std::u16string result = base::JoinString(lines, u"|");
EXPECT_EQ(expected_output, result) << "Case " << i << " failed!";
}
}
@@ -974,14 +885,10 @@ TEST(TextEliderTest, ElideRectangleTextCheckLineWidth) {
#endif
const float kAvailableWidth = 235;
const int kAvailableHeight = 1000;
- const char text[] = "that Russian place we used to go to after fencing";
+ const char16_t text[] = u"that Russian place we used to go to after fencing";
std::vector<std::u16string> lines;
- EXPECT_EQ(0, ElideRectangleText(UTF8ToUTF16(text),
- font_list,
- kAvailableWidth,
- kAvailableHeight,
- WRAP_LONG_WORDS,
- &lines));
+ EXPECT_EQ(0, ElideRectangleText(text, font_list, kAvailableWidth,
+ kAvailableHeight, WRAP_LONG_WORDS, &lines));
ASSERT_EQ(2u, lines.size());
EXPECT_LE(GetStringWidthF(lines[0], font_list), kAvailableWidth);
EXPECT_LE(GetStringWidthF(lines[1], font_list), kAvailableWidth);
@@ -995,10 +902,10 @@ TEST(TextEliderTest, ElideRectangleTextCheckConcatWidthEqualsSumOfWidths) {
FontList font_list;
font_list = FontList("Noto Sans UI,ui-sans, 12px");
SetFontRenderParamsDeviceScaleFactor(1.25f);
-#define WIDTH(x) GetStringWidthF(UTF8ToUTF16(x), font_list)
- EXPECT_EQ(WIDTH("The administrator for this account has"),
- WIDTH("The ") + WIDTH("administrator ") + WIDTH("for ") +
- WIDTH("this ") + WIDTH("account ") + WIDTH("has"));
+#define WIDTH(x) GetStringWidthF((x), font_list)
+ EXPECT_EQ(WIDTH(u"The administrator for this account has"),
+ WIDTH(u"The ") + WIDTH(u"administrator ") + WIDTH(u"for ") +
+ WIDTH(u"this ") + WIDTH(u"account ") + WIDTH(u"has"));
#undef WIDTH
SetFontRenderParamsDeviceScaleFactor(1.0f);
}
@@ -1006,181 +913,172 @@ TEST(TextEliderTest, ElideRectangleTextCheckConcatWidthEqualsSumOfWidths) {
TEST(TextEliderTest, ElideRectangleString) {
struct TestData {
- const char* input;
+ const char16_t* input;
int max_rows;
int max_cols;
bool result;
- const char* output;
+ const char16_t* output;
} cases[] = {
- { "", 0, 0, false, "" },
- { "", 1, 1, false, "" },
- { "Hi, my name is\nTom", 0, 0, true, "..." },
- { "Hi, my name is\nTom", 1, 0, true, "\n..." },
- { "Hi, my name is\nTom", 0, 1, true, "..." },
- { "Hi, my name is\nTom", 1, 1, true, "H\n..." },
- { "Hi, my name is\nTom", 2, 1, true, "H\ni\n..." },
- { "Hi, my name is\nTom", 3, 1, true, "H\ni\n,\n..." },
- { "Hi, my name is\nTom", 4, 1, true, "H\ni\n,\n \n..." },
- { "Hi, my name is\nTom", 5, 1, true, "H\ni\n,\n \nm\n..." },
- { "Hi, my name is\nTom", 0, 2, true, "..." },
- { "Hi, my name is\nTom", 1, 2, true, "Hi\n..." },
- { "Hi, my name is\nTom", 2, 2, true, "Hi\n, \n..." },
- { "Hi, my name is\nTom", 3, 2, true, "Hi\n, \nmy\n..." },
- { "Hi, my name is\nTom", 4, 2, true, "Hi\n, \nmy\n n\n..." },
- { "Hi, my name is\nTom", 5, 2, true, "Hi\n, \nmy\n n\nam\n..." },
- { "Hi, my name is\nTom", 0, 3, true, "..." },
- { "Hi, my name is\nTom", 1, 3, true, "Hi,\n..." },
- { "Hi, my name is\nTom", 2, 3, true, "Hi,\n my\n..." },
- { "Hi, my name is\nTom", 3, 3, true, "Hi,\n my\n na\n..." },
- { "Hi, my name is\nTom", 4, 3, true, "Hi,\n my\n na\nme \n..." },
- { "Hi, my name is\nTom", 5, 3, true, "Hi,\n my\n na\nme \nis\n..." },
- { "Hi, my name is\nTom", 1, 4, true, "Hi, \n..." },
- { "Hi, my name is\nTom", 2, 4, true, "Hi, \nmy n\n..." },
- { "Hi, my name is\nTom", 3, 4, true, "Hi, \nmy n\name \n..." },
- { "Hi, my name is\nTom", 4, 4, true, "Hi, \nmy n\name \nis\n..." },
- { "Hi, my name is\nTom", 5, 4, false, "Hi, \nmy n\name \nis\nTom" },
- { "Hi, my name is\nTom", 1, 5, true, "Hi, \n..." },
- { "Hi, my name is\nTom", 2, 5, true, "Hi, \nmy na\n..." },
- { "Hi, my name is\nTom", 3, 5, true, "Hi, \nmy na\nme \n..." },
- { "Hi, my name is\nTom", 4, 5, true, "Hi, \nmy na\nme \nis\n..." },
- { "Hi, my name is\nTom", 5, 5, false, "Hi, \nmy na\nme \nis\nTom" },
- { "Hi, my name is\nTom", 1, 6, true, "Hi, \n..." },
- { "Hi, my name is\nTom", 2, 6, true, "Hi, \nmy \n..." },
- { "Hi, my name is\nTom", 3, 6, true, "Hi, \nmy \nname \n..." },
- { "Hi, my name is\nTom", 4, 6, true, "Hi, \nmy \nname \nis\n..." },
- { "Hi, my name is\nTom", 5, 6, false, "Hi, \nmy \nname \nis\nTom" },
- { "Hi, my name is\nTom", 1, 7, true, "Hi, \n..." },
- { "Hi, my name is\nTom", 2, 7, true, "Hi, \nmy \n..." },
- { "Hi, my name is\nTom", 3, 7, true, "Hi, \nmy \nname \n..." },
- { "Hi, my name is\nTom", 4, 7, true, "Hi, \nmy \nname \nis\n..." },
- { "Hi, my name is\nTom", 5, 7, false, "Hi, \nmy \nname \nis\nTom" },
- { "Hi, my name is\nTom", 1, 8, true, "Hi, my \n..." },
- { "Hi, my name is\nTom", 2, 8, true, "Hi, my \nname \n..." },
- { "Hi, my name is\nTom", 3, 8, true, "Hi, my \nname \nis\n..." },
- { "Hi, my name is\nTom", 4, 8, false, "Hi, my \nname \nis\nTom" },
- { "Hi, my name is\nTom", 1, 9, true, "Hi, my \n..." },
- { "Hi, my name is\nTom", 2, 9, true, "Hi, my \nname is\n..." },
- { "Hi, my name is\nTom", 3, 9, false, "Hi, my \nname is\nTom" },
- { "Hi, my name is\nTom", 1, 10, true, "Hi, my \n..." },
- { "Hi, my name is\nTom", 2, 10, true, "Hi, my \nname is\n..." },
- { "Hi, my name is\nTom", 3, 10, false, "Hi, my \nname is\nTom" },
- { "Hi, my name is\nTom", 1, 11, true, "Hi, my \n..." },
- { "Hi, my name is\nTom", 2, 11, true, "Hi, my \nname is\n..." },
- { "Hi, my name is\nTom", 3, 11, false, "Hi, my \nname is\nTom" },
- { "Hi, my name is\nTom", 1, 12, true, "Hi, my \n..." },
- { "Hi, my name is\nTom", 2, 12, true, "Hi, my \nname is\n..." },
- { "Hi, my name is\nTom", 3, 12, false, "Hi, my \nname is\nTom" },
- { "Hi, my name is\nTom", 1, 13, true, "Hi, my name \n..." },
- { "Hi, my name is\nTom", 2, 13, true, "Hi, my name \nis\n..." },
- { "Hi, my name is\nTom", 3, 13, false, "Hi, my name \nis\nTom" },
- { "Hi, my name is\nTom", 1, 20, true, "Hi, my name is\n..." },
- { "Hi, my name is\nTom", 2, 20, false, "Hi, my name is\nTom" },
- { "Hi, my name is Tom", 1, 40, false, "Hi, my name is Tom" },
+ {u"", 0, 0, false, u""},
+ {u"", 1, 1, false, u""},
+ {u"Hi, my name is\nTom", 0, 0, true, u"..."},
+ {u"Hi, my name is\nTom", 1, 0, true, u"\n..."},
+ {u"Hi, my name is\nTom", 0, 1, true, u"..."},
+ {u"Hi, my name is\nTom", 1, 1, true, u"H\n..."},
+ {u"Hi, my name is\nTom", 2, 1, true, u"H\ni\n..."},
+ {u"Hi, my name is\nTom", 3, 1, true, u"H\ni\n,\n..."},
+ {u"Hi, my name is\nTom", 4, 1, true, u"H\ni\n,\n \n..."},
+ {u"Hi, my name is\nTom", 5, 1, true, u"H\ni\n,\n \nm\n..."},
+ {u"Hi, my name is\nTom", 0, 2, true, u"..."},
+ {u"Hi, my name is\nTom", 1, 2, true, u"Hi\n..."},
+ {u"Hi, my name is\nTom", 2, 2, true, u"Hi\n, \n..."},
+ {u"Hi, my name is\nTom", 3, 2, true, u"Hi\n, \nmy\n..."},
+ {u"Hi, my name is\nTom", 4, 2, true, u"Hi\n, \nmy\n n\n..."},
+ {u"Hi, my name is\nTom", 5, 2, true, u"Hi\n, \nmy\n n\nam\n..."},
+ {u"Hi, my name is\nTom", 0, 3, true, u"..."},
+ {u"Hi, my name is\nTom", 1, 3, true, u"Hi,\n..."},
+ {u"Hi, my name is\nTom", 2, 3, true, u"Hi,\n my\n..."},
+ {u"Hi, my name is\nTom", 3, 3, true, u"Hi,\n my\n na\n..."},
+ {u"Hi, my name is\nTom", 4, 3, true, u"Hi,\n my\n na\nme \n..."},
+ {u"Hi, my name is\nTom", 5, 3, true, u"Hi,\n my\n na\nme \nis\n..."},
+ {u"Hi, my name is\nTom", 1, 4, true, u"Hi, \n..."},
+ {u"Hi, my name is\nTom", 2, 4, true, u"Hi, \nmy n\n..."},
+ {u"Hi, my name is\nTom", 3, 4, true, u"Hi, \nmy n\name \n..."},
+ {u"Hi, my name is\nTom", 4, 4, true, u"Hi, \nmy n\name \nis\n..."},
+ {u"Hi, my name is\nTom", 5, 4, false, u"Hi, \nmy n\name \nis\nTom"},
+ {u"Hi, my name is\nTom", 1, 5, true, u"Hi, \n..."},
+ {u"Hi, my name is\nTom", 2, 5, true, u"Hi, \nmy na\n..."},
+ {u"Hi, my name is\nTom", 3, 5, true, u"Hi, \nmy na\nme \n..."},
+ {u"Hi, my name is\nTom", 4, 5, true, u"Hi, \nmy na\nme \nis\n..."},
+ {u"Hi, my name is\nTom", 5, 5, false, u"Hi, \nmy na\nme \nis\nTom"},
+ {u"Hi, my name is\nTom", 1, 6, true, u"Hi, \n..."},
+ {u"Hi, my name is\nTom", 2, 6, true, u"Hi, \nmy \n..."},
+ {u"Hi, my name is\nTom", 3, 6, true, u"Hi, \nmy \nname \n..."},
+ {u"Hi, my name is\nTom", 4, 6, true, u"Hi, \nmy \nname \nis\n..."},
+ {u"Hi, my name is\nTom", 5, 6, false, u"Hi, \nmy \nname \nis\nTom"},
+ {u"Hi, my name is\nTom", 1, 7, true, u"Hi, \n..."},
+ {u"Hi, my name is\nTom", 2, 7, true, u"Hi, \nmy \n..."},
+ {u"Hi, my name is\nTom", 3, 7, true, u"Hi, \nmy \nname \n..."},
+ {u"Hi, my name is\nTom", 4, 7, true, u"Hi, \nmy \nname \nis\n..."},
+ {u"Hi, my name is\nTom", 5, 7, false, u"Hi, \nmy \nname \nis\nTom"},
+ {u"Hi, my name is\nTom", 1, 8, true, u"Hi, my \n..."},
+ {u"Hi, my name is\nTom", 2, 8, true, u"Hi, my \nname \n..."},
+ {u"Hi, my name is\nTom", 3, 8, true, u"Hi, my \nname \nis\n..."},
+ {u"Hi, my name is\nTom", 4, 8, false, u"Hi, my \nname \nis\nTom"},
+ {u"Hi, my name is\nTom", 1, 9, true, u"Hi, my \n..."},
+ {u"Hi, my name is\nTom", 2, 9, true, u"Hi, my \nname is\n..."},
+ {u"Hi, my name is\nTom", 3, 9, false, u"Hi, my \nname is\nTom"},
+ {u"Hi, my name is\nTom", 1, 10, true, u"Hi, my \n..."},
+ {u"Hi, my name is\nTom", 2, 10, true, u"Hi, my \nname is\n..."},
+ {u"Hi, my name is\nTom", 3, 10, false, u"Hi, my \nname is\nTom"},
+ {u"Hi, my name is\nTom", 1, 11, true, u"Hi, my \n..."},
+ {u"Hi, my name is\nTom", 2, 11, true, u"Hi, my \nname is\n..."},
+ {u"Hi, my name is\nTom", 3, 11, false, u"Hi, my \nname is\nTom"},
+ {u"Hi, my name is\nTom", 1, 12, true, u"Hi, my \n..."},
+ {u"Hi, my name is\nTom", 2, 12, true, u"Hi, my \nname is\n..."},
+ {u"Hi, my name is\nTom", 3, 12, false, u"Hi, my \nname is\nTom"},
+ {u"Hi, my name is\nTom", 1, 13, true, u"Hi, my name \n..."},
+ {u"Hi, my name is\nTom", 2, 13, true, u"Hi, my name \nis\n..."},
+ {u"Hi, my name is\nTom", 3, 13, false, u"Hi, my name \nis\nTom"},
+ {u"Hi, my name is\nTom", 1, 20, true, u"Hi, my name is\n..."},
+ {u"Hi, my name is\nTom", 2, 20, false, u"Hi, my name is\nTom"},
+ {u"Hi, my name is Tom", 1, 40, false, u"Hi, my name is Tom"},
};
std::u16string output;
for (size_t i = 0; i < base::size(cases); ++i) {
EXPECT_EQ(cases[i].result,
- ElideRectangleString(UTF8ToUTF16(cases[i].input),
- cases[i].max_rows, cases[i].max_cols,
- true, &output));
- EXPECT_EQ(cases[i].output, UTF16ToUTF8(output));
+ ElideRectangleString(cases[i].input, cases[i].max_rows,
+ cases[i].max_cols, true, &output));
+ EXPECT_EQ(cases[i].output, output);
}
}
TEST(TextEliderTest, ElideRectangleStringNotStrict) {
struct TestData {
- const char* input;
+ const char16_t* input;
int max_rows;
int max_cols;
bool result;
- const char* output;
+ const char16_t* output;
} cases[] = {
- { "", 0, 0, false, "" },
- { "", 1, 1, false, "" },
- { "Hi, my name_is\nDick", 0, 0, true, "..." },
- { "Hi, my name_is\nDick", 1, 0, true, "\n..." },
- { "Hi, my name_is\nDick", 0, 1, true, "..." },
- { "Hi, my name_is\nDick", 1, 1, true, "H\n..." },
- { "Hi, my name_is\nDick", 2, 1, true, "H\ni\n..." },
- { "Hi, my name_is\nDick", 3, 1, true, "H\ni\n,\n..." },
- { "Hi, my name_is\nDick", 4, 1, true, "H\ni\n,\n \n..." },
- { "Hi, my name_is\nDick", 5, 1, true, "H\ni\n,\n \nm\n..." },
- { "Hi, my name_is\nDick", 0, 2, true, "..." },
- { "Hi, my name_is\nDick", 1, 2, true, "Hi\n..." },
- { "Hi, my name_is\nDick", 2, 2, true, "Hi\n, \n..." },
- { "Hi, my name_is\nDick", 3, 2, true, "Hi\n, \nmy\n..." },
- { "Hi, my name_is\nDick", 4, 2, true, "Hi\n, \nmy\n n\n..." },
- { "Hi, my name_is\nDick", 5, 2, true, "Hi\n, \nmy\n n\nam\n..." },
- { "Hi, my name_is\nDick", 0, 3, true, "..." },
- { "Hi, my name_is\nDick", 1, 3, true, "Hi,\n..." },
- { "Hi, my name_is\nDick", 2, 3, true, "Hi,\n my\n..." },
- { "Hi, my name_is\nDick", 3, 3, true, "Hi,\n my\n na\n..." },
- { "Hi, my name_is\nDick", 4, 3, true, "Hi,\n my\n na\nme_\n..." },
- { "Hi, my name_is\nDick", 5, 3, true, "Hi,\n my\n na\nme_\nis\n..." },
- { "Hi, my name_is\nDick", 1, 4, true, "Hi, ..." },
- { "Hi, my name_is\nDick", 2, 4, true, "Hi, my n\n..." },
- { "Hi, my name_is\nDick", 3, 4, true, "Hi, my n\name_\n..." },
- { "Hi, my name_is\nDick", 4, 4, true, "Hi, my n\name_\nis\n..." },
- { "Hi, my name_is\nDick", 5, 4, false, "Hi, my n\name_\nis\nDick" },
- { "Hi, my name_is\nDick", 1, 5, true, "Hi, ..." },
- { "Hi, my name_is\nDick", 2, 5, true, "Hi, my na\n..." },
- { "Hi, my name_is\nDick", 3, 5, true, "Hi, my na\nme_is\n..." },
- { "Hi, my name_is\nDick", 4, 5, true, "Hi, my na\nme_is\n\n..." },
- { "Hi, my name_is\nDick", 5, 5, false, "Hi, my na\nme_is\n\nDick" },
- { "Hi, my name_is\nDick", 1, 6, true, "Hi, ..." },
- { "Hi, my name_is\nDick", 2, 6, true, "Hi, my nam\n..." },
- { "Hi, my name_is\nDick", 3, 6, true, "Hi, my nam\ne_is\n..." },
- { "Hi, my name_is\nDick", 4, 6, false, "Hi, my nam\ne_is\nDick" },
- { "Hi, my name_is\nDick", 5, 6, false, "Hi, my nam\ne_is\nDick" },
- { "Hi, my name_is\nDick", 1, 7, true, "Hi, ..." },
- { "Hi, my name_is\nDick", 2, 7, true, "Hi, my name\n..." },
- { "Hi, my name_is\nDick", 3, 7, true, "Hi, my name\n_is\n..." },
- { "Hi, my name_is\nDick", 4, 7, false, "Hi, my name\n_is\nDick" },
- { "Hi, my name_is\nDick", 5, 7, false, "Hi, my name\n_is\nDick" },
- { "Hi, my name_is\nDick", 1, 8, true, "Hi, my n\n..." },
- { "Hi, my name_is\nDick", 2, 8, true, "Hi, my n\name_is\n..." },
- { "Hi, my name_is\nDick", 3, 8, false, "Hi, my n\name_is\nDick" },
- { "Hi, my name_is\nDick", 1, 9, true, "Hi, my ..." },
- { "Hi, my name_is\nDick", 2, 9, true, "Hi, my name_is\n..." },
- { "Hi, my name_is\nDick", 3, 9, false, "Hi, my name_is\nDick" },
- { "Hi, my name_is\nDick", 1, 10, true, "Hi, my ..." },
- { "Hi, my name_is\nDick", 2, 10, true, "Hi, my name_is\n..." },
- { "Hi, my name_is\nDick", 3, 10, false, "Hi, my name_is\nDick" },
- { "Hi, my name_is\nDick", 1, 11, true, "Hi, my ..." },
- { "Hi, my name_is\nDick", 2, 11, true, "Hi, my name_is\n..." },
- { "Hi, my name_is\nDick", 3, 11, false, "Hi, my name_is\nDick" },
- { "Hi, my name_is\nDick", 1, 12, true, "Hi, my ..." },
- { "Hi, my name_is\nDick", 2, 12, true, "Hi, my name_is\n..." },
- { "Hi, my name_is\nDick", 3, 12, false, "Hi, my name_is\nDick" },
- { "Hi, my name_is\nDick", 1, 13, true, "Hi, my ..." },
- { "Hi, my name_is\nDick", 2, 13, true, "Hi, my name_is\n..." },
- { "Hi, my name_is\nDick", 3, 13, false, "Hi, my name_is\nDick" },
- { "Hi, my name_is\nDick", 1, 20, true, "Hi, my name_is\n..." },
- { "Hi, my name_is\nDick", 2, 20, false, "Hi, my name_is\nDick" },
- { "Hi, my name_is Dick", 1, 40, false, "Hi, my name_is Dick" },
+ {u"", 0, 0, false, u""},
+ {u"", 1, 1, false, u""},
+ {u"Hi, my name_is\nDick", 0, 0, true, u"..."},
+ {u"Hi, my name_is\nDick", 1, 0, true, u"\n..."},
+ {u"Hi, my name_is\nDick", 0, 1, true, u"..."},
+ {u"Hi, my name_is\nDick", 1, 1, true, u"H\n..."},
+ {u"Hi, my name_is\nDick", 2, 1, true, u"H\ni\n..."},
+ {u"Hi, my name_is\nDick", 3, 1, true, u"H\ni\n,\n..."},
+ {u"Hi, my name_is\nDick", 4, 1, true, u"H\ni\n,\n \n..."},
+ {u"Hi, my name_is\nDick", 5, 1, true, u"H\ni\n,\n \nm\n..."},
+ {u"Hi, my name_is\nDick", 0, 2, true, u"..."},
+ {u"Hi, my name_is\nDick", 1, 2, true, u"Hi\n..."},
+ {u"Hi, my name_is\nDick", 2, 2, true, u"Hi\n, \n..."},
+ {u"Hi, my name_is\nDick", 3, 2, true, u"Hi\n, \nmy\n..."},
+ {u"Hi, my name_is\nDick", 4, 2, true, u"Hi\n, \nmy\n n\n..."},
+ {u"Hi, my name_is\nDick", 5, 2, true, u"Hi\n, \nmy\n n\nam\n..."},
+ {u"Hi, my name_is\nDick", 0, 3, true, u"..."},
+ {u"Hi, my name_is\nDick", 1, 3, true, u"Hi,\n..."},
+ {u"Hi, my name_is\nDick", 2, 3, true, u"Hi,\n my\n..."},
+ {u"Hi, my name_is\nDick", 3, 3, true, u"Hi,\n my\n na\n..."},
+ {u"Hi, my name_is\nDick", 4, 3, true, u"Hi,\n my\n na\nme_\n..."},
+ {u"Hi, my name_is\nDick", 5, 3, true, u"Hi,\n my\n na\nme_\nis\n..."},
+ {u"Hi, my name_is\nDick", 1, 4, true, u"Hi, ..."},
+ {u"Hi, my name_is\nDick", 2, 4, true, u"Hi, my n\n..."},
+ {u"Hi, my name_is\nDick", 3, 4, true, u"Hi, my n\name_\n..."},
+ {u"Hi, my name_is\nDick", 4, 4, true, u"Hi, my n\name_\nis\n..."},
+ {u"Hi, my name_is\nDick", 5, 4, false, u"Hi, my n\name_\nis\nDick"},
+ {u"Hi, my name_is\nDick", 1, 5, true, u"Hi, ..."},
+ {u"Hi, my name_is\nDick", 2, 5, true, u"Hi, my na\n..."},
+ {u"Hi, my name_is\nDick", 3, 5, true, u"Hi, my na\nme_is\n..."},
+ {u"Hi, my name_is\nDick", 4, 5, true, u"Hi, my na\nme_is\n\n..."},
+ {u"Hi, my name_is\nDick", 5, 5, false, u"Hi, my na\nme_is\n\nDick"},
+ {u"Hi, my name_is\nDick", 1, 6, true, u"Hi, ..."},
+ {u"Hi, my name_is\nDick", 2, 6, true, u"Hi, my nam\n..."},
+ {u"Hi, my name_is\nDick", 3, 6, true, u"Hi, my nam\ne_is\n..."},
+ {u"Hi, my name_is\nDick", 4, 6, false, u"Hi, my nam\ne_is\nDick"},
+ {u"Hi, my name_is\nDick", 5, 6, false, u"Hi, my nam\ne_is\nDick"},
+ {u"Hi, my name_is\nDick", 1, 7, true, u"Hi, ..."},
+ {u"Hi, my name_is\nDick", 2, 7, true, u"Hi, my name\n..."},
+ {u"Hi, my name_is\nDick", 3, 7, true, u"Hi, my name\n_is\n..."},
+ {u"Hi, my name_is\nDick", 4, 7, false, u"Hi, my name\n_is\nDick"},
+ {u"Hi, my name_is\nDick", 5, 7, false, u"Hi, my name\n_is\nDick"},
+ {u"Hi, my name_is\nDick", 1, 8, true, u"Hi, my n\n..."},
+ {u"Hi, my name_is\nDick", 2, 8, true, u"Hi, my n\name_is\n..."},
+ {u"Hi, my name_is\nDick", 3, 8, false, u"Hi, my n\name_is\nDick"},
+ {u"Hi, my name_is\nDick", 1, 9, true, u"Hi, my ..."},
+ {u"Hi, my name_is\nDick", 2, 9, true, u"Hi, my name_is\n..."},
+ {u"Hi, my name_is\nDick", 3, 9, false, u"Hi, my name_is\nDick"},
+ {u"Hi, my name_is\nDick", 1, 10, true, u"Hi, my ..."},
+ {u"Hi, my name_is\nDick", 2, 10, true, u"Hi, my name_is\n..."},
+ {u"Hi, my name_is\nDick", 3, 10, false, u"Hi, my name_is\nDick"},
+ {u"Hi, my name_is\nDick", 1, 11, true, u"Hi, my ..."},
+ {u"Hi, my name_is\nDick", 2, 11, true, u"Hi, my name_is\n..."},
+ {u"Hi, my name_is\nDick", 3, 11, false, u"Hi, my name_is\nDick"},
+ {u"Hi, my name_is\nDick", 1, 12, true, u"Hi, my ..."},
+ {u"Hi, my name_is\nDick", 2, 12, true, u"Hi, my name_is\n..."},
+ {u"Hi, my name_is\nDick", 3, 12, false, u"Hi, my name_is\nDick"},
+ {u"Hi, my name_is\nDick", 1, 13, true, u"Hi, my ..."},
+ {u"Hi, my name_is\nDick", 2, 13, true, u"Hi, my name_is\n..."},
+ {u"Hi, my name_is\nDick", 3, 13, false, u"Hi, my name_is\nDick"},
+ {u"Hi, my name_is\nDick", 1, 20, true, u"Hi, my name_is\n..."},
+ {u"Hi, my name_is\nDick", 2, 20, false, u"Hi, my name_is\nDick"},
+ {u"Hi, my name_is Dick", 1, 40, false, u"Hi, my name_is Dick"},
};
std::u16string output;
for (size_t i = 0; i < base::size(cases); ++i) {
EXPECT_EQ(cases[i].result,
- ElideRectangleString(UTF8ToUTF16(cases[i].input),
- cases[i].max_rows, cases[i].max_cols,
- false, &output));
- EXPECT_EQ(cases[i].output, UTF16ToUTF8(output));
+ ElideRectangleString(cases[i].input, cases[i].max_rows,
+ cases[i].max_cols, false, &output));
+ EXPECT_EQ(cases[i].output, output);
}
}
TEST(TextEliderTest, ElideRectangleWide16) {
// Two greek words separated by space.
- const std::u16string str(
- u"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9"
- u"\x03bf\x03c2\x0020\x0399\x03c3\x03c4\x03cc\x03c2");
- const std::u16string out1(
- u"\x03a0\x03b1\x03b3\x03ba\n"
- u"\x03cc\x03c3\x03bc\x03b9\n"
- u"...");
- const std::u16string out2(
- u"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9\x03bf\x03c2\x0020\n"
- u"\x0399\x03c3\x03c4\x03cc\x03c2");
+ const std::u16string str(u"Παγκόσμιος Ιστός");
+ const std::u16string out1(u"Παγκ\nόσμι\n...");
+ const std::u16string out2(u"Παγκόσμιος \nΙστός");
std::u16string output;
EXPECT_TRUE(ElideRectangleString(str, 2, 4, true, &output));
EXPECT_EQ(out1, output);
@@ -1189,13 +1087,8 @@ TEST(TextEliderTest, ElideRectangleWide16) {
}
TEST(TextEliderTest, ElideRectangleWide32) {
- // Four U+1D49C MATHEMATICAL SCRIPT CAPITAL A followed by space "aaaaa".
- const std::u16string str(UTF8ToUTF16(
- "\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C"
- " aaaaa"));
- const std::u16string out(
- UTF8ToUTF16("\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\n"
- "\xF0\x9D\x92\x9C \naaa\n..."));
+ const std::u16string str(u"𝒜𝒜𝒜𝒜 aaaaa");
+ const std::u16string out(u"𝒜𝒜𝒜\n𝒜 \naaa\n...");
std::u16string output;
EXPECT_TRUE(ElideRectangleString(str, 3, 3, true, &output));
EXPECT_EQ(out, output);
@@ -1209,36 +1102,31 @@ TEST(TextEliderTest, TruncateString) {
EXPECT_EQ(std::u16string(), TruncateString(str, 0, CHARACTER_BREAK));
// Test breaking at character 1.
- EXPECT_EQ(L"\x2026", UTF16ToWide(TruncateString(str, 1, WORD_BREAK)));
- EXPECT_EQ(L"\x2026", UTF16ToWide(TruncateString(str, 1, CHARACTER_BREAK)));
+ EXPECT_EQ(u"…", TruncateString(str, 1, WORD_BREAK));
+ EXPECT_EQ(u"…", TruncateString(str, 1, CHARACTER_BREAK));
// Test breaking in the middle of the first word.
- EXPECT_EQ(L"f\x2026", UTF16ToWide(TruncateString(str, 2, WORD_BREAK)));
- EXPECT_EQ(L"f\x2026", UTF16ToWide(TruncateString(str, 2, CHARACTER_BREAK)));
+ EXPECT_EQ(u"f…", TruncateString(str, 2, WORD_BREAK));
+ EXPECT_EQ(u"f…", TruncateString(str, 2, CHARACTER_BREAK));
// Test breaking in between words.
- EXPECT_EQ(L"fooooey\x2026", UTF16ToWide(TruncateString(str, 9, WORD_BREAK)));
- EXPECT_EQ(L"fooooey\x2026",
- UTF16ToWide(TruncateString(str, 9, CHARACTER_BREAK)));
+ EXPECT_EQ(u"fooooey…", TruncateString(str, 9, WORD_BREAK));
+ EXPECT_EQ(u"fooooey…", TruncateString(str, 9, CHARACTER_BREAK));
// Test breaking at the start of a later word.
- EXPECT_EQ(L"fooooey\x2026", UTF16ToWide(TruncateString(str, 11, WORD_BREAK)));
- EXPECT_EQ(L"fooooey\x2026",
- UTF16ToWide(TruncateString(str, 11, CHARACTER_BREAK)));
+ EXPECT_EQ(u"fooooey…", TruncateString(str, 11, WORD_BREAK));
+ EXPECT_EQ(u"fooooey…", TruncateString(str, 11, CHARACTER_BREAK));
// Test breaking in the middle of a word.
- EXPECT_EQ(L"fooooey\x2026", UTF16ToWide(TruncateString(str, 12, WORD_BREAK)));
- EXPECT_EQ(L"fooooey\x2026",
- UTF16ToWide(TruncateString(str, 12, CHARACTER_BREAK)));
- EXPECT_EQ(L"fooooey\x2026", UTF16ToWide(TruncateString(str, 14, WORD_BREAK)));
- EXPECT_EQ(L"fooooey bx\x2026",
- UTF16ToWide(TruncateString(str, 14, CHARACTER_BREAK)));
+ EXPECT_EQ(u"fooooey…", TruncateString(str, 12, WORD_BREAK));
+ EXPECT_EQ(u"fooooey…", TruncateString(str, 12, CHARACTER_BREAK));
+ EXPECT_EQ(u"fooooey…", TruncateString(str, 14, WORD_BREAK));
+ EXPECT_EQ(u"fooooey bx…", TruncateString(str, 14, CHARACTER_BREAK));
// Test breaking in whitespace at the end of the string.
- EXPECT_EQ(L"fooooey bxxxar baz\x2026",
- UTF16ToWide(TruncateString(str, 22, WORD_BREAK)));
- EXPECT_EQ(L"fooooey bxxxar baz\x2026",
- UTF16ToWide(TruncateString(str, 22, CHARACTER_BREAK)));
+ EXPECT_EQ(u"fooooey bxxxar baz…", TruncateString(str, 22, WORD_BREAK));
+ EXPECT_EQ(u"fooooey bxxxar baz…",
+ TruncateString(str, 22, CHARACTER_BREAK));
// Test breaking at the end of the string.
EXPECT_EQ(str, TruncateString(str, str.length(), WORD_BREAK));
@@ -1253,19 +1141,18 @@ TEST(TextEliderTest, TruncateString) {
std::u16string str2 = u" foo";
// Test breaking in leading whitespace.
- EXPECT_EQ(L"\x2026", UTF16ToWide(TruncateString(str2, 2, WORD_BREAK)));
- EXPECT_EQ(L"\x2026", UTF16ToWide(TruncateString(str2, 2, CHARACTER_BREAK)));
+ EXPECT_EQ(u"…", TruncateString(str2, 2, WORD_BREAK));
+ EXPECT_EQ(u"…", TruncateString(str2, 2, CHARACTER_BREAK));
// Test breaking at the beginning of the first word, with leading whitespace.
- EXPECT_EQ(L"\x2026", UTF16ToWide(TruncateString(str2, 3, WORD_BREAK)));
- EXPECT_EQ(L"\x2026", UTF16ToWide(TruncateString(str2, 3, CHARACTER_BREAK)));
+ EXPECT_EQ(u"…", TruncateString(str2, 3, WORD_BREAK));
+ EXPECT_EQ(u"…", TruncateString(str2, 3, CHARACTER_BREAK));
// Test breaking in the middle of the first word, with leading whitespace.
- EXPECT_EQ(L"\x2026", UTF16ToWide(TruncateString(str2, 4, WORD_BREAK)));
- EXPECT_EQ(L"\x2026", UTF16ToWide(TruncateString(str2, 4, CHARACTER_BREAK)));
- EXPECT_EQ(L" f\x2026", UTF16ToWide(TruncateString(str2, 5, WORD_BREAK)));
- EXPECT_EQ(L" f\x2026",
- UTF16ToWide(TruncateString(str2, 5, CHARACTER_BREAK)));
+ EXPECT_EQ(u"…", TruncateString(str2, 4, WORD_BREAK));
+ EXPECT_EQ(u"…", TruncateString(str2, 4, CHARACTER_BREAK));
+ EXPECT_EQ(u" f…", TruncateString(str2, 5, WORD_BREAK));
+ EXPECT_EQ(u" f…", TruncateString(str2, 5, CHARACTER_BREAK));
}
} // namespace gfx
diff --git a/chromium/ui/gfx/vector_icon_utils.cc b/chromium/ui/gfx/vector_icon_utils.cc
new file mode 100644
index 00000000000..44b68fabcb8
--- /dev/null
+++ b/chromium/ui/gfx/vector_icon_utils.cc
@@ -0,0 +1,24 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/vector_icon_utils.h"
+
+#include "base/check.h"
+#include "ui/gfx/vector_icon_types.h"
+
+namespace gfx {
+
+int GetDefaultSizeOfVectorIcon(const VectorIcon& icon) {
+ if (icon.is_empty())
+ return -1;
+ const PathElement* default_icon_path = icon.reps[icon.reps_size - 1].path;
+ DCHECK_EQ(default_icon_path[0].command, CANVAS_DIMENSIONS)
+ << " " << icon.name
+ << " has no size in its icon definition, and it seems unlikely you want "
+ "to display at the default of 48dip. Please specify a size in "
+ "CreateVectorIcon().";
+ return default_icon_path[1].arg;
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/vector_icon_utils.h b/chromium/ui/gfx/vector_icon_utils.h
new file mode 100644
index 00000000000..532f29f2b1c
--- /dev/null
+++ b/chromium/ui/gfx/vector_icon_utils.h
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_VECTOR_ICON_UTILS_H_
+#define UI_GFX_VECTOR_ICON_UTILS_H_
+
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+struct VectorIcon;
+
+// Calculates the size that will be default for |icon|, in dip. This will be the
+// smallest icon size |icon| contains.
+GFX_EXPORT int GetDefaultSizeOfVectorIcon(const gfx::VectorIcon& icon);
+
+} // namespace gfx
+
+#endif // UI_GFX_VECTOR_ICON_UTILS_H_
diff --git a/chromium/ui/gfx/win/direct_write.cc b/chromium/ui/gfx/win/direct_write.cc
index 4ddff6f42dd..feed566b58c 100644
--- a/chromium/ui/gfx/win/direct_write.cc
+++ b/chromium/ui/gfx/win/direct_write.cc
@@ -108,7 +108,7 @@ IDWriteFactory* GetDirectWriteFactory() {
return g_direct_write_factory;
}
-base::Optional<std::string> RetrieveLocalizedString(
+absl::optional<std::string> RetrieveLocalizedString(
IDWriteLocalizedStrings* names,
const std::string& locale) {
std::wstring locale_wide = base::UTF8ToWide(locale);
@@ -120,20 +120,20 @@ base::Optional<std::string> RetrieveLocalizedString(
if (!locale.empty() &&
(FAILED(names->FindLocaleName(locale_wide.c_str(), &index, &exists)) ||
!exists)) {
- return base::nullopt;
+ return absl::nullopt;
}
// Get the string length.
UINT32 length = 0;
if (FAILED(names->GetStringLength(index, &length)))
- return base::nullopt;
+ return absl::nullopt;
// The output buffer length needs to be one larger to receive the NUL
// character.
std::wstring buffer;
buffer.resize(length + 1);
if (FAILED(names->GetString(index, &buffer[0], buffer.size())))
- return base::nullopt;
+ return absl::nullopt;
// Shrink the string to fit the actual length.
buffer.resize(length);
@@ -141,7 +141,7 @@ base::Optional<std::string> RetrieveLocalizedString(
return base::WideToUTF8(buffer);
}
-base::Optional<std::string> RetrieveLocalizedFontName(
+absl::optional<std::string> RetrieveLocalizedFontName(
base::StringPiece font_name,
const std::string& locale) {
Microsoft::WRL::ComPtr<IDWriteFactory> factory;
@@ -149,7 +149,7 @@ base::Optional<std::string> RetrieveLocalizedFontName(
Microsoft::WRL::ComPtr<IDWriteFontCollection> font_collection;
if (FAILED(factory->GetSystemFontCollection(&font_collection))) {
- return base::nullopt;
+ return absl::nullopt;
}
UINT32 index = 0;
@@ -158,14 +158,14 @@ base::Optional<std::string> RetrieveLocalizedFontName(
if (FAILED(font_collection->FindFamilyName(font_name_wide.c_str(), &index,
&exists)) ||
!exists) {
- return base::nullopt;
+ return absl::nullopt;
}
Microsoft::WRL::ComPtr<IDWriteFontFamily> font_family;
Microsoft::WRL::ComPtr<IDWriteLocalizedStrings> family_names;
if (FAILED(font_collection->GetFontFamily(index, &font_family)) ||
FAILED(font_family->GetFamilyNames(&family_names))) {
- return base::nullopt;
+ return absl::nullopt;
}
return RetrieveLocalizedString(family_names.Get(), locale);
diff --git a/chromium/ui/gfx/win/direct_write.h b/chromium/ui/gfx/win/direct_write.h
index 7c7316fd3f8..2cbb4a58e80 100644
--- a/chromium/ui/gfx/win/direct_write.h
+++ b/chromium/ui/gfx/win/direct_write.h
@@ -7,8 +7,8 @@
#include <dwrite.h>
-#include "base/optional.h"
#include "base/strings/string_piece.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/gfx_export.h"
namespace gfx {
@@ -24,13 +24,13 @@ GFX_EXPORT IDWriteFactory* GetDirectWriteFactory();
// Retrieves the localized string for a given locale. If locale is empty,
// retrieves the first element of |names|.
-GFX_EXPORT base::Optional<std::string> RetrieveLocalizedString(
+GFX_EXPORT absl::optional<std::string> RetrieveLocalizedString(
IDWriteLocalizedStrings* names,
const std::string& locale);
// Retrieves the localized font name for a given locale. If locale is empty,
// retrieves the default native font name.
-GFX_EXPORT base::Optional<std::string> RetrieveLocalizedFontName(
+GFX_EXPORT absl::optional<std::string> RetrieveLocalizedFontName(
base::StringPiece font_name,
const std::string& locale);
diff --git a/chromium/ui/gfx/win/physical_size.h b/chromium/ui/gfx/win/physical_size.h
index 10d94714ffb..5b768adba6e 100644
--- a/chromium/ui/gfx/win/physical_size.h
+++ b/chromium/ui/gfx/win/physical_size.h
@@ -28,4 +28,4 @@ GFX_EXPORT std::vector<PhysicalDisplaySize> GetPhysicalSizeForDisplays();
} // namespace gfx
-#endif // UI_GFX_DPI_WIN_H_
+#endif // UI_GFX_WIN_PHYSICAL_SIZE_H_
diff --git a/chromium/ui/gfx/win/singleton_hwnd.h b/chromium/ui/gfx/win/singleton_hwnd.h
index 11ac73c0de3..d987f310c74 100644
--- a/chromium/ui/gfx/win/singleton_hwnd.h
+++ b/chromium/ui/gfx/win/singleton_hwnd.h
@@ -6,7 +6,6 @@
#define UI_GFX_WIN_SINGLETON_HWND_H_
#include <windows.h>
-#include <vector>
#include "base/macros.h"
#include "base/observer_list.h"
diff --git a/chromium/ui/gfx/win/singleton_hwnd_hot_key_observer.cc b/chromium/ui/gfx/win/singleton_hwnd_hot_key_observer.cc
index 2d2363477b2..be3d7c2fed7 100644
--- a/chromium/ui/gfx/win/singleton_hwnd_hot_key_observer.cc
+++ b/chromium/ui/gfx/win/singleton_hwnd_hot_key_observer.cc
@@ -8,7 +8,7 @@
#include "base/containers/flat_set.h"
#include "base/memory/ptr_util.h"
#include "base/no_destructor.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/win/singleton_hwnd.h"
namespace gfx {
@@ -20,14 +20,14 @@ base::flat_set<int>& GetUsedHotKeyIDs() {
return *used_hot_key_ids;
}
-base::Optional<int> GetAvailableHotKeyID() {
+absl::optional<int> GetAvailableHotKeyID() {
// Valid hot key IDs are in the range 0x0000 to 0xBFFF. See
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-registerhotkey
for (int i = 0x0000; i < 0xBFFF; i++) {
if (!GetUsedHotKeyIDs().contains(i))
return i;
}
- return base::nullopt;
+ return absl::nullopt;
}
void SetHotKeyIDUsed(int id) {
@@ -47,7 +47,7 @@ SingletonHwndHotKeyObserver::Create(
const SingletonHwndObserver::WndProc& wnd_proc,
UINT key_code,
int modifiers) {
- base::Optional<int> hot_key_id = GetAvailableHotKeyID();
+ absl::optional<int> hot_key_id = GetAvailableHotKeyID();
// If there are no available hot key IDs, return null.
if (!hot_key_id.has_value())
diff --git a/chromium/ui/gfx/win/window_impl.cc b/chromium/ui/gfx/win/window_impl.cc
index a28dd7ea4b0..dd3ea766734 100644
--- a/chromium/ui/gfx/win/window_impl.cc
+++ b/chromium/ui/gfx/win/window_impl.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/debug/alias.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/stl_util.h"
diff --git a/chromium/ui/gfx/x/connection.cc b/chromium/ui/gfx/x/connection.cc
index b38f0696c8d..cf033f9126a 100644
--- a/chromium/ui/gfx/x/connection.cc
+++ b/chromium/ui/gfx/x/connection.cc
@@ -362,10 +362,19 @@ void Connection::SynchronizeForTest(bool synchronous) {
void Connection::ReadResponses() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- while (auto* event = xcb_poll_for_event(XcbConnection())) {
+ while (ReadResponse(false)) {
+ }
+}
+
+bool Connection::ReadResponse(bool queued) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto* event = queued ? xcb_poll_for_queued_event(XcbConnection())
+ : xcb_poll_for_event(XcbConnection());
+ if (event) {
events_.emplace_back(base::MakeRefCounted<MallocedRefCountedMemory>(event),
this);
}
+ return event;
}
Event Connection::WaitForNextEvent() {
@@ -520,7 +529,7 @@ void Connection::ProcessNextResponse() {
requests_.pop_front();
if (last_non_void_request_id_.has_value() &&
last_non_void_request_id_.value() == first_request_id_) {
- last_non_void_request_id_ = base::nullopt;
+ last_non_void_request_id_ = absl::nullopt;
}
first_request_id_++;
if (request.callback) {
diff --git a/chromium/ui/gfx/x/connection.h b/chromium/ui/gfx/x/connection.h
index 761a1ef5d5d..4281481678e 100644
--- a/chromium/ui/gfx/x/connection.h
+++ b/chromium/ui/gfx/x/connection.h
@@ -9,8 +9,8 @@
#include "base/component_export.h"
#include "base/containers/circular_deque.h"
#include "base/containers/flat_map.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/platform/platform_event_source.h"
#include "ui/gfx/x/extension_manager.h"
#include "ui/gfx/x/xlib_support.h"
@@ -140,9 +140,16 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,
// If |synchronous| is true, this makes all requests Sync().
void SynchronizeForTest(bool synchronous);
- // Read all responses from the socket without blocking.
+ // Read all responses from the socket without blocking. This function will
+ // make non-blocking read() syscalls.
void ReadResponses();
+ // Read a single response. If |queued| is true, no read() will be done; a
+ // response may only be translated from buffered socket data. If |queued| is
+ // false, a non-blocking read() will only be done if no response is buffered.
+ // Returns true if an event was read.
+ bool ReadResponse(bool queued);
+
Event WaitForNextEvent();
// Are there any events, errors, or replies already buffered?
@@ -323,8 +330,8 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,
// the 0'th request is handled internally by XCB when opening the connection.
SequenceType first_request_id_ = 1;
// If any request in |requests_| will generate a reply, this is the ID of the
- // latest one, otherwise this is base::nullopt.
- base::Optional<SequenceType> last_non_void_request_id_;
+ // latest one, otherwise this is absl::nullopt.
+ absl::optional<SequenceType> last_non_void_request_id_;
using ErrorParser = std::unique_ptr<Error> (*)(RawError error_bytes);
std::array<ErrorParser, 256> error_parsers_{};
diff --git a/chromium/ui/gfx/x/gen_xproto.py b/chromium/ui/gfx/x/gen_xproto.py
index efb9aacbb19..715d80f9b00 100644
--- a/chromium/ui/gfx/x/gen_xproto.py
+++ b/chromium/ui/gfx/x/gen_xproto.py
@@ -538,7 +538,7 @@ class GenXproto(FileWriter):
self.copy_field(case_field)
def declare_switch(self, field):
- return [('base::Optional<%s>' % field_type, field_name)
+ return [('absl::optional<%s>' % field_type, field_name)
for case in field.type.bitcases
for field_type, field_name in self.declare_case(case)]
@@ -843,7 +843,7 @@ class GenXproto(FileWriter):
return []
if field.type.is_switch:
- return ['base::nullopt'] * len(self.declare_switch(field))
+ return ['absl::nullopt'] * len(self.declare_switch(field))
if field.type.is_list or not field.type.is_container:
return ['{}']
@@ -1222,7 +1222,7 @@ class GenXproto(FileWriter):
self.write('#include "base/component_export.h"')
self.write('#include "base/memory/ref_counted_memory.h"')
self.write('#include "base/memory/scoped_refptr.h"')
- self.write('#include "base/optional.h"')
+ self.write('#include "third_party/abseil-cpp/absl/types/optional.h"')
self.write('#include "base/files/scoped_file.h"')
self.write('#include "ui/gfx/x/ref_counted_fd.h"')
self.write('#include "ui/gfx/x/error.h"')
diff --git a/chromium/ui/gfx/x/generated_protos/bigreq.h b/chromium/ui/gfx/x/generated_protos/bigreq.h
index 4f32d9d68ff..46d12de250e 100644
--- a/chromium/ui/gfx/x/generated_protos/bigreq.h
+++ b/chromium/ui/gfx/x/generated_protos/bigreq.h
@@ -41,17 +41,15 @@
#ifndef UI_GFX_X_GENERATED_PROTOS_BIGREQ_H_
#define UI_GFX_X_GENERATED_PROTOS_BIGREQ_H_
-#include <array>
#include <cstddef>
#include <cstdint>
#include <cstring>
-#include <vector>
#include "base/component_export.h"
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/composite.h b/chromium/ui/gfx/x/generated_protos/composite.h
index 4b84691e768..76e8be6f10f 100644
--- a/chromium/ui/gfx/x/generated_protos/composite.h
+++ b/chromium/ui/gfx/x/generated_protos/composite.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xfixes.h"
diff --git a/chromium/ui/gfx/x/generated_protos/damage.h b/chromium/ui/gfx/x/generated_protos/damage.h
index cb6cd3db0b0..bcfd8c4ee40 100644
--- a/chromium/ui/gfx/x/generated_protos/damage.h
+++ b/chromium/ui/gfx/x/generated_protos/damage.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xfixes.h"
diff --git a/chromium/ui/gfx/x/generated_protos/dpms.h b/chromium/ui/gfx/x/generated_protos/dpms.h
index 59779ce56be..f81f656db0e 100644
--- a/chromium/ui/gfx/x/generated_protos/dpms.h
+++ b/chromium/ui/gfx/x/generated_protos/dpms.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/dri2.h b/chromium/ui/gfx/x/generated_protos/dri2.h
index 1db7856c83b..5d4a6bdf5f4 100644
--- a/chromium/ui/gfx/x/generated_protos/dri2.h
+++ b/chromium/ui/gfx/x/generated_protos/dri2.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/dri3.h b/chromium/ui/gfx/x/generated_protos/dri3.h
index 35bc163d0aa..9fda8e3e458 100644
--- a/chromium/ui/gfx/x/generated_protos/dri3.h
+++ b/chromium/ui/gfx/x/generated_protos/dri3.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/ge.h b/chromium/ui/gfx/x/generated_protos/ge.h
index 1a690c9c95a..5e36176f067 100644
--- a/chromium/ui/gfx/x/generated_protos/ge.h
+++ b/chromium/ui/gfx/x/generated_protos/ge.h
@@ -41,17 +41,15 @@
#ifndef UI_GFX_X_GENERATED_PROTOS_GE_H_
#define UI_GFX_X_GENERATED_PROTOS_GE_H_
-#include <array>
#include <cstddef>
#include <cstdint>
#include <cstring>
-#include <vector>
#include "base/component_export.h"
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/glx.h b/chromium/ui/gfx/x/generated_protos/glx.h
index d20eec6df74..cc805bbd232 100644
--- a/chromium/ui/gfx/x/generated_protos/glx.h
+++ b/chromium/ui/gfx/x/generated_protos/glx.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/present.h b/chromium/ui/gfx/x/generated_protos/present.h
index a77befb0479..dcfd695858c 100644
--- a/chromium/ui/gfx/x/generated_protos/present.h
+++ b/chromium/ui/gfx/x/generated_protos/present.h
@@ -51,9 +51,9 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
#include "randr.h"
#include "sync.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xfixes.h"
diff --git a/chromium/ui/gfx/x/generated_protos/randr.h b/chromium/ui/gfx/x/generated_protos/randr.h
index 3d618aa925b..1f420bb79bd 100644
--- a/chromium/ui/gfx/x/generated_protos/randr.h
+++ b/chromium/ui/gfx/x/generated_protos/randr.h
@@ -51,8 +51,8 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
#include "render.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
@@ -307,13 +307,13 @@ class COMPONENT_EXPORT(X11) RandR {
Lease lease{};
uint8_t created{};
};
- base::Optional<Cc> cc{};
- base::Optional<Oc> oc{};
- base::Optional<Op> op{};
- base::Optional<Pc> pc{};
- base::Optional<Pp> pp{};
- base::Optional<Rc> rc{};
- base::Optional<Lc> lc{};
+ absl::optional<Cc> cc{};
+ absl::optional<Oc> oc{};
+ absl::optional<Op> op{};
+ absl::optional<Pc> pc{};
+ absl::optional<Pp> pp{};
+ absl::optional<Rc> rc{};
+ absl::optional<Lc> lc{};
x11::Window* GetWindow() { return nullptr; }
};
diff --git a/chromium/ui/gfx/x/generated_protos/record.h b/chromium/ui/gfx/x/generated_protos/record.h
index 068ac048662..123f200cad5 100644
--- a/chromium/ui/gfx/x/generated_protos/record.h
+++ b/chromium/ui/gfx/x/generated_protos/record.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/render.cc b/chromium/ui/gfx/x/generated_protos/render.cc
index 7985f551a47..553afbd9dd1 100644
--- a/chromium/ui/gfx/x/generated_protos/render.cc
+++ b/chromium/ui/gfx/x/generated_protos/render.cc
@@ -758,19 +758,19 @@ Future<void> Render::CreatePicture(
const Picture& pid,
const Drawable& drawable,
const PictFormat& format,
- const base::Optional<Repeat>& repeat,
- const base::Optional<Picture>& alphamap,
- const base::Optional<int32_t>& alphaxorigin,
- const base::Optional<int32_t>& alphayorigin,
- const base::Optional<int32_t>& clipxorigin,
- const base::Optional<int32_t>& clipyorigin,
- const base::Optional<Pixmap>& clipmask,
- const base::Optional<uint32_t>& graphicsexposure,
- const base::Optional<SubwindowMode>& subwindowmode,
- const base::Optional<PolyEdge>& polyedge,
- const base::Optional<PolyMode>& polymode,
- const base::Optional<Atom>& dither,
- const base::Optional<uint32_t>& componentalpha) {
+ const absl::optional<Repeat>& repeat,
+ const absl::optional<Picture>& alphamap,
+ const absl::optional<int32_t>& alphaxorigin,
+ const absl::optional<int32_t>& alphayorigin,
+ const absl::optional<int32_t>& clipxorigin,
+ const absl::optional<int32_t>& clipyorigin,
+ const absl::optional<Pixmap>& clipmask,
+ const absl::optional<uint32_t>& graphicsexposure,
+ const absl::optional<SubwindowMode>& subwindowmode,
+ const absl::optional<PolyEdge>& polyedge,
+ const absl::optional<PolyMode>& polymode,
+ const absl::optional<Atom>& dither,
+ const absl::optional<uint32_t>& componentalpha) {
return Render::CreatePicture(Render::CreatePictureRequest{
pid, drawable, format, repeat, alphamap, alphaxorigin, alphayorigin,
clipxorigin, clipyorigin, clipmask, graphicsexposure, subwindowmode,
@@ -930,19 +930,19 @@ Future<void> Render::ChangePicture(
Future<void> Render::ChangePicture(
const Picture& picture,
- const base::Optional<Repeat>& repeat,
- const base::Optional<Picture>& alphamap,
- const base::Optional<int32_t>& alphaxorigin,
- const base::Optional<int32_t>& alphayorigin,
- const base::Optional<int32_t>& clipxorigin,
- const base::Optional<int32_t>& clipyorigin,
- const base::Optional<Pixmap>& clipmask,
- const base::Optional<uint32_t>& graphicsexposure,
- const base::Optional<SubwindowMode>& subwindowmode,
- const base::Optional<PolyEdge>& polyedge,
- const base::Optional<PolyMode>& polymode,
- const base::Optional<Atom>& dither,
- const base::Optional<uint32_t>& componentalpha) {
+ const absl::optional<Repeat>& repeat,
+ const absl::optional<Picture>& alphamap,
+ const absl::optional<int32_t>& alphaxorigin,
+ const absl::optional<int32_t>& alphayorigin,
+ const absl::optional<int32_t>& clipxorigin,
+ const absl::optional<int32_t>& clipyorigin,
+ const absl::optional<Pixmap>& clipmask,
+ const absl::optional<uint32_t>& graphicsexposure,
+ const absl::optional<SubwindowMode>& subwindowmode,
+ const absl::optional<PolyEdge>& polyedge,
+ const absl::optional<PolyMode>& polymode,
+ const absl::optional<Atom>& dither,
+ const absl::optional<uint32_t>& componentalpha) {
return Render::ChangePicture(Render::ChangePictureRequest{
picture, repeat, alphamap, alphaxorigin, alphayorigin, clipxorigin,
clipyorigin, clipmask, graphicsexposure, subwindowmode, polyedge,
diff --git a/chromium/ui/gfx/x/generated_protos/render.h b/chromium/ui/gfx/x/generated_protos/render.h
index cf372e709c8..62d784fc1e1 100644
--- a/chromium/ui/gfx/x/generated_protos/render.h
+++ b/chromium/ui/gfx/x/generated_protos/render.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
@@ -392,19 +392,19 @@ class COMPONENT_EXPORT(X11) Render {
Picture pid{};
Drawable drawable{};
PictFormat format{};
- base::Optional<Repeat> repeat{};
- base::Optional<Picture> alphamap{};
- base::Optional<int32_t> alphaxorigin{};
- base::Optional<int32_t> alphayorigin{};
- base::Optional<int32_t> clipxorigin{};
- base::Optional<int32_t> clipyorigin{};
- base::Optional<Pixmap> clipmask{};
- base::Optional<uint32_t> graphicsexposure{};
- base::Optional<SubwindowMode> subwindowmode{};
- base::Optional<PolyEdge> polyedge{};
- base::Optional<PolyMode> polymode{};
- base::Optional<Atom> dither{};
- base::Optional<uint32_t> componentalpha{};
+ absl::optional<Repeat> repeat{};
+ absl::optional<Picture> alphamap{};
+ absl::optional<int32_t> alphaxorigin{};
+ absl::optional<int32_t> alphayorigin{};
+ absl::optional<int32_t> clipxorigin{};
+ absl::optional<int32_t> clipyorigin{};
+ absl::optional<Pixmap> clipmask{};
+ absl::optional<uint32_t> graphicsexposure{};
+ absl::optional<SubwindowMode> subwindowmode{};
+ absl::optional<PolyEdge> polyedge{};
+ absl::optional<PolyMode> polymode{};
+ absl::optional<Atom> dither{};
+ absl::optional<uint32_t> componentalpha{};
};
using CreatePictureResponse = Response<void>;
@@ -415,35 +415,35 @@ class COMPONENT_EXPORT(X11) Render {
const Picture& pid = {},
const Drawable& drawable = {},
const PictFormat& format = {},
- const base::Optional<Repeat>& repeat = base::nullopt,
- const base::Optional<Picture>& alphamap = base::nullopt,
- const base::Optional<int32_t>& alphaxorigin = base::nullopt,
- const base::Optional<int32_t>& alphayorigin = base::nullopt,
- const base::Optional<int32_t>& clipxorigin = base::nullopt,
- const base::Optional<int32_t>& clipyorigin = base::nullopt,
- const base::Optional<Pixmap>& clipmask = base::nullopt,
- const base::Optional<uint32_t>& graphicsexposure = base::nullopt,
- const base::Optional<SubwindowMode>& subwindowmode = base::nullopt,
- const base::Optional<PolyEdge>& polyedge = base::nullopt,
- const base::Optional<PolyMode>& polymode = base::nullopt,
- const base::Optional<Atom>& dither = base::nullopt,
- const base::Optional<uint32_t>& componentalpha = base::nullopt);
+ const absl::optional<Repeat>& repeat = absl::nullopt,
+ const absl::optional<Picture>& alphamap = absl::nullopt,
+ const absl::optional<int32_t>& alphaxorigin = absl::nullopt,
+ const absl::optional<int32_t>& alphayorigin = absl::nullopt,
+ const absl::optional<int32_t>& clipxorigin = absl::nullopt,
+ const absl::optional<int32_t>& clipyorigin = absl::nullopt,
+ const absl::optional<Pixmap>& clipmask = absl::nullopt,
+ const absl::optional<uint32_t>& graphicsexposure = absl::nullopt,
+ const absl::optional<SubwindowMode>& subwindowmode = absl::nullopt,
+ const absl::optional<PolyEdge>& polyedge = absl::nullopt,
+ const absl::optional<PolyMode>& polymode = absl::nullopt,
+ const absl::optional<Atom>& dither = absl::nullopt,
+ const absl::optional<uint32_t>& componentalpha = absl::nullopt);
struct ChangePictureRequest {
Picture picture{};
- base::Optional<Repeat> repeat{};
- base::Optional<Picture> alphamap{};
- base::Optional<int32_t> alphaxorigin{};
- base::Optional<int32_t> alphayorigin{};
- base::Optional<int32_t> clipxorigin{};
- base::Optional<int32_t> clipyorigin{};
- base::Optional<Pixmap> clipmask{};
- base::Optional<uint32_t> graphicsexposure{};
- base::Optional<SubwindowMode> subwindowmode{};
- base::Optional<PolyEdge> polyedge{};
- base::Optional<PolyMode> polymode{};
- base::Optional<Atom> dither{};
- base::Optional<uint32_t> componentalpha{};
+ absl::optional<Repeat> repeat{};
+ absl::optional<Picture> alphamap{};
+ absl::optional<int32_t> alphaxorigin{};
+ absl::optional<int32_t> alphayorigin{};
+ absl::optional<int32_t> clipxorigin{};
+ absl::optional<int32_t> clipyorigin{};
+ absl::optional<Pixmap> clipmask{};
+ absl::optional<uint32_t> graphicsexposure{};
+ absl::optional<SubwindowMode> subwindowmode{};
+ absl::optional<PolyEdge> polyedge{};
+ absl::optional<PolyMode> polymode{};
+ absl::optional<Atom> dither{};
+ absl::optional<uint32_t> componentalpha{};
};
using ChangePictureResponse = Response<void>;
@@ -452,19 +452,19 @@ class COMPONENT_EXPORT(X11) Render {
Future<void> ChangePicture(
const Picture& picture = {},
- const base::Optional<Repeat>& repeat = base::nullopt,
- const base::Optional<Picture>& alphamap = base::nullopt,
- const base::Optional<int32_t>& alphaxorigin = base::nullopt,
- const base::Optional<int32_t>& alphayorigin = base::nullopt,
- const base::Optional<int32_t>& clipxorigin = base::nullopt,
- const base::Optional<int32_t>& clipyorigin = base::nullopt,
- const base::Optional<Pixmap>& clipmask = base::nullopt,
- const base::Optional<uint32_t>& graphicsexposure = base::nullopt,
- const base::Optional<SubwindowMode>& subwindowmode = base::nullopt,
- const base::Optional<PolyEdge>& polyedge = base::nullopt,
- const base::Optional<PolyMode>& polymode = base::nullopt,
- const base::Optional<Atom>& dither = base::nullopt,
- const base::Optional<uint32_t>& componentalpha = base::nullopt);
+ const absl::optional<Repeat>& repeat = absl::nullopt,
+ const absl::optional<Picture>& alphamap = absl::nullopt,
+ const absl::optional<int32_t>& alphaxorigin = absl::nullopt,
+ const absl::optional<int32_t>& alphayorigin = absl::nullopt,
+ const absl::optional<int32_t>& clipxorigin = absl::nullopt,
+ const absl::optional<int32_t>& clipyorigin = absl::nullopt,
+ const absl::optional<Pixmap>& clipmask = absl::nullopt,
+ const absl::optional<uint32_t>& graphicsexposure = absl::nullopt,
+ const absl::optional<SubwindowMode>& subwindowmode = absl::nullopt,
+ const absl::optional<PolyEdge>& polyedge = absl::nullopt,
+ const absl::optional<PolyMode>& polymode = absl::nullopt,
+ const absl::optional<Atom>& dither = absl::nullopt,
+ const absl::optional<uint32_t>& componentalpha = absl::nullopt);
struct SetPictureClipRectanglesRequest {
Picture picture{};
diff --git a/chromium/ui/gfx/x/generated_protos/res.h b/chromium/ui/gfx/x/generated_protos/res.h
index da92e06f3f4..11bd31088fd 100644
--- a/chromium/ui/gfx/x/generated_protos/res.h
+++ b/chromium/ui/gfx/x/generated_protos/res.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/screensaver.cc b/chromium/ui/gfx/x/generated_protos/screensaver.cc
index a02c1ef5d8b..b28f6632d68 100644
--- a/chromium/ui/gfx/x/generated_protos/screensaver.cc
+++ b/chromium/ui/gfx/x/generated_protos/screensaver.cc
@@ -532,21 +532,21 @@ Future<void> ScreenSaver::SetAttributes(
const WindowClass& c_class,
const uint8_t& depth,
const VisualId& visual,
- const base::Optional<Pixmap>& background_pixmap,
- const base::Optional<uint32_t>& background_pixel,
- const base::Optional<Pixmap>& border_pixmap,
- const base::Optional<uint32_t>& border_pixel,
- const base::Optional<Gravity>& bit_gravity,
- const base::Optional<Gravity>& win_gravity,
- const base::Optional<BackingStore>& backing_store,
- const base::Optional<uint32_t>& backing_planes,
- const base::Optional<uint32_t>& backing_pixel,
- const base::Optional<Bool32>& override_redirect,
- const base::Optional<Bool32>& save_under,
- const base::Optional<EventMask>& event_mask,
- const base::Optional<EventMask>& do_not_propogate_mask,
- const base::Optional<ColorMap>& colormap,
- const base::Optional<Cursor>& cursor) {
+ const absl::optional<Pixmap>& background_pixmap,
+ const absl::optional<uint32_t>& background_pixel,
+ const absl::optional<Pixmap>& border_pixmap,
+ const absl::optional<uint32_t>& border_pixel,
+ const absl::optional<Gravity>& bit_gravity,
+ const absl::optional<Gravity>& win_gravity,
+ const absl::optional<BackingStore>& backing_store,
+ const absl::optional<uint32_t>& backing_planes,
+ const absl::optional<uint32_t>& backing_pixel,
+ const absl::optional<Bool32>& override_redirect,
+ const absl::optional<Bool32>& save_under,
+ const absl::optional<EventMask>& event_mask,
+ const absl::optional<EventMask>& do_not_propogate_mask,
+ const absl::optional<ColorMap>& colormap,
+ const absl::optional<Cursor>& cursor) {
return ScreenSaver::SetAttributes(
ScreenSaver::SetAttributesRequest{drawable,
x,
diff --git a/chromium/ui/gfx/x/generated_protos/screensaver.h b/chromium/ui/gfx/x/generated_protos/screensaver.h
index 8c10111cf68..7f43bcd7d25 100644
--- a/chromium/ui/gfx/x/generated_protos/screensaver.h
+++ b/chromium/ui/gfx/x/generated_protos/screensaver.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
@@ -174,21 +174,21 @@ class COMPONENT_EXPORT(X11) ScreenSaver {
WindowClass c_class{};
uint8_t depth{};
VisualId visual{};
- base::Optional<Pixmap> background_pixmap{};
- base::Optional<uint32_t> background_pixel{};
- base::Optional<Pixmap> border_pixmap{};
- base::Optional<uint32_t> border_pixel{};
- base::Optional<Gravity> bit_gravity{};
- base::Optional<Gravity> win_gravity{};
- base::Optional<BackingStore> backing_store{};
- base::Optional<uint32_t> backing_planes{};
- base::Optional<uint32_t> backing_pixel{};
- base::Optional<Bool32> override_redirect{};
- base::Optional<Bool32> save_under{};
- base::Optional<EventMask> event_mask{};
- base::Optional<EventMask> do_not_propogate_mask{};
- base::Optional<ColorMap> colormap{};
- base::Optional<Cursor> cursor{};
+ absl::optional<Pixmap> background_pixmap{};
+ absl::optional<uint32_t> background_pixel{};
+ absl::optional<Pixmap> border_pixmap{};
+ absl::optional<uint32_t> border_pixel{};
+ absl::optional<Gravity> bit_gravity{};
+ absl::optional<Gravity> win_gravity{};
+ absl::optional<BackingStore> backing_store{};
+ absl::optional<uint32_t> backing_planes{};
+ absl::optional<uint32_t> backing_pixel{};
+ absl::optional<Bool32> override_redirect{};
+ absl::optional<Bool32> save_under{};
+ absl::optional<EventMask> event_mask{};
+ absl::optional<EventMask> do_not_propogate_mask{};
+ absl::optional<ColorMap> colormap{};
+ absl::optional<Cursor> cursor{};
};
using SetAttributesResponse = Response<void>;
@@ -205,21 +205,21 @@ class COMPONENT_EXPORT(X11) ScreenSaver {
const WindowClass& c_class = {},
const uint8_t& depth = {},
const VisualId& visual = {},
- const base::Optional<Pixmap>& background_pixmap = base::nullopt,
- const base::Optional<uint32_t>& background_pixel = base::nullopt,
- const base::Optional<Pixmap>& border_pixmap = base::nullopt,
- const base::Optional<uint32_t>& border_pixel = base::nullopt,
- const base::Optional<Gravity>& bit_gravity = base::nullopt,
- const base::Optional<Gravity>& win_gravity = base::nullopt,
- const base::Optional<BackingStore>& backing_store = base::nullopt,
- const base::Optional<uint32_t>& backing_planes = base::nullopt,
- const base::Optional<uint32_t>& backing_pixel = base::nullopt,
- const base::Optional<Bool32>& override_redirect = base::nullopt,
- const base::Optional<Bool32>& save_under = base::nullopt,
- const base::Optional<EventMask>& event_mask = base::nullopt,
- const base::Optional<EventMask>& do_not_propogate_mask = base::nullopt,
- const base::Optional<ColorMap>& colormap = base::nullopt,
- const base::Optional<Cursor>& cursor = base::nullopt);
+ const absl::optional<Pixmap>& background_pixmap = absl::nullopt,
+ const absl::optional<uint32_t>& background_pixel = absl::nullopt,
+ const absl::optional<Pixmap>& border_pixmap = absl::nullopt,
+ const absl::optional<uint32_t>& border_pixel = absl::nullopt,
+ const absl::optional<Gravity>& bit_gravity = absl::nullopt,
+ const absl::optional<Gravity>& win_gravity = absl::nullopt,
+ const absl::optional<BackingStore>& backing_store = absl::nullopt,
+ const absl::optional<uint32_t>& backing_planes = absl::nullopt,
+ const absl::optional<uint32_t>& backing_pixel = absl::nullopt,
+ const absl::optional<Bool32>& override_redirect = absl::nullopt,
+ const absl::optional<Bool32>& save_under = absl::nullopt,
+ const absl::optional<EventMask>& event_mask = absl::nullopt,
+ const absl::optional<EventMask>& do_not_propogate_mask = absl::nullopt,
+ const absl::optional<ColorMap>& colormap = absl::nullopt,
+ const absl::optional<Cursor>& cursor = absl::nullopt);
struct UnsetAttributesRequest {
Drawable drawable{};
diff --git a/chromium/ui/gfx/x/generated_protos/shape.h b/chromium/ui/gfx/x/generated_protos/shape.h
index 33c64b6296e..7262c397778 100644
--- a/chromium/ui/gfx/x/generated_protos/shape.h
+++ b/chromium/ui/gfx/x/generated_protos/shape.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/shm.h b/chromium/ui/gfx/x/generated_protos/shm.h
index 7766811169b..6df3185de60 100644
--- a/chromium/ui/gfx/x/generated_protos/shm.h
+++ b/chromium/ui/gfx/x/generated_protos/shm.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/sync.cc b/chromium/ui/gfx/x/generated_protos/sync.cc
index 5b180a91d5c..f175c29b22b 100644
--- a/chromium/ui/gfx/x/generated_protos/sync.cc
+++ b/chromium/ui/gfx/x/generated_protos/sync.cc
@@ -894,12 +894,12 @@ Future<void> Sync::CreateAlarm(const Sync::CreateAlarmRequest& request) {
}
Future<void> Sync::CreateAlarm(const Alarm& id,
- const base::Optional<Counter>& counter,
- const base::Optional<Valuetype>& valueType,
- const base::Optional<Int64>& value,
- const base::Optional<Testtype>& testType,
- const base::Optional<Int64>& delta,
- const base::Optional<uint32_t>& events) {
+ const absl::optional<Counter>& counter,
+ const absl::optional<Valuetype>& valueType,
+ const absl::optional<Int64>& value,
+ const absl::optional<Testtype>& testType,
+ const absl::optional<Int64>& delta,
+ const absl::optional<uint32_t>& events) {
return Sync::CreateAlarm(Sync::CreateAlarmRequest{
id, counter, valueType, value, testType, delta, events});
}
@@ -1013,12 +1013,12 @@ Future<void> Sync::ChangeAlarm(const Sync::ChangeAlarmRequest& request) {
}
Future<void> Sync::ChangeAlarm(const Alarm& id,
- const base::Optional<Counter>& counter,
- const base::Optional<Valuetype>& valueType,
- const base::Optional<Int64>& value,
- const base::Optional<Testtype>& testType,
- const base::Optional<Int64>& delta,
- const base::Optional<uint32_t>& events) {
+ const absl::optional<Counter>& counter,
+ const absl::optional<Valuetype>& valueType,
+ const absl::optional<Int64>& value,
+ const absl::optional<Testtype>& testType,
+ const absl::optional<Int64>& delta,
+ const absl::optional<uint32_t>& events) {
return Sync::ChangeAlarm(Sync::ChangeAlarmRequest{
id, counter, valueType, value, testType, delta, events});
}
diff --git a/chromium/ui/gfx/x/generated_protos/sync.h b/chromium/ui/gfx/x/generated_protos/sync.h
index f78f7402ece..85ef3d14f52 100644
--- a/chromium/ui/gfx/x/generated_protos/sync.h
+++ b/chromium/ui/gfx/x/generated_protos/sync.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
@@ -290,12 +290,12 @@ class COMPONENT_EXPORT(X11) Sync {
struct CreateAlarmRequest {
Alarm id{};
- base::Optional<Counter> counter{};
- base::Optional<Valuetype> valueType{};
- base::Optional<Int64> value{};
- base::Optional<Testtype> testType{};
- base::Optional<Int64> delta{};
- base::Optional<uint32_t> events{};
+ absl::optional<Counter> counter{};
+ absl::optional<Valuetype> valueType{};
+ absl::optional<Int64> value{};
+ absl::optional<Testtype> testType{};
+ absl::optional<Int64> delta{};
+ absl::optional<uint32_t> events{};
};
using CreateAlarmResponse = Response<void>;
@@ -304,21 +304,21 @@ class COMPONENT_EXPORT(X11) Sync {
Future<void> CreateAlarm(
const Alarm& id = {},
- const base::Optional<Counter>& counter = base::nullopt,
- const base::Optional<Valuetype>& valueType = base::nullopt,
- const base::Optional<Int64>& value = base::nullopt,
- const base::Optional<Testtype>& testType = base::nullopt,
- const base::Optional<Int64>& delta = base::nullopt,
- const base::Optional<uint32_t>& events = base::nullopt);
+ const absl::optional<Counter>& counter = absl::nullopt,
+ const absl::optional<Valuetype>& valueType = absl::nullopt,
+ const absl::optional<Int64>& value = absl::nullopt,
+ const absl::optional<Testtype>& testType = absl::nullopt,
+ const absl::optional<Int64>& delta = absl::nullopt,
+ const absl::optional<uint32_t>& events = absl::nullopt);
struct ChangeAlarmRequest {
Alarm id{};
- base::Optional<Counter> counter{};
- base::Optional<Valuetype> valueType{};
- base::Optional<Int64> value{};
- base::Optional<Testtype> testType{};
- base::Optional<Int64> delta{};
- base::Optional<uint32_t> events{};
+ absl::optional<Counter> counter{};
+ absl::optional<Valuetype> valueType{};
+ absl::optional<Int64> value{};
+ absl::optional<Testtype> testType{};
+ absl::optional<Int64> delta{};
+ absl::optional<uint32_t> events{};
};
using ChangeAlarmResponse = Response<void>;
@@ -327,12 +327,12 @@ class COMPONENT_EXPORT(X11) Sync {
Future<void> ChangeAlarm(
const Alarm& id = {},
- const base::Optional<Counter>& counter = base::nullopt,
- const base::Optional<Valuetype>& valueType = base::nullopt,
- const base::Optional<Int64>& value = base::nullopt,
- const base::Optional<Testtype>& testType = base::nullopt,
- const base::Optional<Int64>& delta = base::nullopt,
- const base::Optional<uint32_t>& events = base::nullopt);
+ const absl::optional<Counter>& counter = absl::nullopt,
+ const absl::optional<Valuetype>& valueType = absl::nullopt,
+ const absl::optional<Int64>& value = absl::nullopt,
+ const absl::optional<Testtype>& testType = absl::nullopt,
+ const absl::optional<Int64>& delta = absl::nullopt,
+ const absl::optional<uint32_t>& events = absl::nullopt);
struct DestroyAlarmRequest {
Alarm alarm{};
diff --git a/chromium/ui/gfx/x/generated_protos/xc_misc.h b/chromium/ui/gfx/x/generated_protos/xc_misc.h
index cbfc45f3583..ea890feb62a 100644
--- a/chromium/ui/gfx/x/generated_protos/xc_misc.h
+++ b/chromium/ui/gfx/x/generated_protos/xc_misc.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/xevie.h b/chromium/ui/gfx/x/generated_protos/xevie.h
index f820d2e73fd..be6723c69aa 100644
--- a/chromium/ui/gfx/x/generated_protos/xevie.h
+++ b/chromium/ui/gfx/x/generated_protos/xevie.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/xf86dri.h b/chromium/ui/gfx/x/generated_protos/xf86dri.h
index c290d7c4c1e..42cbd474f51 100644
--- a/chromium/ui/gfx/x/generated_protos/xf86dri.h
+++ b/chromium/ui/gfx/x/generated_protos/xf86dri.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/xf86vidmode.h b/chromium/ui/gfx/x/generated_protos/xf86vidmode.h
index 19e9bbbdc1d..fa451a2c22f 100644
--- a/chromium/ui/gfx/x/generated_protos/xf86vidmode.h
+++ b/chromium/ui/gfx/x/generated_protos/xf86vidmode.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/xfixes.h b/chromium/ui/gfx/x/generated_protos/xfixes.h
index ed5a58a4549..b880acd9946 100644
--- a/chromium/ui/gfx/x/generated_protos/xfixes.h
+++ b/chromium/ui/gfx/x/generated_protos/xfixes.h
@@ -51,9 +51,9 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
#include "render.h"
#include "shape.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/xinerama.h b/chromium/ui/gfx/x/generated_protos/xinerama.h
index 866616dcf7e..367d70c5e54 100644
--- a/chromium/ui/gfx/x/generated_protos/xinerama.h
+++ b/chromium/ui/gfx/x/generated_protos/xinerama.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/xinput.cc b/chromium/ui/gfx/x/generated_protos/xinput.cc
index cc97c1745c4..f98f5b23b84 100644
--- a/chromium/ui/gfx/x/generated_protos/xinput.cc
+++ b/chromium/ui/gfx/x/generated_protos/xinput.cc
@@ -5242,9 +5242,9 @@ Future<void> Input::ChangeDeviceProperty(
const uint8_t& device_id,
const PropMode& mode,
const uint32_t& num_items,
- const base::Optional<std::vector<uint8_t>>& data8,
- const base::Optional<std::vector<uint16_t>>& data16,
- const base::Optional<std::vector<uint32_t>>& data32) {
+ const absl::optional<std::vector<uint8_t>>& data8,
+ const absl::optional<std::vector<uint16_t>>& data16,
+ const absl::optional<std::vector<uint32_t>>& data32) {
return Input::ChangeDeviceProperty(Input::ChangeDevicePropertyRequest{
property, type, device_id, mode, num_items, data8, data16, data32});
}
@@ -7233,9 +7233,9 @@ Future<void> Input::XIChangeProperty(
const Atom& property,
const Atom& type,
const uint32_t& num_items,
- const base::Optional<std::vector<uint8_t>>& data8,
- const base::Optional<std::vector<uint16_t>>& data16,
- const base::Optional<std::vector<uint32_t>>& data32) {
+ const absl::optional<std::vector<uint8_t>>& data8,
+ const absl::optional<std::vector<uint16_t>>& data16,
+ const absl::optional<std::vector<uint32_t>>& data32) {
return Input::XIChangeProperty(Input::XIChangePropertyRequest{
deviceid, mode, property, type, num_items, data8, data16, data32});
}
diff --git a/chromium/ui/gfx/x/generated_protos/xinput.h b/chromium/ui/gfx/x/generated_protos/xinput.h
index c94010d69d9..e522384c04c 100644
--- a/chromium/ui/gfx/x/generated_protos/xinput.h
+++ b/chromium/ui/gfx/x/generated_protos/xinput.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xfixes.h"
@@ -430,9 +430,9 @@ class COMPONENT_EXPORT(X11) Input {
uint32_t motion_size{};
std::vector<AxisInfo> axes{};
};
- base::Optional<Key> key{};
- base::Optional<Button> button{};
- base::Optional<Valuator> valuator{};
+ absl::optional<Key> key{};
+ absl::optional<Button> button{};
+ absl::optional<Valuator> valuator{};
};
struct DeviceName {
@@ -542,12 +542,12 @@ class COMPONENT_EXPORT(X11) Input {
uint16_t pitch{};
uint16_t duration{};
};
- base::Optional<Keyboard> keyboard{};
- base::Optional<Pointer> pointer{};
- base::Optional<String> string{};
- base::Optional<Integer> integer{};
- base::Optional<Led> led{};
- base::Optional<Bell> bell{};
+ absl::optional<Keyboard> keyboard{};
+ absl::optional<Pointer> pointer{};
+ absl::optional<String> string{};
+ absl::optional<Integer> integer{};
+ absl::optional<Led> led{};
+ absl::optional<Bell> bell{};
};
struct KbdFeedbackCtl {
@@ -637,12 +637,12 @@ class COMPONENT_EXPORT(X11) Input {
int16_t pitch{};
int16_t duration{};
};
- base::Optional<Keyboard> keyboard{};
- base::Optional<Pointer> pointer{};
- base::Optional<String> string{};
- base::Optional<Integer> integer{};
- base::Optional<Led> led{};
- base::Optional<Bell> bell{};
+ absl::optional<Keyboard> keyboard{};
+ absl::optional<Pointer> pointer{};
+ absl::optional<String> string{};
+ absl::optional<Integer> integer{};
+ absl::optional<Led> led{};
+ absl::optional<Bell> bell{};
};
struct KeyState {
@@ -680,9 +680,9 @@ class COMPONENT_EXPORT(X11) Input {
ValuatorStateModeMask mode{};
std::vector<int32_t> valuators{};
};
- base::Optional<Key> key{};
- base::Optional<Button> button{};
- base::Optional<Valuator> valuator{};
+ absl::optional<Key> key{};
+ absl::optional<Button> button{};
+ absl::optional<Valuator> valuator{};
};
struct DeviceResolutionState {
@@ -762,11 +762,11 @@ class COMPONENT_EXPORT(X11) Input {
uint32_t screen{};
uint32_t following{};
};
- base::Optional<Resolution> resolution{};
- base::Optional<AbsCalib> abs_calib{};
- base::Optional<Core> core{};
- base::Optional<Enable> enable{};
- base::Optional<AbsArea> abs_area{};
+ absl::optional<Resolution> resolution{};
+ absl::optional<AbsCalib> abs_calib{};
+ absl::optional<Core> core{};
+ absl::optional<Enable> enable{};
+ absl::optional<AbsArea> abs_area{};
};
struct DeviceResolutionCtl {
@@ -842,11 +842,11 @@ class COMPONENT_EXPORT(X11) Input {
int32_t screen{};
uint32_t following{};
};
- base::Optional<Resolution> resolution{};
- base::Optional<AbsCalib> abs_calib{};
- base::Optional<Core> core{};
- base::Optional<Enable> enable{};
- base::Optional<AbsArea> abs_area{};
+ absl::optional<Resolution> resolution{};
+ absl::optional<AbsCalib> abs_calib{};
+ absl::optional<Core> core{};
+ absl::optional<Enable> enable{};
+ absl::optional<AbsArea> abs_area{};
};
struct GroupInfo {
@@ -913,10 +913,10 @@ class COMPONENT_EXPORT(X11) Input {
struct DetachSlave {
DeviceId deviceid{};
};
- base::Optional<AddMaster> add_master{};
- base::Optional<RemoveMaster> remove_master{};
- base::Optional<AttachSlave> attach_slave{};
- base::Optional<DetachSlave> detach_slave{};
+ absl::optional<AddMaster> add_master{};
+ absl::optional<RemoveMaster> remove_master{};
+ absl::optional<AttachSlave> attach_slave{};
+ absl::optional<DetachSlave> detach_slave{};
};
struct EventMask {
@@ -999,11 +999,11 @@ class COMPONENT_EXPORT(X11) Input {
TouchMode mode{};
uint8_t num_touches{};
};
- base::Optional<Key> key{};
- base::Optional<Button> button{};
- base::Optional<Valuator> valuator{};
- base::Optional<Scroll> scroll{};
- base::Optional<Touch> touch{};
+ absl::optional<Key> key{};
+ absl::optional<Button> button{};
+ absl::optional<Valuator> valuator{};
+ absl::optional<Scroll> scroll{};
+ absl::optional<Touch> touch{};
};
struct XIDeviceInfo {
@@ -1848,12 +1848,12 @@ class COMPONENT_EXPORT(X11) Input {
const FeedbackCtl& feedback = {
{},
{},
- base::nullopt,
- base::nullopt,
- base::nullopt,
- base::nullopt,
- base::nullopt,
- base::nullopt});
+ absl::nullopt,
+ absl::nullopt,
+ absl::nullopt,
+ absl::nullopt,
+ absl::nullopt,
+ absl::nullopt});
struct GetDeviceKeyMappingRequest {
uint8_t device_id{};
@@ -2103,11 +2103,11 @@ class COMPONENT_EXPORT(X11) Input {
const DeviceControl& control_id = {},
const uint8_t& device_id = {},
const DeviceCtl& control = {{},
- base::nullopt,
- base::nullopt,
- base::nullopt,
- base::nullopt,
- base::nullopt});
+ absl::nullopt,
+ absl::nullopt,
+ absl::nullopt,
+ absl::nullopt,
+ absl::nullopt});
struct ListDevicePropertiesRequest {
uint8_t device_id{};
@@ -2133,9 +2133,9 @@ class COMPONENT_EXPORT(X11) Input {
uint8_t device_id{};
PropMode mode{};
uint32_t num_items{};
- base::Optional<std::vector<uint8_t>> data8{};
- base::Optional<std::vector<uint16_t>> data16{};
- base::Optional<std::vector<uint32_t>> data32{};
+ absl::optional<std::vector<uint8_t>> data8{};
+ absl::optional<std::vector<uint16_t>> data16{};
+ absl::optional<std::vector<uint32_t>> data32{};
};
using ChangeDevicePropertyResponse = Response<void>;
@@ -2148,9 +2148,9 @@ class COMPONENT_EXPORT(X11) Input {
const uint8_t& device_id = {},
const PropMode& mode = {},
const uint32_t& num_items = {},
- const base::Optional<std::vector<uint8_t>>& data8 = base::nullopt,
- const base::Optional<std::vector<uint16_t>>& data16 = base::nullopt,
- const base::Optional<std::vector<uint32_t>>& data32 = base::nullopt);
+ const absl::optional<std::vector<uint8_t>>& data8 = absl::nullopt,
+ const absl::optional<std::vector<uint16_t>>& data16 = absl::nullopt,
+ const absl::optional<std::vector<uint32_t>>& data32 = absl::nullopt);
struct DeleteDevicePropertyRequest {
Atom property{};
@@ -2180,9 +2180,9 @@ class COMPONENT_EXPORT(X11) Input {
uint32_t bytes_after{};
uint32_t num_items{};
uint8_t device_id{};
- base::Optional<std::vector<uint8_t>> data8{};
- base::Optional<std::vector<uint16_t>> data16{};
- base::Optional<std::vector<uint32_t>> data32{};
+ absl::optional<std::vector<uint8_t>> data8{};
+ absl::optional<std::vector<uint16_t>> data16{};
+ absl::optional<std::vector<uint32_t>> data32{};
};
using GetDevicePropertyResponse = Response<GetDevicePropertyReply>;
@@ -2520,9 +2520,9 @@ class COMPONENT_EXPORT(X11) Input {
Atom property{};
Atom type{};
uint32_t num_items{};
- base::Optional<std::vector<uint8_t>> data8{};
- base::Optional<std::vector<uint16_t>> data16{};
- base::Optional<std::vector<uint32_t>> data32{};
+ absl::optional<std::vector<uint8_t>> data8{};
+ absl::optional<std::vector<uint16_t>> data16{};
+ absl::optional<std::vector<uint32_t>> data32{};
};
using XIChangePropertyResponse = Response<void>;
@@ -2535,9 +2535,9 @@ class COMPONENT_EXPORT(X11) Input {
const Atom& property = {},
const Atom& type = {},
const uint32_t& num_items = {},
- const base::Optional<std::vector<uint8_t>>& data8 = base::nullopt,
- const base::Optional<std::vector<uint16_t>>& data16 = base::nullopt,
- const base::Optional<std::vector<uint32_t>>& data32 = base::nullopt);
+ const absl::optional<std::vector<uint8_t>>& data8 = absl::nullopt,
+ const absl::optional<std::vector<uint16_t>>& data16 = absl::nullopt,
+ const absl::optional<std::vector<uint32_t>>& data32 = absl::nullopt);
struct XIDeletePropertyRequest {
DeviceId deviceid{};
@@ -2565,9 +2565,9 @@ class COMPONENT_EXPORT(X11) Input {
Atom type{};
uint32_t bytes_after{};
uint32_t num_items{};
- base::Optional<std::vector<uint8_t>> data8{};
- base::Optional<std::vector<uint16_t>> data16{};
- base::Optional<std::vector<uint32_t>> data32{};
+ absl::optional<std::vector<uint8_t>> data8{};
+ absl::optional<std::vector<uint16_t>> data16{};
+ absl::optional<std::vector<uint32_t>> data32{};
};
using XIGetPropertyResponse = Response<XIGetPropertyReply>;
diff --git a/chromium/ui/gfx/x/generated_protos/xkb.cc b/chromium/ui/gfx/x/generated_protos/xkb.cc
index ebe1f194827..e623c972041 100644
--- a/chromium/ui/gfx/x/generated_protos/xkb.cc
+++ b/chromium/ui/gfx/x/generated_protos/xkb.cc
@@ -1270,28 +1270,28 @@ Future<void> Xkb::SelectEvents(
const EventType& selectAll,
const MapPart& affectMap,
const MapPart& map,
- const base::Optional<NKNDetail>& affectNewKeyboard,
- const base::Optional<NKNDetail>& newKeyboardDetails,
- const base::Optional<StatePart>& affectState,
- const base::Optional<StatePart>& stateDetails,
- const base::Optional<Control>& affectCtrls,
- const base::Optional<Control>& ctrlDetails,
- const base::Optional<uint32_t>& affectIndicatorState,
- const base::Optional<uint32_t>& indicatorStateDetails,
- const base::Optional<uint32_t>& affectIndicatorMap,
- const base::Optional<uint32_t>& indicatorMapDetails,
- const base::Optional<NameDetail>& affectNames,
- const base::Optional<NameDetail>& namesDetails,
- const base::Optional<CMDetail>& affectCompat,
- const base::Optional<CMDetail>& compatDetails,
- const base::Optional<uint8_t>& affectBell,
- const base::Optional<uint8_t>& bellDetails,
- const base::Optional<uint8_t>& affectMsgDetails,
- const base::Optional<uint8_t>& msgDetails,
- const base::Optional<AXNDetail>& affectAccessX,
- const base::Optional<AXNDetail>& accessXDetails,
- const base::Optional<XIFeature>& affectExtDev,
- const base::Optional<XIFeature>& extdevDetails) {
+ const absl::optional<NKNDetail>& affectNewKeyboard,
+ const absl::optional<NKNDetail>& newKeyboardDetails,
+ const absl::optional<StatePart>& affectState,
+ const absl::optional<StatePart>& stateDetails,
+ const absl::optional<Control>& affectCtrls,
+ const absl::optional<Control>& ctrlDetails,
+ const absl::optional<uint32_t>& affectIndicatorState,
+ const absl::optional<uint32_t>& indicatorStateDetails,
+ const absl::optional<uint32_t>& affectIndicatorMap,
+ const absl::optional<uint32_t>& indicatorMapDetails,
+ const absl::optional<NameDetail>& affectNames,
+ const absl::optional<NameDetail>& namesDetails,
+ const absl::optional<CMDetail>& affectCompat,
+ const absl::optional<CMDetail>& compatDetails,
+ const absl::optional<uint8_t>& affectBell,
+ const absl::optional<uint8_t>& bellDetails,
+ const absl::optional<uint8_t>& affectMsgDetails,
+ const absl::optional<uint8_t>& msgDetails,
+ const absl::optional<AXNDetail>& affectAccessX,
+ const absl::optional<AXNDetail>& accessXDetails,
+ const absl::optional<XIFeature>& affectExtDev,
+ const absl::optional<XIFeature>& extdevDetails) {
return Xkb::SelectEvents(Xkb::SelectEventsRequest{deviceSpec,
affectWhich,
clear,
@@ -3110,15 +3110,15 @@ Future<void> Xkb::SetMap(
const uint8_t& nVModMapKeys,
const uint8_t& totalVModMapKeys,
const VMod& virtualMods,
- const base::Optional<std::vector<SetKeyType>>& types,
- const base::Optional<std::vector<KeySymMap>>& syms,
- const base::Optional<std::vector<uint8_t>>& actionsCount,
- const base::Optional<std::vector<Action>>& actions,
- const base::Optional<std::vector<SetBehavior>>& behaviors,
- const base::Optional<std::vector<uint8_t>>& vmods,
- const base::Optional<std::vector<SetExplicit>>& c_explicit,
- const base::Optional<std::vector<KeyModMap>>& modmap,
- const base::Optional<std::vector<KeyVModMap>>& vmodmap) {
+ const absl::optional<std::vector<SetKeyType>>& types,
+ const absl::optional<std::vector<KeySymMap>>& syms,
+ const absl::optional<std::vector<uint8_t>>& actionsCount,
+ const absl::optional<std::vector<Action>>& actions,
+ const absl::optional<std::vector<SetBehavior>>& behaviors,
+ const absl::optional<std::vector<uint8_t>>& vmods,
+ const absl::optional<std::vector<SetExplicit>>& c_explicit,
+ const absl::optional<std::vector<KeyModMap>>& modmap,
+ const absl::optional<std::vector<KeyVModMap>>& vmodmap) {
return Xkb::SetMap(Xkb::SetMapRequest{deviceSpec,
flags,
minKeyCode,
@@ -4715,21 +4715,21 @@ Future<void> Xkb::SetNames(
const uint8_t& nKeys,
const uint8_t& nKeyAliases,
const uint16_t& totalKTLevelNames,
- const base::Optional<Atom>& keycodesName,
- const base::Optional<Atom>& geometryName,
- const base::Optional<Atom>& symbolsName,
- const base::Optional<Atom>& physSymbolsName,
- const base::Optional<Atom>& typesName,
- const base::Optional<Atom>& compatName,
- const base::Optional<std::vector<Atom>>& typeNames,
- const base::Optional<std::vector<uint8_t>>& nLevelsPerType,
- const base::Optional<std::vector<Atom>>& ktLevelNames,
- const base::Optional<std::vector<Atom>>& indicatorNames,
- const base::Optional<std::vector<Atom>>& virtualModNames,
- const base::Optional<std::vector<Atom>>& groups,
- const base::Optional<std::vector<KeyName>>& keyNames,
- const base::Optional<std::vector<KeyAlias>>& keyAliases,
- const base::Optional<std::vector<Atom>>& radioGroupNames) {
+ const absl::optional<Atom>& keycodesName,
+ const absl::optional<Atom>& geometryName,
+ const absl::optional<Atom>& symbolsName,
+ const absl::optional<Atom>& physSymbolsName,
+ const absl::optional<Atom>& typesName,
+ const absl::optional<Atom>& compatName,
+ const absl::optional<std::vector<Atom>>& typeNames,
+ const absl::optional<std::vector<uint8_t>>& nLevelsPerType,
+ const absl::optional<std::vector<Atom>>& ktLevelNames,
+ const absl::optional<std::vector<Atom>>& indicatorNames,
+ const absl::optional<std::vector<Atom>>& virtualModNames,
+ const absl::optional<std::vector<Atom>>& groups,
+ const absl::optional<std::vector<KeyName>>& keyNames,
+ const absl::optional<std::vector<KeyAlias>>& keyAliases,
+ const absl::optional<std::vector<Atom>>& radioGroupNames) {
return Xkb::SetNames(Xkb::SetNamesRequest{deviceSpec,
virtualMods,
firstType,
diff --git a/chromium/ui/gfx/x/generated_protos/xkb.h b/chromium/ui/gfx/x/generated_protos/xkb.h
index 7d89785b25f..7346ca1a2b4 100644
--- a/chromium/ui/gfx/x/generated_protos/xkb.h
+++ b/chromium/ui/gfx/x/generated_protos/xkb.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
@@ -1203,28 +1203,28 @@ class COMPONENT_EXPORT(X11) Xkb {
EventType selectAll{};
MapPart affectMap{};
MapPart map{};
- base::Optional<NKNDetail> affectNewKeyboard{};
- base::Optional<NKNDetail> newKeyboardDetails{};
- base::Optional<StatePart> affectState{};
- base::Optional<StatePart> stateDetails{};
- base::Optional<Control> affectCtrls{};
- base::Optional<Control> ctrlDetails{};
- base::Optional<uint32_t> affectIndicatorState{};
- base::Optional<uint32_t> indicatorStateDetails{};
- base::Optional<uint32_t> affectIndicatorMap{};
- base::Optional<uint32_t> indicatorMapDetails{};
- base::Optional<NameDetail> affectNames{};
- base::Optional<NameDetail> namesDetails{};
- base::Optional<CMDetail> affectCompat{};
- base::Optional<CMDetail> compatDetails{};
- base::Optional<uint8_t> affectBell{};
- base::Optional<uint8_t> bellDetails{};
- base::Optional<uint8_t> affectMsgDetails{};
- base::Optional<uint8_t> msgDetails{};
- base::Optional<AXNDetail> affectAccessX{};
- base::Optional<AXNDetail> accessXDetails{};
- base::Optional<XIFeature> affectExtDev{};
- base::Optional<XIFeature> extdevDetails{};
+ absl::optional<NKNDetail> affectNewKeyboard{};
+ absl::optional<NKNDetail> newKeyboardDetails{};
+ absl::optional<StatePart> affectState{};
+ absl::optional<StatePart> stateDetails{};
+ absl::optional<Control> affectCtrls{};
+ absl::optional<Control> ctrlDetails{};
+ absl::optional<uint32_t> affectIndicatorState{};
+ absl::optional<uint32_t> indicatorStateDetails{};
+ absl::optional<uint32_t> affectIndicatorMap{};
+ absl::optional<uint32_t> indicatorMapDetails{};
+ absl::optional<NameDetail> affectNames{};
+ absl::optional<NameDetail> namesDetails{};
+ absl::optional<CMDetail> affectCompat{};
+ absl::optional<CMDetail> compatDetails{};
+ absl::optional<uint8_t> affectBell{};
+ absl::optional<uint8_t> bellDetails{};
+ absl::optional<uint8_t> affectMsgDetails{};
+ absl::optional<uint8_t> msgDetails{};
+ absl::optional<AXNDetail> affectAccessX{};
+ absl::optional<AXNDetail> accessXDetails{};
+ absl::optional<XIFeature> affectExtDev{};
+ absl::optional<XIFeature> extdevDetails{};
};
using SelectEventsResponse = Response<void>;
@@ -1238,28 +1238,28 @@ class COMPONENT_EXPORT(X11) Xkb {
const EventType& selectAll = {},
const MapPart& affectMap = {},
const MapPart& map = {},
- const base::Optional<NKNDetail>& affectNewKeyboard = base::nullopt,
- const base::Optional<NKNDetail>& newKeyboardDetails = base::nullopt,
- const base::Optional<StatePart>& affectState = base::nullopt,
- const base::Optional<StatePart>& stateDetails = base::nullopt,
- const base::Optional<Control>& affectCtrls = base::nullopt,
- const base::Optional<Control>& ctrlDetails = base::nullopt,
- const base::Optional<uint32_t>& affectIndicatorState = base::nullopt,
- const base::Optional<uint32_t>& indicatorStateDetails = base::nullopt,
- const base::Optional<uint32_t>& affectIndicatorMap = base::nullopt,
- const base::Optional<uint32_t>& indicatorMapDetails = base::nullopt,
- const base::Optional<NameDetail>& affectNames = base::nullopt,
- const base::Optional<NameDetail>& namesDetails = base::nullopt,
- const base::Optional<CMDetail>& affectCompat = base::nullopt,
- const base::Optional<CMDetail>& compatDetails = base::nullopt,
- const base::Optional<uint8_t>& affectBell = base::nullopt,
- const base::Optional<uint8_t>& bellDetails = base::nullopt,
- const base::Optional<uint8_t>& affectMsgDetails = base::nullopt,
- const base::Optional<uint8_t>& msgDetails = base::nullopt,
- const base::Optional<AXNDetail>& affectAccessX = base::nullopt,
- const base::Optional<AXNDetail>& accessXDetails = base::nullopt,
- const base::Optional<XIFeature>& affectExtDev = base::nullopt,
- const base::Optional<XIFeature>& extdevDetails = base::nullopt);
+ const absl::optional<NKNDetail>& affectNewKeyboard = absl::nullopt,
+ const absl::optional<NKNDetail>& newKeyboardDetails = absl::nullopt,
+ const absl::optional<StatePart>& affectState = absl::nullopt,
+ const absl::optional<StatePart>& stateDetails = absl::nullopt,
+ const absl::optional<Control>& affectCtrls = absl::nullopt,
+ const absl::optional<Control>& ctrlDetails = absl::nullopt,
+ const absl::optional<uint32_t>& affectIndicatorState = absl::nullopt,
+ const absl::optional<uint32_t>& indicatorStateDetails = absl::nullopt,
+ const absl::optional<uint32_t>& affectIndicatorMap = absl::nullopt,
+ const absl::optional<uint32_t>& indicatorMapDetails = absl::nullopt,
+ const absl::optional<NameDetail>& affectNames = absl::nullopt,
+ const absl::optional<NameDetail>& namesDetails = absl::nullopt,
+ const absl::optional<CMDetail>& affectCompat = absl::nullopt,
+ const absl::optional<CMDetail>& compatDetails = absl::nullopt,
+ const absl::optional<uint8_t>& affectBell = absl::nullopt,
+ const absl::optional<uint8_t>& bellDetails = absl::nullopt,
+ const absl::optional<uint8_t>& affectMsgDetails = absl::nullopt,
+ const absl::optional<uint8_t>& msgDetails = absl::nullopt,
+ const absl::optional<AXNDetail>& affectAccessX = absl::nullopt,
+ const absl::optional<AXNDetail>& accessXDetails = absl::nullopt,
+ const absl::optional<XIFeature>& affectExtDev = absl::nullopt,
+ const absl::optional<XIFeature>& extdevDetails = absl::nullopt);
struct BellRequest {
DeviceSpec deviceSpec{};
@@ -1499,15 +1499,15 @@ class COMPONENT_EXPORT(X11) Xkb {
uint8_t nVModMapKeys{};
uint8_t totalVModMapKeys{};
VMod virtualMods{};
- base::Optional<std::vector<KeyType>> types_rtrn{};
- base::Optional<std::vector<KeySymMap>> syms_rtrn{};
- base::Optional<std::vector<uint8_t>> acts_rtrn_count{};
- base::Optional<std::vector<Action>> acts_rtrn_acts{};
- base::Optional<std::vector<SetBehavior>> behaviors_rtrn{};
- base::Optional<std::vector<ModMask>> vmods_rtrn{};
- base::Optional<std::vector<SetExplicit>> explicit_rtrn{};
- base::Optional<std::vector<KeyModMap>> modmap_rtrn{};
- base::Optional<std::vector<KeyVModMap>> vmodmap_rtrn{};
+ absl::optional<std::vector<KeyType>> types_rtrn{};
+ absl::optional<std::vector<KeySymMap>> syms_rtrn{};
+ absl::optional<std::vector<uint8_t>> acts_rtrn_count{};
+ absl::optional<std::vector<Action>> acts_rtrn_acts{};
+ absl::optional<std::vector<SetBehavior>> behaviors_rtrn{};
+ absl::optional<std::vector<ModMask>> vmods_rtrn{};
+ absl::optional<std::vector<SetExplicit>> explicit_rtrn{};
+ absl::optional<std::vector<KeyModMap>> modmap_rtrn{};
+ absl::optional<std::vector<KeyVModMap>> vmodmap_rtrn{};
};
using GetMapResponse = Response<GetMapReply>;
@@ -1559,15 +1559,15 @@ class COMPONENT_EXPORT(X11) Xkb {
uint8_t nVModMapKeys{};
uint8_t totalVModMapKeys{};
VMod virtualMods{};
- base::Optional<std::vector<SetKeyType>> types{};
- base::Optional<std::vector<KeySymMap>> syms{};
- base::Optional<std::vector<uint8_t>> actionsCount{};
- base::Optional<std::vector<Action>> actions{};
- base::Optional<std::vector<SetBehavior>> behaviors{};
- base::Optional<std::vector<uint8_t>> vmods{};
- base::Optional<std::vector<SetExplicit>> c_explicit{};
- base::Optional<std::vector<KeyModMap>> modmap{};
- base::Optional<std::vector<KeyVModMap>> vmodmap{};
+ absl::optional<std::vector<SetKeyType>> types{};
+ absl::optional<std::vector<KeySymMap>> syms{};
+ absl::optional<std::vector<uint8_t>> actionsCount{};
+ absl::optional<std::vector<Action>> actions{};
+ absl::optional<std::vector<SetBehavior>> behaviors{};
+ absl::optional<std::vector<uint8_t>> vmods{};
+ absl::optional<std::vector<SetExplicit>> c_explicit{};
+ absl::optional<std::vector<KeyModMap>> modmap{};
+ absl::optional<std::vector<KeyVModMap>> vmodmap{};
};
using SetMapResponse = Response<void>;
@@ -1600,16 +1600,16 @@ class COMPONENT_EXPORT(X11) Xkb {
const uint8_t& nVModMapKeys = {},
const uint8_t& totalVModMapKeys = {},
const VMod& virtualMods = {},
- const base::Optional<std::vector<SetKeyType>>& types = base::nullopt,
- const base::Optional<std::vector<KeySymMap>>& syms = base::nullopt,
- const base::Optional<std::vector<uint8_t>>& actionsCount = base::nullopt,
- const base::Optional<std::vector<Action>>& actions = base::nullopt,
- const base::Optional<std::vector<SetBehavior>>& behaviors = base::nullopt,
- const base::Optional<std::vector<uint8_t>>& vmods = base::nullopt,
- const base::Optional<std::vector<SetExplicit>>& c_explicit =
- base::nullopt,
- const base::Optional<std::vector<KeyModMap>>& modmap = base::nullopt,
- const base::Optional<std::vector<KeyVModMap>>& vmodmap = base::nullopt);
+ const absl::optional<std::vector<SetKeyType>>& types = absl::nullopt,
+ const absl::optional<std::vector<KeySymMap>>& syms = absl::nullopt,
+ const absl::optional<std::vector<uint8_t>>& actionsCount = absl::nullopt,
+ const absl::optional<std::vector<Action>>& actions = absl::nullopt,
+ const absl::optional<std::vector<SetBehavior>>& behaviors = absl::nullopt,
+ const absl::optional<std::vector<uint8_t>>& vmods = absl::nullopt,
+ const absl::optional<std::vector<SetExplicit>>& c_explicit =
+ absl::nullopt,
+ const absl::optional<std::vector<KeyModMap>>& modmap = absl::nullopt,
+ const absl::optional<std::vector<KeyVModMap>>& vmodmap = absl::nullopt);
struct GetCompatMapRequest {
DeviceSpec deviceSpec{};
@@ -1810,21 +1810,21 @@ class COMPONENT_EXPORT(X11) Xkb {
uint8_t nRadioGroups{};
uint8_t nKeyAliases{};
uint16_t nKTLevels{};
- base::Optional<Atom> keycodesName{};
- base::Optional<Atom> geometryName{};
- base::Optional<Atom> symbolsName{};
- base::Optional<Atom> physSymbolsName{};
- base::Optional<Atom> typesName{};
- base::Optional<Atom> compatName{};
- base::Optional<std::vector<Atom>> typeNames{};
- base::Optional<std::vector<uint8_t>> nLevelsPerType{};
- base::Optional<std::vector<Atom>> ktLevelNames{};
- base::Optional<std::vector<Atom>> indicatorNames{};
- base::Optional<std::vector<Atom>> virtualModNames{};
- base::Optional<std::vector<Atom>> groups{};
- base::Optional<std::vector<KeyName>> keyNames{};
- base::Optional<std::vector<KeyAlias>> keyAliases{};
- base::Optional<std::vector<Atom>> radioGroupNames{};
+ absl::optional<Atom> keycodesName{};
+ absl::optional<Atom> geometryName{};
+ absl::optional<Atom> symbolsName{};
+ absl::optional<Atom> physSymbolsName{};
+ absl::optional<Atom> typesName{};
+ absl::optional<Atom> compatName{};
+ absl::optional<std::vector<Atom>> typeNames{};
+ absl::optional<std::vector<uint8_t>> nLevelsPerType{};
+ absl::optional<std::vector<Atom>> ktLevelNames{};
+ absl::optional<std::vector<Atom>> indicatorNames{};
+ absl::optional<std::vector<Atom>> virtualModNames{};
+ absl::optional<std::vector<Atom>> groups{};
+ absl::optional<std::vector<KeyName>> keyNames{};
+ absl::optional<std::vector<KeyAlias>> keyAliases{};
+ absl::optional<std::vector<Atom>> radioGroupNames{};
};
using GetNamesResponse = Response<GetNamesReply>;
@@ -1848,21 +1848,21 @@ class COMPONENT_EXPORT(X11) Xkb {
uint8_t nKeys{};
uint8_t nKeyAliases{};
uint16_t totalKTLevelNames{};
- base::Optional<Atom> keycodesName{};
- base::Optional<Atom> geometryName{};
- base::Optional<Atom> symbolsName{};
- base::Optional<Atom> physSymbolsName{};
- base::Optional<Atom> typesName{};
- base::Optional<Atom> compatName{};
- base::Optional<std::vector<Atom>> typeNames{};
- base::Optional<std::vector<uint8_t>> nLevelsPerType{};
- base::Optional<std::vector<Atom>> ktLevelNames{};
- base::Optional<std::vector<Atom>> indicatorNames{};
- base::Optional<std::vector<Atom>> virtualModNames{};
- base::Optional<std::vector<Atom>> groups{};
- base::Optional<std::vector<KeyName>> keyNames{};
- base::Optional<std::vector<KeyAlias>> keyAliases{};
- base::Optional<std::vector<Atom>> radioGroupNames{};
+ absl::optional<Atom> keycodesName{};
+ absl::optional<Atom> geometryName{};
+ absl::optional<Atom> symbolsName{};
+ absl::optional<Atom> physSymbolsName{};
+ absl::optional<Atom> typesName{};
+ absl::optional<Atom> compatName{};
+ absl::optional<std::vector<Atom>> typeNames{};
+ absl::optional<std::vector<uint8_t>> nLevelsPerType{};
+ absl::optional<std::vector<Atom>> ktLevelNames{};
+ absl::optional<std::vector<Atom>> indicatorNames{};
+ absl::optional<std::vector<Atom>> virtualModNames{};
+ absl::optional<std::vector<Atom>> groups{};
+ absl::optional<std::vector<KeyName>> keyNames{};
+ absl::optional<std::vector<KeyAlias>> keyAliases{};
+ absl::optional<std::vector<Atom>> radioGroupNames{};
};
using SetNamesResponse = Response<void>;
@@ -1883,22 +1883,22 @@ class COMPONENT_EXPORT(X11) Xkb {
const uint8_t& nKeys = {},
const uint8_t& nKeyAliases = {},
const uint16_t& totalKTLevelNames = {},
- const base::Optional<Atom>& keycodesName = base::nullopt,
- const base::Optional<Atom>& geometryName = base::nullopt,
- const base::Optional<Atom>& symbolsName = base::nullopt,
- const base::Optional<Atom>& physSymbolsName = base::nullopt,
- const base::Optional<Atom>& typesName = base::nullopt,
- const base::Optional<Atom>& compatName = base::nullopt,
- const base::Optional<std::vector<Atom>>& typeNames = base::nullopt,
- const base::Optional<std::vector<uint8_t>>& nLevelsPerType =
- base::nullopt,
- const base::Optional<std::vector<Atom>>& ktLevelNames = base::nullopt,
- const base::Optional<std::vector<Atom>>& indicatorNames = base::nullopt,
- const base::Optional<std::vector<Atom>>& virtualModNames = base::nullopt,
- const base::Optional<std::vector<Atom>>& groups = base::nullopt,
- const base::Optional<std::vector<KeyName>>& keyNames = base::nullopt,
- const base::Optional<std::vector<KeyAlias>>& keyAliases = base::nullopt,
- const base::Optional<std::vector<Atom>>& radioGroupNames = base::nullopt);
+ const absl::optional<Atom>& keycodesName = absl::nullopt,
+ const absl::optional<Atom>& geometryName = absl::nullopt,
+ const absl::optional<Atom>& symbolsName = absl::nullopt,
+ const absl::optional<Atom>& physSymbolsName = absl::nullopt,
+ const absl::optional<Atom>& typesName = absl::nullopt,
+ const absl::optional<Atom>& compatName = absl::nullopt,
+ const absl::optional<std::vector<Atom>>& typeNames = absl::nullopt,
+ const absl::optional<std::vector<uint8_t>>& nLevelsPerType =
+ absl::nullopt,
+ const absl::optional<std::vector<Atom>>& ktLevelNames = absl::nullopt,
+ const absl::optional<std::vector<Atom>>& indicatorNames = absl::nullopt,
+ const absl::optional<std::vector<Atom>>& virtualModNames = absl::nullopt,
+ const absl::optional<std::vector<Atom>>& groups = absl::nullopt,
+ const absl::optional<std::vector<KeyName>>& keyNames = absl::nullopt,
+ const absl::optional<std::vector<KeyAlias>>& keyAliases = absl::nullopt,
+ const absl::optional<std::vector<Atom>>& radioGroupNames = absl::nullopt);
struct PerClientFlagsRequest {
DeviceSpec deviceSpec{};
@@ -2000,15 +2000,15 @@ class COMPONENT_EXPORT(X11) Xkb {
uint8_t nVModMapKeys{};
uint8_t totalVModMapKeys{};
VMod virtualMods{};
- base::Optional<std::vector<KeyType>> types_rtrn{};
- base::Optional<std::vector<KeySymMap>> syms_rtrn{};
- base::Optional<std::vector<uint8_t>> acts_rtrn_count{};
- base::Optional<std::vector<Action>> acts_rtrn_acts{};
- base::Optional<std::vector<SetBehavior>> behaviors_rtrn{};
- base::Optional<std::vector<ModMask>> vmods_rtrn{};
- base::Optional<std::vector<SetExplicit>> explicit_rtrn{};
- base::Optional<std::vector<KeyModMap>> modmap_rtrn{};
- base::Optional<std::vector<KeyVModMap>> vmodmap_rtrn{};
+ absl::optional<std::vector<KeyType>> types_rtrn{};
+ absl::optional<std::vector<KeySymMap>> syms_rtrn{};
+ absl::optional<std::vector<uint8_t>> acts_rtrn_count{};
+ absl::optional<std::vector<Action>> acts_rtrn_acts{};
+ absl::optional<std::vector<SetBehavior>> behaviors_rtrn{};
+ absl::optional<std::vector<ModMask>> vmods_rtrn{};
+ absl::optional<std::vector<SetExplicit>> explicit_rtrn{};
+ absl::optional<std::vector<KeyModMap>> modmap_rtrn{};
+ absl::optional<std::vector<KeyVModMap>> vmodmap_rtrn{};
};
struct CompatMap {
uint8_t compatmap_type{};
@@ -2046,21 +2046,21 @@ class COMPONENT_EXPORT(X11) Xkb {
uint8_t nRadioGroups{};
uint8_t nKeyAliases{};
uint16_t nKTLevels{};
- base::Optional<Atom> keycodesName{};
- base::Optional<Atom> geometryName{};
- base::Optional<Atom> symbolsName{};
- base::Optional<Atom> physSymbolsName{};
- base::Optional<Atom> typesName{};
- base::Optional<Atom> compatName{};
- base::Optional<std::vector<Atom>> typeNames{};
- base::Optional<std::vector<uint8_t>> nLevelsPerType{};
- base::Optional<std::vector<Atom>> ktLevelNames{};
- base::Optional<std::vector<Atom>> indicatorNames{};
- base::Optional<std::vector<Atom>> virtualModNames{};
- base::Optional<std::vector<Atom>> groups{};
- base::Optional<std::vector<KeyName>> keyNames{};
- base::Optional<std::vector<KeyAlias>> keyAliases{};
- base::Optional<std::vector<Atom>> radioGroupNames{};
+ absl::optional<Atom> keycodesName{};
+ absl::optional<Atom> geometryName{};
+ absl::optional<Atom> symbolsName{};
+ absl::optional<Atom> physSymbolsName{};
+ absl::optional<Atom> typesName{};
+ absl::optional<Atom> compatName{};
+ absl::optional<std::vector<Atom>> typeNames{};
+ absl::optional<std::vector<uint8_t>> nLevelsPerType{};
+ absl::optional<std::vector<Atom>> ktLevelNames{};
+ absl::optional<std::vector<Atom>> indicatorNames{};
+ absl::optional<std::vector<Atom>> virtualModNames{};
+ absl::optional<std::vector<Atom>> groups{};
+ absl::optional<std::vector<KeyName>> keyNames{};
+ absl::optional<std::vector<KeyAlias>> keyAliases{};
+ absl::optional<std::vector<Atom>> radioGroupNames{};
};
struct Geometry {
uint8_t geometry_type{};
@@ -2081,11 +2081,11 @@ class COMPONENT_EXPORT(X11) Xkb {
uint8_t labelColorNdx{};
CountedString16 labelFont{};
};
- base::Optional<Types> types{};
- base::Optional<CompatMap> compat_map{};
- base::Optional<IndicatorMaps> indicator_maps{};
- base::Optional<KeyNames> key_names{};
- base::Optional<Geometry> geometry{};
+ absl::optional<Types> types{};
+ absl::optional<CompatMap> compat_map{};
+ absl::optional<IndicatorMaps> indicator_maps{};
+ absl::optional<KeyNames> key_names{};
+ absl::optional<Geometry> geometry{};
};
using GetKbdByNameResponse = Response<GetKbdByNameReply>;
diff --git a/chromium/ui/gfx/x/generated_protos/xprint.h b/chromium/ui/gfx/x/generated_protos/xprint.h
index 0a73811aeb2..0b776aef02b 100644
--- a/chromium/ui/gfx/x/generated_protos/xprint.h
+++ b/chromium/ui/gfx/x/generated_protos/xprint.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/xproto.cc b/chromium/ui/gfx/x/generated_protos/xproto.cc
index 161d8d55500..0d8e0085de3 100644
--- a/chromium/ui/gfx/x/generated_protos/xproto.cc
+++ b/chromium/ui/gfx/x/generated_protos/xproto.cc
@@ -2968,21 +2968,21 @@ Future<void> XProto::CreateWindow(
const uint16_t& border_width,
const WindowClass& c_class,
const VisualId& visual,
- const base::Optional<Pixmap>& background_pixmap,
- const base::Optional<uint32_t>& background_pixel,
- const base::Optional<Pixmap>& border_pixmap,
- const base::Optional<uint32_t>& border_pixel,
- const base::Optional<Gravity>& bit_gravity,
- const base::Optional<Gravity>& win_gravity,
- const base::Optional<BackingStore>& backing_store,
- const base::Optional<uint32_t>& backing_planes,
- const base::Optional<uint32_t>& backing_pixel,
- const base::Optional<Bool32>& override_redirect,
- const base::Optional<Bool32>& save_under,
- const base::Optional<EventMask>& event_mask,
- const base::Optional<EventMask>& do_not_propogate_mask,
- const base::Optional<ColorMap>& colormap,
- const base::Optional<Cursor>& cursor) {
+ const absl::optional<Pixmap>& background_pixmap,
+ const absl::optional<uint32_t>& background_pixel,
+ const absl::optional<Pixmap>& border_pixmap,
+ const absl::optional<uint32_t>& border_pixel,
+ const absl::optional<Gravity>& bit_gravity,
+ const absl::optional<Gravity>& win_gravity,
+ const absl::optional<BackingStore>& backing_store,
+ const absl::optional<uint32_t>& backing_planes,
+ const absl::optional<uint32_t>& backing_pixel,
+ const absl::optional<Bool32>& override_redirect,
+ const absl::optional<Bool32>& save_under,
+ const absl::optional<EventMask>& event_mask,
+ const absl::optional<EventMask>& do_not_propogate_mask,
+ const absl::optional<ColorMap>& colormap,
+ const absl::optional<Cursor>& cursor) {
return XProto::CreateWindow(CreateWindowRequest{depth,
wid,
parent,
@@ -3180,21 +3180,21 @@ Future<void> XProto::ChangeWindowAttributes(
Future<void> XProto::ChangeWindowAttributes(
const Window& window,
- const base::Optional<Pixmap>& background_pixmap,
- const base::Optional<uint32_t>& background_pixel,
- const base::Optional<Pixmap>& border_pixmap,
- const base::Optional<uint32_t>& border_pixel,
- const base::Optional<Gravity>& bit_gravity,
- const base::Optional<Gravity>& win_gravity,
- const base::Optional<BackingStore>& backing_store,
- const base::Optional<uint32_t>& backing_planes,
- const base::Optional<uint32_t>& backing_pixel,
- const base::Optional<Bool32>& override_redirect,
- const base::Optional<Bool32>& save_under,
- const base::Optional<EventMask>& event_mask,
- const base::Optional<EventMask>& do_not_propogate_mask,
- const base::Optional<ColorMap>& colormap,
- const base::Optional<Cursor>& cursor) {
+ const absl::optional<Pixmap>& background_pixmap,
+ const absl::optional<uint32_t>& background_pixel,
+ const absl::optional<Pixmap>& border_pixmap,
+ const absl::optional<uint32_t>& border_pixel,
+ const absl::optional<Gravity>& bit_gravity,
+ const absl::optional<Gravity>& win_gravity,
+ const absl::optional<BackingStore>& backing_store,
+ const absl::optional<uint32_t>& backing_planes,
+ const absl::optional<uint32_t>& backing_pixel,
+ const absl::optional<Bool32>& override_redirect,
+ const absl::optional<Bool32>& save_under,
+ const absl::optional<EventMask>& event_mask,
+ const absl::optional<EventMask>& do_not_propogate_mask,
+ const absl::optional<ColorMap>& colormap,
+ const absl::optional<Cursor>& cursor) {
return XProto::ChangeWindowAttributes(ChangeWindowAttributesRequest{
window, background_pixmap, background_pixel, border_pixmap, border_pixel,
bit_gravity, win_gravity, backing_store, backing_planes, backing_pixel,
@@ -3706,13 +3706,13 @@ Future<void> XProto::ConfigureWindow(const ConfigureWindowRequest& request) {
Future<void> XProto::ConfigureWindow(
const Window& window,
- const base::Optional<int32_t>& x,
- const base::Optional<int32_t>& y,
- const base::Optional<uint32_t>& width,
- const base::Optional<uint32_t>& height,
- const base::Optional<uint32_t>& border_width,
- const base::Optional<Window>& sibling,
- const base::Optional<StackMode>& stack_mode) {
+ const absl::optional<int32_t>& x,
+ const absl::optional<int32_t>& y,
+ const absl::optional<uint32_t>& width,
+ const absl::optional<uint32_t>& height,
+ const absl::optional<uint32_t>& border_width,
+ const absl::optional<Window>& sibling,
+ const absl::optional<StackMode>& stack_mode) {
return XProto::ConfigureWindow(ConfigureWindowRequest{
window, x, y, width, height, border_width, sibling, stack_mode});
}
@@ -6915,29 +6915,29 @@ Future<void> XProto::CreateGC(const CreateGCRequest& request) {
Future<void> XProto::CreateGC(
const GraphicsContext& cid,
const Drawable& drawable,
- const base::Optional<Gx>& function,
- const base::Optional<uint32_t>& plane_mask,
- const base::Optional<uint32_t>& foreground,
- const base::Optional<uint32_t>& background,
- const base::Optional<uint32_t>& line_width,
- const base::Optional<LineStyle>& line_style,
- const base::Optional<CapStyle>& cap_style,
- const base::Optional<JoinStyle>& join_style,
- const base::Optional<FillStyle>& fill_style,
- const base::Optional<FillRule>& fill_rule,
- const base::Optional<Pixmap>& tile,
- const base::Optional<Pixmap>& stipple,
- const base::Optional<int32_t>& tile_stipple_x_origin,
- const base::Optional<int32_t>& tile_stipple_y_origin,
- const base::Optional<Font>& font,
- const base::Optional<SubwindowMode>& subwindow_mode,
- const base::Optional<Bool32>& graphics_exposures,
- const base::Optional<int32_t>& clip_x_origin,
- const base::Optional<int32_t>& clip_y_origin,
- const base::Optional<Pixmap>& clip_mask,
- const base::Optional<uint32_t>& dash_offset,
- const base::Optional<uint32_t>& dashes,
- const base::Optional<ArcMode>& arc_mode) {
+ const absl::optional<Gx>& function,
+ const absl::optional<uint32_t>& plane_mask,
+ const absl::optional<uint32_t>& foreground,
+ const absl::optional<uint32_t>& background,
+ const absl::optional<uint32_t>& line_width,
+ const absl::optional<LineStyle>& line_style,
+ const absl::optional<CapStyle>& cap_style,
+ const absl::optional<JoinStyle>& join_style,
+ const absl::optional<FillStyle>& fill_style,
+ const absl::optional<FillRule>& fill_rule,
+ const absl::optional<Pixmap>& tile,
+ const absl::optional<Pixmap>& stipple,
+ const absl::optional<int32_t>& tile_stipple_x_origin,
+ const absl::optional<int32_t>& tile_stipple_y_origin,
+ const absl::optional<Font>& font,
+ const absl::optional<SubwindowMode>& subwindow_mode,
+ const absl::optional<Bool32>& graphics_exposures,
+ const absl::optional<int32_t>& clip_x_origin,
+ const absl::optional<int32_t>& clip_y_origin,
+ const absl::optional<Pixmap>& clip_mask,
+ const absl::optional<uint32_t>& dash_offset,
+ const absl::optional<uint32_t>& dashes,
+ const absl::optional<ArcMode>& arc_mode) {
return XProto::CreateGC(CreateGCRequest{cid,
drawable,
function,
@@ -7204,29 +7204,29 @@ Future<void> XProto::ChangeGC(const ChangeGCRequest& request) {
Future<void> XProto::ChangeGC(
const GraphicsContext& gc,
- const base::Optional<Gx>& function,
- const base::Optional<uint32_t>& plane_mask,
- const base::Optional<uint32_t>& foreground,
- const base::Optional<uint32_t>& background,
- const base::Optional<uint32_t>& line_width,
- const base::Optional<LineStyle>& line_style,
- const base::Optional<CapStyle>& cap_style,
- const base::Optional<JoinStyle>& join_style,
- const base::Optional<FillStyle>& fill_style,
- const base::Optional<FillRule>& fill_rule,
- const base::Optional<Pixmap>& tile,
- const base::Optional<Pixmap>& stipple,
- const base::Optional<int32_t>& tile_stipple_x_origin,
- const base::Optional<int32_t>& tile_stipple_y_origin,
- const base::Optional<Font>& font,
- const base::Optional<SubwindowMode>& subwindow_mode,
- const base::Optional<Bool32>& graphics_exposures,
- const base::Optional<int32_t>& clip_x_origin,
- const base::Optional<int32_t>& clip_y_origin,
- const base::Optional<Pixmap>& clip_mask,
- const base::Optional<uint32_t>& dash_offset,
- const base::Optional<uint32_t>& dashes,
- const base::Optional<ArcMode>& arc_mode) {
+ const absl::optional<Gx>& function,
+ const absl::optional<uint32_t>& plane_mask,
+ const absl::optional<uint32_t>& foreground,
+ const absl::optional<uint32_t>& background,
+ const absl::optional<uint32_t>& line_width,
+ const absl::optional<LineStyle>& line_style,
+ const absl::optional<CapStyle>& cap_style,
+ const absl::optional<JoinStyle>& join_style,
+ const absl::optional<FillStyle>& fill_style,
+ const absl::optional<FillRule>& fill_rule,
+ const absl::optional<Pixmap>& tile,
+ const absl::optional<Pixmap>& stipple,
+ const absl::optional<int32_t>& tile_stipple_x_origin,
+ const absl::optional<int32_t>& tile_stipple_y_origin,
+ const absl::optional<Font>& font,
+ const absl::optional<SubwindowMode>& subwindow_mode,
+ const absl::optional<Bool32>& graphics_exposures,
+ const absl::optional<int32_t>& clip_x_origin,
+ const absl::optional<int32_t>& clip_y_origin,
+ const absl::optional<Pixmap>& clip_mask,
+ const absl::optional<uint32_t>& dash_offset,
+ const absl::optional<uint32_t>& dashes,
+ const absl::optional<ArcMode>& arc_mode) {
return XProto::ChangeGC(ChangeGCRequest{gc,
function,
plane_mask,
@@ -10410,14 +10410,14 @@ Future<void> XProto::ChangeKeyboardControl(
}
Future<void> XProto::ChangeKeyboardControl(
- const base::Optional<int32_t>& key_click_percent,
- const base::Optional<int32_t>& bell_percent,
- const base::Optional<int32_t>& bell_pitch,
- const base::Optional<int32_t>& bell_duration,
- const base::Optional<uint32_t>& led,
- const base::Optional<LedMode>& led_mode,
- const base::Optional<KeyCode32>& key,
- const base::Optional<AutoRepeatMode>& auto_repeat_mode) {
+ const absl::optional<int32_t>& key_click_percent,
+ const absl::optional<int32_t>& bell_percent,
+ const absl::optional<int32_t>& bell_pitch,
+ const absl::optional<int32_t>& bell_duration,
+ const absl::optional<uint32_t>& led,
+ const absl::optional<LedMode>& led_mode,
+ const absl::optional<KeyCode32>& key,
+ const absl::optional<AutoRepeatMode>& auto_repeat_mode) {
return XProto::ChangeKeyboardControl(ChangeKeyboardControlRequest{
key_click_percent, bell_percent, bell_pitch, bell_duration, led, led_mode,
key, auto_repeat_mode});
diff --git a/chromium/ui/gfx/x/generated_protos/xproto.h b/chromium/ui/gfx/x/generated_protos/xproto.h
index 3dfa0bc6fbe..fef9551761d 100644
--- a/chromium/ui/gfx/x/generated_protos/xproto.h
+++ b/chromium/ui/gfx/x/generated_protos/xproto.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
@@ -1453,42 +1453,42 @@ struct CreateWindowRequest {
uint16_t border_width{};
WindowClass c_class{};
VisualId visual{};
- base::Optional<Pixmap> background_pixmap{};
- base::Optional<uint32_t> background_pixel{};
- base::Optional<Pixmap> border_pixmap{};
- base::Optional<uint32_t> border_pixel{};
- base::Optional<Gravity> bit_gravity{};
- base::Optional<Gravity> win_gravity{};
- base::Optional<BackingStore> backing_store{};
- base::Optional<uint32_t> backing_planes{};
- base::Optional<uint32_t> backing_pixel{};
- base::Optional<Bool32> override_redirect{};
- base::Optional<Bool32> save_under{};
- base::Optional<EventMask> event_mask{};
- base::Optional<EventMask> do_not_propogate_mask{};
- base::Optional<ColorMap> colormap{};
- base::Optional<Cursor> cursor{};
+ absl::optional<Pixmap> background_pixmap{};
+ absl::optional<uint32_t> background_pixel{};
+ absl::optional<Pixmap> border_pixmap{};
+ absl::optional<uint32_t> border_pixel{};
+ absl::optional<Gravity> bit_gravity{};
+ absl::optional<Gravity> win_gravity{};
+ absl::optional<BackingStore> backing_store{};
+ absl::optional<uint32_t> backing_planes{};
+ absl::optional<uint32_t> backing_pixel{};
+ absl::optional<Bool32> override_redirect{};
+ absl::optional<Bool32> save_under{};
+ absl::optional<EventMask> event_mask{};
+ absl::optional<EventMask> do_not_propogate_mask{};
+ absl::optional<ColorMap> colormap{};
+ absl::optional<Cursor> cursor{};
};
using CreateWindowResponse = Response<void>;
struct ChangeWindowAttributesRequest {
Window window{};
- base::Optional<Pixmap> background_pixmap{};
- base::Optional<uint32_t> background_pixel{};
- base::Optional<Pixmap> border_pixmap{};
- base::Optional<uint32_t> border_pixel{};
- base::Optional<Gravity> bit_gravity{};
- base::Optional<Gravity> win_gravity{};
- base::Optional<BackingStore> backing_store{};
- base::Optional<uint32_t> backing_planes{};
- base::Optional<uint32_t> backing_pixel{};
- base::Optional<Bool32> override_redirect{};
- base::Optional<Bool32> save_under{};
- base::Optional<EventMask> event_mask{};
- base::Optional<EventMask> do_not_propogate_mask{};
- base::Optional<ColorMap> colormap{};
- base::Optional<Cursor> cursor{};
+ absl::optional<Pixmap> background_pixmap{};
+ absl::optional<uint32_t> background_pixel{};
+ absl::optional<Pixmap> border_pixmap{};
+ absl::optional<uint32_t> border_pixel{};
+ absl::optional<Gravity> bit_gravity{};
+ absl::optional<Gravity> win_gravity{};
+ absl::optional<BackingStore> backing_store{};
+ absl::optional<uint32_t> backing_planes{};
+ absl::optional<uint32_t> backing_pixel{};
+ absl::optional<Bool32> override_redirect{};
+ absl::optional<Bool32> save_under{};
+ absl::optional<EventMask> event_mask{};
+ absl::optional<EventMask> do_not_propogate_mask{};
+ absl::optional<ColorMap> colormap{};
+ absl::optional<Cursor> cursor{};
};
using ChangeWindowAttributesResponse = Response<void>;
@@ -1572,13 +1572,13 @@ using UnmapSubwindowsResponse = Response<void>;
struct ConfigureWindowRequest {
Window window{};
- base::Optional<int32_t> x{};
- base::Optional<int32_t> y{};
- base::Optional<uint32_t> width{};
- base::Optional<uint32_t> height{};
- base::Optional<uint32_t> border_width{};
- base::Optional<Window> sibling{};
- base::Optional<StackMode> stack_mode{};
+ absl::optional<int32_t> x{};
+ absl::optional<int32_t> y{};
+ absl::optional<uint32_t> width{};
+ absl::optional<uint32_t> height{};
+ absl::optional<uint32_t> border_width{};
+ absl::optional<Window> sibling{};
+ absl::optional<StackMode> stack_mode{};
};
using ConfigureWindowResponse = Response<void>;
@@ -2054,58 +2054,58 @@ using FreePixmapResponse = Response<void>;
struct CreateGCRequest {
GraphicsContext cid{};
Drawable drawable{};
- base::Optional<Gx> function{};
- base::Optional<uint32_t> plane_mask{};
- base::Optional<uint32_t> foreground{};
- base::Optional<uint32_t> background{};
- base::Optional<uint32_t> line_width{};
- base::Optional<LineStyle> line_style{};
- base::Optional<CapStyle> cap_style{};
- base::Optional<JoinStyle> join_style{};
- base::Optional<FillStyle> fill_style{};
- base::Optional<FillRule> fill_rule{};
- base::Optional<Pixmap> tile{};
- base::Optional<Pixmap> stipple{};
- base::Optional<int32_t> tile_stipple_x_origin{};
- base::Optional<int32_t> tile_stipple_y_origin{};
- base::Optional<Font> font{};
- base::Optional<SubwindowMode> subwindow_mode{};
- base::Optional<Bool32> graphics_exposures{};
- base::Optional<int32_t> clip_x_origin{};
- base::Optional<int32_t> clip_y_origin{};
- base::Optional<Pixmap> clip_mask{};
- base::Optional<uint32_t> dash_offset{};
- base::Optional<uint32_t> dashes{};
- base::Optional<ArcMode> arc_mode{};
+ absl::optional<Gx> function{};
+ absl::optional<uint32_t> plane_mask{};
+ absl::optional<uint32_t> foreground{};
+ absl::optional<uint32_t> background{};
+ absl::optional<uint32_t> line_width{};
+ absl::optional<LineStyle> line_style{};
+ absl::optional<CapStyle> cap_style{};
+ absl::optional<JoinStyle> join_style{};
+ absl::optional<FillStyle> fill_style{};
+ absl::optional<FillRule> fill_rule{};
+ absl::optional<Pixmap> tile{};
+ absl::optional<Pixmap> stipple{};
+ absl::optional<int32_t> tile_stipple_x_origin{};
+ absl::optional<int32_t> tile_stipple_y_origin{};
+ absl::optional<Font> font{};
+ absl::optional<SubwindowMode> subwindow_mode{};
+ absl::optional<Bool32> graphics_exposures{};
+ absl::optional<int32_t> clip_x_origin{};
+ absl::optional<int32_t> clip_y_origin{};
+ absl::optional<Pixmap> clip_mask{};
+ absl::optional<uint32_t> dash_offset{};
+ absl::optional<uint32_t> dashes{};
+ absl::optional<ArcMode> arc_mode{};
};
using CreateGCResponse = Response<void>;
struct ChangeGCRequest {
GraphicsContext gc{};
- base::Optional<Gx> function{};
- base::Optional<uint32_t> plane_mask{};
- base::Optional<uint32_t> foreground{};
- base::Optional<uint32_t> background{};
- base::Optional<uint32_t> line_width{};
- base::Optional<LineStyle> line_style{};
- base::Optional<CapStyle> cap_style{};
- base::Optional<JoinStyle> join_style{};
- base::Optional<FillStyle> fill_style{};
- base::Optional<FillRule> fill_rule{};
- base::Optional<Pixmap> tile{};
- base::Optional<Pixmap> stipple{};
- base::Optional<int32_t> tile_stipple_x_origin{};
- base::Optional<int32_t> tile_stipple_y_origin{};
- base::Optional<Font> font{};
- base::Optional<SubwindowMode> subwindow_mode{};
- base::Optional<Bool32> graphics_exposures{};
- base::Optional<int32_t> clip_x_origin{};
- base::Optional<int32_t> clip_y_origin{};
- base::Optional<Pixmap> clip_mask{};
- base::Optional<uint32_t> dash_offset{};
- base::Optional<uint32_t> dashes{};
- base::Optional<ArcMode> arc_mode{};
+ absl::optional<Gx> function{};
+ absl::optional<uint32_t> plane_mask{};
+ absl::optional<uint32_t> foreground{};
+ absl::optional<uint32_t> background{};
+ absl::optional<uint32_t> line_width{};
+ absl::optional<LineStyle> line_style{};
+ absl::optional<CapStyle> cap_style{};
+ absl::optional<JoinStyle> join_style{};
+ absl::optional<FillStyle> fill_style{};
+ absl::optional<FillRule> fill_rule{};
+ absl::optional<Pixmap> tile{};
+ absl::optional<Pixmap> stipple{};
+ absl::optional<int32_t> tile_stipple_x_origin{};
+ absl::optional<int32_t> tile_stipple_y_origin{};
+ absl::optional<Font> font{};
+ absl::optional<SubwindowMode> subwindow_mode{};
+ absl::optional<Bool32> graphics_exposures{};
+ absl::optional<int32_t> clip_x_origin{};
+ absl::optional<int32_t> clip_y_origin{};
+ absl::optional<Pixmap> clip_mask{};
+ absl::optional<uint32_t> dash_offset{};
+ absl::optional<uint32_t> dashes{};
+ absl::optional<ArcMode> arc_mode{};
};
using ChangeGCResponse = Response<void>;
@@ -2602,14 +2602,14 @@ struct GetKeyboardMappingReply {
using GetKeyboardMappingResponse = Response<GetKeyboardMappingReply>;
struct ChangeKeyboardControlRequest {
- base::Optional<int32_t> key_click_percent{};
- base::Optional<int32_t> bell_percent{};
- base::Optional<int32_t> bell_pitch{};
- base::Optional<int32_t> bell_duration{};
- base::Optional<uint32_t> led{};
- base::Optional<LedMode> led_mode{};
- base::Optional<KeyCode32> key{};
- base::Optional<AutoRepeatMode> auto_repeat_mode{};
+ absl::optional<int32_t> key_click_percent{};
+ absl::optional<int32_t> bell_percent{};
+ absl::optional<int32_t> bell_pitch{};
+ absl::optional<int32_t> bell_duration{};
+ absl::optional<uint32_t> led{};
+ absl::optional<LedMode> led_mode{};
+ absl::optional<KeyCode32> key{};
+ absl::optional<AutoRepeatMode> auto_repeat_mode{};
};
using ChangeKeyboardControlResponse = Response<void>;
@@ -2792,42 +2792,42 @@ class COMPONENT_EXPORT(X11) XProto {
const uint16_t& border_width = {},
const WindowClass& c_class = {},
const VisualId& visual = {},
- const base::Optional<Pixmap>& background_pixmap = base::nullopt,
- const base::Optional<uint32_t>& background_pixel = base::nullopt,
- const base::Optional<Pixmap>& border_pixmap = base::nullopt,
- const base::Optional<uint32_t>& border_pixel = base::nullopt,
- const base::Optional<Gravity>& bit_gravity = base::nullopt,
- const base::Optional<Gravity>& win_gravity = base::nullopt,
- const base::Optional<BackingStore>& backing_store = base::nullopt,
- const base::Optional<uint32_t>& backing_planes = base::nullopt,
- const base::Optional<uint32_t>& backing_pixel = base::nullopt,
- const base::Optional<Bool32>& override_redirect = base::nullopt,
- const base::Optional<Bool32>& save_under = base::nullopt,
- const base::Optional<EventMask>& event_mask = base::nullopt,
- const base::Optional<EventMask>& do_not_propogate_mask = base::nullopt,
- const base::Optional<ColorMap>& colormap = base::nullopt,
- const base::Optional<Cursor>& cursor = base::nullopt);
+ const absl::optional<Pixmap>& background_pixmap = absl::nullopt,
+ const absl::optional<uint32_t>& background_pixel = absl::nullopt,
+ const absl::optional<Pixmap>& border_pixmap = absl::nullopt,
+ const absl::optional<uint32_t>& border_pixel = absl::nullopt,
+ const absl::optional<Gravity>& bit_gravity = absl::nullopt,
+ const absl::optional<Gravity>& win_gravity = absl::nullopt,
+ const absl::optional<BackingStore>& backing_store = absl::nullopt,
+ const absl::optional<uint32_t>& backing_planes = absl::nullopt,
+ const absl::optional<uint32_t>& backing_pixel = absl::nullopt,
+ const absl::optional<Bool32>& override_redirect = absl::nullopt,
+ const absl::optional<Bool32>& save_under = absl::nullopt,
+ const absl::optional<EventMask>& event_mask = absl::nullopt,
+ const absl::optional<EventMask>& do_not_propogate_mask = absl::nullopt,
+ const absl::optional<ColorMap>& colormap = absl::nullopt,
+ const absl::optional<Cursor>& cursor = absl::nullopt);
Future<void> ChangeWindowAttributes(
const ChangeWindowAttributesRequest& request);
Future<void> ChangeWindowAttributes(
const Window& window = {},
- const base::Optional<Pixmap>& background_pixmap = base::nullopt,
- const base::Optional<uint32_t>& background_pixel = base::nullopt,
- const base::Optional<Pixmap>& border_pixmap = base::nullopt,
- const base::Optional<uint32_t>& border_pixel = base::nullopt,
- const base::Optional<Gravity>& bit_gravity = base::nullopt,
- const base::Optional<Gravity>& win_gravity = base::nullopt,
- const base::Optional<BackingStore>& backing_store = base::nullopt,
- const base::Optional<uint32_t>& backing_planes = base::nullopt,
- const base::Optional<uint32_t>& backing_pixel = base::nullopt,
- const base::Optional<Bool32>& override_redirect = base::nullopt,
- const base::Optional<Bool32>& save_under = base::nullopt,
- const base::Optional<EventMask>& event_mask = base::nullopt,
- const base::Optional<EventMask>& do_not_propogate_mask = base::nullopt,
- const base::Optional<ColorMap>& colormap = base::nullopt,
- const base::Optional<Cursor>& cursor = base::nullopt);
+ const absl::optional<Pixmap>& background_pixmap = absl::nullopt,
+ const absl::optional<uint32_t>& background_pixel = absl::nullopt,
+ const absl::optional<Pixmap>& border_pixmap = absl::nullopt,
+ const absl::optional<uint32_t>& border_pixel = absl::nullopt,
+ const absl::optional<Gravity>& bit_gravity = absl::nullopt,
+ const absl::optional<Gravity>& win_gravity = absl::nullopt,
+ const absl::optional<BackingStore>& backing_store = absl::nullopt,
+ const absl::optional<uint32_t>& backing_planes = absl::nullopt,
+ const absl::optional<uint32_t>& backing_pixel = absl::nullopt,
+ const absl::optional<Bool32>& override_redirect = absl::nullopt,
+ const absl::optional<Bool32>& save_under = absl::nullopt,
+ const absl::optional<EventMask>& event_mask = absl::nullopt,
+ const absl::optional<EventMask>& do_not_propogate_mask = absl::nullopt,
+ const absl::optional<ColorMap>& colormap = absl::nullopt,
+ const absl::optional<Cursor>& cursor = absl::nullopt);
Future<GetWindowAttributesReply> GetWindowAttributes(
const GetWindowAttributesRequest& request);
@@ -2875,13 +2875,13 @@ class COMPONENT_EXPORT(X11) XProto {
Future<void> ConfigureWindow(
const Window& window = {},
- const base::Optional<int32_t>& x = base::nullopt,
- const base::Optional<int32_t>& y = base::nullopt,
- const base::Optional<uint32_t>& width = base::nullopt,
- const base::Optional<uint32_t>& height = base::nullopt,
- const base::Optional<uint32_t>& border_width = base::nullopt,
- const base::Optional<Window>& sibling = base::nullopt,
- const base::Optional<StackMode>& stack_mode = base::nullopt);
+ const absl::optional<int32_t>& x = absl::nullopt,
+ const absl::optional<int32_t>& y = absl::nullopt,
+ const absl::optional<uint32_t>& width = absl::nullopt,
+ const absl::optional<uint32_t>& height = absl::nullopt,
+ const absl::optional<uint32_t>& border_width = absl::nullopt,
+ const absl::optional<Window>& sibling = absl::nullopt,
+ const absl::optional<StackMode>& stack_mode = absl::nullopt);
Future<void> CirculateWindow(const CirculateWindowRequest& request);
@@ -3141,57 +3141,57 @@ class COMPONENT_EXPORT(X11) XProto {
Future<void> CreateGC(
const GraphicsContext& cid = {},
const Drawable& drawable = {},
- const base::Optional<Gx>& function = base::nullopt,
- const base::Optional<uint32_t>& plane_mask = base::nullopt,
- const base::Optional<uint32_t>& foreground = base::nullopt,
- const base::Optional<uint32_t>& background = base::nullopt,
- const base::Optional<uint32_t>& line_width = base::nullopt,
- const base::Optional<LineStyle>& line_style = base::nullopt,
- const base::Optional<CapStyle>& cap_style = base::nullopt,
- const base::Optional<JoinStyle>& join_style = base::nullopt,
- const base::Optional<FillStyle>& fill_style = base::nullopt,
- const base::Optional<FillRule>& fill_rule = base::nullopt,
- const base::Optional<Pixmap>& tile = base::nullopt,
- const base::Optional<Pixmap>& stipple = base::nullopt,
- const base::Optional<int32_t>& tile_stipple_x_origin = base::nullopt,
- const base::Optional<int32_t>& tile_stipple_y_origin = base::nullopt,
- const base::Optional<Font>& font = base::nullopt,
- const base::Optional<SubwindowMode>& subwindow_mode = base::nullopt,
- const base::Optional<Bool32>& graphics_exposures = base::nullopt,
- const base::Optional<int32_t>& clip_x_origin = base::nullopt,
- const base::Optional<int32_t>& clip_y_origin = base::nullopt,
- const base::Optional<Pixmap>& clip_mask = base::nullopt,
- const base::Optional<uint32_t>& dash_offset = base::nullopt,
- const base::Optional<uint32_t>& dashes = base::nullopt,
- const base::Optional<ArcMode>& arc_mode = base::nullopt);
+ const absl::optional<Gx>& function = absl::nullopt,
+ const absl::optional<uint32_t>& plane_mask = absl::nullopt,
+ const absl::optional<uint32_t>& foreground = absl::nullopt,
+ const absl::optional<uint32_t>& background = absl::nullopt,
+ const absl::optional<uint32_t>& line_width = absl::nullopt,
+ const absl::optional<LineStyle>& line_style = absl::nullopt,
+ const absl::optional<CapStyle>& cap_style = absl::nullopt,
+ const absl::optional<JoinStyle>& join_style = absl::nullopt,
+ const absl::optional<FillStyle>& fill_style = absl::nullopt,
+ const absl::optional<FillRule>& fill_rule = absl::nullopt,
+ const absl::optional<Pixmap>& tile = absl::nullopt,
+ const absl::optional<Pixmap>& stipple = absl::nullopt,
+ const absl::optional<int32_t>& tile_stipple_x_origin = absl::nullopt,
+ const absl::optional<int32_t>& tile_stipple_y_origin = absl::nullopt,
+ const absl::optional<Font>& font = absl::nullopt,
+ const absl::optional<SubwindowMode>& subwindow_mode = absl::nullopt,
+ const absl::optional<Bool32>& graphics_exposures = absl::nullopt,
+ const absl::optional<int32_t>& clip_x_origin = absl::nullopt,
+ const absl::optional<int32_t>& clip_y_origin = absl::nullopt,
+ const absl::optional<Pixmap>& clip_mask = absl::nullopt,
+ const absl::optional<uint32_t>& dash_offset = absl::nullopt,
+ const absl::optional<uint32_t>& dashes = absl::nullopt,
+ const absl::optional<ArcMode>& arc_mode = absl::nullopt);
Future<void> ChangeGC(const ChangeGCRequest& request);
Future<void> ChangeGC(
const GraphicsContext& gc = {},
- const base::Optional<Gx>& function = base::nullopt,
- const base::Optional<uint32_t>& plane_mask = base::nullopt,
- const base::Optional<uint32_t>& foreground = base::nullopt,
- const base::Optional<uint32_t>& background = base::nullopt,
- const base::Optional<uint32_t>& line_width = base::nullopt,
- const base::Optional<LineStyle>& line_style = base::nullopt,
- const base::Optional<CapStyle>& cap_style = base::nullopt,
- const base::Optional<JoinStyle>& join_style = base::nullopt,
- const base::Optional<FillStyle>& fill_style = base::nullopt,
- const base::Optional<FillRule>& fill_rule = base::nullopt,
- const base::Optional<Pixmap>& tile = base::nullopt,
- const base::Optional<Pixmap>& stipple = base::nullopt,
- const base::Optional<int32_t>& tile_stipple_x_origin = base::nullopt,
- const base::Optional<int32_t>& tile_stipple_y_origin = base::nullopt,
- const base::Optional<Font>& font = base::nullopt,
- const base::Optional<SubwindowMode>& subwindow_mode = base::nullopt,
- const base::Optional<Bool32>& graphics_exposures = base::nullopt,
- const base::Optional<int32_t>& clip_x_origin = base::nullopt,
- const base::Optional<int32_t>& clip_y_origin = base::nullopt,
- const base::Optional<Pixmap>& clip_mask = base::nullopt,
- const base::Optional<uint32_t>& dash_offset = base::nullopt,
- const base::Optional<uint32_t>& dashes = base::nullopt,
- const base::Optional<ArcMode>& arc_mode = base::nullopt);
+ const absl::optional<Gx>& function = absl::nullopt,
+ const absl::optional<uint32_t>& plane_mask = absl::nullopt,
+ const absl::optional<uint32_t>& foreground = absl::nullopt,
+ const absl::optional<uint32_t>& background = absl::nullopt,
+ const absl::optional<uint32_t>& line_width = absl::nullopt,
+ const absl::optional<LineStyle>& line_style = absl::nullopt,
+ const absl::optional<CapStyle>& cap_style = absl::nullopt,
+ const absl::optional<JoinStyle>& join_style = absl::nullopt,
+ const absl::optional<FillStyle>& fill_style = absl::nullopt,
+ const absl::optional<FillRule>& fill_rule = absl::nullopt,
+ const absl::optional<Pixmap>& tile = absl::nullopt,
+ const absl::optional<Pixmap>& stipple = absl::nullopt,
+ const absl::optional<int32_t>& tile_stipple_x_origin = absl::nullopt,
+ const absl::optional<int32_t>& tile_stipple_y_origin = absl::nullopt,
+ const absl::optional<Font>& font = absl::nullopt,
+ const absl::optional<SubwindowMode>& subwindow_mode = absl::nullopt,
+ const absl::optional<Bool32>& graphics_exposures = absl::nullopt,
+ const absl::optional<int32_t>& clip_x_origin = absl::nullopt,
+ const absl::optional<int32_t>& clip_y_origin = absl::nullopt,
+ const absl::optional<Pixmap>& clip_mask = absl::nullopt,
+ const absl::optional<uint32_t>& dash_offset = absl::nullopt,
+ const absl::optional<uint32_t>& dashes = absl::nullopt,
+ const absl::optional<ArcMode>& arc_mode = absl::nullopt);
Future<void> CopyGC(const CopyGCRequest& request);
@@ -3526,14 +3526,14 @@ class COMPONENT_EXPORT(X11) XProto {
const ChangeKeyboardControlRequest& request);
Future<void> ChangeKeyboardControl(
- const base::Optional<int32_t>& key_click_percent = base::nullopt,
- const base::Optional<int32_t>& bell_percent = base::nullopt,
- const base::Optional<int32_t>& bell_pitch = base::nullopt,
- const base::Optional<int32_t>& bell_duration = base::nullopt,
- const base::Optional<uint32_t>& led = base::nullopt,
- const base::Optional<LedMode>& led_mode = base::nullopt,
- const base::Optional<KeyCode32>& key = base::nullopt,
- const base::Optional<AutoRepeatMode>& auto_repeat_mode = base::nullopt);
+ const absl::optional<int32_t>& key_click_percent = absl::nullopt,
+ const absl::optional<int32_t>& bell_percent = absl::nullopt,
+ const absl::optional<int32_t>& bell_pitch = absl::nullopt,
+ const absl::optional<int32_t>& bell_duration = absl::nullopt,
+ const absl::optional<uint32_t>& led = absl::nullopt,
+ const absl::optional<LedMode>& led_mode = absl::nullopt,
+ const absl::optional<KeyCode32>& key = absl::nullopt,
+ const absl::optional<AutoRepeatMode>& auto_repeat_mode = absl::nullopt);
Future<GetKeyboardControlReply> GetKeyboardControl(
const GetKeyboardControlRequest& request);
diff --git a/chromium/ui/gfx/x/generated_protos/xselinux.h b/chromium/ui/gfx/x/generated_protos/xselinux.h
index bd5e30ffc0b..172395a9fb0 100644
--- a/chromium/ui/gfx/x/generated_protos/xselinux.h
+++ b/chromium/ui/gfx/x/generated_protos/xselinux.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/xtest.h b/chromium/ui/gfx/x/generated_protos/xtest.h
index 492c9e9ba50..b987f5361f7 100644
--- a/chromium/ui/gfx/x/generated_protos/xtest.h
+++ b/chromium/ui/gfx/x/generated_protos/xtest.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/xv.h b/chromium/ui/gfx/x/generated_protos/xv.h
index 268d3779caf..c4a89f32693 100644
--- a/chromium/ui/gfx/x/generated_protos/xv.h
+++ b/chromium/ui/gfx/x/generated_protos/xv.h
@@ -51,8 +51,8 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
#include "shm.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/generated_protos/xvmc.h b/chromium/ui/gfx/x/generated_protos/xvmc.h
index cd95f9d6edd..b166167808a 100644
--- a/chromium/ui/gfx/x/generated_protos/xvmc.h
+++ b/chromium/ui/gfx/x/generated_protos/xvmc.h
@@ -51,7 +51,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/error.h"
#include "ui/gfx/x/ref_counted_fd.h"
#include "xproto.h"
diff --git a/chromium/ui/gfx/x/property_cache.h b/chromium/ui/gfx/x/property_cache.h
index 2ab765a9016..1004b07626a 100644
--- a/chromium/ui/gfx/x/property_cache.h
+++ b/chromium/ui/gfx/x/property_cache.h
@@ -11,7 +11,7 @@
#include "base/containers/flat_map.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/connection.h"
#include "ui/gfx/x/future.h"
#include "ui/gfx/x/x11_window_event_manager.h"
@@ -61,7 +61,7 @@ class COMPONENT_EXPORT(X11) PropertyCache : public EventObserver {
Future<GetPropertyReply> future;
// |response| is nullopt if the request hasn't yet finished.
- base::Optional<GetPropertyResponse> response = base::nullopt;
+ absl::optional<GetPropertyResponse> response = absl::nullopt;
};
// EventObserver:
diff --git a/chromium/ui/gfx/x/xproto_internal.h b/chromium/ui/gfx/x/xproto_internal.h
index 3f9348c0c5b..4d043d3299b 100644
--- a/chromium/ui/gfx/x/xproto_internal.h
+++ b/chromium/ui/gfx/x/xproto_internal.h
@@ -15,7 +15,7 @@
#include "base/component_export.h"
#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/x/future.h"
#include "ui/gfx/x/xproto.h"
#include "ui/gfx/x/xproto_types.h"
diff --git a/chromium/ui/gfx/x/xproto_types.h b/chromium/ui/gfx/x/xproto_types.h
index cab307a08fb..8390d17cdfc 100644
--- a/chromium/ui/gfx/x/xproto_types.h
+++ b/chromium/ui/gfx/x/xproto_types.h
@@ -14,7 +14,7 @@
#include "base/memory/free_deleter.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace x11 {
diff --git a/chromium/ui/gl/BUILD.gn b/chromium/ui/gl/BUILD.gn
index 23a0ee6130c..20e9894382d 100644
--- a/chromium/ui/gl/BUILD.gn
+++ b/chromium/ui/gl/BUILD.gn
@@ -168,9 +168,11 @@ component("gl") {
":buildflags",
"//base/third_party/dynamic_annotations",
"//build:chromeos_buildflags",
+ "//mojo/public/cpp/bindings",
# ANGLE includes are used cross-platform.
"//third_party/angle:includes",
+ "//ui/gfx/mojom",
]
public_deps = [
"//base",
@@ -288,8 +290,6 @@ component("gl") {
"gl_image_glx_native_pixmap.h",
"gl_surface_glx.cc",
"gl_surface_glx.h",
- "gl_visual_picker_glx.cc",
- "gl_visual_picker_glx.h",
"glx_util.cc",
"glx_util.h",
]
@@ -580,6 +580,7 @@ test("gl_unittests") {
if (is_win) {
sources += [
+ "delegated_ink_point_renderer_gpu_unittest.cc",
"direct_composition_surface_win_unittest.cc",
"gl_fence_win_unittest.cc",
"gl_image_d3d_unittest.cc",
diff --git a/chromium/ui/gl/DEPS b/chromium/ui/gl/DEPS
index e0adf27d88e..a135d3babde 100644
--- a/chromium/ui/gl/DEPS
+++ b/chromium/ui/gl/DEPS
@@ -1,5 +1,7 @@
include_rules = [
"+cc/base",
+ "+components/viz/common/resources/resource_format.h",
+ "+mojo/public/cpp/bindings",
"+third_party/khronos",
"+third_party/libsync",
"+third_party/skia",
@@ -14,6 +16,9 @@ specific_include_rules = {
"angle_platform_impl.cc": [
"+third_party/angle/include/platform/PlatformMethods.h",
],
+ "delegated_ink_point_renderer_gpu_unittest.cc": [
+ "+ui/base/win/hidden_window.h",
+ ],
"direct_composition_surface_win_unittest.cc": [
"+ui/base/win/hidden_window.h",
"+ui/platform_window",
diff --git a/chromium/ui/gl/GL/glextchromium.h b/chromium/ui/gl/GL/glextchromium.h
index 41818d7f5ae..b8a2283a4b4 100644
--- a/chromium/ui/gl/GL/glextchromium.h
+++ b/chromium/ui/gl/GL/glextchromium.h
@@ -4,8 +4,8 @@
// This file contains Chromium-specific GL extensions declarations.
-#ifndef GPU_GL_GLEXTCHROMIUM_H_
-#define GPU_GL_GLEXTCHROMIUM_H_
+#ifndef UI_GL_GL_GLEXTCHROMIUM_H_
+#define UI_GL_GL_GLEXTCHROMIUM_H_
#ifdef __cplusplus
extern "C" {
@@ -23,4 +23,4 @@ extern "C" {
}
#endif
-#endif // GPU_GL_GLEXTCHROMIUM_H_
+#endif // UI_GL_GL_GLEXTCHROMIUM_H_
diff --git a/chromium/ui/gl/angle_platform_impl.h b/chromium/ui/gl/angle_platform_impl.h
index 777b1d20828..0bbbabb5cf7 100644
--- a/chromium/ui/gl/angle_platform_impl.h
+++ b/chromium/ui/gl/angle_platform_impl.h
@@ -8,7 +8,6 @@
// Implements the ANGLE platform interface, for functionality like
// histograms and trace profiling.
-#include "base/callback_forward.h"
#include "ui/gl/gl_context_egl.h"
#include "ui/gl/gl_export.h"
diff --git a/chromium/ui/gl/ca_renderer_layer_params.cc b/chromium/ui/gl/ca_renderer_layer_params.cc
index b31832aa5fc..b5275055dd0 100644
--- a/chromium/ui/gl/ca_renderer_layer_params.cc
+++ b/chromium/ui/gl/ca_renderer_layer_params.cc
@@ -18,7 +18,8 @@ CARendererLayerParams::CARendererLayerParams(
unsigned background_color,
unsigned edge_aa_mask,
float opacity,
- unsigned filter)
+ unsigned filter,
+ gfx::ProtectedVideoType protected_video_type)
: is_clipped(is_clipped),
clip_rect(clip_rect),
rounded_corner_bounds(rounded_corner_bounds),
@@ -30,7 +31,8 @@ CARendererLayerParams::CARendererLayerParams(
background_color(background_color),
edge_aa_mask(edge_aa_mask),
opacity(opacity),
- filter(filter) {}
+ filter(filter),
+ protected_video_type(protected_video_type) {}
CARendererLayerParams::CARendererLayerParams(
const CARendererLayerParams& other) = default;
diff --git a/chromium/ui/gl/ca_renderer_layer_params.h b/chromium/ui/gl/ca_renderer_layer_params.h
index d6ce053f17a..e7db07bfc34 100644
--- a/chromium/ui/gl/ca_renderer_layer_params.h
+++ b/chromium/ui/gl/ca_renderer_layer_params.h
@@ -13,6 +13,7 @@
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/rrect_f.h"
#include "ui/gfx/transform.h"
+#include "ui/gfx/video_types.h"
#include "ui/gl/gl_export.h"
namespace gl {
@@ -33,7 +34,8 @@ struct GL_EXPORT CARendererLayerParams {
unsigned background_color,
unsigned edge_aa_mask,
float opacity,
- unsigned filter);
+ unsigned filter,
+ gfx::ProtectedVideoType protected_video_type);
CARendererLayerParams(const CARendererLayerParams& other);
~CARendererLayerParams();
@@ -49,6 +51,7 @@ struct GL_EXPORT CARendererLayerParams {
unsigned edge_aa_mask;
float opacity;
unsigned filter;
+ gfx::ProtectedVideoType protected_video_type;
// This is a subset of cc::FilterOperation::FilterType.
enum class FilterEffectType : uint32_t {
diff --git a/chromium/ui/gl/dc_layer_tree.cc b/chromium/ui/gl/dc_layer_tree.cc
index 8a8bd381997..60cc2cf975a 100644
--- a/chromium/ui/gl/dc_layer_tree.cc
+++ b/chromium/ui/gl/dc_layer_tree.cc
@@ -34,11 +34,7 @@ DCLayerTree::DCLayerTree(bool disable_nv12_dynamic_textures,
bool disable_vp_scaling)
: disable_nv12_dynamic_textures_(disable_nv12_dynamic_textures),
disable_vp_scaling_(disable_vp_scaling),
- ink_renderer_(
- std::make_unique<
- DelegatedInkPointRendererGpu<IDCompositionInkTrailDevice,
- IDCompositionDelegatedInkTrail>>()) {
-}
+ ink_renderer_(std::make_unique<DelegatedInkRenderer>()) {}
DCLayerTree::~DCLayerTree() = default;
@@ -356,4 +352,12 @@ void DCLayerTree::SetDelegatedInkTrailStartPoint(
ink_renderer_->SetDelegatedInkTrailStartPoint(std::move(metadata));
}
+void DCLayerTree::InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver) {
+ DCHECK(SupportsDelegatedInk());
+
+ ink_renderer_->InitMessagePipeline(std::move(pending_receiver));
+}
+
} // namespace gl
diff --git a/chromium/ui/gl/dc_layer_tree.h b/chromium/ui/gl/dc_layer_tree.h
index 0bcfc41d511..0ca8dcc61cd 100644
--- a/chromium/ui/gl/dc_layer_tree.h
+++ b/chromium/ui/gl/dc_layer_tree.h
@@ -13,6 +13,7 @@
#include <memory>
#include "base/containers/flat_map.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/gfx/color_space_win.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gl/dc_renderer_layer_params.h"
@@ -20,6 +21,9 @@
#include "ui/gl/hdr_metadata_helper_win.h"
namespace gfx {
+namespace mojom {
+class DelegatedInkPointRenderer;
+} // namespace mojom
class DelegatedInkMetadata;
} // namespace gfx
@@ -60,6 +64,10 @@ class DCLayerTree {
public:
using VideoProcessorMap =
base::flat_map<VideoProcessorType, VideoProcessorWrapper>;
+ using DelegatedInkRenderer =
+ DelegatedInkPointRendererGpu<IDCompositionInkTrailDevice,
+ IDCompositionDelegatedInkTrail,
+ DCompositionInkTrailPoint>;
DCLayerTree(bool disable_nv12_dynamic_textures, bool disable_vp_scaling);
@@ -117,6 +125,14 @@ class DCLayerTree {
void SetDelegatedInkTrailStartPoint(
std::unique_ptr<gfx::DelegatedInkMetadata>);
+ void InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver);
+
+ DelegatedInkRenderer* GetInkRendererForTesting() const {
+ return ink_renderer_.get();
+ }
+
private:
// This will add an ink visual to the visual tree to enable delegated ink
// trails. This will initially always be called directly before an OS
@@ -176,9 +192,7 @@ class DCLayerTree {
// when the DCLayerTree is created, but can only be queried to check if the
// platform supports delegated ink trails. It must be initialized via the
// Initialize() method in order to be used for drawing delegated ink trails.
- std::unique_ptr<DelegatedInkPointRendererGpu<IDCompositionInkTrailDevice,
- IDCompositionDelegatedInkTrail>>
- ink_renderer_;
+ std::unique_ptr<DelegatedInkRenderer> ink_renderer_;
DISALLOW_COPY_AND_ASSIGN(DCLayerTree);
};
diff --git a/chromium/ui/gl/dc_renderer_layer_params.h b/chromium/ui/gl/dc_renderer_layer_params.h
index 0016bb971f4..70f2fa83d5c 100644
--- a/chromium/ui/gl/dc_renderer_layer_params.h
+++ b/chromium/ui/gl/dc_renderer_layer_params.h
@@ -8,6 +8,7 @@
#include <array>
#include "base/memory/ref_counted.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
@@ -49,9 +50,8 @@ struct GL_EXPORT DCRendererLayerParams {
// after applying the |quad_rect.origin()| as an offset.
gfx::Transform transform;
- // If |is_clipped| is true, then clip to |clip_rect| in root target space.
- bool is_clipped = false;
- gfx::Rect clip_rect;
+ // If present, then clip to |clip_rect| in root target space.
+ absl::optional<gfx::Rect> clip_rect;
gfx::ProtectedVideoType protected_video_type =
gfx::ProtectedVideoType::kClear;
diff --git a/chromium/ui/gl/delegated_ink_point_renderer_gpu.h b/chromium/ui/gl/delegated_ink_point_renderer_gpu.h
index 459dfc734ae..653ccdd6a34 100644
--- a/chromium/ui/gl/delegated_ink_point_renderer_gpu.h
+++ b/chromium/ui/gl/delegated_ink_point_renderer_gpu.h
@@ -8,23 +8,42 @@
#include <dcomp.h>
#include <wrl/client.h>
+#include <iterator>
#include <memory>
#include <utility>
+#include "base/containers/circular_deque.h"
+#include "base/containers/flat_map.h"
#include "base/trace_event/trace_event.h"
+#include "mojo/public/cpp/bindings/receiver.h"
#include "ui/gfx/delegated_ink_metadata.h"
+#include "ui/gfx/mojom/delegated_ink_point_renderer.mojom.h"
// Required for SFINAE to check if these Win10 types exist.
// TODO(1171374): Remove this when the types are available in the Win10 SDK.
struct IDCompositionInkTrailDevice;
struct IDCompositionDelegatedInkTrail;
+struct DCompositionInkTrailPoint;
namespace gl {
+namespace {
+
+// Maximum number of points that can be drawn. This is used to limit the total
+// number of ink trail tokens that we will store, and the total number of points
+// that we will store to provide to the Direct Composition APIs. It should match
+// the exact number of points that the OS Compositor will store to draw as part
+// of a trail.
+constexpr int kMaximumNumberOfPoints = 128;
+
+} // namespace
+
// TODO(1171374): Remove this class and remove templates when the types are
// available in the Win10 SDK.
template <typename InkTrailDevice,
typename DelegatedInkTrail,
+ typename InkTrailPoint,
+ typename = void,
typename = void,
typename = void>
class DelegatedInkPointRendererGpu {
@@ -53,6 +72,37 @@ class DelegatedInkPointRendererGpu {
std::unique_ptr<gfx::DelegatedInkMetadata> metadata) {
NOTREACHED();
}
+
+ void InitMessagePipeline(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer> receiver) {
+ NOTREACHED();
+ }
+
+ void StoreDelegatedInkPoint(const gfx::DelegatedInkPoint& point) {
+ NOTREACHED();
+ }
+
+ gfx::DelegatedInkMetadata* MetadataForTesting() const {
+ NOTREACHED();
+ return nullptr;
+ }
+
+ base::circular_deque<gfx::DelegatedInkPoint> DelegatedInkPointsForTesting()
+ const {
+ NOTREACHED();
+ return base::circular_deque<gfx::DelegatedInkPoint>();
+ }
+
+ base::flat_map<base::TimeTicks, unsigned int> InkTrailTokensForTesting()
+ const {
+ NOTREACHED();
+ return base::flat_map<base::TimeTicks, unsigned int>();
+ }
+
+ bool WaitForNewTrailToDrawForTesting() const {
+ NOTREACHED();
+ return false;
+ }
};
// This class will call the OS delegated ink trail APIs when they become
@@ -68,15 +118,34 @@ class DelegatedInkPointRendererGpu {
// visual this way.
// For more information about the design of this class and using the OS APIs,
// view the design doc here: https://aka.ms/GPUBackedDesignDoc
-template <typename InkTrailDevice, typename DelegatedInkTrail>
+template <typename InkTrailDevice,
+ typename DelegatedInkTrail,
+ typename InkTrailPoint>
class DelegatedInkPointRendererGpu<InkTrailDevice,
DelegatedInkTrail,
+ InkTrailPoint,
decltype(typeid(InkTrailDevice), void()),
- decltype(typeid(DelegatedInkTrail),
- void())> {
+ decltype(typeid(DelegatedInkTrail), void()),
+ decltype(typeid(InkTrailPoint), void())>
+ : public gfx::mojom::DelegatedInkPointRenderer {
public:
DelegatedInkPointRendererGpu() = default;
+ void InitMessagePipeline(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver) {
+ // The remote end of this pipeline exists on a per-tab basis, so if tab A
+ // is using the feature and then tab B starts trying to use it, a new
+ // PendingReceiver will arrive here while |receiver_| is still bound to the
+ // remote in tab A. Because of this possibility, we unconditionally reset
+ // |receiver_| before trying to bind anything here. This is fine to do
+ // because we only ever need to actively receive points from one tab as only
+ // one tab can be in the foreground and actively inking at a time.
+ receiver_.reset();
+
+ receiver_.Bind(std::move(pending_receiver));
+ }
+
bool Initialize(
const Microsoft::WRL::ComPtr<IDCompositionDevice2>& dcomp_device2,
const Microsoft::WRL::ComPtr<IDXGISwapChain1>& root_swap_chain) {
@@ -148,9 +217,100 @@ class DelegatedInkPointRendererGpu<InkTrailDevice,
TRACE_EVENT1("gpu",
"DelegatedInkPointRendererGpu::SetDelegatedInkTrailStartPoint",
"metadata", metadata->ToString());
+
+ DCHECK(ink_visual_);
+ DCHECK(delegated_ink_trail_);
+
+ // If a trail has already been started and |metadata| is a point that was
+ // drawn as part of that trail (meaning it is found in |ink_trail_tokens_|),
+ // simply remove all the points up to the point that |metadata| describes.
+ // The only exception to this is if the color on |metadata| doesn't match
+ // |metadata_|'s color - then a new trail needs to be started to describe
+ // the new color.
+ auto metadata_token = ink_trail_tokens_.find(metadata->timestamp());
+ if (metadata_ && metadata->color() == metadata_->color() &&
+ metadata_token != ink_trail_tokens_.end()) {
+ bool remove_trail_points_failed = TraceEventOnFailure(
+ delegated_ink_trail_->RemoveTrailPoints(metadata_token->second),
+ "DelegatedInkPointRendererGpu::SetDelegatedInkTrailStartPoint - "
+ "Failed to remove trail points.");
+ if (!remove_trail_points_failed &&
+ UpdateVisualClip(metadata->presentation_area())) {
+ ink_trail_tokens_.erase(ink_trail_tokens_.begin(),
+ std::next(metadata_token));
+ metadata_ = std::move(metadata);
+ RemoveSavedPointsOlderThanMetadata();
+ return;
+ }
+ }
+
+ if (!UpdateVisualClip(metadata->presentation_area()))
+ return;
+
+ D2D1_COLOR_F d2d1_color;
+ const float kMaxRGBAValue = 255.f;
+ d2d1_color.a = SkColorGetA(metadata->color()) / kMaxRGBAValue;
+ d2d1_color.r = SkColorGetR(metadata->color()) / kMaxRGBAValue;
+ d2d1_color.g = SkColorGetG(metadata->color()) / kMaxRGBAValue;
+ d2d1_color.b = SkColorGetB(metadata->color()) / kMaxRGBAValue;
+ if (TraceEventOnFailure(
+ delegated_ink_trail_->StartNewTrail(d2d1_color),
+ "DelegatedInkPointRendererGpu::SetDelegatedInkTrailStartPoint - "
+ "Failed to start a new trail.")) {
+ return;
+ }
+
+ wait_for_new_trail_to_draw_ = false;
+ ink_trail_tokens_.clear();
metadata_ = std::move(metadata);
- // TODO(1052145): Start using OS APIs to inform of the starting point of the
- // ink trail.
+ DrawSavedTrailPoints();
+ }
+
+ void StoreDelegatedInkPoint(const gfx::DelegatedInkPoint& point) override {
+ TRACE_EVENT1("gpu", "DelegatedInkPointRendererGpu::StoreDelegatedInkPoint",
+ "delegated ink point", point.ToString());
+
+ DCHECK(delegated_ink_points_.empty() ||
+ point.timestamp() > delegated_ink_points_.back().timestamp());
+
+ if (metadata_ && point.timestamp() < metadata_->timestamp())
+ return;
+
+ // Always save the point so that it can be drawn later. This allows points
+ // that arrive before the first metadata makes it here to be drawn after
+ // StartNewTrail is called. If we get to the maximum number of points that
+ // we will store, start erasing the oldest ones first. This matches what the
+ // OS compositor does internally when it hits the max number of points.
+ if (delegated_ink_points_.size() == kMaximumNumberOfPoints)
+ delegated_ink_points_.pop_front();
+ delegated_ink_points_.push_back(point);
+
+ DrawDelegatedInkPoint(point);
+ }
+
+ void ResetPrediction() override {
+ // Don't reset |metadata_| here so that RemoveTrailPoints() can continue
+ // to be called as the final metadata(s) arrive.
+ // TODO(1052145): Start predicting points and reset it here.
+ wait_for_new_trail_to_draw_ = true;
+ }
+
+ gfx::DelegatedInkMetadata* MetadataForTesting() const {
+ return metadata_.get();
+ }
+
+ const base::circular_deque<gfx::DelegatedInkPoint>&
+ DelegatedInkPointsForTesting() const {
+ return delegated_ink_points_;
+ }
+
+ const base::flat_map<base::TimeTicks, unsigned int>&
+ InkTrailTokensForTesting() const {
+ return ink_trail_tokens_;
+ }
+
+ bool WaitForNewTrailToDrawForTesting() const {
+ return wait_for_new_trail_to_draw_;
}
private:
@@ -158,13 +318,85 @@ class DelegatedInkPointRendererGpu<InkTrailDevice,
// meaning that it returns true when an event is traced (because of a
// failure).
static bool TraceEventOnFailure(HRESULT hr, const char* name) {
- if (!FAILED(hr))
+ if (SUCCEEDED(hr))
return false;
TRACE_EVENT_INSTANT1("gpu", name, TRACE_EVENT_SCOPE_THREAD, "hr", hr);
return true;
}
+ bool UpdateVisualClip(const gfx::RectF& new_presentation_area) {
+ if (metadata_ && metadata_->presentation_area() == new_presentation_area)
+ return true;
+
+ // If (0,0) of a visual is clipped out, it can result in delegated ink not
+ // being drawn at all. This is more common when DComp Surfaces are enabled,
+ // but doesn't negatively impact things when the swapchain is used, so just
+ // offset the visual instead of clipping the top left corner in all cases.
+ ink_visual_->SetOffsetX(new_presentation_area.x());
+ ink_visual_->SetOffsetY(new_presentation_area.y());
+
+ D2D_RECT_F clip_rect;
+ clip_rect.bottom = new_presentation_area.bottom();
+ clip_rect.right = new_presentation_area.right();
+ // If setting the clip or committing failed, we want to bail early so that a
+ // trail can't incorrectly appear over things on the user's screen.
+ return SUCCEEDED(ink_visual_->SetClip(clip_rect)) &&
+ SUCCEEDED(dcomp_device_->Commit());
+ }
+
+ void RemoveSavedPointsOlderThanMetadata() {
+ DCHECK(metadata_);
+ while (!delegated_ink_points_.empty() &&
+ delegated_ink_points_.front().timestamp() < metadata_->timestamp()) {
+ delegated_ink_points_.pop_front();
+ }
+ }
+
+ void DrawSavedTrailPoints() {
+ RemoveSavedPointsOlderThanMetadata();
+
+ for (const gfx::DelegatedInkPoint& point : delegated_ink_points_)
+ DrawDelegatedInkPoint(point);
+ }
+
+ void DrawDelegatedInkPoint(const gfx::DelegatedInkPoint& point) {
+ if (wait_for_new_trail_to_draw_ || !metadata_ ||
+ !metadata_->presentation_area().Contains(point.point())) {
+ return;
+ }
+
+ DCHECK(delegated_ink_trail_);
+
+ InkTrailPoint ink_point;
+ ink_point.radius = metadata_->diameter() / 2.f;
+ // In order to account for the visual offset, the point must be offset in
+ // the opposite direction.
+ ink_point.x = point.point().x() - metadata_->presentation_area().x();
+ ink_point.y = point.point().y() - metadata_->presentation_area().y();
+ unsigned int token;
+
+ // AddTrailPoints() can accept and draw more than one InkTrailPoint per
+ // call. However, all the points get lumped together in the one token then,
+ // which means that they can only be removed all together. This may be fine
+ // in some scenarios, but in the vast majority of cases we will need to
+ // remove one point at a time, so we choose to only add one InkTrailPoint at
+ // a time.
+ if (TraceEventOnFailure(
+ delegated_ink_trail_->AddTrailPoints(&ink_point,
+ /*inkPointsCount*/ 1, &token),
+ "DelegatedInkPointRendererGpu::DrawDelegatedInkPoint - Failed to "
+ "add trail point")) {
+ // TODO(1052145): Start predicting points.
+ return;
+ }
+
+ if (ink_trail_tokens_.size() == kMaximumNumberOfPoints)
+ ink_trail_tokens_.erase(ink_trail_tokens_.begin());
+
+ ink_trail_tokens_.insert({point.timestamp(), token});
+ }
+
// The visual within the tree that will contain the delegated ink trail. It
// should be a child of the root surface visual.
Microsoft::WRL::ComPtr<IDCompositionVisual> ink_visual_;
@@ -173,16 +405,50 @@ class DelegatedInkPointRendererGpu<InkTrailDevice,
// content of the ink visual.
Microsoft::WRL::ComPtr<DelegatedInkTrail> delegated_ink_trail_;
- // The most recent metadata received. The metadata marks the last point of
- // the app rendered stroke, which corresponds to the first point of the
- // delegated ink trail that will be drawn.
- std::unique_ptr<gfx::DelegatedInkMetadata> metadata_;
-
// Remember the dcomp device and swap chain used to create
// |delegated_ink_trail_| and |ink_visual_| so that we can avoid recreating
// them when it isn't necessary.
IDCompositionDevice2* dcomp_device_ = nullptr;
IDXGISwapChain1* swap_chain_ = nullptr;
+
+ // The most recent metadata received. The metadata marks the last point of
+ // the app rendered stroke, which corresponds to the first point of the
+ // delegated ink trail that will be drawn.
+ std::unique_ptr<gfx::DelegatedInkMetadata> metadata_;
+
+ // All the points that have arrived in StoreDelegatedInkPoint(). These are
+ // stored in increasing timestamp order, and are not guaranteed to be
+ // currently drawn to the screen. They are not guaranteed to be currently on
+ // the screen because all points that arrive are stored, even if no metadata
+ // has arrived in SetDelegatedInkTrailStartPoint(), the DelegatedInkPoint
+ // is outside of |metadata_|'s presentation area, or we are waiting for a new
+ // SetDelegatedInkTrailStartPoint() call. The only exception is if a point
+ // arrives with a timestamp earlier than |metadata_|'s, then we just bail
+ // without even saving it. Each time a new trail is started, all points in
+ // |delegated_ink_points_| are iterated over and either removed from the list
+ // because their timestamp is earlier than |metadata_|'s, or we send them
+ // through StoreDelegatedInkPoint() again.
+ base::circular_deque<gfx::DelegatedInkPoint> delegated_ink_points_;
+
+ // Tokens received when adding points to the trail. The tokens are then later
+ // used to remove points from the trail. The timestamps should always match
+ // all the points that are being drawn except the first point of the trail and
+ // no more.
+ base::flat_map<base::TimeTicks, unsigned int> ink_trail_tokens_;
+
+ // Flag to know if new DelegatedInkPoints that arrive should be drawn
+ // immediately or if they should wait for a new trail to be started. Set to
+ // true when ResetPrediction is called, as this tells us that something about
+ // the pointerevents in the browser process changed. When that happens, we
+ // should continue to remove points for any metadata that arrive with
+ // timestamps that match DelegatedInkPoints that arrived before the
+ // ResetPrediction call. However, once a metadata arrives with a timestamp
+ // after the ResetPrediction, then we know that inking should continue, so a
+ // new trail is started and we try to draw everything in
+ // |delegated_ink_points_|.
+ bool wait_for_new_trail_to_draw_ = true;
+
+ mojo::Receiver<gfx::mojom::DelegatedInkPointRenderer> receiver_{this};
};
} // namespace gl
diff --git a/chromium/ui/gl/delegated_ink_point_renderer_gpu_unittest.cc b/chromium/ui/gl/delegated_ink_point_renderer_gpu_unittest.cc
new file mode 100644
index 00000000000..a8a521f7774
--- /dev/null
+++ b/chromium/ui/gl/delegated_ink_point_renderer_gpu_unittest.cc
@@ -0,0 +1,262 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/delegated_ink_point_renderer_gpu.h"
+
+#include <memory>
+
+#include "base/run_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/win/hidden_window.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+#include "ui/gl/dc_layer_tree.h"
+#include "ui/gl/direct_composition_surface_win.h"
+#include "ui/gl/gl_angle_util_win.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/init/gl_factory.h"
+
+namespace gl {
+namespace {
+
+class DelegatedInkPointRendererGpuTest : public testing::Test {
+ public:
+ DelegatedInkPointRendererGpuTest() : parent_window_(ui::GetHiddenWindow()) {}
+
+ DirectCompositionSurfaceWin* surface() { return surface_.get(); }
+
+ DCLayerTree* layer_tree() { return surface()->GetLayerTreeForTesting(); }
+
+ DCLayerTree::DelegatedInkRenderer* ink_renderer() {
+ return layer_tree()->GetInkRendererForTesting();
+ }
+
+ void SendDelegatedInkPointBasedOnPrevious() {
+ const base::circular_deque<gfx::DelegatedInkPoint>& ink_points =
+ ink_renderer()->DelegatedInkPointsForTesting();
+ DCHECK(!ink_points.empty());
+
+ auto last_point = ink_points.back();
+ ink_renderer()->StoreDelegatedInkPoint(gfx::DelegatedInkPoint(
+ last_point.point() + gfx::Vector2dF(5, 5),
+ last_point.timestamp() + base::TimeDelta::FromMicroseconds(10),
+ last_point.pointer_id()));
+ }
+
+ void SendMetadata(const gfx::DelegatedInkMetadata& metadata) {
+ surface()->SetDelegatedInkTrailStartPoint(
+ std::make_unique<gfx::DelegatedInkMetadata>(metadata));
+ }
+
+ gfx::DelegatedInkMetadata SendMetadataBasedOnStoredPoint(uint64_t point) {
+ const base::circular_deque<gfx::DelegatedInkPoint>& ink_points =
+ ink_renderer()->DelegatedInkPointsForTesting();
+ EXPECT_GE(ink_points.size(), point);
+
+ auto ink_point = ink_points[point];
+ gfx::DelegatedInkMetadata metadata(
+ ink_point.point(), /*diameter=*/3, SK_ColorBLACK, ink_point.timestamp(),
+ gfx::RectF(0, 0, 100, 100), /*hovering=*/false);
+ SendMetadata(metadata);
+ return metadata;
+ }
+
+ void StoredMetadataMatchesSentMetadata(
+ const gfx::DelegatedInkMetadata& sent_metadata) {
+ gfx::DelegatedInkMetadata* renderer_metadata =
+ ink_renderer()->MetadataForTesting();
+ EXPECT_TRUE(renderer_metadata);
+ EXPECT_EQ(renderer_metadata->point(), sent_metadata.point());
+ EXPECT_EQ(renderer_metadata->diameter(), sent_metadata.diameter());
+ EXPECT_EQ(renderer_metadata->color(), sent_metadata.color());
+ EXPECT_EQ(renderer_metadata->timestamp(), sent_metadata.timestamp());
+ EXPECT_EQ(renderer_metadata->presentation_area(),
+ sent_metadata.presentation_area());
+ EXPECT_EQ(renderer_metadata->is_hovering(), sent_metadata.is_hovering());
+ }
+
+ protected:
+ void SetUp() override {
+ // Without this, the following check always fails.
+ gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true);
+ if (!QueryDirectCompositionDevice(QueryD3D11DeviceObjectFromANGLE())) {
+ LOG(WARNING)
+ << "GL implementation not using DirectComposition, skipping test.";
+ return;
+ }
+
+ CreateDirectCompositionSurfaceWin();
+ if (!surface_->SupportsDelegatedInk()) {
+ LOG(WARNING) << "Delegated ink unsupported, skipping test.";
+ return;
+ }
+
+ CreateGLContext();
+ surface_->SetEnableDCLayers(true);
+
+ // Create the swap chain
+ constexpr gfx::Size window_size(100, 100);
+ EXPECT_TRUE(surface_->Resize(window_size, 1.0, gfx::ColorSpace(), true));
+ EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(window_size)));
+ }
+
+ void TearDown() override {
+ context_ = nullptr;
+ if (surface_)
+ DestroySurface(std::move(surface_));
+ gl::init::ShutdownGL(false);
+ }
+
+ private:
+ void CreateDirectCompositionSurfaceWin() {
+ DirectCompositionSurfaceWin::Settings settings;
+ surface_ = base::MakeRefCounted<DirectCompositionSurfaceWin>(
+ parent_window_, DirectCompositionSurfaceWin::VSyncCallback(), settings);
+ EXPECT_TRUE(surface_->Initialize(GLSurfaceFormat()));
+
+ // ImageTransportSurfaceDelegate::DidCreateAcceleratedSurfaceChildWindow()
+ // is called in production code here. However, to remove dependency from
+ // gpu/ipc/service/image_transport_surface_delegate.h, here we directly
+ // executes the required minimum code.
+ if (parent_window_)
+ ::SetParent(surface_->window(), parent_window_);
+ }
+
+ void CreateGLContext() {
+ context_ =
+ gl::init::CreateGLContext(nullptr, surface_.get(), GLContextAttribs());
+ EXPECT_TRUE(context_->MakeCurrent(surface_.get()));
+ }
+
+ void DestroySurface(scoped_refptr<DirectCompositionSurfaceWin> surface) {
+ scoped_refptr<base::TaskRunner> task_runner =
+ surface->GetWindowTaskRunnerForTesting();
+ DCHECK(surface->HasOneRef());
+
+ surface = nullptr;
+
+ base::RunLoop run_loop;
+ task_runner->PostTask(FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ HWND parent_window_;
+ scoped_refptr<DirectCompositionSurfaceWin> surface_;
+ scoped_refptr<GLContext> context_;
+};
+
+// Test to confirm that points and tokens are stored and removed correctly based
+// on when the metadata and points arrive.
+TEST_F(DelegatedInkPointRendererGpuTest, StoreAndRemovePointsAndTokens) {
+ if (!surface() || !surface()->SupportsDelegatedInk())
+ return;
+
+ // Send some points and make sure they are all stored even with no metadata.
+ ink_renderer()->StoreDelegatedInkPoint(
+ gfx::DelegatedInkPoint(gfx::PointF(10, 10), base::TimeTicks::Now(), 1));
+ const uint64_t kPointsToStore = 5u;
+ for (uint64_t i = 1; i < kPointsToStore; ++i)
+ SendDelegatedInkPointBasedOnPrevious();
+
+ EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting().size(),
+ kPointsToStore);
+ EXPECT_TRUE(ink_renderer()->InkTrailTokensForTesting().empty());
+ EXPECT_FALSE(ink_renderer()->MetadataForTesting());
+ EXPECT_TRUE(ink_renderer()->WaitForNewTrailToDrawForTesting());
+
+ // Now send metadata that matches the first stored point. This should result
+ // in all of the points being drawn and matching tokens stored. None of the
+ // points should be removed from the circular deque because they are stored
+ // until a metadata arrives with a later timestamp
+ gfx::DelegatedInkMetadata metadata = SendMetadataBasedOnStoredPoint(0);
+
+ EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting().size(),
+ kPointsToStore);
+ EXPECT_EQ(ink_renderer()->InkTrailTokensForTesting().size(), kPointsToStore);
+ EXPECT_FALSE(ink_renderer()->WaitForNewTrailToDrawForTesting());
+ StoredMetadataMatchesSentMetadata(metadata);
+
+ // Now send a metadata that matches a later one of the points. It should
+ // result in some of the stored points being erased, and one more token erased
+ // than points erased. This is because we don't need to store the token of the
+ // point that exactly matches the metadata.
+ const uint64_t kPointToSend = 3u;
+ metadata = SendMetadataBasedOnStoredPoint(kPointToSend);
+ EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting().size(),
+ kPointsToStore - kPointToSend);
+ // Subtract one extra because the token for the point that matches the new
+ // metadata is erased too.
+ EXPECT_EQ(ink_renderer()->InkTrailTokensForTesting().size(),
+ kPointsToStore - kPointToSend - 1);
+ StoredMetadataMatchesSentMetadata(metadata);
+
+ // Now send a metadata after all of the stored point to make sure that it
+ // results in all the tokens and stored points being erased because a new
+ // trail is started.
+ gfx::DelegatedInkPoint last_point =
+ ink_renderer()->DelegatedInkPointsForTesting().back();
+ metadata = gfx::DelegatedInkMetadata(
+ last_point.point() + gfx::Vector2dF(2, 2), /*diameter=*/3, SK_ColorBLACK,
+ last_point.timestamp() + base::TimeDelta::FromMicroseconds(20),
+ gfx::RectF(0, 0, 100, 100), /*hovering=*/false);
+ SendMetadata(metadata);
+ EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting().size(), 0u);
+ EXPECT_EQ(ink_renderer()->InkTrailTokensForTesting().size(), 0u);
+ StoredMetadataMatchesSentMetadata(metadata);
+}
+
+// Basic test to confirm that points are drawn as they arrive if they are in the
+// presentation area and after the metadata's timestamp.
+TEST_F(DelegatedInkPointRendererGpuTest, DrawPointsAsTheyArrive) {
+ if (!surface() || !surface()->SupportsDelegatedInk())
+ return;
+
+ gfx::DelegatedInkMetadata metadata(
+ gfx::PointF(12, 12), /*diameter=*/3, SK_ColorBLACK,
+ base::TimeTicks::Now(), gfx::RectF(10, 10, 90, 90), /*hovering=*/false);
+ SendMetadata(metadata);
+
+ // Send some points that should all be drawn to ensure that they are all drawn
+ // as they arrive.
+ const uint64_t kPointsToSend = 5u;
+ for (uint64_t i = 1u; i <= kPointsToSend; ++i) {
+ if (i == 1) {
+ ink_renderer()->StoreDelegatedInkPoint(gfx::DelegatedInkPoint(
+ metadata.point(), metadata.timestamp(), /*pointer_id=*/1));
+ } else {
+ SendDelegatedInkPointBasedOnPrevious();
+ }
+ EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting().size(), i);
+ EXPECT_EQ(ink_renderer()->InkTrailTokensForTesting().size(), i);
+ }
+
+ // Now send a point that is outside of the presentation area to ensure that
+ // it is not drawn. It will still be stored - this is so if a future metadata
+ // arrives with a presentation area that would contain this point, it can
+ // still be drawn.
+ gfx::DelegatedInkPoint last_point =
+ ink_renderer()->DelegatedInkPointsForTesting().back();
+ gfx::DelegatedInkPoint outside_point(
+ gfx::PointF(5, 5),
+ last_point.timestamp() + base::TimeDelta::FromMicroseconds(10),
+ /*pointer_id=*/1);
+ EXPECT_FALSE(metadata.presentation_area().Contains((outside_point.point())));
+ ink_renderer()->StoreDelegatedInkPoint(outside_point);
+
+ const uint64_t kTotalPointsSent = kPointsToSend + 1u;
+ EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting().size(),
+ kTotalPointsSent);
+ EXPECT_EQ(ink_renderer()->InkTrailTokensForTesting().size(), kPointsToSend);
+
+ // Then send a metadata with a larger presentation area and timestamp earlier
+ // than the above point to confirm it will be the only point drawn, but all
+ // the points with later timestamps will be stored.
+ const uint64_t kMetadataToSend = 3u;
+ SendMetadataBasedOnStoredPoint(kMetadataToSend);
+ EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting().size(),
+ kTotalPointsSent - kMetadataToSend);
+ EXPECT_EQ(ink_renderer()->InkTrailTokensForTesting().size(), 1u);
+}
+
+} // namespace
+} // namespace gl
diff --git a/chromium/ui/gl/direct_composition_surface_win.cc b/chromium/ui/gl/direct_composition_surface_win.cc
index 734e18577b5..106ecde195f 100644
--- a/chromium/ui/gl/direct_composition_surface_win.cc
+++ b/chromium/ui/gl/direct_composition_surface_win.cc
@@ -928,6 +928,13 @@ void DirectCompositionSurfaceWin::SetDelegatedInkTrailStartPoint(
layer_tree_->SetDelegatedInkTrailStartPoint(std::move(metadata));
}
+void DirectCompositionSurfaceWin::InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver) {
+ layer_tree_->InitDelegatedInkPointRendererReceiver(
+ std::move(pending_receiver));
+}
+
scoped_refptr<base::TaskRunner>
DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() {
return child_window_.GetTaskRunnerForTesting();
diff --git a/chromium/ui/gl/direct_composition_surface_win.h b/chromium/ui/gl/direct_composition_surface_win.h
index 1fe92ebf7aa..7b160683eeb 100644
--- a/chromium/ui/gl/direct_composition_surface_win.h
+++ b/chromium/ui/gl/direct_composition_surface_win.h
@@ -12,6 +12,7 @@
#include "base/callback.h"
#include "base/time/time.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/gfx/transform.h"
#include "ui/gl/child_window_win.h"
#include "ui/gl/gl_export.h"
@@ -20,6 +21,9 @@
#include "ui/gl/vsync_observer.h"
namespace gfx {
+namespace mojom {
+class DelegatedInkPointRenderer;
+} // namespace mojom
class DelegatedInkMetadata;
} // namespace gfx
@@ -171,6 +175,9 @@ class GL_EXPORT DirectCompositionSurfaceWin : public GLSurfaceEGL,
bool SupportsDelegatedInk() override;
void SetDelegatedInkTrailStartPoint(
std::unique_ptr<gfx::DelegatedInkMetadata> metadata) override;
+ void InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver) override;
HWND window() const { return window_; }
@@ -192,6 +199,8 @@ class GL_EXPORT DirectCompositionSurfaceWin : public GLSurfaceEGL,
void SetMonitorInfoForTesting(int num_of_monitors, gfx::Size monitor_size);
+ DCLayerTree* GetLayerTreeForTesting() { return layer_tree_.get(); }
+
protected:
~DirectCompositionSurfaceWin() override;
diff --git a/chromium/ui/gl/direct_composition_surface_win_unittest.cc b/chromium/ui/gl/direct_composition_surface_win_unittest.cc
index c47020fac91..7502a021c77 100644
--- a/chromium/ui/gl/direct_composition_surface_win_unittest.cc
+++ b/chromium/ui/gl/direct_composition_surface_win_unittest.cc
@@ -12,7 +12,7 @@
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
-#include "base/test/power_monitor_test_base.h"
+#include "base/test/power_monitor_test.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/win/scoped_gdi_object.h"
@@ -1113,7 +1113,6 @@ TEST_F(DirectCompositionPixelTest, ResizeVideoLayer) {
params.content_rect = gfx::Rect(50, 50);
params.quad_rect = on_screen_rect;
params.clip_rect = on_screen_rect;
- params.is_clipped = true;
surface_->ScheduleDCLayer(params);
EXPECT_EQ(gfx::SwapResult::SWAP_ACK,
@@ -1214,8 +1213,9 @@ TEST_F(DirectCompositionPixelTest, SwapChainImage) {
ASSERT_TRUE(front_buffer_texture);
auto front_buffer_image = base::MakeRefCounted<GLImageD3D>(
- swap_chain_size, GL_BGRA_EXT, GL_UNSIGNED_BYTE, front_buffer_texture,
- swap_chain);
+ swap_chain_size, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
+ gfx::ColorSpace::CreateSRGB(), front_buffer_texture,
+ /*array_slice=*/0, /*plane_index=*/0, swap_chain);
ASSERT_TRUE(front_buffer_image->Initialize());
Microsoft::WRL::ComPtr<ID3D11Texture2D> back_buffer_texture;
diff --git a/chromium/ui/gl/dual_gpu_state_mac.h b/chromium/ui/gl/dual_gpu_state_mac.h
index 43b5a45fc8a..72848ef30b5 100644
--- a/chromium/ui/gl/dual_gpu_state_mac.h
+++ b/chromium/ui/gl/dual_gpu_state_mac.h
@@ -13,7 +13,6 @@
#include "base/memory/scoped_refptr.h"
#include "base/no_destructor.h"
#include "base/synchronization/lock.h"
-#include "base/time/time.h"
#include "build/build_config.h"
#include "ui/gl/dual_gpu_state.h"
#include "ui/gl/gl_bindings.h"
diff --git a/chromium/ui/gl/egl_timestamps.h b/chromium/ui/gl/egl_timestamps.h
index 50ccdfb3464..429d852ccc9 100644
--- a/chromium/ui/gl/egl_timestamps.h
+++ b/chromium/ui/gl/egl_timestamps.h
@@ -25,6 +25,7 @@ class GL_EXPORT EGLTimestampClient {
virtual bool GetFrameTimestampInfoIfAvailable(
base::TimeTicks* presentation_time,
base::TimeDelta* composite_interval,
+ base::TimeTicks* writes_done_time,
uint32_t* presentation_flags,
int frame_id) = 0;
};
diff --git a/chromium/ui/gl/gl_context_glx.h b/chromium/ui/gl/gl_context_glx.h
index b8925ae2fb5..cad557a2330 100644
--- a/chromium/ui/gl/gl_context_glx.h
+++ b/chromium/ui/gl/gl_context_glx.h
@@ -5,7 +5,6 @@
#ifndef UI_GL_GL_CONTEXT_GLX_H_
#define UI_GL_GL_CONTEXT_GLX_H_
-#include <string>
#include "base/compiler_specific.h"
#include "base/macros.h"
diff --git a/chromium/ui/gl/gl_context_glx_unittest.cc b/chromium/ui/gl/gl_context_glx_unittest.cc
index 85bcb6446f1..58d7a5d08a6 100644
--- a/chromium/ui/gl/gl_context_glx_unittest.cc
+++ b/chromium/ui/gl/gl_context_glx_unittest.cc
@@ -45,7 +45,7 @@ TEST(GLContextGLXTest, MAYBE_DoNotDestroyOnFailedMakeCurrent) {
// to ensure the map is complete.
connection->Sync();
- GLImageTestSupport::InitializeGL(base::nullopt);
+ GLImageTestSupport::InitializeGL(absl::nullopt);
auto surface = gl::InitializeGLSurface(base::MakeRefCounted<GLSurfaceGLXX11>(
static_cast<gfx::AcceleratedWidget>(xwindow)));
scoped_refptr<GLContext> context =
diff --git a/chromium/ui/gl/gl_features.cc b/chromium/ui/gl/gl_features.cc
index c71e70c3d9d..f7998070dc7 100644
--- a/chromium/ui/gl/gl_features.cc
+++ b/chromium/ui/gl/gl_features.cc
@@ -6,14 +6,62 @@
#include "base/command_line.h"
#include "base/feature_list.h"
+#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "ui/gl/gl_switches.h"
+#if defined(OS_ANDROID)
+#include "base/android/build_info.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/strings/pattern.h"
+#include "base/strings/string_split.h"
+#endif
+
namespace features {
namespace {
const base::Feature kGpuVsync{"GpuVsync", base::FEATURE_ENABLED_BY_DEFAULT};
+#if defined(OS_ANDROID)
+const base::FeatureParam<std::string>
+ kPassthroughCommandDecoderBlockListByBrand{
+ &kDefaultPassthroughCommandDecoder, "BlockListByBrand", ""};
+
+const base::FeatureParam<std::string>
+ kPassthroughCommandDecoderBlockListByDevice{
+ &kDefaultPassthroughCommandDecoder, "BlockListByDevice", ""};
+
+const base::FeatureParam<std::string>
+ kPassthroughCommandDecoderBlockListByAndroidBuildId{
+ &kDefaultPassthroughCommandDecoder, "BlockListByAndroidBuildId", ""};
+
+const base::FeatureParam<std::string>
+ kPassthroughCommandDecoderBlockListByManufacturer{
+ &kDefaultPassthroughCommandDecoder, "BlockListByManufacturer", ""};
+
+const base::FeatureParam<std::string>
+ kPassthroughCommandDecoderBlockListByModel{
+ &kDefaultPassthroughCommandDecoder, "BlockListByModel", ""};
+
+const base::FeatureParam<std::string>
+ kPassthroughCommandDecoderBlockListByBoard{
+ &kDefaultPassthroughCommandDecoder, "BlockListByBoard", ""};
+
+const base::FeatureParam<std::string>
+ kPassthroughCommandDecoderBlockListByAndroidBuildFP{
+ &kDefaultPassthroughCommandDecoder, "BlockListByAndroidBuildFP", ""};
+
+bool IsDeviceBlocked(const char* field, const std::string& block_list) {
+ auto disable_patterns = base::SplitString(
+ block_list, "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ for (const auto& disable_pattern : disable_patterns) {
+ if (base::MatchPattern(field, disable_pattern))
+ return true;
+ }
+ return false;
+}
+#endif
+
} // namespace
// Use the passthrough command decoder by default. This can be overridden with
@@ -38,4 +86,39 @@ bool UseGpuVsync() {
base::FeatureList::IsEnabled(kGpuVsync);
}
+bool UsePassthroughCommandDecoder() {
+ if (!base::FeatureList::IsEnabled(kDefaultPassthroughCommandDecoder))
+ return false;
+
+#if defined(OS_ANDROID)
+ // Check block list against build info.
+ const auto* build_info = base::android::BuildInfo::GetInstance();
+ if (IsDeviceBlocked(build_info->brand(),
+ kPassthroughCommandDecoderBlockListByBrand.Get()))
+ return false;
+ if (IsDeviceBlocked(build_info->device(),
+ kPassthroughCommandDecoderBlockListByDevice.Get()))
+ return false;
+ if (IsDeviceBlocked(
+ build_info->android_build_id(),
+ kPassthroughCommandDecoderBlockListByAndroidBuildId.Get()))
+ return false;
+ if (IsDeviceBlocked(build_info->manufacturer(),
+ kPassthroughCommandDecoderBlockListByManufacturer.Get()))
+ return false;
+ if (IsDeviceBlocked(build_info->model(),
+ kPassthroughCommandDecoderBlockListByModel.Get()))
+ return false;
+ if (IsDeviceBlocked(build_info->board(),
+ kPassthroughCommandDecoderBlockListByBoard.Get()))
+ return false;
+ if (IsDeviceBlocked(
+ build_info->android_build_fp(),
+ kPassthroughCommandDecoderBlockListByAndroidBuildFP.Get()))
+ return false;
+#endif // defined(OS_ANDROID)
+
+ return true;
+}
+
} // namespace features
diff --git a/chromium/ui/gl/gl_features.h b/chromium/ui/gl/gl_features.h
index e84a953c2c0..32f955576e0 100644
--- a/chromium/ui/gl/gl_features.h
+++ b/chromium/ui/gl/gl_features.h
@@ -18,6 +18,8 @@ GL_EXPORT bool UseGpuVsync();
// alongside the definition of their values in the .cc file.
GL_EXPORT extern const base::Feature kDefaultPassthroughCommandDecoder;
+GL_EXPORT bool UsePassthroughCommandDecoder();
+
} // namespace features
#endif // UI_GL_GL_FEATURES_H_
diff --git a/chromium/ui/gl/gl_fence_win.h b/chromium/ui/gl/gl_fence_win.h
index 10f51137133..e007f0f73e2 100644
--- a/chromium/ui/gl/gl_fence_win.h
+++ b/chromium/ui/gl/gl_fence_win.h
@@ -39,4 +39,4 @@ class GL_EXPORT GLFenceWin : public GLFence {
} // namespace gl
-#endif
+#endif // UI_GL_GL_FENCE_WIN_H_
diff --git a/chromium/ui/gl/gl_image_d3d.cc b/chromium/ui/gl/gl_image_d3d.cc
index 976ab720e3e..75fc087c761 100644
--- a/chromium/ui/gl/gl_image_d3d.cc
+++ b/chromium/ui/gl/gl_image_d3d.cc
@@ -11,49 +11,30 @@
#ifndef EGL_ANGLE_image_d3d11_texture
#define EGL_D3D11_TEXTURE_ANGLE 0x3484
#define EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D
+#define EGL_D3D11_TEXTURE_PLANE_ANGLE 0x3492
+#define EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE 0x3493
#endif /* EGL_ANGLE_image_d3d11_texture */
namespace gl {
-namespace {
-
-bool ValidGLInternalFormat(unsigned internal_format) {
- switch (internal_format) {
- case GL_RGB:
- case GL_RGBA:
- case GL_BGRA_EXT:
- return true;
- default:
- return false;
- }
-}
-
-bool ValidGLDataType(unsigned data_type) {
- switch (data_type) {
- case GL_UNSIGNED_BYTE:
- case GL_HALF_FLOAT_OES:
- return true;
- default:
- return false;
- }
-}
-
-} // namespace
-
GLImageD3D::GLImageD3D(const gfx::Size& size,
unsigned internal_format,
unsigned data_type,
+ const gfx::ColorSpace& color_space,
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture,
+ size_t array_slice,
+ size_t plane_index,
Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain)
: GLImage(),
size_(size),
internal_format_(internal_format),
data_type_(data_type),
texture_(std::move(texture)),
+ array_slice_(array_slice),
+ plane_index_(plane_index),
swap_chain_(std::move(swap_chain)) {
+ GLImage::SetColorSpace(color_space);
DCHECK(texture_);
- DCHECK(ValidGLInternalFormat(internal_format_));
- DCHECK(ValidGLDataType(data_type_));
}
GLImageD3D::~GLImageD3D() {
@@ -69,7 +50,12 @@ GLImageD3D::~GLImageD3D() {
bool GLImageD3D::Initialize() {
DCHECK_EQ(egl_image_, EGL_NO_IMAGE_KHR);
const EGLint attribs[] = {EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
- GetInternalFormat(), EGL_NONE};
+ internal_format_,
+ EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE,
+ array_slice_,
+ EGL_D3D11_TEXTURE_PLANE_ANGLE,
+ plane_index_,
+ EGL_NONE};
egl_image_ =
eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(), EGL_NO_CONTEXT,
EGL_D3D11_TEXTURE_ANGLE,
diff --git a/chromium/ui/gl/gl_image_d3d.h b/chromium/ui/gl/gl_image_d3d.h
index 6c5b2166256..fa62f424647 100644
--- a/chromium/ui/gl/gl_image_d3d.h
+++ b/chromium/ui/gl/gl_image_d3d.h
@@ -22,13 +22,19 @@ class GL_EXPORT GLImageD3D : public GLImage {
// |internal_format| and |data_type| are passed to ANGLE and used for GL
// operations. |internal_format| may be different from the internal format
// associated with the DXGI_FORMAT of the texture (e.g. RGB instead of
- // BGRA_EXT for DXGI_FORMAT_B8G8R8A8_UNORM). |data_type| should match the
- // data type accociated with the DXGI_FORMAT of the texture.
+ // BGRA_EXT for DXGI_FORMAT_B8G8R8A8_UNORM). |data_type| should match the data
+ // type accociated with the DXGI_FORMAT of the texture. |array_slice| is used
+ // when the |texture| is a D3D11 texture array, and |plane_index| is used for
+ // specifying the plane to bind to for multi-planar YUV textures.
+ // See EGL_ANGLE_d3d_texture_client_buffer spec for format restrictions.
GLImageD3D(const gfx::Size& size,
unsigned internal_format,
unsigned data_type,
+ const gfx::ColorSpace& color_space,
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture,
- Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain);
+ size_t array_slice = 0,
+ size_t plane_index = 0,
+ Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain = nullptr);
// Safe downcast. Returns nullptr on failure.
static GLImageD3D* FromGLImage(GLImage* image);
@@ -62,21 +68,28 @@ class GL_EXPORT GLImageD3D : public GLImage {
const Microsoft::WRL::ComPtr<ID3D11Texture2D>& texture() const {
return texture_;
}
-
const Microsoft::WRL::ComPtr<IDXGISwapChain1>& swap_chain() const {
return swap_chain_;
}
+ size_t array_slice() const { return array_slice_; }
+ size_t plane_index() const { return plane_index_; }
- private:
- ~GLImageD3D() override;
-
+ protected:
const gfx::Size size_;
const unsigned internal_format_; // GLenum
const unsigned data_type_; // GLenum
- void* egl_image_ = nullptr; // EGLImageKHR
+
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture_;
+ const size_t array_slice_;
+ const size_t plane_index_;
+
Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain_;
+ private:
+ ~GLImageD3D() override;
+
+ void* egl_image_ = nullptr; // EGLImageKHR
+
DISALLOW_COPY_AND_ASSIGN(GLImageD3D);
};
diff --git a/chromium/ui/gl/gl_image_d3d_unittest.cc b/chromium/ui/gl/gl_image_d3d_unittest.cc
index febd42eeb88..7b924d7021a 100644
--- a/chromium/ui/gl/gl_image_d3d_unittest.cc
+++ b/chromium/ui/gl/gl_image_d3d_unittest.cc
@@ -25,9 +25,9 @@ class GLImageD3DTestDelegate : public GLImageTestDelegateBase {
void WillTearDown() override { d3d11_device_ = nullptr; }
- base::Optional<GLImplementationParts> GetPreferedGLImplementation()
+ absl::optional<GLImplementationParts> GetPreferedGLImplementation()
const override {
- return base::Optional<GLImplementationParts>(
+ return absl::optional<GLImplementationParts>(
GLImplementationParts(ANGLEImplementation::kD3D11));
}
@@ -52,7 +52,8 @@ class GLImageD3DTestDelegate : public GLImageTestDelegateBase {
EXPECT_TRUE(SUCCEEDED(hr));
auto image = base::MakeRefCounted<GLImageD3D>(
- size, internal_format, data_type, std::move(d3d11_texture), nullptr);
+ size, internal_format, data_type, gfx::ColorSpace::CreateSRGB(),
+ std::move(d3d11_texture));
EXPECT_TRUE(image->Initialize());
return image;
}
diff --git a/chromium/ui/gl/gl_image_egl_pixmap.cc b/chromium/ui/gl/gl_image_egl_pixmap.cc
index 6c5612de92e..ac11b6d8196 100644
--- a/chromium/ui/gl/gl_image_egl_pixmap.cc
+++ b/chromium/ui/gl/gl_image_egl_pixmap.cc
@@ -6,10 +6,10 @@
#include <memory>
+#include "ui/gfx/x/connection.h"
#include "ui/gl/buffer_format_utils.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_surface_glx.h"
-#include "ui/gl/gl_visual_picker_glx.h"
namespace gl {
diff --git a/chromium/ui/gl/gl_image_glx.cc b/chromium/ui/gl/gl_image_glx.cc
index 01f95ed0445..29d182ec0e9 100644
--- a/chromium/ui/gl/gl_image_glx.cc
+++ b/chromium/ui/gl/gl_image_glx.cc
@@ -7,11 +7,11 @@
#include <memory>
#include "base/logging.h"
+#include "ui/base/x/visual_picker_glx.h"
#include "ui/gl/buffer_format_utils.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_image_glx.h"
#include "ui/gl/gl_surface_glx.h"
-#include "ui/gl/gl_visual_picker_glx.h"
#include "ui/gl/glx_util.h"
namespace gl {
@@ -46,7 +46,7 @@ GLImageGLX::~GLImageGLX() {
bool GLImageGLX::Initialize(x11::Pixmap pixmap) {
auto fbconfig_id =
- GLVisualPickerGLX::GetInstance()->GetFbConfigForFormat(format_);
+ ui::VisualPickerGlx::GetInstance()->GetFbConfigForFormat(format_);
auto* connection = x11::Connection::Get();
GLXFBConfig config = GetGlxFbConfigForXProtoFbConfig(connection, fbconfig_id);
diff --git a/chromium/ui/gl/gl_image_io_surface.h b/chromium/ui/gl/gl_image_io_surface.h
index 2c765ca2958..16c7594e9c5 100644
--- a/chromium/ui/gl/gl_image_io_surface.h
+++ b/chromium/ui/gl/gl_image_io_surface.h
@@ -31,7 +31,13 @@ class GL_EXPORT GLImageIOSurface : public GLImage {
static GLImageIOSurface* Create(const gfx::Size& size,
unsigned internalformat);
+ // Initialize to wrap of |io_surface|. The format of the plane to wrap is
+ // specified in |format|. The index of the plane to wrap is
+ // |io_surface_plane|. If |format| is a multi-planar format (e.g,
+ // YUV_420_BIPLANAR or P010), then this will automatically convert from YUV
+ // to RGB, and |io_surface_plane| is ignored.
bool Initialize(IOSurfaceRef io_surface,
+ uint32_t io_surface_plane,
gfx::GenericSharedMemoryId io_surface_id,
gfx::BufferFormat format);
@@ -112,6 +118,7 @@ class GL_EXPORT GLImageIOSurface : public GLImage {
base::ScopedCFTypeRef<IOSurfaceRef> io_surface_;
base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer_;
gfx::GenericSharedMemoryId io_surface_id_;
+ uint32_t io_surface_plane_ = 0;
base::ThreadChecker thread_checker_;
// The default value of Rec. 601 is based on historical shader code.
diff --git a/chromium/ui/gl/gl_image_io_surface.mm b/chromium/ui/gl/gl_image_io_surface.mm
index 697d6e26127..8fa77296d70 100644
--- a/chromium/ui/gl/gl_image_io_surface.mm
+++ b/chromium/ui/gl/gl_image_io_surface.mm
@@ -192,6 +192,7 @@ GLImageIOSurface::~GLImageIOSurface() {
}
bool GLImageIOSurface::Initialize(IOSurfaceRef io_surface,
+ uint32_t io_surface_plane,
gfx::GenericSharedMemoryId io_surface_id,
gfx::BufferFormat format) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -215,6 +216,7 @@ bool GLImageIOSurface::Initialize(IOSurfaceRef io_surface,
format_ = format;
io_surface_.reset(io_surface, base::scoped_policy::RETAIN);
io_surface_id_ = io_surface_id;
+ io_surface_plane_ = io_surface_plane;
return true;
}
@@ -223,12 +225,13 @@ bool GLImageIOSurface::InitializeWithCVPixelBuffer(
gfx::GenericSharedMemoryId io_surface_id,
gfx::BufferFormat format) {
IOSurfaceRef io_surface = CVPixelBufferGetIOSurface(cv_pixel_buffer);
+ const uint32_t io_surface_plane = 0;
if (!io_surface) {
LOG(ERROR) << "Can't init GLImage from CVPixelBuffer with no IOSurface";
return false;
}
- if (!Initialize(io_surface, io_surface_id, format))
+ if (!Initialize(io_surface, io_surface_plane, io_surface_id, format))
return false;
cv_pixel_buffer_.reset(cv_pixel_buffer, base::scoped_policy::RETAIN);
@@ -296,7 +299,7 @@ bool GLImageIOSurface::BindTexImageImpl(unsigned target,
CGLError cgl_error = CGLTexImageIOSurface2D(
cgl_context, GL_TEXTURE_RECTANGLE_ARB, texture_format, size_.width(),
size_.height(), DataFormat(format_), DataType(format_), io_surface_.get(),
- 0);
+ io_surface_plane_);
if (cgl_error != kCGLNoError) {
LOG(ERROR) << "Error in CGLTexImageIOSurface2D: "
<< CGLErrorString(cgl_error);
@@ -513,6 +516,7 @@ GLImageIOSurface* GLImageIOSurface::FromGLImage(GLImage* image) {
bool GLImageIOSurface::ValidFormat(gfx::BufferFormat format) {
switch (format) {
case gfx::BufferFormat::R_8:
+ case gfx::BufferFormat::RG_88:
case gfx::BufferFormat::BGRA_8888:
case gfx::BufferFormat::BGRX_8888:
case gfx::BufferFormat::RGBA_8888:
@@ -522,7 +526,6 @@ bool GLImageIOSurface::ValidFormat(gfx::BufferFormat format) {
case gfx::BufferFormat::P010:
return true;
case gfx::BufferFormat::R_16:
- case gfx::BufferFormat::RG_88:
case gfx::BufferFormat::BGR_565:
case gfx::BufferFormat::RGBA_4444:
case gfx::BufferFormat::RGBX_8888:
diff --git a/chromium/ui/gl/gl_image_io_surface_egl.mm b/chromium/ui/gl/gl_image_io_surface_egl.mm
index 82222eeb9c9..48c9f2d4cba 100644
--- a/chromium/ui/gl/gl_image_io_surface_egl.mm
+++ b/chromium/ui/gl/gl_image_io_surface_egl.mm
@@ -212,7 +212,7 @@ bool GLImageIOSurfaceEGL::BindTexImageImpl(unsigned target,
const EGLint attribs[] = {
EGL_WIDTH, size_.width(),
EGL_HEIGHT, size_.height(),
- EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_IOSURFACE_PLANE_ANGLE, io_surface_plane_,
EGL_TEXTURE_TARGET, texture_target_,
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, formatType.format,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
diff --git a/chromium/ui/gl/gl_image_io_surface_unittest.cc b/chromium/ui/gl/gl_image_io_surface_unittest.cc
index 3488aebbdc7..c1e0e57b502 100644
--- a/chromium/ui/gl/gl_image_io_surface_unittest.cc
+++ b/chromium/ui/gl/gl_image_io_surface_unittest.cc
@@ -27,8 +27,9 @@ class GLImageIOSurfaceTestDelegate : public GLImageTestDelegateBase {
scoped_refptr<GLImageIOSurface> image(GLImageIOSurface::Create(
size, GLImageIOSurface::GetInternalFormatForTesting(format)));
IOSurfaceRef surface_ref = gfx::CreateIOSurface(size, format);
- bool rv =
- image->Initialize(surface_ref, gfx::GenericSharedMemoryId(1), format);
+ const uint32_t surface_plane = 0;
+ bool rv = image->Initialize(surface_ref, surface_plane,
+ gfx::GenericSharedMemoryId(1), format);
EXPECT_TRUE(rv);
return image;
}
@@ -38,6 +39,7 @@ class GLImageIOSurfaceTestDelegate : public GLImageTestDelegateBase {
scoped_refptr<GLImageIOSurface> image(GLImageIOSurface::Create(
size, GLImageIOSurface::GetInternalFormatForTesting(format)));
IOSurfaceRef surface_ref = gfx::CreateIOSurface(size, format);
+ const uint32_t surface_plane = 0;
IOReturn status = IOSurfaceLock(surface_ref, 0, nullptr);
EXPECT_NE(status, kIOReturnCannotLock);
@@ -64,8 +66,8 @@ class GLImageIOSurfaceTestDelegate : public GLImageTestDelegateBase {
}
IOSurfaceUnlock(surface_ref, 0, nullptr);
- bool rv =
- image->Initialize(surface_ref, gfx::GenericSharedMemoryId(1), format);
+ bool rv = image->Initialize(surface_ref, surface_plane,
+ gfx::GenericSharedMemoryId(1), format);
EXPECT_TRUE(rv);
return image;
diff --git a/chromium/ui/gl/gl_image_memory.cc b/chromium/ui/gl/gl_image_memory.cc
index 2a5849f9c82..73955929055 100644
--- a/chromium/ui/gl/gl_image_memory.cc
+++ b/chromium/ui/gl/gl_image_memory.cc
@@ -120,7 +120,7 @@ std::vector<uint8_t> GLES2RGB565Data(const gfx::Size& size,
return gles2_rgb_data;
}
-base::Optional<std::vector<uint8_t>> GLES2Data(const gfx::Size& size,
+absl::optional<std::vector<uint8_t>> GLES2Data(const gfx::Size& size,
gfx::BufferFormat format,
size_t stride,
const uint8_t* data,
@@ -132,7 +132,7 @@ base::Optional<std::vector<uint8_t>> GLES2Data(const gfx::Size& size,
switch (format) {
case gfx::BufferFormat::RGBX_8888:
- return base::make_optional(GLES2RGBData(
+ return absl::make_optional(GLES2RGBData(
size, stride, data,
[](const uint8_t* src, uint8_t* dst) {
dst[0] = src[0];
@@ -141,10 +141,10 @@ base::Optional<std::vector<uint8_t>> GLES2Data(const gfx::Size& size,
},
data_format, data_type, data_row_length));
case gfx::BufferFormat::BGR_565:
- return base::make_optional(GLES2RGB565Data(
+ return absl::make_optional(GLES2RGB565Data(
size, stride, data, data_format, data_type, data_row_length));
case gfx::BufferFormat::BGRX_8888:
- return base::make_optional(GLES2RGBData(
+ return absl::make_optional(GLES2RGBData(
size, stride, data,
[](const uint8_t* src, uint8_t* dst) {
dst[0] = src[2];
@@ -165,7 +165,7 @@ base::Optional<std::vector<uint8_t>> GLES2Data(const gfx::Size& size,
RowSizeForBufferFormat(size.width(), format, 0);
if (stride == gles2_data_stride ||
g_current_gl_driver->ext.b_GL_EXT_unpack_subimage)
- return base::nullopt; // No data conversion needed
+ return absl::nullopt; // No data conversion needed
std::vector<uint8_t> gles2_data(gles2_data_stride * size.height());
for (int y = 0; y < size.height(); ++y) {
@@ -173,17 +173,17 @@ base::Optional<std::vector<uint8_t>> GLES2Data(const gfx::Size& size,
gles2_data_stride);
}
*data_row_length = size.width();
- return base::make_optional(gles2_data);
+ return absl::make_optional(gles2_data);
}
case gfx::BufferFormat::YVU_420:
case gfx::BufferFormat::YUV_420_BIPLANAR:
case gfx::BufferFormat::P010:
NOTREACHED() << gfx::BufferFormatToString(format);
- return base::nullopt;
+ return absl::nullopt;
}
NOTREACHED();
- return base::nullopt;
+ return absl::nullopt;
}
void MemcpyTask(const void* src,
@@ -340,7 +340,7 @@ bool GLImageMemory::CopyTexImage(unsigned target) {
GLenum data_format = GetDataFormat();
GLenum data_type = GetDataType();
GLint data_row_length = DataRowLength(stride_, format_);
- base::Optional<std::vector<uint8_t>> gles2_data;
+ absl::optional<std::vector<uint8_t>> gles2_data;
GLContext* context = GLContext::GetCurrent();
DCHECK(context);
@@ -430,7 +430,7 @@ bool GLImageMemory::CopyTexSubImage(unsigned target,
GLenum data_format = GetDataFormat();
GLenum data_type = GetDataType();
GLint data_row_length = DataRowLength(stride_, format_);
- base::Optional<std::vector<uint8_t>> gles2_data;
+ absl::optional<std::vector<uint8_t>> gles2_data;
if (GLContext::GetCurrent()->GetVersionInfo()->is_es) {
gles2_data = GLES2Data(rect.size(), format_, stride_, data, &data_format,
diff --git a/chromium/ui/gl/gl_image_native_pixmap_unittest.cc b/chromium/ui/gl/gl_image_native_pixmap_unittest.cc
index cc1ec600556..481874771a4 100644
--- a/chromium/ui/gl/gl_image_native_pixmap_unittest.cc
+++ b/chromium/ui/gl/gl_image_native_pixmap_unittest.cc
@@ -32,13 +32,13 @@ const uint8_t kImageColor[] = {0x30, 0x40, 0x10, 0xFF};
template <gfx::BufferFormat format>
class GLImageNativePixmapTestDelegate : public GLImageTestDelegateBase {
public:
- base::Optional<GLImplementationParts> GetPreferedGLImplementation()
+ absl::optional<GLImplementationParts> GetPreferedGLImplementation()
const override {
#if defined(OS_WIN)
- return base::Optional<GLImplementationParts>(GLImplementationParts(
+ return absl::optional<GLImplementationParts>(GLImplementationParts(
kGLImplementationEGLANGLE, ANGLEImplementation::kNone));
#else
- return base::Optional<GLImplementationParts>(
+ return absl::optional<GLImplementationParts>(
GLImplementationParts(kGLImplementationEGLGLES2));
#endif
}
diff --git a/chromium/ui/gl/gl_implementation.cc b/chromium/ui/gl/gl_implementation.cc
index 5acbd036bd8..3a1baf0d809 100644
--- a/chromium/ui/gl/gl_implementation.cc
+++ b/chromium/ui/gl/gl_implementation.cc
@@ -205,6 +205,19 @@ void SetSoftwareGLCommandLineSwitches(base::CommandLine* command_line,
}
}
+void SetSoftwareWebGLCommandLineSwitches(base::CommandLine* command_line,
+ bool legacy_software_gl) {
+ if (legacy_software_gl) {
+ command_line->AppendSwitchASCII(switches::kUseGL,
+ kGLImplementationSwiftShaderForWebGLName);
+ } else {
+ command_line->AppendSwitchASCII(switches::kUseGL,
+ kGLImplementationANGLEName);
+ command_line->AppendSwitchASCII(
+ switches::kUseANGLE, kANGLEImplementationSwiftShaderForWebGLName);
+ }
+}
+
const char* GetGLImplementationGLName(GLImplementationParts implementation) {
for (auto name_pair : kGLImplementationNamePairs) {
if (implementation.gl == name_pair.implementation.gl &&
diff --git a/chromium/ui/gl/gl_implementation.h b/chromium/ui/gl/gl_implementation.h
index 2c34023a859..054d2c29a41 100644
--- a/chromium/ui/gl/gl_implementation.h
+++ b/chromium/ui/gl/gl_implementation.h
@@ -140,6 +140,11 @@ GL_EXPORT GLImplementationParts GetSoftwareGLForTestsImplementation();
GL_EXPORT void SetSoftwareGLCommandLineSwitches(base::CommandLine* command_line,
bool legacy_software_gl);
+// Set the software WebGL implementation on the provided command line
+GL_EXPORT void SetSoftwareWebGLCommandLineSwitches(
+ base::CommandLine* command_line,
+ bool legacy_software_gl);
+
// Whether the implementation is one of the software GL implementations
GL_EXPORT bool IsSoftwareGLImplementation(GLImplementationParts implementation);
diff --git a/chromium/ui/gl/gl_share_group.h b/chromium/ui/gl/gl_share_group.h
index bf9bdf1c9aa..9ca5025a830 100644
--- a/chromium/ui/gl/gl_share_group.h
+++ b/chromium/ui/gl/gl_share_group.h
@@ -6,7 +6,6 @@
#define UI_GL_GL_SHARE_GROUP_H_
#include <set>
-#include <unordered_map>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
diff --git a/chromium/ui/gl/gl_stub_autogen_gl.h b/chromium/ui/gl/gl_stub_autogen_gl.h
index 72a2fdfdf31..84c2e01814a 100644
--- a/chromium/ui/gl/gl_stub_autogen_gl.h
+++ b/chromium/ui/gl/gl_stub_autogen_gl.h
@@ -8,8 +8,8 @@
// clang-format -i -style=chromium filename
// DO NOT EDIT!
-#ifndef UI_GL_GL_STUB_AUTOGEN_H_
-#define UI_GL_GL_STUB_AUTOGEN_H_
+#ifndef UI_GL_GL_STUB_AUTOGEN_GL_H_
+#define UI_GL_GL_STUB_AUTOGEN_GL_H_
void glActiveShaderProgramFn(GLuint pipeline, GLuint program) override {}
void glActiveTextureFn(GLenum texture) override {}
@@ -1664,4 +1664,4 @@ void glWindowRectanglesEXTFn(GLenum mode,
GLsizei n,
const GLint* box) override {}
-#endif // UI_GL_GL_STUB_AUTOGEN_H_ \ No newline at end of file
+#endif // UI_GL_GL_STUB_AUTOGEN_GL_H_
diff --git a/chromium/ui/gl/gl_surface.cc b/chromium/ui/gl/gl_surface.cc
index c180260e045..80c8725f8a5 100644
--- a/chromium/ui/gl/gl_surface.cc
+++ b/chromium/ui/gl/gl_surface.cc
@@ -255,6 +255,12 @@ bool GLSurface::SupportsDelegatedInk() {
return false;
}
+void GLSurface::InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver) {
+ NOTREACHED();
+}
+
void GLSurface::SetGpuVSyncEnabled(bool enabled) {}
GLSurface* GLSurface::GetCurrent() {
@@ -552,6 +558,12 @@ void GLSurfaceAdapter::SetDelegatedInkTrailStartPoint(
surface_->SetDelegatedInkTrailStartPoint(std::move(metadata));
}
+void GLSurfaceAdapter::InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver) {
+ surface_->InitDelegatedInkPointRendererReceiver(std::move(pending_receiver));
+}
+
GLSurfaceAdapter::~GLSurfaceAdapter() = default;
scoped_refptr<GLSurface> InitializeGLSurfaceWithFormat(
diff --git a/chromium/ui/gl/gl_surface.h b/chromium/ui/gl/gl_surface.h
index 6aa6a8dded5..9eb8f719824 100644
--- a/chromium/ui/gl/gl_surface.h
+++ b/chromium/ui/gl/gl_surface.h
@@ -13,6 +13,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/gfx/delegated_ink_metadata.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -29,6 +30,9 @@
#include "ui/gl/gl_surface_format.h"
namespace gfx {
+namespace mojom {
+class DelegatedInkPointRenderer;
+} // namespace mojom
class ColorSpace;
class GpuFence;
class VSyncProvider;
@@ -325,6 +329,9 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface>,
virtual bool SupportsDelegatedInk();
virtual void SetDelegatedInkTrailStartPoint(
std::unique_ptr<gfx::DelegatedInkMetadata> metadata) {}
+ virtual void InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver);
protected:
virtual ~GLSurface();
@@ -424,6 +431,9 @@ class GL_EXPORT GLSurfaceAdapter : public GLSurface {
bool SupportsDelegatedInk() override;
void SetDelegatedInkTrailStartPoint(
std::unique_ptr<gfx::DelegatedInkMetadata> metadata) override;
+ void InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver) override;
GLSurface* surface() const { return surface_.get(); }
diff --git a/chromium/ui/gl/gl_surface_egl.cc b/chromium/ui/gl/gl_surface_egl.cc
index cce04278d5e..f7928a8a4bc 100644
--- a/chromium/ui/gl/gl_surface_egl.cc
+++ b/chromium/ui/gl/gl_surface_egl.cc
@@ -907,7 +907,8 @@ void GetEGLInitDisplays(bool supports_angle_d3d,
}
if (supports_angle_swiftshader) {
- if (requested_renderer == kANGLEImplementationSwiftShaderName) {
+ if (requested_renderer == kANGLEImplementationSwiftShaderName ||
+ requested_renderer == kANGLEImplementationSwiftShaderForWebGLName) {
AddInitDisplay(init_displays, ANGLE_SWIFTSHADER);
}
}
@@ -1362,7 +1363,7 @@ EGLDisplay GLSurfaceEGL::InitializeDisplay(EGLDisplayPlatform native_display) {
#if defined(USE_X11)
// Unset DISPLAY env, so the vulkan can be initialized successfully, if the
// X server doesn't support Vulkan surface.
- base::Optional<ui::ScopedUnsetDisplay> unset_display;
+ absl::optional<ui::ScopedUnsetDisplay> unset_display;
if (display_type == ANGLE_VULKAN && !ui::IsVulkanSurfaceSupported())
unset_display.emplace();
#endif // defined(USE_X11)
@@ -1602,6 +1603,9 @@ void NativeViewGLSurfaceEGL::SetEnableSwapTimestamps() {
presentation_flags_ = gfx::PresentationFeedback::kVSync |
gfx::PresentationFeedback::kHWCompletion;
break;
+ case EGL_RENDERING_COMPLETE_TIME_ANDROID:
+ writes_done_index_ = static_cast<int>(supported_egl_timestamps_.size());
+ break;
}
// Stored in separate vectors so we can pass the egl timestamps
@@ -1879,6 +1883,7 @@ bool NativeViewGLSurfaceEGL::IsEGLTimestampSupported() const {
bool NativeViewGLSurfaceEGL::GetFrameTimestampInfoIfAvailable(
base::TimeTicks* presentation_time,
base::TimeDelta* composite_interval,
+ base::TimeTicks* writes_done_time,
uint32_t* presentation_flags,
int frame_id) {
DCHECK(presentation_time);
@@ -1961,6 +1966,17 @@ bool NativeViewGLSurfaceEGL::GetFrameTimestampInfoIfAvailable(
base::TimeDelta::FromNanoseconds(presentation_time_ns);
*presentation_flags = presentation_flags_;
}
+
+ // Get the WritesDone time if available, otherwise set to a null TimeTicks.
+ EGLnsecsANDROID writes_done_time_ns = egl_timestamps[writes_done_index_];
+ if (writes_done_time_ns == EGL_TIMESTAMP_INVALID_ANDROID ||
+ writes_done_time_ns == EGL_TIMESTAMP_PENDING_ANDROID) {
+ *writes_done_time = base::TimeTicks();
+ } else {
+ *writes_done_time = base::TimeTicks() +
+ base::TimeDelta::FromNanoseconds(writes_done_time_ns);
+ }
+
return true;
}
diff --git a/chromium/ui/gl/gl_surface_egl.h b/chromium/ui/gl/gl_surface_egl.h
index c649b5fa7b5..abe2f3f3bec 100644
--- a/chromium/ui/gl/gl_surface_egl.h
+++ b/chromium/ui/gl/gl_surface_egl.h
@@ -189,6 +189,7 @@ class GL_EXPORT NativeViewGLSurfaceEGL : public GLSurfaceEGL,
bool GetFrameTimestampInfoIfAvailable(base::TimeTicks* presentation_time,
base::TimeDelta* composite_interval,
+ base::TimeTicks* writes_done_time,
uint32_t* presentation_flags,
int frame_id) override;
@@ -239,6 +240,7 @@ class GL_EXPORT NativeViewGLSurfaceEGL : public GLSurfaceEGL,
// PresentationFeedback support.
int presentation_feedback_index_ = -1;
int composition_start_index_ = -1;
+ int writes_done_index_ = -1;
uint32_t presentation_flags_ = 0;
base::queue<SwapInfo> swap_info_queue_;
diff --git a/chromium/ui/gl/gl_surface_egl_surface_control.cc b/chromium/ui/gl/gl_surface_egl_surface_control.cc
index 66a7c373337..2c7f88ccc79 100644
--- a/chromium/ui/gl/gl_surface_egl_surface_control.cc
+++ b/chromium/ui/gl/gl_surface_egl_surface_control.cc
@@ -66,7 +66,8 @@ GLSurfaceEGLSurfaceControl::GLSurfaceEGLSurfaceControl(
root_surface_(
new gfx::SurfaceControl::Surface(window, root_surface_name_.c_str())),
transaction_ack_timeout_manager_(task_runner),
- gpu_task_runner_(std::move(task_runner)) {}
+ gpu_task_runner_(std::move(task_runner)),
+ using_on_commit_callback_(gfx::SurfaceControl::SupportsOnCommit()) {}
GLSurfaceEGLSurfaceControl::~GLSurfaceEGLSurfaceControl() {
Destroy();
@@ -269,6 +270,14 @@ void GLSurfaceEGLSurfaceControl::CommitPendingTransaction(
std::move(primary_plane_fences_));
primary_plane_fences_.reset();
pending_transaction_->SetOnCompleteCb(std::move(callback), gpu_task_runner_);
+
+ if (using_on_commit_callback_) {
+ gfx::SurfaceControl::Transaction::OnCommitCb callback = base::BindOnce(
+ &GLSurfaceEGLSurfaceControl::OnTransactionCommittedOnGpuThread,
+ weak_factory_.GetWeakPtr());
+ pending_transaction_->SetOnCommitCb(std::move(callback), gpu_task_runner_);
+ }
+
pending_surfaces_count_ = 0u;
frame_rate_update_pending_ = false;
@@ -387,8 +396,33 @@ bool GLSurfaceEGLSurfaceControl::ScheduleOverlayPlane(
gfx::RectF scaled_rect =
gfx::ScaleRect(crop_rect, buffer_size.width(), buffer_size.height());
- gfx::Rect src = gfx::ToEnclosedRect(scaled_rect);
gfx::Rect dst = bounds_rect;
+ gfx::Rect src = gfx::ToEnclosedRect(scaled_rect);
+
+ // When the video is being scrolled offscreen DisplayCompositor will crop it
+ // to only visible portion and adjust crop_rect accordingly. When the video
+ // is smaller than the surface is can lead to the crop rect being less than
+ // a pixel in size. This adjusts the crop rect size to at least 1 pixel as
+ // we want to stretch last visible pixel line/column in this case.
+ // Note: We will do it even if crop_rect width/height is exact 0.0f. In
+ // reality this should never happen and there is no way to display video
+ // with empty crop rect, so display compositor should not request this.
+
+ if (src.width() == 0) {
+ src.set_width(1);
+ if (src.right() > buffer_size.width())
+ src.set_x(buffer_size.width() - 1);
+ }
+ if (src.height() == 0) {
+ src.set_height(1);
+ if (src.bottom() > buffer_size.height())
+ src.set_y(buffer_size.height() - 1);
+ }
+
+ // When display compositor rounds up destination rect to integer coordinates
+ // it becomes slightly bigger. After we adjust source rect accordingly, it
+ // can become larger then a buffer so we clip it here. See crbug.com/1083412
+ src.Intersect(gfx::Rect(buffer_size));
if (uninitialized || surface_state.src != src || surface_state.dst != dst ||
surface_state.transform != transform) {
@@ -446,16 +480,13 @@ void GLSurfaceEGLSurfaceControl::OnTransactionAckOnGpuThread(
SwapCompletionCallback completion_callback,
PresentationCallback presentation_callback,
ResourceRefs released_resources,
- base::Optional<PrimaryPlaneFences> primary_plane_fences,
+ absl::optional<PrimaryPlaneFences> primary_plane_fences,
gfx::SurfaceControl::TransactionStats transaction_stats) {
TRACE_EVENT0("gpu",
"GLSurfaceEGLSurfaceControl::OnTransactionAckOnGpuThread");
DCHECK(gpu_task_runner_->BelongsToCurrentThread());
- DCHECK(transaction_ack_pending_);
-
transaction_ack_timeout_manager_.OnTransactionAck();
- transaction_ack_pending_ = false;
const bool has_context = context_->MakeCurrent(this);
for (auto& surface_stat : transaction_stats.surface_stats) {
@@ -501,6 +532,23 @@ void GLSurfaceEGLSurfaceControl::OnTransactionAckOnGpuThread(
CheckPendingPresentationCallbacks();
+ // If we don't use OnCommit, we advance transaction queue after we received
+ // OnComplete.
+ if (!using_on_commit_callback_)
+ AdvanceTransactionQueue();
+}
+
+void GLSurfaceEGLSurfaceControl::OnTransactionCommittedOnGpuThread() {
+ TRACE_EVENT0("gpu",
+ "GLSurfaceEGLSurfaceControl::OnTransactionCommittedOnGpuThread");
+ DCHECK(using_on_commit_callback_);
+ AdvanceTransactionQueue();
+}
+
+void GLSurfaceEGLSurfaceControl::AdvanceTransactionQueue() {
+ DCHECK(transaction_ack_pending_);
+ transaction_ack_pending_ = false;
+
if (!pending_transaction_queue_.empty()) {
transaction_ack_pending_ = true;
pending_transaction_queue_.front().Apply();
diff --git a/chromium/ui/gl/gl_surface_egl_surface_control.h b/chromium/ui/gl/gl_surface_egl_surface_control.h
index ba24b4ca19a..c1735232f6a 100644
--- a/chromium/ui/gl/gl_surface_egl_surface_control.h
+++ b/chromium/ui/gl/gl_surface_egl_surface_control.h
@@ -12,7 +12,7 @@
#include "base/cancelable_callback.h"
#include "base/containers/flat_map.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/android/android_surface_control_compat.h"
#include "ui/gl/gl_export.h"
#include "ui/gl/gl_surface_egl.h"
@@ -185,9 +185,14 @@ class GL_EXPORT GLSurfaceEGLSurfaceControl : public GLSurfaceEGL {
SwapCompletionCallback completion_callback,
PresentationCallback presentation_callback,
ResourceRefs released_resources,
- base::Optional<PrimaryPlaneFences> primary_plane_fences,
+ absl::optional<PrimaryPlaneFences> primary_plane_fences,
gfx::SurfaceControl::TransactionStats transaction_stats);
+ // Called on the |gpu_task_runner_| when a transaction is committed by the
+ // framework.
+ void OnTransactionCommittedOnGpuThread();
+
+ void AdvanceTransactionQueue();
void CheckPendingPresentationCallbacks();
gfx::Rect ApplyDisplayInverse(const gfx::Rect& input) const;
@@ -201,7 +206,7 @@ class GL_EXPORT GLSurfaceEGLSurfaceControl : public GLSurfaceEGL {
gfx::Rect window_rect_;
// Holds the surface state changes made since the last call to SwapBuffers.
- base::Optional<gfx::SurfaceControl::Transaction> pending_transaction_;
+ absl::optional<gfx::SurfaceControl::Transaction> pending_transaction_;
size_t pending_surfaces_count_ = 0u;
// Resources in the pending frame, for which updates are being
// collected in |pending_transaction_|. These are resources for which the
@@ -211,7 +216,7 @@ class GL_EXPORT GLSurfaceEGLSurfaceControl : public GLSurfaceEGL {
// The fences associated with the primary plane (renderer by the display
// compositor) for the pending frame.
- base::Optional<PrimaryPlaneFences> primary_plane_fences_;
+ absl::optional<PrimaryPlaneFences> primary_plane_fences_;
// Transactions waiting to be applied once the previous transaction is acked.
std::queue<gfx::SurfaceControl::Transaction> pending_transaction_queue_;
@@ -255,6 +260,9 @@ class GL_EXPORT GLSurfaceEGLSurfaceControl : public GLSurfaceEGL {
bool preserve_children_ = false;
scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_;
+
+ const bool using_on_commit_callback_;
+
base::WeakPtrFactory<GLSurfaceEGLSurfaceControl> weak_factory_{this};
};
diff --git a/chromium/ui/gl/gl_surface_egl_x11.cc b/chromium/ui/gl/gl_surface_egl_x11.cc
index 8b48842f495..d85d99967da 100644
--- a/chromium/ui/gl/gl_surface_egl_x11.cc
+++ b/chromium/ui/gl/gl_surface_egl_x11.cc
@@ -4,7 +4,7 @@
#include "ui/gl/gl_surface_egl_x11.h"
-#include "base/stl_util.h"
+#include "base/containers/contains.h"
#include "ui/base/x/x11_util.h"
#include "ui/base/x/x11_xrandr_interval_only_vsync_provider.h"
#include "ui/gfx/x/xproto.h"
diff --git a/chromium/ui/gl/gl_surface_egl_x11_gles2.h b/chromium/ui/gl/gl_surface_egl_x11_gles2.h
index 55ff91f670a..17c4d07b179 100644
--- a/chromium/ui/gl/gl_surface_egl_x11_gles2.h
+++ b/chromium/ui/gl/gl_surface_egl_x11_gles2.h
@@ -7,7 +7,6 @@
#include <stdint.h>
-#include <string>
#include "base/macros.h"
#include "ui/gfx/x/event.h"
diff --git a/chromium/ui/gl/gl_surface_glx.cc b/chromium/ui/gl/gl_surface_glx.cc
index 6a8e2536b81..1e40d49e3f5 100644
--- a/chromium/ui/gl/gl_surface_glx.cc
+++ b/chromium/ui/gl/gl_surface_glx.cc
@@ -22,6 +22,7 @@
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "ui/base/x/visual_picker_glx.h"
#include "ui/base/x/x11_display_util.h"
#include "ui/base/x/x11_util.h"
#include "ui/base/x/x11_xrandr_interval_only_vsync_provider.h"
@@ -32,7 +33,6 @@
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface_presentation_helper.h"
-#include "ui/gl/gl_visual_picker_glx.h"
#include "ui/gl/glx_util.h"
#include "ui/gl/sync_control_vsync_provider.h"
@@ -437,7 +437,7 @@ bool GLSurfaceGLX::InitializeOneOff() {
return false;
}
- auto* visual_picker = gl::GLVisualPickerGLX::GetInstance();
+ auto* visual_picker = ui::VisualPickerGlx::GetInstance();
auto visual_id = visual_picker->rgba_visual();
if (visual_id == x11::VisualId{})
visual_id = visual_picker->system_visual();
diff --git a/chromium/ui/gl/gl_surface_presentation_helper.cc b/chromium/ui/gl/gl_surface_presentation_helper.cc
index 0521b51d4ad..901e025159d 100644
--- a/chromium/ui/gl/gl_surface_presentation_helper.cc
+++ b/chromium/ui/gl/gl_surface_presentation_helper.cc
@@ -67,12 +67,13 @@ bool GLSurfacePresentationHelper::GetFrameTimestampInfoIfAvailable(
const Frame& frame,
base::TimeTicks* timestamp,
base::TimeDelta* interval,
+ base::TimeTicks* writes_done,
uint32_t* flags) {
DCHECK(frame.timer || frame.fence || egl_timestamp_client_);
if (egl_timestamp_client_) {
bool result = egl_timestamp_client_->GetFrameTimestampInfoIfAvailable(
- timestamp, interval, flags, frame.frame_id);
+ timestamp, interval, writes_done, flags, frame.frame_id);
// Workaround null timestamp by setting it to TimeTicks::Now() snapped to
// the next vsync interval. See
@@ -319,14 +320,17 @@ void GLSurfacePresentationHelper::CheckPendingFrames() {
base::TimeTicks timestamp;
base::TimeDelta interval;
+ base::TimeTicks writes_done;
uint32_t flags = 0;
// Get timestamp info for a frame if available. If timestamp is not
// available, it means this frame is not yet done.
- if (!GetFrameTimestampInfoIfAvailable(frame, &timestamp, &interval, &flags))
+ if (!GetFrameTimestampInfoIfAvailable(frame, &timestamp, &interval,
+ &writes_done, &flags))
break;
- frame_presentation_callback(
- gfx::PresentationFeedback(timestamp, interval, flags));
+ gfx::PresentationFeedback feedback(timestamp, interval, flags);
+ feedback.writes_done_timestamp = writes_done;
+ frame_presentation_callback(feedback);
}
if (!pending_frames_.empty())
diff --git a/chromium/ui/gl/gl_surface_presentation_helper.h b/chromium/ui/gl/gl_surface_presentation_helper.h
index 67a163c7a7f..097989f81ac 100644
--- a/chromium/ui/gl/gl_surface_presentation_helper.h
+++ b/chromium/ui/gl/gl_surface_presentation_helper.h
@@ -83,6 +83,7 @@ class GL_EXPORT GLSurfacePresentationHelper {
bool GetFrameTimestampInfoIfAvailable(const Frame& frame,
base::TimeTicks* timestamp,
base::TimeDelta* interval,
+ base::TimeTicks* writes_done,
uint32_t* flags);
// Check |pending_frames_| and run presentation callbacks.
diff --git a/chromium/ui/gl/gl_switches.cc b/chromium/ui/gl/gl_switches.cc
index 8c94f9f2a7f..f95cc05e019 100644
--- a/chromium/ui/gl/gl_switches.cc
+++ b/chromium/ui/gl/gl_switches.cc
@@ -34,6 +34,7 @@ const char kANGLEImplementationOpenGLESEGLName[] = "gles-egl";
const char kANGLEImplementationNullName[] = "null";
const char kANGLEImplementationVulkanName[] = "vulkan";
const char kANGLEImplementationSwiftShaderName[] = "swiftshader";
+const char kANGLEImplementationSwiftShaderForWebGLName[] = "swiftshader-webgl";
const char kANGLEImplementationMetalName[] = "metal";
const char kANGLEImplementationNoneName[] = "";
diff --git a/chromium/ui/gl/gl_switches.h b/chromium/ui/gl/gl_switches.h
index 184f9a44dbb..36c44d1a9e2 100644
--- a/chromium/ui/gl/gl_switches.h
+++ b/chromium/ui/gl/gl_switches.h
@@ -34,6 +34,7 @@ GL_EXPORT extern const char kANGLEImplementationOpenGLESEGLName[];
GL_EXPORT extern const char kANGLEImplementationNullName[];
GL_EXPORT extern const char kANGLEImplementationVulkanName[];
GL_EXPORT extern const char kANGLEImplementationSwiftShaderName[];
+GL_EXPORT extern const char kANGLEImplementationSwiftShaderForWebGLName[];
GL_EXPORT extern const char kANGLEImplementationMetalName[];
GL_EXPORT extern const char kANGLEImplementationNoneName[];
diff --git a/chromium/ui/gl/gl_utils.cc b/chromium/ui/gl/gl_utils.cc
index 77d3d1ad124..d404739aeaf 100644
--- a/chromium/ui/gl/gl_utils.cc
+++ b/chromium/ui/gl/gl_utils.cc
@@ -27,9 +27,10 @@
#endif
#if defined(USE_X11) || defined(USE_OZONE_PLATFORM_X11)
+#include "ui/base/x/visual_picker_glx.h" // nogncheck
#include "ui/gfx/linux/gpu_memory_buffer_support_x11.h" // nogncheck
+#include "ui/gfx/x/glx.h" // nogncheck
#include "ui/gl/gl_implementation.h" // nogncheck
-#include "ui/gl/gl_visual_picker_glx.h" // nogncheck
#endif
namespace gl {
@@ -87,8 +88,7 @@ bool UsePassthroughCommandDecoder(const base::CommandLine* command_line) {
return false;
} else {
// Unrecognized or missing switch, use the default.
- return base::FeatureList::IsEnabled(
- features::kDefaultPassthroughCommandDecoder);
+ return features::UsePassthroughCommandDecoder();
}
}
@@ -163,12 +163,9 @@ void CollectX11GpuExtraInfo(bool enable_native_gpu_memory_buffers,
}
if (GetGLImplementation() == kGLImplementationDesktopGL) {
- // Create the GLVisualPickerGLX singleton now while the GbmSupportX11
+ // Create the VisualPickerGlx singleton now while the GbmSupportX11
// singleton is busy being created on another thread.
- GLVisualPickerGLX* visual_picker = GLVisualPickerGLX::GetInstance();
-
- info.system_visual = visual_picker->system_visual();
- info.rgba_visual = visual_picker->rgba_visual();
+ auto* visual_picker = ui::VisualPickerGlx::GetInstance();
// With GLX, only BGR(A) buffer formats are supported. EGL does not have
// this restriction.
diff --git a/chromium/ui/gl/gl_version_info.cc b/chromium/ui/gl/gl_version_info.cc
index f948e8983f0..2a1fa2f8968 100644
--- a/chromium/ui/gl/gl_version_info.cc
+++ b/chromium/ui/gl/gl_version_info.cc
@@ -56,7 +56,7 @@ void GLVersionInfo::Initialize(const char* version_str,
is_angle_swiftshader =
renderer_string.find("SwiftShader Device") != std::string::npos;
is_angle_vulkan = renderer_string.find("Vulkan") != std::string::npos;
- is_angle_metal = renderer_string.find("Metal") != std::string::npos;
+ is_angle_metal = renderer_string.find("ANGLE Metal") != std::string::npos;
}
is_swiftshader = base::StartsWith(renderer_str, "Google SwiftShader",
@@ -253,7 +253,7 @@ void GLVersionInfo::ExtractDriverVendorANGLE(const char* renderer_str) {
driver_vendor = "ANGLE (Google)";
}
if (is_angle_metal) {
- DCHECK(base::StartsWith(rstr, "Metal", base::CompareCase::SENSITIVE));
+ DCHECK(base::StartsWith(rstr, "ANGLE Metal", base::CompareCase::SENSITIVE));
}
if (base::StartsWith(rstr, "NVIDIA ", base::CompareCase::SENSITIVE))
driver_vendor = "ANGLE (NVIDIA)";
diff --git a/chromium/ui/gl/hdr_metadata_helper_win.cc b/chromium/ui/gl/hdr_metadata_helper_win.cc
index 633ed290010..240d64fd8c5 100644
--- a/chromium/ui/gl/hdr_metadata_helper_win.cc
+++ b/chromium/ui/gl/hdr_metadata_helper_win.cc
@@ -22,7 +22,7 @@ HDRMetadataHelperWin::HDRMetadataHelperWin(
HDRMetadataHelperWin::~HDRMetadataHelperWin() = default;
-base::Optional<DXGI_HDR_METADATA_HDR10>
+absl::optional<DXGI_HDR_METADATA_HDR10>
HDRMetadataHelperWin::GetDisplayMetadata() {
return hdr_metadata_;
}
diff --git a/chromium/ui/gl/hdr_metadata_helper_win.h b/chromium/ui/gl/hdr_metadata_helper_win.h
index d276f052bf6..2a5a226806b 100644
--- a/chromium/ui/gl/hdr_metadata_helper_win.h
+++ b/chromium/ui/gl/hdr_metadata_helper_win.h
@@ -9,12 +9,9 @@
#include <dxgi1_6.h>
#include <wrl/client.h>
-#include <memory>
-#include <utility>
-#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/hdr_metadata.h"
#include "ui/gl/gl_export.h"
@@ -31,7 +28,7 @@ class GL_EXPORT HDRMetadataHelperWin {
// Return the metadata for the display, if available. Must call
// UpdateDisplayMetadata first.
- base::Optional<DXGI_HDR_METADATA_HDR10> GetDisplayMetadata();
+ absl::optional<DXGI_HDR_METADATA_HDR10> GetDisplayMetadata();
// Query the display metadata from all monitors. In the event of monitor
// hot plugging, the metadata should be updated again.
@@ -43,8 +40,7 @@ class GL_EXPORT HDRMetadataHelperWin {
const gfx::HDRMetadata& hdr_metadata);
private:
-
- base::Optional<DXGI_HDR_METADATA_HDR10> hdr_metadata_;
+ absl::optional<DXGI_HDR_METADATA_HDR10> hdr_metadata_;
DISALLOW_COPY_AND_ASSIGN(HDRMetadataHelperWin);
};
diff --git a/chromium/ui/gl/init/BUILD.gn b/chromium/ui/gl/init/BUILD.gn
index e447744aa69..62763048aff 100644
--- a/chromium/ui/gl/init/BUILD.gn
+++ b/chromium/ui/gl/init/BUILD.gn
@@ -25,6 +25,7 @@ component("init") {
deps = [
"//base",
+ "//mojo/public/cpp/bindings",
"//ui/gfx",
"//ui/gl:buildflags",
]
diff --git a/chromium/ui/gl/init/gl_factory.cc b/chromium/ui/gl/init/gl_factory.cc
index ddb538a4ed3..c7c0733a59a 100644
--- a/chromium/ui/gl/init/gl_factory.cc
+++ b/chromium/ui/gl/init/gl_factory.cc
@@ -92,6 +92,13 @@ GLImplementationParts GetRequestedGLImplementation(
(requested_implementation_gl_name ==
kGLImplementationSwiftShaderForWebGLName)) {
impl = GLImplementationParts(kGLImplementationSwiftShaderGL);
+ } else if ((requested_implementation_gl_name ==
+ kGLImplementationANGLEName) &&
+ ((requested_implementation_angle_name ==
+ kANGLEImplementationSwiftShaderName) ||
+ (requested_implementation_angle_name ==
+ kANGLEImplementationSwiftShaderForWebGLName))) {
+ impl = GLImplementationParts(ANGLEImplementation::kSwiftShader);
} else {
impl = GetNamedGLImplementation(requested_implementation_gl_name,
requested_implementation_angle_name);
diff --git a/chromium/ui/gl/init/gl_initializer_win.cc b/chromium/ui/gl/init/gl_initializer_win.cc
index dae3a193e77..9b4677f7e2f 100644
--- a/chromium/ui/gl/init/gl_initializer_win.cc
+++ b/chromium/ui/gl/init/gl_initializer_win.cc
@@ -13,7 +13,6 @@
#include "base/logging.h"
#include "base/native_library.h"
#include "base/path_service.h"
-#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/trace_event.h"
#include "base/win/windows_version.h"
diff --git a/chromium/ui/gl/scoped_make_current.h b/chromium/ui/gl/scoped_make_current.h
index 8f521298f92..15aed53b0d0 100644
--- a/chromium/ui/gl/scoped_make_current.h
+++ b/chromium/ui/gl/scoped_make_current.h
@@ -8,7 +8,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gl/gl_export.h"
namespace gl {
diff --git a/chromium/ui/gl/swap_chain_presenter.cc b/chromium/ui/gl/swap_chain_presenter.cc
index 6889bc6fbb6..784834301d8 100644
--- a/chromium/ui/gl/swap_chain_presenter.cc
+++ b/chromium/ui/gl/swap_chain_presenter.cc
@@ -30,6 +30,11 @@
namespace gl {
namespace {
+// When in BGRA888 overlay format, wait for this time delta before retrying
+// YUV format.
+constexpr base::TimeDelta kDelayForRetryingYUVFormat =
+ base::TimeDelta::FromMinutes(10);
+
// Some drivers fail to correctly handle BT.709 video in overlays. This flag
// converts them to BT.601 in the video processor.
const base::Feature kFallbackBT709VideoToBT601{
@@ -201,6 +206,9 @@ void LabelSwapChainBuffers(IDXGISwapChain* swap_chain) {
SwapChainPresenter::PresentationHistory::PresentationHistory() = default;
SwapChainPresenter::PresentationHistory::~PresentationHistory() = default;
+SwapChainPresenter::VisualInfo::VisualInfo() = default;
+SwapChainPresenter::VisualInfo::~VisualInfo() = default;
+
void SwapChainPresenter::PresentationHistory::AddSample(
DXGI_FRAME_PRESENTATION_MODE mode) {
if (mode == DXGI_FRAME_PRESENTATION_MODE_COMPOSED)
@@ -235,6 +243,7 @@ SwapChainPresenter::SwapChainPresenter(
Microsoft::WRL::ComPtr<IDCompositionDevice2> dcomp_device)
: layer_tree_(layer_tree),
window_(window),
+ switched_to_BGRA8888_time_tick_(base::TimeTicks::Now()),
d3d11_device_(d3d11_device),
dcomp_device_(dcomp_device),
is_on_battery_power_(
@@ -274,12 +283,21 @@ DXGI_FORMAT SwapChainPresenter::GetSwapChainFormat(
if (swap_chain_format_ == yuv_overlay_format) {
// Switch to BGRA once 3/4 of presents are composed.
- if (composition_count >= (PresentationHistory::kPresentsToStore * 3 / 4))
+ if (composition_count >= (PresentationHistory::kPresentsToStore * 3 / 4)) {
+ switched_to_BGRA8888_time_tick_ = base::TimeTicks::Now();
return DXGI_FORMAT_B8G8R8A8_UNORM;
+ }
} else {
- // Switch to YUV once 3/4 are using overlays (or unknown).
- if (composition_count < (PresentationHistory::kPresentsToStore / 4))
+ // To prevent it from switching back and forth between YUV and BGRA8888,
+ // Wait for at least 10 minutes before we re-try YUV. On a system that
+ // can promote BGRA8888 but not YUV, the format change might cause
+ // flickers.
+ base::TimeDelta time_delta =
+ base::TimeTicks::Now() - switched_to_BGRA8888_time_tick_;
+ if (time_delta >= kDelayForRetryingYUVFormat) {
+ presentation_history_.Clear();
return yuv_overlay_format;
+ }
}
return swap_chain_format_;
}
@@ -426,7 +444,7 @@ void SwapChainPresenter::AdjustSwapChainToFullScreenSizeIfNeeded(
gfx::Transform* transform,
gfx::Rect* clip_rect) {
gfx::Rect onscreen_rect = overlay_onscreen_rect;
- if (params.is_clipped)
+ if (params.clip_rect)
onscreen_rect.Intersect(*clip_rect);
// Because of the rounding when converting between pixels and DIPs, a
@@ -465,7 +483,7 @@ void SwapChainPresenter::AdjustSwapChainToFullScreenSizeIfNeeded(
}
// Adjust the clip rect.
- if (params.is_clipped) {
+ if (params.clip_rect) {
*clip_rect = gfx::Rect(monitor_size);
}
@@ -590,15 +608,16 @@ void SwapChainPresenter::UpdateVisuals(const ui::DCRendererLayerParams& params,
content_visual_->SetTransform(dcomp_transform.Get());
}
- if (visual_info_.is_clipped != params.is_clipped ||
+ if (visual_info_.clip_rect.has_value() != params.clip_rect.has_value() ||
visual_info_.clip_rect != clip_rect) {
- visual_info_.is_clipped = params.is_clipped;
- visual_info_.clip_rect = clip_rect;
+ if (params.clip_rect) {
+ visual_info_.clip_rect = clip_rect;
+ }
layer_tree_->SetNeedsRebuildVisualTree();
// DirectComposition clips happen in the pre-transform visual space, while
// cc/ clips happen post-transform. So the clip needs to go on a separate
// parent visual that's untransformed.
- if (params.is_clipped) {
+ if (params.clip_rect) {
Microsoft::WRL::ComPtr<IDCompositionRectangleClip> clip;
dcomp_device_->CreateRectangleClip(&clip);
DCHECK(clip);
@@ -619,23 +638,28 @@ void SwapChainPresenter::UpdateVisuals(const ui::DCRendererLayerParams& params,
}
bool SwapChainPresenter::TryPresentToDecodeSwapChain(
- GLImageDXGI* nv12_image,
+ Microsoft::WRL::ComPtr<ID3D11Texture2D> texture,
+ unsigned array_slice,
+ const gfx::ColorSpace& color_space,
const gfx::Rect& content_rect,
- const gfx::Size& swap_chain_size) {
+ const gfx::Size& swap_chain_size,
+ DXGI_FORMAT swap_chain_format) {
if (ShouldUseVideoProcessorScaling())
return false;
auto not_used_reason = DecodeSwapChainNotUsedReason::kFailedToPresent;
bool nv12_supported =
+ (swap_chain_format == DXGI_FORMAT_NV12) &&
(DXGI_FORMAT_NV12 ==
DirectCompositionSurfaceWin::GetOverlayFormatUsedForSDR());
// TODO(sunnyps): Try using decode swap chain for uploaded video images.
- if (nv12_image && nv12_supported && !failed_to_present_decode_swapchain_) {
+ if (texture && nv12_supported && !failed_to_present_decode_swapchain_) {
D3D11_TEXTURE2D_DESC texture_desc = {};
- nv12_image->texture()->GetDesc(&texture_desc);
+ texture->GetDesc(&texture_desc);
- bool is_decoder_texture = texture_desc.BindFlags & D3D11_BIND_DECODER;
+ bool is_decoder_texture = (texture_desc.Format == DXGI_FORMAT_NV12) &&
+ (texture_desc.BindFlags & D3D11_BIND_DECODER);
// Decode swap chains do not support shared resources.
// TODO(sunnyps): Find a workaround for when the decoder moves to its own
@@ -669,8 +693,10 @@ bool SwapChainPresenter::TryPresentToDecodeSwapChain(
if (is_decoder_texture && !is_shared_texture && !is_unitary_texture_array &&
is_overlay_supported_transform) {
- if (PresentToDecodeSwapChain(nv12_image, content_rect, swap_chain_size))
+ if (PresentToDecodeSwapChain(texture, array_slice, color_space,
+ content_rect, swap_chain_size)) {
return true;
+ }
ReleaseSwapChainResources();
failed_to_present_decode_swapchain_ = true;
not_used_reason = DecodeSwapChainNotUsedReason::kFailedToPresent;
@@ -685,7 +711,7 @@ bool SwapChainPresenter::TryPresentToDecodeSwapChain(
} else if (!is_overlay_supported_transform) {
not_used_reason = DecodeSwapChainNotUsedReason::kIncompatibleTransform;
}
- } else if (!nv12_image) {
+ } else if (!texture) {
not_used_reason = DecodeSwapChainNotUsedReason::kSoftwareFrame;
} else if (!nv12_supported) {
not_used_reason = DecodeSwapChainNotUsedReason::kNv12NotSupported;
@@ -699,7 +725,9 @@ bool SwapChainPresenter::TryPresentToDecodeSwapChain(
}
bool SwapChainPresenter::PresentToDecodeSwapChain(
- GLImageDXGI* nv12_image,
+ Microsoft::WRL::ComPtr<ID3D11Texture2D> texture,
+ unsigned array_slice,
+ const gfx::ColorSpace& color_space,
const gfx::Rect& content_rect,
const gfx::Size& swap_chain_size) {
DCHECK(!swap_chain_size.IsEmpty());
@@ -709,7 +737,7 @@ bool SwapChainPresenter::PresentToDecodeSwapChain(
swap_chain_size.ToString());
Microsoft::WRL::ComPtr<IDXGIResource> decode_resource;
- nv12_image->texture().As(&decode_resource);
+ texture.As(&decode_resource);
DCHECK(decode_resource);
if (!decode_swap_chain_ || decode_resource_ != decode_resource) {
@@ -771,10 +799,6 @@ bool SwapChainPresenter::PresentToDecodeSwapChain(
content_visual_->SetContent(decode_surface_.Get());
layer_tree_->SetNeedsRebuildVisualTree();
- } else if (last_presented_images_[kNV12ImageIndex] == nv12_image &&
- swap_chain_size_ == swap_chain_size) {
- // Early out if we're presenting the same image again.
- return true;
}
RECT source_rect = content_rect.ToRECT();
@@ -785,10 +809,6 @@ bool SwapChainPresenter::PresentToDecodeSwapChain(
RECT target_rect = gfx::Rect(swap_chain_size).ToRECT();
decode_swap_chain_->SetTargetRect(&target_rect);
- gfx::ColorSpace color_space = nv12_image->color_space();
- if (!color_space.IsValid())
- color_space = gfx::ColorSpace::CreateREC709();
-
// TODO(sunnyps): Move this to gfx::ColorSpaceWin helper where we can access
// internal color space state and do a better job.
// Common color spaces have primaries and transfer function similar to BT 709
@@ -796,7 +816,8 @@ bool SwapChainPresenter::PresentToDecodeSwapChain(
int color_space_flags = DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAG_BT709;
// Proper Rec 709 and 601 have limited or nominal color range.
if (color_space == gfx::ColorSpace::CreateREC709() ||
- color_space == gfx::ColorSpace::CreateREC601()) {
+ color_space == gfx::ColorSpace::CreateREC601() ||
+ !color_space.IsValid()) {
color_space_flags |= DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAG_NOMINAL_RANGE;
}
// xvYCC allows colors outside nominal range to encode negative colors that
@@ -808,8 +829,7 @@ bool SwapChainPresenter::PresentToDecodeSwapChain(
static_cast<DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAGS>(color_space_flags));
UINT present_flags = DXGI_PRESENT_USE_DURATION;
- HRESULT hr =
- decode_swap_chain_->PresentBuffer(nv12_image->level(), 1, present_flags);
+ HRESULT hr = decode_swap_chain_->PresentBuffer(array_slice, 1, present_flags);
// Ignore DXGI_STATUS_OCCLUDED since that's not an error but only indicates
// that the window is occluded and we can stop rendering.
if (FAILED(hr) && hr != DXGI_STATUS_OCCLUDED) {
@@ -817,8 +837,6 @@ bool SwapChainPresenter::PresentToDecodeSwapChain(
return false;
}
- last_presented_images_ = ui::DCRendererLayerParams::OverlayImages();
- last_presented_images_[kNV12ImageIndex] = nv12_image;
swap_chain_size_ = swap_chain_size;
if (swap_chain_format_ == DXGI_FORMAT_NV12) {
frames_since_color_space_change_++;
@@ -837,14 +855,20 @@ bool SwapChainPresenter::PresentToSwapChain(
const ui::DCRendererLayerParams& params) {
GLImageDXGI* image_dxgi =
GLImageDXGI::FromGLImage(params.images[kNV12ImageIndex].get());
+ GLImageD3D* image_d3d =
+ GLImageD3D::FromGLImage(params.images[kNV12ImageIndex].get());
+
GLImageMemory* y_image_memory =
GLImageMemory::FromGLImage(params.images[kYPlaneImageIndex].get());
GLImageMemory* uv_image_memory =
GLImageMemory::FromGLImage(params.images[kUVPlaneImageIndex].get());
+
GLImageD3D* swap_chain_image =
GLImageD3D::FromGLImage(params.images[kSwapChainImageIndex].get());
+ if (swap_chain_image && !swap_chain_image->swap_chain())
+ swap_chain_image = nullptr;
- if (!image_dxgi && (!y_image_memory || !uv_image_memory) &&
+ if (!image_dxgi && !image_d3d && (!y_image_memory || !uv_image_memory) &&
!swap_chain_image) {
DLOG(ERROR) << "Video GLImages are missing";
ReleaseSwapChainResources();
@@ -854,7 +878,8 @@ bool SwapChainPresenter::PresentToSwapChain(
return true;
}
- if (image_dxgi && !image_dxgi->texture()) {
+ if ((image_dxgi && !image_dxgi->texture()) ||
+ (image_d3d && !image_d3d->texture())) {
// We can't proceed if |image_dxgi| has no underlying d3d11 texture. It's
// unclear how we get into this state, but we do observe crashes due to it.
// Just stop here instead, and render incorrectly.
@@ -864,14 +889,17 @@ bool SwapChainPresenter::PresentToSwapChain(
return true;
}
- std::string image_type = "software video frame";
- if (image_dxgi)
- image_type = "hardware video frame";
- if (swap_chain_image)
+ std::string image_type;
+ if (swap_chain_image) {
image_type = "swap chain";
+ } else if (image_d3d || image_dxgi) {
+ image_type = "hardware video frame";
+ } else {
+ image_type = "software video frame";
+ }
gfx::Transform transform = params.transform;
- gfx::Rect clip_rect = params.clip_rect;
+ gfx::Rect clip_rect = params.clip_rect.value_or(gfx::Rect());
gfx::Size swap_chain_size;
if (swap_chain_image) {
swap_chain_size = swap_chain_image->GetSize();
@@ -885,12 +913,29 @@ bool SwapChainPresenter::PresentToSwapChain(
TRACE_EVENT2("gpu", "SwapChainPresenter::PresentToSwapChain", "image_type",
image_type, "swap_chain_size", swap_chain_size.ToString());
- bool content_is_hdr = image_dxgi && image_dxgi->color_space().IsHDR();
+ Microsoft::WRL::ComPtr<ID3D11Texture2D> input_texture;
+ unsigned input_level = 0u;
+ Microsoft::WRL::ComPtr<IDXGIKeyedMutex> keyed_mutex;
+ gfx::ColorSpace input_color_space;
+ if (image_dxgi) {
+ input_texture = image_dxgi->texture();
+ input_level = image_dxgi->level();
+ // Keyed mutex may not exist.
+ keyed_mutex = image_dxgi->keyed_mutex();
+ input_color_space = image_dxgi->color_space();
+ } else if (image_d3d) {
+ input_texture = image_d3d->texture();
+ input_level = image_d3d->array_slice();
+ input_color_space = image_d3d->color_space();
+ }
+ if (!input_color_space.IsValid())
+ input_color_space = gfx::ColorSpace::CreateREC709();
+
+ bool content_is_hdr = input_color_space.IsHDR();
// Do not create a swap chain if swap chain size will be empty.
if (swap_chain_size.IsEmpty()) {
swap_chain_size_ = swap_chain_size;
if (swap_chain_) {
- last_presented_images_ = ui::DCRendererLayerParams::OverlayImages();
ReleaseSwapChainResources();
content_visual_->SetContent(nullptr);
layer_tree_->SetNeedsRebuildVisualTree();
@@ -903,20 +948,16 @@ bool SwapChainPresenter::PresentToSwapChain(
// Swap chain image already has a swap chain that's presented by the client
// e.g. for webgl/canvas low-latency/desynchronized mode.
if (swap_chain_image) {
+ DCHECK(swap_chain_image->swap_chain());
content_visual_->SetContent(swap_chain_image->swap_chain().Get());
- if (last_presented_images_[kSwapChainImageIndex] != swap_chain_image) {
- last_presented_images_ = params.images;
+ if (last_presented_images_ != params.images) {
ReleaseSwapChainResources();
+ last_presented_images_ = params.images;
layer_tree_->SetNeedsRebuildVisualTree();
}
return true;
}
- if (TryPresentToDecodeSwapChain(image_dxgi, params.content_rect,
- swap_chain_size)) {
- return true;
- }
-
bool swap_chain_resized = swap_chain_size_ != swap_chain_size;
DXGI_FORMAT swap_chain_format =
@@ -925,6 +966,21 @@ bool SwapChainPresenter::PresentToSwapChain(
bool toggle_protected_video =
protected_video_type_ != params.protected_video_type;
+ if (swap_chain_ && !swap_chain_resized && !swap_chain_format_changed &&
+ !toggle_protected_video && last_presented_images_ == params.images) {
+ // The swap chain is presenting the same images as last swap, which means
+ // that the images were never returned to the video decoder and should
+ // have the same contents as last time. It shouldn't need to be redrawn.
+ return true;
+ }
+
+ if (TryPresentToDecodeSwapChain(input_texture, input_level, input_color_space,
+ params.content_rect, swap_chain_size,
+ swap_chain_format)) {
+ last_presented_images_ = params.images;
+ return true;
+ }
+
// Try reallocating swap chain if resizing fails.
if (!swap_chain_ || swap_chain_resized || swap_chain_format_changed ||
toggle_protected_video) {
@@ -935,22 +991,9 @@ bool SwapChainPresenter::PresentToSwapChain(
}
content_visual_->SetContent(swap_chain_.Get());
layer_tree_->SetNeedsRebuildVisualTree();
- } else if (last_presented_images_ == params.images) {
- // The swap chain is presenting the same images as last swap, which means
- // that the images were never returned to the video decoder and should
- // have the same contents as last time. It shouldn't need to be redrawn.
- return true;
}
- last_presented_images_ = params.images;
- Microsoft::WRL::ComPtr<ID3D11Texture2D> input_texture;
- UINT input_level;
- Microsoft::WRL::ComPtr<IDXGIKeyedMutex> keyed_mutex;
- if (image_dxgi) {
- input_texture = image_dxgi->texture();
- input_level = static_cast<UINT>(image_dxgi->level());
- // Keyed mutex may not exist.
- keyed_mutex = image_dxgi->keyed_mutex();
+ if (input_texture) {
staging_texture_.Reset();
copy_texture_.Reset();
} else {
@@ -970,7 +1013,7 @@ bool SwapChainPresenter::PresentToSwapChain(
if (image_dxgi && image_dxgi->color_space().IsValid())
src_color_space = image_dxgi->color_space();
- base::Optional<DXGI_HDR_METADATA_HDR10> stream_metadata;
+ absl::optional<DXGI_HDR_METADATA_HDR10> stream_metadata;
if (params.hdr_metadata.IsValid()) {
stream_metadata =
gl::HDRMetadataHelperWin::HDRMetadataToDXGI(params.hdr_metadata);
@@ -1041,6 +1084,7 @@ bool SwapChainPresenter::PresentToSwapChain(
DLOG(ERROR) << "Present failed with error 0x" << std::hex << hr;
return false;
}
+ last_presented_images_ = params.images;
frames_since_color_space_change_++;
RecordPresentationStatistics();
return true;
@@ -1111,7 +1155,7 @@ bool SwapChainPresenter::VideoProcessorBlt(
const gfx::Rect& content_rect,
const gfx::ColorSpace& src_color_space,
bool content_is_hdr,
- base::Optional<DXGI_HDR_METADATA_HDR10> stream_hdr_metadata) {
+ absl::optional<DXGI_HDR_METADATA_HDR10> stream_hdr_metadata) {
TRACE_EVENT2("gpu", "SwapChainPresenter::VideoProcessorBlt", "content_rect",
content_rect.ToString(), "swap_chain_size",
swap_chain_size_.ToString());
@@ -1172,7 +1216,7 @@ bool SwapChainPresenter::VideoProcessorBlt(
&output_d3d11_color_space);
}
Microsoft::WRL::ComPtr<ID3D11VideoContext2> context2;
- base::Optional<DXGI_HDR_METADATA_HDR10> display_metadata =
+ absl::optional<DXGI_HDR_METADATA_HDR10> display_metadata =
layer_tree_->GetHDRMetadataHelper()->GetDisplayMetadata();
if (display_metadata.has_value() && SUCCEEDED(video_context.As(&context2))) {
if (stream_hdr_metadata.has_value()) {
@@ -1187,7 +1231,7 @@ bool SwapChainPresenter::VideoProcessorBlt(
}
{
- base::Optional<ScopedReleaseKeyedMutex> release_keyed_mutex;
+ absl::optional<ScopedReleaseKeyedMutex> release_keyed_mutex;
if (keyed_mutex) {
// The producer may still be using this texture for a short period of
// time, so wait long enough to hopefully avoid glitches. For example,
@@ -1270,6 +1314,7 @@ bool SwapChainPresenter::VideoProcessorBlt(
}
void SwapChainPresenter::ReleaseSwapChainResources() {
+ last_presented_images_ = ui::DCRendererLayerParams::OverlayImages();
output_view_.Reset();
swap_chain_.Reset();
decode_surface_.Reset();
diff --git a/chromium/ui/gl/swap_chain_presenter.h b/chromium/ui/gl/swap_chain_presenter.h
index c93bbcab4c8..0a5c72354fc 100644
--- a/chromium/ui/gl/swap_chain_presenter.h
+++ b/chromium/ui/gl/swap_chain_presenter.h
@@ -12,13 +12,13 @@
#include "base/containers/circular_deque.h"
#include "base/power_monitor/power_monitor.h"
+#include "base/time/time.h"
#include "base/win/scoped_handle.h"
#include "ui/gfx/color_space.h"
#include "ui/gl/dc_renderer_layer_params.h"
namespace gl {
class DCLayerTree;
-class GLImageDXGI;
class GLImageMemory;
// SwapChainPresenter holds a swap chain, direct composition visuals, and other
@@ -50,7 +50,7 @@ class SwapChainPresenter : public base::PowerStateObserver {
gfx::Rect* clip_rect) const {
*transform = visual_info_.transform;
*offset = visual_info_.offset;
- *clip_rect = visual_info_.clip_rect;
+ *clip_rect = visual_info_.clip_rect.value_or(gfx::Rect());
}
private:
@@ -132,7 +132,7 @@ class SwapChainPresenter : public base::PowerStateObserver {
const gfx::Rect& content_rect,
const gfx::ColorSpace& src_color_space,
bool content_is_hdr,
- base::Optional<DXGI_HDR_METADATA_HDR10> stream_hdr_metadata);
+ absl::optional<DXGI_HDR_METADATA_HDR10> stream_hdr_metadata);
gfx::Size GetMonitorSize();
@@ -160,14 +160,20 @@ class SwapChainPresenter : public base::PowerStateObserver {
// Try presenting to a decode swap chain based on various conditions such as
// global state (e.g. finch, NV12 support), texture flags, and transform.
// Returns true on success. See PresentToDecodeSwapChain() for more info.
- bool TryPresentToDecodeSwapChain(GLImageDXGI* nv12_image,
- const gfx::Rect& content_rect,
- const gfx::Size& swap_chain_size);
+ bool TryPresentToDecodeSwapChain(
+ Microsoft::WRL::ComPtr<ID3D11Texture2D> texture,
+ unsigned array_slice,
+ const gfx::ColorSpace& color_space,
+ const gfx::Rect& content_rect,
+ const gfx::Size& swap_chain_size,
+ DXGI_FORMAT swap_chain_format);
// Present to a decode swap chain created from compatible video decoder
// buffers using given |nv12_image| with destination size |swap_chain_size|.
// Returns true on success.
- bool PresentToDecodeSwapChain(GLImageDXGI* nv12_image,
+ bool PresentToDecodeSwapChain(Microsoft::WRL::ComPtr<ID3D11Texture2D> texture,
+ unsigned array_slice,
+ const gfx::ColorSpace& color_space,
const gfx::Rect& content_rect,
const gfx::Size& swap_chain_size);
@@ -202,6 +208,9 @@ class SwapChainPresenter : public base::PowerStateObserver {
// Current swap chain format.
DXGI_FORMAT swap_chain_format_ = DXGI_FORMAT_B8G8R8A8_UNORM;
+ // Last time tick when switching to BGRA8888 format.
+ base::TimeTicks switched_to_BGRA8888_time_tick_;
+
// Whether the swap chain was reallocated, and next present will be the first.
bool first_present_ = false;
@@ -229,10 +238,12 @@ class SwapChainPresenter : public base::PowerStateObserver {
// being presented so that properties that aren't changed aren't sent to
// DirectComposition.
struct VisualInfo {
+ VisualInfo();
+ ~VisualInfo();
+
gfx::Point offset;
gfx::Transform transform;
- bool is_clipped = false;
- gfx::Rect clip_rect;
+ absl::optional<gfx::Rect> clip_rect;
int z_order = 0;
} visual_info_;
diff --git a/chromium/ui/gl/yuv_to_rgb_converter.h b/chromium/ui/gl/yuv_to_rgb_converter.h
index 9be78a082f9..de5cd7d1ac9 100644
--- a/chromium/ui/gl/yuv_to_rgb_converter.h
+++ b/chromium/ui/gl/yuv_to_rgb_converter.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_GL_YUV420_RGB_CONVERTER_H_
-#define UI_GL_YUV420_RGB_CONVERTER_H_
+#ifndef UI_GL_YUV_TO_RGB_CONVERTER_H_
+#define UI_GL_YUV_TO_RGB_CONVERTER_H_
#include "ui/gfx/geometry/size.h"
@@ -49,4 +49,4 @@ class YUVToRGBConverter {
} // namespace gl
-#endif // UI_GL_YUV420_RGB_CONVERTER_H_
+#endif // UI_GL_YUV_TO_RGB_CONVERTER_H_
diff --git a/chromium/ui/gtk/BUILD.gn b/chromium/ui/gtk/BUILD.gn
index 47ec07c887d..7bdb5a0e439 100644
--- a/chromium/ui/gtk/BUILD.gn
+++ b/chromium/ui/gtk/BUILD.gn
@@ -2,10 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//build/buildflag_header.gni")
import("//build/config/chromeos/ui_mode.gni")
import("//build/config/features.gni")
-import("//build/config/linux/gtk/gtk.gni")
import("//build/config/ozone.gni")
import("//build/config/ui.gni")
import("//printing/buildflags/buildflags.gni")
@@ -15,18 +13,13 @@ import("//tools/generate_stubs/rules.gni")
assert(is_linux || is_chromeos_lacros || is_chromeos,
"This file should only be referenced on Linux")
-buildflag_header("gtk_buildflags") {
- header = "gtk_buildflags.h"
-
- flags = [ "GTK_VERSION=$gtk_version" ]
-}
-
source_set("gtk_types") {
- sources = [ "gtk_types.h" ]
- deps = [ ":gtk_buildflags" ]
+ visibility = [ ":gtk_stubs" ]
+ public = [ "gtk_types.h" ]
}
generate_stubs("gtk_stubs") {
+ visibility = [ ":gtk" ]
sigs = [
"gdk_pixbuf.sigs",
"gdk.sigs",
@@ -36,29 +29,17 @@ generate_stubs("gtk_stubs") {
]
extra_header = "gtk.fragment"
output_name = "gtk_stubs"
- deps = [
+ public_deps = [
":gtk_types",
"//build/config/linux/gtk",
+ "//build/config/linux/gtk:gtkprint",
]
logging_function = "LogNoop()"
logging_include = "ui/gtk/log_noop.h"
}
-component("gtk_ui_delegate") {
- public = [ "gtk_ui_delegate.h" ]
- sources = [ "gtk_ui_delegate.cc" ]
- deps = [
- "//base",
- "//ui/gfx",
- ]
- public_deps = [ ":gtk_buildflags" ]
- defines = [ "IS_GTK_IMPL" ]
-}
-
component("gtk") {
- public = [ "gtk_ui.h" ]
-
- friend = [ ":gtk_unittests" ]
+ public = [ "gtk_ui_factory.h" ]
sources = [
"gtk_color_mixers.cc",
@@ -68,6 +49,9 @@ component("gtk") {
"gtk_key_bindings_handler.cc",
"gtk_key_bindings_handler.h",
"gtk_ui.cc",
+ "gtk_ui.h",
+ "gtk_ui_factory.cc",
+ "gtk_ui_platform.h",
"gtk_util.cc",
"gtk_util.h",
"input_method_context_impl_gtk.cc",
@@ -105,16 +89,12 @@ component("gtk") {
deps = [
":gtk_stubs",
- ":gtk_types",
"//base",
- "//build/config/linux/gtk:gtkprint",
- "//printing",
"//skia",
# GTK pulls pangoft2, which requires HarfBuzz symbols. When linking
# our own HarfBuzz avoid mixing symbols from system HarfBuzz and
# our own through the indirect dependency to harfbuzz-ng here.
- "//build/config/linux/gtk",
"//third_party:freetype_harfbuzz",
"//ui/aura",
"//ui/base",
@@ -137,11 +117,34 @@ component("gtk") {
"//ui/views",
]
+ if (enable_basic_printing) {
+ deps += [ "//printing" ]
+ }
+
if (use_cups) {
deps += [ "//printing/mojom" ]
}
- public_deps = [ ":gtk_ui_delegate" ]
+ if (use_x11 || ozone_platform_x11) {
+ sources += [
+ "x/gtk_event_loop_x11.cc",
+ "x/gtk_event_loop_x11.h",
+ "x/gtk_ui_platform_x11.cc",
+ "x/gtk_ui_platform_x11.h",
+ ]
+ deps += [
+ "//ui/events/platform/x11",
+ "//ui/gfx/x",
+ "//ui/platform_window/x11",
+ ]
+ }
+
+ if (ozone_platform_wayland) {
+ sources += [
+ "wayland/gtk_ui_platform_wayland.cc",
+ "wayland/gtk_ui_platform_wayland.h",
+ ]
+ }
# TODO: This should be removed.
if (use_ozone) {
@@ -156,12 +159,10 @@ test("gtk_unittests") {
":gtk",
"//base/test:run_all_unittests",
"//base/test:test_support",
-
- # Required so that including gtk_util.h can resolve <gtk/gtk.h>.
- "//build/config/linux/gtk",
"//testing/gtest",
"//ui/base:features",
"//ui/native_theme",
"//ui/native_theme:test_support",
+ "//ui/views",
]
}
diff --git a/chromium/ui/gtk/gdk.sigs b/chromium/ui/gtk/gdk.sigs
index a2170ffd40d..7a393ed7080 100644
--- a/chromium/ui/gtk/gdk.sigs
+++ b/chromium/ui/gtk/gdk.sigs
@@ -17,4 +17,20 @@ GdkTexture* gdk_memory_texture_new(int width, int height, GdkMemoryFormat format
int gdk_paintable_get_intrinsic_width(GdkPaintable* paintable);
int gdk_paintable_get_intrinsic_height(GdkPaintable* paintable);
GdkScreen* gdk_screen_get_default(void);
+void gdk_color_free(GdkColor* color);
+gboolean gdk_wayland_window_set_transient_for_exported(GdkWindow* window, char* parent_handle_str);
+gboolean gdk_wayland_toplevel_set_transient_for_exported(GdkToplevel* toplevel, const char* parent_handle_str);
+unsigned long gdk_x11_surface_get_xid(GdkSurface* surface);
+unsigned long gdk_x11_window_get_xid(GdkWindow* window);
+void gdk_event_handler_set(GdkEventFunc func, gpointer data, GDestroyNotify notify);
+GdkWindow* gdk_x11_window_foreign_new_for_display(GdkDisplay* display, unsigned long window);
+GdkWindow* gdk_x11_window_lookup_for_display(GdkDisplay* display, unsigned long window);
+guint gdk_key_event_get_keycode(GdkEvent* event);
+guint gdk_key_event_get_keyval(GdkEvent* event);
+GdkSurface* gdk_event_get_surface(GdkEvent* event);
+GdkModifierType gdk_event_get_modifier_state(GdkEvent *event);
+GType gdk_toplevel_get_type(void);
+void gdk_set_allowed_backends(const gchar* backends);
+void gdk_display_notify_startup_complete(GdkDisplay* display, const char* startup_id);
+guint32 gdk_keyval_to_unicode(guint keyval);
gdouble gdk_screen_get_resolution(GdkScreen *screen);
diff --git a/chromium/ui/gtk/gtk.sigs b/chromium/ui/gtk/gtk.sigs
index 39dd8f1e29d..5bf454bbc67 100644
--- a/chromium/ui/gtk/gtk.sigs
+++ b/chromium/ui/gtk/gtk.sigs
@@ -52,3 +52,135 @@ void gtk_style_context_add_provider_for_screen(GdkScreen* screen, GtkStyleProvid
void gtk_style_context_add_provider_for_display(GdkDisplay* display, GtkStyleProvider* provider, guint priority);
void gtk_style_context_remove_provider_for_screen(GdkScreen* screen, GtkStyleProvider* provider);
void gtk_style_context_remove_provider_for_display(GdkDisplay* display, GtkStyleProvider* provider);
+void gtk_window_destroy(GtkWindow* window);
+GtkIconTheme* gtk_icon_theme_get_for_display(GdkDisplay* display);
+GtkIconTheme* gtk_icon_theme_get_default(void);
+gboolean gtk_widget_path_iter_has_class(const GtkWidgetPath* path, gint pos, const gchar* name);
+GdkWindow* gtk_widget_get_window(GtkWidget* widget);
+void gtk_main_do_event(GdkEvent *event);
+guint gtk_get_major_version(void);
+guint gtk_get_minor_version(void);
+guint gtk_get_micro_version(void);
+void gtk_window_present(GtkWindow* window);
+void gtk_window_present_with_time(GtkWindow* window, guint32 timestamp);
+GType gtk_box_get_type(void);
+GType gtk_button_get_type(void);
+GType gtk_cell_view_get_type(void);
+GType gtk_combo_box_text_get_type(void);
+GType gtk_entry_get_type(void);
+GType gtk_file_chooser_get_type(void);
+GType gtk_frame_get_type(void);
+GType gtk_header_bar_get_type(void);
+GType gtk_image_get_type(void);
+GType gtk_info_bar_get_type(void);
+GType gtk_label_get_type(void);
+GType gtk_print_unix_dialog_get_type(void);
+GType gtk_range_get_type(void);
+GType gtk_scale_get_type(void);
+GType gtk_scrollbar_get_type(void);
+GType gtk_scrolled_window_get_type(void);
+GType gtk_separator_get_type(void);
+GType gtk_spinner_get_type(void);
+GType gtk_style_provider_get_type(void);
+GType gtk_text_view_get_type(void);
+GType gtk_toggle_button_get_type(void);
+GType gtk_tree_model_get_type(void);
+GType gtk_tree_view_get_type(void);
+GType gtk_widget_get_type(void);
+GType gtk_window_get_type(void);
+GtkWidget* gtk_combo_box_new_with_model(GtkTreeModel* model);
+GtkCssProvider* gtk_css_provider_new(void);
+void gtk_disable_setlocale(void);
+void gtk_enumerate_printers(GtkPrinterFunc func, gpointer data, GDestroyNotify destroy, gboolean wait);
+void gtk_file_chooser_add_filter(GtkFileChooser* chooser, GtkFileFilter* filter);
+GFile* gtk_file_chooser_get_file(GtkFileChooser* chooser);
+GtkFileFilter* gtk_file_chooser_get_filter(GtkFileChooser* chooser);
+void gtk_file_chooser_set_create_folders(GtkFileChooser* chooser, gboolean create_folders);
+void gtk_file_chooser_set_current_name(GtkFileChooser* chooser, const gchar* name);
+gboolean gtk_file_chooser_set_file(GtkFileChooser* chooser, GFile* file, GError** error);
+void gtk_file_chooser_set_filter(GtkFileChooser* chooser, GtkFileFilter* filter);
+void gtk_file_chooser_set_select_multiple(GtkFileChooser* chooser, gboolean select_multiple);
+void gtk_file_filter_add_mime_type(GtkFileFilter* filter, const gchar* mime_type);
+void gtk_file_filter_add_pattern(GtkFileFilter* filter, const gchar* pattern);
+GtkFileFilter* gtk_file_filter_new(void);
+void gtk_file_filter_set_name(GtkFileFilter* filter, const gchar* name);
+GtkWidget* gtk_image_new(void);
+void gtk_image_set_from_pixbuf(GtkImage* image, GdkPixbuf* pixbuf);
+void gtk_im_context_focus_in(GtkIMContext* context);
+void gtk_im_context_focus_out(GtkIMContext* context);
+void gtk_im_context_get_preedit_string(GtkIMContext* context, gchar** str, PangoAttrList** attrs, gint* cursor_pos);
+void gtk_im_context_reset(GtkIMContext* context);
+void gtk_im_context_set_cursor_location(GtkIMContext* context, const GdkRectangle* area);
+GtkIMContext* gtk_im_context_simple_new(void);
+GtkIMContext* gtk_im_multicontext_new(void);
+GtkWidget* gtk_label_new(const gchar* str);
+gdouble gtk_page_setup_get_left_margin(GtkPageSetup* setup, GtkUnit unit);
+gdouble gtk_page_setup_get_page_height(GtkPageSetup* setup, GtkUnit unit);
+gdouble gtk_page_setup_get_page_width(GtkPageSetup* setup, GtkUnit unit);
+gdouble gtk_page_setup_get_paper_height(GtkPageSetup* setup, GtkUnit unit);
+GtkPaperSize* gtk_page_setup_get_paper_size(GtkPageSetup* setup);
+gdouble gtk_page_setup_get_paper_width(GtkPageSetup* setup, GtkUnit unit);
+gdouble gtk_page_setup_get_top_margin(GtkPageSetup* setup, GtkUnit unit);
+GtkPageSetup* gtk_page_setup_new(void);
+void gtk_page_setup_set_paper_size(GtkPageSetup* setup, GtkPaperSize* size);
+void gtk_paper_size_free(GtkPaperSize* size);
+gdouble gtk_paper_size_get_height(GtkPaperSize* size, GtkUnit unit);
+GList* gtk_paper_size_get_paper_sizes(gboolean include_custom);
+const gchar* gtk_paper_size_get_ppd_name(GtkPaperSize* size);
+gdouble gtk_paper_size_get_width(GtkPaperSize* size, GtkUnit unit);
+GtkPaperSize* gtk_paper_size_new_custom(const gchar* name, const gchar* display_name, gdouble width, gdouble height, GtkUnit unit);
+GtkPageSetup* gtk_printer_get_default_page_size(GtkPrinter* printer);
+const gchar* gtk_printer_get_name(GtkPrinter* printer);
+gboolean gtk_printer_is_default(GtkPrinter* printer);
+GtkPrintJob* gtk_print_job_new(const gchar* title, GtkPrinter* printer, GtkPrintSettings* settings, GtkPageSetup* page_setup);
+void gtk_print_job_send(GtkPrintJob* job, GtkPrintJobCompleteFunc callback, gpointer user_data, GDestroyNotify dnotify);
+gboolean gtk_print_job_set_source_file(GtkPrintJob* job, const gchar* filename, GError** error);
+GtkPrintSettings* gtk_print_settings_copy(GtkPrintSettings* other);
+GtkPageOrientation gtk_print_settings_get_orientation(GtkPrintSettings* settings);
+GtkPageRange* gtk_print_settings_get_page_ranges(GtkPrintSettings* settings, gint *num_ranges);
+const gchar* gtk_print_settings_get_printer(GtkPrintSettings* settings);
+GtkPrintPages gtk_print_settings_get_print_pages(GtkPrintSettings* settings);
+gint gtk_print_settings_get_resolution(GtkPrintSettings* settings);
+GtkPrintSettings* gtk_print_settings_new(void);
+void gtk_print_settings_set(GtkPrintSettings* settings, const gchar* key, const gchar* value);
+void gtk_print_settings_set_collate(GtkPrintSettings* settings, gboolean collate);
+void gtk_print_settings_set_n_copies(GtkPrintSettings* settings, gint num_copies);
+void gtk_print_settings_set_orientation(GtkPrintSettings* settings, GtkPageOrientation orientation);
+void gtk_print_settings_set_printer_lpi(GtkPrintSettings* settings, gdouble lpi);
+void gtk_print_settings_set_print_pages(GtkPrintSettings* settings, GtkPrintPages pages);
+void gtk_print_settings_set_resolution_xy(GtkPrintSettings* settings, gint resolution_x, gint resolution_y);
+GtkPageSetup* gtk_print_unix_dialog_get_page_setup(GtkPrintUnixDialog* dialog);
+GtkPrinter* gtk_print_unix_dialog_get_selected_printer(GtkPrintUnixDialog* dialog);
+GtkPrintSettings* gtk_print_unix_dialog_get_settings(GtkPrintUnixDialog* dialog);
+GtkWidget* gtk_print_unix_dialog_new(const char* title, GtkWindow* parent);
+void gtk_print_unix_dialog_set_embed_page_setup(GtkPrintUnixDialog* dialog, gboolean embed);
+void gtk_print_unix_dialog_set_has_selection(GtkPrintUnixDialog* dialog, gboolean has_selection);
+void gtk_print_unix_dialog_set_manual_capabilities(GtkPrintUnixDialog* dialog, GtkPrintCapabilities capabilities);
+void gtk_print_unix_dialog_set_settings(GtkPrintUnixDialog* dialog, GtkPrintSettings* settings);
+void gtk_print_unix_dialog_set_support_selection(GtkPrintUnixDialog* dialog, gboolean support_selection);
+void gtk_render_background(GtkStyleContext* context, cairo_t* cr, gdouble x, gdouble y, gdouble width, gdouble height);
+void gtk_render_focus(GtkStyleContext* context, cairo_t* cr, gdouble x, gdouble y, gdouble width, gdouble height);
+void gtk_render_frame(GtkStyleContext* context, cairo_t* cr, gdouble x, gdouble y, gdouble width, gdouble height);
+GtkWidget* gtk_separator_new(GtkOrientation orientation);
+void gtk_style_context_add_class(GtkStyleContext* context, const gchar* class_name);
+void gtk_style_context_add_provider(GtkStyleContext* context, GtkStyleProvider* provider, guint priority);
+GtkStateFlags gtk_style_context_get_state(GtkStyleContext* context);
+gboolean gtk_style_context_has_class(GtkStyleContext* context, const gchar* class_name);
+void gtk_style_context_set_scale(GtkStyleContext* context, gint scale);
+void gtk_style_context_set_state(GtkStyleContext* context, GtkStateFlags flags);
+PangoContext* gtk_widget_get_pango_context(GtkWidget* widget);
+GtkWidget* gtk_widget_get_parent(GtkWidget* widget);
+void gtk_widget_get_preferred_size(GtkWidget* widget, GtkRequisition* minimum_size, GtkRequisition* natural_size);
+gint gtk_widget_get_scale_factor(GtkWidget* widget);
+GtkStyleContext* gtk_widget_get_style_context(GtkWidget* widget);
+void gtk_widget_hide(GtkWidget* widget);
+void gtk_widget_realize(GtkWidget* widget);
+void gtk_widget_set_can_focus(GtkWidget* widget, gboolean can_focus);
+void gtk_widget_set_name(GtkWidget* widget, const gchar* name);
+void gtk_widget_set_parent(GtkWidget* widget, GtkWidget* parent);
+void gtk_widget_set_sensitive(GtkWidget* widget, gboolean sensitive);
+void gtk_widget_set_size_request(GtkWidget* widget, gint width, gint height);
+void gtk_widget_set_state_flags(GtkWidget* widget, GtkStateFlags flags, gboolean clear);
+void gtk_widget_show(GtkWidget* widget);
+void gtk_window_set_modal(GtkWindow* window, gboolean modal);
+void gtk_print_settings_set_printer(GtkPrintSettings* settings, const gchar* printer);
diff --git a/chromium/ui/gtk/gtk_color_mixers.cc b/chromium/ui/gtk/gtk_color_mixers.cc
index 044ddd4390c..b4b0710438a 100644
--- a/chromium/ui/gtk/gtk_color_mixers.cc
+++ b/chromium/ui/gtk/gtk_color_mixers.cc
@@ -21,13 +21,19 @@ namespace gtk {
void AddGtkNativeCoreColorMixer(
ui::ColorProvider* provider,
ui::ColorProviderManager::ColorMode color_mode,
- ui::ColorProviderManager::ContrastMode contrast_mode) {
+ ui::ColorProviderManager::ContrastMode contrast_mode,
+ ui::ColorProviderManager::ThemeName theme_name) {
+ // `theme_name` is empty when using the system theme. We do not initialize the
+ // GTK mixer in this case.
+ if (theme_name.empty())
+ return;
+
ui::ColorMixer& mixer = provider->AddMixer();
ui::ColorSet::ColorMap color_map;
for (ui::ColorId id = ui::kUiColorsStart; id < ui::kUiColorsEnd; ++id) {
// Add GTK color definitions to the map if they exist.
- base::Optional<SkColor> color = gtk::SkColorFromColorId(id);
+ absl::optional<SkColor> color = gtk::SkColorFromColorId(id);
if (color)
color_map[id] = *color;
}
diff --git a/chromium/ui/gtk/gtk_color_mixers.h b/chromium/ui/gtk/gtk_color_mixers.h
index 3b4edb55e00..eb7b92bcfe6 100644
--- a/chromium/ui/gtk/gtk_color_mixers.h
+++ b/chromium/ui/gtk/gtk_color_mixers.h
@@ -16,7 +16,8 @@ namespace gtk {
void AddGtkNativeCoreColorMixer(
ui::ColorProvider* provider,
ui::ColorProviderManager::ColorMode color_mode,
- ui::ColorProviderManager::ContrastMode contrast_mode);
+ ui::ColorProviderManager::ContrastMode contrast_mode,
+ ui::ColorProviderManager::ThemeName theme_name);
} // namespace gtk
diff --git a/chromium/ui/gtk/gtk_compat.cc b/chromium/ui/gtk/gtk_compat.cc
index 0610d8aa5dd..d05e866401f 100644
--- a/chromium/ui/gtk/gtk_compat.cc
+++ b/chromium/ui/gtk/gtk_compat.cc
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/debug/leak_annotations.h"
#include "base/no_destructor.h"
+#include "ui/gfx/color_palette.h"
#include "ui/gtk/gtk_stubs.h"
namespace gtk {
@@ -19,9 +20,29 @@ namespace gtk {
namespace {
-void* DlOpen(const char* library_name) {
+struct Gdk3Rgba {
+ gdouble r;
+ gdouble g;
+ gdouble b;
+ gdouble a;
+};
+
+struct Gdk4Rgba {
+ float r;
+ float g;
+ float b;
+ float a;
+};
+
+template <typename T>
+SkColor GdkRgbaToSkColor(const T& color) {
+ return SkColorSetARGB(color.a * 255, color.r * 255, color.g * 255,
+ color.b * 255);
+}
+
+void* DlOpen(const char* library_name, bool check = true) {
void* library = dlopen(library_name, RTLD_LAZY | RTLD_GLOBAL);
- CHECK(library);
+ CHECK(!check || library);
return library;
}
@@ -51,8 +72,8 @@ void* GetLibGdk3() {
return libgdk3;
}
-void* GetLibGtk3() {
- static void* libgtk3 = DlOpen("libgtk-3.so.0");
+void* GetLibGtk3(bool check = true) {
+ static void* libgtk3 = DlOpen("libgtk-3.so.0", check);
return libgtk3;
}
@@ -67,14 +88,9 @@ void* GetLibGtk() {
return GetLibGtk3();
}
-gfx::Insets InsetsFromGtkBorder(const GtkBorder& border) {
- return gfx::Insets(border.top, border.left, border.bottom, border.right);
-}
-
-} // namespace
-
-bool LoadGtk(int gtk_version) {
- if (gtk_version < 4) {
+bool LoadGtkImpl(int gtk_version) {
+ // Prefer GTK3 for now as the GTK4 ecosystem is still immature.
+ if (GetLibGtk3(false)) {
ui_gtk::InitializeGdk_pixbuf(GetLibGdkPixbuf());
ui_gtk::InitializeGdk(GetLibGdk3());
ui_gtk::InitializeGtk(GetLibGtk3());
@@ -92,6 +108,17 @@ bool LoadGtk(int gtk_version) {
return true;
}
+gfx::Insets InsetsFromGtkBorder(const GtkBorder& border) {
+ return gfx::Insets(border.top, border.left, border.bottom, border.right);
+}
+
+} // namespace
+
+bool LoadGtk() {
+ static bool loaded = LoadGtkImpl(GTK_MAJOR_VERSION);
+ return loaded;
+}
+
const base::Version& GtkVersion() {
static base::NoDestructor<base::Version> gtk_version(
std::vector<uint32_t>{gtk_get_major_version(), gtk_get_minor_version(),
@@ -172,6 +199,45 @@ gfx::Insets GtkStyleContextGetMargin(GtkStyleContext* context) {
}
DISABLE_CFI_ICALL
+SkColor GtkStyleContextGetColor(GtkStyleContext* context) {
+ static void* get_color = DlSym(GetLibGtk(), "gtk_style_context_get_color");
+ if (GtkCheckVersion(4)) {
+ Gdk4Rgba color;
+ DlCast<void(GtkStyleContext*, Gdk4Rgba*)>(get_color)(context, &color);
+ return GdkRgbaToSkColor(color);
+ }
+ Gdk3Rgba color;
+ DlCast<void(GtkStyleContext*, GtkStateFlags, Gdk3Rgba*)>(get_color)(
+ context, gtk_style_context_get_state(context), &color);
+ return GdkRgbaToSkColor(color);
+}
+
+DISABLE_CFI_ICALL
+SkColor GtkStyleContextGetBackgroundColor(GtkStyleContext* context) {
+ DCHECK(!GtkCheckVersion(4));
+ static void* get_bg_color =
+ DlSym(GetLibGtk(), "gtk_style_context_get_background_color");
+ Gdk3Rgba color;
+ DlCast<void(GtkStyleContext*, GtkStateFlags, Gdk3Rgba*)>(get_bg_color)(
+ context, gtk_style_context_get_state(context), &color);
+ return GdkRgbaToSkColor(color);
+}
+
+DISABLE_CFI_ICALL
+SkColor GtkStyleContextLookupColor(GtkStyleContext* context,
+ const gchar* color_name) {
+ DCHECK(!GtkCheckVersion(4));
+ static void* lookup_color =
+ DlSym(GetLibGtk(), "gtk_style_context_lookup_color");
+ Gdk3Rgba color;
+ if (DlCast<gboolean(GtkStyleContext*, const gchar*, Gdk3Rgba*)>(lookup_color)(
+ context, color_name, &color)) {
+ return GdkRgbaToSkColor(color);
+ }
+ return gfx::kPlaceholderColor;
+}
+
+DISABLE_CFI_ICALL
bool GtkImContextFilterKeypress(GtkIMContext* context, GdkEventKey* event) {
static void* filter = DlSym(GetLibGtk(), "gtk_im_context_filter_keypress");
if (GtkCheckVersion(4)) {
@@ -213,6 +279,28 @@ void GtkRenderIcon(GtkStyleContext* context,
}
}
+DISABLE_CFI_ICALL
+GtkWidget* GtkToplevelWindowNew() {
+ static void* window_new = DlSym(GetLibGtk(), "gtk_window_new");
+ if (GtkCheckVersion(4))
+ return DlCast<GtkWidget*()>(window_new)();
+ return DlCast<GtkWidget*(GtkWindowType)>(window_new)(GTK_WINDOW_TOPLEVEL);
+}
+
+DISABLE_CFI_ICALL
+void GtkCssProviderLoadFromData(GtkCssProvider* css_provider,
+ const char* data,
+ gssize length) {
+ static void* load = DlSym(GetLibGtk(), "gtk_css_provider_load_from_data");
+ if (GtkCheckVersion(4)) {
+ DlCast<void(GtkCssProvider*, const char*, gssize)>(load)(css_provider, data,
+ length);
+ } else {
+ DlCast<gboolean(GtkCssProvider*, const char*, gssize, GError**)>(load)(
+ css_provider, data, length, nullptr);
+ }
+}
+
ScopedGObject<GListModel> Gtk4FileChooserGetFiles(GtkFileChooser* dialog) {
DCHECK(GtkCheckVersion(4));
static void* get = DlSym(GetLibGtk(), "gtk_file_chooser_get_files");
@@ -279,4 +367,45 @@ ScopedGObject<GtkIconPaintable> Gtk4IconThemeLookupByGicon(
theme, icon, size, scale, direction, flags));
}
+DISABLE_CFI_ICALL
+GtkWidget* GtkFileChooserDialogNew(const gchar* title,
+ GtkWindow* parent,
+ GtkFileChooserAction action,
+ const gchar* first_button_text,
+ GtkResponseType first_response,
+ const gchar* second_button_text,
+ GtkResponseType second_response) {
+ static void* create = DlSym(GetLibGtk(), "gtk_file_chooser_dialog_new");
+ return DlCast<GtkWidget*(const gchar*, GtkWindow*, GtkFileChooserAction,
+ const gchar*, ...)>(create)(
+ title, parent, action, first_button_text, first_response,
+ second_button_text, second_response, nullptr);
+}
+
+DISABLE_CFI_ICALL
+GtkTreeStore* GtkTreeStoreNew(GType type) {
+ static void* create = DlSym(GetLibGtk(), "gtk_tree_store_new");
+ return DlCast<GtkTreeStore*(gint, ...)>(create)(1, type);
+}
+
+DISABLE_CFI_ICALL
+GdkEventType GdkEventGetEventType(GdkEvent* event) {
+ static void* get = DlSym(GetLibGtk(), "gdk_event_get_event_type");
+ return DlCast<GdkEventType(GdkEvent*)>(get)(event);
+}
+
+DISABLE_CFI_ICALL
+guint32 GdkEventGetTime(GdkEvent* event) {
+ static void* get = DlSym(GetLibGtk(), "gdk_event_get_time");
+ return DlCast<guint32(GdkEvent*)>(get)(event);
+}
+
+GdkEventType GdkKeyPress() {
+ return static_cast<GdkEventType>(GtkCheckVersion(4) ? 4 : 8);
+}
+
+GdkEventType GdkKeyRelease() {
+ return static_cast<GdkEventType>(GtkCheckVersion(4) ? 5 : 9);
+}
+
} // namespace gtk
diff --git a/chromium/ui/gtk/gtk_compat.h b/chromium/ui/gtk/gtk_compat.h
index 5d87d1b14c3..a1a63ded31e 100644
--- a/chromium/ui/gtk/gtk_compat.h
+++ b/chromium/ui/gtk/gtk_compat.h
@@ -9,11 +9,11 @@
#include <gdk/gdk.h>
#include <gio/gio.h>
#include <gtk/gtk.h>
+#include <gtk/gtkunixprint.h>
#include <string>
#include <vector>
-#include "base/component_export.h"
#include "base/files/file_path.h"
#include "base/version.h"
#include "ui/base/glib/scoped_gobject.h"
@@ -28,10 +28,16 @@ extern "C" {
#include "ui/gtk/gtk.sigs"
}
+#define GDK_KEY_PRESS Do_not_use_GDK_KEY_PRESS_because_it_is_not_ABI_compatible
+#define GDK_KEY_RELEASE \
+ Do_not_use_GDK_KEY_RELEASE_because_it_is_not_ABI_compatible
+
+using SkColor = uint32_t;
+
namespace gtk {
// Loads libgtk and related libraries and returns true on success.
-COMPONENT_EXPORT(GTK) bool LoadGtk(int gtk_version);
+bool LoadGtk();
const base::Version& GtkVersion();
@@ -51,6 +57,15 @@ gfx::Insets GtkStyleContextGetBorder(GtkStyleContext* context);
gfx::Insets GtkStyleContextGetMargin(GtkStyleContext* context);
+SkColor GtkStyleContextGetColor(GtkStyleContext* context);
+
+// Only available in Gtk3.
+SkColor GtkStyleContextGetBackgroundColor(GtkStyleContext* context);
+
+// Only available in Gtk3.
+SkColor GtkStyleContextLookupColor(GtkStyleContext* context,
+ const gchar* color_name);
+
bool GtkImContextFilterKeypress(GtkIMContext* context, GdkEventKey* event);
bool GtkFileChooserSetCurrentFolder(GtkFileChooser* dialog,
@@ -63,6 +78,12 @@ void GtkRenderIcon(GtkStyleContext* context,
double x,
double y);
+GtkWidget* GtkToplevelWindowNew();
+
+void GtkCssProviderLoadFromData(GtkCssProvider* css_provider,
+ const char* data,
+ gssize length);
+
ScopedGObject<GListModel> Gtk4FileChooserGetFiles(GtkFileChooser* dialog);
ScopedGObject<GtkIconInfo> Gtk3IconThemeLookupByGicon(GtkIconTheme* theme,
@@ -94,6 +115,32 @@ void GtkStyleContextGet(GtkStyleContext* context, ...);
void GtkStyleContextGetStyle(GtkStyleContext* context, ...);
+// These variadic functions do not have corresponding va_list equivalents,
+// so instances with only a fixed set of arguments are provided.
+
+GtkWidget* GtkFileChooserDialogNew(const gchar* title,
+ GtkWindow* parent,
+ GtkFileChooserAction action,
+ const gchar* first_button_text,
+ GtkResponseType first_response,
+ const gchar* second_button_text,
+ GtkResponseType second_response);
+
+GtkTreeStore* GtkTreeStoreNew(GType type);
+
+// These functions have dropped "const" in their signatures, so cannot be
+// declared in *.sigs.
+
+GdkEventType GdkEventGetEventType(GdkEvent* event);
+
+guint32 GdkEventGetTime(GdkEvent* event);
+
+// Some enum values have changed between versions.
+
+GdkEventType GdkKeyPress();
+
+GdkEventType GdkKeyRelease();
+
} // namespace gtk
-#endif
+#endif // UI_GTK_GTK_COMPAT_H_
diff --git a/chromium/ui/gtk/gtk_key_bindings_handler.cc b/chromium/ui/gtk/gtk_key_bindings_handler.cc
index bacf6abb9f2..70edaed2b04 100644
--- a/chromium/ui/gtk/gtk_key_bindings_handler.cc
+++ b/chromium/ui/gtk/gtk_key_bindings_handler.cc
@@ -4,9 +4,7 @@
#include "ui/gtk/gtk_key_bindings_handler.h"
-#include <gdk/gdkkeysyms.h>
-#include <stddef.h>
-
+#include <cstddef>
#include <string>
#include "base/logging.h"
@@ -52,7 +50,7 @@ bool GtkKeyBindingsHandler::MatchEvent(
// will be emitted.
auto* key = reinterpret_cast<GdkEventKey*>(gdk_event);
- DCHECK(key->type == GDK_KEY_PRESS || key->type == GDK_KEY_RELEASE);
+ DCHECK(key->type == GdkKeyPress() || key->type == GdkKeyRelease());
gtk_bindings_activate_event(G_OBJECT(handler_), key);
gdk_event_free(gdk_event);
@@ -90,18 +88,16 @@ void GtkKeyBindingsHandler::HandlerInit(Handler* self) {
}
void GtkKeyBindingsHandler::HandlerClassInit(HandlerClass* klass) {
- GtkTextViewClass* text_view_class = GTK_TEXT_VIEW_CLASS(klass);
-
// Overrides all virtual methods related to editor key bindings.
- text_view_class->backspace = BackSpace;
- text_view_class->copy_clipboard = CopyClipboard;
- text_view_class->cut_clipboard = CutClipboard;
- text_view_class->delete_from_cursor = DeleteFromCursor;
- text_view_class->insert_at_cursor = InsertAtCursor;
- text_view_class->move_cursor = MoveCursor;
- text_view_class->paste_clipboard = PasteClipboard;
- text_view_class->set_anchor = SetAnchor;
- text_view_class->toggle_overwrite = ToggleOverwrite;
+ klass->backspace = BackSpace;
+ klass->copy_clipboard = CopyClipboard;
+ klass->cut_clipboard = CutClipboard;
+ klass->delete_from_cursor = DeleteFromCursor;
+ klass->insert_at_cursor = InsertAtCursor;
+ klass->move_cursor = MoveCursor;
+ klass->paste_clipboard = PasteClipboard;
+ klass->set_anchor = SetAnchor;
+ klass->toggle_overwrite = ToggleOverwrite;
// "move-focus", "move-viewport", "select-all" and "toggle-cursor-visible"
// have no corresponding virtual methods. Since glib 2.18 (gtk 2.14),
diff --git a/chromium/ui/gtk/gtk_key_bindings_handler.h b/chromium/ui/gtk/gtk_key_bindings_handler.h
index afd795a4471..f3c3831cf18 100644
--- a/chromium/ui/gtk/gtk_key_bindings_handler.h
+++ b/chromium/ui/gtk/gtk_key_bindings_handler.h
@@ -5,14 +5,12 @@
#ifndef UI_GTK_GTK_KEY_BINDINGS_HANDLER_H_
#define UI_GTK_GTK_KEY_BINDINGS_HANDLER_H_
-#include <gtk/gtk.h>
-
#include <string>
#include <vector>
#include "ui/base/ime/linux/text_edit_command_auralinux.h"
#include "ui/events/platform_event.h"
-#include "ui/gtk/gtk_types.h"
+#include "ui/gtk/gtk_compat.h"
namespace ui {
class Event;
@@ -52,13 +50,57 @@ class GtkKeyBindingsHandler {
private:
// Object structure of Handler class, which is derived from GtkTextView.
struct Handler {
- GtkTextView parent_object;
+ // Starting in Gtk4, GtkTextView subclasses from GtkWidget instead of
+ // GtkContainer. This class is only used on Gtk3, so to ensure ABI
+ // compatibility, we always want the Gtk3 struct layout even when building
+ // with Gtk4 headers. To facilitate this, we manually copy the class
+ // hierarchy up to GtkWidget.
+ GtkWidget widget;
+ void* container_private;
+ void* text_view_private;
GtkKeyBindingsHandler* owner;
};
// Class structure of Handler class.
struct HandlerClass {
- GtkTextViewClass parent_class;
+ // Class layout for types changes between GTK versions, but is stable within
+ // the same major version. This class is only used on Gtk3, so manually
+ // expand the class layout as it appears in Gtk3.
+ GInitiallyUnownedClass parent_class;
+
+ // GtkWidgetClass and GtkContainerClass
+ guint pad0;
+ void* pad1[95];
+ unsigned int pad2 : 1;
+ void* pad3[8];
+
+ // GtkTextViewClass
+ void (*populate_popup)(GtkTextView* text_view, GtkWidget* popup);
+ void (*move_cursor)(GtkTextView* text_view,
+ GtkMovementStep step,
+ gint count,
+ gboolean extend_selection);
+ void (*set_anchor)(GtkTextView* text_view);
+ void (*insert_at_cursor)(GtkTextView* text_view, const gchar* str);
+ void (*delete_from_cursor)(GtkTextView* text_view,
+ GtkDeleteType type,
+ gint count);
+ void (*backspace)(GtkTextView* text_view);
+ void (*cut_clipboard)(GtkTextView* text_view);
+ void (*copy_clipboard)(GtkTextView* text_view);
+ void (*paste_clipboard)(GtkTextView* text_view);
+ void (*toggle_overwrite)(GtkTextView* text_view);
+ GtkTextBuffer* (*create_buffer)(GtkTextView* text_view);
+ void (*draw_layer)(GtkTextView* text_view,
+ GtkTextViewLayer layer,
+ cairo_t* cr);
+ gboolean (*extend_selection)(GtkTextView* text_view,
+ GtkTextExtendSelection granularity,
+ const GtkTextIter* location,
+ GtkTextIter* start,
+ GtkTextIter* end);
+ void (*insert_emoji)(GtkTextView* text_view);
+ void* pad4[4];
};
// Creates a new instance of Handler class.
diff --git a/chromium/ui/gtk/gtk_types.h b/chromium/ui/gtk/gtk_types.h
index a891983fdf0..32ac5cddde1 100644
--- a/chromium/ui/gtk/gtk_types.h
+++ b/chromium/ui/gtk/gtk_types.h
@@ -6,13 +6,15 @@
#define UI_GTK_GTK_TYPES_H_
#include <gdk/gdk.h>
-
-#include "ui/gtk/gtk_buildflags.h"
+#include <gtk/gtk.h>
// This file provides types that are only available in specific versions of GTK.
+// This struct uses doubles in Gtk3, but floats in Gtk4.
+#define GdkRGBA Do_not_use_GdkRGBA_because_it_is_not_ABI_compatible
+
extern "C" {
-#if BUILDFLAG(GTK_VERSION) == 3
+#if GTK_MAJOR_VERSION == 3
using GskRenderNodeType = enum {
GSK_NOT_A_RENDER_NODE = 0,
GSK_CONTAINER_NODE,
@@ -52,10 +54,12 @@ using GtkSnapshot = GdkSnapshot;
using GdkPaintable = struct _GdkPaintable;
using GtkNative = struct _GtkNative;
using GdkSurface = struct _GdkSurface;
+using GdkToplevel = struct _GdkToplevel;
constexpr GdkMemoryFormat GDK_MEMORY_B8G8R8A8 = static_cast<GdkMemoryFormat>(3);
-#else
+#elif GTK_MAJOR_VERSION == 4
enum GtkWidgetHelpType : int;
+enum GtkWindowType : int;
using GtkWidgetPath = struct _GtkWidgetPath;
using GtkContainer = struct _GtkContainer;
@@ -64,6 +68,9 @@ using GdkWindow = struct _GdkWindow;
using GdkKeymap = struct _GdkKeymap;
using GtkIconInfo = struct _GtkIconInfo;
using GdkScreen = struct _GdkScreen;
+using GdkColor = struct _GdkColor;
+
+using GdkEventFunc = void (*)(GdkEvent* event, gpointer data);
struct _GdkEventKey {
GdkEventType type;
@@ -79,11 +86,20 @@ struct _GdkEventKey {
guint is_modifier : 1;
};
+struct _GdkColor {
+ guint32 pixel;
+ guint16 red;
+ guint16 green;
+ guint16 blue;
+};
+
constexpr int GTK_ICON_LOOKUP_USE_BUILTIN = 1 << 2;
constexpr int GTK_ICON_LOOKUP_GENERIC_FALLBACK = 1 << 3;
constexpr int GTK_ICON_LOOKUP_FORCE_SIZE = 1 << 4;
-constexpr const char GTK_STYLE_PROPERTY_BACKGROUND_IMAGE[] = "background-image";
+constexpr auto GTK_WINDOW_TOPLEVEL = static_cast<GtkWindowType>(0);
+#else
+#error "Unsupported GTK version"
#endif
}
diff --git a/chromium/ui/gtk/gtk_ui.cc b/chromium/ui/gtk/gtk_ui.cc
index b99afd66e79..3c7fe071cda 100644
--- a/chromium/ui/gtk/gtk_ui.cc
+++ b/chromium/ui/gtk/gtk_ui.cc
@@ -5,8 +5,6 @@
#include "ui/gtk/gtk_ui.h"
#include <cairo.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkkeysyms.h>
#include <pango/pango.h>
#include <cmath>
@@ -23,9 +21,8 @@
#include "base/nix/xdg_util.h"
#include "base/stl_util.h"
#include "base/strings/string_split.h"
-#include "base/strings/stringprintf.h"
#include "chrome/browser/themes/theme_properties.h" // nogncheck
-#include "printing/buildflags/buildflags.h"
+#include "printing/buildflags/buildflags.h" // nogncheck
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -35,6 +32,7 @@
#include "ui/base/ime/linux/fake_input_method_context.h"
#include "ui/base/ime/linux/linux_input_method_context.h"
#include "ui/base/ime/linux/linux_input_method_context_factory.h"
+#include "ui/base/linux/linux_ui_delegate.h"
#include "ui/display/display.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/dom_keyboard_layout_manager.h"
@@ -49,7 +47,7 @@
#include "ui/gfx/skia_util.h"
#include "ui/gtk/gtk_compat.h"
#include "ui/gtk/gtk_key_bindings_handler.h"
-#include "ui/gtk/gtk_ui_delegate.h"
+#include "ui/gtk/gtk_ui_platform.h"
#include "ui/gtk/gtk_util.h"
#include "ui/gtk/input_method_context_impl_gtk.h"
#include "ui/gtk/native_theme_gtk.h"
@@ -74,13 +72,28 @@
#if defined(USE_OZONE)
#include "ui/base/ime/input_method.h"
#include "ui/base/ui_base_features.h"
+#include "ui/ozone/buildflags.h"
#include "ui/ozone/public/ozone_platform.h"
+#if BUILDFLAG(OZONE_PLATFORM_WAYLAND)
+#define USE_WAYLAND
+#endif
+#if BUILDFLAG(OZONE_PLATFORM_X11) && !defined(USE_X11)
+#define USE_X11
+#endif
#endif
#if BUILDFLAG(ENABLE_PRINTING)
#include "printing/printing_context_linux.h"
#endif
+#if defined(USE_WAYLAND)
+#include "ui/gtk/wayland/gtk_ui_platform_wayland.h"
+#endif
+
+#if defined(USE_X11)
+#include "ui/gtk/x/gtk_ui_platform_x11.h"
+#endif
+
namespace gtk {
namespace {
@@ -284,23 +297,38 @@ views::LinuxUI::WindowFrameAction GetDefaultMiddleClickAction() {
}
}
+std::unique_ptr<GtkUiPlatform> CreateGtkUiPlatform(ui::LinuxUiBackend backend) {
+ switch (backend) {
+#if defined(USE_X11)
+ case ui::LinuxUiBackend::kX11:
+ return std::make_unique<GtkUiPlatformX11>();
+#endif
+#if defined(USE_WAYLAND)
+ case ui::LinuxUiBackend::kWayland:
+ return std::make_unique<GtkUiPlatformWayland>();
+#endif
+ default:
+ NOTREACHED();
+ return nullptr;
+ }
+}
+
} // namespace
-GtkUi::GtkUi(ui::GtkUiDelegate* delegate) : delegate_(delegate) {
+GtkUi::GtkUi() {
using Action = views::LinuxUI::WindowFrameAction;
using ActionSource = views::LinuxUI::WindowFrameActionSource;
- DCHECK(delegate_);
DCHECK(!g_gtk_ui);
g_gtk_ui = this;
- window_frame_actions_ = {
- {ActionSource::kDoubleClick, Action::kToggleMaximize},
- {ActionSource::kMiddleClick, GetDefaultMiddleClickAction()},
- {ActionSource::kRightClick, Action::kMenu}};
+ CHECK(LoadGtk());
- static bool loaded = LoadGtk(BUILDFLAG(GTK_VERSION));
- CHECK(loaded);
+ auto* delegate = ui::LinuxUiDelegate::GetInstance();
+ // TODO(thomasanderson): This should be replaced with DCHECK(delegate) once
+ // fully migrated to ozone.
+ auto backend = delegate ? delegate->GetBackend() : ui::LinuxUiBackend::kX11;
+ platform_ = CreateGtkUiPlatform(backend);
// Avoid GTK initializing atk-bridge, and let AuraLinux implementation
// do it once it is ready.
@@ -308,15 +336,22 @@ GtkUi::GtkUi(ui::GtkUiDelegate* delegate) : delegate_(delegate) {
env->SetVar("NO_AT_BRIDGE", "1");
GtkInitFromCommandLine(*base::CommandLine::ForCurrentProcess());
native_theme_ = NativeThemeGtk::instance();
+
+ window_frame_actions_ = {
+ {ActionSource::kDoubleClick, Action::kToggleMaximize},
+ {ActionSource::kMiddleClick, GetDefaultMiddleClickAction()},
+ {ActionSource::kRightClick, Action::kMenu}};
}
GtkUi::~GtkUi() {
+ DCHECK_EQ(g_gtk_ui, this);
g_gtk_ui = nullptr;
}
-ui::GtkUiDelegate* GtkUi::GetDelegate() {
+// static
+GtkUiPlatform* GtkUi::GetPlatform() {
DCHECK(g_gtk_ui) << "GtkUi instance is not set.";
- return g_gtk_ui->delegate_;
+ return g_gtk_ui->platform_.get();
}
void GtkUi::Initialize() {
@@ -374,7 +409,7 @@ void GtkUi::Initialize() {
indicators_count = 0;
- GetDelegate()->OnInitialized(GetDummyWindow());
+ platform_->OnInitialized(GetDummyWindow());
}
bool GtkUi::GetTint(int id, color_utils::HSL* tint) const {
@@ -782,7 +817,7 @@ bool GtkUi::MatchEvent(const ui::Event& event,
// determine if GtkUi's key binding handling implementation is used or not.
// Ozone/Wayland was unintentionally using GtkUi for keybinding handling, so
// early out here, for now, until a proper solution for ozone is implemented.
- if (!GetDelegate()->GetGdkKeymap())
+ if (!platform_->GetGdkKeymap())
return false;
// Ensure that we have a keyboard handler.
@@ -1073,7 +1108,3 @@ float GtkUi::GetDeviceScaleFactor() const {
}
} // namespace gtk
-
-views::LinuxUI* BuildGtkUi(ui::GtkUiDelegate* delegate) {
- return new gtk::GtkUi(delegate);
-}
diff --git a/chromium/ui/gtk/gtk_ui.h b/chromium/ui/gtk/gtk_ui.h
index 3cb1c8df374..e4ecb6e3640 100644
--- a/chromium/ui/gtk/gtk_ui.h
+++ b/chromium/ui/gtk/gtk_ui.h
@@ -10,12 +10,11 @@
#include <vector>
#include "base/compiler_specific.h"
-#include "base/component_export.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "ui/base/glib/glib_signal.h"
#include "ui/gfx/color_utils.h"
-#include "ui/gtk/gtk_ui_delegate.h"
+#include "ui/gtk/gtk_ui_platform.h"
#include "ui/views/linux_ui/linux_ui.h"
#include "ui/views/window/frame_buttons.h"
@@ -35,12 +34,12 @@ class SettingsProvider;
// Interface to GTK desktop features.
class GtkUi : public views::LinuxUI {
public:
- explicit GtkUi(ui::GtkUiDelegate* delegate);
+ GtkUi();
~GtkUi() override;
// Static delegate getter, used by different objects (created by GtkUi), e.g:
// Dialogs, IME Context, when platform-specific functionality is required.
- static ui::GtkUiDelegate* GetDelegate();
+ static GtkUiPlatform* GetPlatform();
// Setters used by SettingsProvider:
void SetWindowButtonOrdering(
@@ -146,8 +145,7 @@ class GtkUi : public views::LinuxUI {
float GetRawDeviceScaleFactor();
- // Not owned by GtkUi.
- ui::GtkUiDelegate* const delegate_;
+ std::unique_ptr<GtkUiPlatform> platform_;
NativeThemeGtk* native_theme_;
@@ -214,8 +212,4 @@ class GtkUi : public views::LinuxUI {
} // namespace gtk
-// Access point to the GTK desktop system.
-COMPONENT_EXPORT(GTK)
-views::LinuxUI* BuildGtkUi(ui::GtkUiDelegate* delegate);
-
#endif // UI_GTK_GTK_UI_H_
diff --git a/chromium/ui/gtk/gtk_ui_delegate.cc b/chromium/ui/gtk/gtk_ui_delegate.cc
deleted file mode 100644
index 9936e87daab..00000000000
--- a/chromium/ui/gtk/gtk_ui_delegate.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/gtk/gtk_ui_delegate.h"
-
-namespace ui {
-
-namespace {
-
-GtkUiDelegate* g_gtk_ui_delegate = nullptr;
-
-} // namespace
-
-void GtkUiDelegate::SetInstance(GtkUiDelegate* instance) {
- g_gtk_ui_delegate = instance;
-}
-
-GtkUiDelegate* GtkUiDelegate::instance() {
- return g_gtk_ui_delegate;
-}
-
-} // namespace ui
diff --git a/chromium/ui/gtk/gtk_ui_factory.cc b/chromium/ui/gtk/gtk_ui_factory.cc
new file mode 100644
index 00000000000..06cd8306a98
--- /dev/null
+++ b/chromium/ui/gtk/gtk_ui_factory.cc
@@ -0,0 +1,11 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gtk/gtk_ui_factory.h"
+
+#include "ui/gtk/gtk_ui.h"
+
+std::unique_ptr<views::LinuxUI> BuildGtkUi() {
+ return std::make_unique<gtk::GtkUi>();
+}
diff --git a/chromium/ui/gtk/gtk_ui_factory.h b/chromium/ui/gtk/gtk_ui_factory.h
new file mode 100644
index 00000000000..f0766020c4a
--- /dev/null
+++ b/chromium/ui/gtk/gtk_ui_factory.h
@@ -0,0 +1,21 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GTK_GTK_UI_FACTORY_H_
+#define UI_GTK_GTK_UI_FACTORY_H_
+
+#include <memory>
+
+#include "base/component_export.h"
+
+namespace views {
+class LinuxUI;
+}
+
+// Access point to the GTK desktop system. This should be the only symbol
+// exported from this component.
+COMPONENT_EXPORT(GTK)
+std::unique_ptr<views::LinuxUI> BuildGtkUi();
+
+#endif // UI_GTK_GTK_UI_FACTORY_H_
diff --git a/chromium/ui/gtk/gtk_ui_delegate.h b/chromium/ui/gtk/gtk_ui_platform.h
index 07a50008199..8650770cd8c 100644
--- a/chromium/ui/gtk/gtk_ui_delegate.h
+++ b/chromium/ui/gtk/gtk_ui_platform.h
@@ -2,39 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_GTK_GTK_UI_DELEGATE_H_
-#define UI_GTK_GTK_UI_DELEGATE_H_
+#ifndef UI_GTK_GTK_UI_PLATFORM_H_
+#define UI_GTK_GTK_UI_PLATFORM_H_
-#include "base/component_export.h"
#include "ui/gfx/native_widget_types.h"
-#include "ui/gtk/gtk_buildflags.h"
using GdkKeymap = struct _GdkKeymap;
using GtkWindow = struct _GtkWindow;
using GtkWidget = struct _GtkWidget;
using GdkWindow = struct _GdkWindow;
-namespace ui {
+namespace gtk {
-// GtkUiDelegate encapsulates platform-specific functionalities required by
-// a Gtk-based LinuxUI implementation. The main goal of this interface is to
-// make GtkUi platform agnostic, moving the platform specifics to lower level
-// layers (e.g: ozone). Linux backends (e.g: ozone/x11, aura/x11, ozone/wayland)
-// must provide a GtkUiDelegate implementation and inject its singleton instance
-// of it via |SetInstance| in order to be able to use GtkUi.
-class COMPONENT_EXPORT(GTK) GtkUiDelegate {
+// GtkUiPlatform encapsulates platform-specific functionalities required by
+// a Gtk-based LinuxUI implementation.
+class GtkUiPlatform {
public:
- virtual ~GtkUiDelegate() = default;
-
- // Sets the singleton delegate instance to be used by GtkUi. This makes it
- // possible for ozone-based backends, for example, to inject the GtkUiDelegate
- // object without polluting Ozone API, since just a small subset of ozone
- // backends make use of GtkUi. This pointer is not owned, and if this method
- // is called a second time, the first instance is not deleted.
- static void SetInstance(GtkUiDelegate* instance);
-
- // Returns the current active instance.
- static GtkUiDelegate* instance();
+ virtual ~GtkUiPlatform() = default;
// Called when the GtkUi instance initialization process finished. |widget| is
// a dummy window passed in for context.
@@ -63,6 +47,6 @@ class COMPONENT_EXPORT(GTK) GtkUiDelegate {
virtual int GetGdkKeyState() = 0;
};
-} // namespace ui
+} // namespace gtk
-#endif // UI_GTK_GTK_UI_DELEGATE_H_
+#endif // UI_GTK_GTK_UI_PLATFORM_H_
diff --git a/chromium/ui/gtk/gtk_util.cc b/chromium/ui/gtk/gtk_util.cc
index 2bf77787479..fd08941211a 100644
--- a/chromium/ui/gtk/gtk_util.cc
+++ b/chromium/ui/gtk/gtk_util.cc
@@ -4,8 +4,6 @@
#include "ui/gtk/gtk_util.h"
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
#include <locale.h>
#include <stddef.h>
@@ -27,8 +25,9 @@
#include "ui/gfx/color_utils.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/gtk/gtk_compat.h"
#include "ui/gtk/gtk_ui.h"
-#include "ui/gtk/gtk_ui_delegate.h"
+#include "ui/gtk/gtk_ui_platform.h"
#include "ui/native_theme/common_theme.h"
#include "ui/ozone/public/ozone_platform.h"
#include "ui/views/linux_ui/linux_ui.h"
@@ -37,16 +36,6 @@ using base::StrCat;
namespace gtk {
-#if BUILDFLAG(GTK_VERSION) >= 4
-const char kGtkCSSMenu[] = "#popover.background.menu #contents";
-const char kGtkCSSMenuItem[] = "#modelbutton.flat";
-const char kGtkCSSMenuScrollbar[] = "#scrollbar #range";
-#else
-const char kGtkCSSMenu[] = "GtkMenu#menu";
-const char kGtkCSSMenuItem[] = "GtkMenuItem#menuitem";
-const char kGtkCSSMenuScrollbar[] = "GtkScrollbar#scrollbar #trough";
-#endif
-
namespace {
const char kAuraTransientParent[] = "aura-transient-parent";
@@ -161,17 +150,27 @@ GtkCssContext AppendCssNodeToStyleContextImpl(
}
GtkWidget* CreateDummyWindow() {
-#if BUILDFLAG(GTK_VERSION) >= 4
- GtkWidget* window = gtk_window_new();
-#else
- GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-#endif
+ GtkWidget* window = GtkToplevelWindowNew();
gtk_widget_realize(window);
return window;
}
} // namespace
+const char* GtkCssMenu() {
+ return GtkCheckVersion(4) ? "#popover.background.menu #contents"
+ : "GtkMenu#menu";
+}
+
+const char* GtkCssMenuItem() {
+ return GtkCheckVersion(4) ? "#modelbutton.flat" : "GtkMenuItem#menuitem";
+}
+
+const char* GtkCssMenuScrollbar() {
+ return GtkCheckVersion(4) ? "#scrollbar #range"
+ : "GtkScrollbar#scrollbar #trough";
+}
+
void GtkInitFromCommandLine(const base::CommandLine& command_line) {
CommonInitFromCommandLine(command_line);
}
@@ -182,7 +181,7 @@ void SetGtkTransientForAura(GtkWidget* dialog, aura::Window* parent) {
gtk_widget_realize(dialog);
gfx::AcceleratedWidget parent_id = parent->GetHost()->GetAcceleratedWidget();
- GtkUi::GetDelegate()->SetGtkWidgetTransientFor(dialog, parent_id);
+ GtkUi::GetPlatform()->SetGtkWidgetTransientFor(dialog, parent_id);
// We also set the |parent| as a property of |dialog|, so that we can unlink
// the two later.
@@ -196,7 +195,7 @@ aura::Window* GetAuraTransientParent(GtkWidget* dialog) {
void ClearAuraTransientParent(GtkWidget* dialog, aura::Window* parent) {
g_object_set_data(G_OBJECT(dialog), kAuraTransientParent, nullptr);
- GtkUi::GetDelegate()->ClearTransientFor(
+ GtkUi::GetPlatform()->ClearTransientFor(
parent->GetHost()->GetAcceleratedWidget());
}
@@ -337,11 +336,6 @@ GtkStateFlags StateToStateFlags(ui::NativeTheme::State state) {
}
}
-SkColor GdkRgbaToSkColor(const GdkRGBA& color) {
- return SkColorSetARGB(color.alpha * 255, color.red * 255, color.green * 255,
- color.blue * 255);
-}
-
NO_SANITIZE("cfi-icall")
GtkCssContext AppendCssNodeToStyleContext(GtkCssContext context,
const std::string& css_node) {
@@ -408,10 +402,10 @@ GtkCssContext AppendCssNodeToStyleContext(GtkCssContext context,
object_name = t.token();
break;
case CSS_TYPE: {
-#if BUILDFLAG(GTK_VERSION) < 4
- gtype = g_type_from_name(t.token().c_str());
- DCHECK(gtype);
-#endif
+ if (!GtkCheckVersion(4)) {
+ gtype = g_type_from_name(t.token().c_str());
+ DCHECK(gtype);
+ }
break;
}
case CSS_CLASS:
@@ -457,17 +451,6 @@ GtkCssContext GetStyleContextFromCss(const std::string& css_selector) {
return context;
}
-SkColor GetFgColorFromStyleContext(GtkStyleContext* context) {
- GdkRGBA color;
-#if BUILDFLAG(GTK_VERSION) >= 4
- gtk_style_context_get_color(context, &color);
-#else
- gtk_style_context_get_color(context, gtk_style_context_get_state(context),
- &color);
-#endif
- return GdkRgbaToSkColor(color);
-}
-
SkColor GetBgColorFromStyleContext(GtkCssContext context) {
// Backgrounds are more general than solid colors (eg. gradients),
// but chromium requires us to boil this down to one color. We
@@ -488,18 +471,12 @@ SkColor GetBgColorFromStyleContext(GtkCssContext context) {
}
SkColor GetFgColor(const std::string& css_selector) {
- return GetFgColorFromStyleContext(GetStyleContextFromCss(css_selector));
+ return GtkStyleContextGetColor(GetStyleContextFromCss(css_selector));
}
ScopedCssProvider GetCssProvider(const std::string& css) {
auto provider = TakeGObject(gtk_css_provider_new());
-#if BUILDFLAG(GTK_VERSION) >= 4
- gtk_css_provider_load_from_data(provider, css.c_str(), -1);
-#else
- GError* error = nullptr;
- gtk_css_provider_load_from_data(provider, css.c_str(), -1, &error);
- DCHECK(!error);
-#endif
+ GtkCssProviderLoadFromData(provider, css.c_str(), -1);
return provider;
}
@@ -544,28 +521,19 @@ SkColor GetSelectionBgColor(const std::string& css_selector) {
auto context = GetStyleContextFromCss(css_selector);
if (GtkCheckVersion(3, 20))
return GetBgColorFromStyleContext(context);
-#if BUILDFLAG(GTK_VERSION) < 4
- // This is verbatim how Gtk gets the selection color on versions before 3.20.
- GdkRGBA selection_color;
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
- gtk_style_context_get_background_color(
- context, gtk_style_context_get_state(context), &selection_color);
- G_GNUC_END_IGNORE_DEPRECATIONS;
- return GdkRgbaToSkColor(selection_color);
-#else
- NOTREACHED();
- return gfx::kPlaceholderColor;
-#endif
+ DCHECK(!GtkCheckVersion(4));
+ // This is verbatim how Gtk gets the selection color on versions
+ // before 3.20.
+ return GtkStyleContextGetBackgroundColor(context);
}
bool ContextHasClass(GtkCssContext context, const std::string& style_class) {
-#if BUILDFLAG(GTK_VERSION) >= 4
- return gtk_style_context_has_class(context, style_class.c_str());
-#else
- return gtk_style_context_has_class(context, style_class.c_str()) ||
- gtk_widget_path_iter_has_class(gtk_style_context_get_path(context), -1,
- style_class.c_str());
-#endif
+ bool has_class = gtk_style_context_has_class(context, style_class.c_str());
+ if (!GtkCheckVersion(4)) {
+ has_class |= gtk_widget_path_iter_has_class(
+ gtk_style_context_get_path(context), -1, style_class.c_str());
+ }
+ return has_class;
}
SkColor GetSeparatorColor(const std::string& css_selector) {
@@ -576,22 +544,17 @@ SkColor GetSeparatorColor(const std::string& css_selector) {
bool horizontal = ContextHasClass(context, "horizontal");
int w = 1, h = 1;
- GtkBorder border, padding;
-#if BUILDFLAG(GTK_VERSION) >= 4
- auto size = GetSeparatorSize(horizontal);
- w = size.width();
- h = size.height();
- gtk_style_context_get_border(context, &border);
- gtk_style_context_get_padding(context, &padding);
-#else
- gtk_style_context_get(context, gtk_style_context_get_state(context),
- "min-width", &w, "min-height", &h, nullptr);
- GtkStateFlags state = gtk_style_context_get_state(context);
- gtk_style_context_get_border(context, state, &border);
- gtk_style_context_get_padding(context, state, &padding);
-#endif
- w += border.left + padding.left + padding.right + border.right;
- h += border.top + padding.top + padding.bottom + border.bottom;
+ if (GtkCheckVersion(4)) {
+ auto size = GetSeparatorSize(horizontal);
+ w = size.width();
+ h = size.height();
+ } else {
+ GtkStyleContextGet(context, "min-width", &w, "min-height", &h, nullptr);
+ }
+ auto border = GtkStyleContextGetBorder(context);
+ auto padding = GtkStyleContextGetPadding(context);
+ w += border.left() + padding.left() + padding.right() + border.right();
+ h += border.top() + padding.top() + padding.bottom() + border.bottom();
if (horizontal) {
w = 24;
@@ -646,7 +609,7 @@ GdkModifierType GetGdkKeyEventState(const ui::KeyEvent& key_event) {
// In such a case there is no event being dispatching in the display
// backend.
state = static_cast<GdkModifierType>(
- state | ui::GtkUiDelegate::instance()->GetGdkKeyState());
+ state | GtkUi::GetPlatform()->GetGdkKeyState());
}
return state;
@@ -655,13 +618,13 @@ GdkModifierType GetGdkKeyEventState(const ui::KeyEvent& key_event) {
GdkEvent* GdkEventFromKeyEvent(const ui::KeyEvent& key_event) {
DCHECK(!GtkCheckVersion(4));
GdkEventType event_type =
- key_event.type() == ui::ET_KEY_PRESSED ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
+ key_event.type() == ui::ET_KEY_PRESSED ? GdkKeyPress() : GdkKeyRelease();
auto event_time = key_event.time_stamp() - base::TimeTicks();
int hw_code = GetKeyEventProperty(key_event, ui::kPropertyKeyboardHwKeyCode);
int group = GetKeyEventProperty(key_event, ui::kPropertyKeyboardGroup);
// Get GdkKeymap
- GdkKeymap* keymap = GtkUi::GetDelegate()->GetGdkKeymap();
+ GdkKeymap* keymap = GtkUi::GetPlatform()->GetGdkKeymap();
// Get keyval and state
GdkModifierType state = GetGdkKeyEventState(key_event);
@@ -690,19 +653,16 @@ GdkEvent* GdkEventFromKeyEvent(const ui::KeyEvent& key_event) {
}
GtkIconTheme* GetDefaultIconTheme() {
-#if BUILDFLAG(GTK_VERSION) >= 4
- return gtk_icon_theme_get_for_display(gdk_display_get_default());
-#else
- return gtk_icon_theme_get_default();
-#endif
+ return GtkCheckVersion(4)
+ ? gtk_icon_theme_get_for_display(gdk_display_get_default())
+ : gtk_icon_theme_get_default();
}
void GtkWindowDestroy(GtkWidget* widget) {
-#if BUILDFLAG(GTK_VERSION) >= 4
- gtk_window_destroy(GTK_WINDOW(widget));
-#else
- gtk_widget_destroy(widget);
-#endif
+ if (GtkCheckVersion(4))
+ gtk_window_destroy(GTK_WINDOW(widget));
+ else
+ gtk_widget_destroy(widget);
}
GtkWidget* GetDummyWindow() {
@@ -776,7 +736,7 @@ GdkTexture* GetTextureFromRenderNode(GskRenderNode* node) {
// TODO(tluk): Refactor this to make better use of the hierarchical nature of
// ColorPipeline.
-base::Optional<SkColor> SkColorFromColorId(ui::ColorId color_id) {
+absl::optional<SkColor> SkColorFromColorId(ui::ColorId color_id) {
switch (color_id) {
case ui::kColorWindowBackground:
case ui::kColorDialogBackground:
@@ -787,11 +747,13 @@ base::Optional<SkColor> SkColorFromColorId(ui::ColorId color_id) {
case ui::kColorAvatarIconIncognito:
return GetFgColor("GtkLabel#label");
case ui::kColorBubbleFooterBackground:
+ case ui::kColorSyncInfoBackground:
+ return GetBgColor("#statusbar");
case ui::kColorNotificationActionsBackground:
case ui::kColorNotificationBackgroundActive:
case ui::kColorNotificationImageBackground:
- case ui::kColorSyncInfoBackground:
- return GetBgColor("#statusbar");
+ return color_utils::BlendTowardMaxContrast(GetBgColor(""),
+ gfx::kGoogleGreyAlpha100);
// FocusableBorder
case ui::kColorFocusableBorderFocused:
@@ -814,60 +776,61 @@ base::Optional<SkColor> SkColorFromColorId(ui::ColorId color_id) {
case ui::kColorMenuItemBackgroundAlertedInitial:
case ui::kColorMenuItemBackgroundAlertedTarget:
case ui::kColorSubtleEmphasisBackground:
- return GetBgColor(kGtkCSSMenu);
+ return GetBgColor(GtkCssMenu());
case ui::kColorMenuBorder:
- return GetBorderColor(kGtkCSSMenu);
+ return GetBorderColor(GtkCssMenu());
case ui::kColorMenuItemBackgroundSelected:
- return GetBgColor(StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, ":hover"}));
+ return GetBgColor(
+ StrCat({GtkCssMenu(), " ", GtkCssMenuItem(), ":hover"}));
case ui::kColorMenuItemForeground:
case ui::kColorMenuDropmarker:
case ui::kColorMenuItemForegroundHighlighted:
return GetFgColor(
- StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, " GtkLabel#label"}));
+ StrCat({GtkCssMenu(), " ", GtkCssMenuItem(), " GtkLabel#label"}));
case ui::kColorMenuItemForegroundSelected:
- return GetFgColor(
- StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, ":hover GtkLabel#label"}));
+ return GetFgColor(StrCat(
+ {GtkCssMenu(), " ", GtkCssMenuItem(), ":hover GtkLabel#label"}));
case ui::kColorMenuItemForegroundDisabled:
return GetFgColor(StrCat(
- {kGtkCSSMenu, " ", kGtkCSSMenuItem, ":disabled GtkLabel#label"}));
+ {GtkCssMenu(), " ", GtkCssMenuItem(), ":disabled GtkLabel#label"}));
case ui::kColorAvatarIconGuest:
case ui::kColorMenuItemForegroundSecondary:
if (GtkCheckVersion(3, 20)) {
return GetFgColor(
- StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, " #accelerator"}));
+ StrCat({GtkCssMenu(), " ", GtkCssMenuItem(), " #accelerator"}));
}
- return GetFgColor(StrCat(
- {kGtkCSSMenu, " ", kGtkCSSMenuItem, " GtkLabel#label.accelerator"}));
+ return GetFgColor(StrCat({GtkCssMenu(), " ", GtkCssMenuItem(),
+ " GtkLabel#label.accelerator"}));
case ui::kColorMenuSeparator:
case ui::kColorAvatarHeaderArt:
if (GtkCheckVersion(3, 20)) {
return GetSeparatorColor(
- StrCat({kGtkCSSMenu, " GtkSeparator#separator.horizontal"}));
+ StrCat({GtkCssMenu(), " GtkSeparator#separator.horizontal"}));
}
return GetFgColor(
- StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, ".separator"}));
+ StrCat({GtkCssMenu(), " ", GtkCssMenuItem(), ".separator"}));
// Dropdown
case ui::kColorDropdownBackground:
return GetBgColor(
StrCat({"GtkComboBoxText#combobox GtkWindow#window.background.popup ",
- "GtkTreeMenu#menu(gtk-combobox-popup-menu) ", kGtkCSSMenuItem,
- " ", "GtkCellView#cellview"}));
+ "GtkTreeMenu#menu(gtk-combobox-popup-menu) ",
+ GtkCssMenuItem(), " ", "GtkCellView#cellview"}));
case ui::kColorDropdownForeground:
return GetFgColor(
StrCat({"GtkComboBoxText#combobox GtkWindow#window.background.popup ",
- "GtkTreeMenu#menu(gtk-combobox-popup-menu) ", kGtkCSSMenuItem,
- " ", "GtkCellView#cellview"}));
+ "GtkTreeMenu#menu(gtk-combobox-popup-menu) ",
+ GtkCssMenuItem(), " ", "GtkCellView#cellview"}));
case ui::kColorDropdownBackgroundSelected:
return GetBgColor(
StrCat({"GtkComboBoxText#combobox GtkWindow#window.background.popup ",
- "GtkTreeMenu#menu(gtk-combobox-popup-menu) ", kGtkCSSMenuItem,
- ":hover GtkCellView#cellview"}));
+ "GtkTreeMenu#menu(gtk-combobox-popup-menu) ",
+ GtkCssMenuItem(), ":hover GtkCellView#cellview"}));
case ui::kColorDropdownForegroundSelected:
return GetFgColor(
StrCat({"GtkComboBoxText#combobox GtkWindow#window.background.popup ",
- "GtkTreeMenu#menu(gtk-combobox-popup-menu) ", kGtkCSSMenuItem,
- ":hover GtkCellView#cellview"}));
+ "GtkTreeMenu#menu(gtk-combobox-popup-menu) ",
+ GtkCssMenuItem(), ":hover GtkCellView#cellview"}));
// Label
case ui::kColorLabelForeground:
@@ -898,22 +861,20 @@ base::Optional<SkColor> SkColorFromColorId(ui::ColorId color_id) {
case ui::kColorLinkForeground: {
if (GtkCheckVersion(3, 12))
return GetFgColor("GtkLabel#label.link:link");
-#if BUILDFLAG(GTK_VERSION) < 4
auto link_context = GetStyleContextFromCss("GtkLabel#label.view");
- GdkColor* color;
- gtk_style_context_get_style(link_context, "link-color", &color, nullptr);
+ GdkColor* color = nullptr;
+ GtkStyleContextGetStyle(link_context, "link-color", &color, nullptr);
if (color) {
SkColor ret_color =
SkColorSetRGB(color->red >> 8, color->green >> 8, color->blue >> 8);
// gdk_color_free() was deprecated in Gtk3.14. This code path is only
- // taken on versions earlier than Gtk3.12, but the compiler doesn't know
- // that, so silence the deprecation warnings.
+ // taken on versions earlier than Gtk3.12, but the compiler doesn't
+ // know that, so silence the deprecation warnings.
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
gdk_color_free(color);
G_GNUC_END_IGNORE_DEPRECATIONS;
return ret_color;
}
-#endif
// Default color comes from gtklinkbutton.c.
return SkColorSetRGB(0x00, 0x00, 0xEE);
}
@@ -1010,12 +971,10 @@ base::Optional<SkColor> SkColorFromColorId(ui::ColorId color_id) {
return GetBgColor(GtkCheckVersion(3, 20) ? "GtkTextView#textview.view"
: "GtkTextView.view");
case ui::kColorTextfieldForegroundPlaceholder:
- if (!GtkCheckVersion(3, 90)) {
+ if (!GtkCheckVersion(4)) {
auto context = GetStyleContextFromCss("GtkEntry#entry");
// This is copied from gtkentry.c.
- GdkRGBA fg = {0.5, 0.5, 0.5};
- gtk_style_context_lookup_color(context, "placeholder_text_color", &fg);
- return GdkRgbaToSkColor(fg);
+ return GtkStyleContextLookupColor(context, "placeholder_text_color");
}
return GetFgColor("GtkEntry#entry #text #placeholder");
case ui::kColorTextfieldForegroundDisabled:
@@ -1045,7 +1004,7 @@ base::Optional<SkColor> SkColorFromColorId(ui::ColorId color_id) {
case ui::kColorTooltipForeground: {
auto context = GetTooltipContext();
context = AppendCssNodeToStyleContext(context, "GtkLabel#label");
- return GetFgColorFromStyleContext(context);
+ return GtkStyleContextGetColor(context);
}
// Trees and Tables (implemented on GTK using the same class)
@@ -1106,8 +1065,9 @@ base::Optional<SkColor> SkColorFromColorId(ui::ColorId color_id) {
case ui::kColorMenuIcon:
if (GtkCheckVersion(3, 20))
return GetFgColor(
- StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, " #radio"}));
- return GetFgColor(StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, ".radio"}));
+ StrCat({GtkCssMenu(), " ", GtkCssMenuItem(), " #radio"}));
+ return GetFgColor(
+ StrCat({GtkCssMenu(), " ", GtkCssMenuItem(), ".radio"}));
case ui::kColorIcon:
return GetFgColor("GtkButton#button.flat.scale GtkImage#image");
@@ -1115,7 +1075,7 @@ base::Optional<SkColor> SkColorFromColorId(ui::ColorId color_id) {
default:
break;
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace gtk
diff --git a/chromium/ui/gtk/gtk_util.h b/chromium/ui/gtk/gtk_util.h
index 67550b1fd24..6be49077607 100644
--- a/chromium/ui/gtk/gtk_util.h
+++ b/chromium/ui/gtk/gtk_util.h
@@ -5,16 +5,12 @@
#ifndef UI_GTK_GTK_UTIL_H_
#define UI_GTK_GTK_UTIL_H_
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
#include <string>
#include <vector>
#include "base/component_export.h"
#include "ui/base/glib/scoped_gobject.h"
#include "ui/color/color_id.h"
-#include "ui/gtk/gtk_buildflags.h"
#include "ui/gtk/gtk_compat.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/window/frame_buttons.h"
@@ -33,11 +29,10 @@ class KeyEvent;
namespace gtk {
-extern const char kGtkCSSMenu[];
-extern const char kGtkCSSMenuItem[];
-extern const char kGtkCSSMenuScrollbar[];
+const char* GtkCssMenu();
+const char* GtkCssMenuItem();
+const char* GtkCssMenuScrollbar();
-COMPONENT_EXPORT(GTK)
void GtkInitFromCommandLine(const base::CommandLine& command_line);
// Sets |dialog| as transient for |parent|, which will keep it on top and center
@@ -122,7 +117,6 @@ class GtkCssContext {
using ScopedCssProvider = ScopedGObject<GtkCssProvider>;
-#if BUILDFLAG(GTK_VERSION) < 4
} // namespace gtk
// Template override cannot be in the gtk namespace.
@@ -150,13 +144,10 @@ inline void ScopedGObject<GtkStyleContext>::Unref() {
}
namespace gtk {
-#endif
// Converts ui::NativeTheme::State to GtkStateFlags.
GtkStateFlags StateToStateFlags(ui::NativeTheme::State state);
-SkColor GdkRgbaToSkColor(const GdkRGBA& color);
-
// If |context| is nullptr, creates a new top-level style context
// specified by parsing |css_node|. Otherwise, creates the child
// context with |context| as the parent.
@@ -171,8 +162,6 @@ GtkCssContext AppendCssNodeToStyleContext(GtkCssContext context,
// must g_object_unref() the returned context.
GtkCssContext GetStyleContextFromCss(const std::string& css_selector);
-SkColor GetFgColorFromStyleContext(GtkStyleContext* context);
-
SkColor GetBgColorFromStyleContext(GtkCssContext context);
// Overrides properties on |context| and all its parents with those
@@ -249,7 +238,7 @@ float GetDeviceScaleFactor();
GdkTexture* GetTextureFromRenderNode(GskRenderNode* node);
// Gets the GTK theme color for a given `color_id`.
-base::Optional<SkColor> SkColorFromColorId(ui::ColorId color_id);
+absl::optional<SkColor> SkColorFromColorId(ui::ColorId color_id);
} // namespace gtk
diff --git a/chromium/ui/gtk/input_method_context_impl_gtk.cc b/chromium/ui/gtk/input_method_context_impl_gtk.cc
index 4346c07488e..74f95a1ceaf 100644
--- a/chromium/ui/gtk/input_method_context_impl_gtk.cc
+++ b/chromium/ui/gtk/input_method_context_impl_gtk.cc
@@ -4,10 +4,7 @@
#include "ui/gtk/input_method_context_impl_gtk.h"
-#include <gdk/gdk.h>
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-#include <stddef.h>
+#include <cstddef>
#include "base/strings/utf_string_conversions.h"
#include "ui/aura/window_tree_host.h"
@@ -21,7 +18,7 @@
#include "ui/gfx/native_widget_types.h"
#include "ui/gtk/gtk_compat.h"
#include "ui/gtk/gtk_ui.h"
-#include "ui/gtk/gtk_ui_delegate.h"
+#include "ui/gtk/gtk_ui_platform.h"
#include "ui/gtk/gtk_util.h"
#include "ui/views/linux_ui/linux_ui.h"
@@ -32,7 +29,7 @@ namespace {
GdkEventKey* GdkEventToKey(GdkEvent* event) {
DCHECK(!GtkCheckVersion(4));
auto* key = reinterpret_cast<GdkEventKey*>(event);
- DCHECK(key->type == GDK_KEY_PRESS || key->type == GDK_KEY_RELEASE);
+ DCHECK(key->type == GdkKeyPress() || key->type == GdkKeyRelease());
return key;
}
@@ -46,7 +43,7 @@ GdkWindow* GetTargetWindow(const ui::KeyEvent& key_event) {
DCHECK(window) << "KeyEvent target window not set.";
auto window_id = window->GetHost()->GetAcceleratedWidget();
- return GtkUi::GetDelegate()->GetGdkWindow(window_id);
+ return GtkUi::GetPlatform()->GetGdkWindow(window_id);
}
// Translate IME ui::KeyEvent to a GdkEventKey.
diff --git a/chromium/ui/gtk/input_method_context_impl_gtk.h b/chromium/ui/gtk/input_method_context_impl_gtk.h
index 2fb3356649e..c5f21cde752 100644
--- a/chromium/ui/gtk/input_method_context_impl_gtk.h
+++ b/chromium/ui/gtk/input_method_context_impl_gtk.h
@@ -12,7 +12,6 @@
#include "ui/base/glib/glib_signal.h"
#include "ui/base/ime/linux/linux_input_method_context.h"
#include "ui/gfx/geometry/rect.h"
-#include "ui/gtk/gtk_buildflags.h"
using GtkIMContext = struct _GtkIMContext;
using GdkWindow = struct _GdkWindow;
diff --git a/chromium/ui/gtk/native_theme_gtk.cc b/chromium/ui/gtk/native_theme_gtk.cc
index 7efdd8cf94e..9696db767cf 100644
--- a/chromium/ui/gtk/native_theme_gtk.cc
+++ b/chromium/ui/gtk/native_theme_gtk.cc
@@ -4,8 +4,6 @@
#include "ui/gtk/native_theme_gtk.h"
-#include <gtk/gtk.h>
-
#include "base/strings/strcat.h"
#include "ui/color/color_provider_manager.h"
#include "ui/gfx/color_palette.h"
@@ -108,8 +106,7 @@ NativeThemeGtk::NativeThemeGtk() {
// Initialize the GtkTreeMenu type. _gtk_tree_menu_get_type() is private,
// so we need to initialize it indirectly.
- auto model =
- TakeGObject(GTK_TREE_MODEL(gtk_tree_store_new(1, G_TYPE_STRING)));
+ auto model = TakeGObject(GTK_TREE_MODEL(GtkTreeStoreNew(G_TYPE_STRING)));
auto combo = TakeGObject(gtk_combo_box_new_with_model(model));
}
@@ -164,11 +161,22 @@ void NativeThemeGtk::NotifyOnNativeThemeUpdated() {
native_theme->NotifyOnNativeThemeUpdated();
}
+std::string NativeThemeGtk::GetNativeThemeName() const {
+ gchar* theme = nullptr;
+ g_object_get(gtk_settings_get_default(), "gtk-theme-name", &theme, nullptr);
+ std::string theme_string;
+ if (theme) {
+ theme_string = theme;
+ g_free(theme);
+ }
+ return theme_string;
+}
+
void NativeThemeGtk::OnThemeChanged(GtkSettings* settings,
GtkParamSpec* param) {
SetThemeCssOverride(ScopedCssProvider());
for (auto& color : color_cache_)
- color = base::nullopt;
+ color = absl::nullopt;
// Hack to workaround a bug on GNOME standard themes which would
// cause black patches to be rendered on GtkFileChooser dialogs.
@@ -212,15 +220,13 @@ void NativeThemeGtk::OnThemeChanged(GtkSettings* settings,
bool NativeThemeGtk::AllowColorPipelineRedirection(
ColorScheme color_scheme) const {
- // TODO(crbug.com/1186781): Remove this override once we support NativeTheme
- // changes for GTK in Color Pipeline.
- return false;
+ return true;
}
SkColor NativeThemeGtk::GetSystemColorDeprecated(ColorId color_id,
ColorScheme color_scheme,
bool apply_processing) const {
- base::Optional<SkColor> color = color_cache_[color_id];
+ absl::optional<SkColor> color = color_cache_[color_id];
if (!color) {
if (auto provider_color_id = ui::NativeThemeColorIdToColorId(color_id))
color = SkColorFromColorId(provider_color_id.value());
@@ -244,7 +250,7 @@ void NativeThemeGtk::PaintArrowButton(
// Add the "flat" styleclass to avoid drawing a border.
auto context = GetStyleContextFromCss(
GtkCheckVersion(3, 20)
- ? StrCat({kGtkCSSMenuScrollbar, " #range GtkButton#button.flat"})
+ ? StrCat({GtkCssMenuScrollbar(), " #range GtkButton#button.flat"})
: "GtkRange.scrollbar.button.flat");
// Remove any rounded corners since arrow scrollbar buttons are tiny.
ApplyCssToContext(context, "* { border-radius: 0px; }");
@@ -269,7 +275,7 @@ void NativeThemeGtk::PaintArrowButton(
}
PaintWidget(canvas, rect, context, BG_RENDER_NORMAL, false);
- PaintArrow(canvas, rect, direction, GetFgColorFromStyleContext(context));
+ PaintArrow(canvas, rect, direction, GtkStyleContextGetColor(context));
}
void NativeThemeGtk::PaintScrollbarTrack(
@@ -282,7 +288,7 @@ void NativeThemeGtk::PaintScrollbarTrack(
PaintWidget(
canvas, rect,
GetStyleContextFromCss(GtkCheckVersion(3, 20)
- ? StrCat({kGtkCSSMenuScrollbar, " #trough"})
+ ? StrCat({GtkCssMenuScrollbar(), " #trough"})
: "GtkScrollbar.scrollbar.trough"),
BG_RENDER_NORMAL, true);
}
@@ -296,7 +302,7 @@ void NativeThemeGtk::PaintScrollbarThumb(
ColorScheme color_scheme) const {
auto context = GetStyleContextFromCss(
GtkCheckVersion(3, 20)
- ? StrCat({kGtkCSSMenuScrollbar, " #trough #slider"})
+ ? StrCat({GtkCssMenuScrollbar(), " #trough #slider"})
: "GtkScrollbar.scrollbar.slider");
gtk_style_context_set_state(context, StateToStateFlags(state));
PaintWidget(canvas, rect, context, BG_RENDER_NORMAL, true);
@@ -318,7 +324,7 @@ void NativeThemeGtk::PaintMenuPopupBackground(
const gfx::Size& size,
const MenuBackgroundExtraParams& menu_background,
ColorScheme color_scheme) const {
- auto context = GetStyleContextFromCss(kGtkCSSMenu);
+ auto context = GetStyleContextFromCss(GtkCssMenu());
// Chrome menus aren't rendered with transparency, so avoid rounded corners.
ApplyCssToContext(context, "* { border-radius: 0px; }");
PaintWidget(canvas, gfx::Rect(size), context, BG_RENDER_RECURSIVE, false);
@@ -331,7 +337,7 @@ void NativeThemeGtk::PaintMenuItemBackground(
const MenuItemExtraParams& menu_item,
ColorScheme color_scheme) const {
auto context =
- GetStyleContextFromCss(StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem}));
+ GetStyleContextFromCss(StrCat({GtkCssMenu(), " ", GtkCssMenuItem()}));
gtk_style_context_set_state(context, StateToStateFlags(state));
PaintWidget(canvas, rect, context, BG_RENDER_NORMAL, true);
}
@@ -365,7 +371,7 @@ void NativeThemeGtk::PaintMenuSeparator(
};
if (GtkCheckVersion(3, 20)) {
auto context = GetStyleContextFromCss(
- StrCat({kGtkCSSMenu, " GtkSeparator#separator.horizontal"}));
+ StrCat({GtkCssMenu(), " GtkSeparator#separator.horizontal"}));
int min_height = 1;
auto margin = GtkStyleContextGetMargin(context);
auto border = GtkStyleContextGetBorder(context);
@@ -383,7 +389,7 @@ void NativeThemeGtk::PaintMenuSeparator(
PaintWidget(canvas, gfx::Rect(x, y, w, h), context, BG_RENDER_NORMAL, true);
} else {
auto context = GetStyleContextFromCss(
- StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, ".separator.horizontal"}));
+ StrCat({GtkCssMenu(), " ", GtkCssMenuItem(), ".separator.horizontal"}));
gboolean wide_separators = false;
gint separator_height = 0;
GtkStyleContextGetStyle(context, "wide-separators", &wide_separators,
@@ -399,7 +405,7 @@ void NativeThemeGtk::PaintMenuSeparator(
PaintWidget(canvas, gfx::Rect(x, y, w, h), context, BG_RENDER_NONE, true);
} else {
cc::PaintFlags flags;
- flags.setColor(GetFgColorFromStyleContext(context));
+ flags.setColor(GtkStyleContextGetColor(context));
flags.setAntiAlias(true);
flags.setStrokeWidth(1);
canvas->drawLine(x + 0.5f, y + 0.5f, x + w + 0.5f, y + 0.5f, flags);
diff --git a/chromium/ui/gtk/native_theme_gtk.h b/chromium/ui/gtk/native_theme_gtk.h
index 0d9366a3013..34d932a0163 100644
--- a/chromium/ui/gtk/native_theme_gtk.h
+++ b/chromium/ui/gtk/native_theme_gtk.h
@@ -6,10 +6,9 @@
#define UI_GTK_NATIVE_THEME_GTK_H_
#include "base/callback_list.h"
-#include "base/component_export.h"
#include "base/macros.h"
#include "base/no_destructor.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/glib/glib_signal.h"
#include "ui/base/glib/scoped_gobject.h"
#include "ui/native_theme/native_theme_base.h"
@@ -23,7 +22,7 @@ namespace gtk {
using ScopedCssProvider = ScopedGObject<GtkCssProvider>;
// A version of NativeTheme that uses GTK-rendered widgets.
-class COMPONENT_EXPORT(GTK) NativeThemeGtk : public ui::NativeThemeBase {
+class NativeThemeGtk : public ui::NativeThemeBase {
public:
static NativeThemeGtk* instance();
@@ -71,6 +70,7 @@ class COMPONENT_EXPORT(GTK) NativeThemeGtk : public ui::NativeThemeBase {
const FrameTopAreaExtraParams& frame_top_area,
ColorScheme color_scheme) const override;
void NotifyOnNativeThemeUpdated() override;
+ std::string GetNativeThemeName() const override;
void OnThemeChanged(GtkSettings* settings, GtkParamSpec* param);
@@ -89,7 +89,7 @@ class COMPONENT_EXPORT(GTK) NativeThemeGtk : public ui::NativeThemeBase {
void SetThemeCssOverride(ScopedCssProvider provider);
- mutable base::Optional<SkColor> color_cache_[kColorId_NumColors];
+ mutable absl::optional<SkColor> color_cache_[kColorId_NumColors];
ScopedCssProvider theme_css_override_;
diff --git a/chromium/ui/gtk/native_theme_gtk_unittest.cc b/chromium/ui/gtk/native_theme_gtk_unittest.cc
index a19d79f564f..a415404b07e 100644
--- a/chromium/ui/gtk/native_theme_gtk_unittest.cc
+++ b/chromium/ui/gtk/native_theme_gtk_unittest.cc
@@ -2,20 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/gtk/native_theme_gtk.h"
-
+#include <memory>
#include <tuple>
#include "base/check.h"
#include "base/command_line.h"
+#include "base/memory/ptr_util.h"
#include "base/test/scoped_feature_list.h"
-#include "build/buildflag.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/ui_base_features.h"
-#include "ui/gtk/gtk_compat.h"
-#include "ui/gtk/gtk_util.h"
+#include "ui/gtk/gtk_ui_factory.h"
#include "ui/native_theme/native_theme_color_id.h"
#include "ui/native_theme/test/color_utils.h"
+#include "ui/views/linux_ui/linux_ui.h"
namespace gtk {
@@ -25,11 +24,7 @@ class NativeThemeGtkRedirectedEquivalenceTest
: public testing::TestWithParam<
std::tuple<ui::NativeTheme::ColorScheme, ui::NativeTheme::ColorId>> {
public:
- NativeThemeGtkRedirectedEquivalenceTest() {
- static bool loaded = LoadGtk(BUILDFLAG(GTK_VERSION));
- CHECK(loaded);
- GtkInitFromCommandLine(base::CommandLine(base::CommandLine::NO_PROGRAM));
- }
+ NativeThemeGtkRedirectedEquivalenceTest() { gtk_ui_ = BuildGtkUi(); }
static std::string ParamInfoToString(
::testing::TestParamInfo<
@@ -43,6 +38,9 @@ class NativeThemeGtkRedirectedEquivalenceTest
std::get<ui::NativeTheme::ColorId>(param_tuple));
}
+ protected:
+ views::LinuxUI* gtk_ui() { return gtk_ui_.get(); }
+
private:
static std::string ColorSchemeToString(ui::NativeTheme::ColorScheme scheme) {
switch (scheme) {
@@ -58,6 +56,8 @@ class NativeThemeGtkRedirectedEquivalenceTest
return "kPlatformHighContrast";
}
}
+
+ std::unique_ptr<views::LinuxUI> gtk_ui_;
};
} // namespace
@@ -68,7 +68,7 @@ TEST_P(NativeThemeGtkRedirectedEquivalenceTest, GetSystemColor) {
auto color_id = std::get<ui::NativeTheme::ColorId>(param_tuple);
// Verifies that colors with and without the Color Provider are the same.
- auto* native_theme_gtk = NativeThemeGtk::instance();
+ auto* native_theme_gtk = gtk_ui()->GetNativeTheme(nullptr);
ui::test::PrintableSkColor original{
native_theme_gtk->GetSystemColor(color_id, color_scheme)};
diff --git a/chromium/ui/gtk/nav_button_provider_gtk.cc b/chromium/ui/gtk/nav_button_provider_gtk.cc
index 085febcdeac..27239539af4 100644
--- a/chromium/ui/gtk/nav_button_provider_gtk.cc
+++ b/chromium/ui/gtk/nav_button_provider_gtk.cc
@@ -4,8 +4,6 @@
#include "ui/gtk/nav_button_provider_gtk.h"
-#include <gtk/gtk.h>
-
#include "base/notreached.h"
#include "ui/base/glib/glib_cast.h"
#include "ui/base/glib/scoped_gobject.h"
@@ -118,7 +116,7 @@ gfx::Size LoadNavButtonIcon(
SkColor* pixels = reinterpret_cast<SkColor*>(g_malloc(nbytes));
size_t stride = sizeof(SkColor) * width;
gdk_texture_download(texture, reinterpret_cast<guchar*>(pixels), stride);
- SkColor fg = GetFgColorFromStyleContext(button_context);
+ SkColor fg = GtkStyleContextGetColor(button_context);
for (int i = 0; i < width * height; ++i)
pixels[i] = SkColorSetA(fg, SkColorGetA(pixels[i]));
icon->texture = TakeGObject(
@@ -278,8 +276,10 @@ class NavButtonImageSource : public gfx::ImageSkiaSource {
} else {
cairo_pattern_t* cr_pattern = nullptr;
cairo_surface_t* cr_surface = nullptr;
- GtkStyleContextGet(button_context, GTK_STYLE_PROPERTY_BACKGROUND_IMAGE,
- &cr_pattern, nullptr);
+ GtkStyleContextGet(
+ button_context,
+ "background-image" /* GTK_STYLE_PROPERTY_BACKGROUND_IMAGE */,
+ &cr_pattern, nullptr);
if (cr_pattern) {
cairo_pattern_get_surface(cr_pattern, &cr_surface);
if (cr_surface &&
diff --git a/chromium/ui/gtk/nav_button_provider_gtk.h b/chromium/ui/gtk/nav_button_provider_gtk.h
index af521ea535d..ffedf019c8e 100644
--- a/chromium/ui/gtk/nav_button_provider_gtk.h
+++ b/chromium/ui/gtk/nav_button_provider_gtk.h
@@ -7,15 +7,13 @@
#include <map>
-#include "base/component_export.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/linux_ui/nav_button_provider.h"
namespace gtk {
-class COMPONENT_EXPORT(GTK) NavButtonProviderGtk
- : public views::NavButtonProvider {
+class NavButtonProviderGtk : public views::NavButtonProvider {
public:
NavButtonProviderGtk();
~NavButtonProviderGtk() override;
diff --git a/chromium/ui/gtk/printing/print_dialog_gtk.cc b/chromium/ui/gtk/printing/print_dialog_gtk.cc
index 7363dc20823..62108f0eb91 100644
--- a/chromium/ui/gtk/printing/print_dialog_gtk.cc
+++ b/chromium/ui/gtk/printing/print_dialog_gtk.cc
@@ -4,8 +4,6 @@
#include "ui/gtk/printing/print_dialog_gtk.h"
-#include <gtk/gtkunixprint.h>
-
#include <algorithm>
#include <cmath>
#include <memory>
@@ -28,13 +26,14 @@
#include "printing/print_job_constants.h"
#include "printing/print_settings.h"
#include "ui/aura/window.h"
+#include "ui/gtk/gtk_compat.h"
#include "ui/gtk/gtk_ui.h"
-#include "ui/gtk/gtk_ui_delegate.h"
+#include "ui/gtk/gtk_ui_platform.h"
#include "ui/gtk/gtk_util.h"
#include "ui/gtk/printing/printing_gtk_util.h"
#if defined(USE_CUPS)
-#include "printing/mojom/print.mojom.h"
+#include "printing/mojom/print.mojom.h" // nogncheck
#endif
using printing::PageRanges;
@@ -371,12 +370,12 @@ void PrintDialogGtk::ShowDialog(
gtk::SetGtkTransientForAura(dialog_, parent_view);
if (parent_view)
parent_view->AddObserver(this);
-#if BUILDFLAG(GTK_VERSION) >= 4
- gtk_window_set_hide_on_close(GTK_WINDOW(dialog_), true);
-#else
- g_signal_connect(dialog_, "delete-event",
- G_CALLBACK(gtk_widget_hide_on_delete), nullptr);
-#endif
+ if (gtk::GtkCheckVersion(4)) {
+ gtk_window_set_hide_on_close(GTK_WINDOW(dialog_), true);
+ } else {
+ g_signal_connect(dialog_, "delete-event",
+ G_CALLBACK(gtk_widget_hide_on_delete), nullptr);
+ }
// Handle the case when the existing |gtk_settings_| has "selection" selected
// as the page range, but |has_selection| is false.
@@ -408,7 +407,7 @@ void PrintDialogGtk::ShowDialog(
g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
gtk_widget_show(dialog_);
- gtk::GtkUi::GetDelegate()->ShowGtkWindow(GTK_WINDOW(dialog_));
+ gtk::GtkUi::GetPlatform()->ShowGtkWindow(GTK_WINDOW(dialog_));
}
void PrintDialogGtk::PrintDocument(const printing::MetafilePlayer& metafile,
diff --git a/chromium/ui/gtk/printing/print_dialog_gtk.h b/chromium/ui/gtk/printing/print_dialog_gtk.h
index 6eba9d4a192..bbdef2e00ce 100644
--- a/chromium/ui/gtk/printing/print_dialog_gtk.h
+++ b/chromium/ui/gtk/printing/print_dialog_gtk.h
@@ -5,8 +5,6 @@
#ifndef UI_GTK_PRINTING_PRINT_DIALOG_GTK_H_
#define UI_GTK_PRINTING_PRINT_DIALOG_GTK_H_
-#include <gtk/gtk.h>
-#include <gtk/gtkunixprint.h>
#include <memory>
#include "base/compiler_specific.h"
@@ -17,6 +15,7 @@
#include "printing/printing_context_linux.h"
#include "ui/aura/window_observer.h"
#include "ui/base/glib/glib_signal.h"
+#include "ui/gtk/gtk_compat.h"
namespace printing {
class MetafilePlayer;
diff --git a/chromium/ui/gtk/printing/printing_gtk_util.cc b/chromium/ui/gtk/printing/printing_gtk_util.cc
index 0b7d8010cef..0ebed5603f8 100644
--- a/chromium/ui/gtk/printing/printing_gtk_util.cc
+++ b/chromium/ui/gtk/printing/printing_gtk_util.cc
@@ -4,9 +4,6 @@
#include "ui/gtk/printing/printing_gtk_util.h"
-#include <gtk/gtk.h>
-#include <gtk/gtkunixprint.h>
-
#include <string>
#include "base/strings/utf_string_conversions.h"
@@ -15,6 +12,7 @@
#include "printing/units.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/size_f.h"
+#include "ui/gtk/gtk_compat.h"
namespace {
diff --git a/chromium/ui/gtk/select_file_dialog_impl_gtk.cc b/chromium/ui/gtk/select_file_dialog_impl_gtk.cc
index ead63d10c5d..d53f05761af 100644
--- a/chromium/ui/gtk/select_file_dialog_impl_gtk.cc
+++ b/chromium/ui/gtk/select_file_dialog_impl_gtk.cc
@@ -5,12 +5,11 @@
#include "ui/gtk/select_file_dialog_impl_gtk.h"
#include <glib/gi18n.h>
-#include <gtk/gtk.h>
-#include <stddef.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+#include <cstddef>
#include <map>
#include <memory>
#include <set>
@@ -30,7 +29,7 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/gtk/gtk_compat.h"
#include "ui/gtk/gtk_ui.h"
-#include "ui/gtk/gtk_ui_delegate.h"
+#include "ui/gtk/gtk_ui_platform.h"
#include "ui/gtk/gtk_util.h"
#include "ui/gtk/select_file_dialog_impl.h"
#include "ui/shell_dialogs/select_file_dialog.h"
@@ -299,7 +298,7 @@ void SelectFileDialogImplGTK::SelectFileImpl(
if (!GtkCheckVersion(4))
gtk_widget_show_all(dialog);
- gtk::GtkUi::GetDelegate()->ShowGtkWindow(GTK_WINDOW(dialog));
+ gtk::GtkUi::GetPlatform()->ShowGtkWindow(GTK_WINDOW(dialog));
}
void SelectFileDialogImplGTK::AddFilters(GtkFileChooser* chooser) {
@@ -395,9 +394,9 @@ GtkWidget* SelectFileDialogImplGTK::CreateFileOpenHelper(
const std::string& title,
const base::FilePath& default_path,
gfx::NativeWindow parent) {
- GtkWidget* dialog = gtk_file_chooser_dialog_new(
+ GtkWidget* dialog = GtkFileChooserDialogNew(
title.c_str(), nullptr, GTK_FILE_CHOOSER_ACTION_OPEN, GetCancelLabel(),
- GTK_RESPONSE_CANCEL, GetOpenLabel(), GTK_RESPONSE_ACCEPT, nullptr);
+ GTK_RESPONSE_CANCEL, GetOpenLabel(), GTK_RESPONSE_ACCEPT);
SetGtkTransientForAura(dialog, parent);
AddFilters(GTK_FILE_CHOOSER(dialog));
@@ -434,10 +433,10 @@ GtkWidget* SelectFileDialogImplGTK::CreateSelectFolderDialog(
IDS_SELECT_UPLOAD_FOLDER_DIALOG_UPLOAD_BUTTON)
: GetOpenLabel();
- GtkWidget* dialog = gtk_file_chooser_dialog_new(
+ GtkWidget* dialog = GtkFileChooserDialogNew(
title_string.c_str(), nullptr, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
GetCancelLabel(), GTK_RESPONSE_CANCEL, accept_button_label.c_str(),
- GTK_RESPONSE_ACCEPT, nullptr);
+ GTK_RESPONSE_ACCEPT);
SetGtkTransientForAura(dialog, parent);
GtkFileChooser* chooser = GTK_FILE_CHOOSER(dialog);
if (type == SELECT_UPLOAD_FOLDER || type == SELECT_EXISTING_FOLDER)
@@ -498,10 +497,10 @@ GtkWidget* SelectFileDialogImplGTK::CreateSaveAsDialog(
!title.empty() ? title
: l10n_util::GetStringUTF8(IDS_SAVE_AS_DIALOG_TITLE);
- GtkWidget* dialog = gtk_file_chooser_dialog_new(
+ GtkWidget* dialog = GtkFileChooserDialogNew(
title_string.c_str(), nullptr, GTK_FILE_CHOOSER_ACTION_SAVE,
GetCancelLabel(), GTK_RESPONSE_CANCEL, GetSaveLabel(),
- GTK_RESPONSE_ACCEPT, nullptr);
+ GTK_RESPONSE_ACCEPT);
SetGtkTransientForAura(dialog, parent);
AddFilters(GTK_FILE_CHOOSER(dialog));
diff --git a/chromium/ui/gtk/settings_provider_gtk.cc b/chromium/ui/gtk/settings_provider_gtk.cc
index 04a3c1e04d9..0163f4ece56 100644
--- a/chromium/ui/gtk/settings_provider_gtk.cc
+++ b/chromium/ui/gtk/settings_provider_gtk.cc
@@ -5,6 +5,8 @@
#include "ui/gtk/settings_provider_gtk.h"
#include "base/strings/string_split.h"
+#include "gtk_compat.h"
+#include "ui/gtk/gtk_compat.h"
#include "ui/gtk/gtk_ui.h"
#include "ui/gtk/gtk_util.h"
@@ -13,22 +15,18 @@ namespace gtk {
namespace {
std::string GetDecorationLayoutFromGtkWindow() {
-#if BUILDFLAG(GTK_VERSION) >= 4
- NOTREACHED();
- static const char kDefaultGtkLayout[] = "menu:minimize,maximize,close";
- return kDefaultGtkLayout;
-#else
+ DCHECK(!GtkCheckVersion(4));
+
GtkCssContext context = GetStyleContextFromCss("");
gtk_style_context_add_class(context, "csd");
gchar* layout_c = nullptr;
- gtk_style_context_get_style(context, "decoration-button-layout", &layout_c,
- nullptr);
+ GtkStyleContextGetStyle(context, "decoration-button-layout", &layout_c,
+ nullptr);
DCHECK(layout_c);
std::string layout(layout_c);
g_free(layout_c);
return layout;
-#endif
}
void ParseActionString(const std::string& value,
diff --git a/chromium/ui/gtk/wayland/BUILD.gn b/chromium/ui/gtk/wayland/BUILD.gn
deleted file mode 100644
index 599af208624..00000000000
--- a/chromium/ui/gtk/wayland/BUILD.gn
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/ozone.gni")
-
-assert(ozone_platform_wayland)
-
-component("wayland") {
- output_name = "ui_gtk_wayland"
- sources = [
- "gtk_ui_delegate_wayland_base.cc",
- "gtk_ui_delegate_wayland_base.h",
- ]
- deps = [
- "//base",
- "//build/config/linux/gtk",
- ]
- public_deps = [ "//ui/gtk:gtk_ui_delegate" ]
- defines = [ "IS_GTK_WAYLAND_IMPL" ]
-}
diff --git a/chromium/ui/gtk/wayland/gtk_ui_delegate_wayland_base.cc b/chromium/ui/gtk/wayland/gtk_ui_delegate_wayland_base.cc
deleted file mode 100644
index f075333af40..00000000000
--- a/chromium/ui/gtk/wayland/gtk_ui_delegate_wayland_base.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/gtk/wayland/gtk_ui_delegate_wayland_base.h"
-
-#include <gtk/gtk.h>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/environment.h"
-#include "base/logging.h"
-
-#if BUILDFLAG(GTK_VERSION) >= 4
-#include <gdk/wayland/gdkwayland.h>
-#else
-#include <gdk/gdkwayland.h>
-
-#define WEAK_GTK_FN(x) extern "C" __attribute__((weak)) decltype(x) x
-
-WEAK_GTK_FN(gdk_wayland_window_set_transient_for_exported);
-#endif
-
-namespace ui {
-
-GtkUiDelegateWaylandBase::GtkUiDelegateWaylandBase() {
- gdk_set_allowed_backends("wayland");
- // GDK_BACKEND takes precedence over gdk_set_allowed_backends(), so override
- // it to ensure we get the wayland backend.
- base::Environment::Create()->SetVar("GDK_BACKEND", "wayland");
-}
-
-GtkUiDelegateWaylandBase::~GtkUiDelegateWaylandBase() = default;
-
-void GtkUiDelegateWaylandBase::OnInitialized(GtkWidget* widget) {
- // Nothing to do upon initialization for Wayland.
-}
-
-GdkKeymap* GtkUiDelegateWaylandBase::GetGdkKeymap() {
- NOTIMPLEMENTED_LOG_ONCE();
- return nullptr;
-}
-
-GdkWindow* GtkUiDelegateWaylandBase::GetGdkWindow(
- gfx::AcceleratedWidget window_id) {
- NOTIMPLEMENTED_LOG_ONCE();
- return nullptr;
-}
-
-bool GtkUiDelegateWaylandBase::SetGtkWidgetTransientFor(
- GtkWidget* widget,
- gfx::AcceleratedWidget parent) {
-#if BUILDFLAG(GTK_VERSION) < 4
- if (!gdk_wayland_window_set_transient_for_exported) {
- LOG(WARNING) << "set_transient_for_exported not supported in GTK version "
- << GTK_MAJOR_VERSION << '.' << GTK_MINOR_VERSION << '.'
- << GTK_MICRO_VERSION;
- return false;
- }
-#endif
-
- return SetGtkWidgetTransientForImpl(
- parent, base::BindOnce(&GtkUiDelegateWaylandBase::OnHandle,
- weak_factory_.GetWeakPtr(), widget));
-}
-
-void GtkUiDelegateWaylandBase::ClearTransientFor(
- gfx::AcceleratedWidget parent) {
- // Nothing to do here.
-}
-
-void GtkUiDelegateWaylandBase::ShowGtkWindow(GtkWindow* window) {
- // TODO(crbug.com/1008755): Check if gtk_window_present_with_time is needed
- // here as well, similarly to what is done in X11 impl.
- gtk_window_present(window);
-}
-
-void GtkUiDelegateWaylandBase::OnHandle(GtkWidget* widget,
- const std::string& handle) {
- char* parent = const_cast<char*>(handle.c_str());
-#if BUILDFLAG(GTK_VERSION) >= 4
- auto* toplevel =
- GDK_TOPLEVEL(gtk_native_get_surface(gtk_widget_get_native(widget)));
- gdk_wayland_toplevel_set_transient_for_exported(toplevel, parent);
-#else
- gdk_wayland_window_set_transient_for_exported(gtk_widget_get_window(widget),
- parent);
-#endif
-}
-
-} // namespace ui
diff --git a/chromium/ui/gtk/wayland/gtk_ui_platform_wayland.cc b/chromium/ui/gtk/wayland/gtk_ui_platform_wayland.cc
new file mode 100644
index 00000000000..d7d503d8245
--- /dev/null
+++ b/chromium/ui/gtk/wayland/gtk_ui_platform_wayland.cc
@@ -0,0 +1,84 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gtk/wayland/gtk_ui_platform_wayland.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/environment.h"
+#include "base/logging.h"
+#include "ui/base/glib/glib_cast.h"
+#include "ui/base/linux/linux_ui_delegate.h"
+#include "ui/gtk/gtk_compat.h"
+
+namespace gtk {
+
+GtkUiPlatformWayland::GtkUiPlatformWayland() {
+ gdk_set_allowed_backends("wayland");
+ // GDK_BACKEND takes precedence over gdk_set_allowed_backends(), so override
+ // it to ensure we get the wayland backend.
+ base::Environment::Create()->SetVar("GDK_BACKEND", "wayland");
+}
+
+GtkUiPlatformWayland::~GtkUiPlatformWayland() = default;
+
+void GtkUiPlatformWayland::OnInitialized(GtkWidget* widget) {
+ // Nothing to do upon initialization for Wayland.
+}
+
+GdkKeymap* GtkUiPlatformWayland::GetGdkKeymap() {
+ NOTIMPLEMENTED_LOG_ONCE();
+ return nullptr;
+}
+
+GdkWindow* GtkUiPlatformWayland::GetGdkWindow(
+ gfx::AcceleratedWidget window_id) {
+ NOTIMPLEMENTED_LOG_ONCE();
+ return nullptr;
+}
+
+bool GtkUiPlatformWayland::SetGtkWidgetTransientFor(
+ GtkWidget* widget,
+ gfx::AcceleratedWidget parent) {
+ if (!gtk::GtkCheckVersion(3, 22)) {
+ LOG(WARNING) << "set_transient_for_exported not supported in GTK version "
+ << gtk_get_major_version() << '.' << gtk_get_minor_version()
+ << '.' << gtk_get_micro_version();
+ return false;
+ }
+
+ return ui::LinuxUiDelegate::GetInstance()->SetWidgetTransientFor(
+ parent, base::BindOnce(&GtkUiPlatformWayland::OnHandle,
+ weak_factory_.GetWeakPtr(), widget));
+}
+
+void GtkUiPlatformWayland::ClearTransientFor(gfx::AcceleratedWidget parent) {
+ // Nothing to do here.
+}
+
+void GtkUiPlatformWayland::ShowGtkWindow(GtkWindow* window) {
+ // TODO(crbug.com/1008755): Check if gtk_window_present_with_time is needed
+ // here as well, similarly to what is done in X11 impl.
+ gtk_window_present(window);
+}
+
+void GtkUiPlatformWayland::OnHandle(GtkWidget* widget,
+ const std::string& handle) {
+ char* parent = const_cast<char*>(handle.c_str());
+ if (gtk::GtkCheckVersion(4)) {
+ auto* toplevel = GlibCast<GdkToplevel>(
+ gtk_native_get_surface(gtk_widget_get_native(widget)),
+ gdk_toplevel_get_type());
+ gdk_wayland_toplevel_set_transient_for_exported(toplevel, parent);
+ } else {
+ gdk_wayland_window_set_transient_for_exported(gtk_widget_get_window(widget),
+ parent);
+ }
+}
+
+int GtkUiPlatformWayland::GetGdkKeyState() {
+ return ui::LinuxUiDelegate::GetInstance()->GetKeyState();
+}
+
+} // namespace gtk
diff --git a/chromium/ui/gtk/wayland/gtk_ui_delegate_wayland_base.h b/chromium/ui/gtk/wayland/gtk_ui_platform_wayland.h
index afab8a113a6..41eae190208 100644
--- a/chromium/ui/gtk/wayland/gtk_ui_delegate_wayland_base.h
+++ b/chromium/ui/gtk/wayland/gtk_ui_platform_wayland.h
@@ -2,27 +2,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_GTK_WAYLAND_GTK_UI_DELEGATE_WAYLAND_BASE_H_
-#define UI_GTK_WAYLAND_GTK_UI_DELEGATE_WAYLAND_BASE_H_
+#ifndef UI_GTK_WAYLAND_GTK_UI_PLATFORM_WAYLAND_H_
+#define UI_GTK_WAYLAND_GTK_UI_PLATFORM_WAYLAND_H_
#include <string>
#include "base/callback_forward.h"
-#include "base/component_export.h"
#include "base/memory/weak_ptr.h"
-#include "ui/gtk/gtk_ui_delegate.h"
+#include "ui/gtk/gtk_ui_platform.h"
-namespace ui {
+namespace gtk {
-class COMPONENT_EXPORT(GTK_WAYLAND) GtkUiDelegateWaylandBase
- : public GtkUiDelegate {
+class GtkUiPlatformWayland : public GtkUiPlatform {
public:
- GtkUiDelegateWaylandBase();
- GtkUiDelegateWaylandBase(const GtkUiDelegateWaylandBase&) = delete;
- GtkUiDelegateWaylandBase& operator=(const GtkUiDelegateWaylandBase&) = delete;
- ~GtkUiDelegateWaylandBase() override;
+ GtkUiPlatformWayland();
+ GtkUiPlatformWayland(const GtkUiPlatformWayland&) = delete;
+ GtkUiPlatformWayland& operator=(const GtkUiPlatformWayland&) = delete;
+ ~GtkUiPlatformWayland() override;
- // GtkUiDelegate:
+ // GtkUiPlatform:
void OnInitialized(GtkWidget* widget) override;
GdkKeymap* GetGdkKeymap() override;
GdkWindow* GetGdkWindow(gfx::AcceleratedWidget window_id) override;
@@ -30,20 +28,16 @@ class COMPONENT_EXPORT(GTK_WAYLAND) GtkUiDelegateWaylandBase
gfx::AcceleratedWidget parent) override;
void ClearTransientFor(gfx::AcceleratedWidget parent) override;
void ShowGtkWindow(GtkWindow* window) override;
-
- protected:
- virtual bool SetGtkWidgetTransientForImpl(
- gfx::AcceleratedWidget parent,
- base::OnceCallback<void(const std::string&)> callback) = 0;
+ int GetGdkKeyState() override;
private:
// Called when xdg-foreign exports a parent window passed in
// SetGtkWidgetTransientFor.
void OnHandle(GtkWidget* widget, const std::string& handle);
- base::WeakPtrFactory<GtkUiDelegateWaylandBase> weak_factory_{this};
+ base::WeakPtrFactory<GtkUiPlatformWayland> weak_factory_{this};
};
-} // namespace ui
+} // namespace gtk
-#endif // UI_GTK_WAYLAND_GTK_UI_DELEGATE_WAYLAND_BASE_H_
+#endif // UI_GTK_WAYLAND_GTK_UI_PLATFORM_WAYLAND_H_
diff --git a/chromium/ui/gtk/x/BUILD.gn b/chromium/ui/gtk/x/BUILD.gn
deleted file mode 100644
index 6046a39c7a1..00000000000
--- a/chromium/ui/gtk/x/BUILD.gn
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/ozone.gni")
-import("//build/config/ui.gni")
-
-assert(use_x11 || ozone_platform_x11)
-
-component("x") {
- output_name = "ui_gtk_x"
- sources = [
- "gtk_event_loop_x11.cc",
- "gtk_event_loop_x11.h",
- "gtk_ui_delegate_x11.cc",
- "gtk_ui_delegate_x11.h",
- ]
- deps = [
- "//base",
- "//build/config/linux/gtk",
- "//ui/base",
- "//ui/events/platform/x11",
- "//ui/gfx/x",
- "//ui/platform_window/x11",
- ]
- public_deps = [ "//ui/gtk:gtk_ui_delegate" ]
- defines = [ "IS_UI_GTK_X_IMPL" ]
-}
diff --git a/chromium/ui/gtk/x/gtk_event_loop_x11.cc b/chromium/ui/gtk/x/gtk_event_loop_x11.cc
index 53007392631..942c76405cd 100644
--- a/chromium/ui/gtk/x/gtk_event_loop_x11.cc
+++ b/chromium/ui/gtk/x/gtk_event_loop_x11.cc
@@ -4,22 +4,14 @@
#include "ui/gtk/x/gtk_event_loop_x11.h"
-#include <gtk/gtk.h>
#include <xcb/xcb.h>
#include <xcb/xproto.h>
#include "ui/base/x/x11_util.h"
#include "ui/gfx/x/event.h"
+#include "ui/gtk/gtk_compat.h"
-extern "C" {
-#if BUILDFLAG(GTK_VERSION) >= 4
-unsigned long gdk_x11_surface_get_xid(GdkSurface* surface);
-#else
-unsigned long gdk_x11_window_get_xid(GdkWindow* window);
-#endif
-}
-
-namespace ui {
+namespace gtk {
namespace {
@@ -29,7 +21,22 @@ x11::KeyButMask BuildXkbStateFromGdkEvent(unsigned int state,
}
x11::KeyEvent ConvertGdkEventToKeyEvent(GdkEvent* gdk_event) {
-#if BUILDFLAG(GTK_VERSION) >= 4
+ if (!gtk::GtkCheckVersion(4)) {
+ auto* key = reinterpret_cast<GdkEventKey*>(gdk_event);
+ DCHECK(key->type == GdkKeyPress() || key->type == GdkKeyRelease());
+ return {
+ .opcode = key->type == GdkKeyPress() ? x11::KeyEvent::Press
+ : x11::KeyEvent::Release,
+ .send_event = key->send_event,
+ .detail = static_cast<x11::KeyCode>(key->hardware_keycode),
+ .time = static_cast<x11::Time>(key->time),
+ .root = ui::GetX11RootWindow(),
+ .event = static_cast<x11::Window>(gdk_x11_window_get_xid(key->window)),
+ .state = BuildXkbStateFromGdkEvent(key->state, key->group),
+ .same_screen = true,
+ };
+ }
+
GdkKeymapKey* keys = nullptr;
guint* keyvals = nullptr;
gint n_entries = 0;
@@ -50,11 +57,11 @@ x11::KeyEvent ConvertGdkEventToKeyEvent(GdkEvent* gdk_event) {
}
return {
- .opcode = gdk_event_get_event_type(gdk_event) == GDK_KEY_PRESS
+ .opcode = gtk::GdkEventGetEventType(gdk_event) == GdkKeyPress()
? x11::KeyEvent::Press
: x11::KeyEvent::Release,
.detail = static_cast<x11::KeyCode>(keymap_key.keycode),
- .time = static_cast<x11::Time>(gdk_event_get_time(gdk_event)),
+ .time = static_cast<x11::Time>(gtk::GdkEventGetTime(gdk_event)),
.root = ui::GetX11RootWindow(),
.event = static_cast<x11::Window>(
gdk_x11_surface_get_xid(gdk_event_get_surface(gdk_event))),
@@ -62,21 +69,6 @@ x11::KeyEvent ConvertGdkEventToKeyEvent(GdkEvent* gdk_event) {
gdk_event_get_modifier_state(gdk_event), keymap_key.group),
.same_screen = true,
};
-#else
- return {
- .opcode = gdk_event->key.type == GDK_KEY_PRESS ? x11::KeyEvent::Press
- : x11::KeyEvent::Release,
- .send_event = gdk_event->key.send_event,
- .detail = static_cast<x11::KeyCode>(gdk_event->key.hardware_keycode),
- .time = static_cast<x11::Time>(gdk_event->key.time),
- .root = ui::GetX11RootWindow(),
- .event = static_cast<x11::Window>(
- gdk_x11_window_get_xid(gdk_event->key.window)),
- .state =
- BuildXkbStateFromGdkEvent(gdk_event->key.state, gdk_event->key.group),
- .same_screen = true,
- };
-#endif
}
void ProcessGdkEvent(GdkEvent* gdk_event) {
@@ -94,18 +86,11 @@ void ProcessGdkEvent(GdkEvent* gdk_event) {
// corresponding key event in the X event queue. So we have to handle this
// case. ibus-gtk is used through gtk-immodule to support IMEs.
-#if BUILDFLAG(GTK_VERSION) >= 4
- auto event_type = gdk_event_get_event_type(gdk_event);
-#else
- auto event_type = gdk_event->type;
-#endif
- switch (event_type) {
- case GDK_KEY_PRESS:
- case GDK_KEY_RELEASE:
- break;
- default:
- return;
- }
+ auto event_type = gtk::GtkCheckVersion(4)
+ ? gtk::GdkEventGetEventType(gdk_event)
+ : *reinterpret_cast<GdkEventType*>(gdk_event);
+ if (event_type != GdkKeyPress() && event_type != GdkKeyRelease())
+ return;
// We want to process the gtk event; mapped to an X11 event immediately
// otherwise if we put it back on the queue we may get items out of order.
@@ -116,35 +101,35 @@ void ProcessGdkEvent(GdkEvent* gdk_event) {
} // namespace
GtkEventLoopX11::GtkEventLoopX11(GtkWidget* widget) {
-#if BUILDFLAG(GTK_VERSION) >= 4
- surface_ = gtk_native_get_surface(gtk_widget_get_native(widget));
- signal_id_ =
- g_signal_connect(surface_, "event", G_CALLBACK(OnEventThunk), this);
-#else
- gdk_event_handler_set(DispatchGdkEvent, nullptr, nullptr);
-#endif
+ if (gtk::GtkCheckVersion(4)) {
+ surface_ = gtk_native_get_surface(gtk_widget_get_native(widget));
+ signal_id_ =
+ g_signal_connect(surface_, "event", G_CALLBACK(OnEventThunk), this);
+ } else {
+ gdk_event_handler_set(DispatchGdkEvent, nullptr, nullptr);
+ }
}
GtkEventLoopX11::~GtkEventLoopX11() {
-#if BUILDFLAG(GTK_VERSION) >= 4
- g_signal_handler_disconnect(surface_, signal_id_);
-#else
- gdk_event_handler_set(reinterpret_cast<GdkEventFunc>(gtk_main_do_event),
- nullptr, nullptr);
-#endif
+ if (gtk::GtkCheckVersion(4)) {
+ g_signal_handler_disconnect(surface_, signal_id_);
+ } else {
+ gdk_event_handler_set(reinterpret_cast<GdkEventFunc>(gtk_main_do_event),
+ nullptr, nullptr);
+ }
}
-#if BUILDFLAG(GTK_VERSION) >= 4
gboolean GtkEventLoopX11::OnEvent(GdkEvent* gdk_event) {
+ DCHECK(gtk::GtkCheckVersion(4));
ProcessGdkEvent(gdk_event);
return false;
}
-#else
+
// static
void GtkEventLoopX11::DispatchGdkEvent(GdkEvent* gdk_event, gpointer) {
+ DCHECK(!gtk::GtkCheckVersion(4));
ProcessGdkEvent(gdk_event);
gtk_main_do_event(gdk_event);
}
-#endif
-} // namespace ui
+} // namespace gtk
diff --git a/chromium/ui/gtk/x/gtk_event_loop_x11.h b/chromium/ui/gtk/x/gtk_event_loop_x11.h
index 91cbe124268..a6e9251ea3e 100644
--- a/chromium/ui/gtk/x/gtk_event_loop_x11.h
+++ b/chromium/ui/gtk/x/gtk_event_loop_x11.h
@@ -5,14 +5,11 @@
#ifndef UI_GTK_X_GTK_EVENT_LOOP_X11_H_
#define UI_GTK_X_GTK_EVENT_LOOP_X11_H_
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
#include "ui/base/glib/glib_integers.h"
#include "ui/base/glib/glib_signal.h"
-#include "ui/gtk/gtk_buildflags.h"
+#include "ui/gtk/gtk_compat.h"
-namespace ui {
+namespace gtk {
class GtkEventLoopX11 {
public:
@@ -23,15 +20,17 @@ class GtkEventLoopX11 {
GtkEventLoopX11& operator=(const GtkEventLoopX11&) = delete;
private:
-#if BUILDFLAG(GTK_VERSION) >= 4
- CHROMEG_CALLBACK_0(GtkEventLoopX11, gboolean, OnEvent, GdkEvent*);
+ // This state is only used on GTK4.
GdkSurface* surface_ = nullptr;
gulong signal_id_ = 0;
-#else
+
+ // Only called on GTK3.
static void DispatchGdkEvent(GdkEvent* gdk_event, gpointer);
-#endif
+
+ // Only called on GTK4.
+ CHROMEG_CALLBACK_0(GtkEventLoopX11, gboolean, OnEvent, GdkEvent*);
};
-} // namespace ui
+} // namespace gtk
#endif // UI_GTK_X_GTK_EVENT_LOOP_X11_H_
diff --git a/chromium/ui/gtk/x/gtk_ui_delegate_x11.cc b/chromium/ui/gtk/x/gtk_ui_platform_x11.cc
index 618d0865860..a61f472e7a8 100644
--- a/chromium/ui/gtk/x/gtk_ui_delegate_x11.cc
+++ b/chromium/ui/gtk/x/gtk_ui_platform_x11.cc
@@ -2,9 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/gtk/x/gtk_ui_delegate_x11.h"
-
-#include <gtk/gtk.h>
+#include "ui/gtk/x/gtk_ui_platform_x11.h"
#include "base/check.h"
#include "base/environment.h"
@@ -15,29 +13,14 @@
#include "ui/gfx/x/xlib_support.h"
#include "ui/gfx/x/xproto.h"
#include "ui/gfx/x/xproto_util.h"
+#include "ui/gtk/gtk_compat.h"
#include "ui/gtk/x/gtk_event_loop_x11.h"
#include "ui/platform_window/x11/x11_window.h"
#include "ui/platform_window/x11/x11_window_manager.h"
-extern "C" {
-GdkWindow* gdk_x11_window_foreign_new_for_display(GdkDisplay* display,
- unsigned long window);
-
-GdkWindow* gdk_x11_window_lookup_for_display(GdkDisplay* display,
- unsigned long window);
-
-#if BUILDFLAG(GTK_VERSION) >= 4
-unsigned long gdk_x11_surface_get_xid(GdkSurface* surface);
-#else
-unsigned long gdk_x11_window_get_xid(GdkWindow* window);
-#endif
-}
-
-namespace ui {
+namespace gtk {
-GtkUiDelegateX11::GtkUiDelegateX11(x11::Connection* connection)
- : connection_(connection) {
- DCHECK(connection_);
+GtkUiPlatformX11::GtkUiPlatformX11() : connection_(x11::Connection::Get()) {
gdk_set_allowed_backends("x11");
// GDK_BACKEND takes precedence over gdk_set_allowed_backends(), so override
// it to ensure we get the x11 backend.
@@ -45,9 +28,9 @@ GtkUiDelegateX11::GtkUiDelegateX11(x11::Connection* connection)
x11::InitXlib();
}
-GtkUiDelegateX11::~GtkUiDelegateX11() = default;
+GtkUiPlatformX11::~GtkUiPlatformX11() = default;
-void GtkUiDelegateX11::OnInitialized(GtkWidget* widget) {
+void GtkUiPlatformX11::OnInitialized(GtkWidget* widget) {
// Ensure the singleton instance of GtkEventLoopX11 is created and started.
if (!event_loop_)
event_loop_ = std::make_unique<GtkEventLoopX11>(widget);
@@ -58,21 +41,13 @@ void GtkUiDelegateX11::OnInitialized(GtkWidget* widget) {
x11::SetXlibErrorHandler();
}
-GdkKeymap* GtkUiDelegateX11::GetGdkKeymap() {
-#if BUILDFLAG(GTK_VERSION) >= 4
- NOTREACHED();
- return nullptr;
-#else
+GdkKeymap* GtkUiPlatformX11::GetGdkKeymap() {
+ DCHECK(!gtk::GtkCheckVersion(4));
return gdk_keymap_get_for_display(GetGdkDisplay());
-#endif
}
-GdkWindow* GtkUiDelegateX11::GetGdkWindow(gfx::AcceleratedWidget window_id) {
-#if BUILDFLAG(GTK_VERSION) >= 4
- // This function is only used by InputMethodContextImplGtk with GTK3.
- NOTREACHED();
- return nullptr;
-#else
+GdkWindow* GtkUiPlatformX11::GetGdkWindow(gfx::AcceleratedWidget window_id) {
+ DCHECK(!gtk::GtkCheckVersion(4));
GdkDisplay* display = GetGdkDisplay();
GdkWindow* gdk_window = gdk_x11_window_lookup_for_display(
display, static_cast<uint32_t>(window_id));
@@ -82,18 +57,15 @@ GdkWindow* GtkUiDelegateX11::GetGdkWindow(gfx::AcceleratedWidget window_id) {
gdk_window = gdk_x11_window_foreign_new_for_display(
display, static_cast<uint32_t>(window_id));
return gdk_window;
-#endif
}
-bool GtkUiDelegateX11::SetGtkWidgetTransientFor(GtkWidget* widget,
+bool GtkUiPlatformX11::SetGtkWidgetTransientFor(GtkWidget* widget,
gfx::AcceleratedWidget parent) {
-#if BUILDFLAG(GTK_VERSION) >= 4
- auto x11_window = static_cast<x11::Window>(gdk_x11_surface_get_xid(
- gtk_native_get_surface(gtk_widget_get_native(widget))));
-#else
auto x11_window = static_cast<x11::Window>(
- gdk_x11_window_get_xid(gtk_widget_get_window(widget)));
-#endif
+ gtk::GtkCheckVersion(4)
+ ? gdk_x11_surface_get_xid(
+ gtk_native_get_surface(gtk_widget_get_native(widget)))
+ : gdk_x11_window_get_xid(gtk_widget_get_window(widget)));
SetProperty(x11_window, x11::Atom::WM_TRANSIENT_FOR, x11::Atom::WINDOW,
parent);
SetProperty(x11_window, x11::GetAtom("_NET_WM_WINDOW_TYPE"), x11::Atom::ATOM,
@@ -106,7 +78,7 @@ bool GtkUiDelegateX11::SetGtkWidgetTransientFor(GtkWidget* widget,
return true;
}
-void GtkUiDelegateX11::ClearTransientFor(gfx::AcceleratedWidget parent) {
+void GtkUiPlatformX11::ClearTransientFor(gfx::AcceleratedWidget parent) {
ui::X11Window* parent_window =
ui::X11WindowManager::GetInstance()->GetWindow(parent);
// parent_window might be dead if there was a top-down window close
@@ -114,24 +86,24 @@ void GtkUiDelegateX11::ClearTransientFor(gfx::AcceleratedWidget parent) {
parent_window->SetTransientWindow(x11::Window::None);
}
-GdkDisplay* GtkUiDelegateX11::GetGdkDisplay() {
+GdkDisplay* GtkUiPlatformX11::GetGdkDisplay() {
if (!display_)
display_ = gdk_display_get_default();
return display_;
}
-void GtkUiDelegateX11::ShowGtkWindow(GtkWindow* window) {
+void GtkUiPlatformX11::ShowGtkWindow(GtkWindow* window) {
// We need to call gtk_window_present after making the widgets visible to make
// sure window gets correctly raised and gets focus.
- DCHECK(X11EventSource::HasInstance());
+ DCHECK(ui::X11EventSource::HasInstance());
gtk_window_present_with_time(
window,
- static_cast<uint32_t>(X11EventSource::GetInstance()->GetTimestamp()));
+ static_cast<uint32_t>(ui::X11EventSource::GetInstance()->GetTimestamp()));
}
-int GtkUiDelegateX11::GetGdkKeyState() {
+int GtkUiPlatformX11::GetGdkKeyState() {
auto* xevent =
- X11EventSource::GetInstance()->connection()->dispatching_event();
+ ui::X11EventSource::GetInstance()->connection()->dispatching_event();
if (!xevent)
return ui::EF_NONE;
@@ -141,4 +113,4 @@ int GtkUiDelegateX11::GetGdkKeyState() {
return static_cast<int>(key_xevent->state);
}
-} // namespace ui
+} // namespace gtk
diff --git a/chromium/ui/gtk/x/gtk_ui_delegate_x11.h b/chromium/ui/gtk/x/gtk_ui_platform_x11.h
index 334f79930c9..e96d888f766 100644
--- a/chromium/ui/gtk/x/gtk_ui_delegate_x11.h
+++ b/chromium/ui/gtk/x/gtk_ui_platform_x11.h
@@ -2,33 +2,28 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_GTK_X_GTK_UI_DELEGATE_X11_H_
-#define UI_GTK_X_GTK_UI_DELEGATE_X11_H_
+#ifndef UI_GTK_X_GTK_UI_PLATFORM_X11_H_
+#define UI_GTK_X_GTK_UI_PLATFORM_X11_H_
-#include "base/component_export.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/x/connection.h"
-#include "ui/gtk/gtk_ui_delegate.h"
+#include "ui/gtk/gtk_ui_platform.h"
using GdkDisplay = struct _GdkDisplay;
-namespace ui {
+namespace gtk {
class GtkEventLoopX11;
-// GtkUiDelegate implementation for desktop Linux X11 backends.
-//
-// TODO(crbug.com/1002674): For now, this is used by both Aura (legacy) and
-// Ozone X11. Move this into X11 Ozone backend once Linux Chrome migration to
-// Ozone is completed.
-class COMPONENT_EXPORT(UI_GTK_X) GtkUiDelegateX11 : public GtkUiDelegate {
+// GtkUiPlatform implementation for desktop Linux X11 backends.
+class GtkUiPlatformX11 : public GtkUiPlatform {
public:
- explicit GtkUiDelegateX11(x11::Connection* connection);
- GtkUiDelegateX11(const GtkUiDelegateX11&) = delete;
- GtkUiDelegateX11& operator=(const GtkUiDelegateX11&) = delete;
- ~GtkUiDelegateX11() override;
+ GtkUiPlatformX11();
+ GtkUiPlatformX11(const GtkUiPlatformX11&) = delete;
+ GtkUiPlatformX11& operator=(const GtkUiPlatformX11&) = delete;
+ ~GtkUiPlatformX11() override;
- // GtkUiDelegate:
+ // GtkUiPlatform:
void OnInitialized(GtkWidget* widget) override;
GdkKeymap* GetGdkKeymap() override;
GdkWindow* GetGdkWindow(gfx::AcceleratedWidget window_id) override;
@@ -46,6 +41,6 @@ class COMPONENT_EXPORT(UI_GTK_X) GtkUiDelegateX11 : public GtkUiDelegate {
std::unique_ptr<GtkEventLoopX11> event_loop_;
};
-} // namespace ui
+} // namespace gtk
-#endif // UI_GTK_X_GTK_UI_DELEGATE_X11_H_
+#endif // UI_GTK_X_GTK_UI_PLATFORM_X11_H_
diff --git a/chromium/ui/latency/latency_info.cc b/chromium/ui/latency/latency_info.cc
index 6053c6f5199..f12f1cd7a7d 100644
--- a/chromium/ui/latency/latency_info.cc
+++ b/chromium/ui/latency/latency_info.cc
@@ -14,7 +14,6 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "services/tracing/public/cpp/perfetto/flow_event_utils.h"
#include "services/tracing/public/cpp/perfetto/macros.h"
diff --git a/chromium/ui/latency/latency_tracker.cc b/chromium/ui/latency/latency_tracker.cc
index 7fe3a9290a5..05cf568ca3a 100644
--- a/chromium/ui/latency/latency_tracker.cc
+++ b/chromium/ui/latency/latency_tracker.cc
@@ -141,6 +141,29 @@ void LatencyTracker::ReportJankyFrame(base::TimeTicks original_timestamp,
CONFIRM_EVENT_TIMES_EXIST(original_timestamp, gpu_swap_end_timestamp);
base::TimeDelta dur = gpu_swap_end_timestamp - original_timestamp;
+ if (first_frame) {
+ if (total_update_events_ > 0) {
+ // If we have some data from previous scroll, report it to UMA.
+ UMA_HISTOGRAM_MEDIUM_TIMES("Event.Latency.ScrollUpdate.TotalDuration",
+ total_update_duration_);
+ UMA_HISTOGRAM_MEDIUM_TIMES("Event.Latency.ScrollUpdate.JankyDuration",
+ janky_update_duration_);
+
+ UMA_HISTOGRAM_COUNTS_10000("Event.Latency.ScrollUpdate.TotalEvents",
+ total_update_events_);
+ UMA_HISTOGRAM_COUNTS_10000("Event.Latency.ScrollUpdate.JankyEvents",
+ janky_update_events_);
+ }
+
+ total_update_events_ = 0;
+ janky_update_events_ = 0;
+ total_update_duration_ = base::TimeDelta{};
+ janky_update_duration_ = base::TimeDelta{};
+ }
+
+ total_update_events_++;
+ total_update_duration_ += dur;
+
// When processing first frame in a scroll, we do not have any other frames to
// compare it to, and thus no way to detect the jank.
if (!first_frame) {
@@ -161,13 +184,20 @@ void LatencyTracker::ReportJankyFrame(base::TimeTicks original_timestamp,
if (!prev_scroll_update_reported_) {
// The information about previous GestureScrollUpdate was not reported:
// check whether it's janky by comparing to the current frame and report.
- UMA_HISTOGRAM_BOOLEAN("Event.Latency.ScrollJank",
- prev_frames_taken > frames_taken + 0.5);
+ if (prev_frames_taken > frames_taken + 0.5) {
+ UMA_HISTOGRAM_BOOLEAN("Event.Latency.ScrollJank", true);
+ janky_update_events_++;
+ janky_update_duration_ += prev_duration_;
+ } else {
+ UMA_HISTOGRAM_BOOLEAN("Event.Latency.ScrollJank", false);
+ }
}
// The current GestureScrollUpdate is janky compared to the previous one.
if (frames_taken > prev_frames_taken + 0.5) {
UMA_HISTOGRAM_BOOLEAN("Event.Latency.ScrollJank", true);
+ janky_update_events_++;
+ janky_update_duration_ += dur;
// Since we have reported the current event as janky, there is no need to
// report anything about it on the next iteration, as we would like to
diff --git a/chromium/ui/latency/latency_tracker.h b/chromium/ui/latency/latency_tracker.h
index 55e8ac1e9cb..8eebfd0b187 100644
--- a/chromium/ui/latency/latency_tracker.h
+++ b/chromium/ui/latency/latency_tracker.h
@@ -5,7 +5,6 @@
#ifndef UI_LATENCY_LATENCY_TRACKER_H_
#define UI_LATENCY_LATENCY_TRACKER_H_
-#include "base/callback_forward.h"
#include "base/macros.h"
#include "ui/latency/latency_info.h"
@@ -37,6 +36,10 @@ class LatencyTracker {
base::TimeDelta prev_duration_;
bool prev_scroll_update_reported_ = false;
+ int total_update_events_ = 0;
+ int janky_update_events_ = 0;
+ base::TimeDelta total_update_duration_;
+ base::TimeDelta janky_update_duration_;
void ReportUkmScrollLatency(
const InputMetricEvent& metric_event,
diff --git a/chromium/ui/message_center/lock_screen/fake_lock_screen_controller.h b/chromium/ui/message_center/lock_screen/fake_lock_screen_controller.h
index 734b233b56a..c1f5d5f2b52 100644
--- a/chromium/ui/message_center/lock_screen/fake_lock_screen_controller.h
+++ b/chromium/ui/message_center/lock_screen/fake_lock_screen_controller.h
@@ -35,4 +35,4 @@ class FakeLockScreenController : public LockScreenController {
} // namespace message_center
-#endif // UI_MESSAGE_CENTER_LOCK_SCREEN_FAkE_LOCK_SCREEN_CONTROLLER_H_
+#endif // UI_MESSAGE_CENTER_LOCK_SCREEN_FAKE_LOCK_SCREEN_CONTROLLER_H_
diff --git a/chromium/ui/message_center/message_center_impl.cc b/chromium/ui/message_center/message_center_impl.cc
index 705acbc73fe..a4329473777 100644
--- a/chromium/ui/message_center/message_center_impl.cc
+++ b/chromium/ui/message_center/message_center_impl.cc
@@ -338,7 +338,7 @@ void MessageCenterImpl::ClickOnNotification(const std::string& id) {
lock_screen_controller_->DismissLockScreenThenExecute(
base::BindOnce(&MessageCenterImpl::ClickOnNotificationUnlocked,
- base::Unretained(this), id, base::nullopt, base::nullopt),
+ base::Unretained(this), id, absl::nullopt, absl::nullopt),
base::OnceClosure());
}
@@ -350,7 +350,7 @@ void MessageCenterImpl::ClickOnNotificationButton(const std::string& id,
lock_screen_controller_->DismissLockScreenThenExecute(
base::BindOnce(&MessageCenterImpl::ClickOnNotificationUnlocked,
- base::Unretained(this), id, button_index, base::nullopt),
+ base::Unretained(this), id, button_index, absl::nullopt),
base::OnceClosure());
}
@@ -370,8 +370,8 @@ void MessageCenterImpl::ClickOnNotificationButtonWithReply(
void MessageCenterImpl::ClickOnNotificationUnlocked(
const std::string& id,
- const base::Optional<int>& button_index,
- const base::Optional<std::u16string>& reply) {
+ const absl::optional<int>& button_index,
+ const absl::optional<std::u16string>& reply) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// This method must be called under unlocked screen.
@@ -460,7 +460,7 @@ void MessageCenterImpl::SetQuietMode(bool in_quiet_mode) {
for (MessageCenterObserver& observer : observer_list_)
observer.OnQuietModeChanged(in_quiet_mode);
}
- quiet_mode_timer_.reset();
+ quiet_mode_timer_.Stop();
}
void MessageCenterImpl::SetSpokenFeedbackEnabled(bool enabled) {
@@ -470,20 +470,17 @@ void MessageCenterImpl::SetSpokenFeedbackEnabled(bool enabled) {
void MessageCenterImpl::EnterQuietModeWithExpire(
const base::TimeDelta& expires_in) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (quiet_mode_timer_) {
- // Note that the capital Reset() is the method to restart the timer, not
- // scoped_ptr::reset().
- quiet_mode_timer_->Reset();
- } else {
+
+ if (!quiet_mode_timer_.IsRunning()) {
notification_list_->SetQuietMode(true);
for (MessageCenterObserver& observer : observer_list_)
observer.OnQuietModeChanged(true);
-
- quiet_mode_timer_ = std::make_unique<base::OneShotTimer>();
- quiet_mode_timer_->Start(FROM_HERE, expires_in,
- base::BindOnce(&MessageCenterImpl::SetQuietMode,
- base::Unretained(this), false));
}
+
+ // This will restart the timer if it is already running.
+ quiet_mode_timer_.Start(FROM_HERE, expires_in,
+ base::BindOnce(&MessageCenterImpl::SetQuietMode,
+ base::Unretained(this), false));
}
void MessageCenterImpl::RestartPopupTimers() {
diff --git a/chromium/ui/message_center/message_center_impl.h b/chromium/ui/message_center/message_center_impl.h
index 47e62d138c6..fdfc67a78f6 100644
--- a/chromium/ui/message_center/message_center_impl.h
+++ b/chromium/ui/message_center/message_center_impl.h
@@ -104,8 +104,8 @@ class MessageCenterImpl : public MessageCenter,
THREAD_CHECKER(thread_checker_);
void ClickOnNotificationUnlocked(const std::string& id,
- const base::Optional<int>& button_index,
- const base::Optional<std::u16string>& reply);
+ const absl::optional<int>& button_index,
+ const absl::optional<std::u16string>& reply);
const std::unique_ptr<LockScreenController> lock_screen_controller_;
@@ -113,7 +113,7 @@ class MessageCenterImpl : public MessageCenter,
NotificationList::Notifications visible_notifications_;
base::ObserverList<MessageCenterObserver> observer_list_;
std::unique_ptr<PopupTimersController> popup_timers_controller_;
- std::unique_ptr<base::OneShotTimer> quiet_mode_timer_;
+ base::OneShotTimer quiet_mode_timer_;
std::vector<NotificationBlocker*> blockers_;
bool visible_ = false;
@@ -129,4 +129,4 @@ class MessageCenterImpl : public MessageCenter,
} // namespace message_center
-#endif // UI_MESSAGE_CENTER_MESSAGE_CENTER_H_
+#endif // UI_MESSAGE_CENTER_MESSAGE_CENTER_IMPL_H_
diff --git a/chromium/ui/message_center/message_center_impl_unittest.cc b/chromium/ui/message_center/message_center_impl_unittest.cc
index 7fe22bc51ca..db609a081ab 100644
--- a/chromium/ui/message_center/message_center_impl_unittest.cc
+++ b/chromium/ui/message_center/message_center_impl_unittest.cc
@@ -114,8 +114,8 @@ class TestDelegate : public NotificationDelegate {
log_ += "Close_";
log_ += (by_user ? "by_user_" : "programmatically_");
}
- void Click(const base::Optional<int>& button_index,
- const base::Optional<std::u16string>& reply) override {
+ void Click(const absl::optional<int>& button_index,
+ const absl::optional<std::u16string>& reply) override {
if (button_index) {
if (!reply) {
log_ += "ButtonClick_";
@@ -150,8 +150,8 @@ class DeleteOnCloseDelegate : public NotificationDelegate {
// Removing the same notification inside Close should be a noop.
message_center_->RemoveNotification(notification_id_, false /* by_user */);
}
- void Click(const base::Optional<int>& button_index,
- const base::Optional<std::u16string>& reply) override {}
+ void Click(const absl::optional<int>& button_index,
+ const absl::optional<std::u16string>& reply) override {}
private:
~DeleteOnCloseDelegate() override = default;
diff --git a/chromium/ui/message_center/message_center_observer.h b/chromium/ui/message_center/message_center_observer.h
index 32d4e6c764c..aaff5de28e0 100644
--- a/chromium/ui/message_center/message_center_observer.h
+++ b/chromium/ui/message_center/message_center_observer.h
@@ -8,7 +8,7 @@
#include <string>
#include "base/observer_list_types.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/message_center/message_center_export.h"
#include "ui/message_center/message_center_types.h"
@@ -40,8 +40,8 @@ class MESSAGE_CENTER_EXPORT MessageCenterObserver
// an input field associated with the button.
virtual void OnNotificationClicked(
const std::string& notification_id,
- const base::Optional<int>& button_index,
- const base::Optional<std::u16string>& reply) {}
+ const absl::optional<int>& button_index,
+ const absl::optional<std::u16string>& reply) {}
// Called when notification settings button is clicked. The |handled| argument
// indicates whether the notification delegate already handled the operation.
diff --git a/chromium/ui/message_center/message_center_stats_collector.cc b/chromium/ui/message_center/message_center_stats_collector.cc
index 1c7221570d3..477bd558fb6 100644
--- a/chromium/ui/message_center/message_center_stats_collector.cc
+++ b/chromium/ui/message_center/message_center_stats_collector.cc
@@ -102,8 +102,8 @@ void MessageCenterStatsCollector::OnNotificationUpdated(
void MessageCenterStatsCollector::OnNotificationClicked(
const std::string& notification_id,
- const base::Optional<int>& button_index,
- const base::Optional<std::u16string>& reply) {
+ const absl::optional<int>& button_index,
+ const absl::optional<std::u16string>& reply) {
auto iter = stats_.find(notification_id);
if (iter == stats_.end())
return;
diff --git a/chromium/ui/message_center/message_center_stats_collector.h b/chromium/ui/message_center/message_center_stats_collector.h
index fa928a458de..71ca9c097e1 100644
--- a/chromium/ui/message_center/message_center_stats_collector.h
+++ b/chromium/ui/message_center/message_center_stats_collector.h
@@ -72,8 +72,8 @@ class MessageCenterStatsCollector : public MessageCenterObserver {
void OnNotificationUpdated(const std::string& notification_id) override;
void OnNotificationClicked(
const std::string& notification_id,
- const base::Optional<int>& button_index,
- const base::Optional<std::u16string>& reply) override;
+ const absl::optional<int>& button_index,
+ const absl::optional<std::u16string>& reply) override;
void OnNotificationSettingsClicked(bool handled) override;
void OnNotificationDisplayed(const std::string& notification_id,
const DisplaySource source) override;
diff --git a/chromium/ui/message_center/notification_list_unittest.cc b/chromium/ui/message_center/notification_list_unittest.cc
index 5c181f1daac..c2e019dc4d7 100644
--- a/chromium/ui/message_center/notification_list_unittest.cc
+++ b/chromium/ui/message_center/notification_list_unittest.cc
@@ -11,6 +11,7 @@
#include "base/i18n/time_formatting.h"
#include "base/macros.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
@@ -21,8 +22,6 @@
#include "ui/message_center/public/cpp/notification_types.h"
#include "ui/message_center/public/cpp/notifier_id.h"
-using base::UTF8ToUTF16;
-
namespace message_center {
using NotificationState = NotificationList::NotificationState;
@@ -61,13 +60,13 @@ class NotificationListTest : public testing::Test {
const RichNotificationData& optional_fields,
std::string* id_out) {
*id_out = base::StringPrintf(kIdFormat, counter_);
- std::unique_ptr<Notification> notification(new Notification(
- NOTIFICATION_TYPE_SIMPLE, *id_out,
- UTF8ToUTF16(base::StringPrintf(kTitleFormat, counter_)),
- UTF8ToUTF16(base::StringPrintf(kMessageFormat, counter_)), gfx::Image(),
- UTF8ToUTF16(kDisplaySource), GURL(),
- NotifierId(NotifierType::APPLICATION, kExtensionId), optional_fields,
- nullptr));
+ std::unique_ptr<Notification> notification(
+ new Notification(NOTIFICATION_TYPE_SIMPLE, *id_out,
+ u"id" + base::NumberToString16(counter_),
+ u"message" + base::NumberToString16(counter_),
+ gfx::Image(), kDisplaySource, GURL(),
+ NotifierId(NotifierType::APPLICATION, kExtensionId),
+ optional_fields, nullptr));
return notification;
}
@@ -104,9 +103,7 @@ class NotificationListTest : public testing::Test {
}
static const char kIdFormat[];
- static const char kTitleFormat[];
- static const char kMessageFormat[];
- static const char kDisplaySource[];
+ static const char16_t kDisplaySource[];
static const char kExtensionId[];
std::unique_ptr<FakeMessageCenter> message_center_;
@@ -128,9 +125,7 @@ bool IsInNotifications(const NotificationList::Notifications& notifications,
}
const char NotificationListTest::kIdFormat[] = "id%ld";
-const char NotificationListTest::kTitleFormat[] = "id%ld";
-const char NotificationListTest::kMessageFormat[] = "message%ld";
-const char NotificationListTest::kDisplaySource[] = "source";
+const char16_t NotificationListTest::kDisplaySource[] = u"source";
const char NotificationListTest::kExtensionId[] = "ext";
TEST_F(NotificationListTest, Basic) {
@@ -174,11 +169,11 @@ TEST_F(NotificationListTest, UpdateNotification) {
std::string id0 = AddNotification();
std::string replaced = id0 + "_replaced";
EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
- std::unique_ptr<Notification> notification(new Notification(
- NOTIFICATION_TYPE_SIMPLE, replaced, u"newtitle", u"newbody", gfx::Image(),
- UTF8ToUTF16(kDisplaySource), GURL(),
- NotifierId(NotifierType::APPLICATION, kExtensionId),
- RichNotificationData(), nullptr));
+ std::unique_ptr<Notification> notification(
+ new Notification(NOTIFICATION_TYPE_SIMPLE, replaced, u"newtitle",
+ u"newbody", gfx::Image(), kDisplaySource, GURL(),
+ NotifierId(NotifierType::APPLICATION, kExtensionId),
+ RichNotificationData(), nullptr));
notification_list_->UpdateNotificationMessage(id0, std::move(notification));
EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
const NotificationList::Notifications notifications =
@@ -465,11 +460,11 @@ TEST_F(NotificationListTest, UpdateWithoutMessageCenterView) {
EXPECT_EQ(0u, GetPopupCounts());
RichNotificationData optional;
- std::unique_ptr<Notification> notification(new Notification(
- NOTIFICATION_TYPE_SIMPLE, replaced, u"newtitle", u"newbody",
- gfx::Image(), UTF8ToUTF16(kDisplaySource), GURL(),
- NotifierId(NotifierType::APPLICATION, kExtensionId), optional,
- nullptr));
+ std::unique_ptr<Notification> notification(
+ new Notification(NOTIFICATION_TYPE_SIMPLE, replaced, u"newtitle",
+ u"newbody", gfx::Image(), kDisplaySource, GURL(),
+ NotifierId(NotifierType::APPLICATION, kExtensionId),
+ optional, nullptr));
notification_list_->UpdateNotificationMessage(id0, std::move(notification));
EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
EXPECT_EQ(has_message_center_view ? 0U : 1U, GetPopupCounts());
@@ -498,7 +493,7 @@ TEST_F(NotificationListTest, Renotify) {
optional.renotify = true;
std::unique_ptr<Notification> notification(new Notification(
NOTIFICATION_TYPE_SIMPLE, replaced, u"newtitle", u"newbody", gfx::Image(),
- UTF8ToUTF16(kDisplaySource), GURL(),
+ kDisplaySource, GURL(),
NotifierId(NotifierType::APPLICATION, kExtensionId), optional, nullptr));
notification_list_->UpdateNotificationMessage(id0, std::move(notification));
EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
@@ -522,7 +517,7 @@ TEST_F(NotificationListTest, PriorityAndRenotify) {
priority.priority = DEFAULT_PRIORITY;
std::unique_ptr<Notification> notification(new Notification(
NOTIFICATION_TYPE_SIMPLE, id0, u"newtitle", u"newbody", gfx::Image(),
- UTF8ToUTF16(kDisplaySource), GURL(),
+ kDisplaySource, GURL(),
NotifierId(NotifierType::APPLICATION, kExtensionId), priority, nullptr));
notification_list_->UpdateNotificationMessage(id0, std::move(notification));
EXPECT_EQ(1u, GetPopupCounts());
@@ -532,7 +527,7 @@ TEST_F(NotificationListTest, PriorityAndRenotify) {
// update with no promotion change for id0, it won't appear as a toast.
notification = std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, id0, u"newtitle2", u"newbody2", gfx::Image(),
- UTF8ToUTF16(kDisplaySource), GURL(),
+ kDisplaySource, GURL(),
NotifierId(NotifierType::APPLICATION, kExtensionId), priority, nullptr);
notification_list_->UpdateNotificationMessage(id0, std::move(notification));
EXPECT_EQ(0u, GetPopupCounts());
@@ -541,7 +536,7 @@ TEST_F(NotificationListTest, PriorityAndRenotify) {
priority.priority = HIGH_PRIORITY;
notification = std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, id1, u"newtitle", u"newbody", gfx::Image(),
- UTF8ToUTF16(kDisplaySource), GURL(),
+ kDisplaySource, GURL(),
NotifierId(NotifierType::APPLICATION, kExtensionId), priority, nullptr);
notification_list_->UpdateNotificationMessage(id1, std::move(notification));
EXPECT_EQ(0u, GetPopupCounts());
@@ -550,7 +545,7 @@ TEST_F(NotificationListTest, PriorityAndRenotify) {
priority.renotify = true;
notification = std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, id1, u"newtitle", u"newbody", gfx::Image(),
- UTF8ToUTF16(kDisplaySource), GURL(),
+ kDisplaySource, GURL(),
NotifierId(NotifierType::APPLICATION, kExtensionId), priority, nullptr);
notification_list_->UpdateNotificationMessage(id1, std::move(notification));
EXPECT_EQ(1u, GetPopupCounts());
@@ -648,11 +643,11 @@ TEST_F(NotificationListTest, UpdateAfterMarkedAsShown) {
EXPECT_TRUE(n1_state.is_read);
const std::string replaced("test-replaced-id");
- std::unique_ptr<Notification> notification(new Notification(
- NOTIFICATION_TYPE_SIMPLE, replaced, u"newtitle", u"newbody", gfx::Image(),
- UTF8ToUTF16(kDisplaySource), GURL(),
- NotifierId(NotifierType::APPLICATION, kExtensionId),
- RichNotificationData(), nullptr));
+ std::unique_ptr<Notification> notification(
+ new Notification(NOTIFICATION_TYPE_SIMPLE, replaced, u"newtitle",
+ u"newbody", gfx::Image(), kDisplaySource, GURL(),
+ NotifierId(NotifierType::APPLICATION, kExtensionId),
+ RichNotificationData(), nullptr));
notification_list_->UpdateNotificationMessage(id1, std::move(notification));
Notification* n1 = GetNotification(id1);
EXPECT_TRUE(n1 == nullptr);
diff --git a/chromium/ui/message_center/public/cpp/notification.h b/chromium/ui/message_center/public/cpp/notification.h
index 9aa2970150d..953ce646520 100644
--- a/chromium/ui/message_center/public/cpp/notification.h
+++ b/chromium/ui/message_center/public/cpp/notification.h
@@ -11,10 +11,9 @@
#include <vector>
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/time/time.h"
-#include "base/values.h"
#include "build/chromeos_buildflags.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/image/image.h"
@@ -68,7 +67,7 @@ struct MESSAGE_CENTER_PUBLIC_EXPORT ButtonInfo {
// The placeholder string that should be displayed in the input field for
// text input type buttons until the user has entered a response themselves.
// If the value is null, there is no input field associated with the button.
- base::Optional<std::u16string> placeholder;
+ absl::optional<std::u16string> placeholder;
};
enum class FullscreenVisibility {
@@ -179,7 +178,7 @@ class MESSAGE_CENTER_PUBLIC_EXPORT RichNotificationData {
// Usually, it should not be set directly.
// For system notification, ash::CreateSystemNotification with
// SystemNotificationWarningLevel should be used.
- base::Optional<SkColor> accent_color;
+ absl::optional<SkColor> accent_color;
// Controls whether a settings button should appear on the notification. See
// enum definition. TODO(estade): turn this into a boolean. See
@@ -419,7 +418,7 @@ class MESSAGE_CENTER_PUBLIC_EXPORT Notification {
return optional_fields_.accessible_name;
}
- base::Optional<SkColor> accent_color() const {
+ absl::optional<SkColor> accent_color() const {
return optional_fields_.accent_color;
}
void set_accent_color(SkColor accent_color) {
diff --git a/chromium/ui/message_center/public/cpp/notification_delegate.cc b/chromium/ui/message_center/public/cpp/notification_delegate.cc
index 4710f6f3a39..7223351d02f 100644
--- a/chromium/ui/message_center/public/cpp/notification_delegate.cc
+++ b/chromium/ui/message_center/public/cpp/notification_delegate.cc
@@ -21,8 +21,8 @@ void ThunkNotificationDelegate::Close(bool by_user) {
}
void ThunkNotificationDelegate::Click(
- const base::Optional<int>& button_index,
- const base::Optional<std::u16string>& reply) {
+ const absl::optional<int>& button_index,
+ const absl::optional<std::u16string>& reply) {
if (impl_)
impl_->Click(button_index, reply);
}
@@ -62,7 +62,7 @@ void HandleNotificationClickDelegate::SetCallback(
// and just runs the provided closure.
callback_ = base::BindRepeating(
[](const base::RepeatingClosure& closure,
- base::Optional<int> button_index) {
+ absl::optional<int> button_index) {
DCHECK(!button_index);
closure.Run();
},
@@ -73,8 +73,8 @@ void HandleNotificationClickDelegate::SetCallback(
HandleNotificationClickDelegate::~HandleNotificationClickDelegate() {}
void HandleNotificationClickDelegate::Click(
- const base::Optional<int>& button_index,
- const base::Optional<std::u16string>& reply) {
+ const absl::optional<int>& button_index,
+ const absl::optional<std::u16string>& reply) {
if (!callback_.is_null())
callback_.Run(button_index);
}
diff --git a/chromium/ui/message_center/public/cpp/notification_delegate.h b/chromium/ui/message_center/public/cpp/notification_delegate.h
index 028864bb16a..7f476136c70 100644
--- a/chromium/ui/message_center/public/cpp/notification_delegate.h
+++ b/chromium/ui/message_center/public/cpp/notification_delegate.h
@@ -12,7 +12,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/message_center/public/cpp/message_center_public_export.h"
namespace message_center {
@@ -28,8 +28,8 @@ class MESSAGE_CENTER_PUBLIC_EXPORT NotificationObserver {
// if a button was clicked (as opposed to the body of the notification) while
// |reply| is filled in if there was an input field associated with the
// button.
- virtual void Click(const base::Optional<int>& button_index,
- const base::Optional<std::u16string>& reply) {}
+ virtual void Click(const absl::optional<int>& button_index,
+ const absl::optional<std::u16string>& reply) {}
// Called when the user clicks the settings button in a notification which has
// a DELEGATE settings button action.
@@ -62,8 +62,8 @@ class MESSAGE_CENTER_PUBLIC_EXPORT ThunkNotificationDelegate
// NotificationDelegate:
void Close(bool by_user) override;
- void Click(const base::Optional<int>& button_index,
- const base::Optional<std::u16string>& reply) override;
+ void Click(const absl::optional<int>& button_index,
+ const absl::optional<std::u16string>& reply) override;
void SettingsClick() override;
void DisableNotification() override;
@@ -84,7 +84,7 @@ class MESSAGE_CENTER_PUBLIC_EXPORT HandleNotificationClickDelegate
// The parameter is the index of the button that was clicked, or nullopt if
// the body was clicked.
using ButtonClickCallback =
- base::RepeatingCallback<void(base::Optional<int>)>;
+ base::RepeatingCallback<void(absl::optional<int>)>;
// Creates a delegate that handles clicks on a button or on the body.
explicit HandleNotificationClickDelegate(const ButtonClickCallback& callback);
@@ -103,8 +103,8 @@ class MESSAGE_CENTER_PUBLIC_EXPORT HandleNotificationClickDelegate
void SetCallback(const base::RepeatingClosure& closure);
// NotificationDelegate overrides:
- void Click(const base::Optional<int>& button_index,
- const base::Optional<std::u16string>& reply) override;
+ void Click(const absl::optional<int>& button_index,
+ const absl::optional<std::u16string>& reply) override;
protected:
~HandleNotificationClickDelegate() override;
diff --git a/chromium/ui/message_center/public/cpp/notification_delegate_unittest.cc b/chromium/ui/message_center/public/cpp/notification_delegate_unittest.cc
index 376b89ab714..9baeb3a3151 100644
--- a/chromium/ui/message_center/public/cpp/notification_delegate_unittest.cc
+++ b/chromium/ui/message_center/public/cpp/notification_delegate_unittest.cc
@@ -19,14 +19,14 @@ class NotificationDelegateTest : public testing::Test {
void BodyClickCallback() { ++callback_count_; }
- void ButtonClickCallback(base::Optional<int> button_index) {
+ void ButtonClickCallback(absl::optional<int> button_index) {
++callback_count_;
last_button_index_ = button_index;
}
protected:
int callback_count_ = 0;
- base::Optional<int> last_button_index_;
+ absl::optional<int> last_button_index_;
private:
DISALLOW_COPY_AND_ASSIGN(NotificationDelegateTest);
@@ -37,7 +37,7 @@ TEST_F(NotificationDelegateTest, ClickDelegate) {
base::BindRepeating(&NotificationDelegateTest::BodyClickCallback,
base::Unretained(this)));
- delegate->Click(base::nullopt, base::nullopt);
+ delegate->Click(absl::nullopt, absl::nullopt);
EXPECT_EQ(1, callback_count_);
}
@@ -45,7 +45,7 @@ TEST_F(NotificationDelegateTest, NullClickDelegate) {
auto delegate = base::MakeRefCounted<HandleNotificationClickDelegate>(
base::RepeatingClosure());
- delegate->Click(base::nullopt, base::nullopt);
+ delegate->Click(absl::nullopt, absl::nullopt);
EXPECT_EQ(0, callback_count_);
}
@@ -54,11 +54,11 @@ TEST_F(NotificationDelegateTest, ButtonClickDelegate) {
base::BindRepeating(&NotificationDelegateTest::ButtonClickCallback,
base::Unretained(this)));
- delegate->Click(base::nullopt, base::nullopt);
+ delegate->Click(absl::nullopt, absl::nullopt);
EXPECT_EQ(1, callback_count_);
- EXPECT_EQ(base::nullopt, last_button_index_);
+ EXPECT_EQ(absl::nullopt, last_button_index_);
- delegate->Click(3, base::nullopt);
+ delegate->Click(3, absl::nullopt);
EXPECT_EQ(2, callback_count_);
EXPECT_EQ(3, *last_button_index_);
}
diff --git a/chromium/ui/message_center/views/message_popup_collection_unittest.cc b/chromium/ui/message_center/views/message_popup_collection_unittest.cc
index 585902e4895..4329ece4956 100644
--- a/chromium/ui/message_center/views/message_popup_collection_unittest.cc
+++ b/chromium/ui/message_center/views/message_popup_collection_unittest.cc
@@ -166,7 +166,7 @@ class MockMessagePopupView : public MessagePopupView {
void set_expandable(bool expandable) { expandable_ = expandable; }
- void set_height_after_update(base::Optional<int> height_after_update) {
+ void set_height_after_update(absl::optional<int> height_after_update) {
height_after_update_ = height_after_update;
}
@@ -178,7 +178,7 @@ class MockMessagePopupView : public MessagePopupView {
bool expandable_ = false;
std::string title_;
- base::Optional<int> height_after_update_;
+ absl::optional<int> height_after_update_;
};
MessagePopupView* MockMessagePopupCollection::CreatePopup(
diff --git a/chromium/ui/message_center/views/message_popup_view.cc b/chromium/ui/message_center/views/message_popup_view.cc
index 1eb67eadb6c..d963c0fcdc7 100644
--- a/chromium/ui/message_center/views/message_popup_view.cc
+++ b/chromium/ui/message_center/views/message_popup_view.cc
@@ -8,6 +8,8 @@
#include "build/chromeos_buildflags.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/compositor/layer.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/message_center/public/cpp/message_center_constants.h"
@@ -15,7 +17,6 @@
#include "ui/message_center/views/message_view.h"
#include "ui/message_center/views/message_view_factory.h"
#include "ui/views/layout/fill_layout.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/widget/widget.h"
#if defined(OS_WIN)
@@ -117,7 +118,7 @@ void MessagePopupView::Show() {
#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
// Make the widget explicitly activatable as TYPE_POPUP is not activatable by
// default but we need focus for the inline reply textarea.
- params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
+ params.activatable = views::Widget::InitParams::Activatable::kYes;
params.opacity = views::Widget::InitParams::WindowOpacity::kOpaque;
#else
params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
diff --git a/chromium/ui/message_center/views/message_view.cc b/chromium/ui/message_center/views/message_view.cc
index fc0c0d72c9d..6c09e4ebb52 100644
--- a/chromium/ui/message_center/views/message_view.cc
+++ b/chromium/ui/message_center/views/message_view.cc
@@ -10,6 +10,7 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
@@ -177,6 +178,8 @@ void MessageView::SetManuallyExpandedOrCollapsed(bool value) {
void MessageView::UpdateCornerRadius(int top_radius, int bottom_radius) {
SetCornerRadius(top_radius, bottom_radius);
+ if (!GetWidget())
+ return;
UpdateBackgroundPainter();
SchedulePaint();
}
@@ -328,7 +331,7 @@ void MessageView::AddedToWidget() {
}
void MessageView::OnThemeChanged() {
- InkDropHostView::OnThemeChanged();
+ View::OnThemeChanged();
UpdateBackgroundPainter();
}
diff --git a/chromium/ui/message_center/views/message_view.h b/chromium/ui/message_center/views/message_view.h
index c8df0cfa62c..ad7d95c2cc6 100644
--- a/chromium/ui/message_center/views/message_view.h
+++ b/chromium/ui/message_center/views/message_view.h
@@ -19,7 +19,6 @@
#include "ui/message_center/message_center_export.h"
#include "ui/message_center/public/cpp/notification.h"
#include "ui/message_center/public/cpp/notification_delegate.h"
-#include "ui/views/animation/ink_drop_host_view.h"
#include "ui/views/animation/slide_out_controller.h"
#include "ui/views/animation/slide_out_controller_delegate.h"
#include "ui/views/controls/focus_ring.h"
@@ -42,12 +41,8 @@ class NotificationControlButtonsView;
// An base class for a notification entry. Contains background and other
// elements shared by derived notification views.
-// TODO(pkasting): This class only subclasses InkDropHostView because the
-// NotificationViewMD subclass needs ink drop functionality. Rework ink drops
-// to not need to be the base class of views which use them, and move the
-// functionality to the subclass that uses these.
class MESSAGE_CENTER_EXPORT MessageView
- : public views::InkDropHostView,
+ : public views::View,
public views::SlideOutControllerDelegate,
public views::FocusChangeListener {
public:
@@ -117,7 +112,7 @@ class MESSAGE_CENTER_EXPORT MessageView
virtual void OnSettingsButtonPressed(const ui::Event& event);
virtual void OnSnoozeButtonPressed(const ui::Event& event);
- // views::InkDropHostView:
+ // views::View:
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
bool OnMousePressed(const ui::MouseEvent& event) override;
bool OnMouseDragged(const ui::MouseEvent& event) override;
diff --git a/chromium/ui/message_center/views/message_view_factory.h b/chromium/ui/message_center/views/message_view_factory.h
index 8081691ee98..02823f5627c 100644
--- a/chromium/ui/message_center/views/message_view_factory.h
+++ b/chromium/ui/message_center/views/message_view_factory.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_MESSAGE_CENTER_MESSAGE_VIEW_FACTORY_H_
-#define UI_MESSAGE_CENTER_MESSAGE_VIEW_FACTORY_H_
+#ifndef UI_MESSAGE_CENTER_VIEWS_MESSAGE_VIEW_FACTORY_H_
+#define UI_MESSAGE_CENTER_VIEWS_MESSAGE_VIEW_FACTORY_H_
#include "ui/message_center/message_center_export.h"
@@ -47,4 +47,4 @@ class MESSAGE_CENTER_EXPORT MessageViewFactory {
} // namespace message_center
-#endif // UI_MESSAGE_CENTER_MESSAGE_VIEW_FACTORY_H_
+#endif // UI_MESSAGE_CENTER_VIEWS_MESSAGE_VIEW_FACTORY_H_
diff --git a/chromium/ui/message_center/views/notification_control_buttons_view.cc b/chromium/ui/message_center/views/notification_control_buttons_view.cc
index 2844eada9b6..e7d57e4c2e6 100644
--- a/chromium/ui/message_center/views/notification_control_buttons_view.cc
+++ b/chromium/ui/message_center/views/notification_control_buttons_view.cc
@@ -8,6 +8,7 @@
#include "build/chromeos_buildflags.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/compositor/layer.h"
#include "ui/events/event.h"
#include "ui/gfx/color_palette.h"
@@ -20,7 +21,6 @@
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/background.h"
#include "ui/views/layout/box_layout.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace message_center {
diff --git a/chromium/ui/message_center/views/notification_header_view.cc b/chromium/ui/message_center/views/notification_header_view.cc
index 927e50f51bd..a91d2a8e900 100644
--- a/chromium/ui/message_center/views/notification_header_view.cc
+++ b/chromium/ui/message_center/views/notification_header_view.cc
@@ -13,6 +13,8 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/paint_vector_icon.h"
@@ -27,8 +29,6 @@
#include "ui/views/controls/label.h"
#include "ui/views/layout/flex_layout.h"
#include "ui/views/layout/flex_layout_types.h"
-#include "ui/views/metadata/metadata_header_macros.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/painter.h"
#include "ui/views/view_class_properties.h"
@@ -362,7 +362,7 @@ void NotificationHeaderView::SetExpanded(bool expanded) {
NotifyAccessibilityEvent(ax::mojom::Event::kStateChanged, true);
}
-void NotificationHeaderView::SetAccentColor(base::Optional<SkColor> color) {
+void NotificationHeaderView::SetAccentColor(absl::optional<SkColor> color) {
accent_color_ = std::move(color);
UpdateColors();
}
@@ -392,7 +392,7 @@ const std::u16string& NotificationHeaderView::app_name_for_testing() const {
return app_name_view_->GetText();
}
-const gfx::ImageSkia& NotificationHeaderView::app_icon_for_testing() const {
+gfx::ImageSkia NotificationHeaderView::app_icon_for_testing() const {
return app_icon_view_->GetImage();
}
@@ -410,6 +410,8 @@ void NotificationHeaderView::UpdateSummaryTextVisibility() {
}
void NotificationHeaderView::UpdateColors() {
+ if (!GetWidget())
+ return;
SkColor color = accent_color_.value_or(GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_NotificationDefaultAccentColor));
app_name_view_->SetEnabledColor(color);
diff --git a/chromium/ui/message_center/views/notification_header_view.h b/chromium/ui/message_center/views/notification_header_view.h
index 0c5d59dd510..1cde0e78322 100644
--- a/chromium/ui/message_center/views/notification_header_view.h
+++ b/chromium/ui/message_center/views/notification_header_view.h
@@ -5,13 +5,13 @@
#ifndef UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_HEADER_VIEW_H_
#define UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_HEADER_VIEW_H_
-#include "base/optional.h"
#include "base/timer/timer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/gfx/text_constants.h"
#include "ui/message_center/message_center_export.h"
#include "ui/message_center/public/cpp/message_center_constants.h"
#include "ui/views/controls/button/button.h"
-#include "ui/views/metadata/metadata_header_macros.h"
namespace views {
class ImageView;
@@ -47,9 +47,9 @@ class MESSAGE_CENTER_EXPORT NotificationHeaderView : public views::Button {
void SetExpanded(bool expanded);
// Calls UpdateColors() to set the unified theme color used among the app
- // icon, app name, and expand button. If set to base::nullopt it will use the
+ // icon, app name, and expand button. If set to absl::nullopt it will use the
// NotificationDefaultAccentColor from the native theme.
- void SetAccentColor(base::Optional<SkColor> color);
+ void SetAccentColor(absl::optional<SkColor> color);
// Sets the background color of the notification. This is used to ensure that
// the accent color has enough contrast against the background.
@@ -67,7 +67,7 @@ class MESSAGE_CENTER_EXPORT NotificationHeaderView : public views::Button {
views::ImageView* expand_button() { return expand_button_; }
- base::Optional<SkColor> accent_color_for_testing() { return accent_color_; }
+ absl::optional<SkColor> accent_color_for_testing() { return accent_color_; }
const views::Label* summary_text_for_testing() const {
return summary_text_view_;
@@ -83,7 +83,7 @@ class MESSAGE_CENTER_EXPORT NotificationHeaderView : public views::Button {
const std::u16string& app_name_for_testing() const;
- const gfx::ImageSkia& app_icon_for_testing() const;
+ gfx::ImageSkia app_icon_for_testing() const;
private:
FRIEND_TEST_ALL_PREFIXES(NotificationHeaderViewTest, SettingsMode);
@@ -93,11 +93,11 @@ class MESSAGE_CENTER_EXPORT NotificationHeaderView : public views::Button {
void UpdateColors();
- base::Optional<SkColor> accent_color_;
+ absl::optional<SkColor> accent_color_;
// Timer that updates the timestamp over time.
base::OneShotTimer timestamp_update_timer_;
- base::Optional<base::Time> timestamp_;
+ absl::optional<base::Time> timestamp_;
views::ImageView* app_icon_view_ = nullptr;
views::Label* app_name_view_ = nullptr;
diff --git a/chromium/ui/message_center/views/notification_view_md.cc b/chromium/ui/message_center/views/notification_view_md.cc
index c0b9429df2b..5b9bab217cb 100644
--- a/chromium/ui/message_center/views/notification_view_md.cc
+++ b/chromium/ui/message_center/views/notification_view_md.cc
@@ -9,6 +9,7 @@
#include <memory>
#include <utility>
+#include "base/bind.h"
#include "base/i18n/case_conversion.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
@@ -16,6 +17,7 @@
#include "ui/base/class_property.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#include "ui/gfx/canvas.h"
@@ -41,6 +43,7 @@
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/animation/flood_fill_ink_drop_ripple.h"
#include "ui/views/animation/ink_drop_highlight.h"
+#include "ui/views/animation/ink_drop_host_view.h"
#include "ui/views/animation/ink_drop_impl.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
@@ -55,7 +58,6 @@
#include "ui/views/focus/focus_manager.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/fill_layout.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/native_cursor.h"
#include "ui/views/style/typography.h"
#include "ui/views/widget/widget.h"
@@ -307,7 +309,7 @@ gfx::Size LargeImageView::GetResizedImageSize() {
NotificationMdTextButton::NotificationMdTextButton(
PressedCallback callback,
const std::u16string& label,
- const base::Optional<std::u16string>& placeholder)
+ const absl::optional<std::u16string>& placeholder)
: views::MdTextButton(std::move(callback), label),
placeholder_(placeholder) {
SetMinSize(kActionButtonMinSize);
@@ -330,7 +332,7 @@ void NotificationMdTextButton::OnThemeChanged() {
}
void NotificationMdTextButton::OverrideTextColor(
- base::Optional<SkColor> text_color) {
+ absl::optional<SkColor> text_color) {
text_color_ = std::move(text_color);
SetEnabledTextColors(text_color_);
label()->SetAutoColorReadabilityEnabled(true);
@@ -356,8 +358,14 @@ NotificationInputContainerMD::NotificationInputContainerMD(
auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), 0));
- SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER);
- SetInkDropVisibleOpacity(1);
+ ink_drop_.SetMode(views::InkDropHost::InkDropMode::ON_NO_GESTURE_HANDLER);
+ ink_drop_.SetVisibleOpacity(1);
+ ink_drop_.SetBaseColorCallback(base::BindRepeating(
+ [](views::View* host) {
+ return host->GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_NotificationInkDropBase);
+ },
+ this));
AddChildView(ink_drop_container_);
@@ -380,8 +388,8 @@ NotificationInputContainerMD::~NotificationInputContainerMD() = default;
void NotificationInputContainerMD::AnimateBackground(const ui::Event& event) {
std::unique_ptr<ui::Event> located_event =
ConvertToBoundedLocatedEvent(event, this);
- AnimateInkDrop(views::InkDropState::ACTION_PENDING,
- ui::LocatedEvent::FromIfValid(located_event.get()));
+ ink_drop_.AnimateToState(views::InkDropState::ACTION_PENDING,
+ ui::LocatedEvent::FromIfValid(located_event.get()));
}
void NotificationInputContainerMD::AddLayerBeneathView(ui::Layer* layer) {
@@ -402,20 +410,8 @@ void NotificationInputContainerMD::RemoveLayerBeneathView(ui::Layer* layer) {
button_->DestroyLayer();
}
-std::unique_ptr<views::InkDropRipple>
-NotificationInputContainerMD::CreateInkDropRipple() const {
- return std::make_unique<views::FloodFillInkDropRipple>(
- size(), GetInkDropCenterBasedOnLastEvent(), GetInkDropBaseColor(),
- GetInkDropVisibleOpacity());
-}
-
-SkColor NotificationInputContainerMD::GetInkDropBaseColor() const {
- return GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_NotificationInkDropBase);
-}
-
void NotificationInputContainerMD::OnThemeChanged() {
- InkDropHostView::OnThemeChanged();
+ View::OnThemeChanged();
auto* theme = GetNativeTheme();
SetBackground(views::CreateSolidBackground(theme->GetSystemColor(
ui::NativeTheme::kColorId_NotificationActionsRowBackground)));
@@ -424,11 +420,11 @@ void NotificationInputContainerMD::OnThemeChanged() {
textfield_->SetBackgroundColor(SK_ColorTRANSPARENT);
textfield_->set_placeholder_text_color(theme->GetSystemColor(
ui::NativeTheme::kColorId_NotificationPlaceholderColor));
- SetButtonImage();
+ UpdateButtonImage();
}
void NotificationInputContainerMD::Layout() {
- views::InkDropHostView::Layout();
+ View::Layout();
// The animation is needed to run inside of the border.
ink_drop_container_->SetBoundsRect(GetLocalBounds());
}
@@ -447,10 +443,12 @@ bool NotificationInputContainerMD::HandleKeyEvent(views::Textfield* sender,
void NotificationInputContainerMD::OnAfterUserAction(views::Textfield* sender) {
DCHECK_EQ(sender, textfield_);
- SetButtonImage();
+ UpdateButtonImage();
}
-void NotificationInputContainerMD::SetButtonImage() {
+void NotificationInputContainerMD::UpdateButtonImage() {
+ if (!GetWidget())
+ return;
auto icon_color_id =
textfield_->GetText().empty()
? ui::NativeTheme::kColorId_NotificationPlaceholderColor
@@ -490,11 +488,12 @@ class InlineSettingsRadioButton : public views::RadioButton {
class NotificationInkDropImpl : public views::InkDropImpl {
public:
- NotificationInkDropImpl(views::InkDropHostView* ink_drop_host,
+ NotificationInkDropImpl(views::InkDropHost* ink_drop_host,
const gfx::Size& host_size)
- : views::InkDropImpl(ink_drop_host, host_size) {
- SetAutoHighlightMode(views::InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE);
- }
+ : views::InkDropImpl(
+ ink_drop_host,
+ host_size,
+ views::InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE) {}
void HostSizeChanged(const gfx::Size& new_size) override {
// Prevent a call to InkDropImpl::HostSizeChanged which recreates the ripple
@@ -517,7 +516,7 @@ class NotificationViewMD::NotificationViewMDPathGenerator
const NotificationViewMDPathGenerator&) = delete;
// views::HighlightPathGenerator:
- base::Optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override {
+ absl::optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override {
gfx::RectF bounds = rect;
if (!preferred_size_.IsEmpty())
bounds.set_size(gfx::SizeF(preferred_size_));
@@ -570,7 +569,28 @@ NotificationViewMD::NotificationViewMD(const Notification& notification)
SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical, gfx::Insets(), 0));
- SetInkDropVisibleOpacity(1);
+ ink_drop_.SetVisibleOpacity(1.0f);
+ ink_drop_.SetCreateInkDropCallback(base::BindRepeating(
+ [](NotificationViewMD* host) -> std::unique_ptr<views::InkDrop> {
+ return std::make_unique<NotificationInkDropImpl>(host->ink_drop(),
+ host->size());
+ },
+ this));
+ ink_drop_.SetCreateRippleCallback(base::BindRepeating(
+ [](NotificationViewMD* host) -> std::unique_ptr<views::InkDropRipple> {
+ return std::make_unique<views::FloodFillInkDropRipple>(
+ host->GetPreferredSize(),
+ host->ink_drop()->GetInkDropCenterBasedOnLastEvent(),
+ host->ink_drop()->GetBaseColor(),
+ host->ink_drop()->GetVisibleOpacity());
+ },
+ this));
+ ink_drop_.SetBaseColorCallback(base::BindRepeating(
+ [](NotificationViewMD* host) {
+ return host->GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_NotificationBackgroundActive);
+ },
+ this));
AddChildView(ink_drop_container_);
@@ -657,7 +677,7 @@ NotificationViewMD::~NotificationViewMD() {
}
void NotificationViewMD::AddLayerBeneathView(ui::Layer* layer) {
- GetInkDrop()->AddObserver(this);
+ ink_drop_.GetInkDrop()->AddObserver(this);
for (auto* child : GetChildrenForLayerAdjustment()) {
child->SetPaintToLayer();
child->layer()->SetFillsBoundsOpaquely(false);
@@ -669,7 +689,7 @@ void NotificationViewMD::RemoveLayerBeneathView(ui::Layer* layer) {
ink_drop_container_->RemoveLayerBeneathView(layer);
for (auto* child : GetChildrenForLayerAdjustment())
child->DestroyLayer();
- GetInkDrop()->RemoveObserver(this);
+ ink_drop_.GetInkDrop()->RemoveObserver(this);
}
void NotificationViewMD::Layout() {
@@ -1014,6 +1034,11 @@ void NotificationViewMD::CreateOrUpdateIconView(
void NotificationViewMD::CreateOrUpdateSmallIconView(
const Notification& notification) {
+ // This is called when the notification view is inserted into a Widget
+ // hierarchy and when the Widget's theme has changed. If not currently in a
+ // Widget hierarchy defer updating the small icon view.
+ if (!GetWidget())
+ return;
SkColor accent_color =
notification.accent_color().value_or(GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_NotificationDefaultAccentColor));
@@ -1187,7 +1212,7 @@ void NotificationViewMD::CreateOrUpdateInlineSettingsViews(
base::BindRepeating(&NotificationViewMD::ToggleInlineSettings,
base::Unretained(this)),
l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_SETTINGS_DONE),
- base::nullopt);
+ absl::nullopt);
auto* settings_button_row = new views::View;
auto settings_button_layout = std::make_unique<views::BoxLayout>(
@@ -1220,7 +1245,7 @@ void NotificationViewMD::HeaderRowPressed() {
void NotificationViewMD::ActionButtonPressed(size_t index,
const ui::Event& event) {
- const base::Optional<std::u16string>& placeholder =
+ const absl::optional<std::u16string>& placeholder =
action_buttons_[index]->placeholder();
if (placeholder) {
inline_reply_->textfield()->SetProperty(kTextfieldIndexKey, int{index});
@@ -1389,6 +1414,9 @@ SkColor NotificationViewMD::GetNotificationHeaderViewBackgroundColor() const {
}
void NotificationViewMD::UpdateActionButtonsRowBackground() {
+ if (!GetWidget())
+ return;
+
action_buttons_row_->SetBackground(views::CreateBackgroundFromPainter(
std::make_unique<NotificationBackgroundPainter>(
/*top_radius=*/0, bottom_radius(),
@@ -1451,27 +1479,16 @@ void NotificationViewMD::Activate() {
}
void NotificationViewMD::AddBackgroundAnimation(const ui::Event& event) {
- SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER);
+ ink_drop_.SetMode(views::InkDropHost::InkDropMode::ON_NO_GESTURE_HANDLER);
std::unique_ptr<ui::Event> located_event =
ConvertToBoundedLocatedEvent(event, this);
- AnimateInkDrop(views::InkDropState::ACTION_PENDING,
- ui::LocatedEvent::FromIfValid(located_event.get()));
+ ink_drop_.AnimateToState(views::InkDropState::ACTION_PENDING,
+ ui::LocatedEvent::FromIfValid(located_event.get()));
}
void NotificationViewMD::RemoveBackgroundAnimation() {
- SetInkDropMode(InkDropMode::OFF);
- AnimateInkDrop(views::InkDropState::HIDDEN, nullptr);
-}
-
-std::unique_ptr<views::InkDrop> NotificationViewMD::CreateInkDrop() {
- return std::make_unique<NotificationInkDropImpl>(this, size());
-}
-
-std::unique_ptr<views::InkDropRipple> NotificationViewMD::CreateInkDropRipple()
- const {
- return std::make_unique<views::FloodFillInkDropRipple>(
- GetPreferredSize(), GetInkDropCenterBasedOnLastEvent(),
- GetInkDropBaseColor(), GetInkDropVisibleOpacity());
+ ink_drop_.SetMode(views::InkDropHost::InkDropMode::OFF);
+ ink_drop_.AnimateToState(views::InkDropState::HIDDEN, nullptr);
}
std::vector<views::View*> NotificationViewMD::GetChildrenForLayerAdjustment()
@@ -1480,11 +1497,6 @@ std::vector<views::View*> NotificationViewMD::GetChildrenForLayerAdjustment()
settings_done_button_};
}
-SkColor NotificationViewMD::GetInkDropBaseColor() const {
- return GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_NotificationBackgroundActive);
-}
-
void NotificationViewMD::InkDropAnimationStarted() {
header_row_->SetSubpixelRenderingEnabled(false);
}
diff --git a/chromium/ui/message_center/views/notification_view_md.h b/chromium/ui/message_center/views/notification_view_md.h
index 946f34a1cd2..a98d0a107c7 100644
--- a/chromium/ui/message_center/views/notification_view_md.h
+++ b/chromium/ui/message_center/views/notification_view_md.h
@@ -11,14 +11,14 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/message_center/message_center_export.h"
#include "ui/message_center/views/message_view.h"
#include "ui/views/animation/ink_drop_observer.h"
#include "ui/views/controls/button/md_text_button.h"
#include "ui/views/controls/textfield/textfield_controller.h"
-#include "ui/views/metadata/metadata_header_macros.h"
namespace views {
class ImageButton;
@@ -42,28 +42,28 @@ class MESSAGE_CENTER_EXPORT NotificationMdTextButton
NotificationMdTextButton(PressedCallback callback,
const std::u16string& label,
- const base::Optional<std::u16string>& placeholder);
+ const absl::optional<std::u16string>& placeholder);
~NotificationMdTextButton() override;
// views::MdTextButton:
void UpdateBackgroundColor() override;
void OnThemeChanged() override;
- const base::Optional<std::u16string>& placeholder() const {
+ const absl::optional<std::u16string>& placeholder() const {
return placeholder_;
}
- void set_placeholder(base::Optional<std::u16string> placeholder) {
+ void set_placeholder(absl::optional<std::u16string> placeholder) {
placeholder_ = std::move(placeholder);
}
SkColor enabled_color_for_testing() const {
return label()->GetEnabledColor();
}
- void OverrideTextColor(base::Optional<SkColor> text_color);
+ void OverrideTextColor(absl::optional<SkColor> text_color);
private:
- base::Optional<std::u16string> placeholder_;
- base::Optional<SkColor> text_color_;
+ absl::optional<std::u16string> placeholder_;
+ absl::optional<SkColor> text_color_;
};
// CompactTitleMessageView shows notification title and message in a single
@@ -116,7 +116,7 @@ class NotificationInputDelegate {
virtual ~NotificationInputDelegate() = default;
};
-class NotificationInputContainerMD : public views::InkDropHostView,
+class NotificationInputContainerMD : public views::View,
public views::TextfieldController {
public:
explicit NotificationInputContainerMD(NotificationInputDelegate* delegate);
@@ -124,11 +124,9 @@ class NotificationInputContainerMD : public views::InkDropHostView,
void AnimateBackground(const ui::Event& event);
- // views::InkDropHostView:
+ // views::View:
void AddLayerBeneathView(ui::Layer* layer) override;
void RemoveLayerBeneathView(ui::Layer* layer) override;
- std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override;
- SkColor GetInkDropBaseColor() const override;
void OnThemeChanged() override;
void Layout() override;
@@ -141,10 +139,11 @@ class NotificationInputContainerMD : public views::InkDropHostView,
views::ImageButton* button() const { return button_; }
private:
- void SetButtonImage();
+ void UpdateButtonImage();
NotificationInputDelegate* const delegate_;
+ views::InkDropHost ink_drop_{this};
views::InkDropContainerView* const ink_drop_container_;
views::Textfield* const textfield_;
@@ -181,6 +180,8 @@ class MESSAGE_CENTER_EXPORT NotificationViewMD
void AddBackgroundAnimation(const ui::Event& event);
void RemoveBackgroundAnimation();
+ views::InkDropHost* ink_drop() { return &ink_drop_; }
+
// MessageView:
void AddLayerBeneathView(ui::Layer* layer) override;
void RemoveLayerBeneathView(ui::Layer* layer) override;
@@ -192,9 +193,6 @@ class MESSAGE_CENTER_EXPORT NotificationViewMD
void OnMouseEvent(ui::MouseEvent* event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
void PreferredSizeChanged() override;
- std::unique_ptr<views::InkDrop> CreateInkDrop() override;
- std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override;
- SkColor GetInkDropBaseColor() const override;
void UpdateWithNotification(const Notification& notification) override;
void UpdateCornerRadius(int top_radius, int bottom_radius) override;
NotificationControlButtonsView* GetControlButtonsView() const override;
@@ -288,6 +286,7 @@ class MESSAGE_CENTER_EXPORT NotificationViewMD
// destroyed when the ink drop is visible.
std::vector<views::View*> GetChildrenForLayerAdjustment() const;
+ views::InkDropHost ink_drop_{this};
views::InkDropContainerView* const ink_drop_container_;
// View containing close and settings buttons
diff --git a/chromium/ui/message_center/views/notification_view_md_unittest.cc b/chromium/ui/message_center/views/notification_view_md_unittest.cc
index bef957c5f43..bba17a32067 100644
--- a/chromium/ui/message_center/views/notification_view_md_unittest.cc
+++ b/chromium/ui/message_center/views/notification_view_md_unittest.cc
@@ -11,6 +11,7 @@
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/events/event_processor.h"
#include "ui/events/event_utils.h"
@@ -52,8 +53,8 @@ class NotificationTestDelegate : public NotificationDelegate {
public:
NotificationTestDelegate() = default;
- void Click(const base::Optional<int>& button_index,
- const base::Optional<std::u16string>& reply) override {
+ void Click(const absl::optional<int>& button_index,
+ const absl::optional<std::u16string>& reply) override {
if (!button_index && !reply && !expecting_click_)
ADD_FAILURE() << "Click should not be invoked with a button index.";
if (button_index && !reply && !expecting_button_click_)
@@ -225,7 +226,8 @@ void NotificationViewMDTest::TearDown() {
DCHECK(notification_view_ || delete_on_preferred_size_changed_ ||
delete_on_notification_removed_);
if (notification_view_) {
- notification_view_->SetInkDropMode(MessageView::InkDropMode::OFF);
+ notification_view_->ink_drop()->SetMode(
+ views::InkDropHost::InkDropMode::OFF);
static_cast<views::View*>(notification_view_)->RemoveObserver(this);
notification_view_->GetWidget()->Close();
notification_view_ = nullptr;
@@ -506,11 +508,11 @@ TEST_F(NotificationViewMDTest, UpdateButtonsStateTest) {
EXPECT_EQ(views::Button::STATE_NORMAL,
notification_view()->action_buttons_[0]->GetState());
- // Now construct a mouse move event 1 pixel inside the boundary of the action
- // button.
- gfx::Point cursor_location(1, 1);
- views::View::ConvertPointToWidget(notification_view()->action_buttons_[0],
- &cursor_location);
+ // Now construct a mouse move event inside the boundary of the action button.
+ gfx::Point cursor_location = notification_view()
+ ->action_buttons_[0]
+ ->GetBoundsInScreen()
+ .CenterPoint();
ui::test::EventGenerator generator(
GetRootWindow(notification_view()->GetWidget()));
generator.MoveMouseTo(cursor_location);
@@ -523,11 +525,10 @@ TEST_F(NotificationViewMDTest, UpdateButtonsStateTest) {
EXPECT_EQ(views::Button::STATE_HOVERED,
notification_view()->action_buttons_[0]->GetState());
- // Now construct a mouse move event 1 pixel outside the boundary of the
- // widget.
- cursor_location = gfx::Point(-1, -1);
- views::View::ConvertPointToWidget(notification_view()->action_buttons_[0],
- &cursor_location);
+ // Now construct a mouse move event outside the boundary of the widget.
+ cursor_location =
+ notification_view()->action_buttons_[0]->GetBoundsInScreen().origin() +
+ gfx::Vector2d(-1, -1);
generator.MoveMouseTo(cursor_location);
EXPECT_EQ(views::Button::STATE_NORMAL,
@@ -550,11 +551,11 @@ TEST_F(NotificationViewMDTest, UpdateButtonCountTest) {
EXPECT_EQ(views::Button::STATE_NORMAL,
notification_view()->action_buttons_[1]->GetState());
- // Now construct a mouse move event 1 pixel inside the boundary of the action
- // button.
- gfx::Point cursor_location(1, 1);
- views::View::ConvertPointToScreen(notification_view()->action_buttons_[0],
- &cursor_location);
+ // Now construct a mouse move event inside the boundary of the action button.
+ gfx::Point cursor_location = notification_view()
+ ->action_buttons_[0]
+ ->GetBoundsInScreen()
+ .CenterPoint();
ui::test::EventGenerator generator(
GetRootWindow(notification_view()->GetWidget()));
generator.MoveMouseTo(cursor_location);
@@ -571,11 +572,10 @@ TEST_F(NotificationViewMDTest, UpdateButtonCountTest) {
notification_view()->action_buttons_[0]->GetState());
EXPECT_EQ(1u, notification_view()->action_buttons_.size());
- // Now construct a mouse move event 1 pixel outside the boundary of the
- // widget.
- cursor_location = gfx::Point(-1, -1);
- views::View::ConvertPointToScreen(notification_view()->action_buttons_[0],
- &cursor_location);
+ // Now construct a mouse move event outside the boundary of the widget.
+ cursor_location =
+ notification_view()->action_buttons_[0]->GetBoundsInScreen().origin() +
+ gfx::Vector2d(-1, -1);
generator.MoveMouseTo(cursor_location);
EXPECT_EQ(views::Button::STATE_NORMAL,
@@ -598,11 +598,11 @@ TEST_F(NotificationViewMDTest, TestActionButtonClick) {
notification_view()->ToggleExpanded();
EXPECT_TRUE(notification_view()->actions_row_->GetVisible());
- // Now construct a mouse click event 1 pixel inside the boundary of the action
- // button.
- gfx::Point cursor_location(1, 1);
- views::View::ConvertPointToScreen(notification_view()->action_buttons_[1],
- &cursor_location);
+ // Now construct a mouse click event inside the boundary of the action button.
+ gfx::Point cursor_location = notification_view()
+ ->action_buttons_[1]
+ ->GetBoundsInScreen()
+ .CenterPoint();
generator.MoveMouseTo(cursor_location);
generator.ClickLeftButton();
@@ -627,11 +627,11 @@ TEST_F(NotificationViewMDTest, TestInlineReply) {
notification_view()->ToggleExpanded();
EXPECT_TRUE(notification_view()->actions_row_->GetVisible());
- // Now construct a mouse click event 1 pixel inside the boundary of the action
- // button.
- gfx::Point cursor_location(1, 1);
- views::View::ConvertPointToScreen(notification_view()->action_buttons_[1],
- &cursor_location);
+ // Now construct a mouse click event inside the boundary of the action button.
+ gfx::Point cursor_location = notification_view()
+ ->action_buttons_[1]
+ ->GetBoundsInScreen()
+ .CenterPoint();
generator.MoveMouseTo(cursor_location);
generator.ClickLeftButton();
@@ -667,11 +667,11 @@ TEST_F(NotificationViewMDTest, TestInlineReply) {
// Reset values.
delegate_->Reset();
- // Now construct a mouse click event 1 pixel inside the boundary of the action
- // button.
- cursor_location = gfx::Point(1, 1);
- views::View::ConvertPointToScreen(notification_view()->action_buttons_[1],
- &cursor_location);
+ // Now construct a mouse click event inside the boundary of the action button.
+ cursor_location = notification_view()
+ ->action_buttons_[0]
+ ->GetBoundsInScreen()
+ .CenterPoint();
generator.MoveMouseTo(cursor_location);
generator.ClickLeftButton();
@@ -689,9 +689,10 @@ TEST_F(NotificationViewMDTest, TestInlineReply) {
}
// Submit by clicking the reply button.
- cursor_location = gfx::Point(1, 1);
- views::View::ConvertPointToScreen(
- notification_view()->inline_reply_->button(), &cursor_location);
+ cursor_location = notification_view()
+ ->inline_reply_->button()
+ ->GetBoundsInScreen()
+ .CenterPoint();
generator.MoveMouseTo(cursor_location);
generator.ClickLeftButton();
EXPECT_EQ(1, delegate_->clicked_button_index());
@@ -715,11 +716,11 @@ TEST_F(NotificationViewMDTest, TestInlineReplyRemovedByUpdate) {
notification_view()->ToggleExpanded();
EXPECT_TRUE(notification_view()->actions_row_->GetVisible());
- // Now construct a mouse click event 1 pixel inside the boundary of the action
- // button.
- gfx::Point cursor_location(1, 1);
- views::View::ConvertPointToScreen(notification_view()->action_buttons_[1],
- &cursor_location);
+ // Now construct a mouse click event inside the boundary of the action button.
+ gfx::Point cursor_location = notification_view()
+ ->action_buttons_[1]
+ ->GetBoundsInScreen()
+ .CenterPoint();
generator.MoveMouseTo(cursor_location);
generator.ClickLeftButton();
@@ -729,7 +730,7 @@ TEST_F(NotificationViewMDTest, TestInlineReplyRemovedByUpdate) {
EXPECT_TRUE(notification_view()->inline_reply_->GetVisible());
EXPECT_FALSE(notification_view()->action_buttons_row_->GetVisible());
- buttons[1].placeholder = base::nullopt;
+ buttons[1].placeholder = absl::nullopt;
notification->set_buttons(buttons);
UpdateNotificationViews(*notification);
@@ -950,10 +951,10 @@ TEST_F(NotificationViewMDTest, ExpandLongMessage) {
// Without doing this, inappropriate fix such as
// message_view_->GetPreferredSize() returning gfx::Size() can pass.
notification->set_title(std::u16string());
- notification->set_message(base::ASCIIToUTF16(
- "consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore "
- "et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud "
- "exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."));
+ notification->set_message(
+ u"consectetur adipiscing elit, sed do eiusmod tempor incididunt ut "
+ u"labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud "
+ u"exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.");
UpdateNotificationViews(*notification);
EXPECT_FALSE(notification_view()->expanded_);
@@ -979,10 +980,9 @@ TEST_F(NotificationViewMDTest, ExpandLongMessage) {
// user interaction.
EXPECT_FALSE(notification_view()->IsManuallyExpandedOrCollapsed());
- // Construct a mouse click event 1 pixel inside the header.
- gfx::Point done_cursor_location(1, 1);
- views::View::ConvertPointToScreen(notification_view()->header_row_,
- &done_cursor_location);
+ // Construct a mouse click event inside the header.
+ gfx::Point done_cursor_location =
+ notification_view()->header_row_->GetBoundsInScreen().CenterPoint();
ui::test::EventGenerator generator(
GetRootWindow(notification_view()->GetWidget()));
generator.MoveMouseTo(done_cursor_location);
@@ -1177,10 +1177,11 @@ TEST_F(NotificationViewMDTest, UpdateInSettings) {
// Inline settings will be shown by clicking settings button.
EXPECT_FALSE(notification_view()->settings_row_->GetVisible());
- gfx::Point settings_cursor_location(1, 1);
- views::View::ConvertPointToTarget(
- notification_view()->control_buttons_view_->settings_button(),
- notification_view(), &settings_cursor_location);
+ gfx::Point settings_cursor_location =
+ notification_view()
+ ->control_buttons_view_->settings_button()
+ ->GetBoundsInScreen()
+ .CenterPoint();
generator.MoveMouseTo(settings_cursor_location);
generator.ClickLeftButton();
EXPECT_TRUE(notification_view()->settings_row_->GetVisible());
@@ -1205,10 +1206,11 @@ TEST_F(NotificationViewMDTest, InlineSettings) {
// Inline settings will be shown by clicking settings button.
EXPECT_FALSE(notification_view()->settings_row_->GetVisible());
- gfx::Point settings_cursor_location(1, 1);
- views::View::ConvertPointToTarget(
- notification_view()->control_buttons_view_->settings_button(),
- notification_view(), &settings_cursor_location);
+ gfx::Point settings_cursor_location =
+ notification_view()
+ ->control_buttons_view_->settings_button()
+ ->GetBoundsInScreen()
+ .CenterPoint();
generator.MoveMouseTo(settings_cursor_location);
generator.ClickLeftButton();
EXPECT_TRUE(notification_view()->settings_row_->GetVisible());
@@ -1224,11 +1226,13 @@ TEST_F(NotificationViewMDTest, InlineSettings) {
EXPECT_TRUE(notification_view()->settings_row_->GetVisible());
#endif
- // Construct a mouse click event 1 pixel inside the done button.
- gfx::Point done_cursor_location(1, 1);
- views::View::ConvertPointToTarget(notification_view()->settings_done_button_,
- notification_view(), &done_cursor_location);
+ // Construct a mouse click event over the done button.
+ gfx::Point done_cursor_location =
+ notification_view()
+ ->settings_done_button_->GetBoundsInScreen()
+ .CenterPoint();
generator.MoveMouseTo(done_cursor_location);
+
generator.ClickLeftButton();
// Just clicking Done button should not change the setting.
@@ -1239,11 +1243,9 @@ TEST_F(NotificationViewMDTest, InlineSettings) {
generator.ClickLeftButton();
EXPECT_TRUE(notification_view()->settings_row_->GetVisible());
- // Construct a mouse click event 1 pixel inside the block all button.
- gfx::Point block_cursor_location(1, 1);
- views::View::ConvertPointToTarget(notification_view()->block_all_button_,
- notification_view(),
- &block_cursor_location);
+ // Construct a mouse click event inside the block all button.
+ gfx::Point block_cursor_location =
+ notification_view()->block_all_button_->GetBoundsInScreen().CenterPoint();
generator.MoveMouseTo(block_cursor_location);
generator.ClickLeftButton();
generator.MoveMouseTo(done_cursor_location);
@@ -1265,22 +1267,23 @@ TEST_F(NotificationViewMDTest, InlineSettingsInkDropAnimation) {
// Inline settings will be shown by clicking settings button.
EXPECT_FALSE(notification_view()->settings_row_->GetVisible());
- gfx::Point settings_cursor_location(1, 1);
- views::View::ConvertPointToTarget(
- notification_view()->control_buttons_view_->settings_button(),
- notification_view(), &settings_cursor_location);
+ gfx::Point settings_cursor_location =
+ notification_view()
+ ->control_buttons_view_->settings_button()
+ ->GetBoundsInScreen()
+ .CenterPoint();
generator.MoveMouseTo(settings_cursor_location);
generator.ClickLeftButton();
EXPECT_TRUE(notification_view()->settings_row_->GetVisible());
- notification_view()->GetInkDrop()->AddObserver(this);
+ notification_view()->ink_drop()->GetInkDrop()->AddObserver(this);
// Resize the widget by 1px to simulate the expand animation.
gfx::Rect size = notification_view()->GetWidget()->GetWindowBoundsInScreen();
size.Inset(0, 0, 0, 1);
notification_view()->GetWidget()->SetBounds(size);
- notification_view()->GetInkDrop()->RemoveObserver(this);
+ notification_view()->ink_drop()->GetInkDrop()->RemoveObserver(this);
// The ink drop animation should still be running.
EXPECT_FALSE(ink_drop_stopped());
@@ -1310,8 +1313,8 @@ TEST_F(NotificationViewMDTest, InkDropClipRect) {
// Toggle inline settings to show ink drop background.
notification_view()->ToggleInlineSettings(DummyEvent());
- auto* ink_drop =
- static_cast<views::InkDropImpl*>(notification_view()->GetInkDrop());
+ auto* ink_drop = static_cast<views::InkDropImpl*>(
+ notification_view()->ink_drop()->GetInkDrop());
views::test::InkDropImplTestApi ink_drop_test_api(ink_drop);
gfx::Rect clip_rect = ink_drop_test_api.GetRootLayer()->clip_rect();
@@ -1374,10 +1377,10 @@ TEST_F(NotificationViewMDTest, TestDeleteOnToggleExpanded) {
std::unique_ptr<Notification> notification = CreateSimpleNotification();
notification->set_type(NotificationType::NOTIFICATION_TYPE_SIMPLE);
notification->set_title(std::u16string());
- notification->set_message(base::ASCIIToUTF16(
- "consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore "
- "et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud "
- "exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."));
+ notification->set_message(
+ u"consectetur adipiscing elit, sed do eiusmod tempor incididunt ut "
+ u"labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud "
+ u"exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.");
UpdateNotificationViews(*notification);
EXPECT_FALSE(notification_view()->expanded_);
@@ -1406,20 +1409,20 @@ TEST_F(NotificationViewMDTest, TestLongTitleAndMessage) {
std::unique_ptr<Notification> notification = CreateSimpleNotification();
notification->set_type(NotificationType::NOTIFICATION_TYPE_SIMPLE);
notification->set_title(u"title");
- notification->set_message(base::ASCIIToUTF16(
- "consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore "
- "et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud "
- "exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."));
+ notification->set_message(
+ u"consectetur adipiscing elit, sed do eiusmod tempor incididunt ut "
+ u"labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud "
+ u"exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.");
UpdateNotificationViews(*notification);
notification_view()->ToggleExpanded();
// Get the height of the message view with a short title.
const int message_height = notification_view()->message_view_->height();
- notification->set_title(base::ASCIIToUTF16(
- "consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore "
- "et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud "
- "exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."));
+ notification->set_title(
+ u"consectetur adipiscing elit, sed do eiusmod tempor incididunt ut "
+ u"labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud "
+ u"exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.");
UpdateNotificationViews(*notification);
// The height of the message view should stay the same with a long title.
diff --git a/chromium/ui/message_center/views/padded_button.cc b/chromium/ui/message_center/views/padded_button.cc
index 531992e4301..515af01c802 100644
--- a/chromium/ui/message_center/views/padded_button.cc
+++ b/chromium/ui/message_center/views/padded_button.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "build/chromeos_buildflags.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_utils.h"
#include "ui/message_center/public/cpp/message_center_constants.h"
@@ -17,7 +18,6 @@
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/image_button.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace message_center {
@@ -26,16 +26,11 @@ PaddedButton::PaddedButton(PressedCallback callback)
SetBorder(views::CreateEmptyBorder(gfx::Insets(kControlButtonBorderSize)));
SetAnimateOnStateChange(false);
- SetInkDropMode(InkDropMode::ON);
- SetInkDropVisibleOpacity(0.12f);
+ ink_drop()->SetMode(views::InkDropHost::InkDropMode::ON);
+ ink_drop()->SetVisibleOpacity(0.12f);
SetHasInkDropActionOnClick(true);
-}
-
-std::unique_ptr<views::InkDrop> PaddedButton::CreateInkDrop() {
- auto ink_drop = CreateDefaultInkDropImpl();
- ink_drop->SetShowHighlightOnHover(false);
- ink_drop->SetShowHighlightOnFocus(false);
- return std::move(ink_drop);
+ views::InkDrop::UseInkDropForSquareRipple(ink_drop(),
+ /*highlight_on_hover=*/false);
}
void PaddedButton::OnThemeChanged() {
@@ -49,7 +44,8 @@ void PaddedButton::OnThemeChanged() {
SkColor background_color =
theme->GetSystemColor(ui::NativeTheme::kColorId_WindowBackground);
#endif
- SetInkDropBaseColor(color_utils::GetColorWithMaxContrast(background_color));
+ ink_drop()->SetBaseColor(
+ color_utils::GetColorWithMaxContrast(background_color));
}
BEGIN_METADATA(PaddedButton, views::ImageButton)
diff --git a/chromium/ui/message_center/views/padded_button.h b/chromium/ui/message_center/views/padded_button.h
index 1732d330aed..c7ac846c2f0 100644
--- a/chromium/ui/message_center/views/padded_button.h
+++ b/chromium/ui/message_center/views/padded_button.h
@@ -5,10 +5,10 @@
#ifndef UI_MESSAGE_CENTER_VIEWS_PADDED_BUTTON_H_
#define UI_MESSAGE_CENTER_VIEWS_PADDED_BUTTON_H_
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/message_center/message_center_export.h"
#include "ui/views/animation/ink_drop.h"
#include "ui/views/controls/button/image_button.h"
-#include "ui/views/metadata/metadata_header_macros.h"
namespace message_center {
@@ -29,7 +29,6 @@ class MESSAGE_CENTER_EXPORT PaddedButton : public views::ImageButton {
~PaddedButton() override = default;
// views::ImageButton:
- std::unique_ptr<views::InkDrop> CreateInkDrop() override;
void OnThemeChanged() override;
};
diff --git a/chromium/ui/message_center/views/proportional_image_view.cc b/chromium/ui/message_center/views/proportional_image_view.cc
index df2febe5da8..128a3d1b15d 100644
--- a/chromium/ui/message_center/views/proportional_image_view.cc
+++ b/chromium/ui/message_center/views/proportional_image_view.cc
@@ -4,10 +4,10 @@
#include "ui/message_center/views/proportional_image_view.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/message_center/message_center_style.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace message_center {
diff --git a/chromium/ui/native_theme/DIR_METADATA b/chromium/ui/native_theme/DIR_METADATA
deleted file mode 100644
index f31293e3139..00000000000
--- a/chromium/ui/native_theme/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail: {
- component: "UI"
-}
diff --git a/chromium/ui/native_theme/caption_style.cc b/chromium/ui/native_theme/caption_style.cc
index f0a223cbcc1..b3c64068573 100644
--- a/chromium/ui/native_theme/caption_style.cc
+++ b/chromium/ui/native_theme/caption_style.cc
@@ -14,12 +14,12 @@ CaptionStyle::CaptionStyle(const CaptionStyle& other) = default;
CaptionStyle::~CaptionStyle() = default;
// static
-base::Optional<CaptionStyle> CaptionStyle::FromSpec(const std::string& spec) {
+absl::optional<CaptionStyle> CaptionStyle::FromSpec(const std::string& spec) {
CaptionStyle style;
- base::Optional<base::Value> dict = base::JSONReader::Read(spec);
+ absl::optional<base::Value> dict = base::JSONReader::Read(spec);
if (!dict.has_value() || !dict->is_dict())
- return base::nullopt;
+ return absl::nullopt;
if (const std::string* value = dict->FindStringKey("text-color"))
style.text_color = *value;
@@ -30,8 +30,8 @@ base::Optional<CaptionStyle> CaptionStyle::FromSpec(const std::string& spec) {
}
#if !defined(OS_WIN) && !defined(OS_APPLE)
-base::Optional<CaptionStyle> CaptionStyle::FromSystemSettings() {
- return base::nullopt;
+absl::optional<CaptionStyle> CaptionStyle::FromSystemSettings() {
+ return absl::nullopt;
}
#endif
diff --git a/chromium/ui/native_theme/caption_style.h b/chromium/ui/native_theme/caption_style.h
index 557578fcc9c..d95f6f84734 100644
--- a/chromium/ui/native_theme/caption_style.h
+++ b/chromium/ui/native_theme/caption_style.h
@@ -5,7 +5,7 @@
#ifndef UI_NATIVE_THEME_CAPTION_STYLE_H_
#define UI_NATIVE_THEME_CAPTION_STYLE_H_
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkScalar.h"
#include "ui/native_theme/native_theme_export.h"
@@ -24,10 +24,10 @@ struct NATIVE_THEME_EXPORT CaptionStyle {
// variable types. See the body of this method for details. This is used to
// parse the value of the "--force-caption-style" command-line argument and
// for testing.
- static base::Optional<CaptionStyle> FromSpec(const std::string& spec);
+ static absl::optional<CaptionStyle> FromSpec(const std::string& spec);
// Returns a CaptionStyle populated from the System's Settings.
- static base::Optional<CaptionStyle> FromSystemSettings();
+ static absl::optional<CaptionStyle> FromSystemSettings();
// Some or all of these property strings can be empty.
// For example, on Win10 in Settings when a property is set to Default, the
diff --git a/chromium/ui/native_theme/caption_style_mac.mm b/chromium/ui/native_theme/caption_style_mac.mm
index 90029de59e1..390eac6e5c9 100644
--- a/chromium/ui/native_theme/caption_style_mac.mm
+++ b/chromium/ui/native_theme/caption_style_mac.mm
@@ -180,9 +180,9 @@ std::string GetMAWindowRadiusAsCSSNumberInPixels() {
} // namespace
// static
-base::Optional<CaptionStyle> CaptionStyle::FromSystemSettings() {
+absl::optional<CaptionStyle> CaptionStyle::FromSystemSettings() {
if (!base::FeatureList::IsEnabled(features::kSystemCaptionStyle))
- return base::nullopt;
+ return absl::nullopt;
CaptionStyle style;
diff --git a/chromium/ui/native_theme/caption_style_win.cc b/chromium/ui/native_theme/caption_style_win.cc
index b147e53f039..8aa03bc6fb7 100644
--- a/chromium/ui/native_theme/caption_style_win.cc
+++ b/chromium/ui/native_theme/caption_style_win.cc
@@ -12,6 +12,7 @@
#include "base/check_op.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
+#include "base/trace_event/trace_event.h"
#include "base/win/core_winrt_util.h"
#include "base/win/windows_version.h"
#include "skia/ext/skia_utils_win.h"
@@ -170,7 +171,8 @@ std::string GetCssColorWithAlpha(CC::ClosedCaptionColor caption_color,
return color_utils::SkColorToRgbaString(SkColorSetA(color, opacity));
}
-base::Optional<CaptionStyle> InitializeFromSystemSettings() {
+absl::optional<CaptionStyle> InitializeFromSystemSettings() {
+ TRACE_EVENT0("ui", "InitializeFromSystemSettings");
DCHECK_GE(base::win::GetVersion(), base::win::Version::WIN10);
DCHECK(base::FeatureList::IsEnabled(features::kSystemCaptionStyle));
@@ -180,7 +182,7 @@ base::Optional<CaptionStyle> InitializeFromSystemSettings() {
base::win::ScopedHString::ResolveCoreWinRTStringDelayload();
if (!can_use_scoped_hstring)
- return base::nullopt;
+ return absl::nullopt;
base::win::ScopedHString closed_caption_properties_string =
base::win::ScopedHString::Create(
@@ -191,55 +193,55 @@ base::Optional<CaptionStyle> InitializeFromSystemSettings() {
closed_caption_properties_string.get(),
IID_PPV_ARGS(&closed_caption_properties_statics));
if (FAILED(hr))
- return base::nullopt;
+ return absl::nullopt;
CC::ClosedCaptionSize font_size = CC::ClosedCaptionSize_Default;
hr = closed_caption_properties_statics->get_FontSize(&font_size);
if (FAILED(hr))
- return base::nullopt;
+ return absl::nullopt;
CC::ClosedCaptionEdgeEffect edge_effect = CC::ClosedCaptionEdgeEffect_Default;
hr = closed_caption_properties_statics->get_FontEffect(&edge_effect);
if (FAILED(hr))
- return base::nullopt;
+ return absl::nullopt;
CC::ClosedCaptionStyle font_family = CC::ClosedCaptionStyle_Default;
hr = closed_caption_properties_statics->get_FontStyle(&font_family);
if (FAILED(hr))
- return base::nullopt;
+ return absl::nullopt;
CC::ClosedCaptionColor font_color = CC::ClosedCaptionColor_Default;
hr = closed_caption_properties_statics->get_FontColor(&font_color);
if (FAILED(hr))
- return base::nullopt;
+ return absl::nullopt;
CC::ClosedCaptionOpacity font_opacity = CC::ClosedCaptionOpacity_Default;
hr = closed_caption_properties_statics->get_FontOpacity(&font_opacity);
if (FAILED(hr))
- return base::nullopt;
+ return absl::nullopt;
CC::ClosedCaptionColor background_color = CC::ClosedCaptionColor_Default;
hr =
closed_caption_properties_statics->get_BackgroundColor(&background_color);
if (FAILED(hr))
- return base::nullopt;
+ return absl::nullopt;
CC::ClosedCaptionOpacity background_opacity =
CC::ClosedCaptionOpacity_Default;
hr = closed_caption_properties_statics->get_BackgroundOpacity(
&background_opacity);
if (FAILED(hr))
- return base::nullopt;
+ return absl::nullopt;
CC::ClosedCaptionColor region_color = CC::ClosedCaptionColor_Default;
hr = closed_caption_properties_statics->get_RegionColor(&region_color);
if (FAILED(hr))
- return base::nullopt;
+ return absl::nullopt;
CC::ClosedCaptionOpacity region_opacity = CC::ClosedCaptionOpacity_Default;
hr = closed_caption_properties_statics->get_RegionOpacity(&region_opacity);
if (FAILED(hr))
- return base::nullopt;
+ return absl::nullopt;
CaptionStyle caption_style;
if (font_family != CC::ClosedCaptionStyle_Default) {
@@ -277,14 +279,14 @@ base::Optional<CaptionStyle> InitializeFromSystemSettings() {
} // namespace
-base::Optional<CaptionStyle> CaptionStyle::FromSystemSettings() {
+absl::optional<CaptionStyle> CaptionStyle::FromSystemSettings() {
if (base::win::GetVersion() >= base::win::Version::WIN10 &&
base::FeatureList::IsEnabled(features::kSystemCaptionStyle)) {
return InitializeFromSystemSettings();
}
// Return default CaptionStyle for pre Win10 versions since system settings
// don't allow caption styling.
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace ui
diff --git a/chromium/ui/native_theme/caption_style_win_unittest.cc b/chromium/ui/native_theme/caption_style_win_unittest.cc
index ae404e4934c..32595becbe3 100644
--- a/chromium/ui/native_theme/caption_style_win_unittest.cc
+++ b/chromium/ui/native_theme/caption_style_win_unittest.cc
@@ -22,7 +22,7 @@ TEST(CaptionStyleWinTest, TestWinCaptionStyle) {
base::win::ScopedCOMInitializer com_initializer;
ASSERT_TRUE(com_initializer.Succeeded());
- base::Optional<ui::CaptionStyle> caption_style =
+ absl::optional<ui::CaptionStyle> caption_style =
ui::CaptionStyle::FromSystemSettings();
// On Windows out of the box, all caption style properties are set to
// Default. In which case, each of these should be empty.
diff --git a/chromium/ui/native_theme/common_theme.cc b/chromium/ui/native_theme/common_theme.cc
index cdd49c092b6..4a526861f54 100644
--- a/chromium/ui/native_theme/common_theme.cc
+++ b/chromium/ui/native_theme/common_theme.cc
@@ -8,10 +8,10 @@
#include "base/logging.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/color/color_provider_utils.h"
@@ -28,7 +28,7 @@ namespace ui {
namespace {
-base::Optional<SkColor> GetHighContrastColor(
+absl::optional<SkColor> GetHighContrastColor(
NativeTheme::ColorId color_id,
NativeTheme::ColorScheme color_scheme) {
switch (color_id) {
@@ -48,11 +48,11 @@ base::Optional<SkColor> GetHighContrastColor(
? gfx::kGoogleBlue100
: gfx::kGoogleBlue900;
default:
- return base::nullopt;
+ return absl::nullopt;
}
}
-base::Optional<SkColor> GetDarkSchemeColor(NativeTheme::ColorId color_id,
+absl::optional<SkColor> GetDarkSchemeColor(NativeTheme::ColorId color_id,
const NativeTheme* base_theme) {
switch (color_id) {
// Alert
@@ -84,6 +84,10 @@ base::Optional<SkColor> GetDarkSchemeColor(NativeTheme::ColorId color_id,
case NativeTheme::kColorId_LabelEnabledColor:
return gfx::kGoogleGrey200;
+ // Shadow
+ case NativeTheme::kColorId_ShadowBase:
+ return SK_ColorBLACK;
+
// Separator
case NativeTheme::kColorId_SeparatorColor:
return gfx::kGoogleGrey800;
@@ -117,7 +121,7 @@ base::Optional<SkColor> GetDarkSchemeColor(NativeTheme::ColorId color_id,
return color_utils::BlendTowardMaxContrast(gfx::kGoogleGrey900, 0x0A);
default:
- return base::nullopt;
+ return absl::nullopt;
}
}
@@ -164,7 +168,16 @@ SkColor GetDefaultColor(NativeTheme::ColorId color_id,
case NativeTheme::kColorId_BubbleBorder:
return base_theme->GetUnprocessedSystemColor(
NativeTheme::kColorId_SeparatorColor, color_scheme);
-
+ case NativeTheme::kColorId_BubbleBorderShadowLarge:
+ return SkColorSetA(base_theme->GetUnprocessedSystemColor(
+ NativeTheme::kColorId_ShadowBase, color_scheme),
+ 0x1A);
+ case NativeTheme::kColorId_BubbleBorderShadowSmall:
+ return SkColorSetA(base_theme->GetUnprocessedSystemColor(
+ NativeTheme::kColorId_ShadowBase, color_scheme),
+ 0x33);
+ case NativeTheme::kColorId_BubbleBorderWhenShadowPresent:
+ return SkColorSetA(SK_ColorBLACK, 0x26);
// Button
case NativeTheme::kColorId_ButtonColor:
return base_theme->GetUnprocessedSystemColor(
@@ -252,6 +265,8 @@ SkColor GetDefaultColor(NativeTheme::ColorId color_id,
NativeTheme::kColorId_DefaultIconColor, color_scheme);
return SkColorSetA(icon, gfx::kDisabledControlAlpha);
}
+ case NativeTheme::kColorId_SecondaryIconColor:
+ return gfx::kGoogleGrey600;
// Label
case NativeTheme::kColorId_LabelDisabledColor: {
@@ -387,6 +402,27 @@ SkColor GetDefaultColor(NativeTheme::ColorId color_id,
case NativeTheme::kColorId_SeparatorColor:
return gfx::kGoogleGrey300;
+ // Shadow
+ case NativeTheme::kColorId_ShadowBase:
+ return gfx::kGoogleGrey800;
+
+ case NativeTheme::kColorId_ShadowValueAmbientShadowElevationThree:
+ return SkColorSetA(base_theme->GetUnprocessedSystemColor(
+ NativeTheme::kColorId_ShadowBase, color_scheme),
+ 0x40);
+ case NativeTheme::kColorId_ShadowValueKeyShadowElevationThree:
+ return SkColorSetA(base_theme->GetUnprocessedSystemColor(
+ NativeTheme::kColorId_ShadowBase, color_scheme),
+ 0x66);
+ case NativeTheme::kColorId_ShadowValueAmbientShadowElevationSixteen:
+ return SkColorSetA(base_theme->GetUnprocessedSystemColor(
+ NativeTheme::kColorId_ShadowBase, color_scheme),
+ 0x3d);
+ case NativeTheme::kColorId_ShadowValueKeyShadowElevationSixteen:
+ return SkColorSetA(base_theme->GetUnprocessedSystemColor(
+ NativeTheme::kColorId_ShadowBase, color_scheme),
+ 0x1a);
+
// Slider
case NativeTheme::kColorId_SliderThumbMinimal:
return base_theme->GetUnprocessedSystemColor(
@@ -557,6 +593,12 @@ SkColor GetDefaultColor(NativeTheme::ColorId color_id,
// switch enumeration.
NOTREACHED();
return gfx::kPlaceholderColor;
+
+ // Focus ring
+ case NativeTheme::kColorId_FocusAuraColor:
+ const SkColor focus_color = base_theme->GetUnprocessedSystemColor(
+ NativeTheme::kColorId_ProminentButtonColor, color_scheme);
+ return SkColorSetA(focus_color, 0x3D);
}
}
@@ -583,7 +625,7 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
// High contrast overrides the normal colors for certain ColorIds to be much
// darker or lighter.
if (base_theme->UserHasContrastPreference()) {
- base::Optional<SkColor> color =
+ absl::optional<SkColor> color =
GetHighContrastColor(color_id, color_scheme);
if (color.has_value()) {
DVLOG(2) << "GetHighContrastColor: "
@@ -594,7 +636,7 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
}
if (color_scheme == NativeTheme::ColorScheme::kDark) {
- base::Optional<SkColor> color = GetDarkSchemeColor(color_id, base_theme);
+ absl::optional<SkColor> color = GetDarkSchemeColor(color_id, base_theme);
if (color.has_value()) {
DVLOG(2) << "GetDarkSchemeColor: "
<< "NativeTheme::ColorId: " << NativeThemeColorIdName(color_id)
diff --git a/chromium/ui/native_theme/common_theme.h b/chromium/ui/native_theme/common_theme.h
index 73a84cf1ac6..3d035852eaa 100644
--- a/chromium/ui/native_theme/common_theme.h
+++ b/chromium/ui/native_theme/common_theme.h
@@ -5,7 +5,6 @@
#ifndef UI_NATIVE_THEME_COMMON_THEME_H_
#define UI_NATIVE_THEME_COMMON_THEME_H_
-#include <memory>
#include "ui/color/color_id.h"
#include "ui/native_theme/native_theme.h"
diff --git a/chromium/ui/native_theme/native_theme.cc b/chromium/ui/native_theme/native_theme.cc
index 998e819abb4..db0681f9278 100644
--- a/chromium/ui/native_theme/native_theme.cc
+++ b/chromium/ui/native_theme/native_theme.cc
@@ -10,10 +10,11 @@
#include "base/command_line.h"
#include "base/containers/fixed_flat_map.h"
#include "base/feature_list.h"
+#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
-#include "base/optional.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
#include "ui/color/color_id.h"
@@ -111,9 +112,10 @@ NativeTheme::NativeTheme(bool should_use_dark_colors)
NativeTheme::~NativeTheme() = default;
-base::Optional<SkColor> NativeTheme::GetColorProviderColor(
+absl::optional<SkColor> NativeTheme::GetColorProviderColor(
ColorId color_id,
- ColorScheme color_scheme) const {
+ ColorScheme color_scheme,
+ std::string theme_name) const {
if (base::FeatureList::IsEnabled(features::kColorProviderRedirection) &&
AllowColorPipelineRedirection(color_scheme)) {
if (auto provider_color_id = NativeThemeColorIdToColorId(color_id)) {
@@ -123,12 +125,13 @@ base::Optional<SkColor> NativeTheme::GetColorProviderColor(
: ColorProviderManager::ColorMode::kLight,
(color_scheme == NativeTheme::ColorScheme::kPlatformHighContrast)
? ColorProviderManager::ContrastMode::kHigh
- : ColorProviderManager::ContrastMode::kNormal});
+ : ColorProviderManager::ContrastMode::kNormal,
+ std::move(theme_name)});
ReportHistogramBooleanUsesColorProvider(true);
return color_provider->GetColor(provider_color_id.value());
}
}
- return base::nullopt;
+ return absl::nullopt;
}
bool NativeTheme::ShouldUseDarkColors() const {
@@ -154,6 +157,10 @@ NativeTheme::GetPlatformHighContrastColorScheme() const {
: PlatformHighContrastColorScheme::kLight;
}
+std::string NativeTheme::GetNativeThemeName() const {
+ return std::string();
+}
+
NativeTheme::PreferredColorScheme NativeTheme::GetPreferredColorScheme() const {
return preferred_color_scheme_;
}
@@ -203,7 +210,7 @@ SkColor NativeTheme::GetSystemColorDeprecated(ColorId color_id,
return GetAuraColor(color_id, this, color_scheme);
}
-base::Optional<CaptionStyle> NativeTheme::GetSystemCaptionStyle() const {
+absl::optional<CaptionStyle> NativeTheme::GetSystemCaptionStyle() const {
return CaptionStyle::FromSystemSettings();
}
@@ -212,13 +219,13 @@ NativeTheme::GetSystemColors() const {
return system_colors_;
}
-base::Optional<SkColor> NativeTheme::GetSystemThemeColor(
+absl::optional<SkColor> NativeTheme::GetSystemThemeColor(
SystemThemeColor theme_color) const {
auto color = system_colors_.find(theme_color);
if (color != system_colors_.end())
return color->second;
- return base::nullopt;
+ return absl::nullopt;
}
bool NativeTheme::HasDifferentSystemColors(
@@ -307,8 +314,10 @@ SkColor NativeTheme::GetSystemColorCommon(ColorId color_id,
if (color_scheme == NativeTheme::ColorScheme::kDefault)
color_scheme = GetDefaultSystemColorScheme();
- if (auto color = GetColorProviderColor(color_id, color_scheme))
+ if (auto color =
+ GetColorProviderColor(color_id, color_scheme, GetNativeThemeName())) {
return color.value();
+ }
ReportHistogramBooleanUsesColorProvider(false);
return GetSystemColorDeprecated(color_id, color_scheme, apply_processing);
diff --git a/chromium/ui/native_theme/native_theme.h b/chromium/ui/native_theme/native_theme.h
index b4f22b9e718..519e969c308 100644
--- a/chromium/ui/native_theme/native_theme.h
+++ b/chromium/ui/native_theme/native_theme.h
@@ -10,11 +10,11 @@
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "cc/paint/paint_canvas.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/models/menu_separator_types.h"
#include "ui/gfx/geometry/rect.h"
@@ -343,7 +343,7 @@ class NATIVE_THEME_EXPORT NativeTheme {
const gfx::Rect& rect,
const ExtraParams& extra,
ColorScheme color_scheme = ColorScheme::kDefault,
- const base::Optional<SkColor>& accent_color = 0) const = 0;
+ const absl::optional<SkColor>& accent_color = 0) const = 0;
// Paint part during state transition, used for overlay scrollbar state
// transition animation.
@@ -449,6 +449,10 @@ class NATIVE_THEME_EXPORT NativeTheme {
// colors, you probably shouldn't. Instead, use GetSystemColor().
virtual bool ShouldUseDarkColors() const;
+ // Returns the name that uniquely identifies the current NativeTheme. Default
+ // implementation returns an empty string.
+ virtual std::string GetNativeThemeName() const;
+
// Returns the OS-level user preferred color scheme. See the comment for
// CalculatePreferredColorScheme() for details on how preferred color scheme
// is calculated.
@@ -458,13 +462,13 @@ class NATIVE_THEME_EXPORT NativeTheme {
virtual PreferredContrast GetPreferredContrast() const;
// Returns the system's caption style.
- virtual base::Optional<CaptionStyle> GetSystemCaptionStyle() const;
+ virtual absl::optional<CaptionStyle> GetSystemCaptionStyle() const;
virtual ColorScheme GetDefaultSystemColorScheme() const;
virtual const std::map<SystemThemeColor, SkColor>& GetSystemColors() const;
- base::Optional<SkColor> GetSystemThemeColor(
+ absl::optional<SkColor> GetSystemThemeColor(
SystemThemeColor theme_color) const;
bool HasDifferentSystemColors(
@@ -502,8 +506,9 @@ class NATIVE_THEME_EXPORT NativeTheme {
virtual ~NativeTheme();
// Gets the color from the color provider if using a color provider is enable.
- base::Optional<SkColor> GetColorProviderColor(ColorId color_id,
- ColorScheme color_scheme) const;
+ absl::optional<SkColor> GetColorProviderColor(ColorId color_id,
+ ColorScheme color_scheme,
+ std::string theme_name) const;
// Whether high contrast is forced via command-line flag.
bool IsForcedHighContrast() const;
diff --git a/chromium/ui/native_theme/native_theme_base.cc b/chromium/ui/native_theme/native_theme_base.cc
index 313206e211c..bfd8c045bdf 100644
--- a/chromium/ui/native_theme/native_theme_base.cc
+++ b/chromium/ui/native_theme/native_theme_base.cc
@@ -148,7 +148,7 @@ SkColor BrightenColor(const color_utils::HSL& hsl, SkAlpha alpha,
// TODO(crbug.com/1092093): Use separate hard coded colors instead of deferring
// to the dark color scheme for contrast.
ui::NativeTheme::ColorScheme ColorSchemeForAccentColor(
- const base::Optional<SkColor>& accent_color,
+ const absl::optional<SkColor>& accent_color,
const ui::NativeTheme::ColorScheme& color_scheme) {
if (!accent_color)
return color_scheme;
@@ -259,18 +259,24 @@ void NativeThemeBase::Paint(cc::PaintCanvas* canvas,
const gfx::Rect& rect,
const ExtraParams& extra,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const {
+ const absl::optional<SkColor>& accent_color) const {
if (rect.IsEmpty())
return;
canvas->save();
canvas->clipRect(gfx::RectToSkRect(rect));
+ // Form control accents shouldn't be drawn with any transparency.
+ absl::optional<SkColor> accent_color_opaque;
+ if (accent_color) {
+ accent_color_opaque = SkColorSetA(accent_color.value(), SK_AlphaOPAQUE);
+ }
+
switch (part) {
// Please keep these in the order of NativeTheme::Part.
case kCheckbox:
PaintCheckbox(canvas, state, rect, extra.button, color_scheme,
- accent_color);
+ accent_color_opaque);
break;
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
@@ -300,13 +306,14 @@ void NativeThemeBase::Paint(cc::PaintCanvas* canvas,
break;
case kProgressBar:
PaintProgressBar(canvas, state, rect, extra.progress_bar, color_scheme,
- accent_color);
+ accent_color_opaque);
break;
case kPushButton:
PaintButton(canvas, state, rect, extra.button, color_scheme);
break;
case kRadio:
- PaintRadio(canvas, state, rect, extra.button, color_scheme, accent_color);
+ PaintRadio(canvas, state, rect, extra.button, color_scheme,
+ accent_color_opaque);
break;
case kScrollbarDownArrow:
case kScrollbarUpArrow:
@@ -336,11 +343,11 @@ void NativeThemeBase::Paint(cc::PaintCanvas* canvas,
break;
case kSliderTrack:
PaintSliderTrack(canvas, state, rect, extra.slider, color_scheme,
- accent_color);
+ accent_color_opaque);
break;
case kSliderThumb:
PaintSliderThumb(canvas, state, rect, extra.slider, color_scheme,
- accent_color);
+ accent_color_opaque);
break;
case kTabPanelBackground:
NOTIMPLEMENTED();
@@ -622,7 +629,7 @@ void NativeThemeBase::PaintCheckbox(
const gfx::Rect& rect,
const ButtonExtraParams& button,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const {
+ const absl::optional<SkColor>& accent_color) const {
if (features::IsFormControlsRefreshEnabled()) {
color_scheme = ColorSchemeForAccentColor(accent_color, color_scheme);
@@ -715,7 +722,7 @@ SkRect NativeThemeBase::PaintCheckboxRadioCommon(
bool is_checkbox,
const SkScalar border_radius,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const {
+ const absl::optional<SkColor>& accent_color) const {
if (features::IsFormControlsRefreshEnabled()) {
color_scheme = ColorSchemeForAccentColor(accent_color, color_scheme);
@@ -882,7 +889,7 @@ void NativeThemeBase::PaintRadio(
const gfx::Rect& rect,
const ButtonExtraParams& button,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const {
+ const absl::optional<SkColor>& accent_color) const {
if (features::IsFormControlsRefreshEnabled()) {
color_scheme = ColorSchemeForAccentColor(accent_color, color_scheme);
@@ -1199,7 +1206,7 @@ void NativeThemeBase::PaintSliderTrack(
const gfx::Rect& rect,
const SliderExtraParams& slider,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const {
+ const absl::optional<SkColor>& accent_color) const {
if (features::IsFormControlsRefreshEnabled()) {
color_scheme = ColorSchemeForAccentColor(accent_color, color_scheme);
@@ -1272,7 +1279,7 @@ void NativeThemeBase::PaintSliderThumb(
const gfx::Rect& rect,
const SliderExtraParams& slider,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const {
+ const absl::optional<SkColor>& accent_color) const {
if (features::IsFormControlsRefreshEnabled()) {
color_scheme = ColorSchemeForAccentColor(accent_color, color_scheme);
@@ -1373,7 +1380,7 @@ void NativeThemeBase::PaintProgressBar(
const gfx::Rect& rect,
const ProgressBarExtraParams& progress_bar,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const {
+ const absl::optional<SkColor>& accent_color) const {
if (features::IsFormControlsRefreshEnabled()) {
DCHECK(!rect.IsEmpty());
diff --git a/chromium/ui/native_theme/native_theme_base.h b/chromium/ui/native_theme/native_theme_base.h
index a29df63b8a4..28ad2c05257 100644
--- a/chromium/ui/native_theme/native_theme_base.h
+++ b/chromium/ui/native_theme/native_theme_base.h
@@ -5,7 +5,6 @@
#ifndef UI_NATIVE_THEME_NATIVE_THEME_BASE_H_
#define UI_NATIVE_THEME_NATIVE_THEME_BASE_H_
-#include <memory>
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
@@ -36,7 +35,7 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme {
const gfx::Rect& rect,
const ExtraParams& extra,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const override;
+ const absl::optional<SkColor>& accent_color) const override;
bool SupportsNinePatch(Part part) const override;
gfx::Size GetNinePatchCanvasSize(Part part) const override;
@@ -127,14 +126,14 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme {
const gfx::Rect& rect,
const ButtonExtraParams& button,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const;
+ const absl::optional<SkColor>& accent_color) const;
void PaintRadio(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& button,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const;
+ const absl::optional<SkColor>& accent_color) const;
void PaintButton(cc::PaintCanvas* canvas,
State state,
@@ -178,14 +177,14 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme {
const gfx::Rect& rect,
const SliderExtraParams& slider,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const;
+ const absl::optional<SkColor>& accent_color) const;
void PaintSliderThumb(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const SliderExtraParams& slider,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const;
+ const absl::optional<SkColor>& accent_color) const;
virtual void PaintInnerSpinButton(
cc::PaintCanvas* canvas,
@@ -199,7 +198,7 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme {
const gfx::Rect& rect,
const ProgressBarExtraParams& progress_bar,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const;
+ const absl::optional<SkColor>& accent_color) const;
virtual void PaintFrameTopArea(cc::PaintCanvas* canvas,
State state,
@@ -288,7 +287,7 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme {
bool is_checkbox,
const SkScalar border_radius,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const;
+ const absl::optional<SkColor>& accent_color) const;
SkColor ControlsBackgroundColorForState(State state,
ColorScheme color_scheme) const;
diff --git a/chromium/ui/native_theme/native_theme_color_id.h b/chromium/ui/native_theme/native_theme_color_id.h
index 60197576c71..083640808cd 100644
--- a/chromium/ui/native_theme/native_theme_color_id.h
+++ b/chromium/ui/native_theme/native_theme_color_id.h
@@ -107,6 +107,12 @@
OP(kColorId_SliderTroughMinimal), \
/* Separator */ \
OP(kColorId_SeparatorColor), \
+ /* Shadow */ \
+ OP(kColorId_ShadowBase), \
+ OP(kColorId_ShadowValueAmbientShadowElevationThree), \
+ OP(kColorId_ShadowValueKeyShadowElevationThree), \
+ OP(kColorId_ShadowValueAmbientShadowElevationSixteen), \
+ OP(kColorId_ShadowValueKeyShadowElevationSixteen), \
/* Sync info container */ \
OP(kColorId_SyncInfoContainerPaused), \
OP(kColorId_SyncInfoContainerError), \
@@ -156,6 +162,9 @@
OP(kColorId_ThrobberWaitingColor), \
/* Colors for Bubble Border */ \
OP(kColorId_BubbleBorder), \
+ OP(kColorId_BubbleBorderShadowLarge), \
+ OP(kColorId_BubbleBorderShadowSmall), \
+ OP(kColorId_BubbleBorderWhenShadowPresent), \
/* Colors for Footnote Container. */ \
OP(kColorId_FootnoteContainerBorder), \
/* Colors for icons that alert, e.g. upgrade reminders. */ \
@@ -164,7 +173,10 @@
OP(kColorId_AlertSeverityHigh), \
/* Colors for icons in non-menu contexts. */ \
OP(kColorId_DefaultIconColor), \
- OP(kColorId_DisabledIconColor)
+ OP(kColorId_DisabledIconColor), \
+ OP(kColorId_SecondaryIconColor), \
+ /* Color fills inside the focus ring. */ \
+ OP(kColorId_FocusAuraColor)
#if BUILDFLAG(IS_CHROMEOS_ASH)
#define NATIVE_THEME_CHROMEOS_COLOR_IDS \
diff --git a/chromium/ui/native_theme/native_theme_mac.h b/chromium/ui/native_theme/native_theme_mac.h
index f83104b1d47..68fafcb9426 100644
--- a/chromium/ui/native_theme/native_theme_mac.h
+++ b/chromium/ui/native_theme/native_theme_mac.h
@@ -51,7 +51,7 @@ class NATIVE_THEME_EXPORT NativeThemeMac : public NativeThemeBase {
const gfx::Rect& rect,
const ExtraParams& extra,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const override;
+ const absl::optional<SkColor>& accent_color) const override;
void PaintMenuPopupBackground(
cc::PaintCanvas* canvas,
const gfx::Size& size,
@@ -126,7 +126,7 @@ class NATIVE_THEME_EXPORT NativeThemeMac : public NativeThemeBase {
// Used by the GetSystem to run the switch for MacOS override colors that may
// use named NS system colors. This is a separate function from GetSystemColor
// to make sure the NSAppearance can be set in a scoped way.
- base::Optional<SkColor> GetOSColor(ColorId color_id,
+ absl::optional<SkColor> GetOSColor(ColorId color_id,
ColorScheme color_scheme) const;
enum ScrollbarPart {
@@ -135,7 +135,7 @@ class NATIVE_THEME_EXPORT NativeThemeMac : public NativeThemeBase {
kTrackOuterBorder,
};
- base::Optional<SkColor> GetScrollbarColor(
+ absl::optional<SkColor> GetScrollbarColor(
ScrollbarPart part,
ColorScheme color_scheme,
const ScrollbarExtraParams& extra_params) const;
diff --git a/chromium/ui/native_theme/native_theme_mac.mm b/chromium/ui/native_theme/native_theme_mac.mm
index 3eea09d9980..daf974af795 100644
--- a/chromium/ui/native_theme/native_theme_mac.mm
+++ b/chromium/ui/native_theme/native_theme_mac.mm
@@ -159,7 +159,7 @@ SkColor NativeThemeMac::GetSystemColorDeprecated(ColorId color_id,
}
}
- base::Optional<SkColor> os_color = GetOSColor(color_id, color_scheme);
+ absl::optional<SkColor> os_color = GetOSColor(color_id, color_scheme);
if (os_color.has_value())
return os_color.value();
@@ -168,7 +168,7 @@ SkColor NativeThemeMac::GetSystemColorDeprecated(ColorId color_id,
return apply_processing ? ApplySystemControlTint(color) : color;
}
-base::Optional<SkColor> NativeThemeMac::GetOSColor(
+absl::optional<SkColor> NativeThemeMac::GetOSColor(
ColorId color_id,
ColorScheme color_scheme) const {
ScopedCurrentNSAppearance scoped_nsappearance(
@@ -215,7 +215,7 @@ base::Optional<SkColor> NativeThemeMac::GetOSColor(
NSColor.controlAlternatingRowBackgroundColors[1]);
default:
- return base::nullopt;
+ return absl::nullopt;
}
}
@@ -231,7 +231,7 @@ void NativeThemeMac::Paint(cc::PaintCanvas* canvas,
const gfx::Rect& rect,
const ExtraParams& extra,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const {
+ const absl::optional<SkColor>& accent_color) const {
ColorScheme color_scheme_updated = color_scheme;
if (color_scheme_updated == ColorScheme::kDefault)
color_scheme_updated = GetDefaultSystemColorScheme();
@@ -482,7 +482,7 @@ void NativeThemeMac::PaintMacScrollbarThumb(
paint_canvas.DrawRoundRect(bounds, radius, flags);
}
-base::Optional<SkColor> NativeThemeMac::GetScrollbarColor(
+absl::optional<SkColor> NativeThemeMac::GetScrollbarColor(
ScrollbarPart part,
ColorScheme color_scheme,
const ScrollbarExtraParams& extra_params) const {
@@ -517,7 +517,7 @@ base::Optional<SkColor> NativeThemeMac::GetScrollbarColor(
: SkColorSetRGB(0xED, 0xED, 0xED);
}
- return base::nullopt;
+ return absl::nullopt;
}
SkColor NativeThemeMac::GetSystemButtonPressedColor(SkColor base_color) const {
diff --git a/chromium/ui/native_theme/native_theme_unittest.cc b/chromium/ui/native_theme/native_theme_unittest.cc
index 66f0960026e..17e22b95689 100644
--- a/chromium/ui/native_theme/native_theme_unittest.cc
+++ b/chromium/ui/native_theme/native_theme_unittest.cc
@@ -8,7 +8,6 @@
#include <tuple>
#include "base/notreached.h"
-#include "base/strings/stringprintf.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/ui/native_theme/native_theme_utils.cc b/chromium/ui/native_theme/native_theme_utils.cc
index 26d28f5ece1..ee7454dfc0f 100644
--- a/chromium/ui/native_theme/native_theme_utils.cc
+++ b/chromium/ui/native_theme/native_theme_utils.cc
@@ -40,7 +40,7 @@ base::StringPiece NativeThemeColorSchemeName(
}
// clang-format off
-base::Optional<ColorId>
+absl::optional<ColorId>
NativeThemeColorIdToColorId(NativeTheme::ColorId native_theme_color_id) {
using NTCID = NativeTheme::ColorId;
static constexpr const auto map =
@@ -53,6 +53,12 @@ NativeThemeColorIdToColorId(NativeTheme::ColorId native_theme_color_id) {
{NTCID::kColorId_AvatarIconIncognito, kColorAvatarIconIncognito},
{NTCID::kColorId_BubbleBackground, kColorBubbleBackground},
{NTCID::kColorId_BubbleBorder, kColorBubbleBorder},
+ {NTCID::kColorId_BubbleBorderShadowLarge,
+ kColorBubbleBorderShadowLarge},
+ {NTCID::kColorId_BubbleBorderShadowSmall,
+ kColorBubbleBorderShadowSmall},
+ {NTCID::kColorId_BubbleBorderWhenShadowPresent,
+ kColorBubbleBorderWhenShadowPresent},
{NTCID::kColorId_BubbleFooterBackground,
kColorBubbleFooterBackground},
{NTCID::kColorId_ButtonBorderColor, kColorButtonBorder},
@@ -82,6 +88,7 @@ NativeThemeColorIdToColorId(NativeTheme::ColorId native_theme_color_id) {
{NTCID::kColorId_DialogForeground, kColorDialogForeground},
{NTCID::kColorId_DisabledButtonBorderColor, kColorButtonBorderDisabled},
{NTCID::kColorId_DisabledIconColor, kColorIconDisabled},
+ {NTCID::kColorId_SecondaryIconColor, kColorIconSecondary},
{NTCID::kColorId_DisabledMenuItemForegroundColor,
kColorMenuItemForegroundDisabled},
{NTCID::kColorId_DropdownBackgroundColor, kColorDropdownBackground},
@@ -92,6 +99,7 @@ NativeThemeColorIdToColorId(NativeTheme::ColorId native_theme_color_id) {
kColorDropdownForegroundSelected},
{NTCID::kColorId_EnabledMenuItemForegroundColor,
kColorMenuItemForeground},
+ {NTCID::kColorId_FocusAuraColor, kColorFocusAura},
{NTCID::kColorId_FocusedBorderColor, kColorFocusableBorderFocused},
{NTCID::kColorId_FocusedMenuItemBackgroundColor,
kColorMenuItemBackgroundSelected},
@@ -157,6 +165,15 @@ NativeThemeColorIdToColorId(NativeTheme::ColorId native_theme_color_id) {
{NTCID::kColorId_SelectedMenuItemForegroundColor,
kColorMenuItemForegroundSelected},
{NTCID::kColorId_SeparatorColor, kColorSeparator},
+ {NTCID::kColorId_ShadowBase, kColorShadowBase},
+ {NTCID::kColorId_ShadowValueAmbientShadowElevationThree,
+ kColorShadowValueAmbientShadowElevationThree},
+ {NTCID::kColorId_ShadowValueKeyShadowElevationThree,
+ kColorShadowValueKeyShadowElevationThree},
+ {NTCID::kColorId_ShadowValueAmbientShadowElevationSixteen,
+ kColorShadowValueAmbientShadowElevationSixteen},
+ {NTCID::kColorId_ShadowValueKeyShadowElevationSixteen,
+ kColorShadowValueKeyShadowElevationSixteen},
{NTCID::kColorId_SliderThumbDefault, kColorSliderThumb},
{NTCID::kColorId_SliderThumbMinimal, kColorSliderThumbMinimal},
{NTCID::kColorId_SliderTroughDefault, kColorSliderTrack},
@@ -234,7 +251,7 @@ NativeThemeColorIdToColorId(NativeTheme::ColorId native_theme_color_id) {
if (color_it != map.cend()) {
return color_it->second;
}
- return base::nullopt;
+ return absl::nullopt;
}
// clang-format on
diff --git a/chromium/ui/native_theme/native_theme_utils.h b/chromium/ui/native_theme/native_theme_utils.h
index 39a00a766fa..7a4f2989099 100644
--- a/chromium/ui/native_theme/native_theme_utils.h
+++ b/chromium/ui/native_theme/native_theme_utils.h
@@ -25,7 +25,7 @@ base::StringPiece NATIVE_THEME_EXPORT
NativeThemeColorSchemeName(NativeTheme::ColorScheme color_scheme);
// Converts a NativeTheme::ColorId to a ColorPipeline ColorId.
-base::Optional<ColorId> NATIVE_THEME_EXPORT
+absl::optional<ColorId> NATIVE_THEME_EXPORT
NativeThemeColorIdToColorId(NativeTheme::ColorId native_theme_color_id);
} // namespace ui
diff --git a/chromium/ui/native_theme/native_theme_win.cc b/chromium/ui/native_theme/native_theme_win.cc
index 68b798fc755..5e1dcf94874 100644
--- a/chromium/ui/native_theme/native_theme_win.cc
+++ b/chromium/ui/native_theme/native_theme_win.cc
@@ -16,7 +16,6 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/notreached.h"
-#include "base/optional.h"
#include "base/stl_util.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/win/scoped_gdi_object.h"
@@ -27,6 +26,7 @@
#include "cc/paint/paint_flags.h"
#include "skia/ext/platform_canvas.h"
#include "skia/ext/skia_utils_win.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkColorPriv.h"
@@ -249,7 +249,7 @@ void NativeThemeWin::Paint(cc::PaintCanvas* canvas,
const gfx::Rect& rect,
const ExtraParams& extra,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const {
+ const absl::optional<SkColor>& accent_color) const {
if (rect.IsEmpty())
return;
@@ -332,7 +332,7 @@ bool NativeThemeWin::AllowColorPipelineRedirection(
SkColor NativeThemeWin::GetSystemColorDeprecated(ColorId color_id,
ColorScheme color_scheme,
bool apply_processing) const {
- base::Optional<SkColor> color;
+ absl::optional<SkColor> color;
if (color_scheme == ColorScheme::kPlatformHighContrast &&
(color = GetPlatformHighContrastColor(color_id))) {
return color.value();
@@ -609,7 +609,7 @@ void NativeThemeWin::PaintDirect(SkCanvas* destination_canvas,
}
}
-base::Optional<SkColor> NativeThemeWin::GetPlatformHighContrastColor(
+absl::optional<SkColor> NativeThemeWin::GetPlatformHighContrastColor(
ColorId color_id) const {
switch (color_id) {
// Window Background
@@ -711,7 +711,7 @@ base::Optional<SkColor> NativeThemeWin::GetPlatformHighContrastColor(
return system_colors_[SystemThemeColor::kHighlightText];
default:
- return base::nullopt;
+ return absl::nullopt;
}
}
diff --git a/chromium/ui/native_theme/native_theme_win.h b/chromium/ui/native_theme/native_theme_win.h
index 8b273714d3d..71142c1c45b 100644
--- a/chromium/ui/native_theme/native_theme_win.h
+++ b/chromium/ui/native_theme/native_theme_win.h
@@ -15,8 +15,8 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/no_destructor.h"
-#include "base/optional.h"
#include "base/win/registry.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/sys_color_change_listener.h"
@@ -65,7 +65,7 @@ class NATIVE_THEME_EXPORT NativeThemeWin : public NativeTheme,
const gfx::Rect& rect,
const ExtraParams& extra,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const override;
+ const absl::optional<SkColor>& accent_color) const override;
bool SupportsNinePatch(Part part) const override;
gfx::Size GetNinePatchCanvasSize(Part part) const override;
gfx::Rect GetNinePatchAperture(Part part) const override;
@@ -201,7 +201,7 @@ class NATIVE_THEME_EXPORT NativeThemeWin : public NativeTheme,
// Returns the platform provided high contrast color for the given
// |color_id|.
- base::Optional<SkColor> GetPlatformHighContrastColor(ColorId color_id) const;
+ absl::optional<SkColor> GetPlatformHighContrastColor(ColorId color_id) const;
// Dark Mode registry key.
base::win::RegKey hkcu_themes_regkey_;
diff --git a/chromium/ui/native_theme/test_native_theme.cc b/chromium/ui/native_theme/test_native_theme.cc
index f6413f2971b..8f58d490b44 100644
--- a/chromium/ui/native_theme/test_native_theme.cc
+++ b/chromium/ui/native_theme/test_native_theme.cc
@@ -21,7 +21,7 @@ void TestNativeTheme::Paint(cc::PaintCanvas* canvas,
const gfx::Rect& rect,
const ExtraParams& extra,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const {
+ const absl::optional<SkColor>& accent_color) const {
}
bool TestNativeTheme::SupportsNinePatch(Part part) const {
diff --git a/chromium/ui/native_theme/test_native_theme.h b/chromium/ui/native_theme/test_native_theme.h
index f66cd329df1..a511f21cdeb 100644
--- a/chromium/ui/native_theme/test_native_theme.h
+++ b/chromium/ui/native_theme/test_native_theme.h
@@ -25,7 +25,7 @@ class TestNativeTheme : public NativeTheme {
const gfx::Rect& rect,
const ExtraParams& extra,
ColorScheme color_scheme,
- const base::Optional<SkColor>& accent_color) const override;
+ const absl::optional<SkColor>& accent_color) const override;
bool SupportsNinePatch(Part part) const override;
gfx::Size GetNinePatchCanvasSize(Part part) const override;
gfx::Rect GetNinePatchAperture(Part part) const override;
diff --git a/chromium/ui/native_theme/themed_vector_icon.cc b/chromium/ui/native_theme/themed_vector_icon.cc
index d4374ca97c3..437a8648a38 100644
--- a/chromium/ui/native_theme/themed_vector_icon.cc
+++ b/chromium/ui/native_theme/themed_vector_icon.cc
@@ -6,33 +6,37 @@
#include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/vector_icon_types.h"
+#include "ui/gfx/vector_icon_utils.h"
namespace ui {
ThemedVectorIcon::ThemedVectorIcon() = default;
ThemedVectorIcon::ThemedVectorIcon(const gfx::VectorIcon* icon,
- NativeTheme::ColorId color_id,
- int icon_size)
- : icon_(icon), icon_size_(icon_size), color_id_(color_id) {}
+ int color_id,
+ int icon_size,
+ const gfx::VectorIcon* badge)
+ : icon_(icon), icon_size_(icon_size), color_(color_id), badge_(badge) {}
ThemedVectorIcon::ThemedVectorIcon(const VectorIconModel& vector_icon_model)
: icon_(vector_icon_model.vector_icon()),
- icon_size_(vector_icon_model.icon_size()) {
+ icon_size_(vector_icon_model.icon_size()),
+ badge_(vector_icon_model.badge_icon()) {
if (vector_icon_model.has_color()) {
color_ = vector_icon_model.color();
} else if (vector_icon_model.color_id() >= 0) {
- color_id_ =
+ color_ =
static_cast<ui::NativeTheme::ColorId>(vector_icon_model.color_id());
} else {
- color_id_ = ui::NativeTheme::kColorId_MenuIconColor;
+ color_ = ui::NativeTheme::kColorId_MenuIconColor;
}
}
ThemedVectorIcon::ThemedVectorIcon(const gfx::VectorIcon* icon,
SkColor color,
- int icon_size)
- : icon_(icon), icon_size_(icon_size), color_(color) {}
+ int icon_size,
+ const gfx::VectorIcon* badge)
+ : icon_(icon), icon_size_(icon_size), color_(color), badge_(badge) {}
ThemedVectorIcon::ThemedVectorIcon(const ThemedVectorIcon&) = default;
@@ -45,25 +49,35 @@ ThemedVectorIcon& ThemedVectorIcon::operator=(ThemedVectorIcon&&) = default;
gfx::ImageSkia ThemedVectorIcon::GetImageSkia(const NativeTheme* theme) const {
DCHECK(!empty());
- return icon_size_ > 0 ? CreateVectorIcon(*icon_, icon_size_, GetColor(theme))
- : CreateVectorIcon(*icon_, GetColor(theme));
+ return GetImageSkia(theme, (icon_size_ > 0)
+ ? icon_size_
+ : GetDefaultSizeOfVectorIcon(*icon_));
}
gfx::ImageSkia ThemedVectorIcon::GetImageSkia(const NativeTheme* theme,
int icon_size) const {
DCHECK(!empty());
- return CreateVectorIcon(*icon_, icon_size, GetColor(theme));
+ return GetImageSkia(GetColor(theme), icon_size);
}
gfx::ImageSkia ThemedVectorIcon::GetImageSkia(SkColor color) const {
DCHECK(!empty());
- return icon_size_ > 0 ? CreateVectorIcon(*icon_, icon_size_, color)
- : CreateVectorIcon(*icon_, color);
+ return GetImageSkia(color, (icon_size_ > 0)
+ ? icon_size_
+ : GetDefaultSizeOfVectorIcon(*icon_));
}
SkColor ThemedVectorIcon::GetColor(const NativeTheme* theme) const {
- DCHECK(color_id_ || color_);
- return color_id_ ? theme->GetSystemColor(color_id_.value()) : color_.value();
+ return absl::holds_alternative<int>(color_)
+ ? theme->GetSystemColor(static_cast<ui::NativeTheme::ColorId>(
+ absl::get<int>(color_)))
+ : absl::get<SkColor>(color_);
+}
+
+gfx::ImageSkia ThemedVectorIcon::GetImageSkia(SkColor color,
+ int icon_size) const {
+ return badge_ ? CreateVectorIconWithBadge(*icon_, icon_size, color, *badge_)
+ : CreateVectorIcon(*icon_, icon_size, color);
}
} // namespace ui
diff --git a/chromium/ui/native_theme/themed_vector_icon.h b/chromium/ui/native_theme/themed_vector_icon.h
index 33df4298838..1e17e059fd2 100644
--- a/chromium/ui/native_theme/themed_vector_icon.h
+++ b/chromium/ui/native_theme/themed_vector_icon.h
@@ -5,7 +5,7 @@
#ifndef UI_NATIVE_THEME_THEMED_VECTOR_ICON_H_
#define UI_NATIVE_THEME_THEMED_VECTOR_ICON_H_
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/models/image_model.h"
#include "ui/native_theme/native_theme.h"
@@ -21,16 +21,17 @@ namespace ui {
class NATIVE_THEME_EXPORT ThemedVectorIcon {
public:
ThemedVectorIcon();
- explicit ThemedVectorIcon(
- const gfx::VectorIcon* icon,
- NativeTheme::ColorId color_id = NativeTheme::kColorId_MenuIconColor,
- int icon_size = 0);
+ explicit ThemedVectorIcon(const gfx::VectorIcon* icon,
+ int color_id = NativeTheme::kColorId_MenuIconColor,
+ int icon_size = 0,
+ const gfx::VectorIcon* badge = nullptr);
explicit ThemedVectorIcon(const VectorIconModel& vector_icon_model);
// TODO (kylixrd): Remove this once all the hard-coded uses of color are
// removed.
ThemedVectorIcon(const gfx::VectorIcon* icon,
SkColor color,
- int icon_size = 0);
+ int icon_size = 0,
+ const gfx::VectorIcon* badge = nullptr);
// Copyable and moveable
ThemedVectorIcon(const ThemedVectorIcon& other);
@@ -46,11 +47,12 @@ class NATIVE_THEME_EXPORT ThemedVectorIcon {
private:
SkColor GetColor(const NativeTheme* theme) const;
+ gfx::ImageSkia GetImageSkia(SkColor color, int icon_size) const;
const gfx::VectorIcon* icon_ = nullptr;
int icon_size_ = 0;
- base::Optional<NativeTheme::ColorId> color_id_;
- base::Optional<SkColor> color_;
+ absl::variant<int, SkColor> color_ = gfx::kPlaceholderColor;
+ const gfx::VectorIcon* badge_ = nullptr;
};
} // namespace ui
diff --git a/chromium/ui/ozone/BUILD.gn b/chromium/ui/ozone/BUILD.gn
index d0dfdfba774..73ddfd526ec 100644
--- a/chromium/ui/ozone/BUILD.gn
+++ b/chromium/ui/ozone/BUILD.gn
@@ -96,6 +96,8 @@ component("ozone_base") {
"public/platform_gl_egl_utility.h",
"public/platform_global_shortcut_listener.cc",
"public/platform_global_shortcut_listener.h",
+ "public/platform_keyboard_hook.cc",
+ "public/platform_keyboard_hook.h",
"public/platform_menu_utils.cc",
"public/platform_menu_utils.h",
"public/platform_screen.cc",
@@ -125,6 +127,7 @@ component("ozone_base") {
"//ui/display/util",
"//ui/events",
"//ui/events:dom_keycode_converter",
+ "//ui/events/devices:devices",
"//ui/gfx",
"//ui/gfx/geometry",
"//ui/gfx/ipc",
@@ -162,6 +165,8 @@ component("ozone_base") {
source_set("platform") {
sources = [
+ "common/base_keyboard_hook.cc",
+ "common/base_keyboard_hook.h",
"common/stub_client_native_pixmap_factory.cc",
"common/stub_client_native_pixmap_factory.h",
"platform_constructor_list.h",
@@ -377,7 +382,10 @@ if (ozone_platform_x11) {
buildflag_header("buildflags") {
header = "buildflags.h"
- flags = [ "OZONE_PLATFORM_X11=$ozone_platform_x11" ]
+ flags = [
+ "OZONE_PLATFORM_WAYLAND=$ozone_platform_wayland",
+ "OZONE_PLATFORM_X11=$ozone_platform_x11",
+ ]
visibility += [ "*" ]
}
diff --git a/chromium/ui/ozone/common/base_keyboard_hook.cc b/chromium/ui/ozone/common/base_keyboard_hook.cc
new file mode 100644
index 00000000000..96f1a18d64e
--- /dev/null
+++ b/chromium/ui/ozone/common/base_keyboard_hook.cc
@@ -0,0 +1,39 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/common/base_keyboard_hook.h"
+
+#include <utility>
+
+#include "base/containers/contains.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+
+namespace ui {
+
+BaseKeyboardHook::BaseKeyboardHook(
+ absl::optional<base::flat_set<DomCode>> dom_codes,
+ KeyEventCallback callback)
+ : key_event_callback_(std::move(callback)),
+ dom_codes_(std::move(dom_codes)) {
+ DCHECK(key_event_callback_);
+}
+
+BaseKeyboardHook::~BaseKeyboardHook() = default;
+
+bool BaseKeyboardHook::IsKeyLocked(DomCode dom_code) const {
+ return ShouldCaptureKeyEvent(dom_code);
+}
+
+bool BaseKeyboardHook::ShouldCaptureKeyEvent(DomCode dom_code) const {
+ if (dom_code == DomCode::NONE)
+ return false;
+
+ return !dom_codes_ || base::Contains(dom_codes_.value(), dom_code);
+}
+
+void BaseKeyboardHook::ForwardCapturedKeyEvent(KeyEvent* event) {
+ key_event_callback_.Run(event);
+}
+
+} // namespace ui \ No newline at end of file
diff --git a/chromium/ui/ozone/common/base_keyboard_hook.h b/chromium/ui/ozone/common/base_keyboard_hook.h
new file mode 100644
index 00000000000..5c7c4d5a6db
--- /dev/null
+++ b/chromium/ui/ozone/common/base_keyboard_hook.h
@@ -0,0 +1,60 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_COMMON_BASE_KEYBOARD_HOOK_H_
+#define UI_OZONE_COMMON_BASE_KEYBOARD_HOOK_H_
+
+#include "base/callback.h"
+#include "base/component_export.h"
+#include "base/containers/flat_set.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+#include "ui/ozone/public/platform_keyboard_hook.h"
+
+namespace ui {
+
+enum class DomCode;
+class KeyEvent;
+
+// Base implementation of KeyboardHook for Ozone platforms.
+//
+// Holds and provides to the subclasses the set of DOM codes and the callback
+// given upon construction.
+//
+// Can be used as is, and provides the browser-level lock for the given set of
+// keys. Platforms may implement system-level lock. The instance of this class
+// should enable the lock in constructor and release in in the destructor.
+class BaseKeyboardHook : public PlatformKeyboardHook {
+ public:
+ using KeyEventCallback = base::RepeatingCallback<void(KeyEvent* event)>;
+
+ BaseKeyboardHook(absl::optional<base::flat_set<DomCode>> dom_codes,
+ KeyEventCallback callback);
+ BaseKeyboardHook(const BaseKeyboardHook&) = delete;
+ BaseKeyboardHook& operator=(const BaseKeyboardHook&) = delete;
+ ~BaseKeyboardHook() override;
+
+ // BaseKeyboardHook:
+ bool IsKeyLocked(DomCode dom_code) const override;
+
+ protected:
+ // Indicates whether |dom_code| should be intercepted by the keyboard hook.
+ bool ShouldCaptureKeyEvent(DomCode dom_code) const;
+ // Forwards the key event using |key_event_callback_|.
+ // |event| is owned by the calling method and will live until this method
+ // returns.
+ void ForwardCapturedKeyEvent(KeyEvent* event);
+ const absl::optional<base::flat_set<DomCode>>& dom_codes() {
+ return dom_codes_;
+ }
+
+ private:
+ // Used to forward key events.
+ KeyEventCallback key_event_callback_;
+ // The set of keys which should be intercepted by the keyboard hook.
+ absl::optional<base::flat_set<DomCode>> dom_codes_;
+};
+
+} // namespace ui
+#endif // UI_OZONE_COMMON_BASE_KEYBOARD_HOOK_H_
diff --git a/chromium/ui/ozone/demo/gl_renderer.cc b/chromium/ui/ozone/demo/gl_renderer.cc
index c25b8f9c15d..72672c58832 100644
--- a/chromium/ui/ozone/demo/gl_renderer.cc
+++ b/chromium/ui/ozone/demo/gl_renderer.cc
@@ -75,8 +75,8 @@ void GlRenderer::RenderFrame() {
}
void GlRenderer::PostRenderFrameTask(gfx::SwapCompletionResult result) {
- if (result.gpu_fence)
- result.gpu_fence->Wait();
+ if (!result.release_fence.is_null())
+ gfx::GpuFence(std::move(result.release_fence)).Wait();
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
diff --git a/chromium/ui/ozone/demo/simple_renderer_factory.cc b/chromium/ui/ozone/demo/simple_renderer_factory.cc
index 8537ed0a8db..98ac818d159 100644
--- a/chromium/ui/ozone/demo/simple_renderer_factory.cc
+++ b/chromium/ui/ozone/demo/simple_renderer_factory.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/command_line.h"
+#include "base/logging.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/init/gl_factory.h"
#include "ui/ozone/demo/gl_renderer.h"
diff --git a/chromium/ui/ozone/demo/skia/skia_gl_renderer.cc b/chromium/ui/ozone/demo/skia/skia_gl_renderer.cc
index f473144258a..3c464fe0db2 100644
--- a/chromium/ui/ozone/demo/skia/skia_gl_renderer.cc
+++ b/chromium/ui/ozone/demo/skia/skia_gl_renderer.cc
@@ -122,8 +122,8 @@ void SkiaGlRenderer::RenderFrame() {
}
void SkiaGlRenderer::PostRenderFrameTask(gfx::SwapCompletionResult result) {
- if (result.gpu_fence)
- result.gpu_fence->Wait();
+ if (!result.release_fence.is_null())
+ gfx::GpuFence(std::move(result.release_fence)).Wait();
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&SkiaGlRenderer::RenderFrame,
diff --git a/chromium/ui/ozone/demo/skia/skia_renderer_factory.cc b/chromium/ui/ozone/demo/skia/skia_renderer_factory.cc
index f6062b87b28..005c22488e3 100644
--- a/chromium/ui/ozone/demo/skia/skia_renderer_factory.cc
+++ b/chromium/ui/ozone/demo/skia/skia_renderer_factory.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/command_line.h"
+#include "base/logging.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/init/gl_factory.h"
#include "ui/ozone/demo/skia/skia_gl_renderer.h"
diff --git a/chromium/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc b/chromium/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
index 4228fb36aec..d784615f406 100644
--- a/chromium/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
+++ b/chromium/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
@@ -66,7 +66,6 @@ OverlaySurfaceCandidate MakeOverlayCandidate(int z_order,
// The demo overlay instance is always ontop and not clipped. Clipped quads
// cannot be placed in overlays.
- overlay_candidate.is_clipped = false;
return overlay_candidate;
}
diff --git a/chromium/ui/ozone/demo/software_renderer.cc b/chromium/ui/ozone/demo/software_renderer.cc
index 30cd9127c8d..657925ad15e 100644
--- a/chromium/ui/ozone/demo/software_renderer.cc
+++ b/chromium/ui/ozone/demo/software_renderer.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/logging.h"
#include "base/trace_event/trace_event.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"
diff --git a/chromium/ui/ozone/demo/surfaceless_gl_renderer.cc b/chromium/ui/ozone/demo/surfaceless_gl_renderer.cc
index 0d9bc20d4ce..94b7623027a 100644
--- a/chromium/ui/ozone/demo/surfaceless_gl_renderer.cc
+++ b/chromium/ui/ozone/demo/surfaceless_gl_renderer.cc
@@ -58,7 +58,6 @@ OverlaySurfaceCandidate MakeOverlayCandidate(int z_order,
// The demo overlay instance is always ontop and not clipped. Clipped quads
// cannot be placed in overlays.
- overlay_candidate.is_clipped = false;
return overlay_candidate;
}
@@ -289,8 +288,8 @@ void SurfacelessGlRenderer::RenderFrame() {
void SurfacelessGlRenderer::PostRenderFrameTask(
gfx::SwapCompletionResult result) {
- if (result.gpu_fence)
- result.gpu_fence->Wait();
+ if (!result.release_fence.is_null())
+ gfx::GpuFence(std::move(result.release_fence)).Wait();
switch (result.swap_result) {
case gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS:
diff --git a/chromium/ui/ozone/demo/vulkan_overlay_renderer.cc b/chromium/ui/ozone/demo/vulkan_overlay_renderer.cc
index 963b47f69fa..b628f1084a5 100644
--- a/chromium/ui/ozone/demo/vulkan_overlay_renderer.cc
+++ b/chromium/ui/ozone/demo/vulkan_overlay_renderer.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/location.h"
+#include "base/logging.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "gpu/vulkan/init/vulkan_factory.h"
@@ -114,7 +115,7 @@ bool VulkanOverlayRenderer::Initialize() {
VK_SUCCESS);
command_pool_ = std::make_unique<gpu::VulkanCommandPool>(device_queue_.get());
- CHECK(command_pool_->Initialize(false /* use_protected_memory */));
+ CHECK(command_pool_->Initialize());
RecreateBuffers();
@@ -387,8 +388,7 @@ VulkanOverlayRenderer::Buffer::Create(
}
auto command_buffer = std::make_unique<gpu::VulkanCommandBuffer>(
- vulkan_device_queue, vulkan_command_pool, true /* primary */,
- false /* use_protected_memory */);
+ vulkan_device_queue, vulkan_command_pool, true /* primary */);
CHECK(command_buffer->Initialize());
VkFence fence = vulkan_implementation->CreateVkFenceForGpuFence(vk_device);
diff --git a/chromium/ui/ozone/demo/vulkan_renderer.cc b/chromium/ui/ozone/demo/vulkan_renderer.cc
index 4e1a1fc3d1f..dcd8e7ba03f 100644
--- a/chromium/ui/ozone/demo/vulkan_renderer.cc
+++ b/chromium/ui/ozone/demo/vulkan_renderer.cc
@@ -169,7 +169,7 @@ bool VulkanRenderer::Initialize() {
VK_SUCCESS);
command_pool_ = std::make_unique<gpu::VulkanCommandPool>(device_queue_.get());
- CHECK(command_pool_->Initialize(false /* use_protected_memory */));
+ CHECK(command_pool_->Initialize());
RecreateFramebuffers();
@@ -410,8 +410,7 @@ VulkanRenderer::Framebuffer::Create(gpu::VulkanDeviceQueue* vulkan_device_queue,
}
auto command_buffer = std::make_unique<gpu::VulkanCommandBuffer>(
- vulkan_device_queue, vulkan_command_pool, true /* primary */,
- false /* use_protected_memory */);
+ vulkan_device_queue, vulkan_command_pool, true /* primary */);
CHECK(command_buffer->Initialize());
return std::make_unique<VulkanRenderer::Framebuffer>(
diff --git a/chromium/ui/ozone/platform/cast/gl_ozone_egl_cast.cc b/chromium/ui/ozone/platform/cast/gl_ozone_egl_cast.cc
index e45b1ad3afd..8b3f2ced920 100644
--- a/chromium/ui/ozone/platform/cast/gl_ozone_egl_cast.cc
+++ b/chromium/ui/ozone/platform/cast/gl_ozone_egl_cast.cc
@@ -10,6 +10,7 @@
#include <utility>
#include "base/command_line.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "chromecast/base/chromecast_switches.h"
diff --git a/chromium/ui/ozone/platform/cast/ozone_platform_cast.cc b/chromium/ui/ozone/platform/cast/ozone_platform_cast.cc
index b5702ad228d..01ed80e6abb 100644
--- a/chromium/ui/ozone/platform/cast/ozone_platform_cast.cc
+++ b/chromium/ui/ozone/platform/cast/ozone_platform_cast.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/lazy_instance.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "chromecast/chromecast_buildflags.h"
diff --git a/chromium/ui/ozone/platform/cast/ozone_platform_cast.h b/chromium/ui/ozone/platform/cast/ozone_platform_cast.h
index 7698c1acd6a..a21fefa34d9 100644
--- a/chromium/ui/ozone/platform/cast/ozone_platform_cast.h
+++ b/chromium/ui/ozone/platform/cast/ozone_platform_cast.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_OZONE_PLATFORM_CAST_OZONE_PLATFORM_CAST_H
-#define UI_OZONE_PLATFORM_CAST_OZONE_PLATFORM_CAST_H
+#ifndef UI_OZONE_PLATFORM_CAST_OZONE_PLATFORM_CAST_H_
+#define UI_OZONE_PLATFORM_CAST_OZONE_PLATFORM_CAST_H_
namespace ui {
@@ -14,4 +14,4 @@ OzonePlatform* CreateOzonePlatformCast();
} // namespace ui
-#endif // UI_OZONE_PLATFORM_CAST_OZONE_PLATFORM_CAST_H
+#endif // UI_OZONE_PLATFORM_CAST_OZONE_PLATFORM_CAST_H_
diff --git a/chromium/ui/ozone/platform/cast/surface_factory_cast.cc b/chromium/ui/ozone/platform/cast/surface_factory_cast.cc
index aaebad04a50..e5520f84f35 100644
--- a/chromium/ui/ozone/platform/cast/surface_factory_cast.cc
+++ b/chromium/ui/ozone/platform/cast/surface_factory_cast.cc
@@ -129,7 +129,7 @@ scoped_refptr<gfx::NativePixmap> SurfaceFactoryCast::CreateNativePixmap(
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- base::Optional<gfx::Size> framebuffer_size) {
+ absl::optional<gfx::Size> framebuffer_size) {
DCHECK(!framebuffer_size || framebuffer_size == size);
return base::MakeRefCounted<CastPixmap>();
}
diff --git a/chromium/ui/ozone/platform/cast/surface_factory_cast.h b/chromium/ui/ozone/platform/cast/surface_factory_cast.h
index de582c61b4a..70921702855 100644
--- a/chromium/ui/ozone/platform/cast/surface_factory_cast.h
+++ b/chromium/ui/ozone/platform/cast/surface_factory_cast.h
@@ -39,7 +39,7 @@ class SurfaceFactoryCast : public SurfaceFactoryOzone {
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- base::Optional<gfx::Size> framebuffer_size = base::nullopt) override;
+ absl::optional<gfx::Size> framebuffer_size = absl::nullopt) override;
private:
std::unique_ptr<GLOzoneEglCast> egl_implementation_;
diff --git a/chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.cc b/chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.cc
index 3fde52ddaff..6f4c17b6fa9 100644
--- a/chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.cc
@@ -20,6 +20,8 @@ CrtcCommitRequest::CrtcCommitRequest(uint32_t crtc_id,
origin_(origin),
plane_list_(plane_list),
overlays_(std::move(overlays)) {
+ // Verify that at least one overlay plane is a primary plane if we're enabling
+ // a CRTC.
DCHECK(!should_enable || DrmOverlayPlane::GetPrimaryPlane(overlays_));
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h b/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h
index cab7aaec031..babafdea2b3 100644
--- a/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h
+++ b/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h
@@ -12,7 +12,6 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/time/time.h"
#include "ui/gfx/swap_result.h"
#include "ui/ozone/platform/drm/common/scoped_drm_types.h"
#include "ui/ozone/platform/drm/gpu/drm_overlay_plane.h"
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_device.cc b/chromium/ui/ozone/platform/drm/gpu/drm_device.cc
index 6e262e27bbb..9d554a8aa80 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_device.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_device.cc
@@ -275,8 +275,8 @@ bool DrmDevice::Initialize() {
allow_addfb2_modifiers_ =
GetCapability(DRM_CAP_ADDFB2_MODIFIERS, &value) && value;
- watcher_.reset(
- new IOWatcher(file_.GetPlatformFile(), page_flip_manager_.get()));
+ watcher_ = std::make_unique<IOWatcher>(file_.GetPlatformFile(),
+ page_flip_manager_.get());
return true;
}
@@ -430,7 +430,7 @@ ScopedDrmPropertyBlob DrmDevice::CreatePropertyBlob(const void* blob,
int ret = drmModeCreatePropertyBlob(file_.GetPlatformFile(), blob, size, &id);
DCHECK(!ret && id);
- return ScopedDrmPropertyBlob(new DrmPropertyBlobMetadata(this, id));
+ return std::make_unique<DrmPropertyBlobMetadata>(this, id);
}
void DrmDevice::DestroyPropertyBlob(uint32_t id) {
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_display_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/drm_display_unittest.cc
index 208fb3eccf8..0f0023cd15b 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_display_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_display_unittest.cc
@@ -57,7 +57,7 @@ class MockHardwareDisplayPlaneManager : public HardwareDisplayPlaneManager {
}
bool Commit(HardwareDisplayPlaneList* plane_list,
scoped_refptr<PageFlipRequest> page_flip_request,
- std::unique_ptr<gfx::GpuFence>* out_fence) override {
+ gfx::GpuFenceHandle* release_fence) override {
return false;
}
bool DisableOverlayPlanes(HardwareDisplayPlaneList* plane_list) override {
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.h b/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.h
index 8dbfe7f2bd4..2057f2365c2 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_OZONE_PLATFORM_DRM_GPU_SCANOUT_BUFFER_H_
-#define UI_OZONE_PLATFORM_DRM_GPU_SCANOUT_BUFFER_H_
+#ifndef UI_OZONE_PLATFORM_DRM_GPU_DRM_FRAMEBUFFER_H_
+#define UI_OZONE_PLATFORM_DRM_GPU_DRM_FRAMEBUFFER_H_
#include <drm_fourcc.h>
#include <stdint.h>
@@ -123,4 +123,4 @@ class DrmFramebuffer : public base::RefCountedThreadSafe<DrmFramebuffer> {
} // namespace ui
-#endif // UI_OZONE_PLATFORM_DRM_GPU_SCANOUT_BUFFER_H_
+#endif // UI_OZONE_PLATFORM_DRM_GPU_DRM_FRAMEBUFFER_H_
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc
index 928ad048588..29030d9c73e 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc
@@ -155,8 +155,11 @@ bool DrmOverlayManager::CanHandleCandidate(
return true;
// Reject candidates that don't fall on a pixel boundary.
- if (!gfx::IsNearestRectWithinDistance(candidate.display_rect, 0.01f))
+ if (!gfx::IsNearestRectWithinDistance(candidate.display_rect, 0.01f)) {
+ VLOG(3) << "Overlay Rejected: display_rect="
+ << candidate.display_rect.ToString();
return false;
+ }
// DRM supposedly supports subpixel source crop. However, according to
// drm_plane_funcs.update_plane, devices which don't support that are
@@ -164,11 +167,15 @@ bool DrmOverlayManager::CanHandleCandidate(
// of 5.4. So reject candidates that require subpixel source crop.
gfx::RectF crop(candidate.crop_rect);
crop.Scale(candidate.buffer_size.width(), candidate.buffer_size.height());
- if (!gfx::IsNearestRectWithinDistance(crop, 0.01f))
+ if (!gfx::IsNearestRectWithinDistance(crop, 0.01f)) {
+ VLOG(3) << "Overlay Rejected: crop=" << crop.ToString();
return false;
+ }
- if (candidate.is_clipped && !candidate.clip_rect.Contains(
- gfx::ToNearestRect(candidate.display_rect))) {
+ if (candidate.clip_rect && !candidate.clip_rect->Contains(
+ gfx::ToNearestRect(candidate.display_rect))) {
+ VLOG(3) << "Overlay Rejected: clip_rect=" << candidate.clip_rect->ToString()
+ << ", display_rect=" << candidate.display_rect.ToString();
return false;
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
index 76577c6e485..8c612b66a0e 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
@@ -81,15 +81,16 @@ class DrmOverlayValidatorTest : public testing::Test {
bool ModesetController(ui::HardwareDisplayController* controller) {
ui::CommitRequest commit_request;
- ui::DrmOverlayPlane plane(CreateBuffer(), nullptr);
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
- controller->GetModesetProps(&commit_request, plane, kDefaultMode);
+ controller->GetModesetProps(&commit_request, modeset_planes, kDefaultMode);
ui::CommitRequest request_for_update = commit_request;
bool status = drm_->plane_manager()->Commit(std::move(commit_request),
DRM_MODE_ATOMIC_ALLOW_MODESET);
- controller->UpdateState(
- /*enable_requested=*/true,
- ui::DrmOverlayPlane::GetPrimaryPlane(request_for_update[0].overlays()));
+
+ for (const ui::CrtcCommitRequest& crtc_request : request_for_update)
+ controller->UpdateState(crtc_request);
return status;
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc b/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
index 4efe7f98c20..aa505579a01 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
@@ -91,7 +91,7 @@ void DrmThread::Start(base::OnceClosure receiver_completer,
thread_options.message_pump_type = base::MessagePumpType::IO;
thread_options.priority = base::ThreadPriority::DISPLAY;
- if (!StartWithOptions(thread_options))
+ if (!StartWithOptions(std::move(thread_options)))
LOG(FATAL) << "Failed to create DRM thread";
}
@@ -234,7 +234,9 @@ void DrmThread::OnPlanesReadyForPageFlip(
window->SchedulePageFlip(std::move(planes), std::move(submission_callback),
std::move(presentation_callback));
} else {
- std::move(submission_callback).Run(gfx::SwapResult::SWAP_ACK, nullptr);
+ std::move(submission_callback)
+ .Run(gfx::SwapResult::SWAP_ACK,
+ /*release_fence=*/gfx::GpuFenceHandle());
std::move(presentation_callback).Run(gfx::PresentationFeedback::Failure());
}
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_window.cc b/chromium/ui/ozone/platform/drm/gpu/drm_window.cc
index 1218b693ada..0f6ed73c82a 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_window.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_window.cc
@@ -105,7 +105,8 @@ void DrmWindow::SchedulePageFlip(
if (force_buffer_reallocation_) {
force_buffer_reallocation_ = false;
std::move(submission_callback)
- .Run(gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS, nullptr);
+ .Run(gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS,
+ /*release_fence=*/gfx::GpuFenceHandle());
std::move(presentation_callback).Run(gfx::PresentationFeedback::Failure());
return;
}
@@ -113,7 +114,9 @@ void DrmWindow::SchedulePageFlip(
last_submitted_planes_ = DrmOverlayPlane::Clone(planes);
if (!controller_) {
- std::move(submission_callback).Run(gfx::SwapResult::SWAP_ACK, nullptr);
+ std::move(submission_callback)
+ .Run(gfx::SwapResult::SWAP_ACK,
+ /*release_fence=*/gfx::GpuFenceHandle());
std::move(presentation_callback).Run(gfx::PresentationFeedback::Failure());
return;
}
@@ -129,10 +132,6 @@ OverlayStatusList DrmWindow::TestPageFlip(
last_submitted_planes_);
}
-const DrmOverlayPlane* DrmWindow::GetLastModesetBuffer() const {
- return DrmOverlayPlane::GetPrimaryPlane(last_submitted_planes_);
-}
-
void DrmWindow::UpdateCursorImage() {
if (!controller_)
return;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_window.h b/chromium/ui/ozone/platform/drm/gpu/drm_window.h
index 8860f6d0494..13b346bfa10 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_window.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_window.h
@@ -88,8 +88,9 @@ class DrmWindow {
OverlayStatusList TestPageFlip(
const OverlaySurfaceCandidateList& overlay_params);
- // Returns the last buffer associated with this window.
- const DrmOverlayPlane* GetLastModesetBuffer() const;
+ const DrmOverlayPlaneList& last_submitted_planes() const {
+ return last_submitted_planes_;
+ }
private:
// Draw next frame in an animated cursor.
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_window_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/drm_window_unittest.cc
index 9b45a480ebd..9370fc18b6a 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_window_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_window_unittest.cc
@@ -75,8 +75,7 @@ class DrmWindowTest : public testing::Test {
void SetUp() override;
void TearDown() override;
- void OnSubmission(gfx::SwapResult result,
- std::unique_ptr<gfx::GpuFence> out_fence) {
+ void OnSubmission(gfx::SwapResult result, gfx::GpuFenceHandle release_fence) {
last_swap_buffers_result_ = result;
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_overlay_surface.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_overlay_surface.cc
index ffa3f3a2a47..f297291f48e 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_overlay_surface.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_overlay_surface.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/ozone/platform/drm/gpu/drm_overlay_plane.h"
#include "ui/ozone/platform/drm/gpu/drm_window_proxy.h"
#include "ui/ozone/platform/drm/gpu/gbm_pixmap.h"
@@ -67,7 +68,7 @@ void GbmOverlaySurface::SubmitFrame() {
}
void GbmOverlaySurface::OnSubmission(gfx::SwapResult swap_result,
- std::unique_ptr<gfx::GpuFence> out_fence) {
+ gfx::GpuFenceHandle release_fence) {
DCHECK(page_flip_pending_);
DCHECK(have_unsubmitted_frame_);
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_overlay_surface.h b/chromium/ui/ozone/platform/drm/gpu/gbm_overlay_surface.h
index 28a8f3e69e5..8e396f4170b 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_overlay_surface.h
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_overlay_surface.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_OZONE_PLATFORM_DRM_GPU_GBM_GBM_OVERLAY_SURFACE_H_
-#define UI_OZONE_PLATFORM_DRM_GPU_GBM_GBM_OVERLAY_SURFACE_H_
+#ifndef UI_OZONE_PLATFORM_DRM_GPU_GBM_OVERLAY_SURFACE_H_
+#define UI_OZONE_PLATFORM_DRM_GPU_GBM_OVERLAY_SURFACE_H_
#include <memory>
#include <vector>
@@ -45,8 +45,7 @@ class GbmOverlaySurface : public OverlaySurface {
void SubmitFrame();
- void OnSubmission(gfx::SwapResult result,
- std::unique_ptr<gfx::GpuFence> out_fence);
+ void OnSubmission(gfx::SwapResult result, gfx::GpuFenceHandle release_fence);
void OnPresentation(const gfx::PresentationFeedback& presentation_feedback);
const std::unique_ptr<DrmWindowProxy> window_;
@@ -63,4 +62,4 @@ class GbmOverlaySurface : public OverlaySurface {
} // namespace ui
-#endif // UI_OZONE_PLATFORM_DRM_GPU_GBM_GBM_OVERLAY_SURFACE_H_
+#endif // UI_OZONE_PLATFORM_DRM_GPU_GBM_OVERLAY_SURFACE_H_
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.h b/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.h
index 3ada14de4c0..61cafa555f3 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.h
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_OZONE_PLATFORM_DRM_GPU_GBM_BUFFER_H_
-#define UI_OZONE_PLATFORM_DRM_GPU_GBM_BUFFER_H_
+#ifndef UI_OZONE_PLATFORM_DRM_GPU_GBM_PIXMAP_H_
+#define UI_OZONE_PLATFORM_DRM_GPU_GBM_PIXMAP_H_
#include <memory>
#include <vector>
@@ -62,4 +62,4 @@ class GbmPixmap : public gfx::NativePixmap {
} // namespace ui
-#endif // UI_OZONE_PLATFORM_DRM_GPU_GBM_BUFFER_H_
+#endif // UI_OZONE_PLATFORM_DRM_GPU_GBM_PIXMAP_H_
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
index d4ba6cf2727..b61c5bc4774 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
@@ -279,8 +279,7 @@ GLOzone* GbmSurfaceFactory::GetGLOzone(
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanImplementation>
GbmSurfaceFactory::CreateVulkanImplementation(bool use_swiftshader,
- bool allow_protected_memory,
- bool enforce_protected_memory) {
+ bool allow_protected_memory) {
DCHECK(!use_swiftshader)
<< "Vulkan Swiftshader is not supported on this platform.";
return std::make_unique<ui::VulkanImplementationGbm>();
@@ -369,7 +368,7 @@ scoped_refptr<gfx::NativePixmap> GbmSurfaceFactory::CreateNativePixmap(
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- base::Optional<gfx::Size> framebuffer_size) {
+ absl::optional<gfx::Size> framebuffer_size) {
if (framebuffer_size &&
!gfx::Rect(size).Contains(gfx::Rect(*framebuffer_size))) {
return nullptr;
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h
index ab34bda5b20..f6b6d592f15 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h
@@ -40,8 +40,7 @@ class GbmSurfaceFactory : public SurfaceFactoryOzone {
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanImplementation> CreateVulkanImplementation(
bool use_swiftshader,
- bool allow_protected_memory,
- bool enforce_protected_memory) override;
+ bool allow_protected_memory) override;
scoped_refptr<gfx::NativePixmap> CreateNativePixmapForVulkan(
gfx::AcceleratedWidget widget,
gfx::Size size,
@@ -62,7 +61,7 @@ class GbmSurfaceFactory : public SurfaceFactoryOzone {
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- base::Optional<gfx::Size> framebuffer_size = base::nullopt) override;
+ absl::optional<gfx::Size> framebuffer_size = absl::nullopt) override;
void CreateNativePixmapAsync(gfx::AcceleratedWidget widget,
VkDevice vk_device,
gfx::Size size,
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
index 67cb75493b6..1eeedd18ec9 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
@@ -13,7 +13,7 @@
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/trace_event/trace_event.h"
-#include "ui/gfx/gpu_fence.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/gfx/presentation_feedback.h"
#include "ui/gl/gl_bindings.h"
#include "ui/ozone/common/egl_util.h"
@@ -268,7 +268,8 @@ void GbmSurfaceless::SubmitFrame() {
submitted_frame_->ScheduleOverlayPlanes(widget_);
if (!schedule_planes_succeeded) {
- OnSubmission(gfx::SwapResult::SWAP_FAILED, nullptr);
+ OnSubmission(gfx::SwapResult::SWAP_FAILED,
+ /*release_fence=*/gfx::GpuFenceHandle());
OnPresentation(gfx::PresentationFeedback::Failure());
return;
}
@@ -296,7 +297,7 @@ void GbmSurfaceless::FenceRetired(PendingFrame* frame) {
}
void GbmSurfaceless::OnSubmission(gfx::SwapResult result,
- std::unique_ptr<gfx::GpuFence> out_fence) {
+ gfx::GpuFenceHandle release_fence) {
submitted_frame_->swap_result = result;
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.h b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.h
index 153a4e5f343..dd7f3f24cba 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.h
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gl/gl_image.h"
#include "ui/gl/gl_surface_egl.h"
@@ -100,8 +101,7 @@ class GbmSurfaceless : public gl::SurfacelessEGL {
EGLSyncKHR InsertFence(bool implicit);
void FenceRetired(PendingFrame* frame);
- void OnSubmission(gfx::SwapResult result,
- std::unique_ptr<gfx::GpuFence> out_fence);
+ void OnSubmission(gfx::SwapResult result, gfx::GpuFenceHandle release_fence);
void OnPresentation(const gfx::PresentationFeedback& feedback);
GbmSurfaceFactory* const surface_factory_;
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
index 6c4f07658cc..d19b72254ce 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
@@ -19,7 +19,7 @@
#include "third_party/skia/include/core/SkImage.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/gpu_fence.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/gfx/linux/drm_util_linux.h"
#include "ui/gfx/native_pixmap.h"
#include "ui/gfx/presentation_feedback.h"
@@ -76,24 +76,26 @@ HardwareDisplayController::HardwareDisplayController(
HardwareDisplayController::~HardwareDisplayController() = default;
-void HardwareDisplayController::GetModesetProps(CommitRequest* commit_request,
- const DrmOverlayPlane& primary,
- const drmModeModeInfo& mode) {
- GetModesetPropsForCrtcs(commit_request, primary,
+void HardwareDisplayController::GetModesetProps(
+ CommitRequest* commit_request,
+ const DrmOverlayPlaneList& modeset_planes,
+ const drmModeModeInfo& mode) {
+ GetModesetPropsForCrtcs(commit_request, modeset_planes,
/*use_current_crtc_mode=*/false, mode);
}
-void HardwareDisplayController::GetEnableProps(CommitRequest* commit_request,
- const DrmOverlayPlane& primary) {
+void HardwareDisplayController::GetEnableProps(
+ CommitRequest* commit_request,
+ const DrmOverlayPlaneList& modeset_planes) {
// TODO(markyacoub): Simplify and remove the use of empty_mode.
drmModeModeInfo empty_mode = {};
- GetModesetPropsForCrtcs(commit_request, primary,
+ GetModesetPropsForCrtcs(commit_request, modeset_planes,
/*use_current_crtc_mode=*/true, empty_mode);
}
void HardwareDisplayController::GetModesetPropsForCrtcs(
CommitRequest* commit_request,
- const DrmOverlayPlane& primary,
+ const DrmOverlayPlaneList& modeset_planes,
bool use_current_crtc_mode,
const drmModeModeInfo& mode) {
DCHECK(commit_request);
@@ -104,8 +106,7 @@ void HardwareDisplayController::GetModesetPropsForCrtcs(
drmModeModeInfo modeset_mode =
use_current_crtc_mode ? controller->mode() : mode;
- DrmOverlayPlaneList overlays;
- overlays.push_back(primary.Clone());
+ DrmOverlayPlaneList overlays = DrmOverlayPlane::Clone(modeset_planes);
CrtcCommitRequest request = CrtcCommitRequest::EnableCrtcRequest(
controller->crtc(), controller->connector(), modeset_mode, origin_,
@@ -123,14 +124,13 @@ void HardwareDisplayController::GetDisableProps(CommitRequest* commit_request) {
}
void HardwareDisplayController::UpdateState(
- bool enable_requested,
- const DrmOverlayPlane* primary_plane) {
+ const CrtcCommitRequest& crtc_request) {
// Verify that the current state matches the requested state.
- if (enable_requested && IsEnabled()) {
- DCHECK(primary_plane);
+ if (crtc_request.should_enable() && IsEnabled()) {
+ DCHECK(!crtc_request.overlays().empty());
// TODO(markyacoub): This should be absorbed in the commit request.
ResetCursor();
- OnModesetComplete(*primary_plane);
+ OnModesetComplete(crtc_request.overlays());
}
}
@@ -141,10 +141,10 @@ void HardwareDisplayController::SchedulePageFlip(
DCHECK(!page_flip_request_);
scoped_refptr<PageFlipRequest> page_flip_request =
base::MakeRefCounted<PageFlipRequest>(GetRefreshInterval());
- std::unique_ptr<gfx::GpuFence> out_fence;
+ gfx::GpuFenceHandle release_fence;
bool status =
- ScheduleOrTestPageFlip(plane_list, page_flip_request, &out_fence);
+ ScheduleOrTestPageFlip(plane_list, page_flip_request, &release_fence);
if (!status) {
for (const auto& plane : plane_list) {
// If the page flip failed and we see that the buffer has been allocated
@@ -155,7 +155,8 @@ void HardwareDisplayController::SchedulePageFlip(
plane.buffer->modeset_sequence_id_at_allocation() <
plane.buffer->drm_device()->modeset_sequence_id()) {
std::move(submission_callback)
- .Run(gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS, nullptr);
+ .Run(gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS,
+ /*release_fence=*/gfx::GpuFenceHandle());
std::move(presentation_callback)
.Run(gfx::PresentationFeedback::Failure());
return;
@@ -170,13 +171,15 @@ void HardwareDisplayController::SchedulePageFlip(
// able to happen but both CrtcController::AssignOverlayPlanes and
// HardwareDisplayPlaneManagerLegacy::Commit appear to have cases
// where we ACK without actually scheduling a page flip.
- std::move(submission_callback).Run(gfx::SwapResult::SWAP_ACK, nullptr);
+ std::move(submission_callback)
+ .Run(gfx::SwapResult::SWAP_ACK,
+ /*release_fence=*/gfx::GpuFenceHandle());
std::move(presentation_callback).Run(gfx::PresentationFeedback::Failure());
return;
}
std::move(submission_callback)
- .Run(gfx::SwapResult::SWAP_ACK, std::move(out_fence));
+ .Run(gfx::SwapResult::SWAP_ACK, std::move(release_fence));
// Everything was submitted successfully, wait for asynchronous completion.
page_flip_request->TakeCallback(
@@ -194,7 +197,7 @@ bool HardwareDisplayController::TestPageFlip(
bool HardwareDisplayController::ScheduleOrTestPageFlip(
const DrmOverlayPlaneList& plane_list,
scoped_refptr<PageFlipRequest> page_flip_request,
- std::unique_ptr<gfx::GpuFence>* out_fence) {
+ gfx::GpuFenceHandle* release_fence) {
TRACE_EVENT0("drm", "HDC::SchedulePageFlip");
DCHECK(IsEnabled());
@@ -216,7 +219,7 @@ bool HardwareDisplayController::ScheduleOrTestPageFlip(
}
status &= GetDrmDevice()->plane_manager()->Commit(
- &owned_hardware_planes_, page_flip_request, out_fence);
+ &owned_hardware_planes_, page_flip_request, release_fence);
return status;
}
@@ -416,7 +419,7 @@ void HardwareDisplayController::OnPageFlipComplete(
// Only reset the modeset buffer of the crtcs for pageflips that were
// committed after the modeset.
if (modeset_sequence == GetDrmDevice()->modeset_sequence_id()) {
- GetDrmDevice()->plane_manager()->ResetModesetBufferOfCrtc(
+ GetDrmDevice()->plane_manager()->ResetModesetStateForCrtc(
controller->crtc());
}
}
@@ -424,15 +427,14 @@ void HardwareDisplayController::OnPageFlipComplete(
}
void HardwareDisplayController::OnModesetComplete(
- const DrmOverlayPlane& primary) {
- // drmModeSetCrtc has an immediate effect, so we can assume that the current
- // planes have been updated. However if a page flip is still pending, set the
- // pending planes to the same values so that the callback keeps the correct
- // state.
+ const DrmOverlayPlaneList& modeset_planes) {
+ // Modesetting is blocking so it has an immediate effect. We can assume that
+ // the current planes have been updated. However, if a page flip is still
+ // pending, set the pending planes to the same values so that the callback
+ // keeps the correct state.
page_flip_request_ = nullptr;
owned_hardware_planes_.legacy_page_flips.clear();
- current_planes_.clear();
- current_planes_.push_back(primary.Clone());
+ current_planes_ = DrmOverlayPlane::Clone(modeset_planes);
time_of_last_flip_ = base::TimeTicks::Now();
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
index 4cd323a8c39..e92304e4994 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
@@ -10,7 +10,6 @@
#include <xf86drmMode.h>
#include <map>
#include <memory>
-#include <unordered_map>
#include <vector>
#include "base/callback.h"
@@ -26,7 +25,8 @@
namespace gfx {
class Point;
-}
+struct GpuFenceHandle;
+} // namespace gfx
namespace ui {
@@ -98,15 +98,15 @@ class HardwareDisplayController {
// Gets the props required to modeset a CRTC with a |mode| onto
// |commit_request|.
void GetModesetProps(CommitRequest* commit_request,
- const DrmOverlayPlane& primary,
+ const DrmOverlayPlaneList& modeset_planes,
const drmModeModeInfo& mode);
// Gets the props required to enable/disable a CRTC onto |commit_request|.
void GetEnableProps(CommitRequest* commit_request,
- const DrmOverlayPlane& primary);
+ const DrmOverlayPlaneList& modeset_planes);
void GetDisableProps(CommitRequest* commit_request);
// Updates state of the controller after modeset/enable/disable is performed.
- void UpdateState(bool enable_requested, const DrmOverlayPlane* primary_plane);
+ void UpdateState(const CrtcCommitRequest& crtc_request);
// Schedules the |overlays|' framebuffers to be displayed on the next vsync
// event. The event will be posted on the graphics card file descriptor |fd_|
@@ -176,13 +176,13 @@ class HardwareDisplayController {
// Loops over |crtc_controllers_| and save their props into |commit_request|
// to be enabled/modeset.
void GetModesetPropsForCrtcs(CommitRequest* commit_request,
- const DrmOverlayPlane& primary,
+ const DrmOverlayPlaneList& modeset_planes,
bool use_current_crtc_mode,
const drmModeModeInfo& mode);
- void OnModesetComplete(const DrmOverlayPlane& primary);
+ void OnModesetComplete(const DrmOverlayPlaneList& modeset_planes);
bool ScheduleOrTestPageFlip(const DrmOverlayPlaneList& plane_list,
scoped_refptr<PageFlipRequest> page_flip_request,
- std::unique_ptr<gfx::GpuFence>* out_fence);
+ gfx::GpuFenceHandle* release_fence);
void AllocateCursorBuffers();
DrmDumbBuffer* NextCursorBuffer();
void UpdateCursorImage();
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc
index 8a306182295..43c9c793e59 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc
@@ -9,12 +9,14 @@
#include <utility>
#include "base/bind.h"
+#include "base/containers/contains.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/gpu_fence.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/gfx/linux/gbm_buffer.h"
#include "ui/gfx/linux/test/mock_gbm_device.h"
#include "ui/gfx/native_pixmap.h"
@@ -90,7 +92,7 @@ std::unique_ptr<gfx::GpuFence> FakeFenceFD::GetGpuFence() const {
}
void FakeFenceFD::Signal() const {
- base::WriteFileDescriptor(write_fd.get(), "a", 1);
+ base::WriteFileDescriptor(write_fd.get(), "a");
}
class HardwareDisplayControllerTest : public testing::Test {
@@ -104,7 +106,7 @@ class HardwareDisplayControllerTest : public testing::Test {
void InitializeDrmDevice(bool use_atomic);
void SchedulePageFlip(ui::DrmOverlayPlaneList planes);
void OnSubmission(gfx::SwapResult swap_result,
- std::unique_ptr<gfx::GpuFence> out_fence);
+ gfx::GpuFenceHandle release_fence);
void OnPresentation(const gfx::PresentationFeedback& feedback);
uint64_t GetPlanePropertyValue(uint32_t plane,
const std::string& property_name);
@@ -123,7 +125,7 @@ class HardwareDisplayControllerTest : public testing::Test {
}
protected:
- bool ModesetWithPlane(const ui::DrmOverlayPlane& plane);
+ bool ModesetWithPlanes(const ui::DrmOverlayPlaneList& modeset_planes);
bool DisableController();
std::unique_ptr<ui::HardwareDisplayController> controller_;
@@ -211,7 +213,7 @@ void HardwareDisplayControllerTest::InitializeDrmDevice(bool use_atomic) {
plane.properties.push_back(
{/* .id = */ pair.first, /*.value = */ value});
- };
+ }
drm_->SetPropertyBlob(ui::MockDrmDevice::AllocateInFormatsBlob(
kInFormatsBlobPropId, {DRM_FORMAT_XRGB8888}, {}));
@@ -242,16 +244,15 @@ void HardwareDisplayControllerTest::InitializeDrmDevice(bool use_atomic) {
gfx::Point());
}
-bool HardwareDisplayControllerTest::ModesetWithPlane(
- const ui::DrmOverlayPlane& plane) {
+bool HardwareDisplayControllerTest::ModesetWithPlanes(
+ const ui::DrmOverlayPlaneList& modeset_planes) {
ui::CommitRequest commit_request;
- controller_->GetModesetProps(&commit_request, plane, kDefaultMode);
+ controller_->GetModesetProps(&commit_request, modeset_planes, kDefaultMode);
ui::CommitRequest request_for_update = commit_request;
bool status = drm_->plane_manager()->Commit(std::move(commit_request),
DRM_MODE_ATOMIC_ALLOW_MODESET);
- controller_->UpdateState(
- /*enable_requested=*/true,
- ui::DrmOverlayPlane::GetPrimaryPlane(request_for_update[0].overlays()));
+ for (const ui::CrtcCommitRequest& crtc_request : commit_request)
+ controller_->UpdateState(crtc_request);
return status;
}
@@ -262,7 +263,8 @@ bool HardwareDisplayControllerTest::DisableController() {
ui::CommitRequest request_for_update = commit_request;
bool status = drm_->plane_manager()->Commit(std::move(commit_request),
DRM_MODE_ATOMIC_ALLOW_MODESET);
- controller_->UpdateState(/*enable_requested=*/false, nullptr);
+ for (const ui::CrtcCommitRequest& crtc_request : commit_request)
+ controller_->UpdateState(crtc_request);
return status;
}
@@ -279,7 +281,7 @@ void HardwareDisplayControllerTest::SchedulePageFlip(
void HardwareDisplayControllerTest::OnSubmission(
gfx::SwapResult result,
- std::unique_ptr<gfx::GpuFence> out_fence) {
+ gfx::GpuFenceHandle release_fence) {
last_swap_result_ = result;
}
@@ -301,15 +303,18 @@ uint64_t HardwareDisplayControllerTest::GetPlanePropertyValue(
}
TEST_F(HardwareDisplayControllerTest, CheckModesettingResult) {
- ui::DrmOverlayPlane plane(CreateBuffer(), nullptr);
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane));
- EXPECT_FALSE(plane.buffer->HasOneRef());
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
+ EXPECT_FALSE(ui::DrmOverlayPlane::GetPrimaryPlane(modeset_planes)
+ ->buffer->HasOneRef());
}
TEST_F(HardwareDisplayControllerTest, CrtcPropsAfterModeset) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
ui::ScopedDrmObjectPropertyPtr crtc_props =
drm_->GetObjectProperties(kPrimaryCrtc, DRM_MODE_OBJECT_CRTC);
@@ -328,8 +333,9 @@ TEST_F(HardwareDisplayControllerTest, CrtcPropsAfterModeset) {
}
TEST_F(HardwareDisplayControllerTest, ConnectorPropsAfterModeset) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
ui::ScopedDrmObjectPropertyPtr connector_props =
drm_->GetObjectProperties(kConnectorIdBase, DRM_MODE_OBJECT_CONNECTOR);
@@ -343,11 +349,15 @@ TEST_F(HardwareDisplayControllerTest, ConnectorPropsAfterModeset) {
TEST_F(HardwareDisplayControllerTest, PlanePropsAfterModeset) {
const FakeFenceFD fake_fence_fd;
- ui::DrmOverlayPlane plane1(CreateBuffer(), fake_fence_fd.GetGpuFence());
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), fake_fence_fd.GetGpuFence());
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
ui::ScopedDrmObjectPropertyPtr plane_props =
drm_->GetObjectProperties(kPlaneOffset, DRM_MODE_OBJECT_PLANE);
+ const ui::DrmOverlayPlane* primary_plane =
+ ui::DrmOverlayPlane::GetPrimaryPlane(modeset_planes);
+
{
ui::DrmDevice::Property prop = {};
ui::GetDrmPropertyForName(drm_.get(), plane_props.get(), "CRTC_ID", &prop);
@@ -358,13 +368,13 @@ TEST_F(HardwareDisplayControllerTest, PlanePropsAfterModeset) {
ui::DrmDevice::Property prop = {};
ui::GetDrmPropertyForName(drm_.get(), plane_props.get(), "CRTC_X", &prop);
EXPECT_EQ(kCrtcX, prop.id);
- EXPECT_EQ(plane1.display_bounds.x(), static_cast<int>(prop.value));
+ EXPECT_EQ(primary_plane->display_bounds.x(), static_cast<int>(prop.value));
}
{
ui::DrmDevice::Property prop = {};
ui::GetDrmPropertyForName(drm_.get(), plane_props.get(), "CRTC_Y", &prop);
EXPECT_EQ(kCrtcY, prop.id);
- EXPECT_EQ(plane1.display_bounds.y(), static_cast<int>(prop.value));
+ EXPECT_EQ(primary_plane->display_bounds.y(), static_cast<int>(prop.value));
}
{
ui::DrmDevice::Property prop = {};
@@ -382,13 +392,13 @@ TEST_F(HardwareDisplayControllerTest, PlanePropsAfterModeset) {
ui::DrmDevice::Property prop = {};
ui::GetDrmPropertyForName(drm_.get(), plane_props.get(), "FB_ID", &prop);
EXPECT_EQ(kPlaneFbId, prop.id);
- EXPECT_EQ(plane1.buffer->opaque_framebuffer_id(),
+ EXPECT_EQ(primary_plane->buffer->opaque_framebuffer_id(),
static_cast<uint32_t>(prop.value));
}
- gfx::RectF crop_rectf = plane1.crop_rect;
- crop_rectf.Scale(plane1.buffer->size().width(),
- plane1.buffer->size().height());
+ gfx::RectF crop_rectf = primary_plane->crop_rect;
+ crop_rectf.Scale(primary_plane->buffer->size().width(),
+ primary_plane->buffer->size().height());
gfx::Rect crop_rect = gfx::ToNearestRect(crop_rectf);
gfx::Rect fixed_point_rect =
gfx::Rect(crop_rect.x() << 16, crop_rect.y() << 16,
@@ -427,8 +437,10 @@ TEST_F(HardwareDisplayControllerTest, PlanePropsAfterModeset) {
}
TEST_F(HardwareDisplayControllerTest, FenceFdValueChange) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ ui::DrmOverlayPlaneList modeset_planes;
+ ui::DrmOverlayPlane plane(CreateBuffer(), nullptr);
+ modeset_planes.push_back(plane.Clone());
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
// Test invalid fence fd
{
@@ -443,9 +455,9 @@ TEST_F(HardwareDisplayControllerTest, FenceFdValueChange) {
}
const FakeFenceFD fake_fence_fd;
- plane1.gpu_fence = fake_fence_fd.GetGpuFence();
+ plane.gpu_fence = fake_fence_fd.GetGpuFence();
std::vector<ui::DrmOverlayPlane> planes = {};
- planes.push_back(plane1.Clone());
+ planes.push_back(plane.Clone());
SchedulePageFlip(std::move(planes));
// Verify fence FD after a GPU Fence is added to the plane.
@@ -460,8 +472,10 @@ TEST_F(HardwareDisplayControllerTest, FenceFdValueChange) {
static_cast<int>(fence_fd_prop.value));
}
- plane1.gpu_fence = nullptr;
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ plane.gpu_fence = nullptr;
+ modeset_planes.clear();
+ modeset_planes.push_back(plane.Clone());
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
// Test an invalid FD again after the fence is removed.
{
@@ -477,9 +491,9 @@ TEST_F(HardwareDisplayControllerTest, FenceFdValueChange) {
}
TEST_F(HardwareDisplayControllerTest, CheckDisableResetsProps) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
-
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
// Test props values after disabling.
DisableController();
@@ -581,20 +595,21 @@ TEST_F(HardwareDisplayControllerTest, CheckDisableResetsProps) {
}
TEST_F(HardwareDisplayControllerTest, CheckStateAfterPageFlip) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
-
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
EXPECT_EQ(1, drm_->get_commit_count());
- ui::DrmOverlayPlane plane2(CreateBuffer(), nullptr);
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane2.Clone());
+ ui::DrmOverlayPlane page_flip_plane(CreateBuffer(), nullptr);
+ std::vector<ui::DrmOverlayPlane> page_flip_planes;
+ page_flip_planes.push_back(page_flip_plane.Clone());
- SchedulePageFlip(std::move(planes));
+ SchedulePageFlip(std::move(page_flip_planes));
drm_->RunCallbacks();
- EXPECT_TRUE(plane1.buffer->HasOneRef());
- EXPECT_FALSE(plane2.buffer->HasOneRef());
+ EXPECT_TRUE(ui::DrmOverlayPlane::GetPrimaryPlane(modeset_planes)
+ ->buffer->HasOneRef());
+ EXPECT_FALSE(page_flip_plane.buffer->HasOneRef());
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
EXPECT_EQ(1, page_flips_);
@@ -608,24 +623,21 @@ TEST_F(HardwareDisplayControllerTest, CheckStateIfModesetFails) {
InitializeDrmDevice(/* use_atomic */ false);
drm_->set_set_crtc_expectation(false);
- ui::DrmOverlayPlane plane(CreateBuffer(), nullptr);
-
- EXPECT_FALSE(ModesetWithPlane(plane));
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_FALSE(ModesetWithPlanes(modeset_planes));
}
TEST_F(HardwareDisplayControllerTest, CheckOverlayPresent) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- ui::DrmOverlayPlane plane2(
- CreateOverlayBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
- gfx::Rect(kOverlaySize), gfx::RectF(kDefaultModeSizeF), true, nullptr);
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ planes.emplace_back(CreateOverlayBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
+ gfx::Rect(kOverlaySize), gfx::RectF(kDefaultModeSizeF),
+ true, nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ EXPECT_TRUE(ModesetWithPlanes(planes));
EXPECT_EQ(1, drm_->get_commit_count());
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
- planes.push_back(plane2.Clone());
-
SchedulePageFlip(std::move(planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
@@ -637,18 +649,15 @@ TEST_F(HardwareDisplayControllerTest, CheckOverlayPresent) {
}
TEST_F(HardwareDisplayControllerTest, CheckOverlayTestMode) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- ui::DrmOverlayPlane plane2(
- CreateOverlayBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
- gfx::Rect(kOverlaySize), gfx::RectF(kDefaultModeSizeF), true, nullptr);
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ planes.emplace_back(CreateOverlayBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
+ gfx::Rect(kOverlaySize), gfx::RectF(kDefaultModeSizeF),
+ true, nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ EXPECT_TRUE(ModesetWithPlanes(planes));
EXPECT_EQ(1, drm_->get_commit_count());
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
- planes.push_back(plane2.Clone());
-
SchedulePageFlip(ui::DrmOverlayPlane::Clone(planes));
EXPECT_EQ(2, drm_->get_commit_count());
// Verify both planes on the primary display have a valid framebuffer.
@@ -674,16 +683,13 @@ TEST_F(HardwareDisplayControllerTest, CheckOverlayTestMode) {
}
TEST_F(HardwareDisplayControllerTest, AcceptUnderlays) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- ui::DrmOverlayPlane plane2(CreateBuffer(), -1, gfx::OVERLAY_TRANSFORM_NONE,
- gfx::Rect(kDefaultModeSize),
- gfx::RectF(kDefaultModeSizeF), true, nullptr);
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ planes.emplace_back(CreateBuffer(), -1, gfx::OVERLAY_TRANSFORM_NONE,
+ gfx::Rect(kDefaultModeSize),
+ gfx::RectF(kDefaultModeSizeF), true, nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
-
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
- planes.push_back(plane2.Clone());
+ EXPECT_TRUE(ModesetWithPlanes(planes));
SchedulePageFlip(std::move(planes));
drm_->RunCallbacks();
@@ -695,13 +701,12 @@ TEST_F(HardwareDisplayControllerTest, PageflipMirroredControllers) {
controller_->AddCrtc(std::make_unique<ui::CrtcController>(
drm_.get(), kSecondaryCrtc, kConnectorIdBase + 1));
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+
+ EXPECT_TRUE(ModesetWithPlanes(planes));
EXPECT_EQ(1, drm_->get_commit_count());
- ui::DrmOverlayPlane plane2(CreateBuffer(), nullptr);
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane2.Clone());
SchedulePageFlip(std::move(planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
@@ -720,10 +725,10 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterRemoveCrtc) {
controller_->AddCrtc(std::make_unique<ui::CrtcController>(
drm_.get(), kSecondaryCrtc, kConnectorIdBase + 1));
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
+
SchedulePageFlip(ui::DrmOverlayPlane::Clone(planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
@@ -762,10 +767,10 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterRemoveCrtc) {
}
TEST_F(HardwareDisplayControllerTest, PlaneStateAfterDestroyingCrtc) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
+
SchedulePageFlip(std::move(planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
@@ -790,10 +795,10 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterAddCrtc) {
controller_->AddCrtc(std::make_unique<ui::CrtcController>(
drm_.get(), kSecondaryCrtc, kConnectorIdBase + 1));
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
+
SchedulePageFlip(ui::DrmOverlayPlane::Clone(planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
@@ -807,8 +812,7 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterAddCrtc) {
ASSERT_TRUE(primary_crtc_plane != nullptr);
- std::unique_ptr<ui::HardwareDisplayController> hdc_controller;
- hdc_controller = std::make_unique<ui::HardwareDisplayController>(
+ auto hdc_controller = std::make_unique<ui::HardwareDisplayController>(
controller_->RemoveCrtc(drm_, kPrimaryCrtc), controller_->origin());
SchedulePageFlip(ui::DrmOverlayPlane::Clone(planes));
drm_->RunCallbacks();
@@ -835,53 +839,52 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterAddCrtc) {
}
TEST_F(HardwareDisplayControllerTest, ModesetWhilePageFlipping) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
- SchedulePageFlip(std::move(planes));
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
+
+ SchedulePageFlip(ui::DrmOverlayPlane::Clone(planes));
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ EXPECT_TRUE(ModesetWithPlanes(planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
EXPECT_EQ(1, page_flips_);
}
TEST_F(HardwareDisplayControllerTest, FailPageFlipping) {
- ASSERT_TRUE(ModesetWithPlane(ui::DrmOverlayPlane(CreateBuffer(), nullptr)));
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ ASSERT_TRUE(ModesetWithPlanes(modeset_planes));
- drm_->set_commit_expectation(false);
- ui::DrmOverlayPlane post_modeset_plane(CreateBuffer(), nullptr);
+ std::vector<ui::DrmOverlayPlane> page_flip_planes;
+ page_flip_planes.emplace_back(CreateBuffer(), nullptr);
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(post_modeset_plane.Clone());
- EXPECT_DEATH_IF_SUPPORTED(SchedulePageFlip(std::move(planes)),
+ drm_->set_commit_expectation(false);
+ EXPECT_DEATH_IF_SUPPORTED(SchedulePageFlip(std::move(page_flip_planes)),
"SchedulePageFlip failed");
}
TEST_F(HardwareDisplayControllerTest,
RecreateBuffersOnOldPlanesPageFlipFailure) {
- ui::DrmOverlayPlane pre_modeset_plane(CreateBuffer(), nullptr);
- ASSERT_TRUE(ModesetWithPlane(pre_modeset_plane));
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ ASSERT_TRUE(ModesetWithPlanes(planes));
drm_->set_commit_expectation(false);
-
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(pre_modeset_plane.Clone());
SchedulePageFlip(std::move(planes));
EXPECT_EQ(gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS, last_swap_result_);
}
TEST_F(HardwareDisplayControllerTest, CheckNoPrimaryPlaneOnFlip) {
- ui::DrmOverlayPlane modeset_primary_plane(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(modeset_primary_plane));
-
- ui::DrmOverlayPlane plane1(CreateBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
- gfx::Rect(kDefaultModeSize),
- gfx::RectF(0, 0, 1, 1), true, nullptr);
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
- SchedulePageFlip(std::move(planes));
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
+
+ std::vector<ui::DrmOverlayPlane> page_flip_planes;
+ page_flip_planes.emplace_back(CreateBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
+ gfx::Rect(kDefaultModeSize),
+ gfx::RectF(0, 0, 1, 1), true, nullptr);
+ SchedulePageFlip(std::move(page_flip_planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
@@ -889,10 +892,10 @@ TEST_F(HardwareDisplayControllerTest, CheckNoPrimaryPlaneOnFlip) {
}
TEST_F(HardwareDisplayControllerTest, AddCrtcMidPageFlip) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
+
SchedulePageFlip(std::move(planes));
controller_->AddCrtc(std::make_unique<ui::CrtcController>(
@@ -904,10 +907,10 @@ TEST_F(HardwareDisplayControllerTest, AddCrtcMidPageFlip) {
}
TEST_F(HardwareDisplayControllerTest, RemoveCrtcMidPageFlip) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
+
SchedulePageFlip(std::move(planes));
controller_->RemoveCrtc(drm_, kPrimaryCrtc);
@@ -921,16 +924,13 @@ TEST_F(HardwareDisplayControllerTest, Disable) {
// Page flipping overlays is only supported on atomic configurations.
InitializeDrmDevice(/* use_atomic= */ true);
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
-
- ui::DrmOverlayPlane plane2(
- CreateOverlayBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
- gfx::Rect(kOverlaySize), gfx::RectF(kDefaultModeSizeF), true, nullptr);
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
- planes.push_back(plane2.Clone());
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
+ planes.emplace_back(CreateOverlayBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
+ gfx::Rect(kOverlaySize), gfx::RectF(kDefaultModeSizeF),
+ true, nullptr);
SchedulePageFlip(std::move(planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
@@ -947,49 +947,70 @@ TEST_F(HardwareDisplayControllerTest, Disable) {
}
TEST_F(HardwareDisplayControllerTest, PageflipAfterModeset) {
+ ui::DrmOverlayPlaneList planes;
scoped_refptr<ui::DrmFramebuffer> buffer = CreateBuffer();
- ui::DrmOverlayPlane plane1(buffer, nullptr);
-
- ModesetWithPlane(plane1);
+ planes.emplace_back(buffer, nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
- EXPECT_EQ(drm_->plane_manager()
- ->GetCrtcStateForCrtcId(kPrimaryCrtc)
- .modeset_framebuffer,
- buffer);
+ for (const auto& plane : planes) {
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ plane.buffer));
+ }
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
SchedulePageFlip(std::move(planes));
drm_->RunCallbacks();
- // modeset_framebuffer should be cleared after the pageflip is complete.
- EXPECT_EQ(drm_->plane_manager()
- ->GetCrtcStateForCrtcId(kPrimaryCrtc)
- .modeset_framebuffer,
- nullptr);
+ // modeset_framebuffers should be cleared after the pageflip is complete.
+ EXPECT_TRUE(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers.empty());
}
TEST_F(HardwareDisplayControllerTest, PageflipBeforeModeset) {
+ ui::DrmOverlayPlaneList planes;
scoped_refptr<ui::DrmFramebuffer> buffer = CreateBuffer();
- ui::DrmOverlayPlane plane1(buffer, nullptr);
-
- EXPECT_TRUE(ModesetWithPlane(ui::DrmOverlayPlane(CreateBuffer(), nullptr)));
+ planes.emplace_back(buffer, nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
- SchedulePageFlip(std::move(planes));
+ SchedulePageFlip(ui::DrmOverlayPlane::Clone(planes));
- EXPECT_TRUE(ModesetWithPlane(plane1));
- EXPECT_EQ(drm_->plane_manager()
- ->GetCrtcStateForCrtcId(kPrimaryCrtc)
- .modeset_framebuffer,
- buffer);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
+ for (const auto& plane : planes) {
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ plane.buffer));
+ }
- // modeset_framebuffer should not be cleared when a pageflip callback is run
+ // modeset_framebuffers should not be cleared when a pageflip callback is run
// after a modeset
drm_->RunCallbacks();
+ EXPECT_FALSE(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers.empty());
+ for (const auto& plane : planes) {
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ plane.buffer));
+ }
+}
+
+TEST_F(HardwareDisplayControllerTest, MultiplePlanesModeset) {
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ ASSERT_TRUE(ModesetWithPlanes(modeset_planes));
EXPECT_EQ(drm_->plane_manager()
->GetCrtcStateForCrtcId(kPrimaryCrtc)
- .modeset_framebuffer,
- buffer);
+ .modeset_framebuffers.size(),
+ 2UL);
+ for (const auto& plane : modeset_planes) {
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ plane.buffer));
+ }
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
index 634fb042481..448cfa9a14b 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
@@ -459,8 +459,10 @@ void HardwareDisplayPlaneManager::UpdateCrtcAndPlaneStatesAfterModeset(
if (is_enabled) {
crtc_state.mode = crtc_request.mode();
- crtc_state.modeset_framebuffer =
- DrmOverlayPlane::GetPrimaryPlane(crtc_request.overlays())->buffer;
+ crtc_state.modeset_framebuffers.clear();
+ for (const auto& overlay : crtc_request.overlays())
+ crtc_state.modeset_framebuffers.push_back(overlay.buffer);
+
} else {
if (crtc_request.plane_list())
disable_planes_lists.insert(crtc_request.plane_list());
@@ -483,9 +485,9 @@ void HardwareDisplayPlaneManager::UpdateCrtcAndPlaneStatesAfterModeset(
}
}
-void HardwareDisplayPlaneManager::ResetModesetBufferOfCrtc(uint32_t crtc_id) {
+void HardwareDisplayPlaneManager::ResetModesetStateForCrtc(uint32_t crtc_id) {
CrtcState& crtc_state = CrtcStateForCrtcId(crtc_id);
- crtc_state.modeset_framebuffer = nullptr;
+ crtc_state.modeset_framebuffers.clear();
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
index a4593292e8d..4c6bfd39cdc 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
@@ -20,8 +20,8 @@
#include "ui/ozone/public/swap_completion_callback.h"
namespace gfx {
-class GpuFence;
class Rect;
+struct GpuFenceHandle;
} // namespace gfx
namespace ui {
@@ -82,7 +82,7 @@ class HardwareDisplayPlaneManager {
CrtcState(CrtcState&&);
drmModeModeInfo mode = {};
- scoped_refptr<DrmFramebuffer> modeset_framebuffer;
+ std::vector<scoped_refptr<DrmFramebuffer>> modeset_framebuffers;
CrtcProperties properties = {};
@@ -141,7 +141,7 @@ class HardwareDisplayPlaneManager {
// if the system doesn't support out fences.
virtual bool Commit(HardwareDisplayPlaneList* plane_list,
scoped_refptr<PageFlipRequest> page_flip_request,
- std::unique_ptr<gfx::GpuFence>* out_fence) = 0;
+ gfx::GpuFenceHandle* release_fence) = 0;
// Disable all the overlay planes previously submitted and now stored in
// plane_list->old_plane_list.
@@ -187,7 +187,7 @@ class HardwareDisplayPlaneManager {
// which resources needed to be tracked internally in
// HardwareDisplayPlaneManager and which should be taken care of by the
// caller.
- void ResetModesetBufferOfCrtc(uint32_t crtc_id);
+ void ResetModesetStateForCrtc(uint32_t crtc_id);
protected:
struct ConnectorProperties {
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
index 3b8c3eec755..6a6f6609f07 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
@@ -30,7 +30,7 @@ namespace ui {
namespace {
-std::unique_ptr<gfx::GpuFence> CreateMergedGpuFenceFromFDs(
+gfx::GpuFenceHandle CreateMergedGpuFenceFromFDs(
std::vector<base::ScopedFD> fence_fds) {
base::ScopedFD merged_fd;
@@ -43,13 +43,11 @@ std::unique_ptr<gfx::GpuFence> CreateMergedGpuFenceFromFDs(
}
}
- if (merged_fd.is_valid()) {
- gfx::GpuFenceHandle handle;
+ gfx::GpuFenceHandle handle;
+ if (merged_fd.is_valid())
handle.owned_fd = std::move(merged_fd);
- return std::make_unique<gfx::GpuFence>(std::move(handle));
- }
- return nullptr;
+ return handle;
}
std::vector<uint32_t> GetCrtcIdsOfPlanes(
@@ -142,8 +140,11 @@ bool HardwareDisplayPlaneManagerAtomic::Commit(CommitRequest commit_request,
if (crtc_request.should_enable()) {
DCHECK(crtc_request.plane_list());
- status &= AssignOverlayPlanes(crtc_request.plane_list(),
- crtc_request.overlays(), crtc_id);
+ if (!AssignOverlayPlanes(crtc_request.plane_list(),
+ crtc_request.overlays(), crtc_id)) {
+ LOG_IF(ERROR, !is_testing) << "Failed to Assign Overlay Planes";
+ status = false;
+ }
enable_planes_lists.insert(crtc_request.plane_list());
}
}
@@ -245,7 +246,7 @@ void HardwareDisplayPlaneManagerAtomic::SetAtomicPropsForCommit(
bool HardwareDisplayPlaneManagerAtomic::Commit(
HardwareDisplayPlaneList* plane_list,
scoped_refptr<PageFlipRequest> page_flip_request,
- std::unique_ptr<gfx::GpuFence>* out_fence) {
+ gfx::GpuFenceHandle* release_fence) {
bool test_only = !page_flip_request;
std::vector<uint32_t> crtcs = GetCrtcIdsOfPlanes(*plane_list);
@@ -263,7 +264,7 @@ bool HardwareDisplayPlaneManagerAtomic::Commit(
std::vector<base::ScopedFD> out_fence_fds;
{
std::vector<base::ScopedFD::Receiver> out_fence_fd_receivers;
- if (out_fence) {
+ if (release_fence) {
if (!AddOutFencePtrProperties(plane_list->atomic_property_set.get(),
crtcs, &out_fence_fds,
&out_fence_fd_receivers)) {
@@ -288,8 +289,8 @@ bool HardwareDisplayPlaneManagerAtomic::Commit(
}
}
- if (out_fence)
- *out_fence = CreateMergedGpuFenceFromFDs(std::move(out_fence_fds));
+ if (release_fence)
+ *release_fence = CreateMergedGpuFenceFromFDs(std::move(out_fence_fds));
plane_list->plane_list.clear();
plane_list->atomic_property_set.reset(drmModeAtomicAlloc());
@@ -365,7 +366,7 @@ void HardwareDisplayPlaneManagerAtomic::RequestPlanesReadyCallback(
}
bool HardwareDisplayPlaneManagerAtomic::SetPlaneData(
- HardwareDisplayPlaneList* plane_list,
+ HardwareDisplayPlaneList*,
HardwareDisplayPlane* hw_plane,
const DrmOverlayPlane& overlay,
uint32_t crtc_id,
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h
index 6de61131a8e..76ef7b4e2c8 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h
@@ -9,6 +9,7 @@
#include <memory>
#include "base/macros.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
namespace ui {
@@ -23,7 +24,7 @@ class HardwareDisplayPlaneManagerAtomic : public HardwareDisplayPlaneManager {
bool Commit(HardwareDisplayPlaneList* plane_list,
scoped_refptr<PageFlipRequest> page_flip_request,
- std::unique_ptr<gfx::GpuFence>* out_fence) override;
+ gfx::GpuFenceHandle* release_fence) override;
bool DisableOverlayPlanes(HardwareDisplayPlaneList* plane_list) override;
bool SetColorCorrectionOnAllCrtcPlanes(
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
index c79705063a5..a4587a7f339 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
@@ -77,7 +77,7 @@ bool HardwareDisplayPlaneManagerLegacy::Commit(CommitRequest commit_request,
bool HardwareDisplayPlaneManagerLegacy::Commit(
HardwareDisplayPlaneList* plane_list,
scoped_refptr<PageFlipRequest> page_flip_request,
- std::unique_ptr<gfx::GpuFence>* out_fence) {
+ gfx::GpuFenceHandle* release_fence) {
bool test_only = !page_flip_request;
if (test_only) {
for (HardwareDisplayPlane* plane : plane_list->plane_list) {
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h
index 8fffbc28bf2..9576c5dde47 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h
@@ -6,11 +6,14 @@
#define UI_OZONE_PLATFORM_DRM_GPU_HARDWARE_DISPLAY_PLANE_MANAGER_LEGACY_H_
#include <stdint.h>
-#include <memory>
#include "base/macros.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
+namespace gfx {
+struct GpuFenceHandle;
+} // namespace gfx
+
namespace ui {
class HardwareDisplayPlaneManagerLegacy : public HardwareDisplayPlaneManager {
@@ -23,7 +26,7 @@ class HardwareDisplayPlaneManagerLegacy : public HardwareDisplayPlaneManager {
bool Commit(HardwareDisplayPlaneList* plane_list,
scoped_refptr<PageFlipRequest> page_flip_request,
- std::unique_ptr<gfx::GpuFence>* out_fence) override;
+ gfx::GpuFenceHandle* release_fence) override;
bool DisableOverlayPlanes(HardwareDisplayPlaneList* plane_list) override;
bool SetColorCorrectionOnAllCrtcPlanes(
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
index 1f23be53932..cd01a6cecbd 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
@@ -187,7 +187,7 @@ void HardwareDisplayPlaneManagerTest::InitializeDrmState(
}
plane_prop.properties.push_back(
{/* .id = */ pair.first, /* .value = */ value});
- };
+ }
plane_properties_.emplace_back(std::move(plane_prop));
}
@@ -1118,10 +1118,10 @@ TEST_P(HardwareDisplayPlaneManagerAtomicTest,
scoped_refptr<ui::PageFlipRequest> page_flip_request =
base::MakeRefCounted<ui::PageFlipRequest>(base::TimeDelta());
- std::unique_ptr<gfx::GpuFence> out_fence;
+ gfx::GpuFenceHandle release_fence;
EXPECT_TRUE(fake_drm_->plane_manager()->Commit(&state_, page_flip_request,
- &out_fence));
- EXPECT_EQ(nullptr, out_fence);
+ &release_fence));
+ EXPECT_TRUE(release_fence.is_null());
}
TEST_P(HardwareDisplayPlaneManagerTest,
@@ -1213,7 +1213,7 @@ std::unique_ptr<gfx::GpuFence> FakeFenceFD::GetGpuFence() const {
}
void FakeFenceFD::Signal() const {
- base::WriteFileDescriptor(write_fd.get(), "a", 1);
+ base::WriteFileDescriptor(write_fd.get(), "a");
}
class HardwareDisplayPlaneManagerPlanesReadyTest : public testing::Test {
@@ -1357,11 +1357,11 @@ TEST_P(HardwareDisplayPlaneManagerAtomicTest, OverlaySourceCrop) {
EXPECT_TRUE(fake_drm_->plane_manager()->AssignOverlayPlanes(
&state_, assigns, crtc_properties_[0].id));
- std::unique_ptr<gfx::GpuFence> out_fence;
+ gfx::GpuFenceHandle release_fence;
scoped_refptr<ui::PageFlipRequest> page_flip_request =
base::MakeRefCounted<ui::PageFlipRequest>(base::TimeDelta());
EXPECT_TRUE(fake_drm_->plane_manager()->Commit(&state_, page_flip_request,
- &out_fence));
+ &release_fence));
EXPECT_EQ(2u << 16, GetPlanePropertyValue(kPlaneOffset, "SRC_W"));
EXPECT_EQ(2u << 16, GetPlanePropertyValue(kPlaneOffset, "SRC_H"));
@@ -1380,9 +1380,9 @@ TEST_P(HardwareDisplayPlaneManagerAtomicTest, OverlaySourceCrop) {
scoped_refptr<ui::PageFlipRequest> page_flip_request =
base::MakeRefCounted<ui::PageFlipRequest>(base::TimeDelta());
- std::unique_ptr<gfx::GpuFence> out_fence;
+ gfx::GpuFenceHandle release_fence;
EXPECT_TRUE(fake_drm_->plane_manager()->Commit(&state_, page_flip_request,
- &out_fence));
+ &release_fence));
EXPECT_EQ(1u << 16, GetPlanePropertyValue(kPlaneOffset, "SRC_W"));
EXPECT_EQ(2u << 16, GetPlanePropertyValue(kPlaneOffset, "SRC_H"));
@@ -1401,9 +1401,9 @@ TEST_P(HardwareDisplayPlaneManagerAtomicTest, OverlaySourceCrop) {
scoped_refptr<ui::PageFlipRequest> page_flip_request =
base::MakeRefCounted<ui::PageFlipRequest>(base::TimeDelta());
- std::unique_ptr<gfx::GpuFence> out_fence;
+ gfx::GpuFenceHandle release_fence;
EXPECT_TRUE(fake_drm_->plane_manager()->Commit(&state_, page_flip_request,
- &out_fence));
+ &release_fence));
EXPECT_EQ(2u << 16, GetPlanePropertyValue(kPlaneOffset, "SRC_W"));
EXPECT_EQ(1u << 16, GetPlanePropertyValue(kPlaneOffset, "SRC_H"));
diff --git a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
index fe24499014c..1ef0fe9f11f 100644
--- a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
@@ -10,6 +10,7 @@
#include "base/check.h"
#include "base/containers/contains.h"
+#include "base/containers/flat_map.h"
#include "base/logging.h"
#include "skia/ext/legacy_display_globals.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -181,6 +182,24 @@ void MockDrmDevice::UpdateState(
connector_properties_ = connector_properties;
plane_properties_ = plane_properties;
property_names_ = property_names;
+
+ // Props IDs shouldn't change throughout a DRM state. Grab it once at
+ // UpdateState.
+ plane_crtc_id_prop_id_ = 0;
+ for (const PlaneProperties& plane_props : plane_properties) {
+ const std::vector<DrmDevice::Property>& props = plane_props.properties;
+ auto it = std::find_if(
+ props.begin(), props.end(),
+ [&names = property_names_](const DrmDevice::Property& prop) {
+ return names.at(prop.id) == "CRTC_ID";
+ });
+ if (it != props.end()) {
+ plane_crtc_id_prop_id_ = it->id;
+ // all planes should have the same prop ID for the name. Break right after
+ // the first one is found.
+ break;
+ }
+ }
}
void MockDrmDevice::SetModifiersOverhead(
@@ -468,8 +487,10 @@ bool MockDrmDevice::CommitPropertiesInternal(
}
uint64_t requested_resources = 0;
+ base::flat_map<uint64_t, int> crtc_planes_counter;
+
for (uint32_t i = 0; i < request->cursor; ++i) {
- const auto& item = request->items[i];
+ const drmModeAtomicReqItem& item = request->items[i];
if (!ValidatePropertyValue(item.property_id, item.value))
return false;
@@ -477,6 +498,12 @@ bool MockDrmDevice::CommitPropertiesInternal(
const FramebufferProps& props = fb_props_[item.value];
requested_resources += modifiers_overhead_[props.modifier];
}
+
+ if (item.property_id == plane_crtc_id_prop_id_) {
+ if (++crtc_planes_counter[item.value] > 1 &&
+ !modeset_with_overlays_expectation_)
+ return false;
+ }
}
if (requested_resources > system_watermark_limitations_) {
@@ -500,6 +527,12 @@ bool MockDrmDevice::CommitPropertiesInternal(
return false;
}
+ // Count all committed planes at the end just before returning true to reflect
+ // the number of planes that have successfully been committed.
+ last_planes_committed_count_ = 0;
+ for (const auto& planes_counter : crtc_planes_counter)
+ last_planes_committed_count_ += planes_counter.second;
+
return true;
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h
index bdf09aa3b5c..0c2d823f12a 100644
--- a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h
+++ b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h
@@ -92,11 +92,18 @@ class MockDrmDevice : public DrmDevice {
legacy_gamma_ramp_expectation_ = state;
}
void set_commit_expectation(bool state) { commit_expectation_ = state; }
+ void set_overlay_modeset_expecation(bool state) {
+ modeset_with_overlays_expectation_ = state;
+ }
uint32_t current_framebuffer() const { return current_framebuffer_; }
const std::vector<sk_sp<SkSurface>> buffers() const { return buffers_; }
+ int last_planes_committed_count() const {
+ return last_planes_committed_count_;
+ }
+
uint32_t get_cursor_handle_for_crtc(uint32_t crtc) const {
const auto it = crtc_cursor_map_.find(crtc);
return it != crtc_cursor_map_.end() ? it->second : 0;
@@ -224,6 +231,7 @@ class MockDrmDevice : public DrmDevice {
int commit_count_ = 0;
int set_object_property_count_ = 0;
int set_gamma_ramp_count_ = 0;
+ int last_planes_committed_count_ = 0;
bool set_crtc_expectation_;
bool add_framebuffer_expectation_;
@@ -231,8 +239,10 @@ class MockDrmDevice : public DrmDevice {
bool create_dumb_buffer_expectation_;
bool legacy_gamma_ramp_expectation_ = false;
bool commit_expectation_ = true;
+ bool modeset_with_overlays_expectation_ = true;
uint32_t current_framebuffer_;
+ uint32_t plane_crtc_id_prop_id_ = 0;
std::vector<sk_sp<SkSurface>> buffers_;
diff --git a/chromium/ui/ozone/platform/drm/gpu/page_flip_request.h b/chromium/ui/ozone/platform/drm/gpu/page_flip_request.h
index d24d6bbc0da..c7fb160a604 100644
--- a/chromium/ui/ozone/platform/drm/gpu/page_flip_request.h
+++ b/chromium/ui/ozone/platform/drm/gpu/page_flip_request.h
@@ -5,7 +5,6 @@
#ifndef UI_OZONE_PLATFORM_DRM_GPU_PAGE_FLIP_REQUEST_H_
#define UI_OZONE_PLATFORM_DRM_GPU_PAGE_FLIP_REQUEST_H_
-#include <memory>
#include "base/atomic_ref_count.h"
#include "base/callback.h"
diff --git a/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc b/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc
index e54b8cf58d0..c28ce60d075 100644
--- a/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc
@@ -234,8 +234,14 @@ bool ScreenManager::ConfigureDisplayControllers(
// Perform display configurations together for the same DRM only.
for (const auto& configs_on_drm : displays_for_drm_devices) {
const ControllerConfigsList& controllers_params = configs_on_drm.second;
- config_success &=
- TestModeset(controllers_params) && Modeset(controllers_params);
+ bool test_modeset = TestAndSetPreferredModifiers(controllers_params) ||
+ TestAndSetLinearModifier(controllers_params);
+ config_success &= test_modeset;
+ if (!test_modeset)
+ continue;
+ bool can_modeset_with_overlays =
+ TestModesetWithOverlays(controllers_params);
+ config_success &= Modeset(controllers_params, can_modeset_with_overlays);
}
if (config_success)
@@ -244,12 +250,6 @@ bool ScreenManager::ConfigureDisplayControllers(
return config_success;
}
-bool ScreenManager::TestModeset(
- const ControllerConfigsList& controllers_params) {
- return TestAndSetPreferredModifiers(controllers_params) ||
- TestAndSetLinearModifier(controllers_params);
-}
-
bool ScreenManager::TestAndSetPreferredModifiers(
const ControllerConfigsList& controllers_params) {
TRACE_EVENT1("drm", "ScreenManager::TestAndSetPreferredModifiers",
@@ -269,19 +269,21 @@ bool ScreenManager::TestAndSetPreferredModifiers(
display::DisplaySnapshot::PrimaryFormat());
std::vector<uint64_t> modifiers =
controller->GetFormatModifiersForTestModeset(fourcc_format);
-
- DrmOverlayPlane primary_plane = GetModesetBuffer(
+ // Test with no overlays to go for a lower bandwidth usage.
+ DrmOverlayPlaneList modeset_planes = GetModesetPlanes(
controller, gfx::Rect(params.origin, ModeSize(*params.mode)),
- modifiers, /*is_testing=*/true);
- if (!primary_plane.buffer) {
+ modifiers, /*include_overlays=*/false, /*is_testing=*/true);
+ if (modeset_planes.empty())
return false;
- }
- crtcs_preferred_modifier[params.crtc] = std::make_pair(
- modifiers.empty(), primary_plane.buffer->format_modifier());
+ uint64_t primary_modifier =
+ DrmOverlayPlane::GetPrimaryPlane(modeset_planes)
+ ->buffer->format_modifier();
+ crtcs_preferred_modifier[params.crtc] =
+ std::make_pair(modifiers.empty(), primary_modifier);
GetModesetControllerProps(&commit_request, controller, params.origin,
- *params.mode, primary_plane);
+ *params.mode, modeset_planes);
} else {
controller->GetDisableProps(&commit_request);
}
@@ -325,14 +327,15 @@ bool ScreenManager::TestAndSetLinearModifier(
std::make_pair(modifiers.empty(), DRM_FORMAT_MOD_LINEAR);
if (params.mode) {
- DrmOverlayPlane primary_plane = GetModesetBuffer(
+ // Test with no overlays to go for a lower bandwidth usage.
+ DrmOverlayPlaneList modeset_planes = GetModesetPlanes(
controller, gfx::Rect(params.origin, ModeSize(*params.mode)),
- modifiers, /*is_testing=*/true);
- if (!primary_plane.buffer)
+ modifiers, /*include_overlays=*/false, /*is_testing=*/true);
+ if (modeset_planes.empty())
return false;
GetModesetControllerProps(&commit_request, controller, params.origin,
- *params.mode, primary_plane);
+ *params.mode, modeset_planes);
} else {
controller->GetDisableProps(&commit_request);
}
@@ -370,10 +373,54 @@ void ScreenManager::SetPreferredModifiers(
}
}
-bool ScreenManager::Modeset(const ControllerConfigsList& controllers_params) {
- TRACE_EVENT1("drm", "ScreenManager::Modeset", "display_count",
+bool ScreenManager::TestModesetWithOverlays(
+ const ControllerConfigsList& controllers_params) {
+ TRACE_EVENT1("drm", "ScreenManager::TestModesetWithOverlays", "display_count",
controllers_params.size());
+ bool does_an_overlay_exist = false;
+
+ CommitRequest commit_request;
+ auto drm = controllers_params[0].drm;
+ for (const auto& params : controllers_params) {
+ auto it = FindDisplayController(params.drm, params.crtc);
+ DCHECK(controllers_.end() != it);
+ HardwareDisplayController* controller = it->get();
+
+ if (params.mode) {
+ uint32_t fourcc_format = GetFourCCFormatForOpaqueFramebuffer(
+ display::DisplaySnapshot::PrimaryFormat());
+ std::vector<uint64_t> modifiers =
+ controller->GetSupportedModifiers(fourcc_format);
+
+ DrmOverlayPlaneList modeset_planes = GetModesetPlanes(
+ controller, gfx::Rect(params.origin, ModeSize(*params.mode)),
+ modifiers, /*include_overlays=*/true, /*is_testing=*/true);
+ DCHECK(!modeset_planes.empty());
+ does_an_overlay_exist |= modeset_planes.size() > 1;
+
+ GetModesetControllerProps(&commit_request, controller, params.origin,
+ *params.mode, modeset_planes);
+ } else {
+ controller->GetDisableProps(&commit_request);
+ }
+ }
+ // If we have no overlays, report not modesetting with overlays as we haven't
+ // tested with overlays.
+ if (!does_an_overlay_exist)
+ return false;
+
+ return drm->plane_manager()->Commit(
+ std::move(commit_request),
+ DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET);
+}
+
+bool ScreenManager::Modeset(const ControllerConfigsList& controllers_params,
+ bool can_modeset_with_overlays) {
+ TRACE_EVENT2("drm", "ScreenManager::Modeset", "display_count",
+ controllers_params.size(), "modeset_with_overlays",
+ can_modeset_with_overlays);
+
CommitRequest commit_request;
auto drm = controllers_params[0].drm;
@@ -387,15 +434,15 @@ bool ScreenManager::Modeset(const ControllerConfigsList& controllers_params) {
display::DisplaySnapshot::PrimaryFormat());
std::vector<uint64_t> modifiers =
controller->GetSupportedModifiers(fourcc_format, /*is_modeset=*/true);
- DrmOverlayPlane primary_plane = GetModesetBuffer(
- controller, gfx::Rect(params.origin, ModeSize(*params.mode)),
- modifiers, /*is_testing=*/false);
- if (!primary_plane.buffer)
- return false;
+
+ gfx::Rect bounds = gfx::Rect(params.origin, ModeSize(*params.mode));
+ DrmOverlayPlaneList modeset_planes =
+ GetModesetPlanes(controller, bounds, modifiers,
+ can_modeset_with_overlays, /*is_testing=*/false);
SetDisplayControllerForEnableAndGetProps(
&commit_request, params.drm, params.crtc, params.connector,
- params.origin, *params.mode, primary_plane);
+ params.origin, *params.mode, modeset_planes);
} else {
bool disable_set = SetDisableDisplayControllerForDisableAndGetProps(
@@ -420,7 +467,7 @@ void ScreenManager::SetDisplayControllerForEnableAndGetProps(
uint32_t connector,
const gfx::Point& origin,
const drmModeModeInfo& mode,
- const DrmOverlayPlane& primary) {
+ const DrmOverlayPlaneList& modeset_planes) {
HardwareDisplayControllers::iterator it = FindDisplayController(drm, crtc);
DCHECK(controllers_.end() != it)
<< "Display controller (crtc=" << crtc << ") doesn't exist.";
@@ -437,10 +484,10 @@ void ScreenManager::SetDisplayControllerForEnableAndGetProps(
// Otherwise it could apply a mode with the same resolution and refresh
// rate but with different timings to the other CRTC.
GetModesetControllerProps(commit_request, controller,
- controller->origin(), mode, primary);
+ controller->origin(), mode, modeset_planes);
} else {
// Just get props to re-enable the controller re-using the current state.
- GetEnableControllerProps(commit_request, controller, primary);
+ GetEnableControllerProps(commit_request, controller, modeset_planes);
}
return;
}
@@ -456,7 +503,8 @@ void ScreenManager::SetDisplayControllerForEnableAndGetProps(
controller = it->get();
}
- GetModesetControllerProps(commit_request, controller, origin, mode, primary);
+ GetModesetControllerProps(commit_request, controller, origin, mode,
+ modeset_planes);
}
bool ScreenManager::SetDisableDisplayControllerForDisableAndGetProps(
@@ -490,8 +538,7 @@ void ScreenManager::UpdateControllerStateAfterModeset(
HardwareDisplayControllers::iterator it =
FindDisplayController(drm, crtc_request.crtc_id());
if (it != controllers_.end()) {
- it->get()->UpdateState(was_enabled, DrmOverlayPlane::GetPrimaryPlane(
- crtc_request.overlays()));
+ it->get()->UpdateState(crtc_request);
// If the CRTC is mirrored, move it to the mirror controller.
if (did_succeed && was_enabled)
@@ -626,24 +673,25 @@ void ScreenManager::UpdateControllerToWindowMapping() {
display::DisplaySnapshot::PrimaryFormat());
std::vector<uint64_t> modifiers =
controller->GetSupportedModifiers(fourcc_format);
- DrmOverlayPlane primary_plane = GetModesetBuffer(
+ DrmOverlayPlaneList modeset_planes = GetModesetPlanes(
controller,
gfx::Rect(controller->origin(), controller->GetModeSize()), modifiers,
- /*is_testing=*/false);
- DCHECK(primary_plane.buffer);
+ /*include_overlays=*/true, /*is_testing=*/false);
+ DCHECK(!modeset_planes.empty());
CommitRequest commit_request;
- GetEnableControllerProps(&commit_request, controller, primary_plane);
+ GetEnableControllerProps(&commit_request, controller, modeset_planes);
controller->GetDrmDevice()->plane_manager()->Commit(
std::move(commit_request), DRM_MODE_ATOMIC_ALLOW_MODESET);
}
}
}
-DrmOverlayPlane ScreenManager::GetModesetBuffer(
+DrmOverlayPlaneList ScreenManager::GetModesetPlanes(
HardwareDisplayController* controller,
const gfx::Rect& bounds,
const std::vector<uint64_t>& modifiers,
+ bool include_overlays,
bool is_testing) {
scoped_refptr<DrmDevice> drm = controller->GetDrmDevice();
uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer(
@@ -655,19 +703,27 @@ DrmOverlayPlane ScreenManager::GetModesetBuffer(
fourcc_format, bounds.size(), GBM_BO_USE_SCANOUT, modifiers);
if (!buffer) {
LOG(ERROR) << "Failed to create scanout buffer";
- return DrmOverlayPlane::Error();
+ return DrmOverlayPlaneList();
}
// If the current primary plane matches what we need for the next page flip,
- // we can clone it.
+ // clone all last_submitted_planes (matching primary + overlays).
DrmWindow* window = FindWindowAt(bounds);
if (window) {
- const DrmOverlayPlane* primary = window->GetLastModesetBuffer();
- const DrmDevice* drm = controller->GetDrmDevice().get();
+ const DrmOverlayPlaneList& last_submitted_planes =
+ window->last_submitted_planes();
+ const DrmOverlayPlane* primary =
+ DrmOverlayPlane::GetPrimaryPlane(last_submitted_planes);
if (primary && primary->buffer->size() == bounds.size() &&
- primary->buffer->drm_device() == drm) {
- if (primary->buffer->format_modifier() == buffer->GetFormatModifier())
- return primary->Clone();
+ primary->buffer->drm_device() == controller->GetDrmDevice().get() &&
+ primary->buffer->format_modifier() == buffer->GetFormatModifier()) {
+ if (include_overlays) {
+ return DrmOverlayPlane::Clone(last_submitted_planes);
+ } else {
+ DrmOverlayPlaneList modeset_plane;
+ modeset_plane.push_back(primary->Clone());
+ return modeset_plane;
+ }
}
}
@@ -675,7 +731,7 @@ DrmOverlayPlane ScreenManager::GetModesetBuffer(
drm, buffer.get(), buffer->GetSize(), modifiers);
if (!framebuffer) {
LOG(ERROR) << "Failed to add framebuffer for scanout buffer";
- return DrmOverlayPlane::Error();
+ return DrmOverlayPlaneList();
}
if (!is_testing) {
@@ -688,16 +744,19 @@ DrmOverlayPlane ScreenManager::GetModesetBuffer(
surface->getCanvas()->clear(SK_ColorBLACK);
}
}
- return DrmOverlayPlane(framebuffer, nullptr);
+
+ DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(framebuffer, nullptr);
+ return modeset_planes;
}
void ScreenManager::GetEnableControllerProps(
CommitRequest* commit_request,
HardwareDisplayController* controller,
- const DrmOverlayPlane& primary) {
+ const DrmOverlayPlaneList& modeset_planes) {
DCHECK(!controller->crtc_controllers().empty());
- controller->GetEnableProps(commit_request, primary);
+ controller->GetEnableProps(commit_request, modeset_planes);
}
void ScreenManager::GetModesetControllerProps(
@@ -705,11 +764,11 @@ void ScreenManager::GetModesetControllerProps(
HardwareDisplayController* controller,
const gfx::Point& origin,
const drmModeModeInfo& mode,
- const DrmOverlayPlane& primary) {
+ const DrmOverlayPlaneList& modeset_planes) {
DCHECK(!controller->crtc_controllers().empty());
controller->set_origin(origin);
- controller->GetModesetProps(commit_request, primary, mode);
+ controller->GetModesetProps(commit_request, modeset_planes, mode);
}
DrmWindow* ScreenManager::FindWindowAt(const gfx::Rect& bounds) const {
diff --git a/chromium/ui/ozone/platform/drm/gpu/screen_manager.h b/chromium/ui/ozone/platform/drm/gpu/screen_manager.h
index d000d3b9499..53abc7188c6 100644
--- a/chromium/ui/ozone/platform/drm/gpu/screen_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/screen_manager.h
@@ -50,7 +50,7 @@ class ScreenManager {
const uint32_t crtc;
const uint32_t connector;
const gfx::Point origin;
- std::unique_ptr<drmModeModeInfo> mode = nullptr;
+ std::unique_ptr<drmModeModeInfo> mode;
};
using ControllerConfigsList = std::vector<ControllerConfigParams>;
@@ -108,7 +108,6 @@ class ScreenManager {
const scoped_refptr<DrmDevice>& drm,
uint32_t crtc);
- bool TestModeset(const ControllerConfigsList& controllers_params);
bool TestAndSetPreferredModifiers(
const ControllerConfigsList& controllers_params);
bool TestAndSetLinearModifier(
@@ -118,8 +117,12 @@ class ScreenManager {
void SetPreferredModifiers(
const ControllerConfigsList& controllers_params,
const CrtcPreferredModifierMap& crtcs_preferred_modifier);
-
- bool Modeset(const ControllerConfigsList& controllers_params);
+ // The planes used for modesetting can have overlays beside the primary, test
+ // if we can modeset with them. If not, return false to indicate that we must
+ // only use the primary plane.
+ bool TestModesetWithOverlays(const ControllerConfigsList& controllers_params);
+ bool Modeset(const ControllerConfigsList& controllers_params,
+ bool can_modeset_with_overlays);
// Configures a display controller to be enabled. The display controller is
// identified by (|crtc|, |connector|) and the controller is to be modeset
@@ -131,7 +134,7 @@ class ScreenManager {
uint32_t connector,
const gfx::Point& origin,
const drmModeModeInfo& mode,
- const DrmOverlayPlane& primary);
+ const DrmOverlayPlaneList& modeset_planes);
// Configures a display controller to be disabled. The display controller is
// identified by |crtc|. Controller modeset props are added into
@@ -163,20 +166,21 @@ class ScreenManager {
const scoped_refptr<DrmDevice>& drm,
const gfx::Rect& bounds);
- DrmOverlayPlane GetModesetBuffer(HardwareDisplayController* controller,
- const gfx::Rect& bounds,
- const std::vector<uint64_t>& modifiers,
- bool is_testing);
+ DrmOverlayPlaneList GetModesetPlanes(HardwareDisplayController* controller,
+ const gfx::Rect& bounds,
+ const std::vector<uint64_t>& modifiers,
+ bool include_overlays,
+ bool is_testing);
// Gets props for modesetting the |controller| using |origin| and |mode|.
void GetModesetControllerProps(CommitRequest* commit_request,
HardwareDisplayController* controller,
const gfx::Point& origin,
const drmModeModeInfo& mode,
- const DrmOverlayPlane& primary);
+ const DrmOverlayPlaneList& modeset_planes);
void GetEnableControllerProps(CommitRequest* commit_request,
HardwareDisplayController* controller,
- const DrmOverlayPlane& primary);
+ const DrmOverlayPlaneList& modeset_planes);
DrmWindow* FindWindowAt(const gfx::Rect& bounds) const;
diff --git a/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
index 2e96c2d2f95..a98d358da52 100644
--- a/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
@@ -176,7 +176,7 @@ class ScreenManagerTest : public testing::Test {
property_names.insert(plane_property_names.begin(),
plane_property_names.end());
- drm_->SetModifiersOverhead(modifiers_overhead_);
+ drm->SetModifiersOverhead(modifiers_overhead_);
drm->InitializeState(crtc_properties, connector_properties,
plane_properties, property_names, is_atomic);
}
@@ -1467,4 +1467,272 @@ TEST_F(ScreenManagerTest, DrmFramebufferSequenceIdIncrementingAtModeset) {
CHECK_EQ(pre_modeset_buffer->modeset_sequence_id_at_allocation(), 0);
}
+TEST_F(ScreenManagerTest, CloningPlanesOnModeset) {
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
+
+ std::unique_ptr<ui::DrmWindow> window(
+ new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
+ window->Initialize();
+ window->SetBounds(GetPrimaryBounds());
+ scoped_refptr<DrmFramebuffer> buffer =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ ui::DrmOverlayPlaneList planes;
+ planes.push_back(ui::DrmOverlayPlane(buffer, nullptr));
+ window->SchedulePageFlip(std::move(planes), base::DoNothing(),
+ base::DoNothing());
+ screen_manager_->AddWindow(1, std::move(window));
+
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ ASSERT_TRUE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ buffer));
+
+ window = screen_manager_->RemoveWindow(1);
+ window->Shutdown();
+}
+
+TEST_F(ScreenManagerTest, CloningMultiplePlanesOnModeset) {
+ std::vector<CrtcState> crtc_states = {{
+ /* .planes = */
+ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ },
+ }};
+ InitializeDrmState(drm_.get(), crtc_states, /*is_atomic=*/true);
+
+ std::unique_ptr<ui::DrmWindow> window(
+ new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
+ window->Initialize();
+ window->SetBounds(GetPrimaryBounds());
+ scoped_refptr<DrmFramebuffer> primary =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ scoped_refptr<DrmFramebuffer> overlay =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ ui::DrmOverlayPlaneList planes;
+ planes.push_back(ui::DrmOverlayPlane(primary, nullptr));
+ planes.push_back(ui::DrmOverlayPlane(overlay, nullptr));
+ window->SchedulePageFlip(std::move(planes), base::DoNothing(),
+ base::DoNothing());
+ screen_manager_->AddWindow(1, std::move(window));
+
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ ASSERT_TRUE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ primary));
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ overlay));
+
+ window = screen_manager_->RemoveWindow(1);
+ window->Shutdown();
+}
+
+TEST_F(ScreenManagerTest, ModesetWithClonedPlanesNoOverlays) {
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
+
+ std::unique_ptr<ui::DrmWindow> window(
+ new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
+ window->Initialize();
+ window->SetBounds(GetPrimaryBounds());
+ scoped_refptr<DrmFramebuffer> buffer =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ ui::DrmOverlayPlaneList planes;
+ planes.push_back(ui::DrmOverlayPlane(buffer, nullptr));
+ window->SchedulePageFlip(std::move(planes), base::DoNothing(),
+ base::DoNothing());
+ screen_manager_->AddWindow(1, std::move(window));
+
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ ASSERT_TRUE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+ ASSERT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ buffer));
+
+ EXPECT_EQ(drm_->get_test_modeset_count(), 1);
+ EXPECT_EQ(drm_->last_planes_committed_count(), 1);
+
+ window = screen_manager_->RemoveWindow(1);
+ window->Shutdown();
+}
+
+TEST_F(ScreenManagerTest, ModesetWithClonedPlanesWithOverlaySucceeding) {
+ std::vector<CrtcState> crtc_states = {{
+ /* .planes = */
+ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ },
+ }};
+ InitializeDrmState(drm_.get(), crtc_states, /*is_atomic=*/true);
+
+ std::unique_ptr<ui::DrmWindow> window(
+ new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
+ window->Initialize();
+ window->SetBounds(GetPrimaryBounds());
+ scoped_refptr<DrmFramebuffer> primary =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ scoped_refptr<DrmFramebuffer> overlay =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ ui::DrmOverlayPlaneList planes;
+ planes.push_back(ui::DrmOverlayPlane(primary, nullptr));
+ planes.push_back(ui::DrmOverlayPlane(overlay, nullptr));
+ window->SchedulePageFlip(std::move(planes), base::DoNothing(),
+ base::DoNothing());
+ screen_manager_->AddWindow(1, std::move(window));
+
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ ASSERT_TRUE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ primary));
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ overlay));
+
+ EXPECT_EQ(drm_->get_test_modeset_count(), 2);
+ EXPECT_EQ(drm_->last_planes_committed_count(), 2);
+
+ window = screen_manager_->RemoveWindow(1);
+ window->Shutdown();
+}
+
+TEST_F(ScreenManagerTest, ModesetWithClonedPlanesWithOverlayFailing) {
+ std::vector<CrtcState> crtc_states = {{
+ /* .planes = */
+ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ },
+ }};
+ InitializeDrmState(drm_.get(), crtc_states, /*is_atomic=*/true);
+
+ std::unique_ptr<ui::DrmWindow> window(
+ new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
+ window->Initialize();
+ window->SetBounds(GetPrimaryBounds());
+ scoped_refptr<DrmFramebuffer> primary =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ scoped_refptr<DrmFramebuffer> overlay =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ ui::DrmOverlayPlaneList planes;
+ planes.push_back(ui::DrmOverlayPlane(primary, nullptr));
+ planes.push_back(ui::DrmOverlayPlane(overlay, nullptr));
+ window->SchedulePageFlip(std::move(planes), base::DoNothing(),
+ base::DoNothing());
+ screen_manager_->AddWindow(1, std::move(window));
+
+ drm_->set_overlay_modeset_expecation(false);
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ EXPECT_TRUE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ primary));
+ EXPECT_FALSE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ overlay));
+
+ EXPECT_EQ(drm_->get_test_modeset_count(), 2);
+ EXPECT_EQ(drm_->last_planes_committed_count(), 1);
+
+ window = screen_manager_->RemoveWindow(1);
+ window->Shutdown();
+}
+
+TEST_F(ScreenManagerTest, ModesetWithNewBuffersOnModifiersChange) {
+ std::vector<CrtcState> crtc_states = {{
+ /* .planes = */
+ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ },
+ }};
+ InitializeDrmState(drm_.get(), crtc_states, /*is_atomic=*/true,
+ /*use_modifiers_list=*/true);
+ std::unique_ptr<ui::DrmWindow> window(
+ new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
+ window->Initialize();
+ window->SetBounds(GetPrimaryBounds());
+
+ scoped_refptr<DrmFramebuffer> primary =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ scoped_refptr<DrmFramebuffer> overlay =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ ui::DrmOverlayPlaneList planes;
+ planes.push_back(ui::DrmOverlayPlane(primary, nullptr));
+ planes.push_back(ui::DrmOverlayPlane(overlay, nullptr));
+ window->SchedulePageFlip(std::move(planes), base::DoNothing(),
+ base::DoNothing());
+ screen_manager_->AddWindow(1, std::move(window));
+
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ ASSERT_TRUE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+
+ EXPECT_FALSE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ primary));
+ EXPECT_FALSE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ overlay));
+
+ // Testing test modifiers only, no linear or overlays test.
+ EXPECT_EQ(drm_->get_test_modeset_count(), 1);
+ EXPECT_EQ(drm_->last_planes_committed_count(), 1);
+
+ window = screen_manager_->RemoveWindow(1);
+ window->Shutdown();
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/host/drm_cursor.cc b/chromium/ui/ozone/platform/drm/host/drm_cursor.cc
index 49ce7768b42..d0fded55a66 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_cursor.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_cursor.cc
@@ -12,6 +12,7 @@
#include "base/trace_event/trace_event.h"
#include "build/chromeos_buildflags.h"
#include "ui/base/cursor/mojom/cursor_type.mojom.h"
+#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/ozone/platform/drm/host/drm_window_host.h"
#include "ui/ozone/platform/drm/host/drm_window_host_manager.h"
@@ -71,25 +72,22 @@ void DrmCursor::ResetDrmCursorProxy() {
}
gfx::Point DrmCursor::GetBitmapLocationLocked() {
- return gfx::ToFlooredPoint(location_) - bitmap_->hotspot().OffsetFromOrigin();
+ return gfx::ToFlooredPoint(location_) - cursor_->hotspot().OffsetFromOrigin();
}
void DrmCursor::SetCursor(gfx::AcceleratedWidget window,
- PlatformCursor platform_cursor) {
+ scoped_refptr<BitmapCursorOzone> platform_cursor) {
TRACE_EVENT0("drmcursor", "DrmCursor::SetCursor");
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_NE(window, gfx::kNullAcceleratedWidget);
DCHECK(platform_cursor);
- scoped_refptr<BitmapCursorOzone> bitmap =
- BitmapCursorFactoryOzone::GetBitmapCursor(platform_cursor);
-
base::AutoLock lock(lock_);
- if (window_ != window || bitmap_ == bitmap)
+ if (window_ != window || cursor_ == platform_cursor)
return;
- bitmap_ = bitmap;
+ cursor_ = platform_cursor;
SendCursorShowLocked();
}
@@ -211,7 +209,7 @@ void DrmCursor::MoveCursor(const gfx::Vector2dF& delta) {
bool DrmCursor::IsCursorVisible() {
base::AutoLock lock(lock_);
- return bitmap_ != nullptr && bitmap_->type() != CursorType::kNone;
+ return cursor_ != nullptr && cursor_->type() != CursorType::kNone;
}
gfx::PointF DrmCursor::GetLocation() {
@@ -244,13 +242,13 @@ void DrmCursor::SetCursorLocationLocked(const gfx::PointF& location) {
}
void DrmCursor::SendCursorShowLocked() {
- if (!bitmap_ || bitmap_->type() == CursorType::kNone) {
+ if (!cursor_ || cursor_->type() == CursorType::kNone) {
SendCursorHideLocked();
return;
}
- CursorSetLockTested(window_, bitmap_->bitmaps(), GetBitmapLocationLocked(),
- bitmap_->frame_delay());
+ CursorSetLockTested(window_, cursor_->bitmaps(), GetBitmapLocationLocked(),
+ cursor_->frame_delay());
}
void DrmCursor::SendCursorHideLocked() {
@@ -259,7 +257,7 @@ void DrmCursor::SendCursorHideLocked() {
}
void DrmCursor::SendCursorMoveLocked() {
- if (!bitmap_ || bitmap_->type() == CursorType::kNone)
+ if (!cursor_ || cursor_->type() == CursorType::kNone)
return;
MoveLockTested(window_, GetBitmapLocationLocked());
diff --git a/chromium/ui/ozone/platform/drm/host/drm_cursor.h b/chromium/ui/ozone/platform/drm/host/drm_cursor.h
index a5d31630e09..356282608d4 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_cursor.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_cursor.h
@@ -8,9 +8,9 @@
#include <memory>
#include <vector>
+#include "base/memory/scoped_refptr.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
-#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/events/ozone/evdev/cursor_delegate_evdev.h"
#include "ui/gfx/geometry/rect.h"
@@ -53,8 +53,9 @@ class DrmCursor : public CursorDelegateEvdev {
void SetDrmCursorProxy(std::unique_ptr<DrmCursorProxy> proxy);
void ResetDrmCursorProxy();
- // Change the cursor over the specifed window.
- void SetCursor(gfx::AcceleratedWidget window, PlatformCursor platform_cursor);
+ // Change the cursor over the specified window.
+ void SetCursor(gfx::AcceleratedWidget window,
+ scoped_refptr<BitmapCursorOzone> platform_cursor);
// Handle window lifecycle.
void OnWindowAdded(gfx::AcceleratedWidget window,
@@ -101,7 +102,7 @@ class DrmCursor : public CursorDelegateEvdev {
gfx::Point GetBitmapLocationLocked();
// The current cursor bitmap (immutable).
- scoped_refptr<BitmapCursorOzone> bitmap_;
+ scoped_refptr<BitmapCursorOzone> cursor_;
// The window under the cursor.
gfx::AcceleratedWidget window_;
diff --git a/chromium/ui/ozone/platform/drm/host/drm_device_connector.cc b/chromium/ui/ozone/platform/drm/host/drm_device_connector.cc
index 71b27383aa4..1424ec8e93b 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_device_connector.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_device_connector.cc
@@ -29,7 +29,7 @@ void DrmDeviceConnector::OnChannelDestroyed(int host_id) {
void DrmDeviceConnector::OnGpuServiceLaunched(
int host_id,
scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> process_host_runner,
GpuHostBindInterfaceCallback binder,
GpuHostTerminateCallback terminate_callback) {
// We need to preserve |binder| to let us bind interfaces later.
@@ -39,8 +39,21 @@ void DrmDeviceConnector::OnGpuServiceLaunched(
mojo::PendingRemote<ui::ozone::mojom::DrmDevice> drm_device;
BindInterfaceDrmDevice(&drm_device);
- host_drm_device_->OnGpuServiceLaunchedOnIOThread(std::move(drm_device),
- ui_runner);
+ if (ui_runner->BelongsToCurrentThread()) {
+ // If the GpuProcessHost lives on the UI thread this method will be called
+ // before ash::Shell::Init which breaks assumptions since the displays
+ // won't be marked as dummy but we don't have the active list yet from the
+ // GPU process. Simulate the old behavior by inserting a PostTask.
+ // TODO(rjkroege): simplify this code path once GpuProcessHost always lives
+ // on the UI thread.
+ ui_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&HostDrmDevice::OnGpuServiceLaunchedOnProcessThread,
+ host_drm_device_, std::move(drm_device), ui_runner));
+ } else {
+ host_drm_device_->OnGpuServiceLaunchedOnProcessThread(std::move(drm_device),
+ ui_runner);
+ }
}
void DrmDeviceConnector::BindInterfaceDrmDevice(
@@ -51,7 +64,7 @@ void DrmDeviceConnector::BindInterfaceDrmDevice(
void DrmDeviceConnector::ConnectSingleThreaded(
mojo::PendingRemote<ui::ozone::mojom::DrmDevice> drm_device) {
- host_drm_device_->OnGpuServiceLaunchedOnIOThread(
+ host_drm_device_->OnGpuServiceLaunchedOnProcessThread(
std::move(drm_device), base::ThreadTaskRunnerHandle::Get());
}
diff --git a/chromium/ui/ozone/platform/drm/host/drm_device_connector.h b/chromium/ui/ozone/platform/drm/host/drm_device_connector.h
index 094408501b0..5f1427a79df 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_device_connector.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_device_connector.h
@@ -5,7 +5,6 @@
#ifndef UI_OZONE_PLATFORM_DRM_HOST_DRM_DEVICE_CONNECTOR_H_
#define UI_OZONE_PLATFORM_DRM_HOST_DRM_DEVICE_CONNECTOR_H_
-#include <string>
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -28,7 +27,7 @@ class DrmDeviceConnector : public GpuPlatformSupportHost {
void OnGpuServiceLaunched(
int host_id,
scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> process_host_runner,
GpuHostBindInterfaceCallback binder,
GpuHostTerminateCallback terminate_callback) override;
diff --git a/chromium/ui/ozone/platform/drm/host/drm_window_host.cc b/chromium/ui/ozone/platform/drm/host/drm_window_host.cc
index 0445d03e05c..9e08fc27dcb 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_window_host.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_window_host.cc
@@ -5,6 +5,9 @@
#include "ui/ozone/platform/drm/host/drm_window_host.h"
#include "base/bind.h"
+#include "base/memory/scoped_refptr.h"
+#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/display/display.h"
#include "ui/events/devices/device_data_manager.h"
#include "ui/events/event.h"
@@ -125,8 +128,8 @@ bool DrmWindowHost::ShouldUseNativeFrame() const {
return false;
}
-void DrmWindowHost::SetCursor(PlatformCursor cursor) {
- cursor_->SetCursor(widget_, cursor);
+void DrmWindowHost::SetCursor(scoped_refptr<PlatformCursor> cursor) {
+ cursor_->SetCursor(widget_, BitmapCursorOzone::FromPlatformCursor(cursor));
}
void DrmWindowHost::MoveCursorTo(const gfx::Point& location) {
diff --git a/chromium/ui/ozone/platform/drm/host/drm_window_host.h b/chromium/ui/ozone/platform/drm/host/drm_window_host.h
index d7000dd0d9b..3ad049a4b0a 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_window_host.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_window_host.h
@@ -76,7 +76,7 @@ class DrmWindowHost : public PlatformWindow,
void Deactivate() override;
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
- void SetCursor(PlatformCursor cursor) override;
+ void SetCursor(scoped_refptr<PlatformCursor> cursor) override;
void MoveCursorTo(const gfx::Point& location) override;
void ConfineCursorToBounds(const gfx::Rect& bounds) override;
void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override;
diff --git a/chromium/ui/ozone/platform/drm/host/host_drm_device.cc b/chromium/ui/ozone/platform/drm/host/host_drm_device.cc
index 9cd757ceeb6..5ccd4cf4993 100644
--- a/chromium/ui/ozone/platform/drm/host/host_drm_device.cc
+++ b/chromium/ui/ozone/platform/drm/host/host_drm_device.cc
@@ -287,19 +287,20 @@ void HostDrmDevice::GpuSetHDCPStateCallback(int64_t display_id,
display_manager_->GpuUpdatedHDCPState(display_id, success);
}
-void HostDrmDevice::OnGpuServiceLaunchedOnIOThread(
+void HostDrmDevice::OnGpuServiceLaunchedOnProcessThread(
mojo::PendingRemote<ui::ozone::mojom::DrmDevice> drm_device,
scoped_refptr<base::SingleThreadTaskRunner> ui_runner) {
- DCHECK_CALLED_ON_VALID_THREAD(on_io_thread_);
// The observers might send IPC messages from the IO thread during the call to
// OnGpuProcessLaunched.
drm_device_on_io_thread_.Bind(std::move(drm_device));
for (GpuThreadObserver& observer : gpu_thread_observers_)
observer.OnGpuProcessLaunched();
- // In the single-threaded mode, there won't be separate UI and IO threads.
+ // In the single-threaded mode or when GpuProcessHost lives on the UI thread,
+ // there won't be separate UI and IO threads.
if (ui_runner->BelongsToCurrentThread()) {
OnGpuServiceLaunchedOnUIThread(drm_device_on_io_thread_.Unbind());
} else {
+ DCHECK_CALLED_ON_VALID_THREAD(on_io_thread_);
ui_runner->PostTask(
FROM_HERE,
base::BindOnce(&HostDrmDevice::OnGpuServiceLaunchedOnUIThread, this,
diff --git a/chromium/ui/ozone/platform/drm/host/host_drm_device.h b/chromium/ui/ozone/platform/drm/host/host_drm_device.h
index 18170a0bc2f..8307dec2aff 100644
--- a/chromium/ui/ozone/platform/drm/host/host_drm_device.h
+++ b/chromium/ui/ozone/platform/drm/host/host_drm_device.h
@@ -38,7 +38,7 @@ class HostDrmDevice : public base::RefCountedThreadSafe<HostDrmDevice>,
void SetDisplayManager(DrmDisplayHostManager* display_manager);
- void OnGpuServiceLaunchedOnIOThread(
+ void OnGpuServiceLaunchedOnProcessThread(
mojo::PendingRemote<ui::ozone::mojom::DrmDevice> drm_device,
scoped_refptr<base::SingleThreadTaskRunner> ui_runner);
diff --git a/chromium/ui/ozone/platform/drm/ozone_platform_drm.cc b/chromium/ui/ozone/platform/drm/ozone_platform_drm.cc
index aceccb83583..1bae3395e4e 100644
--- a/chromium/ui/ozone/platform/drm/ozone_platform_drm.cc
+++ b/chromium/ui/ozone/platform/drm/ozone_platform_drm.cc
@@ -125,7 +125,7 @@ class OzonePlatformDrm : public OzonePlatform {
binders->Add<ozone::mojom::DrmDevice>(
base::BindRepeating(
&OzonePlatformDrm::CreateDrmDeviceReceiverOnDrmThread,
- weak_factory_.GetWeakPtr()),
+ weak_factory_on_drm_.GetWeakPtr()),
drm_thread_proxy_->GetDrmThreadTaskRunner());
}
}
@@ -304,7 +304,7 @@ class OzonePlatformDrm : public OzonePlatform {
} else {
auto safe_receiver_request_drainer = CreateSafeOnceCallback(
base::BindOnce(&OzonePlatformDrm::DrainReceiverRequests,
- weak_factory_.GetWeakPtr()));
+ weak_factory_on_drm_.GetWeakPtr()));
drm_thread_proxy_->StartDrmThread(
std::move(safe_receiver_request_drainer));
}
@@ -345,6 +345,7 @@ class OzonePlatformDrm : public OzonePlatform {
InitializedHostProperties host_properties_;
base::WeakPtrFactory<OzonePlatformDrm> weak_factory_{this};
+ base::WeakPtrFactory<OzonePlatformDrm> weak_factory_on_drm_{this};
OzonePlatformDrm(const OzonePlatformDrm&) = delete;
OzonePlatformDrm& operator=(const OzonePlatformDrm&) = delete;
};
diff --git a/chromium/ui/ozone/platform/headless/BUILD.gn b/chromium/ui/ozone/platform/headless/BUILD.gn
index 8e665de7724..ca02e70c2cd 100644
--- a/chromium/ui/ozone/platform/headless/BUILD.gn
+++ b/chromium/ui/ozone/platform/headless/BUILD.gn
@@ -2,8 +2,6 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//build/config/chromeos/ui_mode.gni")
-
visibility = [ "//ui/ozone/*" ]
source_set("headless") {
@@ -41,10 +39,6 @@ source_set("headless") {
"//ui/platform_window/stub",
]
- if (is_chromeos_ash) {
- deps += [ "//chromeos/dbus/constants:constants" ]
- }
-
if (is_fuchsia) {
deps += [ "//ui/base/ime/fuchsia" ]
}
diff --git a/chromium/ui/ozone/platform/headless/DEPS b/chromium/ui/ozone/platform/headless/DEPS
index 5faeb9d2490..41cd997bd46 100644
--- a/chromium/ui/ozone/platform/headless/DEPS
+++ b/chromium/ui/ozone/platform/headless/DEPS
@@ -1,4 +1,3 @@
include_rules = [
- "+chromeos/dbus/constants",
"+third_party/skia/include",
]
diff --git a/chromium/ui/ozone/platform/headless/headless_surface_factory.cc b/chromium/ui/ozone/platform/headless/headless_surface_factory.cc
index b5e46fdb9ea..afcfed9a614 100644
--- a/chromium/ui/ozone/platform/headless/headless_surface_factory.cc
+++ b/chromium/ui/ozone/platform/headless/headless_surface_factory.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/location.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/post_task.h"
@@ -251,7 +252,7 @@ scoped_refptr<gfx::NativePixmap> HeadlessSurfaceFactory::CreateNativePixmap(
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- base::Optional<gfx::Size> framebuffer_size) {
+ absl::optional<gfx::Size> framebuffer_size) {
return new TestPixmap(format);
}
diff --git a/chromium/ui/ozone/platform/headless/headless_surface_factory.h b/chromium/ui/ozone/platform/headless/headless_surface_factory.h
index 53dda7b9e45..13ae5e46270 100644
--- a/chromium/ui/ozone/platform/headless/headless_surface_factory.h
+++ b/chromium/ui/ozone/platform/headless/headless_surface_factory.h
@@ -31,7 +31,7 @@ class HeadlessSurfaceFactory : public SurfaceFactoryOzone {
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- base::Optional<gfx::Size> framebuffer_size = base::nullopt) override;
+ absl::optional<gfx::Size> framebuffer_size = absl::nullopt) override;
private:
void CheckBasePath() const;
diff --git a/chromium/ui/ozone/platform/headless/headless_window_manager.h b/chromium/ui/ozone/platform/headless/headless_window_manager.h
index 8768c9c0382..cf71f34ea44 100644
--- a/chromium/ui/ozone/platform/headless/headless_window_manager.h
+++ b/chromium/ui/ozone/platform/headless/headless_window_manager.h
@@ -7,10 +7,7 @@
#include <stdint.h>
-#include <memory>
-
#include "base/containers/id_map.h"
-#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "ui/gfx/native_widget_types.h"
diff --git a/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc b/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc
index 0e65df5d378..28889deb4c1 100644
--- a/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc
+++ b/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc
@@ -10,7 +10,6 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
#include "ui/base/cursor/cursor_factory.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/base/ime/input_method_minimal.h"
@@ -30,10 +29,6 @@
#include "ui/ozone/public/system_input_injector.h"
#include "ui/platform_window/platform_window_init_properties.h"
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "chromeos/dbus/constants/dbus_switches.h"
-#endif
-
#if defined(OS_FUCHSIA)
#include "ui/base/ime/fuchsia/input_method_fuchsia.h"
#endif
@@ -141,11 +136,6 @@ OzonePlatform* CreateOzonePlatformHeadless() {
location = cmd->GetSwitchValuePath(switches::kOzoneDumpFile);
cmd->AppendSwitch(switches::kDisableRunningAsSystemCompositor);
-#if BUILDFLAG(IS_CHROMEOS_ASH)
- // Disable USB input.
- cmd->AppendSwitch(chromeos::switches::kCrosDisksFake);
-#endif
-
return new OzonePlatformHeadless(location);
}
diff --git a/chromium/ui/ozone/platform/scenic/safe_presenter.h b/chromium/ui/ozone/platform/scenic/safe_presenter.h
index 91099573a6f..024c1b80b7b 100644
--- a/chromium/ui/ozone/platform/scenic/safe_presenter.h
+++ b/chromium/ui/ozone/platform/scenic/safe_presenter.h
@@ -7,8 +7,6 @@
#include <lib/ui/scenic/cpp/session.h>
-#include <queue>
-
namespace ui {
using QueuePresentCallback = fit::function<void()>;
diff --git a/chromium/ui/ozone/platform/scenic/scenic_gpu_host.cc b/chromium/ui/ozone/platform/scenic/scenic_gpu_host.cc
index c01c57f38b4..63e9e64199a 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_gpu_host.cc
+++ b/chromium/ui/ozone/platform/scenic/scenic_gpu_host.cc
@@ -80,17 +80,20 @@ void ScenicGpuHost::OnChannelDestroyed(int host_id) {}
void ScenicGpuHost::OnGpuServiceLaunched(
int host_id,
scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> process_host_runner,
GpuHostBindInterfaceCallback binder,
GpuHostTerminateCallback terminate_callback) {
- DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
-
mojo::PendingRemote<mojom::ScenicGpuService> scenic_gpu_service;
BindInterface(scenic_gpu_service.InitWithNewPipeAndPassReceiver(), binder);
- ui_thread_runner_->PostTask(
- FROM_HERE, base::BindOnce(&ScenicGpuHost::OnGpuServiceLaunchedOnUI,
- weak_ptr_factory_.GetWeakPtr(),
- std::move(scenic_gpu_service)));
+ if (ui_runner->BelongsToCurrentThread()) {
+ OnGpuServiceLaunchedOnUI(std::move(scenic_gpu_service));
+ } else {
+ DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
+ ui_thread_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&ScenicGpuHost::OnGpuServiceLaunchedOnUI,
+ weak_ptr_factory_.GetWeakPtr(),
+ std::move(scenic_gpu_service)));
+ }
}
void ScenicGpuHost::OnGpuServiceLaunchedOnUI(
diff --git a/chromium/ui/ozone/platform/scenic/scenic_gpu_host.h b/chromium/ui/ozone/platform/scenic/scenic_gpu_host.h
index 4bf26775ead..64054b34e0a 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_gpu_host.h
+++ b/chromium/ui/ozone/platform/scenic/scenic_gpu_host.h
@@ -52,7 +52,7 @@ class ScenicGpuHost : public mojom::ScenicGpuHost,
void OnGpuServiceLaunched(
int host_id,
scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> process_host_runner,
GpuHostBindInterfaceCallback binder,
GpuHostTerminateCallback terminate_callback) override;
diff --git a/chromium/ui/ozone/platform/scenic/scenic_screen.cc b/chromium/ui/ozone/platform/scenic/scenic_screen.cc
index a5d78fa2c91..350dc0abc13 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_screen.cc
+++ b/chromium/ui/ozone/platform/scenic/scenic_screen.cc
@@ -34,8 +34,10 @@ void ScenicScreen::OnWindowRemoved(int32_t window_id) {
display::Display removed_display = *display_it;
displays_.erase(display_it);
- for (auto& observer : observers_)
+ for (auto& observer : observers_) {
observer.OnDisplayRemoved(removed_display);
+ observer.OnDidRemoveDisplays();
+ }
}
void ScenicScreen::OnWindowBoundsChanged(int32_t window_id, gfx::Rect bounds) {
@@ -47,25 +49,6 @@ void ScenicScreen::OnWindowBoundsChanged(int32_t window_id, gfx::Rect bounds) {
display_it->set_bounds(bounds);
}
-void ScenicScreen::OnWindowMetrics(int32_t window_id,
- float device_pixel_ratio) {
- if (display::Display::HasForceDeviceScaleFactor())
- return;
-
- auto display_it = std::find_if(displays_.begin(), displays_.end(),
- [window_id](display::Display& display) {
- return display.id() == window_id;
- });
- DCHECK(display_it != displays_.end());
-
- display_it->set_device_scale_factor(device_pixel_ratio);
- for (auto& observer : observers_) {
- observer.OnDisplayMetricsChanged(
- *display_it,
- display::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR);
- }
-}
-
base::WeakPtr<ScenicScreen> ScenicScreen::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
diff --git a/chromium/ui/ozone/platform/scenic/scenic_screen.h b/chromium/ui/ozone/platform/scenic/scenic_screen.h
index b55e4bafbc9..c6470ae2782 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_screen.h
+++ b/chromium/ui/ozone/platform/scenic/scenic_screen.h
@@ -24,7 +24,6 @@ class ScenicScreen : public PlatformScreen {
// Processes window state change events for the ScenicWindow |window_id_|.
void OnWindowAdded(int32_t window_id);
void OnWindowRemoved(int32_t window_id);
- void OnWindowMetrics(int32_t window_id, float device_pixel_ratio);
void OnWindowBoundsChanged(int32_t window_id, gfx::Rect bounds);
base::WeakPtr<ScenicScreen> GetWeakPtr();
diff --git a/chromium/ui/ozone/platform/scenic/scenic_surface_factory.cc b/chromium/ui/ozone/platform/scenic/scenic_surface_factory.cc
index 06e5f116d9d..82e6ab5f850 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_surface_factory.cc
+++ b/chromium/ui/ozone/platform/scenic/scenic_surface_factory.cc
@@ -221,7 +221,7 @@ scoped_refptr<gfx::NativePixmap> ScenicSurfaceFactory::CreateNativePixmap(
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- base::Optional<gfx::Size> framebuffer_size) {
+ absl::optional<gfx::Size> framebuffer_size) {
DCHECK(!framebuffer_size || framebuffer_size == size);
auto collection = sysmem_buffer_manager_.CreateCollection(vk_device, size,
format, usage, 1);
@@ -244,13 +244,10 @@ void ScenicSurfaceFactory::CreateNativePixmapAsync(
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanImplementation>
-ScenicSurfaceFactory::CreateVulkanImplementation(
- bool use_swiftshader,
- bool allow_protected_memory,
- bool enforce_protected_memory) {
+ScenicSurfaceFactory::CreateVulkanImplementation(bool use_swiftshader,
+ bool allow_protected_memory) {
return std::make_unique<ui::VulkanImplementationScenic>(
- this, &sysmem_buffer_manager_, allow_protected_memory,
- enforce_protected_memory);
+ this, &sysmem_buffer_manager_, allow_protected_memory);
}
#endif
diff --git a/chromium/ui/ozone/platform/scenic/scenic_surface_factory.h b/chromium/ui/ozone/platform/scenic/scenic_surface_factory.h
index aed23be862c..48c261ea00e 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_surface_factory.h
+++ b/chromium/ui/ozone/platform/scenic/scenic_surface_factory.h
@@ -54,7 +54,7 @@ class ScenicSurfaceFactory : public SurfaceFactoryOzone {
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- base::Optional<gfx::Size> framebuffer_size = base::nullopt) override;
+ absl::optional<gfx::Size> framebuffer_size = absl::nullopt) override;
void CreateNativePixmapAsync(gfx::AcceleratedWidget widget,
VkDevice vk_device,
gfx::Size size,
@@ -64,8 +64,7 @@ class ScenicSurfaceFactory : public SurfaceFactoryOzone {
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanImplementation> CreateVulkanImplementation(
bool use_swiftshader,
- bool allow_protected_memory,
- bool enforce_protected_memory) override;
+ bool allow_protected_memory) override;
#endif
// Registers a surface for a |widget|.
diff --git a/chromium/ui/ozone/platform/scenic/scenic_window.cc b/chromium/ui/ozone/platform/scenic/scenic_window.cc
index 125e40dd99f..4b371df0f88 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_window.cc
+++ b/chromium/ui/ozone/platform/scenic/scenic_window.cc
@@ -14,6 +14,8 @@
#include "base/fuchsia/fuchsia_logging.h"
#include "base/fuchsia/process_context.h"
+#include "base/memory/scoped_refptr.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
@@ -112,7 +114,9 @@ void ScenicWindow::Show(bool inactive) {
visible_ = true;
- view_.AddChild(node_);
+ if (!previous_view_is_zero_sized_) {
+ view_.AddChild(node_);
+ }
// Call Present2() to ensure that the scenic session commands are processed,
// which is necessary to receive metrics event from Scenic.
@@ -124,7 +128,9 @@ void ScenicWindow::Hide() {
return;
visible_ = false;
- node_.Detach();
+ if (!previous_view_is_zero_sized_) {
+ node_.Detach();
+ }
}
void ScenicWindow::Close() {
@@ -190,7 +196,7 @@ bool ScenicWindow::ShouldUseNativeFrame() const {
return false;
}
-void ScenicWindow::SetCursor(PlatformCursor cursor) {
+void ScenicWindow::SetCursor(scoped_refptr<PlatformCursor> cursor) {
NOTIMPLEMENTED_LOG_ONCE();
}
@@ -237,6 +243,26 @@ void ScenicWindow::UpdateSize() {
if (screen)
screen->OnWindowBoundsChanged(window_id_, bounds_);
+ // If the width or height of the window is zero, then we shouldn't render
+ // the node. Instead, we should detach it from its parent.
+ if (width == 0.f || height == 0.f) {
+ if (!previous_view_is_zero_sized_) {
+ if (visible_) {
+ node_.Detach();
+ }
+ previous_view_is_zero_sized_ = true;
+ }
+ return;
+ }
+
+ // Otherwise we add them back to the View.
+ if (previous_view_is_zero_sized_) {
+ if (visible_) {
+ view_.AddChild(node_);
+ }
+ previous_view_is_zero_sized_ = false;
+ }
+
// Translate the node by half of the view dimensions to put it in the center
// of the view.
node_.SetTranslation(width / 2.0, height / 2.0, 0.f);
@@ -310,10 +336,6 @@ void ScenicWindow::OnScenicEvents(
void ScenicWindow::OnViewMetrics(const fuchsia::ui::gfx::Metrics& metrics) {
device_pixel_ratio_ = std::max(metrics.scale_x, metrics.scale_y);
- ScenicScreen* screen = manager_->screen();
- if (screen)
- screen->OnWindowMetrics(window_id_, device_pixel_ratio_);
-
if (view_properties_)
UpdateSize();
}
diff --git a/chromium/ui/ozone/platform/scenic/scenic_window.h b/chromium/ui/ozone/platform/scenic/scenic_window.h
index e2ff6ed51e7..6d674ff4989 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_window.h
+++ b/chromium/ui/ozone/platform/scenic/scenic_window.h
@@ -82,7 +82,7 @@ class COMPONENT_EXPORT(OZONE) ScenicWindow : public PlatformWindow,
void Deactivate() override;
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
- void SetCursor(PlatformCursor cursor) override;
+ void SetCursor(scoped_refptr<PlatformCursor> cursor) override;
void MoveCursorTo(const gfx::Point& location) override;
void ConfineCursorToBounds(const gfx::Rect& bounds) override;
void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override;
@@ -144,8 +144,11 @@ class COMPONENT_EXPORT(OZONE) ScenicWindow : public PlatformWindow,
std::unique_ptr<scenic::ViewHolder> surface_view_holder_;
- // The ratio used for translating device-independent coordinates to absolute
- // pixel coordinates.
+ // The scale between logical pixels and physical pixels, set based on the
+ // fuchsia::ui::gfx::Metrics event. It's used to calculate dimensions of the
+ // view in physical pixels in UpdateSize(). This value doesn't affect the
+ // device_scale_factor reported by ScenicScreen for the corresponding display
+ // (currently always 1.0, see crbug.com/1215330).
float device_pixel_ratio_ = 0.f;
// Current view size in DIPs.
@@ -157,10 +160,15 @@ class COMPONENT_EXPORT(OZONE) ScenicWindow : public PlatformWindow,
// corresponding Scenic view.
gfx::Rect bounds_;
- base::Optional<fuchsia::ui::gfx::ViewProperties> view_properties_;
+ absl::optional<fuchsia::ui::gfx::ViewProperties> view_properties_;
bool visible_ = false;
+ // Tracks if the View was previously hidden due to having a size of zero.
+ // If the View was previously zero sized, then we need to re-attach it to
+ // its parent before we change its size to non-zero; and vice versa.
+ bool previous_view_is_zero_sized_ = false;
+
DISALLOW_COPY_AND_ASSIGN(ScenicWindow);
};
diff --git a/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.cc b/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.cc
index 61741b67acd..f016040e607 100644
--- a/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.cc
+++ b/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.cc
@@ -75,16 +75,6 @@ bool SysmemBufferCollection::IsNativePixmapConfigSupported(
case gfx::BufferUsage::SCANOUT_CPU_READ_WRITE:
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
-#if defined(ARCH_CPU_X86_64)
- // SwiftShader currently doesn't support liner image layouts (b/171299814)
- // required for images accessed by CPU, so these formats cannot be
- // supported with Goldfish Vulkan drivers running under emulator.It's not
- // straightforward to detect format support here because this code runs in
- // the renderer process. Disable these formats for all X64 devices for
- // now.
- // TODO(crbug.com/1141538): remove this workaround.
- return false;
-#endif
break;
default:
@@ -108,7 +98,6 @@ bool SysmemBufferCollection::Initialize(
gfx::BufferUsage usage,
VkDevice vk_device,
size_t min_buffer_count,
- bool force_protected,
bool register_with_image_pipe) {
DCHECK(IsNativePixmapConfigSupported(format, usage));
DCHECK(!collection_);
@@ -137,7 +126,7 @@ bool SysmemBufferCollection::Initialize(
format_ = format;
usage_ = usage;
vk_device_ = vk_device;
- is_protected_ = force_protected;
+ is_protected_ = false;
if (register_with_image_pipe) {
overlay_view_task_runner_ = base::ThreadTaskRunnerHandle::Get();
@@ -218,7 +207,7 @@ bool SysmemBufferCollection::CreateVkImage(
VkImageCreateInfo* vk_image_info,
VkDeviceMemory* vk_device_memory,
VkDeviceSize* mem_allocation_size,
- base::Optional<gpu::VulkanYCbCrInfo>* ycbcr_info) {
+ absl::optional<gpu::VulkanYCbCrInfo>* ycbcr_info) {
DCHECK_CALLED_ON_VALID_THREAD(vulkan_thread_checker_);
if (vk_device_ != vk_device) {
@@ -297,7 +286,7 @@ bool SysmemBufferCollection::CreateVkImage(
buffers_info_.settings.image_format_constraints.color_space[0].type;
switch (color_space) {
case fuchsia::sysmem::ColorSpaceType::SRGB:
- *ycbcr_info = base::nullopt;
+ *ycbcr_info = absl::nullopt;
break;
case fuchsia::sysmem::ColorSpaceType::REC709: {
diff --git a/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.h b/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.h
index 6a3ce46bd6b..4c3462807d0 100644
--- a/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.h
+++ b/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.h
@@ -12,11 +12,11 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "gpu/ipc/common/vulkan_ycbcr_info.h"
#include "gpu/vulkan/fuchsia/vulkan_fuchsia_ext.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_pixmap_handle.h"
@@ -60,7 +60,6 @@ class SysmemBufferCollection
gfx::BufferUsage usage,
VkDevice vk_device,
size_t min_buffer_count,
- bool force_protected,
bool register_with_image_pipe);
// Must not be called more than once.
@@ -79,7 +78,7 @@ class SysmemBufferCollection
VkImageCreateInfo* vk_image_info,
VkDeviceMemory* vk_device_memory,
VkDeviceSize* mem_allocation_size,
- base::Optional<gpu::VulkanYCbCrInfo>* ycbcr_info);
+ absl::optional<gpu::VulkanYCbCrInfo>* ycbcr_info);
gfx::SysmemBufferCollectionId id() const { return id_; }
size_t num_buffers() const { return buffers_info_.buffer_count; }
diff --git a/chromium/ui/ozone/platform/scenic/sysmem_buffer_manager.cc b/chromium/ui/ozone/platform/scenic/sysmem_buffer_manager.cc
index 8d55a71262b..7434a3bad53 100644
--- a/chromium/ui/ozone/platform/scenic/sysmem_buffer_manager.cc
+++ b/chromium/ui/ozone/platform/scenic/sysmem_buffer_manager.cc
@@ -12,6 +12,17 @@
namespace ui {
+namespace {
+
+std::string GetProcessName() {
+ char name[ZX_MAX_NAME_LEN] = {};
+ zx_status_t status =
+ zx::process::self()->get_property(ZX_PROP_NAME, name, sizeof(name));
+ return (status == ZX_OK) ? std::string(name) : "";
+}
+
+} // namespace
+
SysmemBufferManager::SysmemBufferManager(
ScenicSurfaceFactory* scenic_surface_factory)
: scenic_surface_factory_(scenic_surface_factory) {}
@@ -26,6 +37,8 @@ void SysmemBufferManager::Initialize(
DCHECK(collections_.empty());
DCHECK(!allocator_);
allocator_.Bind(std::move(allocator));
+ allocator_->SetDebugClientInfo(GetProcessName() + "-SysmemBufferManager",
+ base::GetCurrentProcId());
}
void SysmemBufferManager::Shutdown() {
@@ -44,7 +57,6 @@ scoped_refptr<SysmemBufferCollection> SysmemBufferManager::CreateCollection(
if (!result->Initialize(allocator_.get(), scenic_surface_factory_,
/*token_channel=*/zx::channel(), size, format, usage,
vk_device, min_buffer_count,
- /*force_protected=*/false,
/*register_with_image_pipe=*/false)) {
return nullptr;
}
@@ -61,13 +73,11 @@ SysmemBufferManager::ImportSysmemBufferCollection(
gfx::BufferFormat format,
gfx::BufferUsage usage,
size_t min_buffer_count,
- bool force_protected,
bool register_with_image_pipe) {
auto result = base::MakeRefCounted<SysmemBufferCollection>(id);
if (!result->Initialize(allocator_.get(), scenic_surface_factory_,
std::move(token), size, format, usage, vk_device,
- min_buffer_count, force_protected,
- register_with_image_pipe)) {
+ min_buffer_count, register_with_image_pipe)) {
return nullptr;
}
RegisterCollection(result.get());
diff --git a/chromium/ui/ozone/platform/scenic/sysmem_buffer_manager.h b/chromium/ui/ozone/platform/scenic/sysmem_buffer_manager.h
index eb2dbaa6f5f..27e0d7f97e4 100644
--- a/chromium/ui/ozone/platform/scenic/sysmem_buffer_manager.h
+++ b/chromium/ui/ozone/platform/scenic/sysmem_buffer_manager.h
@@ -53,7 +53,6 @@ class SysmemBufferManager {
gfx::BufferFormat format,
gfx::BufferUsage usage,
size_t min_buffer_count,
- bool force_protected,
bool register_with_image_pipe);
scoped_refptr<SysmemBufferCollection> GetCollectionById(
diff --git a/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc b/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc
index 83a4793df22..8f3224c3e62 100644
--- a/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc
+++ b/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc
@@ -36,11 +36,8 @@ namespace ui {
VulkanImplementationScenic::VulkanImplementationScenic(
ScenicSurfaceFactory* scenic_surface_factory,
SysmemBufferManager* sysmem_buffer_manager,
- bool allow_protected_memory,
- bool enforce_protected_memory)
- : VulkanImplementation(false /* use_swiftshader */,
- allow_protected_memory,
- enforce_protected_memory),
+ bool allow_protected_memory)
+ : VulkanImplementation(false /* use_swiftshader */, allow_protected_memory),
scenic_surface_factory_(scenic_surface_factory),
sysmem_buffer_manager_(sysmem_buffer_manager) {}
@@ -110,9 +107,8 @@ VulkanImplementationScenic::CreateViewSurface(gfx::AcceleratedWidget window) {
LOG(FATAL) << "vkCreateImagePipeSurfaceFUCHSIA failed: " << result;
}
- return std::make_unique<gpu::VulkanSurface>(
- vulkan_instance_.vk_instance(), window, surface,
- enforce_protected_memory() /* use_protected_memory */);
+ return std::make_unique<gpu::VulkanSurface>(vulkan_instance_.vk_instance(),
+ window, surface);
}
bool VulkanImplementationScenic::GetPhysicalDevicePresentationSupport(
@@ -258,7 +254,7 @@ VulkanImplementationScenic::CreateImageFromGpuMemoryHandle(
VkImageCreateInfo vk_image_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
VkDeviceMemory vk_device_memory = VK_NULL_HANDLE;
VkDeviceSize vk_device_size = 0;
- base::Optional<gpu::VulkanYCbCrInfo> ycbcr_info;
+ absl::optional<gpu::VulkanYCbCrInfo> ycbcr_info;
if (!collection->CreateVkImage(gmb_handle.native_pixmap_handle.buffer_index,
device_queue->GetVulkanDevice(), size,
&vk_image, &vk_image_info, &vk_device_memory,
@@ -307,14 +303,10 @@ VulkanImplementationScenic::RegisterSysmemBufferCollection(
gfx::Size size,
size_t min_buffer_count,
bool register_with_image_pipe) {
- // SCANOUT images must be protected in protected mode.
- bool force_protected =
- usage == gfx::BufferUsage::SCANOUT && enforce_protected_memory();
-
fuchsia::images::ImagePipe2Ptr image_pipe = nullptr;
auto buffer_collection = sysmem_buffer_manager_->ImportSysmemBufferCollection(
device, id, std::move(token), size, format, usage, min_buffer_count,
- force_protected, register_with_image_pipe);
+ register_with_image_pipe);
if (!buffer_collection)
return nullptr;
diff --git a/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.h b/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.h
index 04c371db8d1..38c21a78f71 100644
--- a/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.h
+++ b/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.h
@@ -21,8 +21,7 @@ class VulkanImplementationScenic : public gpu::VulkanImplementation {
public:
VulkanImplementationScenic(ScenicSurfaceFactory* scenic_surface_factory,
SysmemBufferManager* sysmem_buffer_manager,
- bool allow_protected_memory,
- bool enforce_protected_memory);
+ bool allow_protected_memory);
~VulkanImplementationScenic() override;
// VulkanImplementation:
diff --git a/chromium/ui/ozone/platform/wayland/BUILD.gn b/chromium/ui/ozone/platform/wayland/BUILD.gn
index 578e7a50ab6..85268ff29d9 100644
--- a/chromium/ui/ozone/platform/wayland/BUILD.gn
+++ b/chromium/ui/ozone/platform/wayland/BUILD.gn
@@ -48,6 +48,10 @@ source_set("wayland") {
"host/gtk_primary_selection_device_manager.h",
"host/gtk_primary_selection_offer.cc",
"host/gtk_primary_selection_offer.h",
+ "host/gtk_shell1.cc",
+ "host/gtk_shell1.h",
+ "host/gtk_surface1.cc",
+ "host/gtk_surface1.h",
"host/shell_object_factory.cc",
"host/shell_object_factory.h",
"host/shell_popup_wrapper.cc",
@@ -67,8 +71,6 @@ source_set("wayland") {
"host/wayland_connection.h",
"host/wayland_cursor.cc",
"host/wayland_cursor.h",
- "host/wayland_cursor_factory.cc",
- "host/wayland_cursor_factory.h",
"host/wayland_cursor_position.cc",
"host/wayland_cursor_position.h",
"host/wayland_data_device.cc",
@@ -136,6 +138,8 @@ source_set("wayland") {
"host/wayland_zcr_cursor_shapes.h",
"host/wayland_zwp_linux_dmabuf.cc",
"host/wayland_zwp_linux_dmabuf.h",
+ "host/wayland_zwp_pointer_gestures.cc",
+ "host/wayland_zwp_pointer_gestures.h",
"host/xdg_foreign_wrapper.cc",
"host/xdg_foreign_wrapper.h",
"host/xdg_popup_wrapper_impl.cc",
@@ -176,12 +180,16 @@ source_set("wayland") {
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//skia",
+ "//third_party/libsync",
+ "//third_party/wayland:wayland_util",
"//third_party/wayland-protocols:cursor_shapes_protocol",
"//third_party/wayland-protocols:extended_drag",
"//third_party/wayland-protocols:gtk_primary_selection_protocol",
+ "//third_party/wayland-protocols:gtk_shell_protocol",
"//third_party/wayland-protocols:keyboard_extension_protocol",
"//third_party/wayland-protocols:linux_dmabuf_protocol",
"//third_party/wayland-protocols:linux_explicit_synchronization_protocol",
+ "//third_party/wayland-protocols:pointer_gestures_protocol",
"//third_party/wayland-protocols:presentation_time_protocol",
"//third_party/wayland-protocols:primary_selection_protocol",
"//third_party/wayland-protocols:text_input_protocol",
@@ -197,6 +205,7 @@ source_set("wayland") {
"//ui/base/cursor:theme_manager",
"//ui/base/cursor/mojom:cursor_type",
"//ui/base/dragdrop:types",
+ "//ui/base/dragdrop/mojom",
"//ui/base/ime/linux",
"//ui/events",
"//ui/events:dom_keycode_converter",
@@ -220,12 +229,8 @@ source_set("wayland") {
if (use_gtk) {
sources += [
- "host/gtk_ui_delegate_wayland.cc",
- "host/gtk_ui_delegate_wayland.h",
- ]
- deps += [
- "//ui/gtk:gtk_ui_delegate",
- "//ui/gtk/wayland",
+ "host/linux_ui_delegate_wayland.cc",
+ "host/linux_ui_delegate_wayland.h",
]
}
@@ -237,6 +242,13 @@ source_set("wayland") {
]
}
+ if (!is_chromeos) {
+ sources += [
+ "host/wayland_cursor_factory.cc",
+ "host/wayland_cursor_factory.h",
+ ]
+ }
+
defines = [ "OZONE_IMPLEMENTATION" ]
if (use_system_libwayland) {
@@ -385,7 +397,6 @@ source_set("wayland_unittests") {
"gpu/wayland_overlay_manager_unittest.cc",
"host/wayland_clipboard_unittest.cc",
"host/wayland_connection_unittest.cc",
- "host/wayland_cursor_factory_unittest.cc",
"host/wayland_data_drag_controller_unittest.cc",
"host/wayland_event_source_unittest.cc",
"host/wayland_input_method_context_unittest.cc",
@@ -419,6 +430,7 @@ source_set("wayland_unittests") {
"//ui/base:buildflags",
"//ui/base/cursor",
"//ui/base/dragdrop:types",
+ "//ui/base/dragdrop/mojom",
"//ui/base/ime/linux",
"//ui/events/ozone/layout",
"//ui/gfx/linux:test_support",
@@ -428,6 +440,10 @@ source_set("wayland_unittests") {
"//ui/platform_window/wm",
]
+ if (!is_chromeos) {
+ sources += [ "host/wayland_cursor_factory_unittest.cc" ]
+ }
+
import("//ui/base/ui_features.gni")
if (use_xkbcommon) {
deps += [ "//ui/events/keycodes:xkb" ]
diff --git a/chromium/ui/ozone/platform/wayland/DEPS b/chromium/ui/ozone/platform/wayland/DEPS
index a035c9180a4..2bb7f7814ae 100644
--- a/chromium/ui/ozone/platform/wayland/DEPS
+++ b/chromium/ui/ozone/platform/wayland/DEPS
@@ -2,12 +2,11 @@ include_rules = [
"+ui/base/buildflags.h", # Doesn't bring in all of ui/base.
"+ui/base/hit_test.h", # UI hit test doesn't bring in all of ui/base.
"+ui/base/ui_base_features.h",
- "+ui/gtk/gtk_ui_delegate.h",
- "+ui/gtk/wayland/gtk_ui_delegate_wayland_base.h",
"+mojo/public",
"+third_party/wayland",
"+ui/base/clipboard/clipboard_constants.h",
"+ui/base/dragdrop/drag_drop_types.h",
+ "+ui/base/dragdrop/mojom",
"+ui/base/clipboard/file_info.h",
"+ui/base/dragdrop/os_exchange_data.h",
"+ui/base/dragdrop/os_exchange_data_provider_non_backed.h",
diff --git a/chromium/ui/ozone/platform/wayland/OWNERS b/chromium/ui/ozone/platform/wayland/OWNERS
index 1aa8e7e3f6f..9469bd25b83 100644
--- a/chromium/ui/ozone/platform/wayland/OWNERS
+++ b/chromium/ui/ozone/platform/wayland/OWNERS
@@ -1,3 +1,4 @@
msisov@igalia.com
nickdiego@igalia.com
tonikitoo@igalia.com
+adunaev@igalia.com
diff --git a/chromium/ui/ozone/platform/wayland/common/data_util.cc b/chromium/ui/ozone/platform/wayland/common/data_util.cc
index 21a372f1f9a..0b0352eb047 100644
--- a/chromium/ui/ozone/platform/wayland/common/data_util.cc
+++ b/chromium/ui/ozone/platform/wayland/common/data_util.cc
@@ -10,6 +10,7 @@
#include "base/check.h"
#include "base/logging.h"
#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/clipboard/clipboard_constants.h"
#include "ui/base/clipboard/file_info.h"
@@ -41,6 +42,8 @@ int MimeTypeToFormat(const std::string& mime_type) {
return OSExchangeData::URL;
if (mime_type == ui::kMimeTypeHTML)
return OSExchangeData::HTML;
+ if (base::StartsWith(mime_type, ui::kMimeTypeOctetStream))
+ return OSExchangeData::FILE_CONTENTS;
return 0;
}
@@ -203,6 +206,14 @@ bool ExtractOSExchangeData(const OSExchangeData& exchange_data,
out_content->append(base::UTF16ToUTF8(data));
return true;
}
+ if (base::StartsWith(mime_type, ui::kMimeTypeOctetStream) &&
+ exchange_data.HasFileContents()) {
+ base::FilePath filename;
+ std::string file_contents;
+ exchange_data.GetFileContents(&filename, &file_contents);
+ out_content->append(file_contents);
+ return true;
+ }
if (exchange_data.HasString()) {
std::u16string data;
exchange_data.GetString(&data);
diff --git a/chromium/ui/ozone/platform/wayland/common/wayland_object.cc b/chromium/ui/ozone/platform/wayland/common/wayland_object.cc
index 8827a5e9f49..5f63eb03901 100644
--- a/chromium/ui/ozone/platform/wayland/common/wayland_object.cc
+++ b/chromium/ui/ozone/platform/wayland/common/wayland_object.cc
@@ -8,13 +8,16 @@
#include <cursor-shapes-unstable-v1-client-protocol.h>
#include <extended-drag-unstable-v1-client-protocol.h>
#include <gtk-primary-selection-client-protocol.h>
+#include <gtk-shell-client-protocol.h>
#include <keyboard-extension-unstable-v1-client-protocol.h>
#include <linux-dmabuf-unstable-v1-client-protocol.h>
#include <linux-explicit-synchronization-unstable-v1-client-protocol.h>
+#include <pointer-gestures-unstable-v1-client-protocol.h>
#include <presentation-time-client-protocol.h>
#include <primary-selection-unstable-v1-client-protocol.h>
#include <text-input-unstable-v1-client-protocol.h>
#include <viewporter-client-protocol.h>
+#include <wayland-client-core.h>
#include <wayland-cursor.h>
#include <wayland-drm-client-protocol.h>
#include <xdg-decoration-unstable-v1-client-protocol.h>
@@ -96,6 +99,14 @@ const wl_interface* ObjectTraits<gtk_primary_selection_source>::interface =
void (*ObjectTraits<gtk_primary_selection_source>::deleter)(
gtk_primary_selection_source*) = &gtk_primary_selection_source_destroy;
+const wl_interface* ObjectTraits<gtk_shell1>::interface = &gtk_shell1_interface;
+void (*ObjectTraits<gtk_shell1>::deleter)(gtk_shell1*) = &gtk_shell1_destroy;
+
+const wl_interface* ObjectTraits<gtk_surface1>::interface =
+ &gtk_surface1_interface;
+void (*ObjectTraits<gtk_surface1>::deleter)(gtk_surface1*) =
+ &gtk_surface1_destroy;
+
const wl_interface*
ObjectTraits<zwp_primary_selection_device_manager_v1>::interface =
&zwp_primary_selection_device_manager_v1_interface;
@@ -158,6 +169,10 @@ void (*ObjectTraits<wl_data_source>::deleter)(wl_data_source*) =
const wl_interface* ObjectTraits<wl_drm>::interface = &wl_drm_interface;
void (*ObjectTraits<wl_drm>::deleter)(wl_drm*) = &wl_drm_destroy;
+const wl_interface* ObjectTraits<wl_event_queue>::interface = nullptr;
+void (*ObjectTraits<wl_event_queue>::deleter)(wl_event_queue*) =
+ &wl_event_queue_destroy;
+
const wl_interface* ObjectTraits<wl_display>::interface = &wl_display_interface;
void (*ObjectTraits<wl_display>::deleter)(wl_display*) = &wl_display_disconnect;
@@ -214,6 +229,19 @@ const wl_interface* ObjectTraits<struct wp_presentation_feedback>::interface =
void (*ObjectTraits<struct wp_presentation_feedback>::deleter)(
struct wp_presentation_feedback*) = &wp_presentation_feedback_destroy;
+const wl_interface* ObjectTraits<struct wl_proxy>::interface = nullptr;
+void (*ObjectTraits<wl_proxy>::deleter)(void*) = &wl_proxy_wrapper_destroy;
+
+const wl_interface* ObjectTraits<zwp_pointer_gesture_pinch_v1>::interface =
+ &zwp_pointer_gesture_pinch_v1_interface;
+void (*ObjectTraits<zwp_pointer_gesture_pinch_v1>::deleter)(
+ zwp_pointer_gesture_pinch_v1*) = &zwp_pointer_gesture_pinch_v1_destroy;
+
+const wl_interface* ObjectTraits<zwp_pointer_gestures_v1>::interface =
+ &zwp_pointer_gestures_v1_interface;
+void (*ObjectTraits<zwp_pointer_gestures_v1>::deleter)(
+ zwp_pointer_gestures_v1*) = &zwp_pointer_gestures_v1_destroy;
+
const wl_interface* ObjectTraits<wp_viewport>::interface =
&wp_viewport_interface;
void (*ObjectTraits<wp_viewport>::deleter)(wp_viewport*) = &wp_viewport_destroy;
diff --git a/chromium/ui/ozone/platform/wayland/common/wayland_object.h b/chromium/ui/ozone/platform/wayland/common/wayland_object.h
index d609c6150fa..ef805db101b 100644
--- a/chromium/ui/ozone/platform/wayland/common/wayland_object.h
+++ b/chromium/ui/ozone/platform/wayland/common/wayland_object.h
@@ -13,6 +13,8 @@ struct gtk_primary_selection_device;
struct gtk_primary_selection_device_manager;
struct gtk_primary_selection_offer;
struct gtk_primary_selection_source;
+struct gtk_shell1;
+struct gtk_surface1;
struct zwp_primary_selection_device_v1;
struct zwp_primary_selection_device_manager_v1;
struct zwp_primary_selection_offer_v1;
@@ -26,6 +28,7 @@ struct wl_data_device;
struct wl_data_offer;
struct wl_data_source;
struct wl_drm;
+struct wl_event_queue;
struct wl_keyboard;
struct wl_output;
struct wl_pointer;
@@ -40,6 +43,7 @@ struct wl_surface;
struct wl_touch;
struct wp_presentation;
struct wp_presentation_feedback;
+struct wl_proxy;
struct wp_viewport;
struct wp_viewporter;
struct xdg_wm_base;
@@ -59,6 +63,8 @@ struct zwp_linux_dmabuf_v1;
struct zwp_linux_buffer_release_v1;
struct zwp_linux_explicit_synchronization_v1;
struct zwp_linux_surface_synchronization_v1;
+struct zwp_pointer_gesture_pinch_v1;
+struct zwp_pointer_gestures_v1;
struct zxdg_shell_v6;
struct zxdg_surface_v6;
struct zxdg_toplevel_v6;
@@ -113,6 +119,18 @@ struct ObjectTraits<gtk_primary_selection_source> {
};
template <>
+struct ObjectTraits<gtk_shell1> {
+ static const wl_interface* interface;
+ static void (*deleter)(gtk_shell1*);
+};
+
+template <>
+struct ObjectTraits<gtk_surface1> {
+ static const wl_interface* interface;
+ static void (*deleter)(gtk_surface1*);
+};
+
+template <>
struct ObjectTraits<zwp_primary_selection_device_manager_v1> {
static const wl_interface* interface;
static void (*deleter)(zwp_primary_selection_device_manager_v1*);
@@ -190,6 +208,12 @@ struct ObjectTraits<wl_drm> {
};
template <>
+struct ObjectTraits<wl_event_queue> {
+ static const wl_interface* interface;
+ static void (*deleter)(wl_event_queue*);
+};
+
+template <>
struct ObjectTraits<wl_display> {
static const wl_interface* interface;
static void (*deleter)(wl_display*);
@@ -280,6 +304,25 @@ struct ObjectTraits<wp_presentation_feedback> {
};
template <>
+struct ObjectTraits<wl_proxy> {
+ // Interface is null for proxy.
+ static const wl_interface* interface;
+ static void (*deleter)(void*);
+};
+
+template <>
+struct ObjectTraits<zwp_pointer_gesture_pinch_v1> {
+ static const wl_interface* interface;
+ static void (*deleter)(zwp_pointer_gesture_pinch_v1*);
+};
+
+template <>
+struct ObjectTraits<zwp_pointer_gestures_v1> {
+ static const wl_interface* interface;
+ static void (*deleter)(zwp_pointer_gestures_v1*);
+};
+
+template <>
struct ObjectTraits<wp_viewport> {
static const wl_interface* interface;
static void (*deleter)(wp_viewport*);
@@ -468,6 +511,7 @@ class Object : public std::unique_ptr<T, Deleter> {
template <typename T>
wl::Object<T> Bind(wl_registry* registry, uint32_t name, uint32_t version) {
+ DCHECK(ObjectTraits<T>::interface);
return wl::Object<T>(wl::bind_registry<T>(
registry, name, ObjectTraits<T>::interface, version));
}
diff --git a/chromium/ui/ozone/platform/wayland/common/wayland_util.cc b/chromium/ui/ozone/platform/wayland/common/wayland_util.cc
index 6d7b05906af..e368b4a84b6 100644
--- a/chromium/ui/ozone/platform/wayland/common/wayland_util.cc
+++ b/chromium/ui/ozone/platform/wayland/common/wayland_util.cc
@@ -253,11 +253,6 @@ gfx::Size ApplyWaylandTransform(const gfx::Size& size,
return result;
}
-bool IsMenuType(ui::PlatformWindowType type) {
- return type == ui::PlatformWindowType::kMenu ||
- type == ui::PlatformWindowType::kPopup;
-}
-
ui::WaylandWindow* RootWindowFromWlSurface(wl_surface* surface) {
if (!surface)
return nullptr;
diff --git a/chromium/ui/ozone/platform/wayland/common/wayland_util.h b/chromium/ui/ozone/platform/wayland/common/wayland_util.h
index 8d8b12f9cc1..9546e29e4ed 100644
--- a/chromium/ui/ozone/platform/wayland/common/wayland_util.h
+++ b/chromium/ui/ozone/platform/wayland/common/wayland_util.h
@@ -75,9 +75,6 @@ gfx::Rect ApplyWaylandTransform(const gfx::Rect& rect,
gfx::Size ApplyWaylandTransform(const gfx::Size& size,
wl_output_transform transform);
-// Says if the type is kPopup or kMenu.
-bool IsMenuType(ui::PlatformWindowType type);
-
// Returns the root WaylandWindow for the given wl_surface.
ui::WaylandWindow* RootWindowFromWlSurface(wl_surface* surface);
diff --git a/chromium/ui/ozone/platform/wayland/emulate/wayland_input_emulate.cc b/chromium/ui/ozone/platform/wayland/emulate/wayland_input_emulate.cc
index bc939e793ca..d365526be0a 100644
--- a/chromium/ui/ozone/platform/wayland/emulate/wayland_input_emulate.cc
+++ b/chromium/ui/ozone/platform/wayland/emulate/wayland_input_emulate.cc
@@ -10,7 +10,6 @@
#include <memory>
-#include "base/callback_forward.h"
#include "base/logging.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/platform_window/common/platform_window_defaults.h"
@@ -43,7 +42,7 @@ WaylandInputEmulate::WaylandInputEmulate() {
wayland_proxy->SetDelegate(this);
- registry_ = wl_display_get_registry(wayland_proxy->GetDisplay());
+ registry_ = wl_display_get_registry(wayland_proxy->GetDisplayWrapper());
if (!registry_)
LOG(FATAL) << "Failed to get Wayland registry";
@@ -53,7 +52,7 @@ WaylandInputEmulate::WaylandInputEmulate() {
wl_registry_add_listener(registry_, &registry_listener, this);
// Roundtrip one time to get the weston-test global.
- wl_display_roundtrip(wayland_proxy->GetDisplay());
+ wayland_proxy->RoundTripQueue();
if (!weston_test_)
LOG(FATAL) << "weston-test is not available.";
diff --git a/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc b/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
index 0e419c88b06..1fa7600f120 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
@@ -13,7 +13,6 @@
#include "base/files/platform_file.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
-#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/buffer_usage_util.h"
@@ -47,20 +46,33 @@ bool GbmPixmapWayland::InitializeBuffer(gfx::Size size,
return false;
const uint32_t fourcc_format = GetFourCCFormatFromBufferFormat(format);
- auto gbm_usage = ui::BufferUsageToGbmFlags(usage);
- std::vector<uint64_t> modifiers;
- if (!(gbm_usage & GBM_BO_USE_LINEAR))
- modifiers = buffer_manager_->GetModifiersForBufferFormat(format);
+ const uint32_t gbm_flags = ui::BufferUsageToGbmFlags(usage);
+ auto modifiers = buffer_manager_->GetModifiersForBufferFormat(format);
+
+ // Create buffer object without format modifiers unless they are explicitly
+ // advertised by the Wayland compositor, via linux-dmabuf protocol.
+ if (modifiers.empty()) {
+ gbm_bo_ = buffer_manager_->gbm_device()->CreateBuffer(fourcc_format, size,
+ gbm_flags);
+ } else {
+ // When buffer |usage| implies on GBM_BO_USE_LINEAR, pass in
+ // DRM_FORMAT_MOD_LINEAR, i.e: no tiling, when creating gbm buffers,
+ // otherwise it fails to create BOs.
+ if (gbm_flags & GBM_BO_USE_LINEAR)
+ modifiers = {DRM_FORMAT_MOD_LINEAR};
+ gbm_bo_ = buffer_manager_->gbm_device()->CreateBufferWithModifiers(
+ fourcc_format, size, gbm_flags, modifiers);
+ }
- gbm_bo_ = buffer_manager_->gbm_device()->CreateBufferWithModifiers(
- fourcc_format, size, gbm_usage, modifiers);
if (!gbm_bo_) {
LOG(ERROR) << "Cannot create bo with format= "
- << gfx::BufferFormatToString(format) << " and usage "
- << gfx::BufferUsageToString(usage);
+ << gfx::BufferFormatToString(format)
+ << " and usage=" << gfx::BufferUsageToString(usage);
return false;
}
+ DVLOG(3) << "Created gbm bo. format= " << gfx::BufferFormatToString(format)
+ << " usage=" << gfx::BufferUsageToString(usage);
CreateDmabufBasedBuffer();
return true;
}
@@ -120,11 +132,21 @@ bool GbmPixmapWayland::ScheduleOverlayPlane(
bool enable_blend,
std::vector<gfx::GpuFence> acquire_fences,
std::vector<gfx::GpuFence> release_fences) {
- // If the widget this pixmap backs has not been assigned before, do it now.
- if (widget_ == gfx::kNullAcceleratedWidget)
- SetAcceleratedWiget(widget);
-
- DCHECK_EQ(widget_, widget);
+ DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
+
+ // It's possible for a buffer to be attached to a different widget or
+ // wl_surface if this buffer represents an overlay and is being tab-dragged to
+ // a different window. Recreate wl_buffer handle if this happens.
+ // TODO(fangzhoug): Remove this workaround once better buffer management is
+ // implemented.
+ z_order_ = z_order_set_ ? z_order_ : plane_z_order;
+ if (widget_ != widget || z_order_ != plane_z_order) {
+ buffer_manager_->DestroyBuffer(widget_, buffer_id_);
+ CreateDmabufBasedBuffer();
+ widget_ = widget;
+ z_order_ = plane_z_order;
+ }
+ z_order_set_ = true;
auto* surface = buffer_manager_->GetSurface(widget);
// This must never be hit.
diff --git a/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h b/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h
index a9b3932b1a8..9ee2aafe0d5 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h
+++ b/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h
@@ -71,6 +71,11 @@ class GbmPixmapWayland : public gfx::NativePixmap {
// A unique ID to identify the buffer for this pixmap.
const uint32_t buffer_id_;
+ // Represents the z-axis order of the wayland surface this buffer is attach
+ // to.
+ int32_t z_order_ = 0;
+ bool z_order_set_ = false;
+
DISALLOW_COPY_AND_ASSIGN(GbmPixmapWayland);
};
diff --git a/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc b/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
index 81d1fddbb71..aba3311b613 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
@@ -4,6 +4,7 @@
#include "ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h"
+#include <sync/sync.h>
#include <memory>
#include "base/bind.h"
@@ -274,7 +275,8 @@ void GbmSurfacelessWayland::SetNoGLFlushForTests() {
}
void GbmSurfacelessWayland::OnSubmission(BufferId buffer_id,
- const gfx::SwapResult& swap_result) {
+ const gfx::SwapResult& swap_result,
+ gfx::GpuFenceHandle release_fence) {
// submitted_frames_ may temporarily have more than one buffer in it if
// buffers are released out of order by the Wayland server.
DCHECK(!submitted_frames_.empty() || background_buffer_id_ == buffer_id);
@@ -292,6 +294,19 @@ void GbmSurfacelessWayland::OnSubmission(BufferId buffer_id,
submitted_frame->swap_result = swap_result;
}
submitted_frame->pending_presentation_buffers.insert(buffer_id);
+
+ // Accumulate release fences into a single fence.
+ if (!release_fence.is_null()) {
+ if (submitted_frame->merged_release_fence_fd.is_valid()) {
+ submitted_frame->merged_release_fence_fd.reset(
+ sync_merge("", submitted_frame->merged_release_fence_fd.get(),
+ release_fence.owned_fd.get()));
+ } else {
+ submitted_frame->merged_release_fence_fd =
+ std::move(release_fence.owned_fd);
+ }
+ DCHECK(submitted_frame->merged_release_fence_fd.is_valid());
+ }
break;
}
}
@@ -307,8 +322,13 @@ void GbmSurfacelessWayland::OnSubmission(BufferId buffer_id,
submitted_frames_.erase(submitted_frames_.begin());
submitted_frame->overlays.clear();
+ gfx::GpuFenceHandle release_fence;
+ if (submitted_frame->merged_release_fence_fd.is_valid())
+ release_fence.owned_fd =
+ std::move(submitted_frame->merged_release_fence_fd);
std::move(submitted_frame->completion_callback)
- .Run(gfx::SwapCompletionResult(submitted_frame->swap_result));
+ .Run(gfx::SwapCompletionResult(submitted_frame->swap_result,
+ std::move(release_fence)));
pending_presentation_frames_.push_back(std::move(submitted_frame));
}
diff --git a/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h b/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
index 2553c380b51..781c761fe84 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
+++ b/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
@@ -77,7 +77,8 @@ class GbmSurfacelessWayland : public gl::SurfacelessEGL,
// WaylandSurfaceGpu overrides:
void OnSubmission(BufferId buffer_id,
- const gfx::SwapResult& swap_result) override;
+ const gfx::SwapResult& swap_result,
+ gfx::GpuFenceHandle release_fence) override;
void OnPresentation(BufferId buffer_id,
const gfx::PresentationFeedback& feedback) override;
@@ -99,7 +100,9 @@ class GbmSurfacelessWayland : public gl::SurfacelessEGL,
std::vector<gl::GLSurfaceOverlay> overlays;
SwapCompletionCallback completion_callback;
PresentationCallback presentation_callback;
-
+ // Merged release fence fd. This is taken as the union of all release
+ // fences for a particular OnSubmission.
+ base::ScopedFD merged_release_fence_fd;
bool schedule_planes_succeeded = false;
// Maps |buffer_id| to an OverlayPlane, used for committing overlays and
diff --git a/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.cc b/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.cc
index 5383fb8209c..39c576acdf5 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.cc
@@ -133,7 +133,9 @@ GLSurfaceEglReadbackWayland::~GLSurfaceEglReadbackWayland() {
void GLSurfaceEglReadbackWayland::OnSubmission(
uint32_t buffer_id,
- const gfx::SwapResult& swap_result) {
+ const gfx::SwapResult& swap_result,
+ gfx::GpuFenceHandle release_fence) {
+ DCHECK(release_fence.is_null());
--pending_frames_;
if (in_flight_pixel_buffers_.front()) {
diff --git a/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.h b/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.h
index 6fb4a60c324..680088d7d9b 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.h
+++ b/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.h
@@ -73,7 +73,8 @@ class GLSurfaceEglReadbackWayland : public GLSurfaceEglReadback,
// WaylandSurfaceGpu:
void OnSubmission(uint32_t buffer_id,
- const gfx::SwapResult& swap_result) override;
+ const gfx::SwapResult& swap_result,
+ gfx::GpuFenceHandle release_fence) override;
void OnPresentation(uint32_t buffer_id,
const gfx::PresentationFeedback& feedback) override;
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc b/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
index e1585512283..a0206f94eb7 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
@@ -63,7 +63,8 @@ void WaylandBufferManagerGpu::Initialize(
void WaylandBufferManagerGpu::OnSubmission(gfx::AcceleratedWidget widget,
uint32_t buffer_id,
- gfx::SwapResult swap_result) {
+ gfx::SwapResult swap_result,
+ gfx::GpuFenceHandle release_fence) {
base::AutoLock scoped_lock(lock_);
DCHECK(io_thread_runner_->BelongsToCurrentThread());
DCHECK_LE(commit_thread_runners_.count(widget), 1u);
@@ -74,7 +75,8 @@ void WaylandBufferManagerGpu::OnSubmission(gfx::AcceleratedWidget widget,
it->second->PostTask(
FROM_HERE,
base::BindOnce(&WaylandBufferManagerGpu::SubmitSwapResultOnOriginThread,
- base::Unretained(this), widget, buffer_id, swap_result));
+ base::Unretained(this), widget, buffer_id, swap_result,
+ std::move(release_fence)));
}
void WaylandBufferManagerGpu::OnPresentation(
@@ -322,12 +324,13 @@ void WaylandBufferManagerGpu::ForgetTaskRunnerForWidgetOnIOThread(
void WaylandBufferManagerGpu::SubmitSwapResultOnOriginThread(
gfx::AcceleratedWidget widget,
uint32_t buffer_id,
- gfx::SwapResult swap_result) {
+ gfx::SwapResult swap_result,
+ gfx::GpuFenceHandle release_fence) {
DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
auto* surface = GetSurface(widget);
// The surface might be destroyed by the time the swap result is provided.
if (surface)
- surface->OnSubmission(buffer_id, swap_result);
+ surface->OnSubmission(buffer_id, swap_result, std::move(release_fence));
}
void WaylandBufferManagerGpu::SubmitPresentationOnOriginThread(
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h b/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
index 56579442530..3917d70a333 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
@@ -59,7 +59,8 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
// OnSubmission call, it can schedule a new buffer for swap.
void OnSubmission(gfx::AcceleratedWidget widget,
uint32_t buffer_id,
- gfx::SwapResult swap_result) override;
+ gfx::SwapResult swap_result,
+ gfx::GpuFenceHandle release_fence_handle) override;
void OnPresentation(gfx::AcceleratedWidget widget,
uint32_t buffer_id,
const gfx::PresentationFeedback& feedback) override;
@@ -172,7 +173,8 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
// presentation results.
void SubmitSwapResultOnOriginThread(gfx::AcceleratedWidget widget,
uint32_t buffer_id,
- gfx::SwapResult swap_result);
+ gfx::SwapResult swap_result,
+ gfx::GpuFenceHandle release_fence);
void SubmitPresentationOnOriginThread(
gfx::AcceleratedWidget widget,
uint32_t buffer_id,
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc b/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc
index bb7029b7d29..182ded32455 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc
@@ -275,7 +275,9 @@ void WaylandCanvasSurface::ProcessUnsubmittedBuffers() {
}
void WaylandCanvasSurface::OnSubmission(uint32_t buffer_id,
- const gfx::SwapResult& swap_result) {
+ const gfx::SwapResult& swap_result,
+ gfx::GpuFenceHandle release_fence) {
+ DCHECK(release_fence.is_null());
// We may get an OnSubmission callback for a buffer that was submitted
// before a ResizeCanvas call, which clears all our buffers. Check to
// see if we still know about this buffer. If we know about this buffer
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h b/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h
index e052981ad3e..6da6c52d3f2 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h
@@ -64,7 +64,8 @@ class WaylandCanvasSurface : public SurfaceOzoneCanvas,
// WaylandSurfaceGpu overrides:
void OnSubmission(uint32_t buffer_id,
- const gfx::SwapResult& swap_result) override;
+ const gfx::SwapResult& swap_result,
+ gfx::GpuFenceHandle release_fence) override;
void OnPresentation(uint32_t buffer_id,
const gfx::PresentationFeedback& feedback) override;
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.cc b/chromium/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.cc
index 089ca8b2cdd..9ced6a630f6 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.cc
@@ -45,8 +45,8 @@ bool WaylandOverlayManager::CanHandleCandidate(
if (!gfx::IsNearestRectWithinDistance(candidate.display_rect, 0.01f))
return false;
- if (candidate.is_clipped && !candidate.clip_rect.Contains(
- gfx::ToNearestRect(candidate.display_rect))) {
+ if (candidate.clip_rect && !candidate.clip_rect->Contains(
+ gfx::ToNearestRect(candidate.display_rect))) {
return false;
}
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc b/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc
index 69d54932edd..c54e9e9f171 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc
@@ -165,10 +165,8 @@ GLOzone* WaylandSurfaceFactory::GetGLOzone(
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanImplementation>
-WaylandSurfaceFactory::CreateVulkanImplementation(
- bool use_swiftshader,
- bool allow_protected_memory,
- bool enforce_protected_memory) {
+WaylandSurfaceFactory::CreateVulkanImplementation(bool use_swiftshader,
+ bool allow_protected_memory) {
return std::make_unique<VulkanImplementationWayland>(use_swiftshader);
}
#endif
@@ -179,7 +177,7 @@ scoped_refptr<gfx::NativePixmap> WaylandSurfaceFactory::CreateNativePixmap(
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- base::Optional<gfx::Size> framebuffer_size) {
+ absl::optional<gfx::Size> framebuffer_size) {
DCHECK(!framebuffer_size || framebuffer_size == size);
#if defined(WAYLAND_GBM)
scoped_refptr<GbmPixmapWayland> pixmap =
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory.h b/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory.h
index a20e8094d39..215fb809e8b 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory.h
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory.h
@@ -32,8 +32,7 @@ class WaylandSurfaceFactory : public SurfaceFactoryOzone {
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanImplementation> CreateVulkanImplementation(
bool use_swiftshader,
- bool allow_protected_memory,
- bool enforce_protected_memory) override;
+ bool allow_protected_memory) override;
#endif
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
gfx::AcceleratedWidget widget) override;
@@ -43,7 +42,7 @@ class WaylandSurfaceFactory : public SurfaceFactoryOzone {
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- base::Optional<gfx::Size> framebuffer_size = base::nullopt) override;
+ absl::optional<gfx::Size> framebuffer_size = absl::nullopt) override;
void CreateNativePixmapAsync(gfx::AcceleratedWidget widget,
VkDevice vk_device,
gfx::Size size,
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc b/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
index 64331f786e7..0567e79e80a 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
@@ -2,14 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <drm_fourcc.h>
+
+#include <cstdint>
#include <memory>
#include <utility>
+#include <vector>
+#include "base/containers/flat_map.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkSurface.h"
+#include "ui/gfx/buffer_types.h"
#include "ui/gfx/linux/gbm_buffer.h"
#include "ui/gfx/linux/gbm_device.h"
#include "ui/gfx/linux/test/mock_gbm_device.h"
@@ -32,6 +38,7 @@
using ::testing::_;
using ::testing::Expectation;
using ::testing::SaveArg;
+using ::testing::Values;
namespace ui {
@@ -175,11 +182,18 @@ class WaylandSurfaceFactoryTest : public WaylandTest {
~WaylandSurfaceFactoryTest() override = default;
void SetUp() override {
+ const base::flat_map<gfx::BufferFormat, std::vector<uint64_t>>
+ kSupportedFormatsWithModifiers{
+ {gfx::BufferFormat::BGRA_8888, {DRM_FORMAT_MOD_LINEAR}}};
+
WaylandTest::SetUp();
auto manager_ptr = connection_->buffer_manager_host()->BindInterface();
- buffer_manager_gpu_->Initialize(std::move(manager_ptr), {}, false, true,
- false);
+ buffer_manager_gpu_->Initialize(std::move(manager_ptr),
+ kSupportedFormatsWithModifiers,
+ /*supports_dma_buf=*/false,
+ /*supports_viewporter=*/true,
+ /*supports_acquire_fence=*/false);
// Wait until initialization and mojo calls go through.
base::RunLoop().RunUntilIdle();
@@ -778,9 +792,11 @@ TEST_P(WaylandSurfaceFactoryTest, CreateSurfaceCheckGbm) {
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandSurfaceFactoryTest,
- ::testing::Values(kXdgShellStable));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
WaylandSurfaceFactoryTest,
- ::testing::Values(kXdgShellV6));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kV6}));
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h b/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h
index a33e0e1f018..64f3aba5dec 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h
@@ -5,7 +5,7 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_SURFACE_GPU_H_
#define UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_SURFACE_GPU_H_
-#include <memory>
+#include "ui/gfx/gpu_fence_handle.h"
namespace gfx {
enum class SwapResult;
@@ -27,7 +27,8 @@ class WaylandSurfaceGpu {
// submitted buffer may be reused. This is guaranteed to be called
// in the same order that buffers were submitted.
virtual void OnSubmission(uint32_t buffer_id,
- const gfx::SwapResult& swap_result) = 0;
+ const gfx::SwapResult& swap_result,
+ gfx::GpuFenceHandle release_fence) = 0;
// Tells the surface the result of the last presentation of buffer with the
// |buffer_id|. This is guaranteed to be called in the same order that
diff --git a/chromium/ui/ozone/platform/wayland/host/DEPS b/chromium/ui/ozone/platform/wayland/host/DEPS
index c23eb538519..8f2915a802a 100644
--- a/chromium/ui/ozone/platform/wayland/host/DEPS
+++ b/chromium/ui/ozone/platform/wayland/host/DEPS
@@ -2,8 +2,8 @@ include_rules = [
# For Lacros.
"+chromeos/crosapi/mojom",
"+chromeos/crosapi/cpp/crosapi_constants.h",
- "+chromeos/lacros/lacros_chrome_service_impl.h",
+ "+chromeos/lacros/lacros_service.h",
"+chromeos/ui/base",
# Common includes.
- "+ui/base/linux/linux_desktop.h",
+ "+ui/base/linux",
]
diff --git a/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.cc b/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.cc
index ed4dc91240c..29f021076ab 100644
--- a/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.cc
+++ b/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.cc
@@ -28,9 +28,9 @@ GtkPrimarySelectionDevice::~GtkPrimarySelectionDevice() = default;
void GtkPrimarySelectionDevice::SetSelectionSource(
GtkPrimarySelectionSource* source) {
- DCHECK(source);
- gtk_primary_selection_device_set_selection(
- data_device_.get(), source->data_source(), connection()->serial());
+ auto* data_source = source ? source->data_source() : nullptr;
+ gtk_primary_selection_device_set_selection(data_device_.get(), data_source,
+ connection()->serial());
connection()->ScheduleFlush();
}
diff --git a/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.h b/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.h
index 4bb586bffc3..c6afbcdcb8f 100644
--- a/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.h
+++ b/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.h
@@ -5,9 +5,6 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_PRIMARY_SELECTION_DEVICE_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_PRIMARY_SELECTION_DEVICE_H_
-#include <memory>
-#include <string>
-#include <vector>
#include "base/callback.h"
#include "base/macros.h"
diff --git a/chromium/ui/ozone/platform/wayland/host/gtk_shell1.cc b/chromium/ui/ozone/platform/wayland/host/gtk_shell1.cc
new file mode 100644
index 00000000000..18a50d08dcd
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/host/gtk_shell1.cc
@@ -0,0 +1,23 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/host/gtk_shell1.h"
+
+#include <gtk-shell-client-protocol.h>
+
+#include "ui/ozone/platform/wayland/host/gtk_surface1.h"
+
+namespace ui {
+
+GtkShell1::GtkShell1(gtk_shell1* shell1) : shell1_(shell1) {}
+
+GtkShell1::~GtkShell1() = default;
+
+std::unique_ptr<GtkSurface1> GtkShell1::GetGtkSurface1(
+ wl_surface* top_level_window_surface) {
+ return std::make_unique<GtkSurface1>(
+ gtk_shell1_get_gtk_surface(shell1_.get(), top_level_window_surface));
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/gtk_shell1.h b/chromium/ui/ozone/platform/wayland/host/gtk_shell1.h
new file mode 100644
index 00000000000..bcf40a7693e
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/host/gtk_shell1.h
@@ -0,0 +1,32 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_SHELL1_H_
+#define UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_SHELL1_H_
+
+#include <memory>
+
+#include "ui/ozone/platform/wayland/common/wayland_object.h"
+
+namespace ui {
+
+class GtkSurface1;
+
+class GtkShell1 {
+ public:
+ explicit GtkShell1(gtk_shell1* shell1);
+ GtkShell1(const GtkShell1&) = delete;
+ GtkShell1& operator=(const GtkShell1&) = delete;
+ ~GtkShell1();
+
+ std::unique_ptr<GtkSurface1> GetGtkSurface1(
+ wl_surface* top_level_window_surface);
+
+ private:
+ wl::Object<gtk_shell1> shell1_;
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_SHELL1_H_
diff --git a/chromium/ui/ozone/platform/wayland/host/gtk_surface1.cc b/chromium/ui/ozone/platform/wayland/host/gtk_surface1.cc
new file mode 100644
index 00000000000..09d21f6f16c
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/host/gtk_surface1.cc
@@ -0,0 +1,21 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/host/gtk_surface1.h"
+
+#include <gtk-shell-client-protocol.h>
+
+#include "base/logging.h"
+
+namespace ui {
+
+GtkSurface1::GtkSurface1(gtk_surface1* surface1) : surface1_(surface1) {}
+
+GtkSurface1::~GtkSurface1() = default;
+
+void GtkSurface1::RequestFocus() {
+ gtk_surface1_request_focus(surface1_.get(), nullptr);
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/gtk_surface1.h b/chromium/ui/ozone/platform/wayland/host/gtk_surface1.h
new file mode 100644
index 00000000000..73c2329ad39
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/host/gtk_surface1.h
@@ -0,0 +1,28 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_SURFACE1_H_
+#define UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_SURFACE1_H_
+
+
+#include "ui/ozone/platform/wayland/common/wayland_object.h"
+
+namespace ui {
+
+class GtkSurface1 {
+ public:
+ explicit GtkSurface1(gtk_surface1* surface1);
+ GtkSurface1(const GtkSurface1&) = delete;
+ GtkSurface1& operator=(const GtkSurface1&) = delete;
+ ~GtkSurface1();
+
+ void RequestFocus();
+
+ private:
+ wl::Object<gtk_surface1> surface1_;
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_SURFACE1_H_
diff --git a/chromium/ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.h b/chromium/ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.h
deleted file mode 100644
index 64daa368936..00000000000
--- a/chromium/ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_UI_DELEGATE_WAYLAND_H_
-#define UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_UI_DELEGATE_WAYLAND_H_
-
-#include "ui/gtk/wayland/gtk_ui_delegate_wayland_base.h"
-
-namespace ui {
-
-class WaylandConnection;
-
-class GtkUiDelegateWayland : public GtkUiDelegateWaylandBase {
- public:
- explicit GtkUiDelegateWayland(WaylandConnection* connection);
- ~GtkUiDelegateWayland() override;
-
- // GtkUiDelegateWaylandBase:
- bool SetGtkWidgetTransientForImpl(
- gfx::AcceleratedWidget parent,
- base::OnceCallback<void(const std::string&)> callback) override;
-
- // GtkUiDelegate:
- int GetGdkKeyState() override;
-
- private:
- WaylandConnection* const connection_;
-};
-
-} // namespace ui
-
-#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_UI_DELEGATE_WAYLAND_H_
diff --git a/chromium/ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.cc b/chromium/ui/ozone/platform/wayland/host/linux_ui_delegate_wayland.cc
index 20bb8662233..34e539bcede 100644
--- a/chromium/ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.cc
+++ b/chromium/ui/ozone/platform/wayland/host/linux_ui_delegate_wayland.cc
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.h"
+#include "ui/ozone/platform/wayland/host/linux_ui_delegate_wayland.h"
#include <utility>
#include "base/logging.h"
+#include "ui/base/linux/linux_ui_delegate.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_event_source.h"
#include "ui/ozone/platform/wayland/host/wayland_surface.h"
@@ -17,14 +18,18 @@
namespace ui {
-GtkUiDelegateWayland::GtkUiDelegateWayland(WaylandConnection* connection)
+LinuxUiDelegateWayland::LinuxUiDelegateWayland(WaylandConnection* connection)
: connection_(connection) {
DCHECK(connection_);
}
-GtkUiDelegateWayland::~GtkUiDelegateWayland() = default;
+LinuxUiDelegateWayland::~LinuxUiDelegateWayland() = default;
-bool GtkUiDelegateWayland::SetGtkWidgetTransientForImpl(
+LinuxUiBackend LinuxUiDelegateWayland::GetBackend() const {
+ return LinuxUiBackend::kWayland;
+}
+
+bool LinuxUiDelegateWayland::SetWidgetTransientFor(
gfx::AcceleratedWidget parent,
base::OnceCallback<void(const std::string&)> callback) {
auto* parent_window =
@@ -39,7 +44,7 @@ bool GtkUiDelegateWayland::SetGtkWidgetTransientForImpl(
return true;
}
-int GtkUiDelegateWayland::GetGdkKeyState() {
+int LinuxUiDelegateWayland::GetKeyState() {
// TODO(crbug/1159460): Test fcitx unikey IME on ozone/wayland.
return connection_->event_source()->keyboard_modifiers();
}
diff --git a/chromium/ui/ozone/platform/wayland/host/linux_ui_delegate_wayland.h b/chromium/ui/ozone/platform/wayland/host/linux_ui_delegate_wayland.h
new file mode 100644
index 00000000000..3c9d9c4bb3d
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/host/linux_ui_delegate_wayland.h
@@ -0,0 +1,33 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_LINUX_UI_DELEGATE_WAYLAND_H_
+#define UI_OZONE_PLATFORM_WAYLAND_HOST_LINUX_UI_DELEGATE_WAYLAND_H_
+
+#include "ui/base/linux/linux_ui_delegate.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace ui {
+
+class WaylandConnection;
+
+class LinuxUiDelegateWayland : public LinuxUiDelegate {
+ public:
+ explicit LinuxUiDelegateWayland(WaylandConnection* connection);
+ ~LinuxUiDelegateWayland() override;
+
+ // LinuxUiDelegate:
+ LinuxUiBackend GetBackend() const override;
+ bool SetWidgetTransientFor(
+ gfx::AcceleratedWidget parent,
+ base::OnceCallback<void(const std::string&)> callback) override;
+ int GetKeyState() override;
+
+ private:
+ WaylandConnection* const connection_;
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_LINUX_UI_DELEGATE_WAYLAND_H_
diff --git a/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy.h b/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy.h
index fae92085432..97e4772231d 100644
--- a/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy.h
+++ b/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy.h
@@ -52,8 +52,12 @@ class COMPONENT_EXPORT(WAYLAND_PROXY) WaylandProxy {
// for the Delegate class.
virtual void SetDelegate(Delegate* delegate) = 0;
- // Returns the wl_display the WaylandConnection has the connection with.
+ // Returns the wl_display the WaylandConnection has the connection with. See
+ // WaylandConnection::display() and WaylandConnection::display_wrapper() to
+ // know the difference between the GetDisplay() and GetDisplayWrapper().
virtual wl_display* GetDisplay() = 0;
+ virtual wl_display* GetDisplayWrapper() = 0;
+ virtual void RoundTripQueue() = 0;
// Returns wl_surface that backs the |widget|.
virtual wl_surface* GetWlSurfaceForAcceleratedWidget(
@@ -85,4 +89,4 @@ class COMPONENT_EXPORT(WAYLAND_PROXY) WaylandProxy {
} // namespace wl
-#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_PROXY_H_
+#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_PROXY_WAYLAND_PROXY_H_
diff --git a/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.cc b/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.cc
index 93aedb6ef8b..ae80285ea5e 100644
--- a/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.cc
+++ b/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.cc
@@ -34,6 +34,14 @@ wl_display* WaylandProxyImpl::GetDisplay() {
return connection_->display();
}
+wl_display* WaylandProxyImpl::GetDisplayWrapper() {
+ return connection_->display_wrapper();
+}
+
+void WaylandProxyImpl::RoundTripQueue() {
+ connection_->RoundTripQueue();
+}
+
wl_surface* WaylandProxyImpl::GetWlSurfaceForAcceleratedWidget(
gfx::AcceleratedWidget widget) {
auto* window = connection_->wayland_window_manager()->GetWindow(widget);
diff --git a/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.h b/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.h
index 9805441d0b6..cf5ee8b568d 100644
--- a/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.h
+++ b/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.h
@@ -25,6 +25,8 @@ class WaylandProxyImpl : public WaylandProxy, public ui::WaylandWindowObserver {
// WaylandProxy overrides:
void SetDelegate(WaylandProxy::Delegate* delegate) override;
wl_display* GetDisplay() override;
+ wl_display* GetDisplayWrapper() override;
+ void RoundTripQueue() override;
wl_surface* GetWlSurfaceForAcceleratedWidget(
gfx::AcceleratedWidget widget) override;
wl_buffer* CreateShmBasedWlBuffer(const gfx::Size& buffer_size) override;
diff --git a/chromium/ui/ozone/platform/wayland/host/shell_popup_wrapper.cc b/chromium/ui/ozone/platform/wayland/host/shell_popup_wrapper.cc
index bcf8fc25847..32a28c7b0a9 100644
--- a/chromium/ui/ozone/platform/wayland/host/shell_popup_wrapper.cc
+++ b/chromium/ui/ozone/platform/wayland/host/shell_popup_wrapper.cc
@@ -8,8 +8,8 @@
#include "base/notreached.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
-#include "ui/ozone/platform/wayland/host/wayland_event_source.h"
#include "ui/ozone/platform/wayland/host/wayland_toplevel_window.h"
+#include "ui/platform_window/platform_window_init_properties.h"
namespace ui {
@@ -17,25 +17,25 @@ constexpr uint32_t kAnchorDefaultWidth = 1;
constexpr uint32_t kAnchorDefaultHeight = 1;
constexpr uint32_t kAnchorHeightParentMenu = 30;
-gfx::Rect GetAnchorRect(MenuType menu_type,
+gfx::Rect GetAnchorRect(PopupType menu_type,
const gfx::Rect& menu_bounds,
const gfx::Rect& parent_window_bounds) {
gfx::Rect anchor_rect;
switch (menu_type) {
- case MenuType::TYPE_RIGHT_CLICK:
- // Place anchor for right click menus normally.
+ case PopupType::TYPE_NORMAL:
+ // Place anchor for normal popups normally.
anchor_rect = gfx::Rect(menu_bounds.x(), menu_bounds.y(),
kAnchorDefaultWidth, kAnchorDefaultHeight);
break;
- case MenuType::TYPE_3DOT_PARENT_MENU:
- // The anchor for parent menu windows is positioned slightly above the
- // specified bounds to ensure flipped window along y-axis won't hide 3-dot
- // menu button.
+ case PopupType::TYPE_3DOT_PARENT_MENU:
+ // The anchor for a parent 3-dot menu windows is positioned slightly above
+ // the specified bounds to ensure flipped window along y-axis won't hide
+ // 3-dot menu button.
anchor_rect = gfx::Rect(menu_bounds.x() - kAnchorDefaultWidth,
menu_bounds.y() - kAnchorHeightParentMenu,
kAnchorDefaultWidth, kAnchorHeightParentMenu);
break;
- case MenuType::TYPE_3DOT_CHILD_MENU:
+ case PopupType::TYPE_3DOT_CHILD_MENU:
// The child menu's anchor must meet the following requirements: at some
// point, the Wayland compositor can flip it along x-axis. To make sure
// it's positioned correctly, place it closer to the beginning of the
@@ -75,24 +75,24 @@ gfx::Rect GetAnchorRect(MenuType menu_type,
}
}
break;
- case MenuType::TYPE_UNKNOWN:
- NOTREACHED() << "Unsupported menu type";
+ case PopupType::TYPE_UNKNOWN:
+ NOTREACHED() << "Unsupported popup type";
break;
}
return anchor_rect;
}
-WlAnchor GetAnchor(MenuType menu_type, const gfx::Rect& bounds) {
+WlAnchor GetAnchor(PopupType menu_type, const gfx::Rect& bounds) {
WlAnchor anchor = WlAnchor::None;
switch (menu_type) {
- case MenuType::TYPE_RIGHT_CLICK:
+ case PopupType::TYPE_NORMAL:
anchor = WlAnchor::TopLeft;
break;
- case MenuType::TYPE_3DOT_PARENT_MENU:
+ case PopupType::TYPE_3DOT_PARENT_MENU:
anchor = WlAnchor::BottomRight;
break;
- case MenuType::TYPE_3DOT_CHILD_MENU:
+ case PopupType::TYPE_3DOT_CHILD_MENU:
// Chromium may want to manually position a child menu on the left side of
// its parent menu. Thus, react accordingly. Positive x means the child is
// located on the right side of the parent and negative - on the left
@@ -102,7 +102,7 @@ WlAnchor GetAnchor(MenuType menu_type, const gfx::Rect& bounds) {
else
anchor = WlAnchor::TopLeft;
break;
- case MenuType::TYPE_UNKNOWN:
+ case PopupType::TYPE_UNKNOWN:
NOTREACHED() << "Unsupported menu type";
break;
}
@@ -110,16 +110,16 @@ WlAnchor GetAnchor(MenuType menu_type, const gfx::Rect& bounds) {
return anchor;
}
-WlGravity GetGravity(MenuType menu_type, const gfx::Rect& bounds) {
+WlGravity GetGravity(PopupType menu_type, const gfx::Rect& bounds) {
WlGravity gravity = WlGravity::None;
switch (menu_type) {
- case MenuType::TYPE_RIGHT_CLICK:
+ case PopupType::TYPE_NORMAL:
gravity = WlGravity::BottomRight;
break;
- case MenuType::TYPE_3DOT_PARENT_MENU:
+ case PopupType::TYPE_3DOT_PARENT_MENU:
gravity = WlGravity::BottomRight;
break;
- case MenuType::TYPE_3DOT_CHILD_MENU:
+ case PopupType::TYPE_3DOT_CHILD_MENU:
// Chromium may want to manually position a child menu on the left side of
// its parent menu. Thus, react accordingly. Positive x means the child is
// located on the right side of the parent and negative - on the left
@@ -129,7 +129,7 @@ WlGravity GetGravity(MenuType menu_type, const gfx::Rect& bounds) {
else
gravity = WlGravity::BottomLeft;
break;
- case MenuType::TYPE_UNKNOWN:
+ case PopupType::TYPE_UNKNOWN:
NOTREACHED() << "Unsupported menu type";
break;
}
@@ -137,26 +137,26 @@ WlGravity GetGravity(MenuType menu_type, const gfx::Rect& bounds) {
return gravity;
}
-WlConstraintAdjustment GetConstraintAdjustment(MenuType menu_type) {
+WlConstraintAdjustment GetConstraintAdjustment(PopupType menu_type) {
WlConstraintAdjustment constraint = WlConstraintAdjustment::None;
switch (menu_type) {
- case MenuType::TYPE_RIGHT_CLICK:
+ case PopupType::TYPE_NORMAL:
constraint =
WlConstraintAdjustment::SlideX | WlConstraintAdjustment::SlideY |
WlConstraintAdjustment::FlipY | WlConstraintAdjustment::ResizeY;
break;
- case MenuType::TYPE_3DOT_PARENT_MENU:
+ case PopupType::TYPE_3DOT_PARENT_MENU:
constraint = WlConstraintAdjustment::SlideX |
WlConstraintAdjustment::FlipY |
WlConstraintAdjustment::ResizeY;
break;
- case MenuType::TYPE_3DOT_CHILD_MENU:
+ case PopupType::TYPE_3DOT_CHILD_MENU:
constraint = WlConstraintAdjustment::SlideY |
WlConstraintAdjustment::FlipX |
WlConstraintAdjustment::ResizeY;
break;
- case MenuType::TYPE_UNKNOWN:
+ case PopupType::TYPE_UNKNOWN:
NOTREACHED() << "Unsupported menu type";
break;
}
@@ -164,21 +164,21 @@ WlConstraintAdjustment GetConstraintAdjustment(MenuType menu_type) {
return constraint;
}
-MenuType ShellPopupWrapper::GetMenuTypeForPositioner(
- WaylandConnection* connection,
+PopupType ShellPopupWrapper::GetPopupTypeForPositioner(
+ PlatformWindowType type,
+ int last_pointer_button_pressed,
WaylandWindow* parent_window) const {
bool is_right_click_menu =
- connection->event_source()->last_pointer_button_pressed() &
- EF_RIGHT_MOUSE_BUTTON;
+ last_pointer_button_pressed & EF_RIGHT_MOUSE_BUTTON;
// Different types of menu require different anchors, constraint adjustments,
// gravity and etc.
- if (is_right_click_menu)
- return MenuType::TYPE_RIGHT_CLICK;
- else if (!wl::IsMenuType(parent_window->type()))
- return MenuType::TYPE_3DOT_PARENT_MENU;
+ if (is_right_click_menu || type == PlatformWindowType::kTooltip)
+ return PopupType::TYPE_NORMAL;
+ else if (!parent_window->AsWaylandPopup())
+ return PopupType::TYPE_3DOT_PARENT_MENU;
else
- return MenuType::TYPE_3DOT_CHILD_MENU;
+ return PopupType::TYPE_3DOT_CHILD_MENU;
}
bool ShellPopupWrapper::CanGrabPopup(WaylandConnection* connection) const {
diff --git a/chromium/ui/ozone/platform/wayland/host/shell_popup_wrapper.h b/chromium/ui/ozone/platform/wayland/host/shell_popup_wrapper.h
index 77eaa71794d..4535a5eda67 100644
--- a/chromium/ui/ozone/platform/wayland/host/shell_popup_wrapper.h
+++ b/chromium/ui/ozone/platform/wayland/host/shell_popup_wrapper.h
@@ -7,14 +7,15 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
+#include "ui/platform_window/platform_window_init_properties.h"
namespace ui {
class WaylandConnection;
class WaylandWindow;
-enum class MenuType {
- TYPE_RIGHT_CLICK,
+enum class PopupType {
+ TYPE_NORMAL,
TYPE_3DOT_PARENT_MENU,
TYPE_3DOT_CHILD_MENU,
TYPE_UNKNOWN,
@@ -78,17 +79,19 @@ class ShellPopupWrapper {
// Sends acknowledge configure event back to wayland.
virtual void AckConfigure(uint32_t serial) = 0;
- MenuType GetMenuTypeForPositioner(WaylandConnection* connection,
- WaylandWindow* parent_window) const;
+ // Returns popup type for |type|.
+ PopupType GetPopupTypeForPositioner(PlatformWindowType type,
+ int last_pointer_button_pressed,
+ WaylandWindow* parent_window) const;
bool CanGrabPopup(WaylandConnection* connection) const;
};
-gfx::Rect GetAnchorRect(MenuType menu_type,
+gfx::Rect GetAnchorRect(PopupType menu_type,
const gfx::Rect& menu_bounds,
const gfx::Rect& parent_window_bounds);
-WlAnchor GetAnchor(MenuType menu_type, const gfx::Rect& bounds);
-WlGravity GetGravity(MenuType menu_type, const gfx::Rect& bounds);
-WlConstraintAdjustment GetConstraintAdjustment(MenuType menu_type);
+WlAnchor GetAnchor(PopupType menu_type, const gfx::Rect& bounds);
+WlGravity GetGravity(PopupType menu_type, const gfx::Rect& bounds);
+WlConstraintAdjustment GetConstraintAdjustment(PopupType menu_type);
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.cc b/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.cc
index f7e0453ff7d..a7d7366c12a 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.cc
@@ -14,7 +14,7 @@ namespace ui {
WaylandBufferManagerConnector::WaylandBufferManagerConnector(
WaylandBufferManagerHost* buffer_manager_host)
: buffer_manager_host_(buffer_manager_host) {
- DETACH_FROM_THREAD(io_thread_checker_);
+ DETACH_FROM_THREAD(process_thread_checker_);
}
WaylandBufferManagerConnector::~WaylandBufferManagerConnector() {
@@ -30,19 +30,23 @@ void WaylandBufferManagerConnector::OnChannelDestroyed(int host_id) {
void WaylandBufferManagerConnector::OnGpuServiceLaunched(
int host_id,
scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> process_host_runner,
GpuHostBindInterfaceCallback binder,
GpuHostTerminateCallback terminate_callback) {
- DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
-
+ DCHECK_CALLED_ON_VALID_THREAD(process_thread_checker_);
binder_ = std::move(binder);
- io_runner_ = io_runner;
-
- ui_runner->PostTask(
- FROM_HERE,
- base::BindOnce(&WaylandBufferManagerConnector::OnGpuServiceLaunchedOnUI,
- base::Unretained(this), host_id,
- std::move(terminate_callback)));
+ process_host_runner_ = process_host_runner;
+
+ if (ui_runner->BelongsToCurrentThread()) {
+ DCHECK(process_host_runner_->BelongsToCurrentThread());
+ OnGpuServiceLaunchedOnUI(host_id, std::move(terminate_callback));
+ } else {
+ ui_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WaylandBufferManagerConnector::OnGpuServiceLaunchedOnUI,
+ base::Unretained(this), host_id,
+ std::move(terminate_callback)));
+ }
}
void WaylandBufferManagerConnector::OnGpuServiceLaunchedOnUI(
@@ -60,17 +64,21 @@ void WaylandBufferManagerConnector::OnGpuServiceLaunchedOnUI(
auto pending_remote = buffer_manager_host_->BindInterface();
- io_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &WaylandBufferManagerConnector::OnBufferManagerHostPtrBinded,
- base::Unretained(this), std::move(pending_remote)));
+ if (process_host_runner_->BelongsToCurrentThread()) {
+ OnBufferManagerHostPtrBinded(std::move(pending_remote));
+ } else {
+ process_host_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &WaylandBufferManagerConnector::OnBufferManagerHostPtrBinded,
+ base::Unretained(this), std::move(pending_remote)));
+ }
}
void WaylandBufferManagerConnector::OnBufferManagerHostPtrBinded(
mojo::PendingRemote<ozone::mojom::WaylandBufferManagerHost>
buffer_manager_host) const {
- DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
+ DCHECK_CALLED_ON_VALID_THREAD(process_thread_checker_);
mojo::Remote<ozone::mojom::WaylandBufferManagerGpu> buffer_manager_gpu_remote;
binder_.Run(
@@ -94,8 +102,13 @@ void WaylandBufferManagerConnector::OnTerminateGpuProcess(std::string message) {
DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
DCHECK(!terminate_callback_.is_null());
- io_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(terminate_callback_),
- std::move(message)));
+ if (process_host_runner_->BelongsToCurrentThread()) {
+ std::move(terminate_callback_).Run(std::move(message));
+ } else {
+ process_host_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(terminate_callback_), std::move(message)));
+ }
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.h b/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.h
index 1a40e3782c8..e651c604e20 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.h
@@ -29,7 +29,7 @@ class WaylandBufferManagerConnector : public GpuPlatformSupportHost {
void OnGpuServiceLaunched(
int host_id,
scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> process_host_runner,
GpuHostBindInterfaceCallback binder,
GpuHostTerminateCallback terminate_callback) override;
@@ -50,13 +50,13 @@ class WaylandBufferManagerConnector : public GpuPlatformSupportHost {
GpuHostBindInterfaceCallback binder_;
GpuHostTerminateCallback terminate_callback_;
- scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> process_host_runner_;
// Owned by the ui thread.
int host_id_ = -1;
THREAD_CHECKER(ui_thread_checker_);
- THREAD_CHECKER(io_thread_checker_);
+ THREAD_CHECKER(process_thread_checker_);
DISALLOW_COPY_AND_ASSIGN(WaylandBufferManagerConnector);
};
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc b/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
index bd1e5231354..c5471d2cb2b 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
@@ -16,6 +16,7 @@
#include "base/task/current_thread.h"
#include "base/trace_event/trace_event.h"
#include "ui/gfx/gpu_fence.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/gfx/linux/drm_util_linux.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_drm.h"
@@ -47,15 +48,6 @@ uint32_t GetPresentationKindFlags(uint32_t flags) {
return presentation_flags;
}
-base::TimeTicks GetPresentationFeedbackTimeStamp(uint32_t tv_sec_hi,
- uint32_t tv_sec_lo,
- uint32_t tv_nsec) {
- const int64_t seconds = (static_cast<int64_t>(tv_sec_hi) << 32) + tv_sec_lo;
- const int64_t microseconds = seconds * base::Time::kMicrosecondsPerSecond +
- tv_nsec / base::Time::kNanosecondsPerMicrosecond;
- return base::TimeTicks() + base::TimeDelta::FromMicroseconds(microseconds);
-}
-
std::string NumberToString(uint32_t number) {
return base::UTF16ToUTF8(base::FormatNumber(number));
}
@@ -228,7 +220,8 @@ class WaylandBufferManagerHost::Surface {
continue;
submitted_buffers_.push_back(
- SubmissionInfo{pending_commit.buffer->buffer_id, /*acked=*/false});
+ SubmissionInfo{pending_commit.buffer->buffer_id,
+ /*acked=*/submitted_buffers_.empty() ? true : false});
if (connection_->presentation()) {
feedback_queue_.push_back(
{wl::Object<struct wp_presentation_feedback>(),
@@ -283,7 +276,7 @@ class WaylandBufferManagerHost::Surface {
uint32_t buffer_id;
// The actual presentation feedback. May be missing if the callback from the
// Wayland server has not arrived yet.
- base::Optional<gfx::PresentationFeedback> feedback;
+ absl::optional<gfx::PresentationFeedback> feedback;
// True iff OnSubmission has been called.
bool submission_completed;
};
@@ -409,7 +402,7 @@ class WaylandBufferManagerHost::Surface {
feedback_queue_.push_back(
{wl::Object<struct wp_presentation_feedback>(wp_presentation_feedback(
connection_->presentation(), wayland_surface_->surface())),
- buffer_id, /*feedback=*/base::nullopt,
+ buffer_id, /*feedback=*/absl::nullopt,
/*submission_completed=*/false});
wp_presentation_feedback_add_listener(
feedback_queue_.back().wp_presentation_feedback.get(),
@@ -518,7 +511,8 @@ class WaylandBufferManagerHost::Surface {
// release because SwapCompletionCallback indicates to the client that the
// previous buffer is available for reuse.
buffer_manager_->OnSubmission(wayland_surface_->GetWidget(), buffer_id,
- gfx::SwapResult::SWAP_ACK);
+ gfx::SwapResult::SWAP_ACK,
+ /*release_fence=*/gfx::GpuFenceHandle());
// If presentation feedback is not supported, use a fake feedback. This
// literally means there are no presentation feedback callbacks created.
@@ -615,10 +609,10 @@ class WaylandBufferManagerHost::Surface {
DCHECK(self);
self->OnPresentation(
wp_presentation_feedback,
- gfx::PresentationFeedback(
- GetPresentationFeedbackTimeStamp(tv_sec_hi, tv_sec_lo, tv_nsec),
- base::TimeDelta::FromNanoseconds(refresh),
- GetPresentationKindFlags(flags)));
+ gfx::PresentationFeedback(self->connection_->ConvertPresentationTime(
+ tv_sec_hi, tv_sec_lo, tv_nsec),
+ base::TimeDelta::FromNanoseconds(refresh),
+ GetPresentationKindFlags(flags)));
}
static void FeedbackDiscarded(
@@ -1249,14 +1243,15 @@ void WaylandBufferManagerHost::OnCreateBufferComplete(
// be destroyed.
}
-void WaylandBufferManagerHost::OnSubmission(
- gfx::AcceleratedWidget widget,
- uint32_t buffer_id,
- const gfx::SwapResult& swap_result) {
+void WaylandBufferManagerHost::OnSubmission(gfx::AcceleratedWidget widget,
+ uint32_t buffer_id,
+ const gfx::SwapResult& swap_result,
+ gfx::GpuFenceHandle release_fence) {
DCHECK(base::CurrentUIThread::IsSet());
DCHECK(buffer_manager_gpu_associated_);
- buffer_manager_gpu_associated_->OnSubmission(widget, buffer_id, swap_result);
+ buffer_manager_gpu_associated_->OnSubmission(widget, buffer_id, swap_result,
+ std::move(release_fence));
}
void WaylandBufferManagerHost::OnPresentation(
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h b/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h
index fac32a14e72..de13bd3760e 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h
@@ -229,7 +229,8 @@ class WaylandBufferManagerHost : public ozone::mojom::WaylandBufferManagerHost,
// it with the presentation feedback.
void OnSubmission(gfx::AcceleratedWidget widget,
uint32_t buffer_id,
- const gfx::SwapResult& swap_result);
+ const gfx::SwapResult& swap_result,
+ gfx::GpuFenceHandle release_fence);
void OnPresentation(gfx::AcceleratedWidget widget,
uint32_t buffer_id,
const gfx::PresentationFeedback& feedback);
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.cc b/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.cc
index aae5b5f2552..ff3e07b57c9 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.cc
@@ -11,7 +11,7 @@
#include "base/containers/contains.h"
#include "base/memory/scoped_refptr.h"
#include "base/notreached.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/clipboard/clipboard_buffer.h"
#include "ui/base/clipboard/clipboard_constants.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
@@ -35,6 +35,9 @@ namespace wl {
// Wayland protocol objects.
class Clipboard {
public:
+ using ClipboardDataChangedCallback =
+ ui::PlatformClipboard::ClipboardDataChangedCallback;
+
virtual ~Clipboard() = default;
// Synchronously retrieves the mime types list currently available to be read.
@@ -51,9 +54,9 @@ class Clipboard {
// Tells if this clipboard instance is the current selection owner.
virtual bool IsSelectionOwner() const = 0;
- // Sets the callback in charge of updating the clipboard sequence number.
- virtual void SetSequenceNumberUpdateCb(
- ui::PlatformClipboard::SequenceNumberUpdateCb callback) = 0;
+ // Sets the callback to be executed when clipboard data changes.
+ virtual void SetClipboardDataChangedCallback(
+ ClipboardDataChangedCallback callback) = 0;
};
// Templated wl::Clipboard implementation. Whereas DataSource is the data source
@@ -81,11 +84,10 @@ class ClipboardImpl final : public Clipboard,
bool Read(const std::string& mime_type,
ui::PlatformClipboard::RequestDataClosure callback) final {
requested_mime_type_ = mime_type;
- if (GetDevice()->RequestSelectionData(GetMimeTypeForRequest(mime_type))) {
- read_clipboard_closure_ = std::move(callback);
+ read_clipboard_closure_ = std::move(callback);
+ if (GetDevice()->RequestSelectionData(GetMimeTypeForRequest(mime_type)))
return true;
- }
- SetData(base::MakeRefCounted<base::RefCountedBytes>(), mime_type);
+ DeliverData(nullptr, mime_type);
return false;
}
@@ -107,17 +109,18 @@ class ClipboardImpl final : public Clipboard,
offered_data_ = *data;
source_ = manager_->CreateSource(this);
source_->Offer(GetOfferedMimeTypes());
- GetDevice()->SetSelectionSource(source_.get());
}
+ GetDevice()->SetSelectionSource(source_.get());
+
+ if (!clipboard_changed_callback_.is_null())
+ clipboard_changed_callback_.Run(buffer_);
}
bool IsSelectionOwner() const final { return !!source_; }
- void SetSequenceNumberUpdateCb(
- ui::PlatformClipboard::SequenceNumberUpdateCb callback) final {
- CHECK(update_sequence_cb_.is_null())
- << "The callback can be installed only once.";
- update_sequence_cb_ = callback;
+ void SetClipboardDataChangedCallback(
+ ClipboardDataChangedCallback callback) final {
+ clipboard_changed_callback_ = std::move(callback);
}
private:
@@ -146,8 +149,8 @@ class ClipboardImpl final : public Clipboard,
return mime_type;
}
- void SetData(ui::PlatformClipboard::Data contents,
- const std::string& mime_type) {
+ void DeliverData(ui::PlatformClipboard::Data contents,
+ const std::string& mime_type) {
CHECK_EQ(GetMimeTypeForRequest(requested_mime_type_), mime_type);
if (!read_clipboard_closure_.is_null())
std::move(read_clipboard_closure_).Run(contents);
@@ -156,16 +159,16 @@ class ClipboardImpl final : public Clipboard,
// WaylandDataDeviceBase::SelectionDelegate:
void OnSelectionOffer(ui::WaylandDataOfferBase* offer) final {
- if (!update_sequence_cb_.is_null())
- update_sequence_cb_.Run(buffer_);
+ if (IsSelectionOwner())
+ return;
- if (!offer)
- SetData({}, {});
+ if (!clipboard_changed_callback_.is_null())
+ clipboard_changed_callback_.Run(buffer_);
}
void OnSelectionDataReceived(const std::string& mime_type,
ui::PlatformClipboard::Data contents) final {
- SetData(contents, mime_type);
+ DeliverData(contents, mime_type);
}
// WaylandDataSource::Delegate:
@@ -202,8 +205,8 @@ class ClipboardImpl final : public Clipboard,
// Last mime type requested to be read from the clipboard.
std::string requested_mime_type_;
- // Notifies when clipboard sequence must change. Can be empty if not set.
- ui::PlatformClipboard::SequenceNumberUpdateCb update_sequence_cb_;
+ // Notifies when clipboard data changes. Can be empty if not set.
+ ClipboardDataChangedCallback clipboard_changed_callback_;
};
} // namespace wl
@@ -249,11 +252,11 @@ bool WaylandClipboard::IsSelectionOwner(ClipboardBuffer buffer) {
return false;
}
-void WaylandClipboard::SetSequenceNumberUpdateCb(
- PlatformClipboard::SequenceNumberUpdateCb cb) {
- copypaste_clipboard_->SetSequenceNumberUpdateCb(cb);
+void WaylandClipboard::SetClipboardDataChangedCallback(
+ ClipboardDataChangedCallback data_changed_callback) {
+ copypaste_clipboard_->SetClipboardDataChangedCallback(data_changed_callback);
if (auto* selection_clipboard = GetClipboard(ClipboardBuffer::kSelection))
- selection_clipboard->SetSequenceNumberUpdateCb(cb);
+ selection_clipboard->SetClipboardDataChangedCallback(data_changed_callback);
}
void WaylandClipboard::GetAvailableMimeTypes(
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.h b/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.h
index 4f080096d1e..7ec9d76023c 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.h
@@ -52,8 +52,8 @@ class WaylandClipboard : public PlatformClipboard {
ClipboardBuffer buffer,
PlatformClipboard::GetMimeTypesClosure callback) override;
bool IsSelectionOwner(ClipboardBuffer buffer) override;
- void SetSequenceNumberUpdateCb(
- PlatformClipboard::SequenceNumberUpdateCb cb) override;
+ void SetClipboardDataChangedCallback(
+ ClipboardDataChangedCallback data_changed_callback) override;
bool IsSelectionBufferAvailable() const override;
private:
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc
index 33134a359a6..c5a928449b4 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc
@@ -10,7 +10,6 @@
#include <vector>
#include "base/bind.h"
-#include "base/callback_forward.h"
#include "base/containers/contains.h"
#include "base/containers/flat_set.h"
#include "base/location.h"
@@ -32,6 +31,7 @@
using testing::_;
using testing::Mock;
+using testing::Values;
namespace ui {
@@ -162,12 +162,9 @@ TEST_P(WaylandClipboardTest, ReadFromClipboardPrioritizeUtf) {
TEST_P(WaylandClipboardTest, ReadFromClipboardWithoutOffer) {
// When no data offer is advertised and client requests clipboard data
// from the server, the response callback should be gracefully called with
- // an empty string.
- auto callback = base::BindOnce([](const PlatformClipboard::Data& data) {
- ASSERT_TRUE(data.get());
- std::string string_data(data->front_as<const char>(), data->size());
- EXPECT_EQ("", string_data);
- });
+ // null data.
+ auto callback = base::BindOnce(
+ [](const PlatformClipboard::Data& data) { ASSERT_FALSE(data); });
clipboard_->RequestClipboardData(ClipboardBuffer::kCopyPaste,
kMimeTypeTextUtf8, std::move(callback));
}
@@ -229,12 +226,37 @@ TEST_P(WaylandClipboardTest, OverlapReadingFromDifferentBuffers) {
Sync();
}
+// Ensures clipboard change callback is fired only once per read/write.
+TEST_P(WaylandClipboardTest, ClipboardChangeNotifications) {
+ base::MockCallback<PlatformClipboard::ClipboardDataChangedCallback>
+ clipboard_changed_callback;
+ clipboard_->SetClipboardDataChangedCallback(clipboard_changed_callback.Get());
+ const auto buffer = ClipboardBuffer::kCopyPaste;
+
+ // 1. For selection offered by an external application.
+ EXPECT_CALL(clipboard_changed_callback, Run(buffer)).Times(1);
+ auto* data_offer = data_device_manager_->data_device()->OnDataOffer();
+ data_offer->OnOffer(kMimeTypeTextUtf8,
+ ToClipboardData(std::string(kSampleClipboardText)));
+ data_device_manager_->data_device()->OnSelection(data_offer);
+ Sync();
+ EXPECT_FALSE(clipboard_->IsSelectionOwner(ClipboardBuffer::kCopyPaste));
+
+ // 2. For selection offered by Chromium.
+ EXPECT_CALL(clipboard_changed_callback, Run(buffer)).Times(1);
+ OfferData(buffer, kSampleClipboardText, {kMimeTypeTextUtf8});
+ Sync();
+ EXPECT_TRUE(clipboard_->IsSelectionOwner(buffer));
+}
+
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandClipboardTest,
- ::testing::Values(kXdgShellStable));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
WaylandClipboardTest,
- ::testing::Values(kXdgShellV6));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kV6}));
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_connection.cc b/chromium/ui/ozone/platform/wayland/host/wayland_connection.cc
index 6c0501b0f95..9e03a64b1ab 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_connection.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_connection.cc
@@ -5,6 +5,7 @@
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include <extended-drag-unstable-v1-client-protocol.h>
+#include <presentation-time-client-protocol.h>
#include <xdg-shell-client-protocol.h>
#include <xdg-shell-unstable-v6-client-protocol.h>
@@ -18,12 +19,14 @@
#include "base/strings/string_util.h"
#include "base/task/current_thread.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
#include "ui/events/devices/device_data_manager.h"
#include "ui/events/devices/input_device.h"
#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
#include "ui/gfx/geometry/point.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
#include "ui/ozone/platform/wayland/host/gtk_primary_selection_device_manager.h"
+#include "ui/ozone/platform/wayland/host/gtk_shell1.h"
#include "ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.h"
#include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h"
#include "ui/ozone/platform/wayland/host/wayland_clipboard.h"
@@ -44,6 +47,7 @@
#include "ui/ozone/platform/wayland/host/wayland_zaura_shell.h"
#include "ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h"
#include "ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h"
+#include "ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.h"
#include "ui/ozone/platform/wayland/host/xdg_foreign_wrapper.h"
#include "ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.h"
#include "ui/platform_window/common/platform_window_defaults.h"
@@ -57,10 +61,11 @@
namespace ui {
namespace {
+
// The maximum supported versions for a given interface.
// The version bound will be the minimum of the value and the version
// advertised by the server.
-constexpr uint32_t kMaxAuraShellVersion = 16;
+constexpr uint32_t kMaxAuraShellVersion = 19;
constexpr uint32_t kMaxCompositorVersion = 4;
constexpr uint32_t kMaxCursorShapesVersion = 1;
constexpr uint32_t kMaxGtkPrimarySelectionDeviceManagerVersion = 1;
@@ -81,6 +86,39 @@ constexpr uint32_t kMaxExtendedDragVersion = 1;
// value.
constexpr uint32_t kMinWlDrmVersion = 2;
constexpr uint32_t kMinWlOutputVersion = 2;
+constexpr uint32_t kMinZwpPointerGesturesVersion = 1;
+
+// gtk_shell1 exposes request_focus() since version 3. Below that, it is not
+// interesting for us, although it provides some shell integration that might be
+// useful.
+constexpr uint32_t kMinGtkShell1Version = 3;
+constexpr uint32_t kMaxGtkShell1Version = 4;
+
+int64_t ConvertTimespecToMicros(const struct timespec& ts) {
+ // On 32-bit systems, the calculation cannot overflow int64_t.
+ // 2**32 * 1000000 + 2**64 / 1000 < 2**63
+ if (sizeof(ts.tv_sec) <= 4 && sizeof(ts.tv_nsec) <= 8) {
+ int64_t result = ts.tv_sec;
+ result *= base::Time::kMicrosecondsPerSecond;
+ result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond);
+ return result;
+ }
+ base::CheckedNumeric<int64_t> result(ts.tv_sec);
+ result *= base::Time::kMicrosecondsPerSecond;
+ result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond);
+ return result.ValueOrDie();
+}
+
+int64_t ConvertTimespecResultToMicros(uint32_t tv_sec_hi,
+ uint32_t tv_sec_lo,
+ uint32_t tv_nsec) {
+ base::CheckedNumeric<int64_t> result =
+ (static_cast<int64_t>(tv_sec_hi) << 32) + tv_sec_lo;
+ result *= base::Time::kMicrosecondsPerSecond;
+ result += (tv_nsec / base::Time::kNanosecondsPerMicrosecond);
+ return result.ValueOrDie();
+}
+
} // namespace
WaylandConnection::WaylandConnection() = default;
@@ -128,7 +166,14 @@ bool WaylandConnection::Initialize() {
return false;
}
- registry_.reset(wl_display_get_registry(display_.get()));
+ wrapped_display_.reset(
+ reinterpret_cast<wl_proxy*>(wl_proxy_create_wrapper(display())));
+ // Create a non-default event queue so that we wouldn't flush messages for
+ // client applications.
+ event_queue_.reset(wl_display_create_queue(display()));
+ wl_proxy_set_queue(wrapped_display_.get(), event_queue_.get());
+
+ registry_.reset(wl_display_get_registry(display_wrapper()));
if (!registry_) {
LOG(ERROR) << "Failed to get Wayland registry";
return false;
@@ -137,13 +182,13 @@ bool WaylandConnection::Initialize() {
// Now that the connection with the display server has been properly
// estabilished, initialize the event source and input objects.
DCHECK(!event_source_);
- event_source_ =
- std::make_unique<WaylandEventSource>(display(), wayland_window_manager());
+ event_source_ = std::make_unique<WaylandEventSource>(
+ display(), event_queue_.get(), wayland_window_manager());
wl_registry_add_listener(registry_.get(), &registry_listener, this);
while (!wayland_output_manager_ ||
!wayland_output_manager_->IsOutputReady()) {
- wl_display_roundtrip(display_.get());
+ RoundTripQueue();
}
buffer_manager_host_ = std::make_unique<WaylandBufferManagerHost>(this);
@@ -168,7 +213,6 @@ bool WaylandConnection::Initialize() {
if (UseTestConfigForPlatformWindows())
wayland_proxy_ = std::make_unique<wl::WaylandProxyImpl>(this);
-
return true;
}
@@ -186,6 +230,11 @@ void WaylandConnection::ScheduleFlush() {
}
}
+void WaylandConnection::RoundTripQueue() {
+ DCHECK(event_queue_.get());
+ wl_display_roundtrip_queue(display(), event_queue_.get());
+}
+
void WaylandConnection::SetShutdownCb(base::OnceCallback<void()> shutdown_cb) {
event_source()->SetShutdownCb(std::move(shutdown_cb));
}
@@ -256,6 +305,11 @@ void WaylandConnection::UpdateInputDevices(wl_seat* seat,
// Wayland doesn't expose InputDeviceType.
devices.emplace_back(InputDevice(
pointer_->id(), InputDeviceType::INPUT_DEVICE_UNKNOWN, "pointer"));
+
+ // Pointer is required for PointerGestures to be functional.
+ if (wayland_zwp_pointer_gestures_)
+ wayland_zwp_pointer_gestures_->Init();
+
} else {
LOG(ERROR) << "Failed to get wl_pointer from seat";
}
@@ -278,7 +332,7 @@ void WaylandConnection::UpdateInputDevices(wl_seat* seat,
}
}
- // Notify about mouse changes.
+ // Notify about keyboard changes.
GetHotplugEventObserver()->OnKeyboardDevicesUpdated(devices);
// TODO(msisov): wl_touch doesn't expose the display it belongs to. Thus, it's
@@ -348,25 +402,34 @@ void WaylandConnection::Global(void* data,
static const zxdg_shell_v6_listener shell_v6_listener = {
&WaylandConnection::PingV6,
};
+ static const wp_presentation_listener presentation_listener = {
+ &WaylandConnection::ClockId,
+ };
WaylandConnection* connection = static_cast<WaylandConnection*>(data);
if (!connection->compositor_ && strcmp(interface, "wl_compositor") == 0) {
connection->compositor_ = wl::Bind<wl_compositor>(
registry, name, std::min(version, kMaxCompositorVersion));
connection->compositor_version_ = version;
- if (!connection->compositor_)
+ if (!connection->compositor_) {
LOG(ERROR) << "Failed to bind to wl_compositor global";
+ return;
+ }
} else if (!connection->subcompositor_ &&
strcmp(interface, "wl_subcompositor") == 0) {
connection->subcompositor_ = wl::Bind<wl_subcompositor>(registry, name, 1);
- if (!connection->subcompositor_)
+ if (!connection->subcompositor_) {
LOG(ERROR) << "Failed to bind to wl_subcompositor global";
+ return;
+ }
} else if (!connection->shm_ && strcmp(interface, "wl_shm") == 0) {
wl::Object<wl_shm> shm =
wl::Bind<wl_shm>(registry, name, std::min(version, kMaxShmVersion));
connection->shm_ = std::make_unique<WaylandShm>(shm.release(), connection);
- if (!connection->shm_)
+ if (!connection->shm_) {
LOG(ERROR) << "Failed to bind to wl_shm global";
+ return;
+ }
} else if (!connection->seat_ && strcmp(interface, "wl_seat") == 0) {
connection->seat_ =
wl::Bind<wl_seat>(registry, name, std::min(version, kMaxSeatVersion));
@@ -405,7 +468,7 @@ void WaylandConnection::Global(void* data,
return;
}
- wl::Object<wl_output> output = wl::Bind<wl_output>(registry, name, version);
+ auto output = wl::Bind<wl_output>(registry, name, version);
if (!output) {
LOG(ERROR) << "Failed to bind to wl_output global";
return;
@@ -419,9 +482,8 @@ void WaylandConnection::Global(void* data,
output.release());
} else if (!connection->data_device_manager_ &&
strcmp(interface, "wl_data_device_manager") == 0) {
- wl::Object<wl_data_device_manager> data_device_manager =
- wl::Bind<wl_data_device_manager>(
- registry, name, std::min(version, kMaxDeviceManagerVersion));
+ auto data_device_manager = wl::Bind<wl_data_device_manager>(
+ registry, name, std::min(version, kMaxDeviceManagerVersion));
if (!data_device_manager) {
LOG(ERROR) << "Failed to bind to wl_data_device_manager global";
return;
@@ -432,20 +494,35 @@ void WaylandConnection::Global(void* data,
connection->CreateDataObjectsIfReady();
} else if (!connection->gtk_primary_selection_device_manager_ &&
strcmp(interface, "gtk_primary_selection_device_manager") == 0) {
- wl::Object<::gtk_primary_selection_device_manager> manager =
- wl::Bind<::gtk_primary_selection_device_manager>(
- registry, name,
- std::min(version, kMaxGtkPrimarySelectionDeviceManagerVersion));
+ auto manager = wl::Bind<::gtk_primary_selection_device_manager>(
+ registry, name,
+ std::min(version, kMaxGtkPrimarySelectionDeviceManagerVersion));
+ if (!manager) {
+ LOG(ERROR) << "Failed to bind gtk_primary_selection_device_manager";
+ return;
+ }
connection->gtk_primary_selection_device_manager_ =
std::make_unique<GtkPrimarySelectionDeviceManager>(manager.release(),
connection);
+ } else if (!connection->gtk_shell1_ && strcmp(interface, "gtk_shell1") == 0 &&
+ version >= kMinGtkShell1Version) {
+ auto gtk_shell1 = wl::Bind<::gtk_shell1>(
+ registry, name, std::min(version, kMaxGtkShell1Version));
+ if (!gtk_shell1) {
+ LOG(ERROR) << "Failed to bind gtk_shell1";
+ return;
+ }
+ connection->gtk_shell1_ = std::make_unique<GtkShell1>(gtk_shell1.release());
} else if (!connection->zwp_primary_selection_device_manager_ &&
strcmp(interface, "zwp_primary_selection_device_manager_v1") ==
0) {
- wl::Object<zwp_primary_selection_device_manager_v1> manager =
- wl::Bind<zwp_primary_selection_device_manager_v1>(
- registry, name,
- std::min(version, kMaxGtkPrimarySelectionDeviceManagerVersion));
+ auto manager = wl::Bind<zwp_primary_selection_device_manager_v1>(
+ registry, name,
+ std::min(version, kMaxGtkPrimarySelectionDeviceManagerVersion));
+ if (!manager) {
+ LOG(ERROR) << "Failed to bind zwp_primary_selection_device_manager_v1";
+ return;
+ }
connection->zwp_primary_selection_device_manager_ =
std::make_unique<ZwpPrimarySelectionDeviceManager>(manager.release(),
connection);
@@ -455,21 +532,38 @@ void WaylandConnection::Global(void* data,
connection->linux_explicit_synchronization_ =
wl::Bind<zwp_linux_explicit_synchronization_v1>(
registry, name, std::min(version, kMaxExplicitSyncVersion));
+ if (!connection->linux_explicit_synchronization_) {
+ LOG(ERROR) << "Failed to bind zwp_linux_explicit_synchronization_v1";
+ return;
+ }
} else if (!connection->zwp_dmabuf_ &&
(strcmp(interface, "zwp_linux_dmabuf_v1") == 0)) {
- wl::Object<zwp_linux_dmabuf_v1> zwp_linux_dmabuf =
- wl::Bind<zwp_linux_dmabuf_v1>(
- registry, name, std::min(version, kMaxLinuxDmabufVersion));
+ auto zwp_linux_dmabuf = wl::Bind<zwp_linux_dmabuf_v1>(
+ registry, name, std::min(version, kMaxLinuxDmabufVersion));
+ if (!zwp_linux_dmabuf) {
+ LOG(ERROR) << "Failed to bind zwp_linux_dmabuf_v1";
+ return;
+ }
connection->zwp_dmabuf_ = std::make_unique<WaylandZwpLinuxDmabuf>(
zwp_linux_dmabuf.release(), connection);
} else if (!connection->presentation_ &&
(strcmp(interface, "wp_presentation") == 0)) {
connection->presentation_ = wl::Bind<wp_presentation>(
registry, name, std::min(version, kMaxWpPresentationVersion));
+ if (!connection->presentation_) {
+ LOG(ERROR) << "Failed to bind wp_presentation";
+ return;
+ }
+ wp_presentation_add_listener(connection->presentation_.get(),
+ &presentation_listener, connection);
} else if (!connection->viewporter_ &&
(strcmp(interface, "wp_viewporter") == 0)) {
connection->viewporter_ = wl::Bind<wp_viewporter>(
registry, name, std::min(version, kMaxWpViewporterVersion));
+ if (!connection->viewporter_) {
+ LOG(ERROR) << "Failed to bind wp_viewporter";
+ return;
+ }
} else if (!connection->zcr_cursor_shapes_ &&
strcmp(interface, "zcr_cursor_shapes_v1") == 0) {
auto zcr_cursor_shapes = wl::Bind<zcr_cursor_shapes_v1>(
@@ -501,13 +595,22 @@ void WaylandConnection::Global(void* data,
}
} else if (!connection->xdg_foreign_ &&
strcmp(interface, "zxdg_exporter_v1") == 0) {
+ auto zxdg_exporter = wl::Bind<zxdg_exporter_v1>(registry, name, version);
+ if (!zxdg_exporter) {
+ LOG(ERROR) << "Failed to bind zxdg_exporter";
+ return;
+ }
connection->xdg_foreign_ = std::make_unique<XdgForeignWrapper>(
- connection, wl::Bind<zxdg_exporter_v1>(registry, name, version));
+ connection, std::move(zxdg_exporter));
} else if (!connection->drm_ && (strcmp(interface, "wl_drm") == 0) &&
version >= kMinWlDrmVersion) {
- auto wayland_drm = wl::Bind<struct wl_drm>(registry, name, version);
+ auto wl_drm = wl::Bind<struct wl_drm>(registry, name, version);
+ if (!wl_drm) {
+ LOG(ERROR) << "Failed to bind wl_drm";
+ return;
+ }
connection->drm_ =
- std::make_unique<WaylandDrm>(wayland_drm.release(), connection);
+ std::make_unique<WaylandDrm>(wl_drm.release(), connection);
} else if (!connection->zaura_shell_ &&
(strcmp(interface, "zaura_shell") == 0)) {
auto zaura_shell = wl::Bind<struct zaura_shell>(
@@ -518,11 +621,28 @@ void WaylandConnection::Global(void* data,
}
connection->zaura_shell_ =
std::make_unique<WaylandZAuraShell>(zaura_shell.release(), connection);
+ } else if (!connection->wayland_zwp_pointer_gestures_ &&
+ strcmp(interface, "zwp_pointer_gestures_v1") == 0 &&
+ version >= kMinZwpPointerGesturesVersion) {
+ auto zwp_pointer_gestures_v1 =
+ wl::Bind<struct zwp_pointer_gestures_v1>(registry, name, version);
+ if (!zwp_pointer_gestures_v1) {
+ LOG(ERROR) << "Failed to bind wp_pointer_gestures_v1";
+ return;
+ }
+ connection->wayland_zwp_pointer_gestures_ =
+ std::make_unique<WaylandZwpPointerGestures>(
+ zwp_pointer_gestures_v1.release(), connection,
+ connection->event_source());
} else if (!connection->xdg_decoration_manager_ &&
strcmp(interface, "zxdg_decoration_manager_v1") == 0) {
connection->xdg_decoration_manager_ =
wl::Bind<struct zxdg_decoration_manager_v1>(
registry, name, std::min(version, kMaxXdgDecorationVersion));
+ if (!connection->xdg_decoration_manager_) {
+ LOG(ERROR) << "Failed to bind zxdg_decoration_manager_v1";
+ return;
+ }
} else if (!connection->extended_drag_v1_ &&
strcmp(interface, "zcr_extended_drag_v1") == 0) {
connection->extended_drag_v1_ = wl::Bind<zcr_extended_drag_v1>(
@@ -536,6 +656,38 @@ void WaylandConnection::Global(void* data,
connection->ScheduleFlush();
}
+base::TimeTicks WaylandConnection::ConvertPresentationTime(uint32_t tv_sec_hi,
+ uint32_t tv_sec_lo,
+ uint32_t tv_nsec) {
+ DCHECK(presentation());
+ // base::TimeTicks::Now() uses CLOCK_MONOTONIC, no need to convert clock
+ // domain if wp_presentation also uses it.
+ if (presentation_clk_id_ == CLOCK_MONOTONIC) {
+ return base::TimeTicks() +
+ base::TimeDelta::FromMicroseconds(
+ ConvertTimespecResultToMicros(tv_sec_hi, tv_sec_lo, tv_nsec));
+ }
+
+ struct timespec presentation_now;
+ base::TimeTicks now = base::TimeTicks::Now();
+ int ret = clock_gettime(presentation_clk_id_, &presentation_now);
+
+ if (ret < 0) {
+ presentation_now.tv_sec = 0;
+ presentation_now.tv_nsec = 0;
+ LOG(ERROR) << "Error: failure to read the wp_presentation clock "
+ << presentation_clk_id_ << ": '" << strerror(errno) << "' "
+ << errno;
+ return base::TimeTicks::Now();
+ }
+
+ int64_t delta_us =
+ ConvertTimespecResultToMicros(tv_sec_hi, tv_sec_lo, tv_nsec) -
+ ConvertTimespecToMicros(presentation_now);
+
+ return now + base::TimeDelta::FromMicroseconds(delta_us);
+}
+
// static
void WaylandConnection::GlobalRemove(void* data,
wl_registry* registry,
@@ -580,4 +732,14 @@ void WaylandConnection::Ping(void* data, xdg_wm_base* shell, uint32_t serial) {
connection->ScheduleFlush();
}
+// static
+void WaylandConnection::ClockId(void* data,
+ wp_presentation* shell_v6,
+ uint32_t clk_id) {
+ DCHECK_EQ(base::TimeTicks::GetClock(),
+ base::TimeTicks::Clock::LINUX_CLOCK_MONOTONIC);
+ WaylandConnection* connection = static_cast<WaylandConnection*>(data);
+ connection->presentation_clk_id_ = clk_id;
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_connection.h b/chromium/ui/ozone/platform/wayland/host/wayland_connection.h
index 104b33c3774..19dca2c1c52 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_connection.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_connection.h
@@ -5,9 +5,11 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_CONNECTION_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_CONNECTION_H_
+#include <time.h>
#include <memory>
#include <vector>
+#include "base/time/time.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/events/event.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
@@ -17,6 +19,7 @@
#include "ui/ozone/platform/wayland/host/wayland_window_manager.h"
struct wl_cursor;
+struct wl_event_queue;
namespace gfx {
class Point;
@@ -41,11 +44,13 @@ class WaylandShm;
class WaylandTouch;
class WaylandZAuraShell;
class WaylandZcrCursorShapes;
+class WaylandZwpPointerGestures;
class WaylandZwpLinuxDmabuf;
class WaylandDataDeviceManager;
class WaylandCursorPosition;
class WaylandWindowDragController;
class GtkPrimarySelectionDeviceManager;
+class GtkShell1;
class ZwpPrimarySelectionDeviceManager;
class XdgForeignWrapper;
@@ -67,11 +72,25 @@ class WaylandConnection {
// Schedules a flush of the Wayland connection.
void ScheduleFlush();
+ // Calls wl_display_roundtrip_queue. Might be required during initialization
+ // of some objects that should block until they are initialized.
+ void RoundTripQueue();
+
// Sets a callback that that shutdowns the browser in case of unrecoverable
// error. Called by WaylandEventWatcher.
void SetShutdownCb(base::OnceCallback<void()> shutdown_cb);
+ // A correct display must be chosen when creating objects or calling
+ // roundrips. That is, all the methods that deal with polling, pulling event
+ // queues, etc, must use original display. All the other methods that create
+ // various wayland objects must use |display_wrapper_| so that the new objects
+ // are associated with the correct event queue. Otherwise, they will use a
+ // default event queue, which we do not use. See the comment below about the
+ // |event_queue_|.
wl_display* display() const { return display_.get(); }
+ wl_display* display_wrapper() const {
+ return reinterpret_cast<wl_display*>(wrapped_display_.get());
+ }
wl_compositor* compositor() const { return compositor_.get(); }
// The server version of the compositor interface (might be higher than the
// version binded).
@@ -102,6 +121,11 @@ class WaylandConnection {
uint32_t serial() const { return serial_.serial; }
EventSerial event_serial() const { return serial_; }
+ void set_pointer_enter_serial(uint32_t serial) {
+ pointer_enter_serial_ = serial;
+ }
+ uint32_t pointer_enter_serial() const { return pointer_enter_serial_; }
+
void SetPlatformCursor(wl_cursor* cursor_data, int buffer_scale);
void SetCursorBufferListener(WaylandCursorBufferListener* listener);
@@ -161,6 +185,8 @@ class WaylandConnection {
return gtk_primary_selection_device_manager_.get();
}
+ GtkShell1* gtk_shell1() { return gtk_shell1_.get(); }
+
ZwpPrimarySelectionDeviceManager* zwp_primary_selection_device_manager()
const {
return zwp_primary_selection_device_manager_.get();
@@ -182,6 +208,17 @@ class WaylandConnection {
// Creates a new wl_surface.
wl::Object<wl_surface> CreateSurface();
+ // base::TimeTicks::Now() in posix uses CLOCK_MONOTONIC, wp_presentation
+ // timestamps are in clk_id sent in wp_presentation.clock_id event. This
+ // converts wp_presentation timestamp to base::TimeTicks.
+ // The approximation relies on presentation timestamp to be close to current
+ // time. The further it is from current time and the bigger the speed
+ // difference between the two clock domains, the bigger the conversion error.
+ // Conversion error due to system load is biased and unbounded.
+ base::TimeTicks ConvertPresentationTime(uint32_t tv_sec_hi,
+ uint32_t tv_sec_lo,
+ uint32_t tv_nsec);
+
private:
friend class WaylandConnectionTestApi;
@@ -216,8 +253,13 @@ class WaylandConnection {
// xdg_wm_base_listener
static void Ping(void* data, xdg_wm_base* shell, uint32_t serial);
+ // xdg_wm_base_listener
+ static void ClockId(void* data, wp_presentation* shell_v6, uint32_t clk_id);
+
uint32_t compositor_version_ = 0;
wl::Object<wl_display> display_;
+ wl::Object<wl_proxy> wrapped_display_;
+ wl::Object<wl_event_queue> event_queue_;
wl::Object<wl_registry> registry_;
wl::Object<wl_compositor> compositor_;
wl::Object<wl_subcompositor> subcompositor_;
@@ -244,26 +286,34 @@ class WaylandConnection {
std::unique_ptr<WaylandCursor> cursor_;
std::unique_ptr<WaylandDataDeviceManager> data_device_manager_;
- std::unique_ptr<WaylandClipboard> clipboard_;
std::unique_ptr<WaylandOutputManager> wayland_output_manager_;
std::unique_ptr<WaylandCursorPosition> wayland_cursor_position_;
std::unique_ptr<WaylandZAuraShell> zaura_shell_;
std::unique_ptr<WaylandZcrCursorShapes> zcr_cursor_shapes_;
+ std::unique_ptr<WaylandZwpPointerGestures> wayland_zwp_pointer_gestures_;
std::unique_ptr<WaylandZwpLinuxDmabuf> zwp_dmabuf_;
std::unique_ptr<WaylandDrm> drm_;
std::unique_ptr<WaylandShm> shm_;
std::unique_ptr<WaylandBufferManagerHost> buffer_manager_host_;
std::unique_ptr<XdgForeignWrapper> xdg_foreign_;
+ // Clipboard-related objects. |clipboard_| must be declared after all
+ // DeviceManager instances it depends on, otherwise tests may crash with
+ // UAFs while attempting to access already destroyed manager pointers.
std::unique_ptr<GtkPrimarySelectionDeviceManager>
gtk_primary_selection_device_manager_;
-
std::unique_ptr<ZwpPrimarySelectionDeviceManager>
zwp_primary_selection_device_manager_;
+ std::unique_ptr<WaylandClipboard> clipboard_;
+
+ std::unique_ptr<GtkShell1> gtk_shell1_;
std::unique_ptr<WaylandDataDragController> data_drag_controller_;
std::unique_ptr<WaylandWindowDragController> window_drag_controller_;
+ // Describes the clock domain that wp_presentation timestamps are in.
+ uint32_t presentation_clk_id_ = CLOCK_MONOTONIC;
+
// Helper class that lets input emulation access some data of objects
// that Wayland holds. For example, wl_surface and others. It's only
// created when platform window test config is set.
@@ -277,6 +327,8 @@ class WaylandConnection {
bool scheduled_flush_ = false;
EventSerial serial_;
+
+ uint32_t pointer_enter_serial_ = 0;
};
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_connection_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_connection_unittest.cc
index 4d6cabb6a2e..fa467468513 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_connection_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_connection_unittest.cc
@@ -16,17 +16,14 @@
namespace ui {
-namespace {
-constexpr uint32_t kXdgVersionStable = 7;
-}
-
TEST(WaylandConnectionTest, Ping) {
base::test::SingleThreadTaskEnvironment task_environment(
base::test::SingleThreadTaskEnvironment::MainThreadType::UI);
wl::TestWaylandServerThread server;
- ASSERT_TRUE(server.Start(kXdgVersionStable));
+ ASSERT_TRUE(server.Start({.shell_version = wl::ShellVersion::kStable}));
WaylandConnection connection;
ASSERT_TRUE(connection.Initialize());
+ connection.event_source()->UseSingleThreadedPollingForTesting();
connection.event_source()->StartProcessingEvents();
base::RunLoop().RunUntilIdle();
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_cursor.cc b/chromium/ui/ozone/platform/wayland/host/wayland_cursor.cc
index 981ade1b03e..575fe2ca9d9 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_cursor.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_cursor.cc
@@ -97,8 +97,8 @@ void WaylandCursor::SetPlatformShape(wl_cursor* cursor_data,
void WaylandCursor::HideCursor() {
DCHECK(pointer_);
- wl_pointer_set_cursor(pointer_->wl_object(), connection_->serial(), nullptr,
- 0, 0);
+ wl_pointer_set_cursor(pointer_->wl_object(),
+ connection_->pointer_enter_serial(), nullptr, 0, 0);
wl_surface_attach(pointer_surface_.get(), nullptr, 0, 0);
wl_surface_commit(pointer_surface_.get());
@@ -142,7 +142,8 @@ void WaylandCursor::AttachAndCommit(wl_buffer* buffer,
uint32_t hotspot_y_dip) {
DCHECK(pointer_);
- wl_pointer_set_cursor(pointer_->wl_object(), connection_->serial(),
+ wl_pointer_set_cursor(pointer_->wl_object(),
+ connection_->pointer_enter_serial(),
pointer_surface_.get(), hotspot_x_dip, hotspot_y_dip);
wl_surface_damage(pointer_surface_.get(), 0, 0, buffer_width, buffer_height);
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.cc b/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.cc
index 32c7d6ffc42..855e347ef03 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.cc
@@ -11,6 +11,7 @@
#include "base/task/thread_pool.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/task_runner_util.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_shm.h"
@@ -48,7 +49,8 @@ void WaylandCursorFactory::ObserveThemeChanges() {
cursor_theme_observer_.Observe(cursor_theme_manager);
}
-PlatformCursor WaylandCursorFactory::GetDefaultCursor(mojom::CursorType type) {
+scoped_refptr<PlatformCursor> WaylandCursorFactory::GetDefaultCursor(
+ mojom::CursorType type) {
if (current_theme_->cache.count(type) == 0) {
for (const std::string& name : CursorNamesFromType(type)) {
wl_cursor* cursor = GetCursorFromTheme(name);
@@ -68,7 +70,7 @@ PlatformCursor WaylandCursorFactory::GetDefaultCursor(mojom::CursorType type) {
if (current_theme_->cache[type].get() == nullptr)
return BitmapCursorFactoryOzone::GetDefaultCursor(type);
- return static_cast<PlatformCursor>(current_theme_->cache[type].get());
+ return current_theme_->cache[type];
}
void WaylandCursorFactory::SetDeviceScaleFactor(float scale) {
@@ -155,6 +157,8 @@ void WaylandCursorFactory::OnThemeLoaded(const std::string& loaded_theme_name,
// wl_cursor_theme_load() can return nullptr. We don't check that here but
// have to be cautious when we actually load the shape.
current_theme_->theme.reset(loaded_theme);
+ current_theme_->cache.clear();
+ NotifyObserversOnThemeLoaded();
}
}
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.h b/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.h
index d480fb20123..2592141344e 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.h
@@ -36,7 +36,8 @@ class WaylandCursorFactory : public BitmapCursorFactoryOzone,
void ObserveThemeChanges() override;
// CursorFactory:
- PlatformCursor GetDefaultCursor(mojom::CursorType type) override;
+ scoped_refptr<PlatformCursor> GetDefaultCursor(
+ mojom::CursorType type) override;
void SetDeviceScaleFactor(float scale) override;
protected:
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory_unittest.cc
index 1d75ac374c4..47cb8394c48 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory_unittest.cc
@@ -8,14 +8,23 @@
#include "base/containers/flat_map.h"
#include "base/gtest_prod_util.h"
+#include "base/memory/scoped_refptr.h"
+#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/ozone/platform/wayland/test/wayland_test.h"
+using ::testing::Values;
+
namespace ui {
namespace {
// Overrides WaylandCursorFactory::GetCursorFromTheme() to pretend that cursors
// are really loaded.
+//
+// Note: the parent class does real Wayland calls that try to load the theme.
+// That may succeed or fail on the bot, but as GetCursorTheme() is overridden,
+// we ignore the result.
class DryRunningWaylandCursorFactory : public WaylandCursorFactory {
public:
explicit DryRunningWaylandCursorFactory(WaylandConnection* connection)
@@ -44,37 +53,53 @@ class DryRunningWaylandCursorFactory : public WaylandCursorFactory {
} // namespace
-class WaylandCursorFactoryTest : public WaylandTest {
+class WaylandCursorFactoryTest : public WaylandTest,
+ public CursorFactoryObserver {
public:
WaylandCursorFactoryTest() = default;
- void SetUp() override {
- WaylandTest::SetUp();
-
- cursor_factory_ =
- std::make_unique<DryRunningWaylandCursorFactory>(connection_.get());
+ // CursorFactoryObserver:
+ void OnThemeLoaded() override {
+ ASSERT_TRUE(loop_quit_closure_);
+ std::move(loop_quit_closure_).Run();
}
protected:
- std::unique_ptr<WaylandCursorFactory> cursor_factory_;
+ void WaitForThemeLoaded() {
+ base::RunLoop loop;
+ ASSERT_FALSE(loop_quit_closure_);
+ loop_quit_closure_ = loop.QuitClosure();
+ loop.Run();
+ }
+
+ private:
+ base::OnceClosure loop_quit_closure_;
};
// Tests that the factory holds the cursor theme until a buffer taken from it
// released.
TEST_P(WaylandCursorFactoryTest, RetainOldThemeUntilNewBufferIsAttached) {
+ std::unique_ptr<WaylandCursorFactory> cursor_factory =
+ std::make_unique<DryRunningWaylandCursorFactory>(connection_.get());
+ cursor_factory->AddObserver(this);
+
// The default theme should be loaded right away. The unloaded theme should
// not be set.
- EXPECT_NE(cursor_factory_->current_theme_, nullptr);
- EXPECT_EQ(cursor_factory_->unloaded_theme_, nullptr);
+ EXPECT_NE(cursor_factory->current_theme_, nullptr);
+ EXPECT_EQ(cursor_factory->unloaded_theme_, nullptr);
+
+ WaitForThemeLoaded();
// Trigger theme reload and ensure that the theme instance has changed.
// As we didn't request any buffers, the unloaded theme should not be held.
{
- auto* const current_theme = cursor_factory_->current_theme_.get();
- cursor_factory_->OnCursorThemeNameChanged("Theme1");
- EXPECT_NE(cursor_factory_->current_theme_, nullptr);
- EXPECT_NE(cursor_factory_->current_theme_.get(), current_theme);
- EXPECT_EQ(cursor_factory_->unloaded_theme_, nullptr);
+ auto* const current_theme = cursor_factory->current_theme_.get();
+ cursor_factory->OnCursorThemeNameChanged("Theme1");
+ EXPECT_NE(cursor_factory->current_theme_, nullptr);
+ EXPECT_NE(cursor_factory->current_theme_.get(), current_theme);
+ EXPECT_EQ(cursor_factory->unloaded_theme_, nullptr);
+
+ WaitForThemeLoaded();
}
// Now request some buffer, and while "holding" it (i.e., not notifying the
@@ -84,51 +109,57 @@ TEST_P(WaylandCursorFactoryTest, RetainOldThemeUntilNewBufferIsAttached) {
// the cursor from the "unloaded" theme. This must not trigger unloading of
// that theme.
{
- auto* const current_theme = cursor_factory_->current_theme_.get();
- auto* const cursor =
- cursor_factory_->GetDefaultCursor(mojom::CursorType::kPointer);
+ auto* const current_theme = cursor_factory->current_theme_.get();
+ auto const cursor =
+ cursor_factory->GetDefaultCursor(mojom::CursorType::kPointer);
EXPECT_NE(cursor, nullptr);
- EXPECT_GT(cursor_factory_->current_theme_->cache.size(), 0U);
+ EXPECT_GT(cursor_factory->current_theme_->cache.size(), 0U);
+
+ cursor_factory->OnCursorThemeNameChanged("Theme2");
+
+ EXPECT_EQ(cursor_factory->current_theme_->cache.size(), 0U);
+ EXPECT_NE(cursor_factory->current_theme_, nullptr);
+ EXPECT_NE(cursor_factory->current_theme_.get(), current_theme);
+ EXPECT_EQ(cursor_factory->unloaded_theme_.get(), current_theme);
- cursor_factory_->OnCursorThemeNameChanged("Theme2");
+ WaitForThemeLoaded();
- EXPECT_EQ(cursor_factory_->current_theme_->cache.size(), 0U);
- EXPECT_NE(cursor_factory_->current_theme_, nullptr);
- EXPECT_NE(cursor_factory_->current_theme_.get(), current_theme);
- EXPECT_EQ(cursor_factory_->unloaded_theme_.get(), current_theme);
+ cursor_factory->OnCursorThemeNameChanged("Theme3");
- cursor_factory_->OnCursorThemeNameChanged("Theme3");
+ EXPECT_EQ(cursor_factory->current_theme_->cache.size(), 0U);
+ EXPECT_NE(cursor_factory->current_theme_, nullptr);
+ EXPECT_NE(cursor_factory->current_theme_.get(), current_theme);
+ EXPECT_EQ(cursor_factory->unloaded_theme_.get(), current_theme);
- EXPECT_EQ(cursor_factory_->current_theme_->cache.size(), 0U);
- EXPECT_NE(cursor_factory_->current_theme_, nullptr);
- EXPECT_NE(cursor_factory_->current_theme_.get(), current_theme);
- EXPECT_EQ(cursor_factory_->unloaded_theme_.get(), current_theme);
+ WaitForThemeLoaded();
- cursor_factory_->OnCursorBufferAttached(static_cast<wl_cursor*>(
- static_cast<BitmapCursorOzone*>(cursor)->platform_data()));
- EXPECT_EQ(cursor_factory_->unloaded_theme_.get(), current_theme);
+ cursor_factory->OnCursorBufferAttached(static_cast<wl_cursor*>(
+ BitmapCursorOzone::FromPlatformCursor(cursor)->platform_data()));
+ EXPECT_EQ(cursor_factory->unloaded_theme_.get(), current_theme);
}
// Finally, tell the factory that we have attached a buffer from the current
// theme. This time the old theme held since a while ago should be freed.
{
- auto* const cursor =
- cursor_factory_->GetDefaultCursor(mojom::CursorType::kPointer);
+ auto const cursor =
+ cursor_factory->GetDefaultCursor(mojom::CursorType::kPointer);
EXPECT_NE(cursor, nullptr);
- cursor_factory_->OnCursorBufferAttached(static_cast<wl_cursor*>(
- static_cast<BitmapCursorOzone*>(cursor)->platform_data()));
+ cursor_factory->OnCursorBufferAttached(static_cast<wl_cursor*>(
+ BitmapCursorOzone::FromPlatformCursor(cursor)->platform_data()));
- EXPECT_EQ(cursor_factory_->unloaded_theme_.get(), nullptr);
+ EXPECT_EQ(cursor_factory->unloaded_theme_.get(), nullptr);
}
}
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandCursorFactoryTest,
- ::testing::Values(kXdgShellStable));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
WaylandCursorFactoryTest,
- ::testing::Values(kXdgShellV6));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kV6}));
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_data_device.cc b/chromium/ui/ozone/platform/wayland/host/wayland_data_device.cc
index 467944f1d96..48bcf635f7b 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_data_device.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_data_device.cc
@@ -75,8 +75,8 @@ void WaylandDataDevice::RequestData(WaylandDataOffer* offer,
}
void WaylandDataDevice::SetSelectionSource(WaylandDataSource* source) {
- DCHECK(source);
- wl_data_device_set_selection(data_device_.get(), source->data_source(),
+ auto* data_source = source ? source->data_source() : nullptr;
+ wl_data_device_set_selection(data_device_.get(), data_source,
connection()->serial());
connection()->ScheduleFlush();
}
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_data_device_base.cc b/chromium/ui/ozone/platform/wayland/host/wayland_data_device_base.cc
index 50be3ad35bc..d68ed87b40d 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_data_device_base.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_data_device_base.cc
@@ -65,7 +65,8 @@ void WaylandDataDeviceBase::ReadClipboardDataFromFD(
void WaylandDataDeviceBase::RegisterDeferredReadCallback() {
DCHECK(!deferred_read_callback_);
- deferred_read_callback_.reset(wl_display_sync(connection_->display()));
+ deferred_read_callback_.reset(
+ wl_display_sync(connection_->display_wrapper()));
static const wl_callback_listener kListener = {
WaylandDataDeviceBase::DeferredReadCallback};
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc b/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
index 56400fa7070..b6168cc347c 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
@@ -4,15 +4,19 @@
#include "ui/ozone/platform/wayland/host/wayland_data_drag_controller.h"
+#include <bitset>
#include <cstdint>
#include "base/check.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_util.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard_constants.h"
#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/dragdrop/os_exchange_data_provider_non_backed.h"
#include "ui/ozone/platform/wayland/common/data_util.h"
@@ -26,9 +30,26 @@
#include "ui/ozone/platform/wayland/host/wayland_window_manager.h"
namespace ui {
-
namespace {
+using mojom::DragOperation;
+
+DragOperation DndActionToDragOperation(uint32_t action) {
+ // Prevent the usage of this function for an operation mask.
+ DCHECK_LE(std::bitset<32>(action).count(), 1u);
+ switch (action) {
+ case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY:
+ return DragOperation::kCopy;
+ case WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE:
+ return DragOperation::kMove;
+ case WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK:
+ // Unsupported in the browser.
+ FALLTHROUGH;
+ default:
+ return DragOperation::kNone;
+ }
+}
+
int DndActionsToDragOperations(uint32_t actions) {
int operations = DragDropTypes::DRAG_NONE;
if (actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
@@ -142,9 +163,6 @@ void WaylandDataDragController::OnDragEnter(WaylandWindow* window,
DCHECK(data_offer_);
window_ = window;
- // TODO(crbug.com/1004715): Set mime type the client can accept. Now it sets
- // all mime types offered because current implementation doesn't decide
- // action based on mime type.
unprocessed_mime_types_.clear();
for (auto mime : data_offer_->mime_types()) {
unprocessed_mime_types_.push_back(mime);
@@ -220,7 +238,8 @@ void WaylandDataDragController::OnDataSourceFinish(bool completed) {
DCHECK(data_source_);
if (origin_window_) {
- origin_window_->OnDragSessionClose(data_source_->dnd_action());
+ origin_window_->OnDragSessionClose(
+ DndActionToDragOperation(data_source_->dnd_action()));
// DnD handlers expect DragLeave to be sent for drag sessions that end up
// with no data transfer (wl_data_source::cancelled event).
if (!completed)
@@ -277,6 +296,18 @@ void WaylandDataDragController::Offer(const OSExchangeData& data,
mime_types.push_back(kMimeTypeTextUtf8);
mime_types.push_back(kMimeTypeText);
}
+ if (data.HasFileContents()) {
+ base::FilePath file_contents_filename;
+ std::string file_contents;
+ data.GetFileContents(&file_contents_filename, &file_contents);
+
+ std::string filename = file_contents_filename.value();
+ base::ReplaceChars(filename, "\\", "\\\\", &filename);
+ base::ReplaceChars(filename, "\"", "\\\"", &filename);
+ const std::string mime_type =
+ base::StrCat({kMimeTypeOctetStream, ";name=\"", filename, "\""});
+ mime_types.push_back(mime_type);
+ }
DCHECK(!mime_types.empty());
data_source_->Offer(mime_types);
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
index cabd7bb976b..8d1c7c68f72 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
@@ -16,6 +16,7 @@
#include "ui/base/clipboard/file_info.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/events/base_event_utils.h"
#include "ui/gfx/geometry/point.h"
@@ -40,15 +41,18 @@
#include "ui/platform_window/wm/wm_drop_handler.h"
#include "url/gurl.h"
-using testing::_;
-using testing::Mock;
+using ::testing::_;
+using ::testing::Mock;
+using ::testing::Values;
+using ui::mojom::DragOperation;
namespace ui {
-
namespace {
constexpr char kSampleTextForDragAndDrop[] =
"This is a sample text for drag-and-drop.";
+constexpr char16_t kSampleTextForDragAndDrop16[] =
+ u"This is a sample text for drag-and-drop.";
constexpr FilenameToURLPolicy kFilenameToURLPolicy =
FilenameToURLPolicy::CONVERT_FILENAMES;
@@ -69,9 +73,8 @@ PlatformClipboard::Data ToClipboardData(const StringType& data_string) {
class MockDragHandlerDelegate : public WmDragHandler::Delegate {
public:
MOCK_METHOD1(OnDragLocationChanged, void(const gfx::Point& location));
- MOCK_METHOD1(OnDragOperationChanged,
- void(DragDropTypes::DragOperation operation));
- MOCK_METHOD1(OnDragFinished, void(int operation));
+ MOCK_METHOD1(OnDragOperationChanged, void(DragOperation operation));
+ MOCK_METHOD1(OnDragFinished, void(DragOperation operation));
};
class MockDropHandler : public WmDropHandler {
@@ -164,8 +167,7 @@ class WaylandDataDragControllerTest : public WaylandDragDropTest {
WaylandWindow* window() { return window_.get(); }
std::u16string sample_text_for_dnd() const {
- static auto text = base::ASCIIToUTF16(kSampleTextForDragAndDrop);
- return text;
+ return kSampleTextForDragAndDrop16;
}
void RunDragLoopWithSampleData(WaylandWindow* origin_window, int operations) {
@@ -206,7 +208,9 @@ class WaylandDataDragControllerTest : public WaylandDragDropTest {
// If DnD was cancelled, or data was dropped where it was not
// accepted, the operation result must be None (0).
// Regression test for https://crbug.com/1136751.
- EXPECT_CALL(*self->drag_handler(), OnDragFinished(0)).Times(1);
+ EXPECT_CALL(*self->drag_handler(),
+ OnDragFinished(DragOperation::kNone))
+ .Times(1);
self->Sync();
},
@@ -307,6 +311,37 @@ TEST_P(WaylandDataDragControllerTest, StartDragWithText) {
window_->SetPointerFocus(restored_focus);
}
+TEST_P(WaylandDataDragControllerTest, StartDragWithFileContents) {
+ bool restored_focus = window_->has_pointer_focus();
+ window_->SetPointerFocus(true);
+
+ // The client starts dragging offering text mime type.
+ OSExchangeData os_exchange_data;
+ os_exchange_data.SetFileContents(
+ base::FilePath(FILE_PATH_LITERAL("t\\est\".jpg")),
+ kSampleTextForDragAndDrop);
+ int operation = DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE;
+ drag_controller()->StartSession(os_exchange_data, operation);
+ Sync();
+
+ base::RunLoop run_loop;
+ auto callback = base::BindOnce(
+ [](base::RunLoop* loop, std::vector<uint8_t>&& data) {
+ std::string result(data.begin(), data.end());
+ EXPECT_EQ(kSampleTextForDragAndDrop, result);
+ loop->Quit();
+ },
+ &run_loop);
+ data_device_manager_->data_source()->ReadData(
+ "application/octet-stream;name=\"t\\\\est\\\".jpg\"",
+ std::move(callback));
+ run_loop.Run();
+ EXPECT_EQ(1u, data_device_manager_->data_source()->mime_types().size());
+ EXPECT_EQ("application/octet-stream;name=\"t\\\\est\\\".jpg\"",
+ data_device_manager_->data_source()->mime_types().front());
+ window_->SetPointerFocus(restored_focus);
+}
+
TEST_P(WaylandDataDragControllerTest, ReceiveDrag) {
auto* data_offer = data_device_manager_->data_device()->OnDataOffer();
data_offer->OnOffer(kMimeTypeText,
@@ -350,9 +385,9 @@ TEST_P(WaylandDataDragControllerTest, DropSeveralMimeTypes) {
auto* data_offer = data_device_manager_->data_device()->OnDataOffer();
data_offer->OnOffer(kMimeTypeText,
ToClipboardData(std::string(kSampleTextForDragAndDrop)));
- data_offer->OnOffer(kMimeTypeMozillaURL, ToClipboardData(base::UTF8ToUTF16(
- "https://sample.com/\r\n"
- "Sample")));
+ data_offer->OnOffer(
+ kMimeTypeMozillaURL,
+ ToClipboardData(std::u16string(u"https://sample.com/\r\nSample")));
data_offer->OnOffer(
kMimeTypeURIList,
ToClipboardData(std::string("file:///home/user/file\r\n")));
@@ -442,21 +477,20 @@ TEST_P(WaylandDataDragControllerTest, ValidateDroppedUriList) {
// the console when this test is running are the expected and valid side effect.
TEST_P(WaylandDataDragControllerTest, ValidateDroppedXMozUrl) {
const struct {
- std::string content;
+ std::u16string content;
std::string expected_url;
- std::string expected_title;
+ std::u16string expected_title;
} kCases[] = {
{{}, {}, {}},
- {"http://sample.com/\r\nSample", "http://sample.com/", "Sample"},
- {"http://title.must.be.set/", {}, {}},
- {"url.must.be.valid/and/have.scheme\r\nInvalid URL", {}, {}},
- {"file:///files/are/ok\r\nThe policy allows that", "file:///files/are/ok",
- "The policy allows that"}};
+ {u"http://sample.com/\r\nSample", "http://sample.com/", u"Sample"},
+ {u"http://title.must.be.set/", {}, {}},
+ {u"url.must.be.valid/and/have.scheme\r\nInvalid URL", {}, {}},
+ {u"file:///files/are/ok\r\nThe policy allows that",
+ "file:///files/are/ok", u"The policy allows that"}};
for (const auto& kCase : kCases) {
auto* data_offer = data_device_manager_->data_device()->OnDataOffer();
- data_offer->OnOffer(kMimeTypeMozillaURL,
- ToClipboardData(base::UTF8ToUTF16(kCase.content)));
+ data_offer->OnOffer(kMimeTypeMozillaURL, ToClipboardData(kCase.content));
EXPECT_CALL(*drop_handler_, MockOnDragEnter()).Times(1);
gfx::Point entered_point(10, 10);
@@ -484,7 +518,7 @@ TEST_P(WaylandDataDragControllerTest, ValidateDroppedXMozUrl) {
EXPECT_TRUE(
dropped_data->GetURLAndTitle(kFilenameToURLPolicy, &url, &title));
EXPECT_EQ(url.spec(), kCase.expected_url);
- EXPECT_EQ(title, base::UTF8ToUTF16(kCase.expected_title));
+ EXPECT_EQ(title, kCase.expected_title);
}
EXPECT_CALL(*drop_handler_, OnDragLeave()).Times(1);
@@ -751,10 +785,12 @@ TEST_P(WaylandDataDragControllerTest, MenuRequestCreatesPopupWindow) {
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandDataDragControllerTest,
- ::testing::Values(kXdgShellStable));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
WaylandDataDragControllerTest,
- ::testing::Values(kXdgShellV6));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kV6}));
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_data_source.cc b/chromium/ui/ozone/platform/wayland/host/wayland_data_source.cc
index 2788c040a64..3c199a27948 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_data_source.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_data_source.cc
@@ -37,7 +37,7 @@ template <typename T>
void DataSource<T>::HandleSendEvent(const std::string& mime_type, int32_t fd) {
std::string contents;
delegate_->OnDataSourceSend(mime_type, &contents);
- bool done = base::WriteFileDescriptor(fd, contents.data(), contents.length());
+ bool done = base::WriteFileDescriptor(fd, contents);
DCHECK(done);
close(fd);
}
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_drm.cc b/chromium/ui/ozone/platform/wayland/host/wayland_drm.cc
index e387e48c686..df692b6734a 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_drm.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_drm.cc
@@ -29,7 +29,7 @@ WaylandDrm::WaylandDrm(wl_drm* drm, WaylandConnection* connection)
// A roundtrip after binding guarantees that the client has received all
// supported formats and capabilities of the device.
- wl_display_roundtrip(connection_->display());
+ connection_->RoundTripQueue();
}
WaylandDrm::~WaylandDrm() = default;
@@ -106,7 +106,7 @@ void WaylandDrm::Authenticate(const char* drm_device_path) {
// Do the roundtrip to make sure the server processes this request and
// authenticates us.
- wl_display_roundtrip(connection_->display());
+ connection_->RoundTripQueue();
}
void WaylandDrm::DrmDeviceAuthenticated(struct wl_drm* wl_drm) {
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_event_source.cc b/chromium/ui/ozone/platform/wayland/host/wayland_event_source.cc
index 46327d9631e..6e23105258a 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_event_source.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_event_source.cc
@@ -10,8 +10,8 @@
#include "base/bind.h"
#include "base/check.h"
#include "base/logging.h"
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
@@ -63,12 +63,24 @@ WaylandEventSource::TouchPoint::TouchPoint(gfx::PointF location,
DCHECK(window);
}
+WaylandEventSource::PointerFrame::PointerFrame() = default;
+WaylandEventSource::PointerFrame::PointerFrame(const PointerFrame&) = default;
+WaylandEventSource::PointerFrame::PointerFrame(PointerFrame&&) = default;
+WaylandEventSource::PointerFrame::~PointerFrame() = default;
+
+WaylandEventSource::PointerFrame& WaylandEventSource::PointerFrame::operator=(
+ const PointerFrame&) = default;
+WaylandEventSource::PointerFrame& WaylandEventSource::PointerFrame::operator=(
+ PointerFrame&&) = default;
+
// WaylandEventSource implementation
WaylandEventSource::WaylandEventSource(wl_display* display,
+ wl_event_queue* event_queue,
WaylandWindowManager* window_manager)
: window_manager_(window_manager),
- event_watcher_(std::make_unique<WaylandEventWatcher>(display)) {
+ event_watcher_(
+ std::make_unique<WaylandEventWatcher>(display, event_queue)) {
DCHECK(window_manager_);
// Observes remove changes to know when touch points can be removed.
@@ -81,12 +93,12 @@ void WaylandEventSource::SetShutdownCb(base::OnceCallback<void()> shutdown_cb) {
event_watcher_->SetShutdownCb(std::move(shutdown_cb));
}
-bool WaylandEventSource::StartProcessingEvents() {
- return event_watcher_->StartProcessingEvents();
+void WaylandEventSource::StartProcessingEvents() {
+ event_watcher_->StartProcessingEvents();
}
-bool WaylandEventSource::StopProcessingEvents() {
- return event_watcher_->StopProcessingEvents();
+void WaylandEventSource::StopProcessingEvents() {
+ event_watcher_->StopProcessingEvents();
}
void WaylandEventSource::OnKeyboardFocusChanged(WaylandWindow* window,
@@ -185,11 +197,7 @@ void WaylandEventSource::OnPointerMotionEvent(const gfx::PointF& location) {
DispatchEvent(&event);
}
-void WaylandEventSource::OnPointerAxisEvent(const gfx::Vector2d& offset) {
- int flags = pointer_flags_ | keyboard_modifiers_;
- MouseWheelEvent event(offset, pointer_location_, pointer_location_,
- EventTimeForNow(), flags, 0);
- DispatchEvent(&event);
+void WaylandEventSource::OnPointerAxisEvent(const gfx::Vector2dF& offset) {
current_pointer_frame_.dx += offset.x();
current_pointer_frame_.dy += offset.y();
}
@@ -198,34 +206,63 @@ void WaylandEventSource::OnResetPointerFlags() {
ResetPointerFlags();
}
+const gfx::PointF& WaylandEventSource::GetPointerLocation() const {
+ return pointer_location_;
+}
+
void WaylandEventSource::OnPointerFrameEvent() {
base::TimeTicks now = EventTimeForNow();
current_pointer_frame_.dt = now - last_pointer_frame_time_;
last_pointer_frame_time_ = now;
+ int flags = pointer_flags_ | keyboard_modifiers_;
+
+ static constexpr bool supports_trackpad_kinetic_scrolling =
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+ true;
+#else
+ false;
+#endif
+
// Dispatch Fling event if pointer.axis_stop is notified and the recent
// pointer.axis events meets the criteria to start fling scroll.
if (current_pointer_frame_.dx == 0 && current_pointer_frame_.dy == 0 &&
- current_pointer_frame_.is_axis_stop) {
+ current_pointer_frame_.is_axis_stop &&
+ supports_trackpad_kinetic_scrolling) {
gfx::Vector2dF initial_velocity = ComputeFlingVelocity();
float vx = initial_velocity.x();
float vy = initial_velocity.y();
ScrollEvent event(
vx == 0 && vy == 0 ? ET_SCROLL_FLING_CANCEL : ET_SCROLL_FLING_START,
- pointer_location_, pointer_location_, now,
- pointer_flags_ | keyboard_modifiers_, vx, vy, vx, vy,
+ pointer_location_, pointer_location_, now, flags, vx, vy, vx, vy,
kGestureScrollFingerCount);
DispatchEvent(&event);
recent_pointer_frames_.clear();
- } else {
+ } else if (current_pointer_frame_.axis_source) {
+ if (*current_pointer_frame_.axis_source == WL_POINTER_AXIS_SOURCE_WHEEL) {
+ MouseWheelEvent event(
+ gfx::Vector2d(current_pointer_frame_.dx, current_pointer_frame_.dy),
+ pointer_location_, pointer_location_, EventTimeForNow(), flags, 0);
+ DispatchEvent(&event);
+ } else if (*current_pointer_frame_.axis_source ==
+ WL_POINTER_AXIS_SOURCE_FINGER) {
+ ScrollEvent event(ET_SCROLL, pointer_location_, pointer_location_,
+ EventTimeForNow(), flags, current_pointer_frame_.dx,
+ current_pointer_frame_.dy, current_pointer_frame_.dx,
+ current_pointer_frame_.dy, kGestureScrollFingerCount);
+ DispatchEvent(&event);
+ }
+
if (recent_pointer_frames_.size() + 1 > kRecentPointerFrameMaxSize)
recent_pointer_frames_.pop_back();
recent_pointer_frames_.push_front(current_pointer_frame_);
}
+
// Reset |current_pointer_frame_|.
current_pointer_frame_.dx = 0;
current_pointer_frame_.dy = 0;
current_pointer_frame_.is_axis_stop = false;
+ current_pointer_frame_.axis_source.reset();
}
void WaylandEventSource::OnPointerAxisSourceEvent(uint32_t axis_source) {
@@ -309,6 +346,23 @@ void WaylandEventSource::OnTouchCancelEvent() {
touch_points_.clear();
}
+void WaylandEventSource::OnPinchEvent(EventType event_type,
+ const gfx::Vector2dF& delta,
+ base::TimeTicks timestamp,
+ int device_id,
+ absl::optional<float> scale) {
+ GestureEventDetails details(event_type);
+ details.set_device_type(GestureDeviceType::DEVICE_TOUCHPAD);
+ if (scale)
+ details.set_scale(*scale);
+
+ auto location = pointer_location_ + delta;
+ GestureEvent event(location.x(), location.y(), 0 /* flags */, timestamp,
+ details);
+ event.set_source_device_id(device_id);
+ DispatchEvent(&event);
+}
+
bool WaylandEventSource::IsPointerButtonPressed(EventFlags button) const {
DCHECK(HasAnyPointerButtonFlag(button));
return pointer_flags_ & button;
@@ -318,6 +372,10 @@ void WaylandEventSource::ResetPointerFlags() {
pointer_flags_ = 0;
}
+void WaylandEventSource::UseSingleThreadedPollingForTesting() {
+ event_watcher_->UseSingleThreadedPollingForTesting();
+}
+
void WaylandEventSource::OnDispatcherListChanged() {
StartProcessingEvents();
}
@@ -372,7 +430,7 @@ void WaylandEventSource::HandlePointerFocusChange(WaylandWindow* window) {
void WaylandEventSource::HandleTouchFocusChange(WaylandWindow* window,
bool focused,
- base::Optional<PointerId> id) {
+ absl::optional<PointerId> id) {
DCHECK(window);
bool actual_focus = id ? !ShouldUnsetTouchFocus(window, id.value()) : focused;
window->set_touch_focus(actual_focus);
@@ -395,8 +453,10 @@ gfx::Vector2dF WaylandEventSource::ComputeFlingVelocity() {
float dx = 0.0f;
float dy = 0.0f;
for (auto& frame : recent_pointer_frames_) {
- if (frame.axis_source != WL_POINTER_AXIS_SOURCE_FINGER)
+ if (frame.axis_source &&
+ *frame.axis_source != WL_POINTER_AXIS_SOURCE_FINGER) {
break;
+ }
if (frame.dx == 0 && frame.dy == 0)
break;
if (dt + frame.dt > base::TimeDelta::FromMilliseconds(200))
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_event_source.h b/chromium/ui/ozone/platform/wayland/host/wayland_event_source.h
index 9617a85b41e..2a44970ebe3 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_event_source.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_event_source.h
@@ -9,8 +9,8 @@
#include <memory>
#include "base/containers/flat_map.h"
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/platform/platform_event_source.h"
@@ -22,13 +22,13 @@
#include "ui/ozone/platform/wayland/host/wayland_keyboard.h"
#include "ui/ozone/platform/wayland/host/wayland_pointer.h"
#include "ui/ozone/platform/wayland/host/wayland_touch.h"
-#include "ui/ozone/platform/wayland/host/wayland_window_manager.h"
#include "ui/ozone/platform/wayland/host/wayland_window_observer.h"
+#include "ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.h"
struct wl_display;
namespace gfx {
-class Vector2d;
+class Vector2dF;
}
namespace ui {
@@ -47,9 +47,12 @@ class WaylandEventSource : public PlatformEventSource,
public WaylandWindowObserver,
public WaylandKeyboard::Delegate,
public WaylandPointer::Delegate,
- public WaylandTouch::Delegate {
+ public WaylandTouch::Delegate,
+ public WaylandZwpPointerGestures::Delegate {
public:
- WaylandEventSource(wl_display* display, WaylandWindowManager* window_manager);
+ WaylandEventSource(wl_display* display,
+ wl_event_queue* event_queue,
+ WaylandWindowManager* window_manager);
WaylandEventSource(const WaylandEventSource&) = delete;
WaylandEventSource& operator=(const WaylandEventSource&) = delete;
~WaylandEventSource() override;
@@ -67,9 +70,9 @@ class WaylandEventSource : public PlatformEventSource,
// Starts polling for events from the wayland connection file descriptor.
// This method assumes connection is already estabilished and input objects
// are already bound and properly initialized.
- bool StartProcessingEvents();
+ void StartProcessingEvents();
// Stops polling for events from input devices.
- bool StopProcessingEvents();
+ void StopProcessingEvents();
// Tells if pointer |button| is currently pressed.
bool IsPointerButtonPressed(EventFlags button) const;
@@ -79,6 +82,9 @@ class WaylandEventSource : public PlatformEventSource,
// button released event is not delivered (e.g: window moving, drag and drop).
void ResetPointerFlags();
+ // See the comment near WaylandEventWatcher::use_dedicated_polling_thread_.
+ void UseSingleThreadedPollingForTesting();
+
protected:
// WaylandKeyboard::Delegate
void OnKeyboardFocusChanged(WaylandWindow* window, bool focused) override;
@@ -97,11 +103,12 @@ class WaylandEventSource : public PlatformEventSource,
int changed_button,
WaylandWindow* window = nullptr) override;
void OnPointerMotionEvent(const gfx::PointF& location) override;
- void OnPointerAxisEvent(const gfx::Vector2d& offset) override;
+ void OnPointerAxisEvent(const gfx::Vector2dF& offset) override;
void OnPointerFrameEvent() override;
void OnPointerAxisSourceEvent(uint32_t axis_source) override;
void OnPointerAxisStopEvent(uint32_t axis) override;
void OnResetPointerFlags() override;
+ const gfx::PointF& GetPointerLocation() const override;
// WaylandTouch::Delegate
void OnTouchPressEvent(WaylandWindow* window,
@@ -114,14 +121,30 @@ class WaylandEventSource : public PlatformEventSource,
PointerId id) override;
void OnTouchCancelEvent() override;
+ // WaylandZwpPointerGesture::Delegate:
+ void OnPinchEvent(EventType event_type,
+ const gfx::Vector2dF& delta,
+ base::TimeTicks timestamp,
+ int device_id,
+ absl::optional<float> scale) override;
+
private:
struct PointerFrame {
- uint32_t axis_source = WL_POINTER_AXIS_SOURCE_WHEEL;
+ PointerFrame();
+ PointerFrame(const PointerFrame& other);
+ PointerFrame(PointerFrame&&);
+ ~PointerFrame();
+
+ PointerFrame& operator=(const PointerFrame&);
+ PointerFrame& operator=(PointerFrame&&);
+
+ absl::optional<uint32_t> axis_source;
float dx = 0.0f;
float dy = 0.0f;
base::TimeDelta dt;
bool is_axis_stop = false;
};
+
struct TouchPoint;
// PlatformEventSource:
@@ -135,7 +158,7 @@ class WaylandEventSource : public PlatformEventSource,
void HandlePointerFocusChange(WaylandWindow* window);
void HandleTouchFocusChange(WaylandWindow* window,
bool focused,
- base::Optional<PointerId> id = base::nullopt);
+ absl::optional<PointerId> id = absl::nullopt);
bool ShouldUnsetTouchFocus(WaylandWindow* window, PointerId id);
// Computes initial velocity of fling scroll based on recent frames.
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_event_source_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_event_source_unittest.cc
index fe57fe1421e..b2606b59502 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_event_source_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_event_source_unittest.cc
@@ -13,6 +13,7 @@
#include "ui/ozone/test/mock_platform_window_delegate.h"
using ::testing::_;
+using ::testing::Values;
namespace ui {
@@ -110,9 +111,11 @@ TEST_P(WaylandEventSourceTest, CheckPointerButtonHandling) {
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandEventSourceTest,
- ::testing::Values(kXdgShellStable));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
WaylandEventSourceTest,
- ::testing::Values(kXdgShellV6));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kV6}));
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher.cc b/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher.cc
index c97a0e31bd3..b51c8670dd8 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher.cc
@@ -5,54 +5,118 @@
#include "ui/ozone/platform/wayland/host/wayland_event_watcher.h"
#include <cstring>
+#include <memory>
#include "base/bind.h"
+#include "base/callback_forward.h"
#include "base/check.h"
#include "base/logging.h"
+#include "base/macros.h"
#include "base/task/current_thread.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "ui/events/event.h"
#include "ui/ozone/platform/wayland/common/wayland.h"
namespace ui {
-WaylandEventWatcher::WaylandEventWatcher(wl_display* display)
- : controller_(FROM_HERE), display_(display) {
- DCHECK(display_);
+namespace {
+
+void DispatchPending(wl_display* display, wl_event_queue* event_queue) {
+ wl_display_dispatch_queue_pending(display, event_queue);
}
-WaylandEventWatcher::~WaylandEventWatcher() {
- StopProcessingEvents();
+} // namespace
+
+// A dedicated thread for watching wl_display's file descriptor. The reason why
+// watching happens on a separate thread is that the thread mustn't be blocked.
+// Otherwise, if Chromium is used with Wayland EGL, a deadlock may happen. The
+// deadlock happened when the thread that had been watching the file descriptor
+// (it used to be the browser's UI thread) called wl_display_prepare_read, and
+// then started to wait until the thread, which was used by the gpu service,
+// completed a buffer swap and shutdowned itself (for example, a menu window is
+// in the process of closing). However, that gpu thread hanged as it called
+// Wayland EGL that also called wl_display_prepare_read internally and started
+// to wait until the previous caller of the wl_display_prepare_read (that's by
+// the design of the wayland-client library). This situation causes a deadlock
+// as the first caller of the wl_display_prepare_read is unable to complete
+// reading as it waits for another thread to complete, and that another thread
+// is also unable to complete reading as it waits until the first caller reads
+// the display's file descriptor. For more details, see the implementation of
+// the wl_display_prepare_read in third_party/wayland/src/src/wayland-client.c.
+class WaylandEventWatcherThread : public base::Thread {
+ public:
+ explicit WaylandEventWatcherThread(
+ base::OnceClosure start_processing_events_cb)
+ : base::Thread("wayland-fd"),
+ start_processing_events_cb_(std::move(start_processing_events_cb)) {}
+ ~WaylandEventWatcherThread() override { Stop(); }
+
+ void Init() override {
+ DCHECK(!start_processing_events_cb_.is_null());
+ std::move(start_processing_events_cb_).Run();
+ }
+
+ private:
+ base::OnceClosure start_processing_events_cb_;
+};
+
+WaylandEventWatcher::WaylandEventWatcher(wl_display* display,
+ wl_event_queue* event_queue)
+ : controller_(FROM_HERE), display_(display), event_queue_(event_queue) {
+ DCHECK(display_);
}
+WaylandEventWatcher::~WaylandEventWatcher() = default;
+
void WaylandEventWatcher::SetShutdownCb(
base::OnceCallback<void()> shutdown_cb) {
DCHECK(shutdown_cb_.is_null());
shutdown_cb_ = std::move(shutdown_cb);
}
-bool WaylandEventWatcher::StartProcessingEvents() {
- DCHECK(display_);
- if (watching_)
- return true;
+void WaylandEventWatcher::StartProcessingEvents() {
+ ui_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
+ if (use_dedicated_polling_thread_ && !thread_) {
+ // FD watching will happen on a different thread.
+ DETACH_FROM_THREAD(thread_checker_);
- DCHECK(display_);
- MaybePrepareReadQueue();
- wl_display_flush(display_);
- return StartWatchingFd(base::MessagePumpForUI::WATCH_READ);
+ thread_ = std::make_unique<WaylandEventWatcherThread>(
+ base::BindOnce(&WaylandEventWatcher::StartProcessingEventsInternal,
+ weak_factory_.GetWeakPtr()));
+ base::Thread::Options thread_options;
+ thread_options.message_pump_type = base::MessagePumpType::UI;
+ thread_options.priority = base::ThreadPriority::DISPLAY;
+ if (!thread_->StartWithOptions(std::move(thread_options)))
+ LOG(FATAL) << "Failed to create input thread";
+
+ } else if (!use_dedicated_polling_thread_) {
+ StartProcessingEventsInternal();
+ }
}
-bool WaylandEventWatcher::StopProcessingEvents() {
+void WaylandEventWatcher::StopProcessingEvents() {
if (!watching_)
- return false;
+ return;
- DCHECK(base::CurrentUIThread::IsSet());
- watching_ = false;
- return controller_.StopWatchingFileDescriptor();
+ if (use_dedicated_polling_thread_) {
+ watching_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WaylandEventWatcher::StopProcessingEventsInternal,
+ weak_factory_.GetWeakPtr()));
+ } else {
+ StopProcessingEventsInternal();
+ }
+}
+
+void WaylandEventWatcher::UseSingleThreadedPollingForTesting() {
+ use_dedicated_polling_thread_ = false;
}
void WaylandEventWatcher::OnFileCanReadWithoutBlocking(int fd) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!CheckForErrors()) {
- StopProcessingEvents();
+ StopProcessingEventsInternal();
return;
}
@@ -62,7 +126,7 @@ void WaylandEventWatcher::OnFileCanReadWithoutBlocking(int fd) {
// CheckForErrors.
if (wl_display_read_events(display_) == -1)
return;
- wl_display_dispatch_pending(display_);
+ DispatchPendingQueue();
}
MaybePrepareReadQueue();
@@ -82,6 +146,7 @@ void WaylandEventWatcher::OnFileCanReadWithoutBlocking(int fd) {
}
void WaylandEventWatcher::OnFileCanWriteWithoutBlocking(int fd) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
int ret = wl_display_flush(display_);
if (ret != -1 || errno != EAGAIN)
StartWatchingFd(base::MessagePumpForUI::WATCH_READ);
@@ -91,8 +156,33 @@ void WaylandEventWatcher::OnFileCanWriteWithoutBlocking(int fd) {
// Otherwise just continue watching in the same mode.
}
-bool WaylandEventWatcher::StartWatchingFd(
+void WaylandEventWatcher::StartProcessingEventsInternal() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(display_);
+ if (watching_)
+ return;
+
+ watching_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
+
+ DCHECK(display_);
+ MaybePrepareReadQueue();
+ wl_display_flush(display_);
+ StartWatchingFd(base::MessagePumpForUI::WATCH_READ);
+}
+
+void WaylandEventWatcher::StopProcessingEventsInternal() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (!watching_)
+ return;
+
+ DCHECK(base::CurrentUIThread::IsSet());
+ watching_ = !controller_.StopWatchingFileDescriptor();
+ DCHECK(!watching_);
+}
+
+void WaylandEventWatcher::StartWatchingFd(
base::WatchableIOMessagePumpPosix::Mode mode) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (watching_) {
// Stop watching first.
watching_ = !controller_.StopWatchingFileDescriptor();
@@ -103,22 +193,36 @@ bool WaylandEventWatcher::StartWatchingFd(
int display_fd = wl_display_get_fd(display_);
watching_ = base::CurrentUIThread::Get()->WatchFileDescriptor(
display_fd, true, mode, &controller_, this);
- return watching_;
+ CHECK(watching_) << "Unable to start watching the wl_display's file "
+ "descriptor.";
}
void WaylandEventWatcher::MaybePrepareReadQueue() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (prepared_)
return;
- if (wl_display_prepare_read(display_) != -1) {
+ if (wl_display_prepare_read_queue(display_, event_queue_) != -1) {
prepared_ = true;
return;
}
// Nothing to read, send events to the queue.
- wl_display_dispatch_pending(display_);
+ DispatchPendingQueue();
+}
+
+void WaylandEventWatcher::DispatchPendingQueue() {
+ if (ui_thread_task_runner_->BelongsToCurrentThread()) {
+ DCHECK(!use_dedicated_polling_thread_);
+ DispatchPending(display_, event_queue_);
+ } else {
+ DCHECK(use_dedicated_polling_thread_);
+ auto cb = base::BindOnce(&DispatchPending, display_, event_queue_);
+ ui_thread_task_runner_->PostTask(FROM_HERE, std::move(cb));
+ }
}
bool WaylandEventWatcher::CheckForErrors() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Errors are fatal. If this function returns non-zero the display can no
// longer be used.
int err = wl_display_get_error(display_);
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher.h b/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher.h
index 6a13ea92f4b..ee4749e3a13 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher.h
@@ -6,10 +6,18 @@
#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_EVENT_WATCHER_H_
#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_pump_for_ui.h"
#include "base/message_loop/watchable_io_message_pump_posix.h"
+#include "base/threading/thread_checker.h"
struct wl_display;
+struct wl_event_queue;
+
+namespace base {
+class Thread;
+class SingleThreadTaskRunner;
+} // namespace base
namespace ui {
@@ -19,7 +27,7 @@ namespace ui {
// into WaylandEventSource, so feeding the platform events pipeline.
class WaylandEventWatcher : public base::MessagePumpForUI::FdWatcher {
public:
- explicit WaylandEventWatcher(wl_display* display);
+ WaylandEventWatcher(wl_display* display, wl_event_queue* event_queue);
WaylandEventWatcher(const WaylandEventWatcher&) = delete;
WaylandEventWatcher& operator=(const WaylandEventWatcher&) = delete;
~WaylandEventWatcher() override;
@@ -31,18 +39,24 @@ class WaylandEventWatcher : public base::MessagePumpForUI::FdWatcher {
// Starts polling for events from the wayland connection file descriptor.
// This method assumes connection is already estabilished and input objects
// are already bound and properly initialized.
- bool StartProcessingEvents();
+ void StartProcessingEvents();
// Stops polling for events from input devices.
- bool StopProcessingEvents();
+ void StopProcessingEvents();
+
+ // See the comment near WaylandEventWatcher::use_dedicated_polling_thread_.
+ void UseSingleThreadedPollingForTesting();
private:
// base::MessagePumpForUI::FdWatcher
void OnFileCanReadWithoutBlocking(int fd) override;
void OnFileCanWriteWithoutBlocking(int fd) override;
- bool StartWatchingFd(base::WatchableIOMessagePumpPosix::Mode mode);
+ void StartProcessingEventsInternal();
+ void StopProcessingEventsInternal();
+ void StartWatchingFd(base::WatchableIOMessagePumpPosix::Mode mode);
void MaybePrepareReadQueue();
+ void DispatchPendingQueue();
// Checks if |display_| has any error set. If so, |shutdown_cb_| is executed
// and false is returned.
@@ -51,11 +65,39 @@ class WaylandEventWatcher : public base::MessagePumpForUI::FdWatcher {
base::MessagePumpForUI::FdWatchController controller_;
wl_display* const display_; // Owned by WaylandConnection.
+ wl_event_queue* const event_queue_; // Owned by WaylandConnection.
bool watching_ = false;
bool prepared_ = false;
+ // A separate thread is not used in some tests (ozone_unittests), as it
+ // requires additional synchronization from the WaylandTest side. Otherwise,
+ // some tests complete without waiting until events come. That is, the tests
+ // suppose that our calls/requests are completed after calling Sync(), which
+ // resumes our fake Wayland server and sends out events, but as long as there
+ // is one additional "polling" thread involved, some additional
+ // synchronization mechanisms are needed. At this point, it's easier to
+ // continue to watch the file descriptor on the same thread where the
+ // ozone_unittests run.
+ bool use_dedicated_polling_thread_ = true;
+
base::OnceCallback<void()> shutdown_cb_;
+
+ // Used to verify watching the fd happens on a valid thread.
+ THREAD_CHECKER(thread_checker_);
+
+ // See the |use_dedicated_polling_thread_| and also the comment in the source
+ // file for this header.
+ // TODO(crbug.com/1117463): consider polling on I/O instead.
+ std::unique_ptr<base::Thread> thread_;
+
+ // The original ui task runner where |this| has been created.
+ scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_;
+
+ // The thread's task runner where the wl_display's fd is being watched.
+ scoped_refptr<base::SingleThreadTaskRunner> watching_thread_task_runner_;
+
+ base::WeakPtrFactory<WaylandEventWatcher> weak_factory_{this};
};
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.cc b/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.cc
index c6b5dca39b9..cca68fde637 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.cc
@@ -9,10 +9,10 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
-#include "base/optional.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/chromeos_buildflags.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/ime_text_span.h"
#include "ui/events/base_event_utils.h"
@@ -33,20 +33,20 @@
#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "base/check.h"
#include "chromeos/crosapi/mojom/crosapi.mojom.h"
-#include "chromeos/lacros/lacros_chrome_service_impl.h"
+#include "chromeos/lacros/lacros_service.h"
#endif
namespace ui {
namespace {
-base::Optional<size_t> OffsetFromUTF8Offset(const base::StringPiece& text,
+absl::optional<size_t> OffsetFromUTF8Offset(const base::StringPiece& text,
uint32_t offset) {
if (offset > text.length())
- return base::nullopt;
+ return absl::nullopt;
std::u16string converted;
if (!base::UTF8ToUTF16(text.data(), offset, &converted))
- return base::nullopt;
+ return absl::nullopt;
return converted.size();
}
@@ -69,13 +69,13 @@ bool IsImeEnabled() {
// Lacros-chrome side, which helps us on releasing.
// TODO(crbug.com/1159237): In the future, we may want to unify the behavior
// of ozone/wayland across platforms.
- const auto* lacros_chrome_service = chromeos::LacrosChromeServiceImpl::Get();
+ const auto* lacros_service = chromeos::LacrosService::Get();
// Note: |init_params| may be null, if ash-chrome is too old.
// TODO(crbug.com/1156033): Clean up the condition, after ash-chrome in the
// world becomes new enough.
const crosapi::mojom::BrowserInitParams* init_params =
- lacros_chrome_service->init_params();
+ lacros_service ? lacros_service->init_params() : nullptr;
if (init_params && init_params->exo_ime_support !=
crosapi::mojom::ExoImeSupport::kUnsupported) {
return true;
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
index ba1e5b0ef60..d73061c6f9b 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
@@ -20,6 +20,7 @@
using ::testing::_;
using ::testing::SaveArg;
+using ::testing::Values;
namespace ui {
@@ -136,9 +137,11 @@ TEST_P(WaylandInputMethodContextTest, OnCommit) {
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandInputMethodContextTest,
- ::testing::Values(kXdgShellStable));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
WaylandInputMethodContextTest,
- ::testing::Values(kXdgShellV6));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kV6}));
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_keyboard.cc b/chromium/ui/ozone/platform/wayland/host/wayland_keyboard.cc
index 85fcd6a423b..94fdc79a25a 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_keyboard.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_keyboard.cc
@@ -207,7 +207,7 @@ void WaylandKeyboard::FlushInput(base::OnceClosure closure) {
// wl_display_sync gives a chance for any key "up" events to arrive.
// With a well behaved wayland compositor this should ensure we never
// get spurious repeats.
- sync_callback_.reset(wl_display_sync(connection_->display()));
+ sync_callback_.reset(wl_display_sync(connection_->display_wrapper()));
wl_callback_add_listener(sync_callback_.get(), &callback_listener_, this);
connection_->ScheduleFlush();
}
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_keyboard_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_keyboard_unittest.cc
index 91c1d3bec7a..fe209dd8594 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_keyboard_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_keyboard_unittest.cc
@@ -27,6 +27,7 @@
using ::testing::_;
using ::testing::SaveArg;
+using ::testing::Values;
namespace ui {
@@ -486,9 +487,11 @@ TEST_P(WaylandKeyboardTest, NoEventAutoRepeatBeforeTimeout) {
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandKeyboardTest,
- ::testing::Values(kXdgShellStable));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
WaylandKeyboardTest,
- ::testing::Values(kXdgShellV6));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kV6}));
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_output.h b/chromium/ui/ozone/platform/wayland/host/wayland_output.h
index 0bf51f670aa..ba5081da560 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_output.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_output.h
@@ -85,4 +85,4 @@ class WaylandOutput {
} // namespace ui
-#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_SCREEN_H_
+#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_OUTPUT_H_
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_pointer.cc b/chromium/ui/ozone/platform/wayland/host/wayland_pointer.cc
index 50d55f66b5c..8073a3255f7 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_pointer.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_pointer.cc
@@ -47,6 +47,8 @@ void WaylandPointer::Enter(void* data,
wl_fixed_t surface_y) {
DCHECK(data);
WaylandPointer* pointer = static_cast<WaylandPointer*>(data);
+ pointer->connection_->set_pointer_enter_serial(serial);
+
WaylandWindow* window = wl::RootWindowFromWlSurface(surface);
gfx::PointF location{wl_fixed_to_double(surface_x),
wl_fixed_to_double(surface_y)};
@@ -60,7 +62,8 @@ void WaylandPointer::Leave(void* data,
wl_surface* surface) {
DCHECK(data);
WaylandPointer* pointer = static_cast<WaylandPointer*>(data);
- pointer->delegate_->OnPointerFocusChanged(nullptr, {});
+ pointer->delegate_->OnPointerFocusChanged(
+ nullptr, pointer->delegate_->GetPointerLocation());
}
// static
@@ -121,7 +124,7 @@ void WaylandPointer::Axis(void* data,
wl_fixed_t value) {
static const double kAxisValueScale = 10.0;
WaylandPointer* pointer = static_cast<WaylandPointer*>(data);
- gfx::Vector2d offset;
+ gfx::Vector2dF offset;
// Wayland compositors send axis events with values in the surface coordinate
// space. They send a value of 10 per mouse wheel click by convention, so
// clients (e.g. GTK+) typically scale down by this amount to convert to
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_pointer.h b/chromium/ui/ozone/platform/wayland/host/wayland_pointer.h
index 70de3afd35a..cafec7123a7 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_pointer.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_pointer.h
@@ -13,7 +13,7 @@
namespace gfx {
class PointF;
-class Vector2d;
+class Vector2dF;
} // namespace gfx
namespace ui {
@@ -89,11 +89,12 @@ class WaylandPointer::Delegate {
int changed_button,
WaylandWindow* window = nullptr) = 0;
virtual void OnPointerMotionEvent(const gfx::PointF& location) = 0;
- virtual void OnPointerAxisEvent(const gfx::Vector2d& offset) = 0;
+ virtual void OnPointerAxisEvent(const gfx::Vector2dF& offset) = 0;
virtual void OnPointerFrameEvent() = 0;
virtual void OnPointerAxisSourceEvent(uint32_t axis_source) = 0;
virtual void OnPointerAxisStopEvent(uint32_t axis) = 0;
virtual void OnResetPointerFlags() = 0;
+ virtual const gfx::PointF& GetPointerLocation() const = 0;
};
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_pointer_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_pointer_unittest.cc
index 1334e8b8bae..ce0ef4b466b 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_pointer_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_pointer_unittest.cc
@@ -8,10 +8,12 @@
#include <cmath>
#include <memory>
+#include "base/memory/scoped_refptr.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/events/devices/device_data_manager.h"
#include "ui/events/event.h"
#include "ui/ozone/platform/wayland/host/wayland_cursor.h"
@@ -27,6 +29,7 @@ using ::testing::_;
using ::testing::Mock;
using ::testing::Ne;
using ::testing::SaveArg;
+using ::testing::Values;
namespace ui {
@@ -205,8 +208,11 @@ TEST_P(WaylandPointerTest, AxisVertical) {
std::unique_ptr<Event> event;
EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event));
// Wayland servers typically send a value of 10 per mouse wheel click.
+ wl_pointer_send_axis_source(pointer_->resource(),
+ WL_POINTER_AXIS_SOURCE_WHEEL);
wl_pointer_send_axis(pointer_->resource(), 1003,
WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_int(20));
+ wl_pointer_send_frame(pointer_->resource());
Sync();
@@ -232,9 +238,12 @@ TEST_P(WaylandPointerTest, AxisHorizontal) {
std::unique_ptr<Event> event;
EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event));
// Wayland servers typically send a value of 10 per mouse wheel click.
+ wl_pointer_send_axis_source(pointer_->resource(),
+ WL_POINTER_AXIS_SOURCE_WHEEL);
wl_pointer_send_axis(pointer_->resource(), 1003,
WL_POINTER_AXIS_HORIZONTAL_SCROLL,
wl_fixed_from_int(10));
+ wl_pointer_send_frame(pointer_->resource());
Sync();
@@ -275,10 +284,8 @@ TEST_P(WaylandPointerTest, SetBitmapOnPointerFocus) {
dummy_cursor.allocPixels(info, 10 * 4);
BitmapCursorFactoryOzone cursor_factory;
- PlatformCursor cursor = cursor_factory.CreateImageCursor(
+ auto cursor = cursor_factory.CreateImageCursor(
mojom::CursorType::kCustom, dummy_cursor, gfx::Point(5, 8));
- scoped_refptr<BitmapCursorOzone> bitmap =
- BitmapCursorFactoryOzone::GetBitmapCursor(cursor);
EXPECT_CALL(*pointer_, SetCursor(Ne(nullptr), 5, 8));
window_->SetCursor(cursor);
@@ -301,6 +308,7 @@ TEST_P(WaylandPointerTest, SetBitmapOnPointerFocus) {
Mock::VerifyAndClearExpectations(pointer_);
}
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
TEST_P(WaylandPointerTest, FlingVertical) {
uint32_t serial = 0;
uint32_t time = 1001;
@@ -336,9 +344,9 @@ TEST_P(WaylandPointerTest, FlingVertical) {
// Usual axis events should follow before the fling event.
ASSERT_TRUE(event1);
- ASSERT_TRUE(event1->IsMouseWheelEvent());
+ ASSERT_TRUE(event1->IsScrollEvent());
ASSERT_TRUE(event2);
- ASSERT_TRUE(event2->IsMouseWheelEvent());
+ ASSERT_TRUE(event2->IsScrollEvent());
// The third dispatched event should be FLING_START.
ASSERT_TRUE(event3);
@@ -390,9 +398,9 @@ TEST_P(WaylandPointerTest, FlingHorizontal) {
// Usual axis events should follow before the fling event.
ASSERT_TRUE(event1);
- ASSERT_TRUE(event1->IsMouseWheelEvent());
+ ASSERT_TRUE(event1->IsScrollEvent());
ASSERT_TRUE(event2);
- ASSERT_TRUE(event2->IsMouseWheelEvent());
+ ASSERT_TRUE(event2->IsScrollEvent());
// The third dispatched event should be FLING_START.
ASSERT_TRUE(event3);
@@ -452,15 +460,16 @@ TEST_P(WaylandPointerTest, FlingCancel) {
// Usual axis events should follow before the fling event.
ASSERT_TRUE(event1);
- ASSERT_TRUE(event1->IsMouseWheelEvent());
+ ASSERT_TRUE(event1->IsScrollEvent());
ASSERT_TRUE(event2);
- ASSERT_TRUE(event2->IsMouseWheelEvent());
+ ASSERT_TRUE(event2->IsScrollEvent());
// The 3rd axis event's offset is 0.
ASSERT_TRUE(event3);
- ASSERT_TRUE(event3->IsMouseWheelEvent());
- auto* mouse_wheel_event = event3->AsMouseWheelEvent();
- EXPECT_EQ(gfx::Vector2d(0, 0), mouse_wheel_event->offset());
+ ASSERT_TRUE(event3->IsScrollEvent());
+ auto* scroll_event0 = event3->AsScrollEvent();
+ EXPECT_EQ(gfx::Vector2dF(0., 0.), gfx::Vector2dF(scroll_event0->x_offset(),
+ scroll_event0->y_offset()));
// The 4th event should be FLING_CANCEL.
ASSERT_TRUE(event4);
@@ -484,14 +493,12 @@ TEST_P(WaylandPointerTest, FlingDiagonal) {
Sync();
- std::unique_ptr<Event> event1, event2, event3, event4, event5;
+ std::unique_ptr<Event> event1, event2, event3;
EXPECT_CALL(delegate_, DispatchEvent(_))
- .Times(5)
+ .Times(3)
.WillOnce(CloneEvent(&event1))
.WillOnce(CloneEvent(&event2))
- .WillOnce(CloneEvent(&event3))
- .WillOnce(CloneEvent(&event4))
- .WillOnce(CloneEvent(&event5));
+ .WillOnce(CloneEvent(&event3));
// 1st axis event notifies scrolls both in vertical and horizontal.
SendDiagonalAxisEvents(pointer_->resource(), ++time,
WL_POINTER_AXIS_SOURCE_FINGER, 20, 10);
@@ -511,18 +518,14 @@ TEST_P(WaylandPointerTest, FlingDiagonal) {
// Usual axis events should follow before the fling event.
ASSERT_TRUE(event1);
- ASSERT_TRUE(event1->IsMouseWheelEvent());
+ ASSERT_TRUE(event1->IsScrollEvent());
ASSERT_TRUE(event2);
- ASSERT_TRUE(event2->IsMouseWheelEvent());
- ASSERT_TRUE(event3);
- ASSERT_TRUE(event3->IsMouseWheelEvent());
- ASSERT_TRUE(event4);
- ASSERT_TRUE(event4->IsMouseWheelEvent());
+ ASSERT_TRUE(event2->IsScrollEvent());
// The third dispatched event should be FLING_START.
- ASSERT_TRUE(event5);
- ASSERT_TRUE(event5->IsScrollEvent());
- auto* scroll_event = event5->AsScrollEvent();
+ ASSERT_TRUE(event3);
+ ASSERT_TRUE(event3->IsScrollEvent());
+ auto* scroll_event = event3->AsScrollEvent();
EXPECT_EQ(ET_SCROLL_FLING_START, scroll_event->type());
EXPECT_EQ(gfx::PointF(50, 75), scroll_event->location_f());
// Check the offset direction. It should non-zero in both axes.
@@ -537,12 +540,15 @@ TEST_P(WaylandPointerTest, FlingDiagonal) {
EXPECT_GT(std::abs(scroll_event->x_offset_ordinal()),
std::abs(scroll_event->y_offset_ordinal()));
}
+#endif
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandPointerTest,
- ::testing::Values(kXdgShellStable));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
WaylandPointerTest,
- ::testing::Values(kXdgShellV6));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kV6}));
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_popup.cc b/chromium/ui/ozone/platform/wayland/host/wayland_popup.cc
index 22d8d81383c..4c26b059bdb 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_popup.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_popup.cc
@@ -6,11 +6,15 @@
#include <aura-shell-client-protocol.h>
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/transform.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/platform/wayland/host/shell_object_factory.h"
#include "ui/ozone/platform/wayland/host/shell_popup_wrapper.h"
#include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
+#include "ui/ozone/platform/wayland/host/wayland_output.h"
+#include "ui/ozone/platform/wayland/host/wayland_output_manager.h"
#include "ui/ozone/platform/wayland/host/wayland_zaura_shell.h"
namespace ui {
@@ -27,12 +31,22 @@ WaylandPopup::~WaylandPopup() = default;
bool WaylandPopup::CreateShellPopup() {
DCHECK(parent_window() && !shell_popup_);
- auto subsurface_bounds_dip =
+ // Set pending initial bounds and notify the delegate.
+ if (!pending_initial_bounds_px_.IsEmpty()) {
+ SetBounds(pending_initial_bounds_px_);
+ pending_initial_bounds_px_ = gfx::Rect();
+ } else if (buffer_scale() != parent_window()->buffer_scale()) {
+ // If scale changed while this was hidden (when WaylandPopup hides, parent
+ // window's child is reset), update buffer scale accordingly.
+ UpdateBufferScale(true);
+ }
+
+ const auto bounds_dip =
wl::TranslateWindowBoundsToParentDIP(this, parent_window());
ShellObjectFactory factory;
- shell_popup_ = factory.CreateShellPopupWrapper(connection(), this,
- subsurface_bounds_dip);
+ shell_popup_ =
+ factory.CreateShellPopupWrapper(connection(), this, bounds_dip);
if (!shell_popup_) {
LOG(ERROR) << "Failed to create Wayland shell popup";
return false;
@@ -70,7 +84,6 @@ void WaylandPopup::Show(bool inactive) {
return;
}
- UpdateBufferScale(false);
connection()->ScheduleFlush();
WaylandWindow::Show(inactive);
}
@@ -101,8 +114,6 @@ void WaylandPopup::HandlePopupConfigure(const gfx::Rect& bounds_dip) {
DCHECK(shell_popup());
DCHECK(parent_window());
- root_surface()->SetBufferScale(parent_window()->buffer_scale(), true);
-
gfx::Rect new_bounds_dip = bounds_dip;
// It's not enough to just set new bounds. If it is a menu window, whose
@@ -117,7 +128,7 @@ void WaylandPopup::HandlePopupConfigure(const gfx::Rect& bounds_dip) {
// is above the top level parent window, the origin of the top level window
// has to be shifted by that value on y-axis so that the origin of the menu
// becomes x,0, and events can be handled normally.
- if (!wl::IsMenuType(parent_window()->type())) {
+ if (!parent_window()->AsWaylandPopup()) {
gfx::Rect parent_bounds = parent_window()->GetBounds();
// The menu window is flipped along y-axis and have x,-y origin. Shift the
// parent top level window instead.
@@ -159,12 +170,50 @@ void WaylandPopup::OnCloseRequest() {
}
bool WaylandPopup::OnInitialize(PlatformWindowInitProperties properties) {
- DCHECK(wl::IsMenuType(type()));
DCHECK(parent_window());
root_surface()->SetBufferScale(parent_window()->buffer_scale(), false);
set_ui_scale(parent_window()->ui_scale());
shadow_type_ = properties.shadow_type;
+
+ // Fix initial bounds. The client initially doesn't know the display where the
+ // WaylandPopup will be located and uses a primary display to convert dip
+ // bounds to pixels. However, Ozone/Wayland does know where it is going to
+ // locate WaylandPopup as it is going to use parent's entered outputs. Thus,
+ // if the primary display's scale is different from parents' scale (and this'
+ // scale), fix bounds accordingly. Otherwise, popup is located using wrong
+ // bounds in DIP.
+ if (auto* primary_output =
+ connection()->wayland_output_manager()->GetPrimaryOutput()) {
+ const auto primary_display_scale_factor = primary_output->scale_factor();
+
+ gfx::RectF float_rect = gfx::RectF(GetBounds());
+ gfx::Transform transform;
+ float scale = primary_display_scale_factor;
+ // The bounds are initially given in the scale of the primary display, so we
+ // have to upscale or downscale the rect to the scale of the target display,
+ // if that scale is different.
+ if (primary_display_scale_factor < buffer_scale()) {
+ scale = static_cast<float>(buffer_scale()) /
+ static_cast<float>(primary_display_scale_factor);
+ transform.Scale(scale, scale);
+ transform.TransformRect(&float_rect);
+ } else if (primary_display_scale_factor > buffer_scale()) {
+ scale = static_cast<float>(primary_display_scale_factor) /
+ static_cast<float>(buffer_scale());
+ transform.Scale(scale, scale);
+ transform.TransformRectReverse(&float_rect);
+ }
+
+ // delegate()->OnBoundsChanged cannot be called at this point. Thus, set
+ // pending internal bounds and call SetBounds later when CreateShellPopup is
+ // called.
+ pending_initial_bounds_px_ = gfx::ToEnclosingRect(float_rect);
+ }
return true;
}
+WaylandPopup* WaylandPopup::AsWaylandPopup() {
+ return this;
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_popup.h b/chromium/ui/ozone/platform/wayland/host/wayland_popup.h
index efe07048d9b..76e566b7af4 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_popup.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_popup.h
@@ -32,6 +32,7 @@ class WaylandPopup : public WaylandWindow {
void HandleSurfaceConfigure(uint32_t serial) override;
void OnCloseRequest() override;
bool OnInitialize(PlatformWindowInitProperties properties) override;
+ WaylandPopup* AsWaylandPopup() override;
// Creates a popup window, which is visible as a menu window.
bool CreateShellPopup();
@@ -51,6 +52,8 @@ class WaylandPopup : public WaylandWindow {
PlatformWindowShadowType shadow_type_ = PlatformWindowShadowType::kNone;
+ gfx::Rect pending_initial_bounds_px_;
+
DISALLOW_COPY_AND_ASSIGN(WaylandPopup);
};
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_screen.h b/chromium/ui/ozone/platform/wayland/host/wayland_screen.h
index 3a9dfa7d132..fb9a8765732 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_screen.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_screen.h
@@ -10,7 +10,7 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/display/display_list.h"
#include "ui/display/display_observer.h"
#include "ui/display/tablet_state.h"
@@ -74,8 +74,8 @@ class WaylandScreen : public PlatformScreen {
base::ObserverList<display::DisplayObserver> observers_;
- base::Optional<gfx::BufferFormat> image_format_alpha_;
- base::Optional<gfx::BufferFormat> image_format_no_alpha_;
+ absl::optional<gfx::BufferFormat> image_format_alpha_;
+ absl::optional<gfx::BufferFormat> image_format_no_alpha_;
base::WeakPtrFactory<WaylandScreen> weak_factory_;
};
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc
index 300b6a7985c..f5a17405280 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc
@@ -23,6 +23,8 @@
#include "ui/ozone/platform/wayland/test/wayland_test.h"
#include "ui/platform_window/platform_window_init_properties.h"
+using ::testing::Values;
+
namespace ui {
namespace {
@@ -737,15 +739,19 @@ TEST_P(LazilyConfiguredScreenTest, DualOutput) {
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandScreenTest,
- ::testing::Values(kXdgShellStable));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
WaylandScreenTest,
- ::testing::Values(kXdgShellV6));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kV6}));
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
LazilyConfiguredScreenTest,
- ::testing::Values(kXdgShellStable));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
LazilyConfiguredScreenTest,
- ::testing::Values(kXdgShellV6));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kV6}));
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_shm.h b/chromium/ui/ozone/platform/wayland/host/wayland_shm.h
index 0b484ed6e87..1eafd53facd 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_shm.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_shm.h
@@ -5,7 +5,6 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_SHM_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_SHM_H_
-#include <memory>
#include "base/files/scoped_file.h"
#include "base/macros.h"
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_shm_buffer.h b/chromium/ui/ozone/platform/wayland/host/wayland_shm_buffer.h
index 1a1a958b093..465183b1f61 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_shm_buffer.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_shm_buffer.h
@@ -5,7 +5,6 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_SHM_BUFFER_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_SHM_BUFFER_H_
-#include <memory>
#include "base/macros.h"
#include "base/memory/shared_memory_mapping.h"
@@ -61,4 +60,4 @@ class WaylandShmBuffer {
} // namespace ui
-#endif // UI_OZONE_PLATFORM_WAYLAND_COMMON_WAYLAND_SHM_BUFFER_H_
+#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_SHM_BUFFER_H_
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_surface.cc b/chromium/ui/ozone/platform/wayland/host/wayland_surface.cc
index 69c7ba3443c..648615f03d4 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_surface.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_surface.cc
@@ -232,9 +232,12 @@ wl::Object<wl_region> WaylandSurface::CreateAndAddRegion(
// Only root_surface and primary_subsurface should use |window_shape_in_dips|.
// Do not use non empty |window_shape_in_dips| if |region_px| is empty, i.e.
// this surface is transluscent.
+ bool is_primary_or_root =
+ root_window_->root_surface() == this ||
+ (root_window()->primary_subsurface() &&
+ root_window()->primary_subsurface()->wayland_surface() == this);
if (window_shape_in_dips.has_value() && !region_px.IsEmpty() &&
- root_window_->root_surface() != this &&
- root_window()->primary_subsurface()->wayland_surface() != this) {
+ is_primary_or_root) {
for (const auto& rect : window_shape_in_dips.value())
wl_region_add(region.get(), rect.x(), rect.y(), rect.width(),
rect.height());
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc b/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc
index cd657d763df..9df1113de72 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc
@@ -12,6 +12,8 @@
#include "third_party/skia/include/core/SkPath.h"
#include "ui/base/hit_test.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/ozone/platform/wayland/host/gtk_shell1.h"
+#include "ui/ozone/platform/wayland/host/gtk_surface1.h"
#include "ui/ozone/platform/wayland/host/shell_object_factory.h"
#include "ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h"
#include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h"
@@ -23,9 +25,7 @@
#include "ui/platform_window/extensions/wayland_extension.h"
#if BUILDFLAG(IS_CHROMEOS_LACROS)
-// TODO(jamescook): The nogncheck is to work around false-positive failures on
-// the code search bot. Remove after https://crrev.com/c/2432137 lands.
-#include "chromeos/crosapi/cpp/crosapi_constants.h" // nogncheck
+#include "chromeos/crosapi/cpp/crosapi_constants.h"
#endif
namespace ui {
@@ -57,7 +57,7 @@ bool WaylandToplevelWindow::CreateShellToplevel() {
shell_toplevel_->SetTitle(window_title_);
SetSizeConstraints();
TriggerStateChanges();
- InitializeAuraShellSurface();
+ SetUpShellIntegration();
OnDecorationModeChanged();
// This could be the proper time to update window mask using
// NonClientView::GetWindowMask, since |non_client_view| is not created yet
@@ -190,11 +190,20 @@ PlatformWindowState WaylandToplevelWindow::GetPlatformWindowState() const {
}
void WaylandToplevelWindow::Activate() {
- // Only supported by compositors that support zaura_shell (e.g. exo).
- // TODO(https://crbug.com/1175327): Use standard Wayland extensions, such as
- // xdg-activation, when those are available.
- if (aura_surface_)
+ // Activation is supported through optional protocol extensions and hence may
+ // or may not work depending on the compositor. The details depend on the
+ // compositor as well; for example, Mutter doesn't bring the window to the top
+ // when it requests focus, but instead shows a system popup notification to
+ // user.
+ //
+ // Exo provides activation through aura-shell, Mutter--through gtk-shell.
+ //
+ // TODO(crbug.com/1175327): add support for xdg-activation.
+ if (aura_surface_ && zaura_surface_get_version(aura_surface_.get()) >=
+ ZAURA_SURFACE_ACTIVATE_SINCE_VERSION)
zaura_surface_activate(aura_surface_.get());
+ else if (gtk_surface1_)
+ gtk_surface1_->RequestFocus();
}
void WaylandToplevelWindow::SizeConstraintsChanged() {
@@ -209,7 +218,7 @@ std::string WaylandToplevelWindow::GetWindowUniqueId() const {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
return window_unique_id_;
#else
- return std::string();
+ return wm_class_class_;
#endif
}
@@ -232,11 +241,25 @@ bool WaylandToplevelWindow::ShouldUseNativeFrame() const {
->xdg_decoration_manager_v1();
}
-base::Optional<std::vector<gfx::Rect>> WaylandToplevelWindow::GetWindowShape()
+bool WaylandToplevelWindow::ShouldUpdateWindowShape() const {
+ return true;
+}
+
+absl::optional<std::vector<gfx::Rect>> WaylandToplevelWindow::GetWindowShape()
const {
return window_shape_in_dips_;
}
+void WaylandToplevelWindow::UpdateBufferScale(bool update_bounds) {
+ auto old_scale = buffer_scale();
+ WaylandWindow::UpdateBufferScale(update_bounds);
+ if (old_scale == buffer_scale())
+ return;
+
+ // Update min/max size in DIP if buffer scale is updated.
+ SizeConstraintsChanged();
+}
+
void WaylandToplevelWindow::HandleToplevelConfigure(int32_t width,
int32_t height,
bool is_maximized,
@@ -413,7 +436,8 @@ void WaylandToplevelWindow::StartWindowDraggingSessionIfNeeded() {
}
void WaylandToplevelWindow::SetImmersiveFullscreenStatus(bool status) {
- if (aura_surface_) {
+ if (aura_surface_ && zaura_surface_get_version(aura_surface_.get()) >=
+ ZAURA_SURFACE_SET_FULLSCREEN_MODE_SINCE_VERSION) {
auto mode = status ? ZAURA_SURFACE_FULLSCREEN_MODE_IMMERSIVE
: ZAURA_SURFACE_FULLSCREEN_MODE_PLAIN;
zaura_surface_set_fullscreen_mode(aura_surface_.get(), mode);
@@ -470,6 +494,16 @@ void WaylandToplevelWindow::CommitSnap(
<< "Window snapping isn't available for non-lacros builds.";
}
+void WaylandToplevelWindow::SetCanGoBack(bool value) {
+ if (aura_surface_ && zaura_surface_get_version(aura_surface_.get()) >=
+ ZAURA_SURFACE_SET_CAN_GO_BACK_SINCE_VERSION) {
+ if (value)
+ zaura_surface_set_can_go_back(aura_surface_.get());
+ else
+ zaura_surface_unset_can_go_back(aura_surface_.get());
+ }
+}
+
void WaylandToplevelWindow::TriggerStateChanges() {
if (!shell_toplevel_)
return;
@@ -545,9 +579,8 @@ void WaylandToplevelWindow::SetOrResetRestoredBounds() {
}
}
-void WaylandToplevelWindow::InitializeAuraShellSurface() {
- // InitializeAuraShellSurface() should be called after the XDG surface is
- // initialized.
+void WaylandToplevelWindow::SetUpShellIntegration() {
+ // This method should be called after the XDG surface is initialized.
DCHECK(shell_toplevel_);
if (connection()->zaura_shell() && !aura_surface_) {
@@ -564,6 +597,11 @@ void WaylandToplevelWindow::InitializeAuraShellSurface() {
this);
SetImmersiveFullscreenStatus(false);
}
+
+ if (connection()->gtk_shell1()) {
+ gtk_surface1_ =
+ connection()->gtk_shell1()->GetGtkSurface1(root_surface()->surface());
+ }
}
void WaylandToplevelWindow::OnDecorationModeChanged() {
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.h b/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.h
index 1c47f1c501e..a6df59f2e77 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.h
@@ -15,6 +15,7 @@
namespace ui {
+class GtkSurface1;
class ShellToplevelWrapper;
class WaylandToplevelWindow : public WaylandWindow,
@@ -56,12 +57,14 @@ class WaylandToplevelWindow : public WaylandWindow,
// xdg-decoration mode for a window.
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
+ bool ShouldUpdateWindowShape() const override;
// WaylandWindow overrides:
- base::Optional<std::vector<gfx::Rect>> GetWindowShape() const override;
+ absl::optional<std::vector<gfx::Rect>> GetWindowShape() const override;
private:
// WaylandWindow overrides:
+ void UpdateBufferScale(bool update_bounds) override;
void HandleToplevelConfigure(int32_t width,
int32_t height,
bool is_maximized,
@@ -91,6 +94,7 @@ class WaylandToplevelWindow : public WaylandWindow,
void SetImmersiveFullscreenStatus(bool status) override;
void ShowSnapPreview(WaylandWindowSnapDirection snap) override;
void CommitSnap(WaylandWindowSnapDirection snap) override;
+ void SetCanGoBack(bool value) override;
void TriggerStateChanges();
void SetWindowState(PlatformWindowState state);
@@ -105,9 +109,9 @@ class WaylandToplevelWindow : public WaylandWindow,
void SetOrResetRestoredBounds();
- // Initializes the aura-shell surface, in the case aura-shell EXO extension
- // is available.
- void InitializeAuraShellSurface();
+ // Initializes additional shell integration, if the appropriate interfaces are
+ // available.
+ void SetUpShellIntegration();
// Sets decoration mode for a window.
void OnDecorationModeChanged();
@@ -154,10 +158,13 @@ class WaylandToplevelWindow : public WaylandWindow,
std::u16string window_title_;
// Max and min sizes of the WaylandToplevelWindow window.
- base::Optional<gfx::Size> min_size_;
- base::Optional<gfx::Size> max_size_;
+ absl::optional<gfx::Size> min_size_;
+ absl::optional<gfx::Size> max_size_;
wl::Object<zaura_surface> aura_surface_;
+ // |gtk_surface1_| is the optional GTK surface that provides better
+ // integration with the desktop shell.
+ std::unique_ptr<GtkSurface1> gtk_surface1_;
// When use_native_frame is false, client-side decoration is set,
// e.g. lacros-browser.
@@ -165,7 +172,7 @@ class WaylandToplevelWindow : public WaylandWindow,
// e.g. lacros-taskmanager.
bool use_native_frame_ = false;
- base::Optional<std::vector<gfx::Rect>> window_shape_in_dips_;
+ absl::optional<std::vector<gfx::Rect>> window_shape_in_dips_;
// Pending xdg-shell configures, once this window is drawn to |bounds_dip|,
// ack_configure with |serial| will be sent to the Wayland compositor.
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_touch_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_touch_unittest.cc
index 4d1c4fedaea..e56094766e9 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_touch_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_touch_unittest.cc
@@ -18,6 +18,7 @@
using ::testing::_;
using ::testing::SaveArg;
+using ::testing::Values;
namespace ui {
@@ -158,9 +159,11 @@ TEST_P(WaylandTouchTest, CheckTouchFocus) {
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandTouchTest,
- ::testing::Values(kXdgShellStable));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
WaylandTouchTest,
- ::testing::Values(kXdgShellV6));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kV6}));
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window.cc b/chromium/ui/ozone/platform/wayland/host/wayland_window.cc
index 20a90ca60ba..f91de04c223 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_window.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_window.cc
@@ -14,7 +14,8 @@
#include "build/chromeos_buildflags.h"
#include "ui/base/cursor/mojom/cursor_type.mojom.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
-#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/cursor/platform_cursor.h"
+#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
@@ -33,6 +34,7 @@
#include "ui/ozone/platform/wayland/host/wayland_output_manager.h"
#include "ui/ozone/platform/wayland/host/wayland_pointer.h"
#include "ui/ozone/platform/wayland/host/wayland_subsurface.h"
+#include "ui/ozone/platform/wayland/host/wayland_surface.h"
#include "ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h"
#include "ui/ozone/public/mojom/wayland/wayland_overlay_config.mojom.h"
#include "ui/platform_window/common/platform_window_defaults.h"
@@ -43,6 +45,7 @@ namespace ui {
namespace {
using mojom::CursorType;
+using mojom::DragOperation;
bool OverlayStackOrderCompare(
const ui::ozone::mojom::WaylandOverlayConfigPtr& i,
@@ -81,7 +84,9 @@ WaylandWindow::~WaylandWindow() {
if (root_surface_)
connection_->wayland_window_manager()->RemoveWindow(GetWidget());
- if (parent_window_)
+ // This might have already been hidden and another window has been shown.
+ // Thus, the parent will have another child window. Do not reset it.
+ if (parent_window_ && parent_window_->child_window() == this)
parent_window_->set_child_window(nullptr);
}
@@ -117,6 +122,12 @@ void WaylandWindow::UpdateBufferScale(bool update_bounds) {
int32_t old_scale = buffer_scale();
root_surface_->SetBufferScale(new_scale, update_bounds);
+ if (primary_subsurface_)
+ primary_subsurface_->wayland_surface()->SetBufferScale(new_scale,
+ update_bounds);
+ for (auto& subsurface : wayland_subsurfaces_)
+ subsurface->wayland_surface()->SetBufferScale(new_scale, update_bounds);
+
// We need to keep DIP size of the window the same whenever the scale changes.
if (update_bounds)
SetBoundsDip(gfx::ScaleToRoundedRect(bounds_px_, 1.0 / old_scale));
@@ -142,7 +153,9 @@ uint32_t WaylandWindow::GetPreferredEnteredOutputId() {
if (entered_outputs_.empty())
return 0;
- DCHECK_EQ(PlatformWindowType::kWindow, type());
+ // PlatformWindowType::kPopup are created as toplevel windows as well.
+ DCHECK(type() == PlatformWindowType::kWindow ||
+ type() == PlatformWindowType::kPopup);
// A window can be located on two or more displays. Thus, return the id of the
// output that has the biggest scale factor. Otherwise, use the very first one
@@ -160,23 +173,11 @@ uint32_t WaylandWindow::GetPreferredEnteredOutputId() {
void WaylandWindow::SetPointerFocus(bool focus) {
has_pointer_focus_ = focus;
- // Whenever the window gets the pointer focus back, we must reinitialize the
- // cursor. Otherwise, it is invalidated whenever the pointer leaves the
- // surface and is not restored by the Wayland compositor.
- if (has_pointer_focus_ && bitmap_ && bitmap_->type() != CursorType::kNone) {
- // Check for theme-provided cursor.
- if (bitmap_->platform_data()) {
- connection_->SetPlatformCursor(
- reinterpret_cast<wl_cursor*>(bitmap_->platform_data()),
- buffer_scale());
- } else {
- // Translate physical pixels to DIPs.
- gfx::Point hotspot_in_dips =
- gfx::ScaleToRoundedPoint(bitmap_->hotspot(), 1.0f / ui_scale_);
- connection_->SetCursorBitmap(bitmap_->bitmaps(), hotspot_in_dips,
- buffer_scale());
- }
- }
+ // Whenever the window gets the pointer focus back, the cursor shape must be
+ // updated. Otherwise, it is invalidated upon wl_pointer::leave and is not
+ // restored by the Wayland compositor.
+ if (has_pointer_focus_ && cursor_)
+ UpdateCursorShape(cursor_);
}
bool WaylandWindow::StartDrag(const ui::OSExchangeData& data,
@@ -228,7 +229,7 @@ bool WaylandWindow::IsVisible() const {
void WaylandWindow::PrepareForShutdown() {
if (drag_handler_delegate_)
- OnDragSessionClose(DragDropTypes::DRAG_NONE);
+ OnDragSessionClose(DragOperation::kNone);
}
void WaylandWindow::SetBounds(const gfx::Rect& bounds_px) {
@@ -317,49 +318,13 @@ bool WaylandWindow::ShouldUseNativeFrame() const {
return false;
}
-void WaylandWindow::SetCursor(PlatformCursor cursor) {
- DCHECK(cursor);
+void WaylandWindow::SetCursor(scoped_refptr<PlatformCursor> platform_cursor) {
+ DCHECK(platform_cursor);
- scoped_refptr<BitmapCursorOzone> bitmap =
- BitmapCursorFactoryOzone::GetBitmapCursor(cursor);
- if (bitmap_ == bitmap)
+ if (cursor_ == platform_cursor)
return;
- bitmap_ = bitmap;
-
- if (bitmap_->type() == CursorType::kNone) {
- // Hide the cursor.
- connection_->SetCursorBitmap(std::vector<SkBitmap>(), gfx::Point(),
- buffer_scale());
- return;
- }
- // Check for theme-provided cursor.
- if (bitmap_->platform_data()) {
- connection_->SetPlatformCursor(
- reinterpret_cast<wl_cursor*>(bitmap_->platform_data()), buffer_scale());
- return;
- }
- // Check for Wayland server-side cursor support (e.g. exo for lacros).
- if (connection_->zcr_cursor_shapes()) {
- base::Optional<int32_t> shape =
- WaylandZcrCursorShapes::ShapeFromType(bitmap->type());
- // If the server supports this cursor type, use a server-side cursor.
- if (shape.has_value()) {
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
- // Lacros should not load image assets for default cursors. See
- // BitmapCursorFactoryOzone::GetDefaultCursor().
- DCHECK(bitmap_->bitmaps().empty());
-#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
- connection_->zcr_cursor_shapes()->SetCursorShape(shape.value());
- return;
- }
- // Fall through to client-side bitmap cursors.
- }
- // Translate physical pixels to DIPs.
- gfx::Point hotspot_in_dips =
- gfx::ScaleToRoundedPoint(bitmap_->hotspot(), 1.0f / ui_scale_);
- connection_->SetCursorBitmap(bitmap_->bitmaps(), hotspot_in_dips,
- buffer_scale());
+ UpdateCursorShape(BitmapCursorOzone::FromPlatformCursor(platform_cursor));
}
void WaylandWindow::MoveCursorTo(const gfx::Point& location) {
@@ -394,12 +359,12 @@ void WaylandWindow::SetWindowIcons(const gfx::ImageSkia& window_icon,
void WaylandWindow::SizeConstraintsChanged() {}
-bool WaylandWindow::ShouldUseLayerForShapedWindow() const {
- return true;
+bool WaylandWindow::ShouldUpdateWindowShape() const {
+ return false;
}
bool WaylandWindow::CanDispatchEvent(const PlatformEvent& event) {
- if (event->IsMouseEvent())
+ if (event->IsMouseEvent() || event->IsPinchEvent())
return has_pointer_focus_;
if (event->IsKeyEvent())
return has_keyboard_focus_;
@@ -479,8 +444,8 @@ void WaylandWindow::OnCloseRequest() {
delegate_->OnCloseRequest();
}
-base::Optional<std::vector<gfx::Rect>> WaylandWindow::GetWindowShape() const {
- return base::nullopt;
+absl::optional<std::vector<gfx::Rect>> WaylandWindow::GetWindowShape() const {
+ return absl::nullopt;
}
void WaylandWindow::UpdateWindowMask() {
@@ -537,9 +502,9 @@ void WaylandWindow::OnDragLeave() {
drop_handler->OnDragLeave();
}
-void WaylandWindow::OnDragSessionClose(uint32_t dnd_action) {
+void WaylandWindow::OnDragSessionClose(DragOperation operation) {
DCHECK(drag_handler_delegate_);
- drag_handler_delegate_->OnDragFinished(dnd_action);
+ drag_handler_delegate_->OnDragFinished(operation);
drag_handler_delegate_ = nullptr;
connection()->event_source()->ResetPointerFlags();
std::move(drag_loop_quit_closure_).Run();
@@ -586,8 +551,6 @@ bool WaylandWindow::Initialize(PlatformWindowInitProperties properties) {
PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
delegate_->OnAcceleratedWidgetAvailable(GetWidget());
- // Will do nothing for menus because they have got their scale above.
- UpdateBufferScale(false);
root_surface_->SetOpaqueRegion(gfx::Rect(bounds_px_.size()));
return true;
@@ -601,7 +564,7 @@ void WaylandWindow::AddEnteredOutputId(struct wl_output* output) {
// Wayland does weird things for menus so instead of tracking outputs that
// we entered or left, we take that from the parent window and ignore this
// event.
- if (wl::IsMenuType(type()) || type() == ui::PlatformWindowType::kTooltip)
+ if (AsWaylandPopup())
return;
entered_outputs_.emplace_back(
@@ -614,7 +577,7 @@ void WaylandWindow::RemoveEnteredOutputId(struct wl_output* output) {
// Wayland does weird things for menus so instead of tracking outputs that
// we entered or left, we take that from the parent window and ignore this
// event.
- if (wl::IsMenuType(type()))
+ if (AsWaylandPopup())
return;
auto entered_outputs_it_ =
@@ -687,6 +650,10 @@ bool WaylandWindow::IsActive() const {
return false;
}
+WaylandPopup* WaylandWindow::AsWaylandPopup() {
+ return nullptr;
+}
+
uint32_t WaylandWindow::DispatchEventToDelegate(
const PlatformEvent& native_event) {
bool handled = DispatchEventFromNativeUiEvent(
@@ -747,6 +714,9 @@ bool WaylandWindow::ArrangeSubsurfaceStack(size_t above, size_t below) {
bool WaylandWindow::CommitOverlays(
std::vector<ui::ozone::mojom::WaylandOverlayConfigPtr>& overlays) {
+ if (overlays.empty())
+ return true;
+
// |overlays| is sorted from bottom to top.
std::sort(overlays.begin(), overlays.end(), OverlayStackOrderCompare);
@@ -770,8 +740,10 @@ bool WaylandWindow::CommitOverlays(
if (!ArrangeSubsurfaceStack(above, below))
return false;
- if (wayland_overlay_delegation_enabled_)
+ if (wayland_overlay_delegation_enabled_) {
+ primary_subsurface()->Show();
connection_->buffer_manager_host()->StartFrame(root_surface());
+ }
{
// Iterate through |subsurface_stack_below_|, setup subsurfaces and place
@@ -839,7 +811,7 @@ bool WaylandWindow::CommitOverlays(
}
}
- if (!num_primary_planes && overlays.front()->z_order == INT32_MIN)
+ if (split == overlays.end() && overlays.front()->z_order == INT32_MIN)
split = overlays.begin();
UpdateVisualSize((*split)->bounds_rect.size());
@@ -862,7 +834,9 @@ bool WaylandWindow::CommitOverlays(
// with viewport.destination == buffer.size. So do not set
// viewport.destination to primary planes if crop_rect is uniform.
// TODO(fangzhoug): Refactor some of this logic s.t. the decision of whether
- // to apply viewport.destination is made at commit time.
+ // to apply viewport.destination is made at commit time. Right now PIP
+ // would have incorrect size b/c it is fullscreen overlay scheduled at
+ // z_order=0.
primary_subsurface_->ConfigureAndShowSurface(
(*split)->transform, (*split)->crop_rect,
(*split)->crop_rect == gfx::RectF(1.f, 1.f) ? gfx::Rect()
@@ -897,4 +871,35 @@ bool WaylandWindow::CommitOverlays(
return true;
}
+void WaylandWindow::UpdateCursorShape(scoped_refptr<BitmapCursorOzone> cursor) {
+ DCHECK(cursor);
+ absl::optional<int32_t> shape =
+ WaylandZcrCursorShapes::ShapeFromType(cursor->type());
+
+ if (cursor->type() == CursorType::kNone) { // Hide the cursor.
+ connection_->SetCursorBitmap({}, gfx::Point(), buffer_scale());
+ } else if (cursor->platform_data()) { // Check for theme-provided cursor.
+ connection_->SetPlatformCursor(
+ reinterpret_cast<wl_cursor*>(cursor->platform_data()), buffer_scale());
+ } else if (connection_->zcr_cursor_shapes() &&
+ shape.has_value()) { // Check for Wayland server-side cursor
+ // support (e.g. exo for lacros).
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+ // Lacros should not load image assets for default cursors. See
+ // BitmapCursorFactoryOzone::GetDefaultCursor().
+ DCHECK(cursor->bitmaps().empty());
+#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
+ connection_->zcr_cursor_shapes()->SetCursorShape(shape.value());
+ } else { // Use client-side bitmap cursors as fallback.
+ // Translate physical pixels to DIPs.
+ gfx::Point hotspot_in_dips =
+ gfx::ScaleToRoundedPoint(cursor->hotspot(), 1.0f / ui_scale_);
+ connection_->SetCursorBitmap(cursor->bitmaps(), hotspot_in_dips,
+ buffer_scale());
+ }
+ // The new cursor needs to be stored last to avoid deleting the old cursor
+ // while it's still in use.
+ cursor_ = cursor;
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window.h b/chromium/ui/ozone/platform/wayland/host/wayland_window.h
index 3c810edca97..e54307647d3 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_window.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_window.h
@@ -35,6 +35,7 @@ class WaylandConnection;
class WaylandSubsurface;
class WaylandWindowDragController;
class WaylandOutput;
+class WaylandPopup;
using WidgetSubsurfaceSet = base::flat_set<std::unique_ptr<WaylandSubsurface>>;
@@ -58,7 +59,7 @@ class WaylandWindow : public PlatformWindow,
// primary one if their widget is not yet created, children inherit scale from
// their parent. The method recalculates window bounds appropriately if asked
// to do so (this is not needed upon window initialization).
- void UpdateBufferScale(bool update_bounds);
+ virtual void UpdateBufferScale(bool update_bounds);
WaylandSurface* root_surface() const { return root_surface_.get(); }
WaylandSubsurface* primary_subsurface() const {
@@ -104,7 +105,7 @@ class WaylandWindow : public PlatformWindow,
WaylandWindow* child_window() const { return child_window_; }
int32_t buffer_scale() const { return root_surface_->buffer_scale(); }
- int32_t ui_scale() const { return ui_scale_; }
+ float ui_scale() const { return ui_scale_; }
// A preferred output is the one with the largest scale. This is needed to
// properly render contents as it seems like an expectation of Wayland.
@@ -155,7 +156,7 @@ class WaylandWindow : public PlatformWindow,
void Deactivate() override;
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
- void SetCursor(PlatformCursor cursor) override;
+ void SetCursor(scoped_refptr<PlatformCursor> cursor) override;
void MoveCursorTo(const gfx::Point& location) override;
void ConfineCursorToBounds(const gfx::Rect& bounds) override;
void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override;
@@ -165,7 +166,7 @@ class WaylandWindow : public PlatformWindow,
void SetWindowIcons(const gfx::ImageSkia& window_icon,
const gfx::ImageSkia& app_icon) override;
void SizeConstraintsChanged() override;
- bool ShouldUseLayerForShapedWindow() const override;
+ bool ShouldUpdateWindowShape() const override;
// PlatformEventDispatcher
bool CanDispatchEvent(const PlatformEvent& event) override;
@@ -193,9 +194,9 @@ class WaylandWindow : public PlatformWindow,
virtual int OnDragMotion(const gfx::PointF& point, int operation);
virtual void OnDragDrop();
virtual void OnDragLeave();
- virtual void OnDragSessionClose(uint32_t dnd_action);
+ virtual void OnDragSessionClose(ui::mojom::DragOperation operation);
- virtual base::Optional<std::vector<gfx::Rect>> GetWindowShape() const;
+ virtual absl::optional<std::vector<gfx::Rect>> GetWindowShape() const;
// Returns a root parent window within the same hierarchy.
WaylandWindow* GetRootParentWindow();
@@ -219,6 +220,11 @@ class WaylandWindow : public PlatformWindow,
// not support that).
virtual bool IsActive() const;
+ // WaylandWindow can be any type of object - WaylandToplevelWindow,
+ // WaylandPopup, WaylandAuxiliaryWindow. This method casts itself to
+ // WaylandPopup, if |this| has type of WaylandPopup.
+ virtual WaylandPopup* AsWaylandPopup();
+
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner() {
return ui_task_runner_;
}
@@ -233,7 +239,7 @@ class WaylandWindow : public PlatformWindow,
// Sets bounds in dip.
void SetBoundsDip(const gfx::Rect& bounds_dip);
- void set_ui_scale(int32_t ui_scale) { ui_scale_ = ui_scale; }
+ void set_ui_scale(float ui_scale) { ui_scale_ = ui_scale; }
// Calls set_opaque_region for this window.
virtual void UpdateWindowMask();
@@ -264,6 +270,8 @@ class WaylandWindow : public PlatformWindow,
friend WaylandWindowDragController;
std::unique_ptr<WaylandSurface> TakeWaylandSurface();
+ void UpdateCursorShape(scoped_refptr<BitmapCursorOzone> cursor);
+
PlatformWindowDelegate* delegate_;
WaylandConnection* connection_;
WaylandWindow* parent_window_ = nullptr;
@@ -288,7 +296,7 @@ class WaylandWindow : public PlatformWindow,
std::list<WaylandSubsurface*> subsurface_stack_below_;
// The current cursor bitmap (immutable).
- scoped_refptr<BitmapCursorOzone> bitmap_;
+ scoped_refptr<BitmapCursorOzone> cursor_;
// Current bounds of the platform window. This is either initialized, or the
// requested size by the Wayland compositor. When this is set in SetBounds(),
@@ -314,7 +322,7 @@ class WaylandWindow : public PlatformWindow,
// The UI scale may be forced through the command line, which means that it
// replaces the default value that is equal to the natural device scale.
// We need it to place and size the menus properly.
- float ui_scale_ = 1.0;
+ float ui_scale_ = 1.0f;
// Stores current opacity of the window. Set on ::Initialize call.
ui::PlatformWindowOpacity opacity_;
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc b/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
index 3431631b596..f1ccb8404ad 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
@@ -14,6 +14,7 @@
#include "base/callback.h"
#include "base/check.h"
+#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
#include "base/run_loop.h"
@@ -371,11 +372,8 @@ void WaylandWindowDragController::HandleMotionEvent(MouseEvent* event) {
// Update current cursor position, so it can be retrieved later on through
// |Screen::GetCursorScreenPoint| API.
- int32_t scale = dragged_window_->buffer_scale();
- gfx::PointF scaled_location =
- gfx::ScalePoint(event->location_f(), scale, scale);
connection_->wayland_cursor_position()->OnCursorPositionChanged(
- gfx::ToFlooredPoint(scaled_location));
+ event->location());
// Notify listeners about window bounds change (i.e: re-positioning) event.
// To do so, set the new bounds as per the motion event location and the drag
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
index b145ebefcc1..e4b83ef1d75 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
@@ -40,6 +40,7 @@
using testing::_;
using testing::Mock;
+using testing::Values;
namespace ui {
@@ -726,12 +727,81 @@ TEST_P(WaylandWindowDragControllerTest, MotionEventsSkippedWhileReattaching) {
EXPECT_EQ(State::kIdle, drag_controller()->state());
}
+// Test that cursor position is using DIP coordinates and is updated correctly
+// on DragMotion event.
+TEST_P(WaylandWindowDragControllerTest, CursorPositionIsUpdatedOnMotion) {
+ // Creating an output with scale 1.
+ wl::TestOutput* output1 = server_.CreateAndInitializeOutput();
+ output1->SetRect(gfx::Rect(0, 0, 1920, 1080));
+ output1->SetScale(1);
+ Sync();
+
+ // Creating an output with scale 2.
+ wl::TestOutput* output2 = server_.CreateAndInitializeOutput();
+ output2->SetRect(gfx::Rect(0, 0, 1920, 1080));
+ output2->SetScale(2);
+ Sync();
+
+ std::vector<wl::TestOutput*> outputs = {output1, output2};
+
+ // Start a window drag session.
+ SendPointerEnter(window_.get(), &delegate_);
+ SendPointerPress(window_.get(), &delegate_, BTN_LEFT);
+ SendPointerMotion(window_.get(), &delegate_, {10, 10});
+ EXPECT_EQ(gfx::Point(10, 10), screen_->GetCursorScreenPoint());
+
+ auto* wayland_extension = GetWaylandExtension(*window_);
+ wayland_extension->StartWindowDraggingSessionIfNeeded();
+ EXPECT_EQ(State::kAttached, drag_controller()->state());
+
+ auto* move_loop_handler = GetWmMoveLoopHandler(*window_);
+ ASSERT_TRUE(move_loop_handler);
+ auto test = [](WaylandWindowDragControllerTest* self, WaylandScreen* screen,
+ wl::TestWaylandServerThread* server, WaylandWindow* window,
+ std::vector<wl::TestOutput*>* outputs,
+ WmMoveLoopHandler* move_loop_handler) {
+ for (auto* output : *outputs) {
+ // Resetting cursor to the initial position.
+ self->SendDndMotion({10, 10});
+ self->Sync();
+ EXPECT_EQ(gfx::Point(10, 10), screen->GetCursorScreenPoint());
+
+ // Send the window to |output|.
+ wl::MockSurface* surface = server->GetObject<wl::MockSurface>(
+ window->root_surface()->GetSurfaceId());
+ ASSERT_TRUE(surface);
+ wl_surface_send_enter(surface->resource(), output->resource());
+ self->Sync();
+ EXPECT_EQ(output->GetScale(), window->buffer_scale());
+
+ self->SendDndMotion({20, 20});
+ self->Sync();
+
+ // GetCursorScreenPoint should return the same value regardless of buffer
+ // scale.
+ EXPECT_EQ(gfx::Point(20, 20), screen->GetCursorScreenPoint());
+ wl_surface_send_leave(surface->resource(), output->resource());
+ }
+
+ move_loop_handler->EndMoveLoop();
+ };
+
+ ScheduleTestTask(base::BindOnce(
+ test, base::Unretained(this), base::Unretained(screen_.get()),
+ base::Unretained(&server_), base::Unretained(window_.get()),
+ base::Unretained(&outputs), base::Unretained(move_loop_handler)));
+ EXPECT_CALL(delegate(), DispatchEvent(_)).Times(::testing::AtLeast(1));
+ move_loop_handler->RunMoveLoop({});
+}
+
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandWindowDragControllerTest,
- ::testing::Values(kXdgShellStable));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
WaylandWindowDragControllerTest,
- ::testing::Values(kXdgShellV6));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kV6}));
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window_factory.cc b/chromium/ui/ozone/platform/wayland/host/wayland_window_factory.cc
index d350c231ed9..a49ecc2750c 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_window_factory.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_window_factory.cc
@@ -43,6 +43,7 @@ std::unique_ptr<WaylandWindow> WaylandWindow::Create(
}
window = std::make_unique<WaylandToplevelWindow>(delegate, connection);
break;
+ case PlatformWindowType::kTooltip:
case PlatformWindowType::kMenu:
// Set the parent window in advance otherwise it is not possible to know
// if the popup is able to find one and if WaylandWindow::Initialize()
@@ -61,11 +62,6 @@ std::unique_ptr<WaylandWindow> WaylandWindow::Create(
window = std::make_unique<WaylandToplevelWindow>(delegate, connection);
}
break;
- case PlatformWindowType::kTooltip:
- window = std::make_unique<WaylandAuxiliaryWindow>(
- delegate, connection,
- GetParentWindow(connection, properties.parent_widget));
- break;
case PlatformWindowType::kWindow:
case PlatformWindowType::kBubble:
case PlatformWindowType::kDrag:
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc b/chromium/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc
index 64ee858d400..dc2dabb0bfd 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc
@@ -12,6 +12,8 @@
namespace ui {
+using ::testing::Values;
+
namespace {
constexpr gfx::Rect kDefaultBounds(0, 0, 100, 100);
@@ -230,10 +232,12 @@ TEST_P(WaylandWindowManagerTest, GetAllWindows) {
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandWindowManagerTest,
- ::testing::Values(kXdgShellStable));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
WaylandWindowManagerTest,
- ::testing::Values(kXdgShellV6));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kV6}));
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
index dd3f1d97c0c..dd36a5ac111 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
@@ -24,8 +24,10 @@
#include "ui/base/hit_test.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/event.h"
+#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/overlay_transform.h"
+#include "ui/gfx/transform.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h"
#include "ui/ozone/platform/wayland/host/wayland_connection_test_api.h"
@@ -53,6 +55,7 @@ using ::testing::Mock;
using ::testing::Return;
using ::testing::SaveArg;
using ::testing::StrEq;
+using ::testing::Values;
namespace ui {
@@ -137,7 +140,7 @@ class WaylandWindowTest : public WaylandTest {
const gfx::Rect bounds) {
auto* popup = GetTextXdgPopupByWindow(menu_window);
ASSERT_TRUE(popup);
- if (GetParam() == kXdgShellV6) {
+ if (GetParam().shell_version == wl::ShellVersion::kV6) {
zxdg_popup_v6_send_configure(popup->resource(), bounds.x(), bounds.y(),
bounds.width(), bounds.height());
} else {
@@ -1632,7 +1635,7 @@ TEST_P(WaylandWindowTest, ToplevelWindowUpdateBufferScale) {
EXPECT_EQ(gfx::Rect(0, 0, 1600, 1200), window_->GetBounds());
}
-TEST_P(WaylandWindowTest, AuxiliaryWindowUpdateBufferScale) {
+TEST_P(WaylandWindowTest, WaylandPopupBufferScale) {
VerifyAndClearExpectations();
// Creating an output with scale 1.
@@ -1643,50 +1646,133 @@ TEST_P(WaylandWindowTest, AuxiliaryWindowUpdateBufferScale) {
// Creating an output with scale 2.
wl::TestOutput* output2 = server_.CreateAndInitializeOutput();
- output2->SetRect(gfx::Rect(0, 0, 1920, 1080));
+ output2->SetRect(gfx::Rect(1920, 0, 1920, 1080));
output2->SetScale(2);
Sync();
- // Send the window to |output1|.
- wl::MockSurface* surface = server_.GetObject<wl::MockSurface>(
- window_->root_surface()->GetSurfaceId());
- ASSERT_TRUE(surface);
- wl_surface_send_enter(surface->resource(), output1->resource());
- Sync();
+ std::vector<PlatformWindowType> window_types{PlatformWindowType::kMenu,
+ PlatformWindowType::kTooltip};
+ for (const auto& type : window_types) {
+ // Send the window to |output1|.
+ wl::MockSurface* surface = server_.GetObject<wl::MockSurface>(
+ window_->root_surface()->GetSurfaceId());
+ ASSERT_TRUE(surface);
+ wl_surface_send_enter(surface->resource(), output1->resource());
+ Sync();
- // Creating a tooltip on |window_|.
- window_->SetPointerFocus(true);
- gfx::Rect subsurface_bounds(15, 15, 10, 10);
- std::unique_ptr<WaylandWindow> auxiliary_window =
- CreateWaylandWindowWithParams(PlatformWindowType::kTooltip,
- gfx::kNullAcceleratedWidget,
- subsurface_bounds, &delegate_);
- EXPECT_TRUE(auxiliary_window);
+ // Creating a wayland_popup on |window_|.
+ window_->SetPointerFocus(true);
+ gfx::Rect wayland_popup_bounds(15, 15, 10, 10);
+ auto wayland_popup = CreateWaylandWindowWithParams(
+ type, window_->GetWidget(), wayland_popup_bounds, &delegate_);
+ EXPECT_TRUE(wayland_popup);
+ wayland_popup->Show(false);
+
+ // the wayland_popup window should inherit its buffer scale from the focused
+ // window.
+ EXPECT_EQ(1, window_->buffer_scale());
+ EXPECT_EQ(window_->buffer_scale(), wayland_popup->buffer_scale());
+ EXPECT_EQ(wayland_popup_bounds, wayland_popup->GetBounds());
+ wayland_popup->Hide();
+
+ // Send the window to |output2|.
+ wl_surface_send_enter(surface->resource(), output2->resource());
+ wl_surface_send_leave(surface->resource(), output1->resource());
+ Sync();
- auxiliary_window->Show(false);
+ EXPECT_EQ(2, window_->buffer_scale());
+ wayland_popup->Show(false);
- // |auxiliary_window| should inherit its buffer scale from the focused window.
- EXPECT_EQ(1, auxiliary_window->buffer_scale());
- EXPECT_EQ(subsurface_bounds, auxiliary_window->GetBounds());
- auxiliary_window->Hide();
+ Sync();
- // Send the window to |output2|.
- wl_surface_send_enter(surface->resource(), output2->resource());
- wl_surface_send_leave(surface->resource(), output1->resource());
+ // |wayland_popup|'s scale and bounds must change whenever its parents
+ // scale is changed.
+ EXPECT_EQ(window_->buffer_scale(), wayland_popup->buffer_scale());
+ EXPECT_EQ(gfx::ScaleToRoundedRect(wayland_popup_bounds,
+ wayland_popup->buffer_scale()),
+ wayland_popup->GetBounds());
+
+ wayland_popup->Hide();
+ window_->SetPointerFocus(false);
+
+ wl_surface_send_leave(surface->resource(), output2->resource());
+ Sync();
+ }
+}
+
+// Tests that WaylandPopup is able to translate provided bounds via
+// PlatformWindowProperties using buffer scale it's going to use that the client
+// is not able to determine before PlatformWindow is created. See
+// WaylandPopup::OnInitialize for more details.
+TEST_P(WaylandWindowTest, WaylandPopupInitialBufferScale) {
+ VerifyAndClearExpectations();
+
+ // Creating an output with scale 1.
+ wl::TestOutput* main_output = server_.CreateAndInitializeOutput();
+ main_output->SetRect(gfx::Rect(0, 0, 1920, 1080));
+ main_output->SetScale(1);
Sync();
- EXPECT_EQ(2, window_->buffer_scale());
- auxiliary_window->Show(false);
+ // Creating an output with scale 2.
+ wl::TestOutput* secondary_output = server_.CreateAndInitializeOutput();
+ secondary_output->SetRect(gfx::Rect(1921, 0, 1920, 1080));
+ secondary_output->SetScale(1);
+ Sync();
- // |auxiliary_window|'s scale and bounds must change whenever its parents
- // scale is changed.
- EXPECT_EQ(2, window_->buffer_scale());
- EXPECT_EQ(2, auxiliary_window->buffer_scale());
- EXPECT_EQ(gfx::ScaleToRoundedRect(subsurface_bounds, 2),
- auxiliary_window->GetBounds());
+ // Send the window to |output1|.
+ wl::MockSurface* surface = server_.GetObject<wl::MockSurface>(
+ window_->root_surface()->GetSurfaceId());
+ ASSERT_TRUE(surface);
- auxiliary_window->Hide();
- window_->SetPointerFocus(false);
+ std::vector<wl::TestOutput*> entered_outputs = {main_output,
+ secondary_output};
+ for (auto* entered_output : entered_outputs) {
+ wl_surface_send_enter(surface->resource(), entered_output->resource());
+ Sync();
+ for (auto main_output_scale = 1; main_output_scale < 5;
+ main_output_scale++) {
+ for (auto secondary_output_scale = 1; secondary_output_scale < 5;
+ secondary_output_scale++) {
+ // Update scale factors first.
+ main_output->SetScale(main_output_scale);
+ secondary_output->SetScale(secondary_output_scale);
+
+ main_output->Flush();
+ secondary_output->Flush();
+ Sync();
+
+ gfx::Rect bounds_dip(15, 15, 10, 10);
+ // DesktopWindowTreeHostPlatform has always to use a primary display's
+ // scale to translate initial bounds to pixels. Thus, use primary's
+ // output's scale to make initial bounds.
+ // This code snippet is a copy of
+ // DesktopWindowTreeHostPlatform::ToPixelRect.
+ gfx::Transform transform;
+ transform.Scale(main_output_scale, main_output_scale);
+ gfx::RectF rect_in_pixels = gfx::RectF(bounds_dip);
+ transform.TransformRect(&rect_in_pixels);
+ gfx::Rect wayland_popup_bounds = gfx::ToEnclosingRect(rect_in_pixels);
+
+ std::unique_ptr<WaylandWindow> wayland_popup =
+ CreateWaylandWindowWithParams(PlatformWindowType::kMenu,
+ window_->GetWidget(),
+ wayland_popup_bounds, &delegate_);
+ EXPECT_TRUE(wayland_popup);
+
+ wayland_popup->Show(false);
+
+ gfx::Rect expected_bounds = wayland_popup_bounds;
+ if (entered_output == secondary_output) {
+ expected_bounds =
+ gfx::ScaleToRoundedRect(bounds_dip, secondary_output_scale);
+ }
+
+ EXPECT_EQ(expected_bounds, wayland_popup->GetBounds());
+ }
+ }
+ wl_surface_send_leave(surface->resource(), entered_output->resource());
+ Sync();
+ }
}
// Tests that a WaylandWindow uses the entered output with largest scale
@@ -1888,7 +1974,7 @@ TEST_P(WaylandWindowTest, GetChildrenPreferredOutput) {
TEST_P(WaylandWindowTest, AdjustPopupBounds) {
PopupPosition menu_window_positioner, nested_menu_window_positioner;
- if (GetParam() == kXdgShellV6) {
+ if (GetParam().shell_version == wl::ShellVersion::kV6) {
menu_window_positioner = {
gfx::Rect(439, 46, 1, 30), gfx::Size(287, 409),
ZXDG_POSITIONER_V6_ANCHOR_BOTTOM | ZXDG_POSITIONER_V6_ANCHOR_RIGHT,
@@ -2101,7 +2187,7 @@ TEST_P(WaylandWindowTest, SetOpaqueRegion) {
TEST_P(WaylandWindowTest, OnCloseRequest) {
EXPECT_CALL(delegate_, OnCloseRequest());
- if (GetParam() == kXdgShellV6)
+ if (GetParam().shell_version == wl::ShellVersion::kV6)
zxdg_toplevel_v6_send_close(xdg_surface_->xdg_toplevel()->resource());
else
xdg_toplevel_send_close(xdg_surface_->xdg_toplevel()->resource());
@@ -2109,39 +2195,32 @@ TEST_P(WaylandWindowTest, OnCloseRequest) {
Sync();
}
-TEST_P(WaylandWindowTest, AuxiliaryWindowSimpleParent) {
+TEST_P(WaylandWindowTest, WaylandPopupSimpleParent) {
VerifyAndClearExpectations();
- // Auxiliary window must ignore the parent provided by aura and should always
+ // WaylandPopup must ignore the parent provided by aura and should always
// use focused window instead.
- gfx::Rect subsurface_bounds(gfx::Point(15, 15), gfx::Size(10, 10));
- std::unique_ptr<WaylandWindow> auxiliary_window =
- CreateWaylandWindowWithParams(PlatformWindowType::kTooltip,
- gfx::kNullAcceleratedWidget,
- subsurface_bounds, &delegate_);
- EXPECT_TRUE(auxiliary_window);
+ gfx::Rect wayland_popup_bounds(gfx::Point(15, 15), gfx::Size(10, 10));
+ std::unique_ptr<WaylandWindow> wayland_popup = CreateWaylandWindowWithParams(
+ PlatformWindowType::kTooltip, gfx::kNullAcceleratedWidget,
+ wayland_popup_bounds, &delegate_);
+ EXPECT_TRUE(wayland_popup);
window_->SetPointerFocus(true);
- auxiliary_window->Show(false);
+ wayland_popup->Show(false);
Sync();
- auto* mock_surface_subsurface = server_.GetObject<wl::MockSurface>(
- auxiliary_window->root_surface()->GetSurfaceId());
- auto* test_subsurface = mock_surface_subsurface->sub_surface();
+ auto* mock_surface_popup = server_.GetObject<wl::MockSurface>(
+ wayland_popup->root_surface()->GetSurfaceId());
+ auto* mock_xdg_popup = mock_surface_popup->xdg_surface()->xdg_popup();
- EXPECT_EQ(test_subsurface->position(), subsurface_bounds.origin());
- EXPECT_FALSE(test_subsurface->sync());
- EXPECT_EQ(mock_surface_subsurface->opaque_region(),
- gfx::Rect(subsurface_bounds.size()));
+ EXPECT_EQ(mock_xdg_popup->anchor_rect().origin(),
+ wayland_popup_bounds.origin());
+ EXPECT_EQ(mock_surface_popup->opaque_region(),
+ gfx::Rect(wayland_popup_bounds.size()));
- auto* parent_resource =
- server_
- .GetObject<wl::MockSurface>(window_->root_surface()->GetSurfaceId())
- ->resource();
- EXPECT_EQ(parent_resource, test_subsurface->parent_resource());
-
- auxiliary_window->Hide();
+ wayland_popup->Hide();
window_->SetPointerFocus(false);
}
@@ -2294,11 +2373,11 @@ TEST_P(WaylandWindowTest, NestedMenuWindows3) {
nested_menu_window->SetPointerFocus(false);
}
-TEST_P(WaylandWindowTest, AuxiliaryWindowNestedParent) {
+TEST_P(WaylandWindowTest, WaylandPopupNestedParent) {
VerifyAndClearExpectations();
gfx::Rect menu_window_bounds(gfx::Point(10, 10), gfx::Size(100, 100));
- std::unique_ptr<WaylandWindow> menu_window = CreateWaylandWindowWithParams(
+ auto menu_window = CreateWaylandWindowWithParams(
PlatformWindowType::kMenu, window_->GetWidget(), menu_window_bounds,
&delegate_);
EXPECT_TRUE(menu_window);
@@ -2306,42 +2385,48 @@ TEST_P(WaylandWindowTest, AuxiliaryWindowNestedParent) {
VerifyAndClearExpectations();
menu_window->SetPointerFocus(true);
- gfx::Rect subsurface_bounds(gfx::Point(15, 15), gfx::Size(10, 10));
- std::unique_ptr<WaylandWindow> auxiliary_window =
- CreateWaylandWindowWithParams(PlatformWindowType::kTooltip,
- menu_window->GetWidget(), subsurface_bounds,
- &delegate_);
- EXPECT_TRUE(auxiliary_window);
+ std::vector<PlatformWindowType> window_types{PlatformWindowType::kMenu,
+ PlatformWindowType::kTooltip};
+ for (const auto& type : window_types) {
+ gfx::Rect nested_wayland_popup_bounds(gfx::Point(15, 15),
+ gfx::Size(10, 10));
+ auto nested_wayland_popup =
+ CreateWaylandWindowWithParams(type, menu_window->GetWidget(),
+ nested_wayland_popup_bounds, &delegate_);
+ EXPECT_TRUE(nested_wayland_popup);
- VerifyAndClearExpectations();
+ VerifyAndClearExpectations();
- auxiliary_window->Show(false);
+ nested_wayland_popup->Show(false);
- Sync();
+ Sync();
- auto* mock_surface_subsurface = server_.GetObject<wl::MockSurface>(
- auxiliary_window->root_surface()->GetSurfaceId());
- auto* test_subsurface = mock_surface_subsurface->sub_surface();
+ auto* mock_surface_nested = server_.GetObject<wl::MockSurface>(
+ nested_wayland_popup->root_surface()->GetSurfaceId());
+ auto* mock_xdg_popup_nested =
+ mock_surface_nested->xdg_surface()->xdg_popup();
- auto new_origin = subsurface_bounds.origin() -
- menu_window_bounds.origin().OffsetFromOrigin();
- EXPECT_EQ(test_subsurface->position(), new_origin);
- EXPECT_EQ(mock_surface_subsurface->opaque_region(),
- gfx::Rect(subsurface_bounds.size()));
+ auto new_origin = nested_wayland_popup_bounds.origin() -
+ menu_window_bounds.origin().OffsetFromOrigin();
+ EXPECT_EQ(mock_xdg_popup_nested->anchor_rect().origin(), new_origin);
+ EXPECT_EQ(mock_surface_nested->opaque_region(),
+ gfx::Rect(nested_wayland_popup_bounds.size()));
- menu_window->SetPointerFocus(false);
+ menu_window->SetPointerFocus(false);
+ nested_wayland_popup->Hide();
+ }
}
TEST_P(WaylandWindowTest, OnSizeConstraintsChanged) {
const bool kBooleans[] = {false, true};
for (bool has_min_size : kBooleans) {
for (bool has_max_size : kBooleans) {
- base::Optional<gfx::Size> min_size =
- has_min_size ? base::Optional<gfx::Size>(gfx::Size(100, 200))
- : base::nullopt;
- base::Optional<gfx::Size> max_size =
- has_max_size ? base::Optional<gfx::Size>(gfx::Size(300, 400))
- : base::nullopt;
+ absl::optional<gfx::Size> min_size =
+ has_min_size ? absl::optional<gfx::Size>(gfx::Size(100, 200))
+ : absl::nullopt;
+ absl::optional<gfx::Size> max_size =
+ has_max_size ? absl::optional<gfx::Size>(gfx::Size(300, 400))
+ : absl::nullopt;
EXPECT_CALL(delegate_, GetMinimumSizeForWindow())
.WillOnce(Return(min_size));
EXPECT_CALL(delegate_, GetMaximumSizeForWindow())
@@ -2526,14 +2611,14 @@ TEST_P(WaylandWindowTest, SetsPropertiesOnShow) {
auto* mock_xdg_toplevel = mock_surface->xdg_surface()->xdg_toplevel();
// Only app id must be set now.
- EXPECT_EQ(std::string(kAppId), mock_xdg_toplevel->app_id());
+ EXPECT_EQ(window->GetWindowUniqueId(), mock_xdg_toplevel->app_id());
EXPECT_TRUE(mock_xdg_toplevel->title().empty());
EXPECT_TRUE(mock_xdg_toplevel->min_size().IsEmpty());
EXPECT_TRUE(mock_xdg_toplevel->max_size().IsEmpty());
// Now, propagate size constraints and title.
- base::Optional<gfx::Size> min_size(gfx::Size(1, 1));
- base::Optional<gfx::Size> max_size(gfx::Size(100, 100));
+ absl::optional<gfx::Size> min_size(gfx::Size(1, 1));
+ absl::optional<gfx::Size> max_size(gfx::Size(100, 100));
EXPECT_CALL(delegate, GetMinimumSizeForWindow())
.Times(2)
.WillRepeatedly(Return(min_size));
@@ -2564,16 +2649,16 @@ TEST_P(WaylandWindowTest, SetsPropertiesOnShow) {
// We can't mock all those methods above as long as the xdg_toplevel is
// created and destroyed on each show and hide call. However, it is the same
- // WaylandToplevelWindow object that cached the values we set and must restore
- // them on Show().
+ // WaylandToplevelWindow object that cached the values we set and must
+ // restore them on Show().
EXPECT_EQ(mock_xdg_toplevel->min_size(), min_size.value());
EXPECT_EQ(mock_xdg_toplevel->max_size(), max_size.value());
- EXPECT_EQ(std::string(kAppId), mock_xdg_toplevel->app_id());
+ EXPECT_EQ(window->GetWindowUniqueId(), mock_xdg_toplevel->app_id());
EXPECT_EQ(mock_xdg_toplevel->title(), base::UTF16ToUTF8(kTitle));
}
-// Tests that a popup window is created using the serial of button press events
-// as required by the Wayland protocol spec.
+// Tests that a popup window is created using the serial of button press
+// events as required by the Wayland protocol spec.
TEST_P(WaylandWindowTest, CreatesPopupOnButtonPressSerial) {
wl_seat_send_capabilities(
server_.seat()->resource(),
@@ -2831,7 +2916,7 @@ TEST_P(WaylandWindowTest, UsesCorrectParentForChildrenWindows) {
gfx::Rect(10, 10, 10, 10), &menu_window_delegate);
EXPECT_TRUE(menu_window->parent_window() == window2);
- EXPECT_TRUE(wl::IsMenuType(menu_window->type()));
+ EXPECT_TRUE(menu_window->AsWaylandPopup());
// Subcase 2: keyboard focus.
window2->SetPointerFocus(false);
@@ -2865,7 +2950,7 @@ TEST_P(WaylandWindowTest, UsesCorrectParentForChildrenWindows) {
gfx::Rect(10, 10, 10, 10), &menu_window_delegate);
EXPECT_TRUE(menu_window->parent_window() == window2);
- EXPECT_TRUE(wl::IsMenuType(menu_window->type()));
+ EXPECT_TRUE(menu_window->AsWaylandPopup());
// Case 3: neither of the windows are focused. However, there is one that is
// active. Must use that then.
@@ -2880,14 +2965,16 @@ TEST_P(WaylandWindowTest, UsesCorrectParentForChildrenWindows) {
gfx::Rect(10, 10, 10, 10), &menu_window_delegate);
EXPECT_TRUE(menu_window->parent_window() == window3);
- EXPECT_TRUE(wl::IsMenuType(menu_window->type()));
+ EXPECT_TRUE(menu_window->AsWaylandPopup());
}
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandWindowTest,
- ::testing::Values(kXdgShellStable));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
WaylandWindowTest,
- ::testing::Values(kXdgShellV6));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kV6}));
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_zaura_shell.h b/chromium/ui/ozone/platform/wayland/host/wayland_zaura_shell.h
index 9c0e8251b1b..82a35ba67ae 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_zaura_shell.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_zaura_shell.h
@@ -5,7 +5,6 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZAURA_SHELL_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZAURA_SHELL_H_
-#include <string>
#include "base/containers/flat_set.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_zaura_shell_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_zaura_shell_unittest.cc
index a8bba1eb24d..ecf6c8afdf0 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_zaura_shell_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_zaura_shell_unittest.cc
@@ -17,7 +17,6 @@ namespace ui {
namespace {
-constexpr uint32_t kXdgVersionStable = 7;
constexpr uint32_t kZAuraShellVersion = 14;
} // namespace
@@ -26,13 +25,14 @@ TEST(WaylandZauraShellTest, Foo) {
base::test::SingleThreadTaskEnvironment task_environment(
base::test::SingleThreadTaskEnvironment::MainThreadType::UI);
wl::TestWaylandServerThread server;
- ASSERT_TRUE(server.Start(kXdgVersionStable));
+ ASSERT_TRUE(server.Start({.shell_version = wl::ShellVersion::kStable}));
wl::GlobalObject zaura_shell_obj(
&zaura_shell_interface, nullptr /* implementation */, kZAuraShellVersion);
zaura_shell_obj.Initialize(server.display());
WaylandConnection connection;
ASSERT_TRUE(connection.Initialize());
+ connection.event_source()->UseSingleThreadedPollingForTesting();
connection.event_source()->StartProcessingEvents();
base::RunLoop().RunUntilIdle();
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.cc b/chromium/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.cc
index fdf633a89ae..b8055608c33 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.cc
@@ -7,7 +7,7 @@
#include <cursor-shapes-unstable-v1-client-protocol.h>
#include "base/check.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
@@ -27,7 +27,7 @@ WaylandZcrCursorShapes::WaylandZcrCursorShapes(
WaylandZcrCursorShapes::~WaylandZcrCursorShapes() = default;
// static
-base::Optional<int32_t> WaylandZcrCursorShapes::ShapeFromType(CursorType type) {
+absl::optional<int32_t> WaylandZcrCursorShapes::ShapeFromType(CursorType type) {
switch (type) {
case CursorType::kNull:
// kNull is an alias for kPointer. Fall through.
@@ -124,10 +124,10 @@ base::Optional<int32_t> WaylandZcrCursorShapes::ShapeFromType(CursorType type) {
case CursorType::kNorthSouthNoResize:
case CursorType::kNorthWestSouthEastNoResize:
// Not supported by this API.
- return base::nullopt;
+ return absl::nullopt;
case CursorType::kCustom:
// Custom means a bitmap cursor, which can't use the shape API.
- return base::nullopt;
+ return absl::nullopt;
case CursorType::kDndNone:
return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_DND_NONE;
case CursorType::kDndMove:
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h b/chromium/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h
index eafea77ae68..0b78df09924 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h
@@ -5,7 +5,7 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZCR_CURSOR_SHAPES_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZCR_CURSOR_SHAPES_H_
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
@@ -26,7 +26,7 @@ class WaylandZcrCursorShapes {
// Returns the cursor shape value for a cursor |type|, or nullopt if the
// type isn't supported by the cursor API.
- static base::Optional<int32_t> ShapeFromType(mojom::CursorType type);
+ static absl::optional<int32_t> ShapeFromType(mojom::CursorType type);
// Calls zcr_cursor_shapes_v1_set_cursor_shape(). See interface description
// for values for |shape|. Virtual for testing.
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc b/chromium/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc
index d82674b3137..32ffaabf146 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc
@@ -25,7 +25,7 @@ WaylandZwpLinuxDmabuf::WaylandZwpLinuxDmabuf(
// A roundtrip after binding guarantees that the client has received all
// supported formats.
- wl_display_roundtrip(connection_->display());
+ connection_->RoundTripQueue();
}
WaylandZwpLinuxDmabuf::~WaylandZwpLinuxDmabuf() = default;
@@ -72,7 +72,7 @@ void WaylandZwpLinuxDmabuf::CreateBuffer(base::ScopedFD fd,
void WaylandZwpLinuxDmabuf::AddSupportedFourCCFormatAndModifier(
uint32_t fourcc_format,
- base::Optional<uint64_t> modifier) {
+ absl::optional<uint64_t> modifier) {
// Return on not supported fourcc formats.
if (!IsValidBufferFormat(fourcc_format))
return;
@@ -130,7 +130,7 @@ void WaylandZwpLinuxDmabuf::Format(void* data,
uint32_t format) {
WaylandZwpLinuxDmabuf* self = static_cast<WaylandZwpLinuxDmabuf*>(data);
if (self)
- self->AddSupportedFourCCFormatAndModifier(format, base::nullopt);
+ self->AddSupportedFourCCFormatAndModifier(format, absl::nullopt);
}
// static
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h b/chromium/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h
index 9ecb0b749b8..3139ce2cfbf 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h
@@ -9,7 +9,7 @@
#include "base/files/scoped_file.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h"
@@ -57,7 +57,7 @@ class WaylandZwpLinuxDmabuf {
// the |supported_buffer_formats_| container. Modifiers can also be passed to
// this method to be stored as a map of the format and modifier.
void AddSupportedFourCCFormatAndModifier(uint32_t fourcc_format,
- base::Optional<uint64_t> modifier);
+ absl::optional<uint64_t> modifier);
// Finds the stored callback corresponding to the |params| created in the
// RequestBufferAsync call, and passes the wl_buffer to the client. The
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc b/chromium/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc
new file mode 100644
index 00000000000..a98a2d61d20
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc
@@ -0,0 +1,100 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.h"
+
+#include <pointer-gestures-unstable-v1-client-protocol.h>
+#include <wayland-util.h>
+
+#include "ui/gfx/geometry/vector2d_f.h"
+#include "ui/ozone/platform/wayland/common/wayland_util.h"
+#include "ui/ozone/platform/wayland/host/wayland_connection.h"
+#include "ui/ozone/platform/wayland/host/wayland_cursor_position.h"
+#include "ui/ozone/platform/wayland/host/wayland_pointer.h"
+#include "ui/ozone/platform/wayland/host/wayland_window_manager.h"
+
+namespace ui {
+
+WaylandZwpPointerGestures::WaylandZwpPointerGestures(
+ zwp_pointer_gestures_v1* pointer_gestures,
+ WaylandConnection* connection,
+ Delegate* delegate)
+ : obj_(pointer_gestures), connection_(connection), delegate_(delegate) {
+ DCHECK(obj_);
+ DCHECK(connection_);
+ DCHECK(delegate_);
+}
+
+WaylandZwpPointerGestures::~WaylandZwpPointerGestures() = default;
+
+void WaylandZwpPointerGestures::Init() {
+ DCHECK(connection_->pointer());
+
+ pinch_.reset(zwp_pointer_gestures_v1_get_pinch_gesture(
+ obj_.get(), connection_->pointer()->wl_object()));
+
+ static const zwp_pointer_gesture_pinch_v1_listener
+ zwp_pointer_gesture_pinch_v1_listener = {
+ &WaylandZwpPointerGestures::OnPinchBegin,
+ &WaylandZwpPointerGestures::OnPinchUpdate,
+ &WaylandZwpPointerGestures::OnPinchEnd,
+ };
+ zwp_pointer_gesture_pinch_v1_add_listener(
+ pinch_.get(), &zwp_pointer_gesture_pinch_v1_listener, this);
+}
+
+// static
+void WaylandZwpPointerGestures::OnPinchBegin(
+ void* data,
+ struct zwp_pointer_gesture_pinch_v1* zwp_pointer_gesture_pinch_v1,
+ uint32_t serial,
+ uint32_t time,
+ struct wl_surface* surface,
+ uint32_t fingers) {
+ auto* thiz = static_cast<WaylandZwpPointerGestures*>(data);
+
+ base::TimeTicks timestamp =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(time);
+
+ thiz->delegate_->OnPinchEvent(ET_GESTURE_PINCH_BEGIN,
+ gfx::Vector2dF() /*delta*/, timestamp,
+ thiz->obj_.id());
+}
+
+// static
+void WaylandZwpPointerGestures::OnPinchUpdate(
+ void* data,
+ struct zwp_pointer_gesture_pinch_v1* zwp_pointer_gesture_pinch_v1,
+ uint32_t time,
+ wl_fixed_t dx,
+ wl_fixed_t dy,
+ wl_fixed_t scale,
+ wl_fixed_t rotation) {
+ auto* thiz = static_cast<WaylandZwpPointerGestures*>(data);
+
+ base::TimeTicks timestamp =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(time);
+
+ gfx::Vector2dF delta = {wl_fixed_to_double(dx), wl_fixed_to_double(dy)};
+ thiz->delegate_->OnPinchEvent(ET_GESTURE_PINCH_UPDATE, delta, timestamp,
+ thiz->obj_.id(), wl_fixed_to_double(scale));
+}
+
+void WaylandZwpPointerGestures::OnPinchEnd(
+ void* data,
+ struct zwp_pointer_gesture_pinch_v1* zwp_pointer_gesture_pinch_v1,
+ uint32_t serial,
+ uint32_t time,
+ int32_t cancelled) {
+ auto* thiz = static_cast<WaylandZwpPointerGestures*>(data);
+
+ base::TimeTicks timestamp =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(time);
+
+ thiz->delegate_->OnPinchEvent(ET_GESTURE_PINCH_END,
+ gfx::Vector2dF() /*delta*/, timestamp,
+ thiz->obj_.id());
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.h b/chromium/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.h
new file mode 100644
index 00000000000..3c3ad0528c3
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.h
@@ -0,0 +1,79 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZWP_POINTER_GESTURES_H_
+#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZWP_POINTER_GESTURES_H_
+
+#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/events/types/event_type.h"
+#include "ui/ozone/platform/wayland/common/wayland_object.h"
+
+namespace gfx {
+class Vector2dF;
+}
+
+namespace ui {
+
+class WaylandConnection;
+
+// Wraps the zwp_pointer_gestures and zwp_pointer_gesture_pinch_v1 objects.
+class WaylandZwpPointerGestures {
+ public:
+ class Delegate;
+
+ WaylandZwpPointerGestures(zwp_pointer_gestures_v1* pointer_gestures,
+ WaylandConnection* connection,
+ Delegate* delegate);
+ WaylandZwpPointerGestures(const WaylandZwpPointerGestures&) = delete;
+ WaylandZwpPointerGestures& operator=(const WaylandZwpPointerGestures&) =
+ delete;
+ ~WaylandZwpPointerGestures();
+
+ // Init is called by WaylandConnection when its wl_pointer object is
+ // instantiated.
+ void Init();
+
+ private:
+ // zwp_pointer_gesture_pinch_v1_listener
+ static void OnPinchBegin(
+ void* data,
+ struct zwp_pointer_gesture_pinch_v1* zwp_pointer_gesture_pinch_v1,
+ uint32_t serial,
+ uint32_t time,
+ struct wl_surface* surface,
+ uint32_t fingers);
+ static void OnPinchUpdate(
+ void* data,
+ struct zwp_pointer_gesture_pinch_v1* zwp_pointer_gesture_pinch_v1,
+ uint32_t time,
+ wl_fixed_t dx,
+ wl_fixed_t dy,
+ wl_fixed_t scale,
+ wl_fixed_t rotation);
+ static void OnPinchEnd(
+ void* data,
+ struct zwp_pointer_gesture_pinch_v1* zwp_pointer_gesture_pinch_v1,
+ uint32_t serial,
+ uint32_t time,
+ int32_t cancelled);
+
+ wl::Object<zwp_pointer_gestures_v1> obj_;
+ wl::Object<zwp_pointer_gesture_pinch_v1> pinch_;
+ WaylandConnection* const connection_;
+ Delegate* const delegate_;
+};
+
+class WaylandZwpPointerGestures::Delegate {
+ public:
+ virtual void OnPinchEvent(EventType event_type,
+ const gfx::Vector2dF& delta,
+ base::TimeTicks timestamp,
+ int device_id,
+ absl::optional<float> scale = absl::nullopt) = 0;
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZWP_POINTER_GESTURES_H_
diff --git a/chromium/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc b/chromium/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc
index c43f6c212fd..0e5faf3379e 100644
--- a/chromium/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc
+++ b/chromium/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc
@@ -17,6 +17,7 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
+#include "ui/ozone/platform/wayland/host/wayland_event_source.h"
#include "ui/ozone/platform/wayland/host/wayland_pointer.h"
#include "ui/ozone/platform/wayland/host/wayland_popup.h"
#include "ui/ozone/platform/wayland/host/wayland_toplevel_window.h"
@@ -120,11 +121,9 @@ bool XDGPopupWrapperImpl::Initialize(WaylandConnection* connection,
XDGSurfaceWrapperImpl* parent_xdg_surface = nullptr;
// If the parent window is a popup, the surface of that popup must be used as
// a parent.
- if (wl::IsMenuType(wayland_window_->parent_window()->type())) {
- auto* wayland_popup =
- static_cast<WaylandPopup*>(wayland_window_->parent_window());
+ if (auto* parent_popup = wayland_window_->parent_window()->AsWaylandPopup()) {
XDGPopupWrapperImpl* popup =
- static_cast<XDGPopupWrapperImpl*>(wayland_popup->shell_popup());
+ static_cast<XDGPopupWrapperImpl*>(parent_popup->shell_popup());
parent_xdg_surface = popup->xdg_surface_wrapper();
} else {
WaylandToplevelWindow* wayland_surface =
@@ -194,7 +193,9 @@ struct xdg_positioner* XDGPopupWrapperImpl::CreatePositioner(
if (!positioner)
return nullptr;
- auto menu_type = GetMenuTypeForPositioner(connection, parent_window);
+ auto menu_type = GetPopupTypeForPositioner(
+ wayland_window_->type(),
+ connection->event_source()->last_pointer_button_pressed(), parent_window);
// The parent we got must be the topmost in the stack of the same family
// windows.
diff --git a/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h b/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h
index b29e63c4dfe..00990cf8b9c 100644
--- a/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h
+++ b/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h
@@ -8,7 +8,6 @@
#include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h"
#include <cstdint>
-#include <string>
#include "ui/ozone/platform/wayland/common/wayland_object.h"
diff --git a/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h b/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h
index 15d16f7a3b7..920f89a7d99 100644
--- a/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h
+++ b/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h
@@ -26,7 +26,7 @@ class XDGToplevelWrapperImpl : public ShellToplevelWrapper {
XDGToplevelWrapperImpl& operator=(const XDGToplevelWrapperImpl&) = delete;
~XDGToplevelWrapperImpl() override;
- // ShellSurfaceWrapper overrides:
+ // ShellToplevelWrapper overrides:
bool Initialize() override;
void SetMaximized() override;
void UnSetMaximized() override;
diff --git a/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.cc b/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.cc
index a9e657d387b..33c26d7948f 100644
--- a/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.cc
+++ b/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.cc
@@ -28,9 +28,9 @@ ZwpPrimarySelectionDevice::~ZwpPrimarySelectionDevice() = default;
void ZwpPrimarySelectionDevice::SetSelectionSource(
ZwpPrimarySelectionSource* source) {
- DCHECK(source);
- zwp_primary_selection_device_v1_set_selection(
- data_device_.get(), source->data_source(), connection()->serial());
+ auto* data_source = source ? source->data_source() : nullptr;
+ zwp_primary_selection_device_v1_set_selection(data_device_.get(), data_source,
+ connection()->serial());
connection()->ScheduleFlush();
}
diff --git a/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.h b/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.h
index c4d36a2ee51..764d8bae45f 100644
--- a/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.h
+++ b/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_PRIMARY_SELECTION_DEVICE_H_
-#define UI_OZONE_PLATFORM_WAYLAND_HOST_PRIMARY_SELECTION_DEVICE_H_
+#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_ZWP_PRIMARY_SELECTION_DEVICE_H_
+#define UI_OZONE_PLATFORM_WAYLAND_HOST_ZWP_PRIMARY_SELECTION_DEVICE_H_
#include "ui/ozone/platform/wayland/common/wayland_object.h"
#include "ui/ozone/platform/wayland/host/wayland_data_device_base.h"
@@ -48,4 +48,4 @@ class ZwpPrimarySelectionDevice : public WaylandDataDeviceBase {
} // namespace ui
-#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_PRIMARY_SELECTION_DEVICE_H_
+#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_ZWP_PRIMARY_SELECTION_DEVICE_H_
diff --git a/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.h b/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.h
index 8fa4d2f74db..cdb44e50a16 100644
--- a/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.h
+++ b/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_PRIMARY_SELECTION_DEVICE_MANAGER_H_
-#define UI_OZONE_PLATFORM_WAYLAND_HOST_PRIMARY_SELECTION_DEVICE_MANAGER_H_
+#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_ZWP_PRIMARY_SELECTION_DEVICE_MANAGER_H_
+#define UI_OZONE_PLATFORM_WAYLAND_HOST_ZWP_PRIMARY_SELECTION_DEVICE_MANAGER_H_
#include <memory>
@@ -43,4 +43,4 @@ class ZwpPrimarySelectionDeviceManager {
} // namespace ui
-#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_PRIMARY_SELECTION_DEVICE_MANAGER_H_
+#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_ZWP_PRIMARY_SELECTION_DEVICE_MANAGER_H_
diff --git a/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_offer.h b/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_offer.h
index e1b63303f9b..d93dad18d1c 100644
--- a/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_offer.h
+++ b/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_offer.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_PRIMARY_SELECTION_OFFER_H_
-#define UI_OZONE_PLATFORM_WAYLAND_HOST_PRIMARY_SELECTION_OFFER_H_
+#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_ZWP_PRIMARY_SELECTION_OFFER_H_
+#define UI_OZONE_PLATFORM_WAYLAND_HOST_ZWP_PRIMARY_SELECTION_OFFER_H_
#include <string>
@@ -47,4 +47,4 @@ class ZwpPrimarySelectionOffer : public WaylandDataOfferBase {
} // namespace ui
-#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_PRIMARY_SELECTION_OFFER_H_
+#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_ZWP_PRIMARY_SELECTION_OFFER_H_
diff --git a/chromium/ui/ozone/platform/wayland/host/zxdg_popup_v6_wrapper_impl.cc b/chromium/ui/ozone/platform/wayland/host/zxdg_popup_v6_wrapper_impl.cc
index f506f0af5f9..393d03e4908 100644
--- a/chromium/ui/ozone/platform/wayland/host/zxdg_popup_v6_wrapper_impl.cc
+++ b/chromium/ui/ozone/platform/wayland/host/zxdg_popup_v6_wrapper_impl.cc
@@ -16,6 +16,7 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
+#include "ui/ozone/platform/wayland/host/wayland_event_source.h"
#include "ui/ozone/platform/wayland/host/wayland_pointer.h"
#include "ui/ozone/platform/wayland/host/wayland_popup.h"
#include "ui/ozone/platform/wayland/host/wayland_toplevel_window.h"
@@ -121,11 +122,9 @@ bool ZXDGPopupV6WrapperImpl::Initialize(WaylandConnection* connection,
ZXDGSurfaceV6WrapperImpl* parent_xdg_surface = nullptr;
// If the parent window is a popup, the surface of that popup must be used as
// a parent.
- if (wl::IsMenuType(wayland_window_->parent_window()->type())) {
- auto* wayland_popup =
- static_cast<WaylandPopup*>(wayland_window_->parent_window());
+ if (auto* parent_popup = wayland_window_->parent_window()->AsWaylandPopup()) {
ZXDGPopupV6WrapperImpl* popup =
- static_cast<ZXDGPopupV6WrapperImpl*>(wayland_popup->shell_popup());
+ static_cast<ZXDGPopupV6WrapperImpl*>(parent_popup->shell_popup());
parent_xdg_surface = popup->zxdg_surface_v6_wrapper();
} else {
WaylandToplevelWindow* wayland_surface =
@@ -198,7 +197,9 @@ zxdg_positioner_v6* ZXDGPopupV6WrapperImpl::CreatePositioner(
if (!positioner)
return nullptr;
- auto menu_type = GetMenuTypeForPositioner(connection, parent_window);
+ auto menu_type = GetPopupTypeForPositioner(
+ wayland_window_->type(),
+ connection->event_source()->last_pointer_button_pressed(), parent_window);
// The parent we got must be the topmost in the stack of the same family
// windows.
diff --git a/chromium/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h b/chromium/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h
index 4a36633996c..b36842d65e3 100644
--- a/chromium/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h
+++ b/chromium/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h
@@ -8,7 +8,6 @@
#include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h"
#include <cstdint>
-#include <string>
#include "ui/ozone/platform/wayland/common/wayland_object.h"
diff --git a/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc
index f3269c19f0e..c4dfb5df2ba 100644
--- a/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc
+++ b/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -31,7 +31,6 @@
#include "ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.h"
#include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
-#include "ui/ozone/platform/wayland/host/wayland_cursor_factory.h"
#include "ui/ozone/platform/wayland/host/wayland_input_method_context_factory.h"
#include "ui/ozone/platform/wayland/host/wayland_menu_utils.h"
#include "ui/ozone/platform/wayland/host/wayland_output_manager.h"
@@ -59,8 +58,13 @@
#endif
#if BUILDFLAG(USE_GTK)
-#include "ui/gtk/gtk_ui_delegate.h" // nogncheck
-#include "ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.h" //nogncheck
+#include "ui/ozone/platform/wayland/host/linux_ui_delegate_wayland.h" // nogncheck
+#endif
+
+#if defined(OS_CHROMEOS)
+#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
+#else
+#include "ui/ozone/platform/wayland/host/wayland_cursor_factory.h"
#endif
namespace ui {
@@ -174,7 +178,7 @@ class OzonePlatformWayland : public OzonePlatform {
buffer_manager_connector_ = std::make_unique<WaylandBufferManagerConnector>(
connection_->buffer_manager_host());
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#if defined(OS_CHROMEOS)
cursor_factory_ = std::make_unique<BitmapCursorFactoryOzone>();
#else
cursor_factory_ = std::make_unique<WaylandCursorFactory>(connection_.get());
@@ -185,10 +189,8 @@ class OzonePlatformWayland : public OzonePlatform {
supported_buffer_formats_ =
connection_->buffer_manager_host()->GetSupportedBufferFormats();
#if BUILDFLAG(USE_GTK)
- DCHECK(!GtkUiDelegate::instance());
- gtk_ui_delegate_ =
- std::make_unique<GtkUiDelegateWayland>(connection_.get());
- GtkUiDelegate::SetInstance(gtk_ui_delegate_.get());
+ gtk_ui_platform_ =
+ std::make_unique<LinuxUiDelegateWayland>(connection_.get());
#endif
menu_utils_ = std::make_unique<WaylandMenuUtils>(connection_.get());
@@ -287,7 +289,7 @@ class OzonePlatformWayland : public OzonePlatform {
buffer_manager_->AddBindingWaylandBufferManagerGpu(std::move(receiver));
}
- void PostMainMessageLoopStart(
+ void PostCreateMainMessageLoop(
base::OnceCallback<void()> shutdown_cb) override {
DCHECK(connection_);
connection_->SetShutdownCb(std::move(shutdown_cb));
@@ -322,7 +324,7 @@ class OzonePlatformWayland : public OzonePlatform {
DrmRenderNodePathFinder path_finder_;
#if BUILDFLAG(USE_GTK)
- std::unique_ptr<GtkUiDelegateWayland> gtk_ui_delegate_;
+ std::unique_ptr<LinuxUiDelegateWayland> gtk_ui_platform_;
#endif
DISALLOW_COPY_AND_ASSIGN(OzonePlatformWayland);
diff --git a/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.h b/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.h
index ca00bd4b59a..4444daac21a 100644
--- a/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.h
+++ b/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_OZONE_PLATFORM_OZONE_PLATFORM_WAYLAND_H_
-#define UI_OZONE_PLATFORM_OZONE_PLATFORM_WAYLAND_H_
+#ifndef UI_OZONE_PLATFORM_WAYLAND_OZONE_PLATFORM_WAYLAND_H_
+#define UI_OZONE_PLATFORM_WAYLAND_OZONE_PLATFORM_WAYLAND_H_
namespace ui {
@@ -14,4 +14,4 @@ OzonePlatform* CreateOzonePlatformWayland();
} // namespace ui
-#endif // UI_OZONE_PLATFORM_OZONE_PLATFORM_WAYLAND_H_
+#endif // UI_OZONE_PLATFORM_WAYLAND_OZONE_PLATFORM_WAYLAND_H_
diff --git a/chromium/ui/ozone/platform/wayland/test/mock_surface.h b/chromium/ui/ozone/platform/wayland/test/mock_surface.h
index fd682b8fa87..7246a7df315 100644
--- a/chromium/ui/ozone/platform/wayland/test/mock_surface.h
+++ b/chromium/ui/ozone/platform/wayland/test/mock_surface.h
@@ -5,8 +5,6 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_MOCK_SURFACE_H_
#define UI_OZONE_PLATFORM_WAYLAND_TEST_MOCK_SURFACE_H_
-#include <memory>
-#include <utility>
#include <wayland-server-protocol.h>
diff --git a/chromium/ui/ozone/platform/wayland/test/test_data_offer.cc b/chromium/ui/ozone/platform/wayland/test/test_data_offer.cc
index 861e685ae9a..acedb732d37 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_data_offer.cc
+++ b/chromium/ui/ozone/platform/wayland/test/test_data_offer.cc
@@ -21,8 +21,7 @@ namespace {
void WriteDataOnWorkerThread(base::ScopedFD fd,
ui::PlatformClipboard::Data data) {
- if (!base::WriteFileDescriptor(fd.get(), data->front_as<char>(),
- data->size())) {
+ if (!base::WriteFileDescriptor(fd.get(), data->data())) {
LOG(ERROR) << "Failed to write selection data to clipboard.";
}
}
diff --git a/chromium/ui/ozone/platform/wayland/test/test_output.cc b/chromium/ui/ozone/platform/wayland/test/test_output.cc
index e83e5971a8c..59db804bb22 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_output.cc
+++ b/chromium/ui/ozone/platform/wayland/test/test_output.cc
@@ -6,7 +6,7 @@
#include <wayland-server-protocol.h>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace wl {
diff --git a/chromium/ui/ozone/platform/wayland/test/test_output.h b/chromium/ui/ozone/platform/wayland/test/test_output.h
index a44c0157364..4706a47578a 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_output.h
+++ b/chromium/ui/ozone/platform/wayland/test/test_output.h
@@ -8,7 +8,7 @@
#include <cstdint>
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/ozone/platform/wayland/test/global_object.h"
@@ -22,6 +22,7 @@ class TestOutput : public GlobalObject {
const gfx::Rect GetRect() { return rect_; }
void SetRect(const gfx::Rect& rect);
+ int32_t GetScale() const { return scale_; }
void SetScale(int32_t factor);
void Flush();
@@ -33,8 +34,8 @@ class TestOutput : public GlobalObject {
gfx::Rect rect_;
int32_t scale_;
- base::Optional<gfx::Rect> pending_rect_ = base::nullopt;
- base::Optional<int32_t> pending_scale_ = base::nullopt;
+ absl::optional<gfx::Rect> pending_rect_ = absl::nullopt;
+ absl::optional<int32_t> pending_scale_ = absl::nullopt;
DISALLOW_COPY_AND_ASSIGN(TestOutput);
};
diff --git a/chromium/ui/ozone/platform/wayland/test/test_subcompositor.h b/chromium/ui/ozone/platform/wayland/test/test_subcompositor.h
index 45be83b98d8..cc8943bf8b0 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_subcompositor.h
+++ b/chromium/ui/ozone/platform/wayland/test/test_subcompositor.h
@@ -5,7 +5,6 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_SUBCOMPOSITOR_H_
#define UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_SUBCOMPOSITOR_H_
-#include <vector>
#include "base/macros.h"
#include "ui/ozone/platform/wayland/test/global_object.h"
diff --git a/chromium/ui/ozone/platform/wayland/test/test_subsurface.h b/chromium/ui/ozone/platform/wayland/test/test_subsurface.h
index d21f398f9c6..959276efea1 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_subsurface.h
+++ b/chromium/ui/ozone/platform/wayland/test/test_subsurface.h
@@ -7,8 +7,6 @@
#include <wayland-server-protocol.h>
-#include <memory>
-#include <utility>
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/gfx/geometry/point.h"
diff --git a/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc b/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc
index 7cf3193cbc2..6279c728fa6 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc
+++ b/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc
@@ -44,7 +44,7 @@ TestWaylandServerThread::~TestWaylandServerThread() {
Stop();
}
-bool TestWaylandServerThread::Start(uint32_t shell_version) {
+bool TestWaylandServerThread::Start(const ServerConfig& config) {
display_.reset(wl_display_create());
if (!display_)
return false;
@@ -72,14 +72,12 @@ bool TestWaylandServerThread::Start(uint32_t shell_version) {
return false;
if (!seat_.Initialize(display_.get()))
return false;
- if (shell_version == 6) {
+ if (config.shell_version == ShellVersion::kV6) {
if (!zxdg_shell_v6_.Initialize(display_.get()))
return false;
- } else if (shell_version == 7) {
+ } else {
if (!xdg_shell_.Initialize(display_.get()))
return false;
- } else {
- NOTREACHED() << "Unsupported shell version: " << shell_version;
}
if (!zwp_text_input_manager_v1_.Initialize(display_.get()))
return false;
@@ -93,7 +91,7 @@ bool TestWaylandServerThread::Start(uint32_t shell_version) {
base::Thread::Options options;
options.message_pump_factory = base::BindRepeating(
&TestWaylandServerThread::CreateMessagePump, base::Unretained(this));
- if (!base::Thread::StartWithOptions(options))
+ if (!base::Thread::StartWithOptions(std::move(options)))
return false;
setenv("WAYLAND_SOCKET", base::NumberToString(client_fd.release()).c_str(),
diff --git a/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.h b/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.h
index 712ce602bf1..1faeee221cb 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.h
+++ b/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.h
@@ -7,6 +7,7 @@
#include <wayland-server-core.h>
+#include <cstdint>
#include <memory>
#include <vector>
@@ -36,6 +37,16 @@ struct DisplayDeleter {
void operator()(wl_display* display);
};
+// Server configuration related enums and structs.
+enum class ShellVersion { kV6, kStable };
+enum class PrimarySelectionProtocol { kNone, kGtk, kZwp };
+
+struct ServerConfig {
+ ShellVersion shell_version = ShellVersion::kStable;
+ PrimarySelectionProtocol primary_selection_protocol =
+ PrimarySelectionProtocol::kNone;
+};
+
class TestWaylandServerThread : public base::Thread,
base::MessagePumpLibevent::FdWatcher {
public:
@@ -51,7 +62,7 @@ class TestWaylandServerThread : public base::Thread,
// wl_display_connect).
// Instantiates an xdg_shell of version |shell_version|; versions 6 and 7
// (stable) are supported.
- bool Start(uint32_t shell_version);
+ bool Start(const ServerConfig& config);
// Pauses the server thread when it becomes idle.
void Pause();
diff --git a/chromium/ui/ozone/platform/wayland/test/wayland_test.cc b/chromium/ui/ozone/platform/wayland/test/wayland_test.cc
index 5bc45ac1aea..f18836a222f 100644
--- a/chromium/ui/ozone/platform/wayland/test/wayland_test.cc
+++ b/chromium/ui/ozone/platform/wayland/test/wayland_test.cc
@@ -12,6 +12,7 @@
#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
#include "ui/events/ozone/layout/scoped_keyboard_layout_engine.h"
#include "ui/ozone/common/features.h"
+#include "ui/ozone/platform/wayland/host/wayland_event_source.h"
#include "ui/ozone/platform/wayland/host/wayland_output_manager.h"
#include "ui/ozone/platform/wayland/host/wayland_screen.h"
#include "ui/ozone/platform/wayland/test/mock_surface.h"
@@ -68,6 +69,7 @@ void WaylandTest::SetUp() {
ASSERT_TRUE(server_.Start(GetParam()));
ASSERT_TRUE(connection_->Initialize());
+ connection_->event_source()->UseSingleThreadedPollingForTesting();
screen_ = connection_->wayland_output_manager()->CreateWaylandScreen();
EXPECT_CALL(delegate_, OnAcceleratedWidgetAvailable(_))
.WillOnce(SaveArg<0>(&widget_));
@@ -131,7 +133,7 @@ void WaylandTest::SendConfigureEvent(wl::MockXdgSurface* xdg_surface,
// surfaces send other data like states, heights and widths.
// Please note that toplevel surfaces may not exist if the surface was created
// for the popup role.
- if (GetParam() == kXdgShellV6) {
+ if (GetParam().shell_version == wl::ShellVersion::kV6) {
if (xdg_surface->xdg_toplevel()) {
zxdg_toplevel_v6_send_configure(xdg_surface->xdg_toplevel()->resource(),
width, height, states);
diff --git a/chromium/ui/ozone/platform/wayland/test/wayland_test.h b/chromium/ui/ozone/platform/wayland/test/wayland_test.h
index f08e25a4bc3..cc34586cd30 100644
--- a/chromium/ui/ozone/platform/wayland/test/wayland_test.h
+++ b/chromium/ui/ozone/platform/wayland/test/wayland_test.h
@@ -33,12 +33,9 @@ namespace ui {
class ScopedKeyboardLayoutEngine;
class WaylandScreen;
-const uint32_t kXdgShellV6 = 6;
-const uint32_t kXdgShellStable = 7;
-
// WaylandTest is a base class that sets up a display, window, and test server,
// and allows easy synchronization between them.
-class WaylandTest : public ::testing::TestWithParam<uint32_t> {
+class WaylandTest : public ::testing::TestWithParam<wl::ServerConfig> {
public:
WaylandTest();
~WaylandTest() override;
diff --git a/chromium/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
index 77e58e1a6e9..18cd3854799 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
@@ -24,6 +24,7 @@
#include "ui/ozone/platform/wayland/test/wayland_test.h"
using testing::_;
+using testing::Values;
namespace ui {
@@ -54,8 +55,10 @@ class MockSurfaceGpu : public WaylandSurfaceGpu {
}
~MockSurfaceGpu() { buffer_manager_->UnregisterSurface(widget_); }
- MOCK_METHOD2(OnSubmission,
- void(uint32_t buffer_id, const gfx::SwapResult& swap_result));
+ MOCK_METHOD3(OnSubmission,
+ void(uint32_t buffer_id,
+ const gfx::SwapResult& swap_result,
+ gfx::GpuFenceHandle release_fence));
MOCK_METHOD2(OnPresentation,
void(uint32_t buffer_id,
const gfx::PresentationFeedback& feedback));
@@ -496,7 +499,7 @@ TEST_P(WaylandBufferManagerTest, EnsureCorrectOrderOfCallbacks) {
// All the other expectations must come in order.
::testing::InSequence sequence;
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
// wp_presentation must not exist now. This means that the buffer
// manager must send synthetized presentation feedbacks.
@@ -519,7 +522,7 @@ TEST_P(WaylandBufferManagerTest, EnsureCorrectOrderOfCallbacks) {
Sync();
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(1);
@@ -550,7 +553,7 @@ TEST_P(WaylandBufferManagerTest, EnsureCorrectOrderOfCallbacks) {
// Even though, the server send the presentation feeedback, the host manager
// must make sure the order of the submission and presentation callbacks is
// correct. Thus, no callbacks must be received by the MockSurfaceGpu.
- EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _)).Times(0);
+ EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _, _)).Times(0);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
mock_wp_presentation->SendPresentationCallback();
@@ -558,7 +561,7 @@ TEST_P(WaylandBufferManagerTest, EnsureCorrectOrderOfCallbacks) {
Sync();
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
@@ -618,7 +621,7 @@ TEST_P(WaylandBufferManagerTest,
// Commit the first buffer and expect OnSubmission immediately.
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, bounds);
mock_surface->SendFrameCallback();
@@ -636,7 +639,7 @@ TEST_P(WaylandBufferManagerTest,
// Destroy the first buffer, which should trigger submission for the second
// buffer.
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, /*fail=*/false);
mock_surface->DestroyPrevAttachedBuffer();
@@ -658,7 +661,7 @@ TEST_P(WaylandBufferManagerTest,
// Destroy buffer 2, which should trigger OnSubmission for buffer 3, and
// OnPresentation for buffer 1, 2, and 3.
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId3, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId3, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(
mock_surface_gpu,
@@ -727,7 +730,7 @@ TEST_P(WaylandBufferManagerTest,
// All the other expectations must come in order.
::testing::InSequence sequence;
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
@@ -745,7 +748,7 @@ TEST_P(WaylandBufferManagerTest,
Sync();
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
@@ -765,7 +768,7 @@ TEST_P(WaylandBufferManagerTest,
Sync();
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId3, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId3, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
@@ -926,12 +929,7 @@ TEST_P(WaylandBufferManagerTest, TestCommitBufferConditionsAckConfigured) {
: gfx::kNullAcceleratedWidget);
auto widget = temp_window->GetWidget();
- // Subsurface doesn't have an interface for sending configure events.
- // Thus, WaylandAuxiliaryWindow notifies the manager that the window is
- // activated upon creation of the subsurface. Skip calling Show() and call
- // later then.
- if (type != PlatformWindowType::kTooltip)
- temp_window->Show(false);
+ temp_window->Show(false);
Sync();
@@ -958,15 +956,8 @@ TEST_P(WaylandBufferManagerTest, TestCommitBufferConditionsAckConfigured) {
widget, kDmabufBufferId, window_->GetBounds(), window_->GetBounds());
Sync();
- if (type != PlatformWindowType::kTooltip) {
- DCHECK(mock_surface->xdg_surface());
- ActivateSurface(mock_surface->xdg_surface());
- } else {
- // WaylandAuxiliaryWindow uses the focused window as a parent.
- window_->SetPointerFocus(true);
- // See the comment near Show() call above.
- temp_window->Show(false);
- }
+ DCHECK(mock_surface->xdg_surface());
+ ActivateSurface(mock_surface->xdg_surface());
EXPECT_CALL(*mock_surface, Attach(_, _, _)).Times(1);
EXPECT_CALL(*mock_surface, Frame(_)).Times(1);
@@ -1018,7 +1009,7 @@ TEST_P(WaylandBufferManagerTest, AnonymousBufferAttachedAndReleased) {
// All the other expectations must come in order.
::testing::InSequence sequence;
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
@@ -1042,7 +1033,7 @@ TEST_P(WaylandBufferManagerTest, AnonymousBufferAttachedAndReleased) {
false /* fail */);
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(1);
@@ -1067,7 +1058,7 @@ TEST_P(WaylandBufferManagerTest, AnonymousBufferAttachedAndReleased) {
Sync();
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId3, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId3, gfx::SwapResult::SWAP_ACK, _))
.Times(0);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId3, _)).Times(0);
@@ -1076,7 +1067,7 @@ TEST_P(WaylandBufferManagerTest, AnonymousBufferAttachedAndReleased) {
Sync();
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId3, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId3, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId3, _)).Times(1);
@@ -1135,7 +1126,7 @@ TEST_P(WaylandBufferManagerTest, DestroyedWindowNoSubmissionSingleBuffer) {
// All the other expectations must come in order.
::testing::InSequence sequence;
- EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _)).Times(0);
+ EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _, _)).Times(0);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
temp_window.reset();
@@ -1178,7 +1169,7 @@ TEST_P(WaylandBufferManagerTest, DestroyedWindowNoSubmissionMultipleBuffers) {
// All the other expectations must come in order.
::testing::InSequence sequence;
- EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _)).Times(1);
+ EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _, _)).Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(1);
buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, bounds);
@@ -1197,7 +1188,7 @@ TEST_P(WaylandBufferManagerTest, DestroyedWindowNoSubmissionMultipleBuffers) {
Sync();
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(1);
@@ -1209,7 +1200,7 @@ TEST_P(WaylandBufferManagerTest, DestroyedWindowNoSubmissionMultipleBuffers) {
Sync();
- EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _)).Times(0);
+ EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _, _)).Times(0);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
temp_window.reset();
@@ -1245,7 +1236,7 @@ TEST_P(WaylandBufferManagerTest, DestroyBufferCommittedTwiceInARow) {
false /* fail */);
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
@@ -1255,7 +1246,7 @@ TEST_P(WaylandBufferManagerTest, DestroyBufferCommittedTwiceInARow) {
testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
// Can't call OnSubmission until there is a release.
- EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _)).Times(0);
+ EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _, _)).Times(0);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds, bounds);
@@ -1276,7 +1267,7 @@ TEST_P(WaylandBufferManagerTest, DestroyBufferCommittedTwiceInARow) {
// Destroying buffer1 should give us two acks for buffer2.
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK, _))
.Times(2);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(2);
DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
@@ -1309,7 +1300,7 @@ TEST_P(WaylandBufferManagerTest, ReleaseBufferCommittedTwiceInARow) {
false /* fail */);
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
@@ -1320,7 +1311,7 @@ TEST_P(WaylandBufferManagerTest, ReleaseBufferCommittedTwiceInARow) {
auto* wl_buffer1 = mock_surface->attached_buffer();
// Can't call OnSubmission until there is a release.
- EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _)).Times(0);
+ EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _, _)).Times(0);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds, bounds);
@@ -1335,7 +1326,7 @@ TEST_P(WaylandBufferManagerTest, ReleaseBufferCommittedTwiceInARow) {
// Releasing buffer1 should trigger two acks for buffer2.
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK, _))
.Times(2);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(2);
mock_surface->ReleaseBuffer(wl_buffer1);
@@ -1373,7 +1364,7 @@ TEST_P(WaylandBufferManagerTest, ReleaseOrderDifferentToCommitOrder) {
false /* fail */);
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
EXPECT_CALL(*mock_surface, Attach(_, _, _)).Times(1);
@@ -1385,7 +1376,7 @@ TEST_P(WaylandBufferManagerTest, ReleaseOrderDifferentToCommitOrder) {
auto* wl_buffer1 = mock_surface->attached_buffer();
// Can't call OnSubmission until there is a release.
- EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _)).Times(0);
+ EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _, _)).Times(0);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
EXPECT_CALL(*mock_surface, Attach(_, _, _)).Times(2);
@@ -1402,19 +1393,19 @@ TEST_P(WaylandBufferManagerTest, ReleaseOrderDifferentToCommitOrder) {
// Releasing buffer2 can't trigger OnSubmission for buffer3, because
// OnSubmission for buffer2 has not been sent yet.
- EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _)).Times(0);
+ EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _, _)).Times(0);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
mock_surface->ReleaseBuffer(wl_buffer2);
testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
// Releasing buffer1 should trigger acks for both.
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(1);
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId3, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId3, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId3, _)).Times(1);
mock_surface->ReleaseBuffer(wl_buffer1);
@@ -1451,7 +1442,7 @@ TEST_P(WaylandBufferManagerTest,
false /* fail */);
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
ASSERT_TRUE(!connection_->presentation());
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
@@ -1471,7 +1462,7 @@ TEST_P(WaylandBufferManagerTest,
testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
testing::Mock::VerifyAndClearExpectations(mock_surface);
- EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _)).Times(0);
+ EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _, _)).Times(0);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
mock_surface->SendFrameCallback();
@@ -1494,7 +1485,7 @@ TEST_P(WaylandBufferManagerTest,
testing::Mock::VerifyAndClearExpectations(mock_surface);
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(1);
@@ -1515,7 +1506,7 @@ TEST_P(WaylandBufferManagerTest,
// sends the submission callback, the compositor is not going to release a
// buffer as it was the same buffer submitted more than once.
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(1);
@@ -1534,7 +1525,7 @@ TEST_P(WaylandBufferManagerTest,
testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
testing::Mock::VerifyAndClearExpectations(mock_surface);
- EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _)).Times(0);
+ EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _, _)).Times(0);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
EXPECT_CALL(*mock_surface, Attach(_, _, _)).Times(0);
@@ -1551,7 +1542,7 @@ TEST_P(WaylandBufferManagerTest,
// If we commit another buffer now, the manager host must not automatically
// trigger OnSubmission and OnPresentation callbacks.
- EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _)).Times(0);
+ EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _, _)).Times(0);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
EXPECT_CALL(*mock_surface, Attach(_, _, _)).Times(1);
@@ -1570,7 +1561,7 @@ TEST_P(WaylandBufferManagerTest,
// Now, they must be triggered once the buffer is released.
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
@@ -1606,7 +1597,7 @@ TEST_P(WaylandBufferManagerTest, OnSubmissionCalledForSingleBuffer) {
false /* fail */);
EXPECT_CALL(mock_surface_gpu,
- OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
+ OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
@@ -1683,9 +1674,11 @@ TEST_P(WaylandBufferManagerTest, RootSurfaceIsCommittedLast) {
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandBufferManagerTest,
- ::testing::Values(kXdgShellStable));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
WaylandBufferManagerTest,
- ::testing::Values(kXdgShellV6));
+ Values(wl::ServerConfig{
+ .shell_version = wl::ShellVersion::kV6}));
} // namespace ui
diff --git a/chromium/ui/ozone/platform/windows/windows_surface_factory.h b/chromium/ui/ozone/platform/windows/windows_surface_factory.h
index 645352d0f29..82002742549 100644
--- a/chromium/ui/ozone/platform/windows/windows_surface_factory.h
+++ b/chromium/ui/ozone/platform/windows/windows_surface_factory.h
@@ -8,7 +8,6 @@
#include <memory>
#include <vector>
-#include "base/files/file_path.h"
#include "base/macros.h"
#include "ui/ozone/public/gl_ozone.h"
#include "ui/ozone/public/surface_factory_ozone.h"
diff --git a/chromium/ui/ozone/platform/windows/windows_window_manager.h b/chromium/ui/ozone/platform/windows/windows_window_manager.h
index a11546c88f7..be35c4cbd1f 100644
--- a/chromium/ui/ozone/platform/windows/windows_window_manager.h
+++ b/chromium/ui/ozone/platform/windows/windows_window_manager.h
@@ -7,10 +7,7 @@
#include <stdint.h>
-#include <memory>
-
#include "base/containers/id_map.h"
-#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "ui/gfx/native_widget_types.h"
diff --git a/chromium/ui/ozone/platform/x11/BUILD.gn b/chromium/ui/ozone/platform/x11/BUILD.gn
index 0d6c78ccd65..4b2643f4a73 100644
--- a/chromium/ui/ozone/platform/x11/BUILD.gn
+++ b/chromium/ui/ozone/platform/x11/BUILD.gn
@@ -3,7 +3,6 @@
# found in the LICENSE file.
import("//build/config/chromeos/ui_mode.gni")
-import("//build/config/linux/gtk/gtk.gni")
import("//gpu/vulkan/features.gni")
import("//ui/base/ui_features.gni")
@@ -29,6 +28,8 @@ source_set("x11") {
"x11_clipboard_ozone.h",
"x11_global_shortcut_listener_ozone.cc",
"x11_global_shortcut_listener_ozone.h",
+ "x11_keyboard_hook_ozone.cc",
+ "x11_keyboard_hook_ozone.h",
"x11_menu_utils.cc",
"x11_menu_utils.h",
"x11_screen_ozone.cc",
@@ -90,10 +91,6 @@ source_set("x11") {
deps += [ "//gpu/vulkan/x" ]
}
- if (use_gtk) {
- deps += [ "//ui/gtk/x" ]
- }
-
if (use_xkbcommon) {
configs += [ "//ui/events/ozone/layout:xkbcommon" ]
}
diff --git a/chromium/ui/ozone/platform/x11/DEPS b/chromium/ui/ozone/platform/x11/DEPS
index 3d70447f3fe..3b6346a6153 100644
--- a/chromium/ui/ozone/platform/x11/DEPS
+++ b/chromium/ui/ozone/platform/x11/DEPS
@@ -1,6 +1,4 @@
include_rules = [
"+ui/base/x",
"+ui/base",
- "+ui/gtk/gtk_ui_delegate.h",
- "+ui/gtk/x/gtk_ui_delegate_x11.h",
]
diff --git a/chromium/ui/ozone/platform/x11/gl_egl_utility_x11.cc b/chromium/ui/ozone/platform/x11/gl_egl_utility_x11.cc
index d5612033adc..387e275450b 100644
--- a/chromium/ui/ozone/platform/x11/gl_egl_utility_x11.cc
+++ b/chromium/ui/ozone/platform/x11/gl_egl_utility_x11.cc
@@ -42,13 +42,4 @@ bool GLEGLUtilityX11::HasVisualManager() {
return true;
}
-bool GLEGLUtilityX11::UpdateVisualsOnGpuInfoChanged(
- bool software_rendering,
- uint32_t default_visual_id,
- uint32_t transparent_visual_id) {
- return ui::UpdateVisualsOnGpuInfoChanged(
- software_rendering, static_cast<x11::VisualId>(default_visual_id),
- static_cast<x11::VisualId>(transparent_visual_id));
-}
-
} // namespace ui
diff --git a/chromium/ui/ozone/platform/x11/gl_egl_utility_x11.h b/chromium/ui/ozone/platform/x11/gl_egl_utility_x11.h
index 1ca2ddf3878..da5e29682f5 100644
--- a/chromium/ui/ozone/platform/x11/gl_egl_utility_x11.h
+++ b/chromium/ui/ozone/platform/x11/gl_egl_utility_x11.h
@@ -28,9 +28,6 @@ class GLEGLUtilityX11 : public PlatformGLEGLUtility {
gfx::GpuExtraInfo& gpu_extra_info) const override;
bool X11DoesVisualHaveAlphaForTest() const override;
bool HasVisualManager() override;
- bool UpdateVisualsOnGpuInfoChanged(bool software_rendering,
- uint32_t default_visual_id,
- uint32_t transparent_visual_id) override;
};
} // namespace ui
diff --git a/chromium/ui/ozone/platform/x11/gl_surface_egl_readback_x11.cc b/chromium/ui/ozone/platform/x11/gl_surface_egl_readback_x11.cc
index ea0e2ec3b42..c76733fc1dd 100644
--- a/chromium/ui/ozone/platform/x11/gl_surface_egl_readback_x11.cc
+++ b/chromium/ui/ozone/platform/x11/gl_surface_egl_readback_x11.cc
@@ -4,6 +4,7 @@
#include "ui/ozone/platform/x11/gl_surface_egl_readback_x11.h"
+#include "base/logging.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkPixmap.h"
#include "ui/base/x/x11_util.h"
diff --git a/chromium/ui/ozone/platform/x11/ozone_platform_x11.cc b/chromium/ui/ozone/platform/x11/ozone_platform_x11.cc
index 5a9ed84fc90..fda67f30e2f 100644
--- a/chromium/ui/ozone/platform/x11/ozone_platform_x11.cc
+++ b/chromium/ui/ozone/platform/x11/ozone_platform_x11.cc
@@ -22,6 +22,7 @@
#include "ui/base/dragdrop/os_exchange_data_provider_factory.h"
#include "ui/base/dragdrop/os_exchange_data_provider_factory_ozone.h"
#include "ui/base/ime/linux/linux_input_method_context_factory.h"
+#include "ui/base/linux/linux_ui_delegate.h"
#include "ui/base/x/x11_cursor_factory.h"
#include "ui/base/x/x11_util.h"
#include "ui/display/fake/fake_display_delegate.h"
@@ -36,6 +37,7 @@
#include "ui/ozone/platform/x11/gl_egl_utility_x11.h"
#include "ui/ozone/platform/x11/x11_clipboard_ozone.h"
#include "ui/ozone/platform/x11/x11_global_shortcut_listener_ozone.h"
+#include "ui/ozone/platform/x11/x11_keyboard_hook_ozone.h"
#include "ui/ozone/platform/x11/x11_menu_utils.h"
#include "ui/ozone/platform/x11/x11_screen_ozone.h"
#include "ui/ozone/platform/x11/x11_surface_factory.h"
@@ -57,29 +59,23 @@
#include "ui/ozone/platform/x11/x11_os_exchange_data_provider_ozone.h"
#endif
-#if BUILDFLAG(USE_GTK)
-#include "ui/gtk/gtk_ui_delegate.h" // nogncheck
-#include "ui/gtk/x/gtk_ui_delegate_x11.h" // nogncheck
-#endif
-
-#if BUILDFLAG(USE_XKBCOMMON)
-#include "ui/events/ozone/layout/xkb/xkb_evdev_codes.h"
-#include "ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h"
-#else
-#include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
-#endif
-
namespace ui {
namespace {
+class LinuxUiDelegateX11 : public LinuxUiDelegate {
+ public:
+ ~LinuxUiDelegateX11() override = default;
+
+ // LinuxUiDelegate:
+ LinuxUiBackend GetBackend() const override { return LinuxUiBackend::kX11; }
+};
+
// Singleton OzonePlatform implementation for X11 platform.
class OzonePlatformX11 : public OzonePlatform,
public ui::OSExchangeDataProviderFactoryOzone {
public:
- OzonePlatformX11() {
- SetInstance(this);
- }
+ OzonePlatformX11() { SetInstance(this); }
~OzonePlatformX11() override = default;
@@ -167,6 +163,20 @@ class OzonePlatformX11 : public OzonePlatform,
return global_shortcut_listener_.get();
}
+ std::unique_ptr<PlatformKeyboardHook> CreateKeyboardHook(
+ PlatformKeyboardHookTypes type,
+ base::RepeatingCallback<void(KeyEvent* event)> callback,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
+ gfx::AcceleratedWidget accelerated_widget) override {
+ switch (type) {
+ case PlatformKeyboardHookTypes::kModifier:
+ return std::make_unique<X11KeyboardHookOzone>(
+ std::move(dom_codes), std::move(callback), accelerated_widget);
+ case PlatformKeyboardHookTypes::kMedia:
+ return nullptr;
+ }
+ }
+
std::unique_ptr<OSExchangeDataProvider> CreateProvider() override {
#if BUILDFLAG(IS_CHROMEOS_ASH)
return std::make_unique<OSExchangeDataProviderNonBacked>();
@@ -227,24 +237,15 @@ class OzonePlatformX11 : public OzonePlatform,
cursor_factory_ = std::make_unique<X11CursorFactory>();
gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost());
-#if BUILDFLAG(USE_XKBCOMMON)
- keyboard_layout_engine_ =
- std::make_unique<XkbKeyboardLayoutEngine>(xkb_evdev_code_converter_);
- // TODO(nickdiego): debugging..
+ // TODO(crbug.com/987939): Support XKB.
keyboard_layout_engine_ = std::make_unique<StubKeyboardLayoutEngine>();
-#else
- keyboard_layout_engine_ = std::make_unique<StubKeyboardLayoutEngine>();
-#endif
KeyboardLayoutEngineManager::SetKeyboardLayoutEngine(
keyboard_layout_engine_.get());
TouchFactory::SetTouchDeviceListFromCommandLine();
#if BUILDFLAG(USE_GTK)
- DCHECK(!GtkUiDelegate::instance());
- gtk_ui_delegate_ =
- std::make_unique<GtkUiDelegateX11>(x11::Connection::Get());
- GtkUiDelegate::SetInstance(gtk_ui_delegate_.get());
+ linux_ui_delegate_ = std::make_unique<LinuxUiDelegateX11>();
#endif
menu_utils_ = std::make_unique<X11MenuUtils>();
@@ -275,7 +276,7 @@ class OzonePlatformX11 : public OzonePlatform,
std::make_unique<X11SurfaceFactory>(std::move(connection));
}
- void PostMainMessageLoopStart(
+ void PostCreateMainMessageLoop(
base::OnceCallback<void()> shutdown_cb) override {
// Installs the X11 error handlers for the UI process after the
// main message loop has started. This will allow us to exit cleanly
@@ -309,10 +310,6 @@ class OzonePlatformX11 : public OzonePlatform,
bool common_initialized_ = false;
-#if BUILDFLAG(USE_XKBCOMMON)
- XkbEvdevCodes xkb_evdev_code_converter_;
-#endif
-
// Objects in the UI process.
std::unique_ptr<KeyboardLayoutEngine> keyboard_layout_engine_;
std::unique_ptr<OverlayManagerOzone> overlay_manager_;
@@ -332,7 +329,7 @@ class OzonePlatformX11 : public OzonePlatform,
std::unique_ptr<X11EventSource> event_source_;
#if BUILDFLAG(USE_GTK)
- std::unique_ptr<GtkUiDelegate> gtk_ui_delegate_;
+ std::unique_ptr<LinuxUiDelegate> linux_ui_delegate_;
#endif
DISALLOW_COPY_AND_ASSIGN(OzonePlatformX11);
diff --git a/chromium/ui/ozone/platform/x11/x11_clipboard_ozone.cc b/chromium/ui/ozone/platform/x11/x11_clipboard_ozone.cc
index aee9ba9eabf..49b3c88f310 100644
--- a/chromium/ui/ozone/platform/x11/x11_clipboard_ozone.cc
+++ b/chromium/ui/ozone/platform/x11/x11_clipboard_ozone.cc
@@ -69,9 +69,9 @@ bool X11ClipboardOzone::IsSelectionOwner(ClipboardBuffer buffer) {
return helper_->IsSelectionOwner(buffer);
}
-void X11ClipboardOzone::SetSequenceNumberUpdateCb(
- PlatformClipboard::SequenceNumberUpdateCb cb) {
- update_sequence_cb_ = std::move(cb);
+void X11ClipboardOzone::SetClipboardDataChangedCallback(
+ ClipboardDataChangedCallback data_changed_callback) {
+ clipboard_changed_callback_ = std::move(data_changed_callback);
}
bool X11ClipboardOzone::IsSelectionBufferAvailable() const {
@@ -79,8 +79,8 @@ bool X11ClipboardOzone::IsSelectionBufferAvailable() const {
}
void X11ClipboardOzone::OnSelectionChanged(ClipboardBuffer buffer) {
- if (update_sequence_cb_)
- update_sequence_cb_.Run(buffer);
+ if (clipboard_changed_callback_)
+ clipboard_changed_callback_.Run(buffer);
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/x11/x11_clipboard_ozone.h b/chromium/ui/ozone/platform/x11/x11_clipboard_ozone.h
index 1c8986e275a..183b30ef259 100644
--- a/chromium/ui/ozone/platform/x11/x11_clipboard_ozone.h
+++ b/chromium/ui/ozone/platform/x11/x11_clipboard_ozone.h
@@ -44,8 +44,8 @@ class X11ClipboardOzone : public PlatformClipboard {
ClipboardBuffer buffer,
PlatformClipboard::GetMimeTypesClosure callback) override;
bool IsSelectionOwner(ClipboardBuffer buffer) override;
- void SetSequenceNumberUpdateCb(
- PlatformClipboard::SequenceNumberUpdateCb cb) override;
+ void SetClipboardDataChangedCallback(
+ ClipboardDataChangedCallback data_changed_callback) override;
bool IsSelectionBufferAvailable() const override;
private:
@@ -53,8 +53,7 @@ class X11ClipboardOzone : public PlatformClipboard {
const std::unique_ptr<XClipboardHelper> helper_;
- // Notifies whenever clipboard sequence number is changed.
- PlatformClipboard::SequenceNumberUpdateCb update_sequence_cb_;
+ ClipboardDataChangedCallback clipboard_changed_callback_;
};
} // namespace ui
diff --git a/chromium/ui/ozone/platform/x11/x11_keyboard_hook_ozone.cc b/chromium/ui/ozone/platform/x11/x11_keyboard_hook_ozone.cc
new file mode 100644
index 00000000000..69da84a41f3
--- /dev/null
+++ b/chromium/ui/ozone/platform/x11/x11_keyboard_hook_ozone.cc
@@ -0,0 +1,24 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/x11/x11_keyboard_hook_ozone.h"
+
+namespace ui {
+
+X11KeyboardHookOzone::X11KeyboardHookOzone(
+ absl::optional<base::flat_set<DomCode>> dom_codes,
+ BaseKeyboardHook::KeyEventCallback callback,
+ gfx::AcceleratedWidget accelerated_widget)
+ : BaseKeyboardHook(std::move(dom_codes), std::move(callback)),
+ XKeyboardHook(accelerated_widget) {
+ RegisterHook(this->dom_codes());
+}
+
+X11KeyboardHookOzone::~X11KeyboardHookOzone() = default;
+
+bool X11KeyboardHookOzone::IsKeyLocked(DomCode dom_code) const {
+ return BaseKeyboardHook::IsKeyLocked(dom_code);
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/x11/x11_keyboard_hook_ozone.h b/chromium/ui/ozone/platform/x11/x11_keyboard_hook_ozone.h
new file mode 100644
index 00000000000..830ac7277fd
--- /dev/null
+++ b/chromium/ui/ozone/platform/x11/x11_keyboard_hook_ozone.h
@@ -0,0 +1,29 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_X11_X11_KEYBOARD_HOOK_OZONE_H_
+#define UI_OZONE_PLATFORM_X11_X11_KEYBOARD_HOOK_OZONE_H_
+
+#include "ui/base/x/x11_keyboard_hook.h"
+#include "ui/ozone/common/base_keyboard_hook.h"
+
+namespace ui {
+
+class X11KeyboardHookOzone : public BaseKeyboardHook, public XKeyboardHook {
+ public:
+ X11KeyboardHookOzone(absl::optional<base::flat_set<DomCode>> dom_codes,
+ BaseKeyboardHook::KeyEventCallback callback,
+ gfx::AcceleratedWidget accelerated_widget);
+ X11KeyboardHookOzone(const X11KeyboardHookOzone&) = delete;
+ X11KeyboardHookOzone& operator=(const X11KeyboardHookOzone&) = delete;
+ ~X11KeyboardHookOzone() override;
+
+ protected:
+ // PlatformKeyboardHook:
+ bool IsKeyLocked(DomCode dom_code) const override;
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_X11_X11_KEYBOARD_HOOK_OZONE_H_
diff --git a/chromium/ui/ozone/platform/x11/x11_screen_ozone.cc b/chromium/ui/ozone/platform/x11/x11_screen_ozone.cc
index 5e70823134f..7b3ab857934 100644
--- a/chromium/ui/ozone/platform/x11/x11_screen_ozone.cc
+++ b/chromium/ui/ozone/platform/x11/x11_screen_ozone.cc
@@ -6,7 +6,7 @@
#include "ui/base/linux/linux_desktop.h"
#include "ui/base/x/x11_idle_query.h"
-#include "ui/base/x/x11_screensaver_window_finder.h"
+#include "ui/base/x/x11_screensaver.h"
#include "ui/base/x/x11_util.h"
#include "ui/display/display_finder.h"
#include "ui/display/util/display_util.h"
@@ -57,14 +57,14 @@ display::Display X11ScreenOzone::GetDisplayForAcceleratedWidget(
}
gfx::Point X11ScreenOzone::GetCursorScreenPoint() const {
- base::Optional<gfx::Point> point_in_pixels;
+ absl::optional<gfx::Point> point_in_pixels;
if (ui::X11EventSource::HasInstance()) {
point_in_pixels = ui::X11EventSource::GetInstance()
->GetRootCursorLocationFromCurrentEvent();
}
if (!point_in_pixels) {
// This call is expensive so we explicitly only call it when
- // |point_in_pixels| is not set. We note that base::Optional::value_or()
+ // |point_in_pixels| is not set. We note that absl::optional::value_or()
// would cause it to be called regardless.
point_in_pixels = GetCursorLocation();
}
@@ -111,7 +111,7 @@ void X11ScreenOzone::SetScreenSaverSuspended(bool suspend) {
bool X11ScreenOzone::IsScreenSaverActive() const {
// Usually the screensaver is used to lock the screen.
- return ScreensaverWindowFinder::ScreensaverWindowExists();
+ return IsXScreensaverActive();
}
base::TimeDelta X11ScreenOzone::CalculateIdleTime() const {
@@ -134,8 +134,6 @@ std::string X11ScreenOzone::GetCurrentWorkspace() {
base::Value X11ScreenOzone::GetGpuExtraInfoAsListValue(
const gfx::GpuExtraInfo& gpu_extra_info) {
auto result = GetDesktopEnvironmentInfoAsListValue();
- StoreGpuExtraInfoIntoListValue(gpu_extra_info.system_visual,
- gpu_extra_info.rgba_visual, result);
StorePlatformNameIntoListValue(result, "x11");
return result;
}
diff --git a/chromium/ui/ozone/platform/x11/x11_surface_factory.cc b/chromium/ui/ozone/platform/x11/x11_surface_factory.cc
index 698327d3489..4fd928c615f 100644
--- a/chromium/ui/ozone/platform/x11/x11_surface_factory.cc
+++ b/chromium/ui/ozone/platform/x11/x11_surface_factory.cc
@@ -123,8 +123,7 @@ GLOzone* X11SurfaceFactory::GetGLOzone(
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanImplementation>
X11SurfaceFactory::CreateVulkanImplementation(bool use_swiftshader,
- bool allow_protected_memory,
- bool enforce_protected_memory) {
+ bool allow_protected_memory) {
return std::make_unique<gpu::VulkanImplementationX11>(use_swiftshader);
}
#endif
@@ -148,7 +147,7 @@ scoped_refptr<gfx::NativePixmap> X11SurfaceFactory::CreateNativePixmap(
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- base::Optional<gfx::Size> framebuffer_size) {
+ absl::optional<gfx::Size> framebuffer_size) {
scoped_refptr<gfx::NativePixmapDmaBuf> pixmap;
auto buffer = ui::GpuMemoryBufferSupportX11::GetInstance()->CreateBuffer(
format, size, usage);
diff --git a/chromium/ui/ozone/platform/x11/x11_surface_factory.h b/chromium/ui/ozone/platform/x11/x11_surface_factory.h
index 7600c923269..2550d0c6cdb 100644
--- a/chromium/ui/ozone/platform/x11/x11_surface_factory.h
+++ b/chromium/ui/ozone/platform/x11/x11_surface_factory.h
@@ -29,8 +29,7 @@ class X11SurfaceFactory : public SurfaceFactoryOzone {
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanImplementation> CreateVulkanImplementation(
bool use_swiftshader,
- bool allow_protected_memory,
- bool enforce_protected_memory) override;
+ bool allow_protected_memory) override;
#endif
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
gfx::AcceleratedWidget widget) override;
@@ -40,7 +39,7 @@ class X11SurfaceFactory : public SurfaceFactoryOzone {
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- base::Optional<gfx::Size> framebuffer_size = base::nullopt) override;
+ absl::optional<gfx::Size> framebuffer_size = absl::nullopt) override;
void CreateNativePixmapAsync(gfx::AcceleratedWidget widget,
VkDevice vk_device,
gfx::Size size,
diff --git a/chromium/ui/ozone/platform_constructor_list.h b/chromium/ui/ozone/platform_constructor_list.h
index e103ab65d65..5600af0b6a7 100644
--- a/chromium/ui/ozone/platform_constructor_list.h
+++ b/chromium/ui/ozone/platform_constructor_list.h
@@ -5,7 +5,6 @@
#ifndef UI_OZONE_PLATFORM_CONSTRUCTOR_LIST_H_
#define UI_OZONE_PLATFORM_CONSTRUCTOR_LIST_H_
-#include <memory>
#include "ui/ozone/platform_list.h"
diff --git a/chromium/ui/ozone/public/gpu_platform_support_host.cc b/chromium/ui/ozone/public/gpu_platform_support_host.cc
index 31e79ccbfd8..5b7e18f82eb 100644
--- a/chromium/ui/ozone/public/gpu_platform_support_host.cc
+++ b/chromium/ui/ozone/public/gpu_platform_support_host.cc
@@ -18,7 +18,7 @@ class StubGpuPlatformSupportHost : public GpuPlatformSupportHost {
void OnGpuServiceLaunched(
int host_id,
scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> process_host_runner,
GpuHostBindInterfaceCallback binder,
GpuHostTerminateCallback terminate_callback) override {}
};
diff --git a/chromium/ui/ozone/public/gpu_platform_support_host.h b/chromium/ui/ozone/public/gpu_platform_support_host.h
index 0077b2574b2..f7a0c566f25 100644
--- a/chromium/ui/ozone/public/gpu_platform_support_host.h
+++ b/chromium/ui/ozone/public/gpu_platform_support_host.h
@@ -39,11 +39,12 @@ class COMPONENT_EXPORT(OZONE_BASE) GpuPlatformSupportHost {
virtual void OnChannelDestroyed(int host_id) = 0;
// Called when the GPU service is launched.
- // Called from the browser IO thread.
+ // Called from the browser IO thread if ProcessHostOnUI is disabled, otherwise
+ // called on the browser UI thread.
virtual void OnGpuServiceLaunched(
int host_id,
- scoped_refptr<base::SingleThreadTaskRunner> host_runner,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> ui_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> process_host_runner,
GpuHostBindInterfaceCallback binder,
GpuHostTerminateCallback terminate_callback) = 0;
};
diff --git a/chromium/ui/ozone/public/input_controller.cc b/chromium/ui/ozone/public/input_controller.cc
index 35fdf8c9a06..e6e3e437084 100644
--- a/chromium/ui/ozone/public/input_controller.cc
+++ b/chromium/ui/ozone/public/input_controller.cc
@@ -9,6 +9,7 @@
#include "base/callback.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "ui/events/devices/stylus_state.h"
namespace ui {
@@ -66,6 +67,9 @@ class StubInputController : public InputController {
void SetInternalTouchpadEnabled(bool enabled) override {}
bool IsInternalTouchpadEnabled() const override { return false; }
void SetTouchscreensEnabled(bool enabled) override {}
+ void GetStylusSwitchState(GetStylusSwitchStateReply reply) override {
+ std::move(reply).Run(ui::StylusState::REMOVED);
+ }
void SetInternalKeyboardFilter(bool enable_filter,
std::vector<DomCode> allowed_keys) override {}
void GetGesturePropertiesService(
diff --git a/chromium/ui/ozone/public/input_controller.h b/chromium/ui/ozone/public/input_controller.h
index c18ba9c72ef..eb4e575cac5 100644
--- a/chromium/ui/ozone/public/input_controller.h
+++ b/chromium/ui/ozone/public/input_controller.h
@@ -22,6 +22,10 @@ class TimeDelta;
}
namespace ui {
+enum class StylusState;
+} // namespace ui
+
+namespace ui {
enum class DomCode;
@@ -37,6 +41,7 @@ class COMPONENT_EXPORT(OZONE_BASE) InputController {
// TODO(sky): convert this to value once mojo supports move for vectors.
using GetTouchEventLogReply =
base::OnceCallback<void(const std::vector<base::FilePath>&)>;
+ using GetStylusSwitchStateReply = base::OnceCallback<void(ui::StylusState)>;
InputController() {}
virtual ~InputController() {}
@@ -105,6 +110,11 @@ class COMPONENT_EXPORT(OZONE_BASE) InputController {
virtual void SetTouchscreensEnabled(bool enabled) = 0;
+ // Find out whether stylus is in its garage; may trigger callback
+ // immediately on platforms where this cannot exist, otherwise
+ // this is be an async reply.
+ virtual void GetStylusSwitchState(GetStylusSwitchStateReply reply) = 0;
+
// Controls vibration for the gamepad device with the corresponding |id|.
// |amplitude| determines the strength of the vibration, where 0 is no
// vibration and 255 is maximum vibration, and |duration_millis|
diff --git a/chromium/ui/ozone/public/mojom/wayland/wayland_buffer_manager.mojom b/chromium/ui/ozone/public/mojom/wayland/wayland_buffer_manager.mojom
index bf5e10f9eb2..b914c743d32 100644
--- a/chromium/ui/ozone/public/mojom/wayland/wayland_buffer_manager.mojom
+++ b/chromium/ui/ozone/public/mojom/wayland/wayland_buffer_manager.mojom
@@ -8,6 +8,7 @@ import "mojo/public/mojom/base/file_path.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
import "ui/gfx/mojom/accelerated_widget.mojom";
import "ui/gfx/mojom/buffer_types.mojom";
+import "ui/gfx/mojom/gpu_fence_handle.mojom";
import "ui/gfx/mojom/presentation_feedback.mojom";
import "ui/gfx/mojom/swap_result.mojom";
import "ui/ozone/public/mojom/wayland/wayland_overlay_config.mojom";
@@ -102,7 +103,8 @@ interface WaylandBufferManagerGpu {
// Signals about swap completion.
OnSubmission(gfx.mojom.AcceleratedWidget widget,
uint32 buffer_id,
- gfx.mojom.SwapResult swap_result);
+ gfx.mojom.SwapResult swap_result,
+ gfx.mojom.GpuFenceHandle? release_fence_handle);
// Signals about presentation.
OnPresentation(gfx.mojom.AcceleratedWidget widget,
diff --git a/chromium/ui/ozone/public/overlay_surface_candidate.h b/chromium/ui/ozone/public/overlay_surface_candidate.h
index 46b7e85d7f6..1df0fe3f6e7 100644
--- a/chromium/ui/ozone/public/overlay_surface_candidate.h
+++ b/chromium/ui/ozone/public/overlay_surface_candidate.h
@@ -31,8 +31,8 @@ class COMPONENT_EXPORT(OZONE_BASE) OverlaySurfaceCandidate {
~OverlaySurfaceCandidate();
OverlaySurfaceCandidate& operator=(const OverlaySurfaceCandidate& other);
- // Note that |clip_rect|, |is_clipped|, |overlay_handled| and |native_pixmap|
- // are *not* used as part of the comparison.
+ // Note that |clip_rect|, |overlay_handled| and |native_pixmap| are *not* used
+ // as part of the comparison.
bool operator<(const OverlaySurfaceCandidate& other) const;
// Transformation to apply to layer during composition.
@@ -50,15 +50,14 @@ class COMPONENT_EXPORT(OZONE_BASE) OverlaySurfaceCandidate {
gfx::RectF display_rect;
// Crop within the buffer to be placed inside |display_rect|.
gfx::RectF crop_rect;
- // Clip rect in the target content space after composition.
- gfx::Rect clip_rect;
- // If the quad is clipped after composition.
- bool is_clipped = false;
+ // If the quad is clipped, the clip rect in the target content space after
+ // composition.
+ absl::optional<gfx::Rect> clip_rect;
// If the quad doesn't require blending.
bool is_opaque = false;
// Optionally contains a pointer to the NativePixmap corresponding to this
// candidate.
- scoped_refptr<gfx::NativePixmap> native_pixmap = nullptr;
+ scoped_refptr<gfx::NativePixmap> native_pixmap;
// A unique ID corresponding to |native_pixmap|. The ID is not reused even if
// |native_pixmap| is destroyed. Zero if |native_pixmap| is null.
// TODO(samans): This will not be necessary once Ozone/DRM not longer uses a
diff --git a/chromium/ui/ozone/public/ozone_gpu_test_helper.h b/chromium/ui/ozone/public/ozone_gpu_test_helper.h
index 09f70d66c17..98d6fbe71ab 100644
--- a/chromium/ui/ozone/public/ozone_gpu_test_helper.h
+++ b/chromium/ui/ozone/public/ozone_gpu_test_helper.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_OZONE_PUBLIC_OZONE_GPU_THREAD_HELPER_H_
-#define UI_OZONE_PUBLIC_OZONE_GPU_THREAD_HELPER_H_
+#ifndef UI_OZONE_PUBLIC_OZONE_GPU_TEST_HELPER_H_
+#define UI_OZONE_PUBLIC_OZONE_GPU_TEST_HELPER_H_
#include <memory>
@@ -42,4 +42,4 @@ class COMPONENT_EXPORT(OZONE) OzoneGpuTestHelper {
} // namespace ui
-#endif // UI_OZONE_PUBLIC_OZONE_GPU_THREAD_HELPER_H_
+#endif // UI_OZONE_PUBLIC_OZONE_GPU_TEST_HELPER_H_
diff --git a/chromium/ui/ozone/public/ozone_platform.cc b/chromium/ui/ozone/public/ozone_platform.cc
index 98cfa91306c..f04aca77a3c 100644
--- a/chromium/ui/ozone/public/ozone_platform.cc
+++ b/chromium/ui/ozone/public/ozone_platform.cc
@@ -11,6 +11,7 @@
#include "base/no_destructor.h"
#include "base/trace_event/trace_event.h"
#include "ui/events/devices/device_data_manager.h"
+#include "ui/ozone/common/base_keyboard_hook.h"
#include "ui/ozone/platform_object.h"
#include "ui/ozone/platform_selection.h"
#include "ui/ozone/public/platform_global_shortcut_listener.h"
@@ -115,6 +116,20 @@ OzonePlatform::GetPlatformGlobalShortcutListener(
return nullptr;
}
+std::unique_ptr<PlatformKeyboardHook> OzonePlatform::CreateKeyboardHook(
+ PlatformKeyboardHookTypes type,
+ base::RepeatingCallback<void(KeyEvent* event)> callback,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
+ gfx::AcceleratedWidget accelerated_widget) {
+ switch (type) {
+ case PlatformKeyboardHookTypes::kModifier:
+ return std::make_unique<BaseKeyboardHook>(std::move(dom_codes),
+ std::move(callback));
+ case PlatformKeyboardHookTypes::kMedia:
+ return nullptr;
+ }
+}
+
bool OzonePlatform::IsNativePixmapConfigSupported(
gfx::BufferFormat format,
gfx::BufferUsage usage) const {
@@ -149,7 +164,7 @@ OzonePlatform::GetPlatformUserInputMonitor(
return {};
}
-void OzonePlatform::PostMainMessageLoopStart(
+void OzonePlatform::PostCreateMainMessageLoop(
base::OnceCallback<void()> shutdown_cb) {}
void OzonePlatform::PostMainMessageLoopRun() {}
diff --git a/chromium/ui/ozone/public/ozone_platform.h b/chromium/ui/ozone/public/ozone_platform.h
index 886fc32c51e..62daa05f856 100644
--- a/chromium/ui/ozone/public/ozone_platform.h
+++ b/chromium/ui/ozone/public/ozone_platform.h
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/component_export.h"
+#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/message_loop/message_pump_type.h"
#include "base/single_thread_task_runner.h"
@@ -25,14 +26,20 @@ class NativeDisplayDelegate;
}
namespace ui {
+enum class DomCode;
+enum class PlatformKeyboardHookTypes;
+
class CursorFactory;
class GpuPlatformSupportHost;
class InputController;
+class KeyEvent;
class OverlayManagerOzone;
class PlatformClipboard;
class PlatformGLEGLUtility;
class PlatformGlobalShortcutListener;
class PlatformGlobalShortcutListenerDelegate;
+class PlatformKeyboardHook;
+class PlatformUtils;
class PlatformMenuUtils;
class PlatformScreen;
class PlatformUserInputMonitor;
@@ -165,7 +172,7 @@ class COMPONENT_EXPORT(OZONE) OzonePlatform {
// Corresponds to chrome_browser_main_extra_parts.h.
//
// The browser process' initialization involves several steps -
- // PreEarlyInitialization, PostMainMessageLoopStart, PostMainMessageLoopRun,
+ // PreEarlyInitialization, PostCreateMainMessageLoop, PostMainMessageLoopRun,
// etc. In order to be consistent with that and allow platform specific
// initialization steps, the OzonePlatform has three methods - one static
// PreEarlyInitialization that is expected to do some early non-ui
@@ -182,7 +189,8 @@ class COMPONENT_EXPORT(OZONE) OzonePlatform {
// Sets error handlers if supported for the browser process after the message
// loop started. It's required to call this so that we can exit cleanly if the
// server can exit before we do.
- virtual void PostMainMessageLoopStart(base::OnceCallback<void()> shutdown_cb);
+ virtual void PostCreateMainMessageLoop(
+ base::OnceCallback<void()> shutdown_cb);
// Resets the error handlers if set.
virtual void PostMainMessageLoopRun();
@@ -226,6 +234,18 @@ class COMPONENT_EXPORT(OZONE) OzonePlatform {
virtual PlatformUtils* GetPlatformUtils();
virtual PlatformGlobalShortcutListener* GetPlatformGlobalShortcutListener(
PlatformGlobalShortcutListenerDelegate* delegate);
+ // Returns the keyboard hook that captures the specified keys. See more in
+ // ui::KeyboardHook. However, unlike that interface, Ozone tries to register
+ // the hook that it has created, and returns the one only if it was registered
+ // successfully.
+ // Handles creating both modifier and media keyboard hooks. |dom_codes| and
+ // |accelerated_widget| are only used if |type| is
+ // PlatformKeyboardHookTypes::kModifier.
+ virtual std::unique_ptr<PlatformKeyboardHook> CreateKeyboardHook(
+ PlatformKeyboardHookTypes type,
+ base::RepeatingCallback<void(KeyEvent* event)> callback,
+ absl::optional<base::flat_set<DomCode>> dom_codes,
+ gfx::AcceleratedWidget accelerated_widget);
// Returns true if the specified buffer format is supported.
virtual bool IsNativePixmapConfigSupported(gfx::BufferFormat format,
diff --git a/chromium/ui/ozone/public/platform_clipboard.h b/chromium/ui/ozone/public/platform_clipboard.h
index e12ce50c592..ea953d95f5c 100644
--- a/chromium/ui/ozone/public/platform_clipboard.h
+++ b/chromium/ui/ozone/public/platform_clipboard.h
@@ -13,7 +13,7 @@
#include "base/component_export.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/clipboard/clipboard_buffer.h"
namespace ui {
@@ -34,11 +34,6 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard {
using Data = scoped_refptr<base::RefCountedBytes>;
using DataMap = std::unordered_map<std::string, Data>;
- // SequenceNumberUpdateCb is a repeating callback, which can be used to tell
- // a client of the PlatformClipboard to increment clipboard's sequence number
- using SequenceNumberUpdateCb =
- base::RepeatingCallback<void(ClipboardBuffer buffer)>;
-
// Offers a given clipboard data 'data_map' to the host system clipboard.
//
// It is common that host clipboard implementations simply get offered
@@ -84,8 +79,14 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard {
// the cached data in order to reply faster to read-clipboard operations.
virtual bool IsSelectionOwner(ClipboardBuffer buffer) = 0;
- // See comment above SequenceNumberUpdateCb. Can be called once.
- virtual void SetSequenceNumberUpdateCb(SequenceNumberUpdateCb cb) = 0;
+ // ClipboardDataChangedCallback is used to notify the PlatformClipboard client
+ // that the clipboard content for a given |buffer| has changed, so that it can
+ // take the necessary actions, e.g: to update clipboard's sequence number,
+ // notify observers, etc.
+ using ClipboardDataChangedCallback =
+ base::RepeatingCallback<void(ClipboardBuffer buffer)>;
+ virtual void SetClipboardDataChangedCallback(
+ ClipboardDataChangedCallback callback) = 0;
// Returns whether the kSelection buffer is available.
virtual bool IsSelectionBufferAvailable() const = 0;
diff --git a/chromium/ui/ozone/public/platform_gl_egl_utility.cc b/chromium/ui/ozone/public/platform_gl_egl_utility.cc
index 38a135e4a0b..756334b40ea 100644
--- a/chromium/ui/ozone/public/platform_gl_egl_utility.cc
+++ b/chromium/ui/ozone/public/platform_gl_egl_utility.cc
@@ -17,13 +17,4 @@ bool PlatformGLEGLUtility::HasVisualManager() {
return false;
}
-bool PlatformGLEGLUtility::UpdateVisualsOnGpuInfoChanged(
- bool software_rendering,
- uint32_t default_visual_id,
- uint32_t transparent_visual_id) {
- NOTREACHED() << "This must not be called if the platform does not support "
- "X11 visuals.";
- return false;
-}
-
} // namespace ui
diff --git a/chromium/ui/ozone/public/platform_gl_egl_utility.h b/chromium/ui/ozone/public/platform_gl_egl_utility.h
index 568ea5644a7..59728da2f6f 100644
--- a/chromium/ui/ozone/public/platform_gl_egl_utility.h
+++ b/chromium/ui/ozone/public/platform_gl_egl_utility.h
@@ -6,7 +6,6 @@
#define UI_OZONE_PUBLIC_PLATFORM_GL_EGL_UTILITY_H_
#include <string>
-#include <unordered_map>
#include <vector>
#include "base/component_export.h"
@@ -45,14 +44,6 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformGLEGLUtility {
// X11 specific; returns whether the platform supports visuals.
virtual bool HasVisualManager();
-
- // X11 specific; sets new visuals.
- // Must be called only if the X11 visual manager is available.
- // Should be called when the updated GPU info is available.
- // Returns whether the visuals provided were valid.
- virtual bool UpdateVisualsOnGpuInfoChanged(bool software_rendering,
- uint32_t default_visual_id,
- uint32_t transparent_visual_id);
};
} // namespace ui
diff --git a/chromium/ui/ozone/public/platform_keyboard_hook.cc b/chromium/ui/ozone/public/platform_keyboard_hook.cc
new file mode 100644
index 00000000000..532ccb66042
--- /dev/null
+++ b/chromium/ui/ozone/public/platform_keyboard_hook.cc
@@ -0,0 +1,18 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/public/platform_keyboard_hook.h"
+
+#include <utility>
+
+#include "base/containers/contains.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+
+namespace ui {
+
+PlatformKeyboardHook::PlatformKeyboardHook() = default;
+
+PlatformKeyboardHook::~PlatformKeyboardHook() = default;
+
+} // namespace ui \ No newline at end of file
diff --git a/chromium/ui/ozone/public/platform_keyboard_hook.h b/chromium/ui/ozone/public/platform_keyboard_hook.h
new file mode 100644
index 00000000000..e584c1d9635
--- /dev/null
+++ b/chromium/ui/ozone/public/platform_keyboard_hook.h
@@ -0,0 +1,36 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PUBLIC_PLATFORM_KEYBOARD_HOOK_H_
+#define UI_OZONE_PUBLIC_PLATFORM_KEYBOARD_HOOK_H_
+
+#include "base/callback.h"
+#include "base/component_export.h"
+#include "base/containers/flat_set.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace ui {
+
+enum class DomCode;
+class KeyEvent;
+
+// Supported hook types.
+enum class PlatformKeyboardHookTypes { kModifier, kMedia };
+
+// Interface for Ozone implementations of KeyboardHook.
+class COMPONENT_EXPORT(OZONE_BASE) PlatformKeyboardHook {
+ public:
+ using KeyEventCallback = base::RepeatingCallback<void(KeyEvent* event)>;
+
+ PlatformKeyboardHook();
+ PlatformKeyboardHook(const PlatformKeyboardHook&) = delete;
+ PlatformKeyboardHook& operator=(const PlatformKeyboardHook&) = delete;
+ virtual ~PlatformKeyboardHook();
+
+ // KeyboardHook:
+ virtual bool IsKeyLocked(DomCode dom_code) const = 0;
+};
+
+} // namespace ui
+#endif // UI_OZONE_PUBLIC_PLATFORM_KEYBOARD_HOOK_H_
diff --git a/chromium/ui/ozone/public/platform_user_input_monitor.h b/chromium/ui/ozone/public/platform_user_input_monitor.h
index ce7684115e9..7d717245620 100644
--- a/chromium/ui/ozone/public/platform_user_input_monitor.h
+++ b/chromium/ui/ozone/public/platform_user_input_monitor.h
@@ -5,7 +5,6 @@
#ifndef UI_OZONE_PUBLIC_PLATFORM_USER_INPUT_MONITOR_H_
#define UI_OZONE_PUBLIC_PLATFORM_USER_INPUT_MONITOR_H_
-#include <memory>
#include "base/component_export.h"
#include "base/memory/shared_memory_mapping.h"
diff --git a/chromium/ui/ozone/public/surface_factory_ozone.cc b/chromium/ui/ozone/public/surface_factory_ozone.cc
index 45b415c7233..3de495f12d3 100644
--- a/chromium/ui/ozone/public/surface_factory_ozone.cc
+++ b/chromium/ui/ozone/public/surface_factory_ozone.cc
@@ -37,8 +37,7 @@ GLOzone* SurfaceFactoryOzone::GetGLOzone(
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanImplementation>
SurfaceFactoryOzone::CreateVulkanImplementation(bool use_swiftshader,
- bool allow_protected_memory,
- bool enforce_protected_memory) {
+ bool allow_protected_memory) {
return nullptr;
}
@@ -78,7 +77,7 @@ scoped_refptr<gfx::NativePixmap> SurfaceFactoryOzone::CreateNativePixmap(
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- base::Optional<gfx::Size> framebuffer_size) {
+ absl::optional<gfx::Size> framebuffer_size) {
return nullptr;
}
diff --git a/chromium/ui/ozone/public/surface_factory_ozone.h b/chromium/ui/ozone/public/surface_factory_ozone.h
index 729c91f8d96..15cc4312124 100644
--- a/chromium/ui/ozone/public/surface_factory_ozone.h
+++ b/chromium/ui/ozone/public/surface_factory_ozone.h
@@ -82,12 +82,9 @@ class COMPONENT_EXPORT(OZONE_BASE) SurfaceFactoryOzone {
// on the platform.
// |allow_protected_memory| suggests that the vulkan implementation should
// create protected-capable resources, such as VkQueue.
- // |enforce_protected_memory| suggests that the vulkan implementation should
- // always use protected memory and resources, such as CommandBuffers.
virtual std::unique_ptr<gpu::VulkanImplementation> CreateVulkanImplementation(
bool use_swiftshader,
- bool allow_protected_memory,
- bool enforce_protected_memory);
+ bool allow_protected_memory);
// Creates a scanout NativePixmap that can be rendered using Vulkan.
// TODO(spang): Remove this once VK_EXT_image_drm_format_modifier is
@@ -140,7 +137,7 @@ class COMPONENT_EXPORT(OZONE_BASE) SurfaceFactoryOzone {
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- base::Optional<gfx::Size> framebuffer_size = base::nullopt);
+ absl::optional<gfx::Size> framebuffer_size = absl::nullopt);
// Similar to CreateNativePixmap, but returns the result asynchronously.
using NativePixmapCallback =
diff --git a/chromium/ui/ozone/public/swap_completion_callback.h b/chromium/ui/ozone/public/swap_completion_callback.h
index 367e30688e3..185bef077a0 100644
--- a/chromium/ui/ozone/public/swap_completion_callback.h
+++ b/chromium/ui/ozone/public/swap_completion_callback.h
@@ -5,20 +5,19 @@
#ifndef UI_OZONE_PUBLIC_SWAP_COMPLETION_CALLBACK_H_
#define UI_OZONE_PUBLIC_SWAP_COMPLETION_CALLBACK_H_
-#include <memory>
#include "base/callback.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/gfx/swap_result.h"
namespace gfx {
-class GpuFence;
struct PresentationFeedback;
} // namespace gfx
namespace ui {
using SwapCompletionOnceCallback =
- base::OnceCallback<void(gfx::SwapResult, std::unique_ptr<gfx::GpuFence>)>;
+ base::OnceCallback<void(gfx::SwapResult, gfx::GpuFenceHandle)>;
using PresentationOnceCallback =
base::OnceCallback<void(const gfx::PresentationFeedback&)>;
diff --git a/chromium/ui/ozone/test/mock_platform_window_delegate.h b/chromium/ui/ozone/test/mock_platform_window_delegate.h
index bfeb9e67839..802ae742319 100644
--- a/chromium/ui/ozone/test/mock_platform_window_delegate.h
+++ b/chromium/ui/ozone/test/mock_platform_window_delegate.h
@@ -29,8 +29,8 @@ class MockPlatformWindowDelegate : public PlatformWindowDelegate {
MOCK_METHOD0(OnWillDestroyAcceleratedWidget, void());
MOCK_METHOD0(OnAcceleratedWidgetDestroyed, void());
MOCK_METHOD1(OnActivationChanged, void(bool active));
- MOCK_METHOD0(GetMinimumSizeForWindow, base::Optional<gfx::Size>());
- MOCK_METHOD0(GetMaximumSizeForWindow, base::Optional<gfx::Size>());
+ MOCK_METHOD0(GetMinimumSizeForWindow, absl::optional<gfx::Size>());
+ MOCK_METHOD0(GetMaximumSizeForWindow, absl::optional<gfx::Size>());
MOCK_METHOD0(OnMouseEnter, void());
private:
diff --git a/chromium/ui/platform_window/extensions/wayland_extension.h b/chromium/ui/platform_window/extensions/wayland_extension.h
index 810dce5d7ca..3b5995e0e8f 100644
--- a/chromium/ui/platform_window/extensions/wayland_extension.h
+++ b/chromium/ui/platform_window/extensions/wayland_extension.h
@@ -39,6 +39,11 @@ class COMPONENT_EXPORT(PLATFORM_WINDOW) WaylandExtension {
// snapping.
virtual void CommitSnap(WaylandWindowSnapDirection snap) = 0;
+ // Signals the underneath platform whether the current tab of the browser
+ // window can go back. The underneath platform might react, for example,
+ // by minimizing the window upon a system wide back gesture.
+ virtual void SetCanGoBack(bool value) = 0;
+
protected:
virtual ~WaylandExtension();
diff --git a/chromium/ui/platform_window/platform_window.cc b/chromium/ui/platform_window/platform_window.cc
index 0560e2ef6ee..340655359d3 100644
--- a/chromium/ui/platform_window/platform_window.cc
+++ b/chromium/ui/platform_window/platform_window.cc
@@ -54,7 +54,7 @@ std::string PlatformWindow::GetWindowUniqueId() const {
return std::string();
}
-bool PlatformWindow::ShouldUseLayerForShapedWindow() const {
+bool PlatformWindow::ShouldUpdateWindowShape() const {
return false;
}
diff --git a/chromium/ui/platform_window/platform_window.h b/chromium/ui/platform_window/platform_window.h
index c88f3b9f19c..b9178723ffa 100644
--- a/chromium/ui/platform_window/platform_window.h
+++ b/chromium/ui/platform_window/platform_window.h
@@ -14,6 +14,9 @@
#include "ui/gfx/native_widget_types.h"
#include "ui/platform_window/platform_window_delegate.h"
+template <class T>
+class scoped_refptr;
+
namespace gfx {
class ImageSkia;
class Point;
@@ -23,7 +26,7 @@ class Transform;
} // namespace gfx
namespace ui {
-using PlatformCursor = void*;
+class PlatformCursor;
// Generic PlatformWindow interface.
class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindow
@@ -73,7 +76,12 @@ class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindow
virtual void SetUseNativeFrame(bool use_native_frame) = 0;
virtual bool ShouldUseNativeFrame() const = 0;
- virtual void SetCursor(PlatformCursor cursor) = 0;
+ // This method sets the current cursor to `cursor`. Note that the platform
+ // window should keep a copy of `cursor` and also avoid replacing it until the
+ // new value has been set if any kind of platform-specific resources are
+ // managed by the platform cursor, e.g. HCURSOR on Windows, which are
+ // destroyed once the last copy of the platform cursor goes out of scope.
+ virtual void SetCursor(scoped_refptr<PlatformCursor> cursor) = 0;
// Moves the cursor to |location|. Location is in platform window coordinates.
virtual void MoveCursorTo(const gfx::Point& location) = 0;
@@ -145,9 +153,10 @@ class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindow
// platform specific. Overriding this method is optional.
virtual std::string GetWindowUniqueId() const;
- // Returns true if window shape should be updated in layer,
- // otherwise false when platform window updates the window shape.
- virtual bool ShouldUseLayerForShapedWindow() const;
+ // Returns true if window shape should be updated in host,
+ // otherwise false when platform window or specific frame views updates the
+ // window shape.
+ virtual bool ShouldUpdateWindowShape() const;
};
} // namespace ui
diff --git a/chromium/ui/platform_window/platform_window_delegate.cc b/chromium/ui/platform_window/platform_window_delegate.cc
index e6a1a477c20..31ba4832567 100644
--- a/chromium/ui/platform_window/platform_window_delegate.cc
+++ b/chromium/ui/platform_window/platform_window_delegate.cc
@@ -20,12 +20,12 @@ PlatformWindowDelegate::PlatformWindowDelegate() = default;
PlatformWindowDelegate::~PlatformWindowDelegate() = default;
-base::Optional<gfx::Size> PlatformWindowDelegate::GetMinimumSizeForWindow() {
- return base::nullopt;
+absl::optional<gfx::Size> PlatformWindowDelegate::GetMinimumSizeForWindow() {
+ return absl::nullopt;
}
-base::Optional<gfx::Size> PlatformWindowDelegate::GetMaximumSizeForWindow() {
- return base::nullopt;
+absl::optional<gfx::Size> PlatformWindowDelegate::GetMaximumSizeForWindow() {
+ return absl::nullopt;
}
SkPath PlatformWindowDelegate::GetWindowMaskForWindowShapeInPixels() {
diff --git a/chromium/ui/platform_window/platform_window_delegate.h b/chromium/ui/platform_window/platform_window_delegate.h
index 6faa3bb304f..e3bd3f97c96 100644
--- a/chromium/ui/platform_window/platform_window_delegate.h
+++ b/chromium/ui/platform_window/platform_window_delegate.h
@@ -6,8 +6,8 @@
#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_H_
#include "base/component_export.h"
-#include "base/optional.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
@@ -93,8 +93,8 @@ class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindowDelegate {
virtual void OnActivationChanged(bool active) = 0;
// Requests size constraints for the PlatformWindow.
- virtual base::Optional<gfx::Size> GetMinimumSizeForWindow();
- virtual base::Optional<gfx::Size> GetMaximumSizeForWindow();
+ virtual absl::optional<gfx::Size> GetMinimumSizeForWindow();
+ virtual absl::optional<gfx::Size> GetMaximumSizeForWindow();
// Returns a mask to be used to clip the window for the size of
// |WindowTreeHost::GetBoundsInPixels|.
diff --git a/chromium/ui/platform_window/platform_window_init_properties.h b/chromium/ui/platform_window/platform_window_init_properties.h
index d1953619790..7cd789aa5d7 100644
--- a/chromium/ui/platform_window/platform_window_init_properties.h
+++ b/chromium/ui/platform_window/platform_window_init_properties.h
@@ -8,8 +8,8 @@
#include <string>
#include "base/component_export.h"
-#include "base/optional.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
@@ -96,7 +96,7 @@ struct COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindowInitProperties {
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
bool prefer_dark_theme = false;
gfx::ImageSkia* icon = nullptr;
- base::Optional<int> background_color;
+ absl::optional<int> background_color;
// Specifies the res_name and res_class fields,
// respectively, of the WM_CLASS window property. Controls window grouping
diff --git a/chromium/ui/platform_window/stub/stub_window.cc b/chromium/ui/platform_window/stub/stub_window.cc
index e3ba798dc80..0276028feeb 100644
--- a/chromium/ui/platform_window/stub/stub_window.cc
+++ b/chromium/ui/platform_window/stub/stub_window.cc
@@ -4,7 +4,9 @@
#include "ui/platform_window/stub/stub_window.h"
+#include "base/memory/scoped_refptr.h"
#include "base/notreached.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/platform_window/platform_window_delegate.h"
namespace ui {
@@ -84,7 +86,7 @@ bool StubWindow::ShouldUseNativeFrame() const {
return false;
}
-void StubWindow::SetCursor(PlatformCursor cursor) {}
+void StubWindow::SetCursor(scoped_refptr<PlatformCursor> cursor) {}
void StubWindow::MoveCursorTo(const gfx::Point& location) {}
diff --git a/chromium/ui/platform_window/stub/stub_window.h b/chromium/ui/platform_window/stub/stub_window.h
index 4c8ffecd9c2..0402e84c5c5 100644
--- a/chromium/ui/platform_window/stub/stub_window.h
+++ b/chromium/ui/platform_window/stub/stub_window.h
@@ -48,7 +48,7 @@ class STUB_WINDOW_EXPORT StubWindow : public PlatformWindow {
void Deactivate() override;
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
- void SetCursor(PlatformCursor cursor) override;
+ void SetCursor(scoped_refptr<PlatformCursor> cursor) override;
void MoveCursorTo(const gfx::Point& location) override;
void ConfineCursorToBounds(const gfx::Rect& bounds) override;
void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override;
diff --git a/chromium/ui/platform_window/stub/stub_window_export.h b/chromium/ui/platform_window/stub/stub_window_export.h
index 2d983ed27fe..4353932aebe 100644
--- a/chromium/ui/platform_window/stub/stub_window_export.h
+++ b/chromium/ui/platform_window/stub/stub_window_export.h
@@ -26,4 +26,4 @@
#define STUB_WINDOW_EXPORT
#endif
-#endif // UI_PLATFORM_WINDOW_STUB_STUB_WINDOW_EXPORT_H
+#endif // UI_PLATFORM_WINDOW_STUB_STUB_WINDOW_EXPORT_H_
diff --git a/chromium/ui/platform_window/win/win_window.cc b/chromium/ui/platform_window/win/win_window.cc
index 36b14c4edc3..2d68fa52ec1 100644
--- a/chromium/ui/platform_window/win/win_window.cc
+++ b/chromium/ui/platform_window/win/win_window.cc
@@ -4,20 +4,22 @@
#include "ui/platform_window/win/win_window.h"
+#include <windows.h>
+
#include <algorithm>
#include <memory>
#include <string>
+#include "base/memory/scoped_refptr.h"
#include "base/notreached.h"
#include "base/strings/string_util_win.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/cursor/win/win_cursor.h"
#include "ui/base/win/shell.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/gfx/win/msg_util.h"
-#include <windows.h>
-
namespace ui {
namespace {
@@ -147,9 +149,15 @@ bool WinWindow::ShouldUseNativeFrame() const {
return false;
}
-void WinWindow::SetCursor(PlatformCursor cursor) {
- DCHECK(cursor);
- ::SetCursor(static_cast<WinCursor*>(cursor)->hcursor());
+void WinWindow::SetCursor(scoped_refptr<PlatformCursor> platform_cursor) {
+ DCHECK(platform_cursor);
+
+ auto cursor = WinCursor::FromPlatformCursor(platform_cursor);
+ ::SetCursor(cursor->hcursor());
+
+ // The new cursor needs to be stored last to avoid deleting the old cursor
+ // while it's still in use.
+ cursor_ = cursor;
}
void WinWindow::MoveCursorTo(const gfx::Point& location) {
diff --git a/chromium/ui/platform_window/win/win_window.h b/chromium/ui/platform_window/win/win_window.h
index 00d61bd9c3a..1ca66af5949 100644
--- a/chromium/ui/platform_window/win/win_window.h
+++ b/chromium/ui/platform_window/win/win_window.h
@@ -7,6 +7,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "ui/gfx/win/msg_util.h"
#include "ui/gfx/win/window_impl.h"
@@ -17,6 +18,7 @@
#include <windows.h>
namespace ui {
+class WinCursor;
class WIN_WINDOW_EXPORT WinWindow : public PlatformWindow,
public gfx::WindowImpl {
@@ -48,7 +50,7 @@ class WIN_WINDOW_EXPORT WinWindow : public PlatformWindow,
void Deactivate() override;
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
- void SetCursor(PlatformCursor cursor) override;
+ void SetCursor(scoped_refptr<PlatformCursor> cursor) override;
void MoveCursorTo(const gfx::Point& location) override;
void ConfineCursorToBounds(const gfx::Rect& bounds) override;
void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override;
@@ -105,6 +107,10 @@ class WIN_WINDOW_EXPORT WinWindow : public PlatformWindow,
PlatformWindowDelegate* delegate_;
+ // Keep a reference to the current cursor to make sure the wrapped HCURSOR
+ // isn't destroyed after the call to SetCursor().
+ scoped_refptr<WinCursor> cursor_;
+
CR_MSG_MAP_CLASS_DECLARATIONS(WinWindow)
DISALLOW_COPY_AND_ASSIGN(WinWindow);
diff --git a/chromium/ui/platform_window/win/win_window_export.h b/chromium/ui/platform_window/win/win_window_export.h
index 69d86d22979..981fcfcd9f6 100644
--- a/chromium/ui/platform_window/win/win_window_export.h
+++ b/chromium/ui/platform_window/win/win_window_export.h
@@ -26,5 +26,4 @@
#define WIN_WINDOW_EXPORT
#endif
-#endif // UI_PLATFORM_WINDOW_WIN_WIN_WINDOW_EXPORT_H
-
+#endif // UI_PLATFORM_WINDOW_WIN_WIN_WINDOW_EXPORT_H_
diff --git a/chromium/ui/platform_window/wm/BUILD.gn b/chromium/ui/platform_window/wm/BUILD.gn
index 7f060579821..bd8b4b4fa12 100644
--- a/chromium/ui/platform_window/wm/BUILD.gn
+++ b/chromium/ui/platform_window/wm/BUILD.gn
@@ -18,7 +18,7 @@ component("wm") {
defines = [ "IS_WM_IMPL" ]
- public_deps = [ "//ui/base/dragdrop:types" ]
+ public_deps = [ "//ui/base/dragdrop/mojom:mojom_headers" ]
deps = [
"//ui/base",
"//ui/platform_window",
diff --git a/chromium/ui/platform_window/wm/wm_drag_handler.h b/chromium/ui/platform_window/wm/wm_drag_handler.h
index 769554c4005..f9fb0057fc3 100644
--- a/chromium/ui/platform_window/wm/wm_drag_handler.h
+++ b/chromium/ui/platform_window/wm/wm_drag_handler.h
@@ -6,7 +6,7 @@
#define UI_PLATFORM_WINDOW_WM_WM_DRAG_HANDLER_H_
#include "base/component_export.h"
-#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h"
#include "ui/gfx/native_widget_types.h"
namespace gfx {
@@ -25,10 +25,9 @@ class COMPONENT_EXPORT(WM) WmDragHandler {
// Called every time when the drag location has changed.
virtual void OnDragLocationChanged(const gfx::Point& screen_point_px) = 0;
// Called when the currently negotiated operation has changed.
- virtual void OnDragOperationChanged(
- DragDropTypes::DragOperation operation) = 0;
+ virtual void OnDragOperationChanged(mojom::DragOperation operation) = 0;
// Called once when the operation has finished.
- virtual void OnDragFinished(int operation) = 0;
+ virtual void OnDragFinished(mojom::DragOperation operation) = 0;
protected:
virtual ~Delegate();
diff --git a/chromium/ui/platform_window/x11/BUILD.gn b/chromium/ui/platform_window/x11/BUILD.gn
index dc65dc7a733..72bce1f107e 100644
--- a/chromium/ui/platform_window/x11/BUILD.gn
+++ b/chromium/ui/platform_window/x11/BUILD.gn
@@ -20,6 +20,7 @@ component("x11") {
"//ui/base:hit_test",
"//ui/base:wm_role_names",
"//ui/base/dragdrop:types",
+ "//ui/base/dragdrop/mojom",
"//ui/base/x",
"//ui/events",
"//ui/events/devices",
@@ -63,14 +64,17 @@ test("x11_unittests") {
"test/x11_event_translation_unittest.cc",
"test/x11_window_unittest.cc",
]
+
deps = [
":x11",
+ "//base",
"//base/test:run_all_unittests",
"//base/test:test_support",
"//build:chromeos_buildflags",
"//skia",
"//testing/gmock",
"//testing/gtest",
+ "//ui/base",
"//ui/base:features",
"//ui/base/x",
"//ui/base/x:test_support",
@@ -79,8 +83,19 @@ test("x11_unittests") {
"//ui/events/x",
"//ui/gfx:test_support",
"//ui/gfx/x",
+ "//ui/gfx/x:unit_test",
"//ui/platform_window",
]
+
+ if (!is_chromeos && !is_chromeos_ash && !is_chromeos_lacros) {
+ sources += [ "test/os_exchange_data_provider_x11_unittest.cc" ]
+ deps += [ "//ui/base/clipboard:clipboard_types" ]
+ }
+
+ if (use_ozone) {
+ deps += [ "//ui/ozone" ]
+ }
+
configs += [ "//build/config:precompiled_headers" ]
# Needed for tests. Please note that if you want to run tests locally,
diff --git a/chromium/ui/platform_window/x11/x11_topmost_window_finder.cc b/chromium/ui/platform_window/x11/x11_topmost_window_finder.cc
index 2b8edfc02db..891f7d25156 100644
--- a/chromium/ui/platform_window/x11/x11_topmost_window_finder.cc
+++ b/chromium/ui/platform_window/x11/x11_topmost_window_finder.cc
@@ -8,12 +8,100 @@
#include <vector>
+#include "base/bind.h"
+#include "ui/base/x/x11_menu_list.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/x/x11_atom_cache.h"
+#include "ui/gfx/x/xproto_util.h"
#include "ui/platform_window/x11/x11_window.h"
#include "ui/platform_window/x11/x11_window_manager.h"
namespace ui {
+namespace {
+
+using ShouldStopIteratingCallback = base::RepeatingCallback<bool(x11::Window)>;
+
+// Returns true if |window| is a named window.
+bool IsWindowNamed(x11::Window window) {
+ return PropertyExists(window, x11::Atom::WM_NAME);
+}
+
+bool EnumerateChildren(ShouldStopIteratingCallback should_stop_iterating,
+ x11::Window window,
+ const int max_depth,
+ int depth) {
+ if (depth > max_depth)
+ return false;
+
+ std::vector<x11::Window> windows;
+ if (depth == 0) {
+ XMenuList::GetInstance()->InsertMenuWindows(&windows);
+ // Enumerate the menus first.
+ std::vector<x11::Window>::iterator iter;
+ for (iter = windows.begin(); iter != windows.end(); iter++) {
+ if (should_stop_iterating.Run(*iter))
+ return true;
+ }
+ windows.clear();
+ }
+
+ auto query_tree = x11::Connection::Get()->QueryTree({window}).Sync();
+ if (!query_tree)
+ return false;
+ windows = std::move(query_tree->children);
+
+ // XQueryTree returns the children of |window| in bottom-to-top order, so
+ // reverse-iterate the list to check the windows from top-to-bottom.
+ std::vector<x11::Window>::reverse_iterator iter;
+ for (iter = windows.rbegin(); iter != windows.rend(); iter++) {
+ if (IsWindowNamed(*iter) && should_stop_iterating.Run(*iter))
+ return true;
+ }
+
+ // If we're at this point, we didn't find the window we're looking for at the
+ // current level, so we need to recurse to the next level. We use a second
+ // loop because the recursion and call to XQueryTree are expensive and is only
+ // needed for a small number of cases.
+ if (++depth <= max_depth) {
+ for (iter = windows.rbegin(); iter != windows.rend(); iter++) {
+ if (EnumerateChildren(should_stop_iterating, *iter, max_depth, depth))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool EnumerateAllWindows(ShouldStopIteratingCallback should_stop_iterating,
+ int max_depth) {
+ x11::Window root = GetX11RootWindow();
+ return EnumerateChildren(should_stop_iterating, root, max_depth, 0);
+}
+
+void EnumerateTopLevelWindows(
+ ui::ShouldStopIteratingCallback should_stop_iterating) {
+ std::vector<x11::Window> stack;
+ if (!ui::GetXWindowStack(ui::GetX11RootWindow(), &stack)) {
+ // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back
+ // to old school enumeration of all X windows. Some WMs parent 'top-level'
+ // windows in unnamed actual top-level windows (ion WM), so extend the
+ // search depth to all children of top-level windows.
+ const int kMaxSearchDepth = 1;
+ ui::EnumerateAllWindows(should_stop_iterating, kMaxSearchDepth);
+ return;
+ }
+ XMenuList::GetInstance()->InsertMenuWindows(&stack);
+
+ std::vector<x11::Window>::iterator iter;
+ for (iter = stack.begin(); iter != stack.end(); iter++) {
+ if (should_stop_iterating.Run(*iter))
+ return;
+ }
+}
+
+} // namespace
+
X11TopmostWindowFinder::X11TopmostWindowFinder() = default;
X11TopmostWindowFinder::~X11TopmostWindowFinder() = default;
@@ -33,14 +121,16 @@ x11::Window X11TopmostWindowFinder::FindLocalProcessWindowAt(
return x11::Window::None;
}
- EnumerateTopLevelWindows(this);
+ EnumerateTopLevelWindows(base::BindRepeating(
+ &X11TopmostWindowFinder::ShouldStopIterating, base::Unretained(this)));
return toplevel_;
}
x11::Window X11TopmostWindowFinder::FindWindowAt(
const gfx::Point& screen_loc_in_pixels) {
screen_loc_in_pixels_ = screen_loc_in_pixels;
- EnumerateTopLevelWindows(this);
+ EnumerateTopLevelWindows(base::BindRepeating(
+ &X11TopmostWindowFinder::ShouldStopIterating, base::Unretained(this)));
return toplevel_;
}
diff --git a/chromium/ui/platform_window/x11/x11_topmost_window_finder.h b/chromium/ui/platform_window/x11/x11_topmost_window_finder.h
index 3b6f08ea7b4..8bd407762e0 100644
--- a/chromium/ui/platform_window/x11/x11_topmost_window_finder.h
+++ b/chromium/ui/platform_window/x11/x11_topmost_window_finder.h
@@ -20,8 +20,7 @@ class X11Window;
// Utility class for finding the topmost window at a given screen position.
class X11_WINDOW_EXPORT X11TopmostWindowFinder
- : public ui::EnumerateWindowsDelegate,
- public ui::XTopmostWindowFinder {
+ : public ui::XTopmostWindowFinder {
public:
X11TopmostWindowFinder();
~X11TopmostWindowFinder() override;
@@ -37,8 +36,7 @@ class X11_WINDOW_EXPORT X11TopmostWindowFinder
x11::Window FindWindowAt(const gfx::Point& screen_loc_in_pixels) override;
private:
- // ui::EnumerateWindowsDelegate:
- bool ShouldStopIterating(x11::Window window) override;
+ bool ShouldStopIterating(x11::Window window);
// Returns true if |window| does not not belong to |ignore|, is visible and
// contains |screen_loc_|.
diff --git a/chromium/ui/platform_window/x11/x11_window.cc b/chromium/ui/platform_window/x11/x11_window.cc
index 37649f7f332..ce480a898c7 100644
--- a/chromium/ui/platform_window/x11/x11_window.cc
+++ b/chromium/ui/platform_window/x11/x11_window.cc
@@ -4,6 +4,7 @@
#include "ui/platform_window/x11/x11_window.h"
+#include "base/memory/scoped_refptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
@@ -12,7 +13,9 @@
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/base/buildflags.h"
#include "ui/base/cursor/cursor.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/hit_test_x11.h"
#include "ui/base/ui_base_features.h"
@@ -50,9 +53,10 @@
#endif
namespace ui {
-
namespace {
+using mojom::DragOperation;
+
// Opacity for drag widget windows.
constexpr float kDragWidgetOpacity = .75f;
@@ -203,8 +207,7 @@ X11Window::~X11Window() {
}
void X11Window::Initialize(PlatformWindowInitProperties properties) {
- PlatformWindowOpacity opacity = properties.opacity;
- CreateXWindow(properties, opacity);
+ CreateXWindow(properties);
// It can be a status icon window. If it fails to initialize, don't provide
// it with a native window handle, close ourselves and let the client destroy
@@ -321,7 +324,7 @@ void X11Window::Initialize(PlatformWindowInitProperties properties) {
if (is_always_on_top_)
window_properties_.insert(x11::GetAtom("_NET_WM_STATE_ABOVE"));
- workspace_ = base::nullopt;
+ workspace_ = absl::nullopt;
if (properties.visible_on_all_workspaces) {
window_properties_.insert(x11::GetAtom("_NET_WM_STATE_STICKY"));
x11::SetProperty(xwindow_, x11::GetAtom("_NET_WM_DESKTOP"),
@@ -396,10 +399,8 @@ void X11Window::Initialize(PlatformWindowInitProperties properties) {
if (properties.icon)
SetWindowIcons(gfx::ImageSkia(), *properties.icon);
- if (properties.type == PlatformWindowType::kDrag &&
- opacity == PlatformWindowOpacity::kTranslucentWindow) {
+ if (properties.type == PlatformWindowType::kDrag)
SetOpacity(kDragWidgetOpacity);
- }
SetWmDragHandler(this, this);
@@ -758,10 +759,10 @@ bool X11Window::ShouldUseNativeFrame() const {
return use_native_frame_;
}
-void X11Window::SetCursor(PlatformCursor cursor) {
+void X11Window::SetCursor(scoped_refptr<PlatformCursor> cursor) {
DCHECK(cursor);
- last_cursor_ = static_cast<X11Cursor*>(cursor);
+ last_cursor_ = X11Cursor::FromPlatformCursor(cursor);
on_cursor_loaded_.Reset(base::BindOnce(DefineCursor, xwindow_));
last_cursor_->OnCursorLoaded(on_cursor_loaded_.callback());
}
@@ -957,10 +958,13 @@ void X11Window::SizeConstraintsChanged() {
}
bool X11Window::IsTranslucentWindowOpacitySupported() const {
- // This function may be called before InitX11Window() (which
- // initializes |visual_has_alpha_|), so we cannot simply return
- // |visual_has_alpha_|.
- return ui::XVisualManager::GetInstance()->ArgbVisualAvailable();
+ // If this function may be called before InitX11Window() (which
+ // initializes |visual_has_alpha_|), return whether it is possible
+ // to create windows with ARGB visuals.
+ if (xwindow_ == x11::Window::None)
+ ui::XVisualManager::GetInstance()->ArgbVisualAvailable();
+
+ return visual_has_alpha_;
}
void X11Window::SetOpacity(float opacity) {
@@ -983,7 +987,7 @@ void X11Window::SetOpacity(float opacity) {
}
std::string X11Window::GetWorkspace() const {
- base::Optional<int> workspace_id = workspace_;
+ absl::optional<int> workspace_id = workspace_;
return workspace_id.has_value() ? base::NumberToString(workspace_id.value())
: std::string();
}
@@ -1287,11 +1291,11 @@ void X11Window::OnXWindowDragDropEvent(const x11::ClientMessageEvent& xev) {
drag_drop_client_->HandleXdndEvent(xev);
}
-base::Optional<gfx::Size> X11Window::GetMinimumSizeForXWindow() {
+absl::optional<gfx::Size> X11Window::GetMinimumSizeForXWindow() {
return platform_window_delegate_->GetMinimumSizeForWindow();
}
-base::Optional<gfx::Size> X11Window::GetMaximumSizeForXWindow() {
+absl::optional<gfx::Size> X11Window::GetMaximumSizeForXWindow() {
return platform_window_delegate_->GetMaximumSizeForWindow();
}
@@ -1328,7 +1332,7 @@ bool X11Window::StartDrag(const OSExchangeData& data,
drag_handler_delegate_ = delegate;
drag_drop_client_->InitDrag(operation, &data);
- drag_operation_ = 0;
+ allowed_drag_operations_ = 0;
notified_enter_ = false;
drag_loop_ = std::make_unique<X11WholeScreenMoveLoop>(this);
@@ -1385,14 +1389,13 @@ int X11Window::UpdateDrag(const gfx::Point& screen_point) {
GetKeyModifiers(source_client));
notified_enter_ = true;
}
- drag_operation_ = drop_handler->OnDragMotion(gfx::PointF(screen_point),
- suggested_operations,
- GetKeyModifiers(source_client));
- return drag_operation_;
+ allowed_drag_operations_ = drop_handler->OnDragMotion(
+ gfx::PointF(screen_point), suggested_operations,
+ GetKeyModifiers(source_client));
+ return allowed_drag_operations_;
}
-void X11Window::UpdateCursor(
- DragDropTypes::DragOperation negotiated_operation) {
+void X11Window::UpdateCursor(DragOperation negotiated_operation) {
DCHECK(drag_handler_delegate_);
drag_handler_delegate_->OnDragOperationChanged(negotiated_operation);
}
@@ -1415,10 +1418,10 @@ void X11Window::OnBeforeDragLeave() {
notified_enter_ = false;
}
-int X11Window::PerformDrop() {
+DragOperation X11Window::PerformDrop() {
WmDropHandler* drop_handler = GetWmDropHandler(*this);
if (!drop_handler || !notified_enter_)
- return DragDropTypes::DRAG_NONE;
+ return DragOperation::kNone;
// The drop data has been supplied on entering the window. The drop handler
// should have it since then.
@@ -1427,13 +1430,14 @@ int X11Window::PerformDrop() {
drop_handler->OnDragDrop({}, GetKeyModifiers(XDragDropClient::GetForWindow(
target_current_context->source_window())));
notified_enter_ = false;
- return drag_operation_;
+ return PreferredDragOperation(allowed_drag_operations_);
}
void X11Window::EndDragLoop() {
DCHECK(drag_handler_delegate_);
- drag_handler_delegate_->OnDragFinished(drag_operation_);
+ drag_handler_delegate_->OnDragFinished(
+ PreferredDragOperation(allowed_drag_operations_));
drag_loop_->EndMoveLoop();
}
@@ -1515,19 +1519,13 @@ void X11Window::ConvertEventLocationToTargetLocation(
located_event);
}
-void X11Window::CreateXWindow(const PlatformWindowInitProperties& properties,
- PlatformWindowOpacity& opacity) {
+void X11Window::CreateXWindow(const PlatformWindowInitProperties& properties) {
auto bounds = properties.bounds;
gfx::Size adjusted_size_in_pixels = AdjustSizeForDisplay(bounds.size());
bounds.set_size(adjusted_size_in_pixels);
const auto override_redirect =
properties.x11_extension_delegate &&
properties.x11_extension_delegate->IsOverrideRedirect(IsWmTiling());
- if (properties.type == PlatformWindowType::kDrag) {
- opacity = ui::IsCompositingManagerPresent()
- ? PlatformWindowOpacity::kTranslucentWindow
- : PlatformWindowOpacity::kOpaqueWindow;
- }
workspace_extension_delegate_ = properties.workspace_extension_delegate;
x11_extension_delegate_ = properties.x11_extension_delegate;
@@ -1571,7 +1569,7 @@ void X11Window::CreateXWindow(const PlatformWindowInitProperties& properties,
override_redirect_ = req.override_redirect.has_value();
bool enable_transparent_visuals;
- switch (opacity) {
+ switch (properties.opacity) {
case PlatformWindowOpacity::kOpaqueWindow:
enable_transparent_visuals = false;
break;
@@ -1733,7 +1731,7 @@ void X11Window::OnWorkspaceUpdated() {
if (GetWindowDesktop(xwindow_, &workspace))
workspace_ = workspace;
else
- workspace_ = base::nullopt;
+ workspace_ = absl::nullopt;
if (workspace_ != old_workspace)
OnXWindowWorkspaceChanged();
@@ -1758,8 +1756,8 @@ void X11Window::SetFlashFrameHint(bool flash_frame) {
}
void X11Window::UpdateMinAndMaxSize() {
- base::Optional<gfx::Size> minimum_in_pixels = GetMinimumSizeForXWindow();
- base::Optional<gfx::Size> maximum_in_pixels = GetMaximumSizeForXWindow();
+ absl::optional<gfx::Size> minimum_in_pixels = GetMinimumSizeForXWindow();
+ absl::optional<gfx::Size> maximum_in_pixels = GetMaximumSizeForXWindow();
if ((!minimum_in_pixels ||
min_size_in_pixels_ == minimum_in_pixels.value()) &&
(!maximum_in_pixels || max_size_in_pixels_ == maximum_in_pixels.value()))
diff --git a/chromium/ui/platform_window/x11/x11_window.h b/chromium/ui/platform_window/x11/x11_window.h
index 3a78032d846..b8b98f0b9ee 100644
--- a/chromium/ui/platform_window/x11/x11_window.h
+++ b/chromium/ui/platform_window/x11/x11_window.h
@@ -90,7 +90,7 @@ class X11_WINDOW_EXPORT X11Window
void Deactivate() override;
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
- void SetCursor(PlatformCursor cursor) override;
+ void SetCursor(scoped_refptr<PlatformCursor> cursor) override;
void MoveCursorTo(const gfx::Point& location) override;
void ConfineCursorToBounds(const gfx::Rect& bounds) override;
void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override;
@@ -144,8 +144,8 @@ class X11_WINDOW_EXPORT X11Window
void OnXWindowLostPointerGrab();
void OnXWindowSelectionEvent(const x11::SelectionNotifyEvent& xev);
void OnXWindowDragDropEvent(const x11::ClientMessageEvent& xev);
- base::Optional<gfx::Size> GetMinimumSizeForXWindow();
- base::Optional<gfx::Size> GetMaximumSizeForXWindow();
+ absl::optional<gfx::Size> GetMinimumSizeForXWindow();
+ absl::optional<gfx::Size> GetMaximumSizeForXWindow();
SkPath GetWindowMaskForXWindow();
private:
@@ -180,11 +180,11 @@ class X11_WINDOW_EXPORT X11Window
// XDragDropClient::Delegate
std::unique_ptr<XTopmostWindowFinder> CreateWindowFinder() override;
int UpdateDrag(const gfx::Point& screen_point) override;
- void UpdateCursor(DragDropTypes::DragOperation negotiated_operation) override;
+ void UpdateCursor(mojom::DragOperation negotiated_operation) override;
void OnBeginForeignDrag(x11::Window window) override;
void OnEndForeignDrag() override;
void OnBeforeDragLeave() override;
- int PerformDrop() override;
+ mojom::DragOperation PerformDrop() override;
void EndDragLoop() override;
// X11MoveLoopDelegate
@@ -220,8 +220,7 @@ class X11_WINDOW_EXPORT X11Window
// Depending on presence of the compositing manager and window type, may
// change the opacity, in which case returns the final opacity type through
// |opacity|.
- void CreateXWindow(const PlatformWindowInitProperties& properties,
- PlatformWindowOpacity& opacity);
+ void CreateXWindow(const PlatformWindowInitProperties& properties);
void CloseXWindow();
void Map(bool inactive = false);
void SetFullscreen(bool fullscreen);
@@ -327,8 +326,8 @@ class X11_WINDOW_EXPORT X11Window
// Whether the drop handler has notified that the drag has entered.
bool notified_enter_ = false;
- // Keeps the last negotiated operation returned by the drop handler.
- int drag_operation_ = 0;
+ // Keeps the last negotiated operations returned by the drop handler.
+ int allowed_drag_operations_ = 0;
// Handles XDND events going through this window.
std::unique_ptr<XDragDropClient> drag_drop_client_;
@@ -376,9 +375,9 @@ class X11_WINDOW_EXPORT X11Window
// Whether we used an ARGB visual for our window.
bool visual_has_alpha_ = false;
- // The workspace containing |xwindow_|. This will be base::nullopt when
+ // The workspace containing |xwindow_|. This will be absl::nullopt when
// _NET_WM_DESKTOP is unset.
- base::Optional<int> workspace_;
+ absl::optional<int> workspace_;
// True if the window should stay on top of most other windows.
bool is_always_on_top_ = false;
diff --git a/chromium/ui/platform_window/x11/x11_window_export.h b/chromium/ui/platform_window/x11/x11_window_export.h
index ab8c004d984..64aef2ccd66 100644
--- a/chromium/ui/platform_window/x11/x11_window_export.h
+++ b/chromium/ui/platform_window/x11/x11_window_export.h
@@ -26,5 +26,4 @@
#define X11_WINDOW_EXPORT
#endif
-#endif // UI_PLATFORM_WINDOW_X11_X11_WINDOW_EXPORT_H
-
+#endif // UI_PLATFORM_WINDOW_X11_X11_WINDOW_EXPORT_H_
diff --git a/chromium/ui/resources/DIR_METADATA b/chromium/ui/resources/DIR_METADATA
deleted file mode 100644
index f31293e3139..00000000000
--- a/chromium/ui/resources/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail: {
- component: "UI"
-}
diff --git a/chromium/ui/resources/default_100_percent/common/pointers/sb_h_double_arrow.png b/chromium/ui/resources/default_100_percent/common/pointers/sb_horizontal_double_arrow.png
index a2951a9ef07..a2951a9ef07 100644
--- a/chromium/ui/resources/default_100_percent/common/pointers/sb_h_double_arrow.png
+++ b/chromium/ui/resources/default_100_percent/common/pointers/sb_horizontal_double_arrow.png
Binary files differ
diff --git a/chromium/ui/resources/default_100_percent/common/pointers/sb_h_double_arrow_big.png b/chromium/ui/resources/default_100_percent/common/pointers/sb_horizontal_double_arrow_big.png
index 70861065d4e..70861065d4e 100644
--- a/chromium/ui/resources/default_100_percent/common/pointers/sb_h_double_arrow_big.png
+++ b/chromium/ui/resources/default_100_percent/common/pointers/sb_horizontal_double_arrow_big.png
Binary files differ
diff --git a/chromium/ui/resources/default_100_percent/common/pointers/sb_v_double_arrow.png b/chromium/ui/resources/default_100_percent/common/pointers/sb_vertical_double_arrow.png
index 48c93798714..48c93798714 100644
--- a/chromium/ui/resources/default_100_percent/common/pointers/sb_v_double_arrow.png
+++ b/chromium/ui/resources/default_100_percent/common/pointers/sb_vertical_double_arrow.png
Binary files differ
diff --git a/chromium/ui/resources/default_100_percent/common/pointers/sb_v_double_arrow_big.png b/chromium/ui/resources/default_100_percent/common/pointers/sb_vertical_double_arrow_big.png
index fd777b14bad..fd777b14bad 100644
--- a/chromium/ui/resources/default_100_percent/common/pointers/sb_v_double_arrow_big.png
+++ b/chromium/ui/resources/default_100_percent/common/pointers/sb_vertical_double_arrow_big.png
Binary files differ
diff --git a/chromium/ui/resources/default_200_percent/common/pointers/sb_h_double_arrow.png b/chromium/ui/resources/default_200_percent/common/pointers/sb_horizontal_double_arrow.png
index 299ae1198b7..299ae1198b7 100644
--- a/chromium/ui/resources/default_200_percent/common/pointers/sb_h_double_arrow.png
+++ b/chromium/ui/resources/default_200_percent/common/pointers/sb_horizontal_double_arrow.png
Binary files differ
diff --git a/chromium/ui/resources/default_200_percent/common/pointers/sb_v_double_arrow.png b/chromium/ui/resources/default_200_percent/common/pointers/sb_vertical_double_arrow.png
index 95ca954d5d7..95ca954d5d7 100644
--- a/chromium/ui/resources/default_200_percent/common/pointers/sb_v_double_arrow.png
+++ b/chromium/ui/resources/default_200_percent/common/pointers/sb_vertical_double_arrow.png
Binary files differ
diff --git a/chromium/ui/resources/ui_resources.grd b/chromium/ui/resources/ui_resources.grd
index 38731743307..deda5545b2f 100644
--- a/chromium/ui/resources/ui_resources.grd
+++ b/chromium/ui/resources/ui_resources.grd
@@ -19,13 +19,13 @@
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_ALIAS" file="common/pointers/alias.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_ALIAS" file="common/pointers/alias_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_CELL" file="common/pointers/cell_big.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_COL_RESIZE" file="common/pointers/sb_h_double_arrow_big.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_COL_RESIZE" file="common/pointers/sb_horizontal_double_arrow_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_CONTEXT_MENU" file="common/pointers/context_menu_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_COPY" file="common/pointers/copy_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_CROSSHAIR" file="common/pointers/crosshair_big.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_EAST_RESIZE" file="common/pointers/sb_h_double_arrow_big.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_EAST_RESIZE" file="common/pointers/sb_horizontal_double_arrow_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_EAST_WEST_NO_RESIZE" file="common/pointers/sb_horizontal_double_arrow_block_big.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_EAST_WEST_RESIZE" file="common/pointers/sb_h_double_arrow_big.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_EAST_WEST_RESIZE" file="common/pointers/sb_horizontal_double_arrow_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_GRAB" file="common/pointers/fleur_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_GRABBING" file="common/pointers/hand3_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_HAND" file="common/pointers/hand2_big.png" />
@@ -35,30 +35,30 @@
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_EAST_RESIZE" file="common/pointers/top_right_corner_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_EAST_SOUTH_WEST_NO_RESIZE" file="common/pointers/top_right_corner_block_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_EAST_SOUTH_WEST_RESIZE" file="common/pointers/top_right_corner_big.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_RESIZE" file="common/pointers/sb_v_double_arrow_big.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_RESIZE" file="common/pointers/sb_vertical_double_arrow_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_SOUTH_NO_RESIZE" file="common/pointers/sb_vertical_double_arrow_block_big.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_SOUTH_RESIZE" file="common/pointers/sb_v_double_arrow_big.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_SOUTH_RESIZE" file="common/pointers/sb_vertical_double_arrow_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_WEST_RESIZE" file="common/pointers/top_left_corner_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_WEST_SOUTH_EAST_NO_RESIZE" file="common/pointers/top_left_corner_block_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NORTH_WEST_SOUTH_EAST_RESIZE" file="common/pointers/top_left_corner_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_NO_DROP" file="common/pointers/nodrop_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_PTR" file="common/pointers/left_ptr_big.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_ROW_RESIZE" file="common/pointers/sb_v_double_arrow_big.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_ROW_RESIZE" file="common/pointers/sb_vertical_double_arrow_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_SOUTH_EAST_RESIZE" file="common/pointers/top_left_corner_big.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_SOUTH_RESIZE" file="common/pointers/sb_v_double_arrow_big.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_SOUTH_RESIZE" file="common/pointers/sb_vertical_double_arrow_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_SOUTH_WEST_RESIZE" file="common/pointers/top_right_corner_big.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_WEST_RESIZE" file="common/pointers/sb_h_double_arrow_big.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_WEST_RESIZE" file="common/pointers/sb_horizontal_double_arrow_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_XTERM_HORIZ" file="common/pointers/xterm_horiz_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_ZOOM_IN" file="common/pointers/zoom_in_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_BIG_ZOOM_OUT" file="common/pointers/zoom_out_big.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_CELL" file="common/pointers/cell.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_COL_RESIZE" file="common/pointers/sb_h_double_arrow.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_COL_RESIZE" file="common/pointers/sb_horizontal_double_arrow.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_CONTEXT_MENU" file="common/pointers/context_menu.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_COPY" file="common/pointers/copy.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_CROSSHAIR" file="common/pointers/crosshair.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_EAST_RESIZE" file="common/pointers/sb_h_double_arrow.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_EAST_RESIZE" file="common/pointers/sb_horizontal_double_arrow.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_EAST_WEST_NO_RESIZE" file="common/pointers/sb_horizontal_double_arrow_block.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_EAST_WEST_RESIZE" file="common/pointers/sb_h_double_arrow.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_EAST_WEST_RESIZE" file="common/pointers/sb_horizontal_double_arrow.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_GRAB" file="common/pointers/fleur.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_GRABBING" file="common/pointers/hand3.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_HAND" file="common/pointers/hand2.png" />
@@ -68,20 +68,20 @@
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_NORTH_EAST_RESIZE" file="common/pointers/top_right_corner.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_NORTH_EAST_SOUTH_WEST_NO_RESIZE" file="common/pointers/top_right_corner_block.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_NORTH_EAST_SOUTH_WEST_RESIZE" file="common/pointers/top_right_corner.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_NORTH_RESIZE" file="common/pointers/sb_v_double_arrow.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_NORTH_RESIZE" file="common/pointers/sb_vertical_double_arrow.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_NORTH_SOUTH_NO_RESIZE" file="common/pointers/sb_vertical_double_arrow_block.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_NORTH_SOUTH_RESIZE" file="common/pointers/sb_v_double_arrow.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_NORTH_SOUTH_RESIZE" file="common/pointers/sb_vertical_double_arrow.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_NORTH_WEST_RESIZE" file="common/pointers/top_left_corner.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_NORTH_WEST_SOUTH_EAST_NO_RESIZE" file="common/pointers/top_left_corner_block.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_NORTH_WEST_SOUTH_EAST_RESIZE" file="common/pointers/top_left_corner.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_NO_DROP" file="common/pointers/nodrop.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_PTR" file="common/pointers/left_ptr.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_ROW_RESIZE" file="common/pointers/sb_v_double_arrow.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_ROW_RESIZE" file="common/pointers/sb_vertical_double_arrow.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_SOUTH_EAST_RESIZE" file="common/pointers/top_left_corner.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_SOUTH_RESIZE" file="common/pointers/sb_v_double_arrow.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_SOUTH_RESIZE" file="common/pointers/sb_vertical_double_arrow.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_SOUTH_WEST_RESIZE" file="common/pointers/top_right_corner.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_THROBBER" file="common/pointers/throbber.png" />
- <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_WEST_RESIZE" file="common/pointers/sb_h_double_arrow.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_WEST_RESIZE" file="common/pointers/sb_horizontal_double_arrow.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_XTERM_HORIZ" file="common/pointers/xterm_horiz.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_ZOOM_IN" file="common/pointers/zoom_in.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_ZOOM_OUT" file="common/pointers/zoom_out.png" />
diff --git a/chromium/ui/shell_dialogs/select_file_dialog.h b/chromium/ui/shell_dialogs/select_file_dialog.h
index a367ba2c004..78fc0620987 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog.h
+++ b/chromium/ui/shell_dialogs/select_file_dialog.h
@@ -9,7 +9,6 @@
#include <string>
#include <vector>
-#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_android.h b/chromium/ui/shell_dialogs/select_file_dialog_android.h
index bb9e25b0ee6..f985e695da8 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_android.h
+++ b/chromium/ui/shell_dialogs/select_file_dialog_android.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_SHELL_DIALOGS_ANDROID_SELECT_FILE_DIALOG_ANDROID_H_
-#define UI_SHELL_DIALOGS_ANDROID_SELECT_FILE_DIALOG_ANDROID_H_
+#ifndef UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_ANDROID_H_
+#define UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_ANDROID_H_
#include <jni.h>
@@ -71,5 +71,4 @@ class SelectFileDialogImpl : public SelectFileDialog {
} // namespace ui
-#endif // UI_SHELL_DIALOGS_ANDROID_SELECT_FILE_DIALOG_ANDROID_H_
-
+#endif // UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_ANDROID_H_
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_lacros.cc b/chromium/ui/shell_dialogs/select_file_dialog_lacros.cc
index a3790f50820..df6fc207cf5 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_lacros.cc
+++ b/chromium/ui/shell_dialogs/select_file_dialog_lacros.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/notreached.h"
#include "chromeos/crosapi/mojom/select_file.mojom.h"
-#include "chromeos/lacros/lacros_chrome_service_impl.h"
+#include "chromeos/lacros/lacros_service.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host_platform.h"
#include "ui/platform_window/platform_window.h"
@@ -132,9 +132,10 @@ void SelectFileDialogLacros::SelectFileImpl(
options->owning_shell_window_id = GetShellWindowUniqueId(owning_window);
// Send request to ash-chrome.
- chromeos::LacrosChromeServiceImpl::Get()->select_file_remote()->Select(
- std::move(options),
- base::BindOnce(&SelectFileDialogLacros::OnSelected, this));
+ chromeos::LacrosService::Get()
+ ->GetRemote<crosapi::mojom::SelectFile>()
+ ->Select(std::move(options),
+ base::BindOnce(&SelectFileDialogLacros::OnSelected, this));
}
void SelectFileDialogLacros::OnSelected(
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_win.cc b/chromium/ui/shell_dialogs/select_file_dialog_win.cc
index 8a7437c91d2..00e360549b8 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_win.cc
+++ b/chromium/ui/shell_dialogs/select_file_dialog_win.cc
@@ -15,6 +15,7 @@
#include "base/macros.h"
#include "base/notreached.h"
#include "base/single_thread_task_runner.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
diff --git a/chromium/ui/shell_dialogs/selected_file_info.h b/chromium/ui/shell_dialogs/selected_file_info.h
index 22f014d5ffb..8cf057b0da0 100644
--- a/chromium/ui/shell_dialogs/selected_file_info.h
+++ b/chromium/ui/shell_dialogs/selected_file_info.h
@@ -9,7 +9,7 @@
#include <vector>
#include "base/files/file_path.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/shell_dialogs/shell_dialogs_export.h"
#include "url/gurl.h"
@@ -37,14 +37,14 @@ struct SHELL_DIALOGS_EXPORT SelectedFileInfo {
// using a URL to access the file, it should be used in preference to
// |local_path|. For example, when opening a .gdoc file from Google Drive the
// file is opened by navigating to a docs.google.com URL.
- base::Optional<GURL> url;
+ absl::optional<GURL> url;
// If set, this virtual path may be used to access the file. If the user is
// capable of using a virtual path to access the file (using the file system
// abstraction in //storage/browser/file_system with a
// storage::kFileSystemTypeExternal FileSystemURL), it should be used in
// preference over |local_path| and |url|.
- base::Optional<base::FilePath> virtual_path;
+ absl::optional<base::FilePath> virtual_path;
SelectedFileInfo();
SelectedFileInfo(const base::FilePath& in_file_path,
diff --git a/chromium/ui/snapshot/screenshot_grabber.h b/chromium/ui/snapshot/screenshot_grabber.h
index f27e0322ef2..2740ef2c02f 100644
--- a/chromium/ui/snapshot/screenshot_grabber.h
+++ b/chromium/ui/snapshot/screenshot_grabber.h
@@ -10,7 +10,6 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/ui/snapshot/snapshot.h b/chromium/ui/snapshot/snapshot.h
index 9fbb3b66a6c..ca6c1e6d27d 100644
--- a/chromium/ui/snapshot/snapshot.h
+++ b/chromium/ui/snapshot/snapshot.h
@@ -5,7 +5,6 @@
#ifndef UI_SNAPSHOT_SNAPSHOT_H_
#define UI_SNAPSHOT_SNAPSHOT_H_
-#include <vector>
#include "base/callback_forward.h"
#include "base/memory/ref_counted.h"
diff --git a/chromium/ui/snapshot/snapshot_aura_unittest.cc b/chromium/ui/snapshot/snapshot_aura_unittest.cc
index de78f946209..86824d12dc3 100644
--- a/chromium/ui/snapshot/snapshot_aura_unittest.cc
+++ b/chromium/ui/snapshot/snapshot_aura_unittest.cc
@@ -196,6 +196,9 @@ INSTANTIATE_TEST_SUITE_P(All, SnapshotAuraTest, ::testing::Bool());
#if defined(OS_WIN) && !defined(NDEBUG)
// https://crbug.com/852512
#define MAYBE_FullScreenWindow DISABLED_FullScreenWindow
+#elif defined(OS_LINUX)
+// https://crbug.com/1143031
+#define MAYBE_FullScreenWindow DISABLED_FullScreenWindow
#else
#define MAYBE_FullScreenWindow FullScreenWindow
#endif
diff --git a/chromium/ui/snapshot/snapshot_export.h b/chromium/ui/snapshot/snapshot_export.h
index 9e27370e7a9..557bb0e47e0 100644
--- a/chromium/ui/snapshot/snapshot_export.h
+++ b/chromium/ui/snapshot/snapshot_export.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_SNAPSHOT_SNAPSHOT_EXPORT_H
-#define UI_SNAPSHOT_SNAPSHOT_EXPORT_H
+#ifndef UI_SNAPSHOT_SNAPSHOT_EXPORT_H_
+#define UI_SNAPSHOT_SNAPSHOT_EXPORT_H_
// Defines SNAPSHOT_EXPORT so that functionality implemented by the snapshot
// module can be exported to consumers.
@@ -29,4 +29,4 @@
#define SNAPSHOT_EXPORT
#endif
-#endif // UI_SNAPSHOT_SNAPSHOT_EXPORT_H
+#endif // UI_SNAPSHOT_SNAPSHOT_EXPORT_H_
diff --git a/chromium/ui/snapshot/snapshot_win.cc b/chromium/ui/snapshot/snapshot_win.cc
index 35fc4daa7a1..6425aa4bc94 100644
--- a/chromium/ui/snapshot/snapshot_win.cc
+++ b/chromium/ui/snapshot/snapshot_win.cc
@@ -15,6 +15,7 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/image/image.h"
+#include "ui/gfx/skia_util.h"
#include "ui/snapshot/snapshot.h"
#include "ui/snapshot/snapshot_aura.h"
diff --git a/chromium/ui/strings/translations/ui_strings_az.xtb b/chromium/ui/strings/translations/ui_strings_az.xtb
index e99e759387f..8b671423d7e 100644
--- a/chromium/ui/strings/translations/ui_strings_az.xtb
+++ b/chromium/ui/strings/translations/ui_strings_az.xtb
@@ -116,7 +116,7 @@
<translation id="3990502903496589789">Sağ Künc</translation>
<translation id="40579289237549812">{UNREAD_NOTIFICATIONS,plural, =1{1 Oxunmamış Bildiriş}other{# Oxunmamış Bildiriş}}</translation>
<translation id="4202807286478387388">keçid</translation>
-<translation id="4250229828105606438">Ani görüntü</translation>
+<translation id="4250229828105606438">Skrinşot</translation>
<translation id="4266252015790371705">{MONTHS,plural, =1{1 ay əvvəl}other{# ay əvvəl}}</translation>
<translation id="4289300219472526559">Danışmağa başlayın</translation>
<translation id="430191667033048642"><ph name="MOVED_APP_NAME" /> <ph name="FOLDER_NAME" /> qovluğuna köçürülüb.</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_gu.xtb b/chromium/ui/strings/translations/ui_strings_gu.xtb
index 3d6cc7c8708..a9aba247e87 100644
--- a/chromium/ui/strings/translations/ui_strings_gu.xtb
+++ b/chromium/ui/strings/translations/ui_strings_gu.xtb
@@ -86,7 +86,7 @@
<translation id="3068711042108640621">શેલ્ફ ડાબી બાજુએ છે</translation>
<translation id="3087734570205094154">તળિયું</translation>
<translation id="3126026824346185272">Ctrl</translation>
-<translation id="3157931365184549694">પુનઃસ્થાપિત કરો</translation>
+<translation id="3157931365184549694">રિસ્ટોર કરો</translation>
<translation id="3183922693828471536">અહીં સુધી સ્ક્રોલ કરો</translation>
<translation id="3234408098842461169">નીચલો એરો</translation>
<translation id="3291688615589870984">{DAYS,plural, =1{1 દિવસ}one{# દિવસ}other{# દિવસ}}</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_sv.xtb b/chromium/ui/strings/translations/ui_strings_sv.xtb
index 41618cf65a1..ebe91e6e53e 100644
--- a/chromium/ui/strings/translations/ui_strings_sv.xtb
+++ b/chromium/ui/strings/translations/ui_strings_sv.xtb
@@ -123,7 +123,7 @@
<translation id="4306392492252714209">Ta bort från urklipp.</translation>
<translation id="4316910396681052118">ALLA APPAR</translation>
<translation id="4491109536499578614">Bild</translation>
-<translation id="4588090240171750605">Rulla åt höger</translation>
+<translation id="4588090240171750605">Scrolla åt höger</translation>
<translation id="4631891353005174729"><ph name="APP_NAME_TYPE" />, betyg <ph name="RATING_SCORE" /></translation>
<translation id="4648249871170053485"><ph name="APP_NAME" />, apprekommendation</translation>
<translation id="4690510401873698237">Hyllan längst ned</translation>
@@ -175,7 +175,7 @@
<translation id="6166852626429024716">Sök på enheten, i appar, inställningar och på webben …</translation>
<translation id="6264365405983206840">Markera &amp;alla</translation>
<translation id="6351032674660237738">APPFÖRSLAG</translation>
-<translation id="6364916375976753737">Rulla åt vänster</translation>
+<translation id="6364916375976753737">Scrolla åt vänster</translation>
<translation id="6394627529324717982">Komma</translation>
<translation id="6397363302884558537">Sluta tala</translation>
<translation id="6404817160109697034">{SECONDS,plural, =1{för 1 sek sedan}other{för # sek sedan}}</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_ta.xtb b/chromium/ui/strings/translations/ui_strings_ta.xtb
index ee55dfd7d61..9fc61229396 100644
--- a/chromium/ui/strings/translations/ui_strings_ta.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ta.xtb
@@ -81,7 +81,7 @@
<translation id="2907671656515444832">{DAYS,plural, =1{இன்னும் 1நா}other{இன்னும் #நா}}</translation>
<translation id="2931838996092594335">கிளிக் செய்க</translation>
<translation id="2981684127883932071">பரிந்துரைகளைக் காட்டுகிறது</translation>
-<translation id="3036649622769666520">கோப்புகளைத் திற</translation>
+<translation id="3036649622769666520">ஃபைல்களைத் திற</translation>
<translation id="3049748772180311791"><ph name="QUANTITY" /> மெ.பை</translation>
<translation id="3068711042108640621">ஷெல்ஃப் இடப்புறம் உள்ளது</translation>
<translation id="3087734570205094154">கீழே</translation>
@@ -188,7 +188,7 @@
<translation id="6567071839949112727">ஆன்செஸ்டரைக் கிளிக் செய்</translation>
<translation id="6578407462441924264">பெயரிடப்படாதது</translation>
<translation id="6612467943526193239">அளவுத்திருத்தத்திலிருந்து வெளியேற, Esc எனும் விசையை அழுத்தவும்.</translation>
-<translation id="6620110761915583480">கோப்பைச் சேமி</translation>
+<translation id="6620110761915583480">ஃபைலைச் சேமி</translation>
<translation id="6699343763173986273">ஊடகத்தின் அடுத்த டிராக்</translation>
<translation id="6710213216561001401">முந்தையது</translation>
<translation id="6786750046913594791">கோப்புறையை மூடு</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_te.xtb b/chromium/ui/strings/translations/ui_strings_te.xtb
index 2bd79e22036..4efa30e616f 100644
--- a/chromium/ui/strings/translations/ui_strings_te.xtb
+++ b/chromium/ui/strings/translations/ui_strings_te.xtb
@@ -243,7 +243,7 @@
<translation id="8331626408530291785">పైకి స్క్రోల్ చేయి</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 సంవత్సరం}other{# సంవత్సరాలు}}</translation>
<translation id="838869780401515933">తనిఖీ చేయి</translation>
-<translation id="8393700583063109961">సందేశాన్ని పంపండి</translation>
+<translation id="8393700583063109961">మెసేజ్‌ను పంపండి</translation>
<translation id="8394908167088220973">మీడియా ప్లే/పాజ్</translation>
<translation id="8458811141851741261">{YEARS,plural, =1{1సం}other{#సం}}</translation>
<translation id="8602707065186045623"><ph name="SAVEAS_EXTENSION_TYPE" /> ఫైల్ (.<ph name="SAVEAS_EXTENSION_NAME" />)</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_uz.xtb b/chromium/ui/strings/translations/ui_strings_uz.xtb
index d2bb2375fc5..f42b4e3c320 100644
--- a/chromium/ui/strings/translations/ui_strings_uz.xtb
+++ b/chromium/ui/strings/translations/ui_strings_uz.xtb
@@ -1,7 +1,7 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="uz">
-<translation id="1028699632127661925"><ph name="DEVICE_NAME" /> qurilmasiga yuborilmoqda...</translation>
+<translation id="1028699632127661925">Bunga yuborilmoqda: <ph name="DEVICE_NAME" />...</translation>
<translation id="111910763555783249">Bildirishnoma sozlamalari</translation>
<translation id="1127811143501539442">{DAYS,plural, =1{1 kun oldin}other{# kun oldin}}</translation>
<translation id="1156623771253174079">{SECONDS,plural, =1{1 daqiqa oldin}other{# daqiqa oldin}}</translation>
diff --git a/chromium/ui/strings/ui_strings.grd b/chromium/ui/strings/ui_strings.grd
index 1613ffe6de3..32b38281c6f 100644
--- a/chromium/ui/strings/ui_strings.grd
+++ b/chromium/ui/strings/ui_strings.grd
@@ -1074,7 +1074,7 @@ need to be translated for each locale.-->
</message>
<!-- Clipboard history menu -->
- <message name="IDS_CLIPBOARD_HISTORY_MENU_BITMAP_IMAGE" desc="Accessibility text for the bitmap image shown on the clipboard history menu">
+ <message name="IDS_CLIPBOARD_HISTORY_MENU_PNG_IMAGE" desc="Accessibility text for the PNG image shown on the clipboard history menu">
Image.
</message>
<message name="IDS_CLIPBOARD_HISTORY_MENU_HTML_IMAGE" desc="Accessibility text for the HTML-rendered image shown on the clipboard history menu">
diff --git a/chromium/ui/strings/ui_strings_grd/IDS_CLIPBOARD_HISTORY_MENU_BITMAP_IMAGE.png.sha1 b/chromium/ui/strings/ui_strings_grd/IDS_CLIPBOARD_HISTORY_MENU_PNG_IMAGE.png.sha1
index 4249a207108..4249a207108 100644
--- a/chromium/ui/strings/ui_strings_grd/IDS_CLIPBOARD_HISTORY_MENU_BITMAP_IMAGE.png.sha1
+++ b/chromium/ui/strings/ui_strings_grd/IDS_CLIPBOARD_HISTORY_MENU_PNG_IMAGE.png.sha1
diff --git a/chromium/ui/surface/DIR_METADATA b/chromium/ui/surface/DIR_METADATA
deleted file mode 100644
index f31293e3139..00000000000
--- a/chromium/ui/surface/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail: {
- component: "UI"
-}
diff --git a/chromium/ui/touch_selection/DEPS b/chromium/ui/touch_selection/DEPS
index 5b830344f32..b6852ea62f5 100644
--- a/chromium/ui/touch_selection/DEPS
+++ b/chromium/ui/touch_selection/DEPS
@@ -2,6 +2,7 @@ include_rules = [
"+ui/aura",
"+ui/aura_extra",
"+ui/base",
+ "+ui/compositor",
"+ui/events",
"+ui/gfx",
"+ui/resources"
diff --git a/chromium/ui/touch_selection/selection_event_type.h b/chromium/ui/touch_selection/selection_event_type.h
index ede8e8de8a7..f55e0ad42ee 100644
--- a/chromium/ui/touch_selection/selection_event_type.h
+++ b/chromium/ui/touch_selection/selection_event_type.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_TOUCH_SELECTION_SELECTION_EVENT_TYPE_
-#define UI_TOUCH_SELECTION_SELECTION_EVENT_TYPE_
+#ifndef UI_TOUCH_SELECTION_SELECTION_EVENT_TYPE_H_
+#define UI_TOUCH_SELECTION_SELECTION_EVENT_TYPE_H_
namespace ui {
@@ -28,4 +28,4 @@ enum SelectionEventType {
} // namespace ui
-#endif // UI_TOUCH_SELECTION_SELECTION_EVENT_TYPE_
+#endif // UI_TOUCH_SELECTION_SELECTION_EVENT_TYPE_H_
diff --git a/chromium/ui/touch_selection/touch_handle_drawable_aura.cc b/chromium/ui/touch_selection/touch_handle_drawable_aura.cc
index fb2e8f88b72..f98d664ab08 100644
--- a/chromium/ui/touch_selection/touch_handle_drawable_aura.cc
+++ b/chromium/ui/touch_selection/touch_handle_drawable_aura.cc
@@ -10,6 +10,7 @@
#include "ui/base/cursor/cursor.h"
#include "ui/base/hit_test.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/compositor/layer.h"
#include "ui/events/event.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/rect_conversions.h"
diff --git a/chromium/ui/touch_selection/touch_handle_orientation.h b/chromium/ui/touch_selection/touch_handle_orientation.h
index e76e73e9e69..55e091035ae 100644
--- a/chromium/ui/touch_selection/touch_handle_orientation.h
+++ b/chromium/ui/touch_selection/touch_handle_orientation.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_TOUCH_SELECTION_TOUCH_HANDLE_ORIENTATION_
-#define UI_TOUCH_SELECTION_TOUCH_HANDLE_ORIENTATION_
+#ifndef UI_TOUCH_SELECTION_TOUCH_HANDLE_ORIENTATION_H_
+#define UI_TOUCH_SELECTION_TOUCH_HANDLE_ORIENTATION_H_
namespace ui {
@@ -21,4 +21,4 @@ enum class TouchHandleOrientation {
} // namespace ui
-#endif // UI_TOUCH_SELECTION_TOUCH_HANDLE_ORIENTATION_
+#endif // UI_TOUCH_SELECTION_TOUCH_HANDLE_ORIENTATION_H_
diff --git a/chromium/ui/touch_selection/touch_selection_draggable.h b/chromium/ui/touch_selection/touch_selection_draggable.h
index 2c7217415cd..5a38534da0a 100644
--- a/chromium/ui/touch_selection/touch_selection_draggable.h
+++ b/chromium/ui/touch_selection/touch_selection_draggable.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_TOUCH_SELECTION_DRAG_DRAGGABLE_H_
-#define UI_TOUCH_SELECTION_DRAG_DRAGGABLE_H_
+#ifndef UI_TOUCH_SELECTION_TOUCH_SELECTION_DRAGGABLE_H_
+#define UI_TOUCH_SELECTION_TOUCH_SELECTION_DRAGGABLE_H_
#include "ui/gfx/geometry/point_f.h"
#include "ui/touch_selection/ui_touch_selection_export.h"
@@ -49,4 +49,4 @@ class UI_TOUCH_SELECTION_EXPORT TouchSelectionDraggable {
} // namespace ui
-#endif // UI_TOUCH_SELECTION_DRAG_DRAGGABLE_H_
+#endif // UI_TOUCH_SELECTION_TOUCH_SELECTION_DRAGGABLE_H_
diff --git a/chromium/ui/views/.clang-tidy b/chromium/ui/views/.clang-tidy
index b6c0d7fc364..09fa8554dbf 100644
--- a/chromium/ui/views/.clang-tidy
+++ b/chromium/ui/views/.clang-tidy
@@ -4,4 +4,5 @@
modernize-replace-auto-ptr,
modernize-use-using'
HeaderFilterRegex: 'ui/views/*'
+ InheritParentConfig: true
...
diff --git a/chromium/ui/views/BUILD.gn b/chromium/ui/views/BUILD.gn
index c0e55a44f12..bc83b44f386 100644
--- a/chromium/ui/views/BUILD.gn
+++ b/chromium/ui/views/BUILD.gn
@@ -42,7 +42,6 @@ aggregate_vector_icons("views_vector_icons") {
"pin.icon",
"radio_button_active.icon",
"radio_button_normal.icon",
- "submenu_arrow.icon",
"uninstall.icon",
"unpin.icon",
]
@@ -160,10 +159,10 @@ component("views") {
"controls/resize_area.h",
"controls/resize_area_delegate.h",
"controls/scroll_view.h",
- "controls/scrollbar/base_scroll_bar_button.h",
"controls/scrollbar/base_scroll_bar_thumb.h",
"controls/scrollbar/overlay_scroll_bar.h",
"controls/scrollbar/scroll_bar.h",
+ "controls/scrollbar/scroll_bar_button.h",
"controls/scrollbar/scroll_bar_views.h",
"controls/separator.h",
"controls/slider.h",
@@ -198,6 +197,8 @@ component("views") {
"focus/widget_focus_manager.h",
"image_model_utils.h",
"input_event_activation_protector.h",
+ "interaction/element_tracker_views.h",
+ "interaction/interaction_sequence_views.h",
"layout/animating_layout_manager.h",
"layout/box_layout.h",
"layout/box_layout_view.h",
@@ -213,12 +214,6 @@ component("views") {
"layout/normalized_geometry.h",
"layout/proposed_layout.h",
"masked_targeter_delegate.h",
- "metadata/metadata_cache.h",
- "metadata/metadata_header_macros.h",
- "metadata/metadata_impl_macros.h",
- "metadata/metadata_macros_internal.h",
- "metadata/metadata_types.h",
- "metadata/property_metadata.h",
"metadata/type_conversion.h",
"metadata/view_factory.h",
"metadata/view_factory_internal.h",
@@ -376,10 +371,10 @@ component("views") {
"controls/progress_bar.cc",
"controls/resize_area.cc",
"controls/scroll_view.cc",
- "controls/scrollbar/base_scroll_bar_button.cc",
"controls/scrollbar/base_scroll_bar_thumb.cc",
"controls/scrollbar/overlay_scroll_bar.cc",
"controls/scrollbar/scroll_bar.cc",
+ "controls/scrollbar/scroll_bar_button.cc",
"controls/scrollbar/scroll_bar_views.cc",
"controls/separator.cc",
"controls/slider.cc",
@@ -407,6 +402,8 @@ component("views") {
"focus/widget_focus_manager.cc",
"image_model_utils.cc",
"input_event_activation_protector.cc",
+ "interaction/element_tracker_views.cc",
+ "interaction/interaction_sequence_views.cc",
"layout/animating_layout_manager.cc",
"layout/box_layout.cc",
"layout/box_layout_view.cc",
@@ -422,8 +419,6 @@ component("views") {
"layout/normalized_geometry.cc",
"layout/proposed_layout.cc",
"masked_targeter_delegate.cc",
- "metadata/metadata_cache.cc",
- "metadata/metadata_types.cc",
"metadata/type_conversion.cc",
"metadata/view_factory_internal.cc",
"metrics.cc",
@@ -794,7 +789,6 @@ component("views") {
"widget/desktop_aura/desktop_focus_rules.cc",
"widget/desktop_aura/desktop_native_cursor_manager.cc",
"widget/desktop_aura/desktop_native_widget_aura.cc",
- "widget/desktop_aura/desktop_screen.cc",
"widget/desktop_aura/desktop_screen_position_client.cc",
"widget/desktop_aura/desktop_window_tree_host.cc",
]
@@ -819,7 +813,10 @@ component("views") {
"widget/desktop_aura/desktop_screen_win.h",
"widget/desktop_aura/desktop_window_tree_host_win.cc",
]
- deps += [ "//ui/events:dom_keyboard_layout" ]
+ deps += [
+ "//ui/events:dom_keyboard_layout",
+ "//ui/events:keyboard_hook",
+ ]
}
if (use_ozone) {
public += [ "widget/desktop_aura/desktop_screen_ozone.h" ]
@@ -846,9 +843,8 @@ component("views") {
"widget/desktop_aura/desktop_drag_drop_client_ozone.h",
"widget/desktop_aura/desktop_window_tree_host_platform.cc",
"widget/desktop_aura/window_move_client_platform.cc",
- "widget/desktop_aura/window_shape_updater.cc",
- "widget/desktop_aura/window_shape_updater.h",
]
+ public_deps += [ "//ui/base/dragdrop/mojom:mojom_shared" ]
}
if (use_atk) {
sources += [
@@ -922,6 +918,8 @@ source_set("test_support") {
"animation/test/test_ink_drop_host.h",
"animation/test/test_ink_drop_ripple_observer.cc",
"animation/test/test_ink_drop_ripple_observer.h",
+ "controls/table/test_table_model.cc",
+ "controls/table/test_table_model.h",
"controls/textfield/textfield_test_api.cc",
"controls/textfield/textfield_test_api.h",
"layout/animating_layout_manager_test_util.cc",
@@ -968,6 +966,8 @@ source_set("test_support") {
"test/views_test_base.h",
"test/views_test_helper.cc",
"test/views_test_helper.h",
+ "test/widget_animation_waiter.cc",
+ "test/widget_animation_waiter.h",
"test/widget_test.cc",
"test/widget_test.h",
"test/widget_test_api.cc",
@@ -1141,7 +1141,7 @@ test("views_unittests") {
"controls/progress_bar_unittest.cc",
"controls/resize_area_unittest.cc",
"controls/scroll_view_unittest.cc",
- "controls/scrollbar/base_scroll_bar_button_unittest.cc",
+ "controls/scrollbar/scroll_bar_button_unittest.cc",
"controls/scrollbar/scrollbar_unittest.cc",
"controls/separator_unittest.cc",
"controls/slider_unittest.cc",
@@ -1149,8 +1149,6 @@ test("views_unittests") {
"controls/tabbed_pane/tabbed_pane_unittest.cc",
"controls/table/table_utils_unittest.cc",
"controls/table/table_view_unittest.cc",
- "controls/table/test_table_model.cc",
- "controls/table/test_table_model.h",
"controls/textarea/textarea_unittest.cc",
"controls/textfield/textfield_model_unittest.cc",
"controls/textfield/textfield_unittest.cc",
@@ -1160,6 +1158,8 @@ test("views_unittests") {
"focus/focus_manager_unittest.cc",
"focus/focus_traversal_unittest.cc",
"image_model_utils_unittest.cc",
+ "interaction/element_tracker_views_unittest.cc",
+ "interaction/interaction_sequence_views_unittest.cc",
"layout/animating_layout_manager_unittest.cc",
"layout/box_layout_unittest.cc",
"layout/box_layout_view_unittest.cc",
@@ -1171,7 +1171,6 @@ test("views_unittests") {
"layout/layout_manager_base_unittest.cc",
"layout/normalized_geometry_unittest.cc",
"layout/proposed_layout_unittest.cc",
- "metadata/metadata_unittest.cc",
"metadata/type_conversion_unittest.cc",
"metadata/view_factory_unittest.cc",
"paint_info_unittest.cc",
@@ -1196,7 +1195,6 @@ test("views_unittests") {
"window/dialog_delegate_unittest.cc",
"window/frame_caption_button_unittest.cc",
"window/hit_test_utils_unittest.cc",
- "window/non_client_view_unittest.cc",
]
configs += [ "//build/config:precompiled_headers" ]
@@ -1359,7 +1357,10 @@ test("views_unittests") {
"widget/desktop_aura/desktop_screen_x11_unittest.cc",
"widget/desktop_aura/x11_drag_drop_client_unittest.cc",
]
- deps += [ "//ui/base/x:test_support" ]
+ deps += [
+ "//ui/base/x",
+ "//ui/base/x:test_support",
+ ]
}
if (is_linux || is_chromeos || is_fuchsia) {
sources += [
@@ -1391,7 +1392,10 @@ test("views_unittests") {
}
if (use_ozone) {
- deps += [ "//ui/ozone" ]
+ deps += [
+ "//ui/ozone",
+ "//ui/events/ozone/layout:test_support",
+ ]
}
if (is_linux || is_chromeos) {
diff --git a/chromium/ui/views/accessibility/ax_aura_obj_cache.cc b/chromium/ui/views/accessibility/ax_aura_obj_cache.cc
index 667f30d4fdb..8ab62ea237b 100644
--- a/chromium/ui/views/accessibility/ax_aura_obj_cache.cc
+++ b/chromium/ui/views/accessibility/ax_aura_obj_cache.cc
@@ -16,6 +16,8 @@
#include "ui/aura/window_observer.h"
#include "ui/views/accessibility/ax_aura_obj_wrapper.h"
#include "ui/views/accessibility/ax_view_obj_wrapper.h"
+#include "ui/views/accessibility/ax_virtual_view.h"
+#include "ui/views/accessibility/ax_virtual_view_wrapper.h"
#include "ui/views/accessibility/ax_widget_obj_wrapper.h"
#include "ui/views/accessibility/ax_window_obj_wrapper.h"
#include "ui/views/accessibility/view_accessibility.h"
@@ -75,6 +77,14 @@ AXAuraObjWrapper* AXAuraObjCache::GetOrCreate(View* view) {
return CreateInternal<AXViewObjWrapper>(view, &view_to_id_map_);
}
+AXAuraObjWrapper* AXAuraObjCache::GetOrCreate(AXVirtualView* virtual_view) {
+ if (!virtual_view->GetOwnerView() ||
+ !virtual_view->GetOwnerView()->GetWidget())
+ return nullptr;
+ return CreateInternal<AXVirtualViewWrapper>(virtual_view,
+ &virtual_view_to_id_map_);
+}
+
AXAuraObjWrapper* AXAuraObjCache::GetOrCreate(Widget* widget) {
return CreateInternal<AXWidgetObjWrapper>(widget, &widget_to_id_map_);
}
@@ -91,6 +101,10 @@ int32_t AXAuraObjCache::GetID(View* view) const {
return GetIDInternal(view, view_to_id_map_);
}
+int32_t AXAuraObjCache::GetID(AXVirtualView* virtual_view) const {
+ return GetIDInternal(virtual_view, virtual_view_to_id_map_);
+}
+
int32_t AXAuraObjCache::GetID(Widget* widget) const {
return GetIDInternal(widget, widget_to_id_map_);
}
@@ -103,6 +117,10 @@ void AXAuraObjCache::Remove(View* view) {
RemoveInternal(view, &view_to_id_map_);
}
+void AXAuraObjCache::Remove(AXVirtualView* virtual_view) {
+ RemoveInternal(virtual_view, &virtual_view_to_id_map_);
+}
+
void AXAuraObjCache::RemoveViewSubtree(View* view) {
Remove(view);
for (View* child : view->children())
@@ -175,6 +193,9 @@ AXAuraObjCache::AXAuraObjCache()
AXAuraObjCache::~AXAuraObjCache() {
if (!root_windows_.empty() && GetFocusClient(*root_windows_.begin()))
GetFocusClient(*root_windows_.begin())->RemoveObserver(this);
+
+ for (auto& entry : virtual_view_to_id_map_)
+ entry.first->set_cache(nullptr);
}
View* AXAuraObjCache::GetFocusedView() {
diff --git a/chromium/ui/views/accessibility/ax_aura_obj_cache.h b/chromium/ui/views/accessibility/ax_aura_obj_cache.h
index 1b3931ec72b..646c739ac58 100644
--- a/chromium/ui/views/accessibility/ax_aura_obj_cache.h
+++ b/chromium/ui/views/accessibility/ax_aura_obj_cache.h
@@ -28,6 +28,7 @@ class NoDestructor;
namespace views {
class AXAuraObjWrapper;
+class AXVirtualView;
class View;
class Widget;
@@ -51,6 +52,7 @@ class VIEWS_EXPORT AXAuraObjCache : public aura::client::FocusChangeObserver {
// Get or create an entry in the cache. May return null if the View is not
// associated with a Widget.
AXAuraObjWrapper* GetOrCreate(View* view);
+ AXAuraObjWrapper* GetOrCreate(AXVirtualView* virtual_view);
// Get or create an entry in the cache.
AXAuraObjWrapper* GetOrCreate(Widget* widget);
@@ -63,11 +65,13 @@ class VIEWS_EXPORT AXAuraObjCache : public aura::client::FocusChangeObserver {
// Gets an id given an Aura view.
ui::AXNodeID GetID(View* view) const;
+ ui::AXNodeID GetID(AXVirtualView* view) const;
ui::AXNodeID GetID(Widget* widget) const;
ui::AXNodeID GetID(aura::Window* window) const;
// Removes an entry from this cache based on an Aura view.
void Remove(View* view);
+ void Remove(AXVirtualView* view);
void Remove(Widget* widget);
// Removes |window| and optionally notifies delegate by sending an event on
@@ -149,6 +153,7 @@ class VIEWS_EXPORT AXAuraObjCache : public aura::client::FocusChangeObserver {
std::unique_ptr<A11yOverrideWindowObserver> a11y_override_window_observer_;
std::map<views::View*, ui::AXNodeID> view_to_id_map_;
+ std::map<views::AXVirtualView*, ui::AXNodeID> virtual_view_to_id_map_;
std::map<views::Widget*, ui::AXNodeID> widget_to_id_map_;
std::map<aura::Window*, ui::AXNodeID> window_to_id_map_;
diff --git a/chromium/ui/views/accessibility/ax_aura_obj_cache_unittest.cc b/chromium/ui/views/accessibility/ax_aura_obj_cache_unittest.cc
index 7ec62ddd4df..e7f751d074b 100644
--- a/chromium/ui/views/accessibility/ax_aura_obj_cache_unittest.cc
+++ b/chromium/ui/views/accessibility/ax_aura_obj_cache_unittest.cc
@@ -21,6 +21,8 @@
#include "ui/views/accessibility/ax_event_manager.h"
#include "ui/views/accessibility/ax_event_observer.h"
#include "ui/views/accessibility/ax_tree_source_views.h"
+#include "ui/views/accessibility/ax_virtual_view.h"
+#include "ui/views/accessibility/ax_virtual_view_wrapper.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/test/widget_test.h"
@@ -147,7 +149,7 @@ TEST_F(AXAuraObjCacheTest, GetFocusIsUnignoredAncestor) {
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
params.bounds = gfx::Rect(0, 0, 200, 200);
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
+ params.activatable = views::Widget::InitParams::Activatable::kYes;
widget->Init(std::move(params));
widget->Show();
@@ -253,7 +255,7 @@ TEST_F(AXAuraObjCacheTest, DoNotCreateWidgetWrapperOnDestroyed) {
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
params.bounds = gfx::Rect(0, 0, 200, 200);
- params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
+ params.activatable = views::Widget::InitParams::Activatable::kYes;
params.delegate = delegate;
widget->Init(std::move(params));
widget->Show();
@@ -267,6 +269,33 @@ TEST_F(AXAuraObjCacheTest, DoNotCreateWidgetWrapperOnDestroyed) {
EXPECT_EQ(ui::kInvalidAXNodeID, cache.GetID(widget));
}
+TEST_F(AXAuraObjCacheTest, VirtualViews) {
+ AXAuraObjCache cache;
+ auto widget = std::make_unique<Widget>();
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.bounds = gfx::Rect(0, 0, 200, 200);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.activatable = views::Widget::InitParams::Activatable::kYes;
+ widget->Init(std::move(params));
+ widget->Show();
+
+ View* parent = new View();
+ widget->GetRootView()->AddChildView(parent);
+ auto* virtual_label = new AXVirtualView;
+ virtual_label->GetCustomData().role = ax::mojom::Role::kStaticText;
+ virtual_label->GetCustomData().SetName("Label");
+ parent->GetViewAccessibility().AddVirtualChildView(
+ base::WrapUnique(virtual_label));
+
+ auto* wrapper = virtual_label->GetOrCreateWrapper(&cache);
+ ui::AXNodeID id = wrapper->GetUniqueId();
+ auto* wrapper2 = cache.Get(id);
+ EXPECT_EQ(wrapper, wrapper2);
+
+ parent->GetViewAccessibility().RemoveVirtualChildView(virtual_label);
+ EXPECT_EQ(nullptr, cache.Get(id));
+}
+
} // namespace
} // namespace test
} // namespace views
diff --git a/chromium/ui/views/accessibility/ax_event_manager.cc b/chromium/ui/views/accessibility/ax_event_manager.cc
index 7e1fd0f3f97..d46d12e1326 100644
--- a/chromium/ui/views/accessibility/ax_event_manager.cc
+++ b/chromium/ui/views/accessibility/ax_event_manager.cc
@@ -33,4 +33,10 @@ void AXEventManager::NotifyViewEvent(views::View* view,
observer.OnViewEvent(view, event_type);
}
+void AXEventManager::NotifyVirtualViewEvent(views::AXVirtualView* virtual_view,
+ ax::mojom::Event event_type) {
+ for (AXEventObserver& observer : observers_)
+ observer.OnVirtualViewEvent(virtual_view, event_type);
+}
+
} // namespace views
diff --git a/chromium/ui/views/accessibility/ax_event_manager.h b/chromium/ui/views/accessibility/ax_event_manager.h
index 0e7345209f4..c491ee0808d 100644
--- a/chromium/ui/views/accessibility/ax_event_manager.h
+++ b/chromium/ui/views/accessibility/ax_event_manager.h
@@ -12,6 +12,7 @@
namespace views {
class AXEventObserver;
+class AXVirtualView;
class View;
// AXEventManager allows observation of accessibility events for all views.
@@ -30,6 +31,8 @@ class VIEWS_EXPORT AXEventManager {
// Notifies observers of an accessibility event. |view| must not be null.
void NotifyViewEvent(views::View* view, ax::mojom::Event event_type);
+ void NotifyVirtualViewEvent(views::AXVirtualView* virtual_view,
+ ax::mojom::Event event_type);
private:
base::ObserverList<AXEventObserver> observers_;
diff --git a/chromium/ui/views/accessibility/ax_event_observer.h b/chromium/ui/views/accessibility/ax_event_observer.h
index 9dfd0a2c95a..96584793b48 100644
--- a/chromium/ui/views/accessibility/ax_event_observer.h
+++ b/chromium/ui/views/accessibility/ax_event_observer.h
@@ -11,12 +11,15 @@
namespace views {
+class AXVirtualView;
class View;
// AXEventObserver is notified for accessibility events on all views.
class VIEWS_EXPORT AXEventObserver : public base::CheckedObserver {
public:
virtual void OnViewEvent(views::View* view, ax::mojom::Event event_type) = 0;
+ virtual void OnVirtualViewEvent(views::AXVirtualView* virtual_view,
+ ax::mojom::Event event_type) {}
protected:
AXEventObserver();
diff --git a/chromium/ui/views/accessibility/ax_virtual_view.cc b/chromium/ui/views/accessibility/ax_virtual_view.cc
index 5a6cdd44feb..e79529af525 100644
--- a/chromium/ui/views/accessibility/ax_virtual_view.cc
+++ b/chromium/ui/views/accessibility/ax_virtual_view.cc
@@ -20,6 +20,7 @@
#include "ui/base/layout.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/views/accessibility/ax_event_manager.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/accessibility/view_ax_platform_node_delegate.h"
#include "ui/views/view.h"
@@ -65,6 +66,11 @@ AXVirtualView::~AXVirtualView() {
ax_platform_node_->Destroy();
ax_platform_node_ = nullptr;
}
+
+#if defined(USE_AURA)
+ if (ax_aura_obj_cache_)
+ ax_aura_obj_cache_->Remove(this);
+#endif
}
void AXVirtualView::AddChildView(std::unique_ptr<AXVirtualView> view) {
@@ -202,7 +208,12 @@ void AXVirtualView::NotifyAccessibilityEvent(ax::mojom::Event event_type) {
if (events_callback)
events_callback.Run(this, event_type);
}
+
+ // This is used on platforms that have a native accessibility API.
ax_platform_node_->NotifyAccessibilityEvent(event_type);
+
+ // This is used on platforms that don't have a native accessibility API.
+ AXEventManager::Get()->NotifyVirtualViewEvent(this, event_type);
}
ui::AXNodeData& AXVirtualView::GetCustomData() {
@@ -287,7 +298,7 @@ gfx::NativeViewAccessible AXVirtualView::ChildAtIndex(int index) {
return nullptr;
}
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
gfx::NativeViewAccessible AXVirtualView::GetNSWindow() {
NOTREACHED();
return nullptr;
@@ -432,7 +443,7 @@ gfx::AcceleratedWidget AXVirtualView::GetTargetForNativeAccessibilityEvent() {
return gfx::kNullAcceleratedWidget;
}
-base::Optional<bool> AXVirtualView::GetTableHasColumnOrRowHeaderNode() const {
+absl::optional<bool> AXVirtualView::GetTableHasColumnOrRowHeaderNode() const {
return GetDelegate()->GetTableHasColumnOrRowHeaderNode();
}
@@ -444,7 +455,7 @@ std::vector<int32_t> AXVirtualView::GetColHeaderNodeIds(int col_index) const {
return GetDelegate()->GetColHeaderNodeIds(col_index);
}
-base::Optional<int32_t> AXVirtualView::GetCellId(int row_index,
+absl::optional<int32_t> AXVirtualView::GetCellId(int row_index,
int col_index) const {
return GetDelegate()->GetCellId(row_index, col_index);
}
@@ -508,11 +519,10 @@ ViewAXPlatformNodeDelegate* AXVirtualView::GetDelegate() const {
AXVirtualViewWrapper* AXVirtualView::GetOrCreateWrapper(
views::AXAuraObjCache* cache) {
#if defined(USE_AURA)
- // cache might be recreated, and if cache is new, recreate the wrapper.
- if (!wrapper_ || wrapper_->cache() != cache)
- wrapper_ = std::make_unique<AXVirtualViewWrapper>(this, cache);
+ return static_cast<AXVirtualViewWrapper*>(cache->GetOrCreate(this));
+#else
+ return nullptr;
#endif
- return wrapper_.get();
}
} // namespace views
diff --git a/chromium/ui/views/accessibility/ax_virtual_view.h b/chromium/ui/views/accessibility/ax_virtual_view.h
index 9ef022c9319..8547b6bac70 100644
--- a/chromium/ui/views/accessibility/ax_virtual_view.h
+++ b/chromium/ui/views/accessibility/ax_virtual_view.h
@@ -12,6 +12,7 @@
#include <vector>
#include "base/callback_forward.h"
+#include "build/build_config.h"
#include "ui/accessibility/ax_enums.mojom-forward.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/platform/ax_platform_node_delegate_base.h"
@@ -23,9 +24,6 @@
#if defined(USE_AURA)
#include "ui/views/accessibility/ax_virtual_view_wrapper.h"
-#else
-// Currently unused.
-class AXVirtualViewWrapper {};
#endif
namespace ui {
@@ -38,6 +36,7 @@ class AXUniqueId;
namespace views {
class AXAuraObjCache;
+class AXVirtualViewWrapper;
class View;
class ViewAccessibility;
class ViewAXPlatformNodeDelegate;
@@ -156,10 +155,10 @@ class VIEWS_EXPORT AXVirtualView : public ui::AXPlatformNodeDelegateBase {
bool IsOffscreen() const override;
const ui::AXUniqueId& GetUniqueId() const override;
gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
- base::Optional<bool> GetTableHasColumnOrRowHeaderNode() const override;
+ absl::optional<bool> GetTableHasColumnOrRowHeaderNode() const override;
std::vector<int32_t> GetColHeaderNodeIds() const override;
std::vector<int32_t> GetColHeaderNodeIds(int col_index) const override;
- base::Optional<int32_t> GetCellId(int row_index,
+ absl::optional<int32_t> GetCellId(int row_index,
int col_index) const override;
// Gets the real View that owns our shallowest virtual ancestor,, if any.
@@ -193,9 +192,18 @@ class VIEWS_EXPORT AXVirtualView : public ui::AXPlatformNodeDelegateBase {
bool HandleAccessibleActionInOwnerView(const ui::AXActionData& action_data);
private:
+ // Needed in order to access set_cache(), so that AXAuraObjCache can
+ // track when an AXVirtualViewWrapper is deleted.
+ friend class AXAuraObjCache;
+ friend class AXVirtualViewWrapper;
+
// Internal class name.
static const char kViewClassName[];
+ // The AXAuraObjCache associated with our wrapper, if any. This is
+ // called by friend classes AXAuraObjCache and AXVirtualViewWrapper.
+ void set_cache(AXAuraObjCache* cache) { ax_aura_obj_cache_ = cache; }
+
// Sets the parent ViewAccessibility if the parent is a real View and not an
// AXVirtualView. It is invalid to set both |parent_view_| and
// |virtual_parent_view_|.
@@ -219,12 +227,14 @@ class VIEWS_EXPORT AXVirtualView : public ui::AXPlatformNodeDelegateBase {
// We own our children.
AXVirtualViews children_;
+ // The AXAuraObjCache that owns the AXVirtualViewWrapper associated with
+ // this object, if any.
+ AXAuraObjCache* ax_aura_obj_cache_ = nullptr;
+
ui::AXUniqueId unique_id_;
ui::AXNodeData custom_data_;
base::RepeatingCallback<void(ui::AXNodeData*)> populate_data_callback_;
- std::unique_ptr<AXVirtualViewWrapper> wrapper_;
-
friend class ViewAccessibility;
};
diff --git a/chromium/ui/views/accessibility/ax_virtual_view_unittest.cc b/chromium/ui/views/accessibility/ax_virtual_view_unittest.cc
index f370f5e6160..aef2de7413d 100644
--- a/chromium/ui/views/accessibility/ax_virtual_view_unittest.cc
+++ b/chromium/ui/views/accessibility/ax_virtual_view_unittest.cc
@@ -46,14 +46,13 @@ class TestButton : public Button {
class AXVirtualViewTest : public ViewsTestBase {
public:
- AXVirtualViewTest() = default;
+ AXVirtualViewTest() : ax_mode_setter_(ui::kAXModeComplete) {}
AXVirtualViewTest(const AXVirtualViewTest&) = delete;
AXVirtualViewTest& operator=(const AXVirtualViewTest&) = delete;
~AXVirtualViewTest() override = default;
void SetUp() override {
ViewsTestBase::SetUp();
- ui::AXPlatformNode::NotifyAddAXModeFlags(ui::kAXModeComplete);
widget_ = new Widget;
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
@@ -112,6 +111,7 @@ class AXVirtualViewTest : public ViewsTestBase {
std::vector<
std::pair<const ui::AXPlatformNodeDelegate*, const ax::mojom::Event>>
accessibility_events_;
+ ui::testing::ScopedAxModeSetter ax_mode_setter_;
};
TEST_F(AXVirtualViewTest, AccessibilityRoleAndName) {
@@ -585,7 +585,7 @@ TEST_F(AXVirtualViewTest, TreeNavigationWithIgnoredVirtualViews) {
virtual_child_2->ChildAtIndex(1));
// Try ignoring a node by changing its role, instead of its state.
- virtual_child_2->GetCustomData().role = ax::mojom::Role::kIgnored;
+ virtual_child_2->GetCustomData().role = ax::mojom::Role::kNone;
EXPECT_EQ(button_->GetNativeViewAccessible(), virtual_label_->GetParent());
EXPECT_EQ(virtual_label_->GetNativeObject(), virtual_child_1->GetParent());
@@ -745,15 +745,6 @@ TEST_F(AXVirtualViewTest, HitTesting) {
virtual_label_->HitTestSync(point_3.x(), point_3.y()));
}
-#if defined(USE_AURA)
-TEST_F(AXVirtualViewTest, GetOrCreateWrapper) {
- std::unique_ptr<AXAuraObjCache> cache;
- auto* wrapper1 = virtual_label_->GetOrCreateWrapper(cache.get());
- cache = std::make_unique<AXAuraObjCache>();
- EXPECT_NE(wrapper1, virtual_label_->GetOrCreateWrapper(cache.get()));
-}
-#endif
-
// Test for GetTargetForNativeAccessibilityEvent().
#if defined(OS_WIN)
TEST_F(AXVirtualViewTest, GetTargetForEvents) {
diff --git a/chromium/ui/views/accessibility/ax_virtual_view_wrapper.cc b/chromium/ui/views/accessibility/ax_virtual_view_wrapper.cc
index bfdc3d663e1..e7a3330dbb4 100644
--- a/chromium/ui/views/accessibility/ax_virtual_view_wrapper.cc
+++ b/chromium/ui/views/accessibility/ax_virtual_view_wrapper.cc
@@ -13,9 +13,11 @@
namespace views {
-AXVirtualViewWrapper::AXVirtualViewWrapper(AXVirtualView* virtual_view,
- AXAuraObjCache* cache)
- : AXAuraObjWrapper(cache), virtual_view_(virtual_view) {}
+AXVirtualViewWrapper::AXVirtualViewWrapper(AXAuraObjCache* cache,
+ AXVirtualView* virtual_view)
+ : AXAuraObjWrapper(cache), virtual_view_(virtual_view) {
+ virtual_view->set_cache(cache);
+}
AXVirtualViewWrapper::~AXVirtualViewWrapper() = default;
@@ -38,6 +40,12 @@ void AXVirtualViewWrapper::GetChildren(
void AXVirtualViewWrapper::Serialize(ui::AXNodeData* out_node_data) {
*out_node_data = virtual_view_->GetData();
+ View* owner_view = virtual_view_->GetOwnerView();
+ if (owner_view && owner_view->GetWidget()) {
+ gfx::Point offset;
+ View::ConvertPointToScreen(owner_view, &offset);
+ out_node_data->relative_bounds.bounds.Offset(offset.x(), offset.y());
+ }
}
ui::AXNodeID AXVirtualViewWrapper::GetUniqueId() const {
diff --git a/chromium/ui/views/accessibility/ax_virtual_view_wrapper.h b/chromium/ui/views/accessibility/ax_virtual_view_wrapper.h
index f2e95234471..859f26965ad 100644
--- a/chromium/ui/views/accessibility/ax_virtual_view_wrapper.h
+++ b/chromium/ui/views/accessibility/ax_virtual_view_wrapper.h
@@ -20,7 +20,7 @@ class AXVirtualView;
// Wraps (and adapts) an AXVirtualView for use with AXTreeSourceViews.
class AXVirtualViewWrapper : public AXAuraObjWrapper {
public:
- AXVirtualViewWrapper(AXVirtualView* virtual_view, AXAuraObjCache* cache);
+ AXVirtualViewWrapper(AXAuraObjCache* cache, AXVirtualView* virtual_view);
AXVirtualViewWrapper(const AXVirtualViewWrapper&) = delete;
AXVirtualViewWrapper& operator=(const AXVirtualViewWrapper&) = delete;
~AXVirtualViewWrapper() override;
diff --git a/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc b/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc
index 53a80920ac0..baf2182f68a 100644
--- a/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc
+++ b/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc
@@ -149,8 +149,8 @@ void AXWindowObjWrapper::Serialize(ui::AXNodeData* out_node_data) {
window_tree_host_platform->platform_window()->GetWindowUniqueId();
if (!window_id.empty())
- out_node_data->AddStringAttribute(
- ax::mojom::StringAttribute::kParentTreeNodeAppId, window_id);
+ out_node_data->AddStringAttribute(ax::mojom::StringAttribute::kAppId,
+ window_id);
}
}
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chromium/ui/views/accessibility/test_list_grid_view.cc b/chromium/ui/views/accessibility/test_list_grid_view.cc
index 031a1194dbf..45169b2f700 100644
--- a/chromium/ui/views/accessibility/test_list_grid_view.cc
+++ b/chromium/ui/views/accessibility/test_list_grid_view.cc
@@ -34,23 +34,23 @@ void TestListGridView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
}
void TestListGridView::SetAriaTableSize(int row_count, int column_count) {
- aria_row_count = base::make_optional(row_count);
- aria_column_count = base::make_optional(column_count);
+ aria_row_count = absl::make_optional(row_count);
+ aria_column_count = absl::make_optional(column_count);
}
void TestListGridView::SetTableSize(int row_count, int column_count) {
- table_row_count = base::make_optional(row_count);
- table_column_count = base::make_optional(column_count);
+ table_row_count = absl::make_optional(row_count);
+ table_column_count = absl::make_optional(column_count);
}
void TestListGridView::UnsetAriaTableSize() {
- aria_row_count = base::nullopt;
- aria_column_count = base::nullopt;
+ aria_row_count = absl::nullopt;
+ aria_column_count = absl::nullopt;
}
void TestListGridView::UnsetTableSize() {
- table_row_count = base::nullopt;
- table_column_count = base::nullopt;
+ table_row_count = absl::nullopt;
+ table_column_count = absl::nullopt;
}
} // namespace test
diff --git a/chromium/ui/views/accessibility/test_list_grid_view.h b/chromium/ui/views/accessibility/test_list_grid_view.h
index 8c742ba1010..0a32c6b4e1b 100644
--- a/chromium/ui/views/accessibility/test_list_grid_view.h
+++ b/chromium/ui/views/accessibility/test_list_grid_view.h
@@ -28,10 +28,10 @@ class TestListGridView : public View {
void UnsetTableSize();
private:
- base::Optional<int> aria_row_count = base::nullopt;
- base::Optional<int> aria_column_count = base::nullopt;
- base::Optional<int> table_row_count = base::nullopt;
- base::Optional<int> table_column_count = base::nullopt;
+ absl::optional<int> aria_row_count = absl::nullopt;
+ absl::optional<int> aria_column_count = absl::nullopt;
+ absl::optional<int> table_row_count = absl::nullopt;
+ absl::optional<int> table_column_count = absl::nullopt;
};
} // namespace test
diff --git a/chromium/ui/views/accessibility/view_accessibility.cc b/chromium/ui/views/accessibility/view_accessibility.cc
index 8cfb389ab99..c9b5e37f570 100644
--- a/chromium/ui/views/accessibility/view_accessibility.cc
+++ b/chromium/ui/views/accessibility/view_accessibility.cc
@@ -35,7 +35,6 @@ bool IsValidRoleForViews(ax::mojom::Role role) {
case ax::mojom::Role::kDocument: // Used for ARIA role="document".
case ax::mojom::Role::kIframe:
case ax::mojom::Role::kIframePresentational:
- case ax::mojom::Role::kNone:
case ax::mojom::Role::kPdfRoot:
case ax::mojom::Role::kPortal:
case ax::mojom::Role::kRootWebArea:
@@ -444,7 +443,7 @@ Widget* ViewAccessibility::GetPreviousFocus() const {
void ViewAccessibility::OverrideChildTreeID(ui::AXTreeID tree_id) {
if (tree_id == ui::AXTreeIDUnknown())
- child_tree_id_ = base::nullopt;
+ child_tree_id_ = absl::nullopt;
else
child_tree_id_ = tree_id;
}
@@ -458,8 +457,7 @@ gfx::NativeViewAccessible ViewAccessibility::GetNativeObject() const {
}
void ViewAccessibility::NotifyAccessibilityEvent(ax::mojom::Event event_type) {
- // On certain platforms, e.g. Chrome OS, we don't create any
- // AXPlatformDelegates, so the base method in this file would be called.
+ // Used for unit testing.
if (accessibility_events_callback_)
accessibility_events_callback_.Run(nullptr, event_type);
}
diff --git a/chromium/ui/views/accessibility/view_accessibility.h b/chromium/ui/views/accessibility/view_accessibility.h
index ccd4dd42fe8..0565142fc3a 100644
--- a/chromium/ui/views/accessibility/view_accessibility.h
+++ b/chromium/ui/views/accessibility/view_accessibility.h
@@ -10,9 +10,9 @@
#include <vector>
#include "base/callback_forward.h"
-#include "base/optional.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_enums.mojom-forward.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/platform/ax_unique_id.h"
@@ -261,7 +261,7 @@ class VIEWS_EXPORT ViewAccessibility {
// Used to override the View's enabled state in case we need to mark the View
// as enabled or disabled only in the accessibility tree.
- base::Optional<bool> is_enabled_ = base::nullopt;
+ absl::optional<bool> is_enabled_ = absl::nullopt;
// Used by the Views system to help some assistive technologies, such as
// screen readers, transition focus from one widget to another.
@@ -269,7 +269,7 @@ class VIEWS_EXPORT ViewAccessibility {
Widget* previous_focus_ = nullptr;
// This view's child tree id.
- base::Optional<ui::AXTreeID> child_tree_id_;
+ absl::optional<ui::AXTreeID> child_tree_id_;
#if defined(USE_AURA) && !BUILDFLAG(IS_CHROMEOS_ASH)
// Each instance of ViewAccessibility that's associated with a root View
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc
index dfcc3aa88c2..a8c999a1753 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc
@@ -262,11 +262,11 @@ void ViewAXPlatformNodeDelegate::NotifyAccessibilityEvent(
ax_platform_node_->NotifyAccessibilityEvent(event_type);
}
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
void ViewAXPlatformNodeDelegate::AnnounceText(const std::u16string& text) {
ax_platform_node_->AnnounceText(text);
}
-#endif // defined(OS_APPLE)
+#endif // defined(OS_MAC)
const ui::AXNodeData& ViewAXPlatformNodeDelegate::GetData() const {
// Clear the data, then populate it.
@@ -649,7 +649,7 @@ const ui::AXUniqueId& ViewAXPlatformNodeDelegate::GetUniqueId() const {
return ViewAccessibility::GetUniqueId();
}
-base::Optional<bool>
+absl::optional<bool>
ViewAXPlatformNodeDelegate::GetTableHasColumnOrRowHeaderNode() const {
if (!GetAncestorTableView())
return false;
@@ -679,22 +679,22 @@ std::vector<int32_t> ViewAXPlatformNodeDelegate::GetColHeaderNodeIds(
return {columns[col_index]};
}
-base::Optional<int32_t> ViewAXPlatformNodeDelegate::GetCellId(
+absl::optional<int32_t> ViewAXPlatformNodeDelegate::GetCellId(
int row_index,
int col_index) const {
if (virtual_children().empty() || !GetAncestorTableView())
- return base::nullopt;
+ return absl::nullopt;
AXVirtualView* ax_cell =
GetAncestorTableView()->GetVirtualAccessibilityCell(row_index, col_index);
if (!ax_cell)
- return base::nullopt;
+ return absl::nullopt;
const ui::AXNodeData& cell_data = ax_cell->GetData();
if (cell_data.role == ax::mojom::Role::kCell)
return cell_data.id;
- return base::nullopt;
+ return absl::nullopt;
}
TableView* ViewAXPlatformNodeDelegate::GetAncestorTableView() const {
@@ -719,7 +719,7 @@ bool ViewAXPlatformNodeDelegate::IsOrderedSet() const {
GetData().HasIntAttribute(ax::mojom::IntAttribute::kSetSize);
}
-base::Optional<int> ViewAXPlatformNodeDelegate::GetPosInSet() const {
+absl::optional<int> ViewAXPlatformNodeDelegate::GetPosInSet() const {
// Consider overridable attributes first.
const ui::AXNodeData& data = GetData();
if (data.HasIntAttribute(ax::mojom::IntAttribute::kPosInSet))
@@ -728,19 +728,19 @@ base::Optional<int> ViewAXPlatformNodeDelegate::GetPosInSet() const {
std::vector<View*> views_in_group;
GetViewsInGroupForSet(&views_in_group);
if (views_in_group.empty())
- return base::nullopt;
+ return absl::nullopt;
// Check this is in views_in_group; it may be removed if it is ignored.
auto found_view =
std::find(views_in_group.begin(), views_in_group.end(), view());
if (found_view == views_in_group.end())
- return base::nullopt;
+ return absl::nullopt;
int posInSet = std::distance(views_in_group.begin(), found_view);
// posInSet is zero-based; users expect one-based, so increment.
return ++posInSet;
}
-base::Optional<int> ViewAXPlatformNodeDelegate::GetSetSize() const {
+absl::optional<int> ViewAXPlatformNodeDelegate::GetSetSize() const {
// Consider overridable attributes first.
const ui::AXNodeData& data = GetData();
if (data.HasIntAttribute(ax::mojom::IntAttribute::kSetSize))
@@ -749,12 +749,12 @@ base::Optional<int> ViewAXPlatformNodeDelegate::GetSetSize() const {
std::vector<View*> views_in_group;
GetViewsInGroupForSet(&views_in_group);
if (views_in_group.empty())
- return base::nullopt;
+ return absl::nullopt;
// Check this is in views_in_group; it may be removed if it is ignored.
auto found_view =
std::find(views_in_group.begin(), views_in_group.end(), view());
if (found_view == views_in_group.end())
- return base::nullopt;
+ return absl::nullopt;
return views_in_group.size();
}
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h
index 04b5412ef25..e5117acc7e3 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h
@@ -10,8 +10,8 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_enums.mojom-forward.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/platform/ax_platform_node_delegate_base.h"
@@ -54,7 +54,7 @@ class ViewAXPlatformNodeDelegate : public ViewAccessibility,
bool IsAccessibilityEnabled() const override;
gfx::NativeViewAccessible GetNativeObject() const override;
void NotifyAccessibilityEvent(ax::mojom::Event event_type) override;
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
void AnnounceText(const std::u16string& text) override;
#endif
@@ -93,15 +93,15 @@ class ViewAXPlatformNodeDelegate : public ViewAccessibility,
bool IsMinimized() const override;
// Also in |ViewAccessibility|.
const ui::AXUniqueId& GetUniqueId() const override;
- base::Optional<bool> GetTableHasColumnOrRowHeaderNode() const override;
+ absl::optional<bool> GetTableHasColumnOrRowHeaderNode() const override;
std::vector<int32_t> GetColHeaderNodeIds() const override;
std::vector<int32_t> GetColHeaderNodeIds(int col_index) const override;
- base::Optional<int32_t> GetCellId(int row_index,
+ absl::optional<int32_t> GetCellId(int row_index,
int col_index) const override;
bool IsOrderedSetItem() const override;
bool IsOrderedSet() const override;
- base::Optional<int> GetPosInSet() const override;
- base::Optional<int> GetSetSize() const override;
+ absl::optional<int> GetPosInSet() const override;
+ absl::optional<int> GetSetSize() const override;
protected:
explicit ViewAXPlatformNodeDelegate(View* view);
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_auralinux_unittest.cc b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_auralinux_unittest.cc
index 09c03eb21b1..5056e869b5f 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_auralinux_unittest.cc
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_auralinux_unittest.cc
@@ -16,12 +16,12 @@ namespace test {
class ViewAXPlatformNodeDelegateAuraLinuxTest : public ViewsTestBase {
public:
- ViewAXPlatformNodeDelegateAuraLinuxTest() = default;
+ ViewAXPlatformNodeDelegateAuraLinuxTest()
+ : ax_mode_setter_(ui::kAXModeComplete) {}
~ViewAXPlatformNodeDelegateAuraLinuxTest() override = default;
- void SetUp() override {
- ViewsTestBase::SetUp();
- ui::AXPlatformNode::NotifyAddAXModeFlags(ui::kAXModeComplete);
- }
+
+ private:
+ ui::testing::ScopedAxModeSetter ax_mode_setter_;
};
TEST_F(ViewAXPlatformNodeDelegateAuraLinuxTest, TextfieldAccessibility) {
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_unittest.cc b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_unittest.cc
index d34d57d1451..010a9e2319e 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_unittest.cc
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_unittest.cc
@@ -103,7 +103,7 @@ class TestTableModel : public ui::TableModel {
class ViewAXPlatformNodeDelegateTest : public ViewsTestBase {
public:
- ViewAXPlatformNodeDelegateTest() = default;
+ ViewAXPlatformNodeDelegateTest() : ax_mode_setter_(ui::kAXModeComplete) {}
ViewAXPlatformNodeDelegateTest(const ViewAXPlatformNodeDelegateTest&) =
delete;
ViewAXPlatformNodeDelegateTest& operator=(
@@ -112,10 +112,10 @@ class ViewAXPlatformNodeDelegateTest : public ViewsTestBase {
void SetUp() override {
ViewsTestBase::SetUp();
- ui::AXPlatformNode::NotifyAddAXModeFlags(ui::kAXModeComplete);
widget_ = new Widget;
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ Widget::InitParams params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
params.bounds = gfx::Rect(0, 0, 200, 200);
widget_->Init(std::move(params));
@@ -127,7 +127,7 @@ class ViewAXPlatformNodeDelegateTest : public ViewsTestBase {
label_->SetID(DEFAULT_VIEW_ID);
button_->AddChildView(label_);
- widget_->GetContentsView()->AddChildView(button_);
+ widget_->GetRootView()->AddChildView(button_);
widget_->Show();
}
@@ -163,7 +163,7 @@ class ViewAXPlatformNodeDelegateTest : public ViewsTestBase {
// child Views.
View::Views SetUpExtraViews() {
View* parent_view =
- widget_->GetContentsView()->AddChildView(std::make_unique<View>());
+ widget_->GetRootView()->AddChildView(std::make_unique<View>());
View::Views views{parent_view};
for (int i = 0; i < 4; i++)
views.push_back(parent_view->AddChildView(std::make_unique<View>()));
@@ -205,6 +205,7 @@ class ViewAXPlatformNodeDelegateTest : public ViewsTestBase {
Widget* widget_ = nullptr;
Button* button_ = nullptr;
Label* label_ = nullptr;
+ ui::testing::ScopedAxModeSetter ax_mode_setter_;
};
class ViewAXPlatformNodeDelegateTableTest
@@ -223,7 +224,7 @@ class ViewAXPlatformNodeDelegateTableTest
auto table =
std::make_unique<TableView>(model_.get(), columns, TEXT_ONLY, true);
table_ = table.get();
- widget_->GetContentsView()->AddChildView(
+ widget_->GetRootView()->AddChildView(
TableView::CreateScrollViewWithTable(std::move(table)));
}
@@ -536,12 +537,12 @@ TEST_F(ViewAXPlatformNodeDelegateTest, TreeNavigation) {
ViewAXPlatformNodeDelegate* child_view_3 = view_accessibility(extra_views[3]);
ViewAXPlatformNodeDelegate* child_view_4 = view_accessibility(extra_views[4]);
- EXPECT_EQ(view_accessibility(widget_->GetContentsView())->GetNativeObject(),
+ EXPECT_EQ(view_accessibility(widget_->GetRootView())->GetNativeObject(),
parent_view->GetParent());
EXPECT_EQ(4, parent_view->GetChildCount());
- EXPECT_EQ(2, button_accessibility()->GetIndexInParent());
- EXPECT_EQ(3, parent_view->GetIndexInParent());
+ EXPECT_EQ(0, button_accessibility()->GetIndexInParent());
+ EXPECT_EQ(1, parent_view->GetIndexInParent());
EXPECT_EQ(child_view_1->GetNativeObject(), parent_view->ChildAtIndex(0));
EXPECT_EQ(child_view_2->GetNativeObject(), parent_view->ChildAtIndex(1));
@@ -585,8 +586,6 @@ TEST_F(ViewAXPlatformNodeDelegateTest, TreeNavigationWithLeafViews) {
// view is added as the next sibling of the already present button view.
//
// Widget
- // ++NonClientView
- // ++NonClientFrameView
// ++Button
// ++++Label
// 0 = ++ParentView
@@ -596,7 +595,7 @@ TEST_F(ViewAXPlatformNodeDelegateTest, TreeNavigationWithLeafViews) {
// 4 = ++++ChildView4
View::Views extra_views = SetUpExtraViews();
ViewAXPlatformNodeDelegate* contents_view =
- view_accessibility(widget_->GetContentsView());
+ view_accessibility(widget_->GetRootView());
ViewAXPlatformNodeDelegate* parent_view = view_accessibility(extra_views[0]);
ViewAXPlatformNodeDelegate* child_view_1 = view_accessibility(extra_views[1]);
ViewAXPlatformNodeDelegate* child_view_2 = view_accessibility(extra_views[2]);
@@ -610,12 +609,12 @@ TEST_F(ViewAXPlatformNodeDelegateTest, TreeNavigationWithLeafViews) {
parent_view->OverrideIsLeaf(true);
child_view_2->OverrideIsLeaf(true);
- EXPECT_EQ(4, contents_view->GetChildCount());
+ EXPECT_EQ(2, contents_view->GetChildCount());
EXPECT_EQ(contents_view->GetNativeObject(), parent_view->GetParent());
EXPECT_EQ(0, parent_view->GetChildCount());
- EXPECT_EQ(2, button_accessibility()->GetIndexInParent());
- EXPECT_EQ(3, parent_view->GetIndexInParent());
+ EXPECT_EQ(0, button_accessibility()->GetIndexInParent());
+ EXPECT_EQ(1, parent_view->GetIndexInParent());
EXPECT_FALSE(contents_view->IsIgnored());
EXPECT_FALSE(parent_view->IsIgnored());
@@ -647,12 +646,12 @@ TEST_F(ViewAXPlatformNodeDelegateTest, TreeNavigationWithLeafViews) {
// have no effect.
parent_view->OverrideIsLeaf(false);
- EXPECT_EQ(4, contents_view->GetChildCount());
+ EXPECT_EQ(2, contents_view->GetChildCount());
EXPECT_EQ(contents_view->GetNativeObject(), parent_view->GetParent());
EXPECT_EQ(4, parent_view->GetChildCount());
- EXPECT_EQ(2, button_accessibility()->GetIndexInParent());
- EXPECT_EQ(3, parent_view->GetIndexInParent());
+ EXPECT_EQ(0, button_accessibility()->GetIndexInParent());
+ EXPECT_EQ(1, parent_view->GetIndexInParent());
EXPECT_FALSE(contents_view->IsIgnored());
EXPECT_FALSE(parent_view->IsIgnored());
@@ -691,8 +690,6 @@ TEST_F(ViewAXPlatformNodeDelegateTest, TreeNavigationWithIgnoredViews) {
// view is added as the next sibling of the already present button view.
//
// Widget
- // ++NonClientView
- // ++NonClientFrameView
// ++Button
// ++++Label
// 0 = ++ParentView
@@ -702,7 +699,7 @@ TEST_F(ViewAXPlatformNodeDelegateTest, TreeNavigationWithIgnoredViews) {
// 4 = ++++ChildView4
View::Views extra_views = SetUpExtraViews();
ViewAXPlatformNodeDelegate* contents_view =
- view_accessibility(widget_->GetContentsView());
+ view_accessibility(widget_->GetRootView());
ViewAXPlatformNodeDelegate* parent_view = view_accessibility(extra_views[0]);
ViewAXPlatformNodeDelegate* child_view_1 = view_accessibility(extra_views[1]);
ViewAXPlatformNodeDelegate* child_view_2 = view_accessibility(extra_views[2]);
@@ -716,7 +713,7 @@ TEST_F(ViewAXPlatformNodeDelegateTest, TreeNavigationWithIgnoredViews) {
EXPECT_EQ(contents_view->GetNativeObject(), parent_view->GetParent());
EXPECT_EQ(3, parent_view->GetChildCount());
- EXPECT_EQ(2, button_accessibility()->GetIndexInParent());
+ EXPECT_EQ(0, button_accessibility()->GetIndexInParent());
EXPECT_EQ(-1, parent_view->GetIndexInParent());
EXPECT_EQ(child_view_1->GetNativeObject(), parent_view->ChildAtIndex(0));
@@ -724,17 +721,17 @@ TEST_F(ViewAXPlatformNodeDelegateTest, TreeNavigationWithIgnoredViews) {
EXPECT_EQ(child_view_4->GetNativeObject(), parent_view->ChildAtIndex(2));
EXPECT_EQ(button_accessibility()->GetNativeObject(),
- contents_view->ChildAtIndex(2));
- EXPECT_EQ(child_view_1->GetNativeObject(), contents_view->ChildAtIndex(3));
- EXPECT_EQ(child_view_3->GetNativeObject(), contents_view->ChildAtIndex(4));
- EXPECT_EQ(child_view_4->GetNativeObject(), contents_view->ChildAtIndex(5));
+ contents_view->ChildAtIndex(0));
+ EXPECT_EQ(child_view_1->GetNativeObject(), contents_view->ChildAtIndex(1));
+ EXPECT_EQ(child_view_3->GetNativeObject(), contents_view->ChildAtIndex(2));
+ EXPECT_EQ(child_view_4->GetNativeObject(), contents_view->ChildAtIndex(3));
EXPECT_EQ(nullptr, parent_view->GetNextSibling());
EXPECT_EQ(nullptr, parent_view->GetPreviousSibling());
EXPECT_EQ(contents_view->GetNativeObject(), child_view_1->GetParent());
EXPECT_EQ(0, child_view_1->GetChildCount());
- EXPECT_EQ(3, child_view_1->GetIndexInParent());
+ EXPECT_EQ(1, child_view_1->GetIndexInParent());
EXPECT_EQ(child_view_3->GetNativeObject(), child_view_1->GetNextSibling());
EXPECT_EQ(button_accessibility()->GetNativeObject(),
child_view_1->GetPreviousSibling());
@@ -747,14 +744,14 @@ TEST_F(ViewAXPlatformNodeDelegateTest, TreeNavigationWithIgnoredViews) {
EXPECT_EQ(contents_view->GetNativeObject(), child_view_3->GetParent());
EXPECT_EQ(0, child_view_3->GetChildCount());
- EXPECT_EQ(4, child_view_3->GetIndexInParent());
+ EXPECT_EQ(2, child_view_3->GetIndexInParent());
EXPECT_EQ(child_view_4->GetNativeObject(), child_view_3->GetNextSibling());
EXPECT_EQ(child_view_1->GetNativeObject(),
child_view_3->GetPreviousSibling());
EXPECT_EQ(contents_view->GetNativeObject(), child_view_4->GetParent());
EXPECT_EQ(0, child_view_4->GetChildCount());
- EXPECT_EQ(5, child_view_4->GetIndexInParent());
+ EXPECT_EQ(3, child_view_4->GetIndexInParent());
EXPECT_EQ(nullptr, child_view_4->GetNextSibling());
EXPECT_EQ(child_view_3->GetNativeObject(),
child_view_4->GetPreviousSibling());
@@ -852,9 +849,9 @@ TEST_F(ViewAXPlatformNodeDelegateTableTest, TableHasHeader) {
}
TEST_F(ViewAXPlatformNodeDelegateTableTest, TableHasCell) {
- EXPECT_NE(base::nullopt, table_accessibility()->GetCellId(0, 0));
- EXPECT_NE(base::nullopt, table_accessibility()->GetCellId(0, 3));
- EXPECT_NE(base::nullopt, table_accessibility()->GetCellId(9, 3));
+ EXPECT_NE(absl::nullopt, table_accessibility()->GetCellId(0, 0));
+ EXPECT_NE(absl::nullopt, table_accessibility()->GetCellId(0, 3));
+ EXPECT_NE(absl::nullopt, table_accessibility()->GetCellId(9, 3));
EXPECT_DCHECK_DEATH(table_accessibility()->GetCellId(-1, 0));
EXPECT_DCHECK_DEATH(table_accessibility()->GetCellId(0, -1));
EXPECT_DCHECK_DEATH(table_accessibility()->GetCellId(10, 0));
@@ -899,13 +896,13 @@ TEST_F(ViewAXPlatformNodeDelegateMenuTest, MenuTest) {
EXPECT_EQ(submenu_item->GetData().GetHasPopup(), ax::mojom::HasPopup::kMenu);
EXPECT_EQ(submenu_item->GetPosInSet(), 2);
EXPECT_EQ(submenu_item->GetSetSize(), 7);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// A virtual child with role menu is exposed so that VoiceOver treats a
// MenuItemView of type kSubMenu as a submenu rather than an item.
EXPECT_EQ(submenu_item->GetChildCount(), 1);
#else
EXPECT_EQ(submenu_item->GetChildCount(), 0);
-#endif // defined(OS_APPLE)
+#endif // defined(OS_MAC)
EXPECT_EQ(submenu_item->GetIndexInParent(), 1);
// MenuItemView::Type::kActionableSubMenu
@@ -924,13 +921,13 @@ TEST_F(ViewAXPlatformNodeDelegateMenuTest, MenuTest) {
ax::mojom::HasPopup::kMenu);
EXPECT_EQ(actionable_submenu_item->GetPosInSet(), 3);
EXPECT_EQ(actionable_submenu_item->GetSetSize(), 7);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// A virtual child with role menu is exposed so that VoiceOver treats a
// MenuItemView of type kActionableSubMenu as a submenu rather than an item.
EXPECT_EQ(actionable_submenu_item->GetChildCount(), 1);
#else
EXPECT_EQ(actionable_submenu_item->GetChildCount(), 0);
-#endif // defined(OS_APPLE)
+#endif // defined(OS_MAC)
EXPECT_EQ(actionable_submenu_item->GetIndexInParent(), 2);
// MenuItemView::Type::kCheckbox
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_win.cc b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_win.cc
index af845a0cc28..d5f032de85a 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_win.cc
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_win.cc
@@ -15,7 +15,6 @@
#include "base/win/windows_version.h"
#include "third_party/iaccessible2/ia2_api_all.h"
#include "ui/accessibility/accessibility_switches.h"
-#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_text_utils.h"
#include "ui/accessibility/platform/ax_fragment_root_win.h"
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_win_unittest.cc b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_win_unittest.cc
index 92ee0e6eb8d..1e6ebdc681b 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_win_unittest.cc
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_win_unittest.cc
@@ -473,7 +473,7 @@ TEST_F(ViewAXPlatformNodeDelegateWinTest, GridRowColumnCount) {
EXPECT_EQ(0, column_count);
// To do still: When nothing is set, currently
// AXPlatformNodeDelegateBase::GetTable{Row/Col}Count() returns 0 Should it
- // return base::nullopt if the attribute is not set? Like
+ // return absl::nullopt if the attribute is not set? Like
// GetTableAria{Row/Col}Count()
// EXPECT_EQ(E_UNEXPECTED, grid_provider->get_RowCount(&row_count));
diff --git a/chromium/ui/views/accessibility/widget_ax_tree_id_map.cc b/chromium/ui/views/accessibility/widget_ax_tree_id_map.cc
index 7892d204af2..617b7712bc1 100644
--- a/chromium/ui/views/accessibility/widget_ax_tree_id_map.cc
+++ b/chromium/ui/views/accessibility/widget_ax_tree_id_map.cc
@@ -4,8 +4,7 @@
#include "ui/views/accessibility/widget_ax_tree_id_map.h"
-#include "base/stl_util.h"
-#include "ui/accessibility/ax_enums.mojom.h"
+#include "base/containers/contains.h"
namespace views {
diff --git a/chromium/ui/views/accessible_pane_view.cc b/chromium/ui/views/accessible_pane_view.cc
index fa9a8203998..f3d4bc26085 100644
--- a/chromium/ui/views/accessible_pane_view.cc
+++ b/chromium/ui/views/accessible_pane_view.cc
@@ -8,8 +8,8 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/views/focus/focus_search.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/view_tracker.h"
#include "ui/views/widget/widget.h"
diff --git a/chromium/ui/views/accessible_pane_view_unittest.cc b/chromium/ui/views/accessible_pane_view_unittest.cc
index 91972aa1ef7..3e06e1579e2 100644
--- a/chromium/ui/views/accessible_pane_view_unittest.cc
+++ b/chromium/ui/views/accessible_pane_view_unittest.cc
@@ -135,7 +135,7 @@ TEST_F(AccessiblePaneViewTest, SetPaneFocusAndRestore) {
// predictable. On Mac, Deactivate() is not implemented. Note that
// TestBarView calls set_allow_deactivate_on_esc(true), which is only
// otherwise used in Ash.
-#if !defined(OS_APPLE) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if !defined(OS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH)
// Esc should deactivate the widget.
test_view_bar->AcceleratorPressed(test_view_bar->escape_key());
EXPECT_TRUE(widget_main->IsActive());
diff --git a/chromium/ui/views/animation/animation_delegate_views.h b/chromium/ui/views/animation/animation_delegate_views.h
index 7edc84d9cf1..afe6a72b0c0 100644
--- a/chromium/ui/views/animation/animation_delegate_views.h
+++ b/chromium/ui/views/animation/animation_delegate_views.h
@@ -5,7 +5,6 @@
#ifndef UI_VIEWS_ANIMATION_ANIMATION_DELEGATE_VIEWS_H_
#define UI_VIEWS_ANIMATION_ANIMATION_DELEGATE_VIEWS_H_
-#include <memory>
#include "base/scoped_observation.h"
#include "ui/gfx/animation/animation_container_observer.h"
diff --git a/chromium/ui/views/animation/bounds_animator.h b/chromium/ui/views/animation/bounds_animator.h
index dff13110422..7684647a1c0 100644
--- a/chromium/ui/views/animation/bounds_animator.h
+++ b/chromium/ui/views/animation/bounds_animator.h
@@ -127,7 +127,7 @@ class VIEWS_EXPORT BoundsAnimator : public AnimationDelegateViews {
std::unique_ptr<gfx::AnimationDelegate> delegate;
// Will only exist if |use_transforms_| is true.
- base::Optional<gfx::Transform> target_transform;
+ absl::optional<gfx::Transform> target_transform;
};
// Used by AnimationEndedOrCanceled.
diff --git a/chromium/ui/views/animation/bubble_slide_animator.cc b/chromium/ui/views/animation/bubble_slide_animator.cc
index 4ba8149c2df..df498b86406 100644
--- a/chromium/ui/views/animation/bubble_slide_animator.cc
+++ b/chromium/ui/views/animation/bubble_slide_animator.cc
@@ -91,10 +91,8 @@ void BubbleSlideAnimator::OnWidgetDestroying(Widget* widget) {
gfx::Rect BubbleSlideAnimator::CalculateTargetBounds(
const View* desired_anchor_view) const {
- gfx::Rect anchor_bounds = desired_anchor_view->GetAnchorBoundsInScreen();
- anchor_bounds.Inset(bubble_delegate_->anchor_view_insets());
return bubble_delegate_->GetBubbleFrameView()->GetUpdatedWindowBounds(
- anchor_bounds, bubble_delegate_->arrow(),
+ desired_anchor_view->GetAnchorBoundsInScreen(), bubble_delegate_->arrow(),
bubble_delegate_->GetWidget()->client_view()->GetPreferredSize(), true);
}
diff --git a/chromium/ui/views/animation/compositor_animation_runner.h b/chromium/ui/views/animation/compositor_animation_runner.h
index b2e543eb643..4aaec551045 100644
--- a/chromium/ui/views/animation/compositor_animation_runner.h
+++ b/chromium/ui/views/animation/compositor_animation_runner.h
@@ -5,7 +5,6 @@
#ifndef UI_VIEWS_ANIMATION_COMPOSITOR_ANIMATION_RUNNER_H_
#define UI_VIEWS_ANIMATION_COMPOSITOR_ANIMATION_RUNNER_H_
-#include <memory>
#include "base/time/time.h"
#include "ui/compositor/compositor.h"
diff --git a/chromium/ui/views/animation/flood_fill_ink_drop_ripple.h b/chromium/ui/views/animation/flood_fill_ink_drop_ripple.h
index 3a63a8a67d3..2343a3fb61b 100644
--- a/chromium/ui/views/animation/flood_fill_ink_drop_ripple.h
+++ b/chromium/ui/views/animation/flood_fill_ink_drop_ripple.h
@@ -5,8 +5,6 @@
#ifndef UI_VIEWS_ANIMATION_FLOOD_FILL_INK_DROP_RIPPLE_H_
#define UI_VIEWS_ANIMATION_FLOOD_FILL_INK_DROP_RIPPLE_H_
-#include <memory>
-#include <string>
#include "base/macros.h"
#include "base/time/time.h"
diff --git a/chromium/ui/views/animation/ink_drop.cc b/chromium/ui/views/animation/ink_drop.cc
index 9eb25dfdcb6..f58667336f0 100644
--- a/chromium/ui/views/animation/ink_drop.cc
+++ b/chromium/ui/views/animation/ink_drop.cc
@@ -4,13 +4,86 @@
#include "ui/views/animation/ink_drop.h"
+#include <memory>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/compositor/layer.h"
+#include "ui/views/animation/ink_drop_host_view.h"
+#include "ui/views/animation/ink_drop_impl.h"
#include "ui/views/animation/ink_drop_observer.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace views {
+namespace {
+
+// TODO(pbos): Remove this by changing the constructor parameters to
+// InkDropImpl.
+std::unique_ptr<InkDrop> CreateInkDropImpl(
+ InkDropHost* host,
+ InkDropImpl::AutoHighlightMode auto_highlight_mode,
+ bool highlight_on_hover,
+ bool highlight_on_focus) {
+ auto ink_drop = std::make_unique<InkDropImpl>(host, host->host_view()->size(),
+ auto_highlight_mode);
+ ink_drop->SetShowHighlightOnHover(highlight_on_hover);
+ ink_drop->SetShowHighlightOnFocus(highlight_on_focus);
+ return ink_drop;
+}
+
+} // namespace
+
InkDrop::~InkDrop() = default;
+std::unique_ptr<InkDrop> InkDrop::CreateInkDropForSquareRipple(
+ InkDropHost* host,
+ bool highlight_on_hover,
+ bool highlight_on_focus) {
+ return CreateInkDropImpl(host, InkDropImpl::AutoHighlightMode::HIDE_ON_RIPPLE,
+ highlight_on_hover, highlight_on_focus);
+}
+
+void InkDrop::UseInkDropForSquareRipple(InkDropHost* host,
+ bool highlight_on_hover,
+ bool highlight_on_focus) {
+ host->SetCreateInkDropCallback(
+ base::BindRepeating(&InkDrop::CreateInkDropForSquareRipple, host,
+ highlight_on_hover, highlight_on_focus));
+}
+
+std::unique_ptr<InkDrop> InkDrop::CreateInkDropForFloodFillRipple(
+ InkDropHost* host,
+ bool highlight_on_hover,
+ bool highlight_on_focus) {
+ return CreateInkDropImpl(host, InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE,
+ highlight_on_hover, highlight_on_focus);
+}
+
+void InkDrop::UseInkDropForFloodFillRipple(InkDropHost* host,
+ bool highlight_on_hover,
+ bool highlight_on_focus) {
+ host->SetCreateInkDropCallback(
+ base::BindRepeating(&InkDrop::CreateInkDropForFloodFillRipple, host,
+ highlight_on_hover, highlight_on_focus));
+}
+
+std::unique_ptr<InkDrop> InkDrop::CreateInkDropWithoutAutoHighlight(
+ InkDropHost* host,
+ bool highlight_on_hover,
+ bool highlight_on_focus) {
+ return CreateInkDropImpl(host, InkDropImpl::AutoHighlightMode::NONE,
+ highlight_on_hover, highlight_on_focus);
+}
+
+void InkDrop::UseInkDropWithoutAutoHighlight(InkDropHost* host,
+ bool highlight_on_hover,
+ bool highlight_on_focus) {
+ host->SetCreateInkDropCallback(
+ base::BindRepeating(&InkDrop::CreateInkDropWithoutAutoHighlight, host,
+ highlight_on_hover, highlight_on_focus));
+}
+
void InkDrop::AddObserver(InkDropObserver* observer) {
CHECK(observer);
observers_.AddObserver(observer);
@@ -33,24 +106,9 @@ void InkDrop::NotifyInkDropRippleAnimationEnded(InkDropState ink_drop_state) {
observer.InkDropRippleAnimationEnded(ink_drop_state);
}
-InkDropContainerView::InkDropContainerView() = default;
-
-void InkDropContainerView::AddInkDropLayer(ui::Layer* ink_drop_layer) {
- SetPaintToLayer();
- SetVisible(true);
- layer()->SetFillsBoundsOpaquely(false);
- layer()->Add(ink_drop_layer);
-}
-
-void InkDropContainerView::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
- layer()->Remove(ink_drop_layer);
- SetVisible(false);
- DestroyLayer();
-}
-
-bool InkDropContainerView::GetCanProcessEventsWithinSubtree() const {
+InkDropContainerView::InkDropContainerView() {
// Ensure the container View is found as the EventTarget instead of this.
- return false;
+ SetCanProcessEventsWithinSubtree(false);
}
BEGIN_METADATA(InkDropContainerView, views::View)
diff --git a/chromium/ui/views/animation/ink_drop.h b/chromium/ui/views/animation/ink_drop.h
index 5260dab3cbc..50e171c0fd6 100644
--- a/chromium/ui/views/animation/ink_drop.h
+++ b/chromium/ui/views/animation/ink_drop.h
@@ -7,18 +7,20 @@
#include <memory>
+#include "base/callback.h"
#include "base/time/time.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/compositor/layer_tree_owner.h"
#include "ui/events/event_handler.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/animation/ink_drop_state.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/view.h"
#include "ui/views/views_export.h"
namespace views {
+class InkDropHost;
class InkDropObserver;
// Base class that manages the lifetime and state of an ink drop ripple as
@@ -29,6 +31,42 @@ class VIEWS_EXPORT InkDrop {
InkDrop& operator=(const InkDrop&) = delete;
virtual ~InkDrop();
+ // Create an InkDrop appropriate for the "square" InkDropRipple effect. This
+ // InkDrop hides when the ripple effect is active instead of layering
+ // underneath it.
+ static std::unique_ptr<InkDrop> CreateInkDropForSquareRipple(
+ InkDropHost* host,
+ bool highlight_on_hover = true,
+ bool highlight_on_focus = false);
+
+ // Configure `host` to use CreateInkDropForSquareRipple().
+ static void UseInkDropForSquareRipple(InkDropHost* host,
+ bool highlight_on_hover = true,
+ bool highlight_on_focus = false);
+
+ // Create an InkDrop appropriate for the "flood-fill" InkDropRipple effect.
+ // This InkDrop shows as a response to the ripple effect.
+ static std::unique_ptr<InkDrop> CreateInkDropForFloodFillRipple(
+ InkDropHost* host,
+ bool highlight_on_hover = true,
+ bool highlight_on_focus = false);
+
+ // Configure `host` to use CreateInkDropForFloodFillRipple().
+ static void UseInkDropForFloodFillRipple(InkDropHost* host,
+ bool highlight_on_hover = true,
+ bool highlight_on_focus = false);
+
+ // Create an InkDrop whose highlight does not react to its ripple.
+ static std::unique_ptr<InkDrop> CreateInkDropWithoutAutoHighlight(
+ InkDropHost* host,
+ bool highlight_on_hover = true,
+ bool highlight_on_focus = false);
+
+ // Configure `host` to use CreateInkDropWithoutAutoHighlight().
+ static void UseInkDropWithoutAutoHighlight(InkDropHost* host,
+ bool highlight_on_hover = true,
+ bool highlight_on_focus = false);
+
// Called by ink drop hosts when their size is changed.
virtual void HostSizeChanged(const gfx::Size& new_size) = 0;
@@ -92,18 +130,14 @@ class VIEWS_EXPORT InkDrop {
// as a non-ancestor view to labels so that the labels can paint on an opaque
// canvas. This is used to avoid ugly text renderings when labels with subpixel
// rendering enabled are painted onto a non-opaque canvas.
-class VIEWS_EXPORT InkDropContainerView : public views::View {
+// TODO(pbos): Replace with a function that returns unique_ptr<View>, this only
+// calls SetProcessEventsWithinSubtree(false) right now.
+class VIEWS_EXPORT InkDropContainerView : public View {
public:
METADATA_HEADER(InkDropContainerView);
InkDropContainerView();
InkDropContainerView(const InkDropContainerView&) = delete;
InkDropContainerView& operator=(const InkDropContainerView&) = delete;
-
- void AddInkDropLayer(ui::Layer* ink_drop_layer);
- void RemoveInkDropLayer(ui::Layer* ink_drop_layer);
-
- // View:
- bool GetCanProcessEventsWithinSubtree() const override;
};
} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_event_handler.cc b/chromium/ui/views/animation/ink_drop_event_handler.cc
index d0771c26ccd..5e89d089f52 100644
--- a/chromium/ui/views/animation/ink_drop_event_handler.cc
+++ b/chromium/ui/views/animation/ink_drop_event_handler.cc
@@ -23,7 +23,7 @@ InkDropEventHandler::InkDropEventHandler(View* host_view, Delegate* delegate)
InkDropEventHandler::~InkDropEventHandler() = default;
-void InkDropEventHandler::AnimateInkDrop(InkDropState state,
+void InkDropEventHandler::AnimateToState(InkDropState state,
const ui::LocatedEvent* event) {
#if defined(OS_WIN)
// On Windows, don't initiate ink-drops for touch/gesture events.
@@ -93,7 +93,7 @@ void InkDropEventHandler::OnGestureEvent(ui::GestureEvent* event) {
// case would prematurely pre-empt these animations.
return;
}
- AnimateInkDrop(ink_drop_state, event);
+ AnimateToState(ink_drop_state, event);
}
void InkDropEventHandler::OnMouseEvent(ui::MouseEvent* event) {
diff --git a/chromium/ui/views/animation/ink_drop_event_handler.h b/chromium/ui/views/animation/ink_drop_event_handler.h
index ebc957908aa..51e97dfffc0 100644
--- a/chromium/ui/views/animation/ink_drop_event_handler.h
+++ b/chromium/ui/views/animation/ink_drop_event_handler.h
@@ -44,7 +44,7 @@ class VIEWS_EXPORT InkDropEventHandler : public ui::EventHandler,
InkDropEventHandler(View* host_view, Delegate* delegate);
~InkDropEventHandler() override;
- void AnimateInkDrop(InkDropState state, const ui::LocatedEvent* event);
+ void AnimateToState(InkDropState state, const ui::LocatedEvent* event);
ui::LocatedEvent* GetLastRippleTriggeringEvent() const;
private:
diff --git a/chromium/ui/views/animation/ink_drop_highlight_observer.h b/chromium/ui/views/animation/ink_drop_highlight_observer.h
index eb98bd7340d..c463f50c551 100644
--- a/chromium/ui/views/animation/ink_drop_highlight_observer.h
+++ b/chromium/ui/views/animation/ink_drop_highlight_observer.h
@@ -5,7 +5,6 @@
#ifndef UI_VIEWS_ANIMATION_INK_DROP_HIGHLIGHT_OBSERVER_H_
#define UI_VIEWS_ANIMATION_INK_DROP_HIGHLIGHT_OBSERVER_H_
-#include <string>
#include "base/macros.h"
#include "ui/views/animation/ink_drop_animation_ended_reason.h"
diff --git a/chromium/ui/views/animation/ink_drop_host_view.cc b/chromium/ui/views/animation/ink_drop_host_view.cc
index 23d77f89c96..5215b9e67dc 100644
--- a/chromium/ui/views/animation/ink_drop_host_view.cc
+++ b/chromium/ui/views/animation/ink_drop_host_view.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/events/event.h"
#include "ui/events/scoped_target_handler.h"
#include "ui/gfx/color_palette.h"
@@ -19,80 +20,103 @@
#include "ui/views/animation/square_ink_drop_ripple.h"
#include "ui/views/controls/focus_ring.h"
#include "ui/views/controls/highlight_path_generator.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/view_class_properties.h"
namespace views {
// static
-constexpr gfx::Size InkDropHostView::kDefaultInkDropSize;
+constexpr gfx::Size InkDropHost::kDefaultSquareInkDropSize;
-InkDropHostView::InkDropHostViewEventHandlerDelegate::
- InkDropHostViewEventHandlerDelegate(InkDropHostView* host_view)
- : host_view_(host_view) {}
+InkDropHost::InkDropHostEventHandlerDelegate::InkDropHostEventHandlerDelegate(
+ InkDropHost* ink_drop_host)
+ : ink_drop_host_(ink_drop_host) {}
-bool InkDropHostView::InkDropHostViewEventHandlerDelegate::HasInkDrop() const {
- return host_view_->HasInkDrop();
+bool InkDropHost::InkDropHostEventHandlerDelegate::HasInkDrop() const {
+ return ink_drop_host_->HasInkDrop();
}
-InkDrop* InkDropHostView::InkDropHostViewEventHandlerDelegate::GetInkDrop() {
- return host_view_->GetInkDrop();
+InkDrop* InkDropHost::InkDropHostEventHandlerDelegate::GetInkDrop() {
+ return ink_drop_host_->GetInkDrop();
}
-bool InkDropHostView::InkDropHostViewEventHandlerDelegate::
- SupportsGestureEvents() const {
- return host_view_->ink_drop_mode_ == InkDropMode::ON;
+bool InkDropHost::InkDropHostEventHandlerDelegate::SupportsGestureEvents()
+ const {
+ return ink_drop_host_->ink_drop_mode_ == InkDropMode::ON;
+}
+
+InkDropHost::ViewLayerTransformObserver::ViewLayerTransformObserver(
+ InkDropHost* ink_drop_host,
+ View* host_view)
+ : ink_drop_host_(ink_drop_host) {
+ observation_.Observe(host_view);
}
-InkDropHostView::InkDropHostView()
- : ink_drop_event_handler_delegate_(this),
- ink_drop_event_handler_(this, &ink_drop_event_handler_delegate_) {}
+InkDropHost::ViewLayerTransformObserver::~ViewLayerTransformObserver() =
+ default;
+
+void InkDropHost::ViewLayerTransformObserver::OnViewLayerTransformed(
+ View* observed_view) {
+ // Notify the ink drop that we have transformed so it can adapt
+ // accordingly.
+ if (ink_drop_host_->HasInkDrop()) {
+ ink_drop_host_->GetInkDrop()->HostTransformChanged(
+ observed_view->GetTransform());
+ }
+}
-InkDropHostView::~InkDropHostView() {
+InkDropHost::InkDropHost(View* view)
+ : host_view_(view),
+ host_view_transform_observer_(this, view),
+ ink_drop_event_handler_delegate_(this),
+ ink_drop_event_handler_(view, &ink_drop_event_handler_delegate_) {}
+
+InkDropHost::~InkDropHost() {
// TODO(bruthig): Improve InkDropImpl to be safer about calling back to
// potentially destroyed InkDropHosts and remove |destroying_|.
destroying_ = true;
}
-void InkDropHostView::AddInkDropLayer(ui::Layer* ink_drop_layer) {
- // If a clip is provided, use that as it is more performant than a mask.
- if (!AddInkDropClip(ink_drop_layer))
- InstallInkDropMask(ink_drop_layer);
- AddLayerBeneathView(ink_drop_layer);
+std::unique_ptr<InkDrop> InkDropHost::CreateInkDrop() {
+ if (create_ink_drop_callback_)
+ return create_ink_drop_callback_.Run();
+ return InkDrop::CreateInkDropForFloodFillRipple(this);
}
-void InkDropHostView::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
- // No need to do anything when called during shutdown, and if a derived
- // class has overridden Add/RemoveInkDropLayer, running this implementation
- // would be wrong.
- if (destroying_)
- return;
- RemoveLayerBeneathView(ink_drop_layer);
-
- // Remove clipping.
- ink_drop_layer->SetClipRect(gfx::Rect());
- ink_drop_layer->SetRoundedCornerRadius(gfx::RoundedCornersF(0.f));
+void InkDropHost::SetCreateInkDropCallback(
+ base::RepeatingCallback<std::unique_ptr<InkDrop>()> callback) {
+ create_ink_drop_callback_ = std::move(callback);
+}
- // Layers safely handle destroying a mask layer before the masked layer.
- ink_drop_mask_.reset();
+std::unique_ptr<InkDropRipple> InkDropHost::CreateInkDropRipple() const {
+ if (create_ink_drop_ripple_callback_)
+ return create_ink_drop_ripple_callback_.Run();
+ return std::make_unique<views::FloodFillInkDropRipple>(
+ host_view_->size(), gfx::Insets(), GetInkDropCenterBasedOnLastEvent(),
+ GetBaseColor(), GetVisibleOpacity());
}
-std::unique_ptr<InkDrop> InkDropHostView::CreateInkDrop() {
- return CreateDefaultFloodFillInkDropImpl();
+void InkDropHost::SetCreateRippleCallback(
+ base::RepeatingCallback<std::unique_ptr<InkDropRipple>()> callback) {
+ create_ink_drop_ripple_callback_ = std::move(callback);
}
-std::unique_ptr<InkDropRipple> InkDropHostView::CreateInkDropRipple() const {
- return std::make_unique<views::FloodFillInkDropRipple>(
- size(), gfx::Insets(), GetInkDropCenterBasedOnLastEvent(),
- GetInkDropBaseColor(), GetInkDropVisibleOpacity());
+gfx::Point InkDropHost::GetInkDropCenterBasedOnLastEvent() const {
+ return GetEventHandler()->GetLastRippleTriggeringEvent()
+ ? GetEventHandler()->GetLastRippleTriggeringEvent()->location()
+ : host_view_->GetMirroredRect(host_view_->GetContentsBounds())
+ .CenterPoint();
}
-std::unique_ptr<InkDropHighlight> InkDropHostView::CreateInkDropHighlight()
- const {
+std::unique_ptr<InkDropHighlight> InkDropHost::CreateInkDropHighlight() const {
+ if (create_ink_drop_highlight_callback_)
+ return create_ink_drop_highlight_callback_.Run();
+
auto highlight = std::make_unique<views::InkDropHighlight>(
- size(), 0, gfx::RectF(GetMirroredRect(GetLocalBounds())).CenterPoint(),
- GetInkDropBaseColor());
+ host_view_->size(), 0,
+ gfx::RectF(host_view_->GetMirroredRect(host_view_->GetLocalBounds()))
+ .CenterPoint(),
+ GetBaseColor());
// TODO(pbos): Once |ink_drop_highlight_opacity_| is either always set or
// callers are using the default InkDropHighlight value then make this a
// constructor argument to InkDropHighlight.
@@ -102,154 +126,164 @@ std::unique_ptr<InkDropHighlight> InkDropHostView::CreateInkDropHighlight()
return highlight;
}
-std::unique_ptr<views::InkDropMask> InkDropHostView::CreateInkDropMask() const {
- return std::make_unique<views::PathInkDropMask>(size(),
- GetHighlightPath(this));
+void InkDropHost::SetCreateHighlightCallback(
+ base::RepeatingCallback<std::unique_ptr<InkDropHighlight>()> callback) {
+ create_ink_drop_highlight_callback_ = std::move(callback);
+}
+
+std::unique_ptr<views::InkDropMask> InkDropHost::CreateInkDropMask() const {
+ if (create_ink_drop_mask_callback_)
+ return create_ink_drop_mask_callback_.Run();
+ return std::make_unique<views::PathInkDropMask>(host_view_->size(),
+ GetHighlightPath(host_view_));
+}
+
+void InkDropHost::SetCreateMaskCallback(
+ base::RepeatingCallback<std::unique_ptr<InkDropMask>()> callback) {
+ create_ink_drop_mask_callback_ = std::move(callback);
+}
+
+SkColor InkDropHost::GetBaseColor() const {
+ if (ink_drop_base_color_callback_)
+ return ink_drop_base_color_callback_.Run();
+ DCHECK(ink_drop_base_color_);
+ return ink_drop_base_color_.value_or(gfx::kPlaceholderColor);
}
-SkColor InkDropHostView::GetInkDropBaseColor() const {
- NOTREACHED();
- return gfx::kPlaceholderColor;
+void InkDropHost::SetBaseColor(SkColor color) {
+ ink_drop_base_color_ = color;
}
-void InkDropHostView::SetInkDropMode(InkDropMode ink_drop_mode) {
+void InkDropHost::SetBaseColorCallback(
+ base::RepeatingCallback<SkColor()> callback) {
+ ink_drop_base_color_callback_ = std::move(callback);
+}
+
+void InkDropHost::SetMode(InkDropMode ink_drop_mode) {
ink_drop_mode_ = ink_drop_mode;
ink_drop_ = nullptr;
}
-void InkDropHostView::SetInkDropVisibleOpacity(float visible_opacity) {
+void InkDropHost::SetVisibleOpacity(float visible_opacity) {
if (visible_opacity == ink_drop_visible_opacity_)
return;
ink_drop_visible_opacity_ = visible_opacity;
- OnPropertyChanged(&ink_drop_visible_opacity_, kPropertyEffectsPaint);
}
-float InkDropHostView::GetInkDropVisibleOpacity() const {
+float InkDropHost::GetVisibleOpacity() const {
return ink_drop_visible_opacity_;
}
-void InkDropHostView::SetInkDropHighlightOpacity(
- base::Optional<float> opacity) {
+void InkDropHost::SetHighlightOpacity(absl::optional<float> opacity) {
if (opacity == ink_drop_highlight_opacity_)
return;
ink_drop_highlight_opacity_ = opacity;
- OnPropertyChanged(&ink_drop_highlight_opacity_, kPropertyEffectsPaint);
}
-base::Optional<float> InkDropHostView::GetInkDropHighlightOpacity() const {
- return ink_drop_highlight_opacity_;
-}
-
-void InkDropHostView::SetInkDropSmallCornerRadius(int small_radius) {
+void InkDropHost::SetSmallCornerRadius(int small_radius) {
if (small_radius == ink_drop_small_corner_radius_)
return;
ink_drop_small_corner_radius_ = small_radius;
- OnPropertyChanged(&ink_drop_small_corner_radius_, kPropertyEffectsLayout);
}
-int InkDropHostView::GetInkDropSmallCornerRadius() const {
+int InkDropHost::GetSmallCornerRadius() const {
return ink_drop_small_corner_radius_;
}
-void InkDropHostView::SetInkDropLargeCornerRadius(int large_radius) {
+void InkDropHost::SetLargeCornerRadius(int large_radius) {
if (large_radius == ink_drop_large_corner_radius_)
return;
ink_drop_large_corner_radius_ = large_radius;
- OnPropertyChanged(&ink_drop_large_corner_radius_, kPropertyEffectsLayout);
}
-int InkDropHostView::GetInkDropLargeCornerRadius() const {
+int InkDropHost::GetLargeCornerRadius() const {
return ink_drop_large_corner_radius_;
}
-void InkDropHostView::AnimateInkDrop(InkDropState state,
- const ui::LocatedEvent* event) {
- GetEventHandler()->AnimateInkDrop(state, event);
+void InkDropHost::AnimateToState(InkDropState state,
+ const ui::LocatedEvent* event) {
+ GetEventHandler()->AnimateToState(state, event);
+}
+
+bool InkDropHost::HasInkDrop() const {
+ return !!ink_drop_;
}
-InkDrop* InkDropHostView::GetInkDrop() {
+InkDrop* InkDropHost::GetInkDrop() {
if (!ink_drop_) {
if (ink_drop_mode_ == InkDropMode::OFF)
ink_drop_ = std::make_unique<InkDropStub>();
else
ink_drop_ = CreateInkDrop();
- OnInkDropCreated();
}
return ink_drop_.get();
}
-bool InkDropHostView::GetHighlighted() const {
+bool InkDropHost::GetHighlighted() const {
return ink_drop_ && ink_drop_->IsHighlightFadingInOrVisible();
}
-base::CallbackListSubscription InkDropHostView::AddHighlightedChangedCallback(
- PropertyChangedCallback callback) {
- // Since the highlight state is not directly represented by a member, use the
- // applicable member (|ink_drop_|) as the property key. Note that this won't
- // suffice if a future InkDrop-related property is added.
- return AddPropertyChangedCallback(&ink_drop_, std::move(callback));
+base::CallbackListSubscription InkDropHost::AddHighlightedChangedCallback(
+ base::RepeatingClosure callback) {
+ return highlighted_changed_callbacks_.Add(std::move(callback));
}
-void InkDropHostView::OnInkDropHighlightedChanged() {
- // See comments in AddHighlightedChangedCallback() re: using |ink_drop_| as
- // the key.
- OnPropertyChanged(&ink_drop_, kPropertyEffectsNone);
+void InkDropHost::OnInkDropHighlightedChanged() {
+ highlighted_changed_callbacks_.Notify();
}
-std::unique_ptr<InkDropImpl> InkDropHostView::CreateDefaultInkDropImpl() {
- auto ink_drop = std::make_unique<InkDropImpl>(this, size());
- ink_drop->SetAutoHighlightMode(
- InkDropImpl::AutoHighlightMode::HIDE_ON_RIPPLE);
- return ink_drop;
+void InkDropHost::AddInkDropLayer(ui::Layer* ink_drop_layer) {
+ // If a clip is provided, use that as it is more performant than a mask.
+ if (!AddInkDropClip(ink_drop_layer))
+ InstallInkDropMask(ink_drop_layer);
+ host_view_->AddLayerBeneathView(ink_drop_layer);
}
-std::unique_ptr<InkDropImpl>
-InkDropHostView::CreateDefaultFloodFillInkDropImpl() {
- auto ink_drop = std::make_unique<InkDropImpl>(this, size());
- ink_drop->SetAutoHighlightMode(
- views::InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE);
- return ink_drop;
-}
+void InkDropHost::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
+ // No need to do anything when called during shutdown.
+ // TODO(pbos): Reinvestigate this now that this is not part of virtual
+ // overrides. This looks like it may accidentally leave a layer attached to
+ // the View? Likely not an issue until InkDropHost start getting removed
+ // without destroying the associated View.
+ if (destroying_)
+ return;
-std::unique_ptr<InkDropRipple> InkDropHostView::CreateDefaultInkDropRipple(
- const gfx::Point& center_point,
- const gfx::Size& size) const {
- return CreateSquareInkDropRipple(center_point, size);
+ host_view_->RemoveLayerBeneathView(ink_drop_layer);
+
+ // Remove clipping.
+ ink_drop_layer->SetClipRect(gfx::Rect());
+ ink_drop_layer->SetRoundedCornerRadius(gfx::RoundedCornersF(0.f));
+
+ // Layers safely handle destroying a mask layer before the masked layer.
+ ink_drop_mask_.reset();
}
-std::unique_ptr<InkDropRipple> InkDropHostView::CreateSquareInkDropRipple(
+std::unique_ptr<InkDropRipple> InkDropHost::CreateSquareRipple(
const gfx::Point& center_point,
const gfx::Size& size) const {
+ constexpr float kLargeInkDropScale = 1.333f;
+ const gfx::Size large_size = gfx::ScaleToCeiledSize(size, kLargeInkDropScale);
auto ripple = std::make_unique<SquareInkDropRipple>(
- CalculateLargeInkDropSize(size), ink_drop_large_corner_radius_, size,
- ink_drop_small_corner_radius_, center_point, GetInkDropBaseColor(),
- GetInkDropVisibleOpacity());
+ large_size, ink_drop_large_corner_radius_, size,
+ ink_drop_small_corner_radius_, center_point, GetBaseColor(),
+ GetVisibleOpacity());
return ripple;
}
-bool InkDropHostView::HasInkDrop() const {
- return !!ink_drop_;
-}
-
-gfx::Point InkDropHostView::GetInkDropCenterBasedOnLastEvent() const {
- return GetEventHandler()->GetLastRippleTriggeringEvent()
- ? GetEventHandler()->GetLastRippleTriggeringEvent()->location()
- : GetMirroredRect(GetContentsBounds()).CenterPoint();
-}
-
-void InkDropHostView::InstallInkDropMask(ui::Layer* ink_drop_layer) {
- ink_drop_mask_ = CreateInkDropMask();
- if (ink_drop_mask_)
- ink_drop_layer->SetMaskLayer(ink_drop_mask_->layer());
+const InkDropEventHandler* InkDropHost::GetEventHandler() const {
+ if (ink_drop_event_handler_override_)
+ return ink_drop_event_handler_override_;
+ return &ink_drop_event_handler_;
}
-void InkDropHostView::ResetInkDropMask() {
- ink_drop_mask_.reset();
+InkDropEventHandler* InkDropHost::GetEventHandler() {
+ return const_cast<InkDropEventHandler*>(
+ const_cast<const InkDropHost*>(this)->GetEventHandler());
}
-bool InkDropHostView::AddInkDropClip(ui::Layer* ink_drop_layer) {
- base::Optional<gfx::RRectF> clipping_data =
- HighlightPathGenerator::GetRoundRectForView(this);
+bool InkDropHost::AddInkDropClip(ui::Layer* ink_drop_layer) {
+ absl::optional<gfx::RRectF> clipping_data =
+ HighlightPathGenerator::GetRoundRectForView(host_view_);
if (!clipping_data)
return false;
@@ -272,41 +306,10 @@ bool InkDropHostView::AddInkDropClip(ui::Layer* ink_drop_layer) {
return true;
}
-// static
-gfx::Size InkDropHostView::CalculateLargeInkDropSize(
- const gfx::Size& small_size) {
- // The scale factor to compute the large size of the default
- // SquareInkDropRipple.
- constexpr float kLargeInkDropScale = 1.333f;
- return gfx::ScaleToCeiledSize(gfx::Size(small_size), kLargeInkDropScale);
-}
-
-void InkDropHostView::OnLayerTransformed(const gfx::Transform& old_transform,
- ui::PropertyChangeReason reason) {
- View::OnLayerTransformed(old_transform, reason);
-
- // Notify the ink drop that we have transformed so it can adapt accordingly.
- if (HasInkDrop())
- GetInkDrop()->HostTransformChanged(GetTransform());
-}
-
-const InkDropEventHandler* InkDropHostView::GetEventHandler() const {
- if (ink_drop_event_handler_override_)
- return ink_drop_event_handler_override_;
- return &ink_drop_event_handler_;
-}
-
-InkDropEventHandler* InkDropHostView::GetEventHandler() {
- return const_cast<InkDropEventHandler*>(
- const_cast<const InkDropHostView*>(this)->GetEventHandler());
+void InkDropHost::InstallInkDropMask(ui::Layer* ink_drop_layer) {
+ ink_drop_mask_ = CreateInkDropMask();
+ DCHECK(ink_drop_mask_);
+ ink_drop_layer->SetMaskLayer(ink_drop_mask_->layer());
}
-BEGIN_METADATA(InkDropHostView, View)
-ADD_READONLY_PROPERTY_METADATA(bool, Highlighted)
-ADD_PROPERTY_METADATA(float, InkDropVisibleOpacity)
-ADD_PROPERTY_METADATA(base::Optional<float>, InkDropHighlightOpacity)
-ADD_PROPERTY_METADATA(int, InkDropLargeCornerRadius)
-ADD_PROPERTY_METADATA(int, InkDropSmallCornerRadius)
-END_METADATA
-
} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_host_view.h b/chromium/ui/views/animation/ink_drop_host_view.h
index 8c8f77fc26d..ac018b12980 100644
--- a/chromium/ui/views/animation/ink_drop_host_view.h
+++ b/chromium/ui/views/animation/ink_drop_host_view.h
@@ -29,15 +29,24 @@ class InkDropRipple;
enum class InkDropState;
namespace test {
-class InkDropHostViewTestApi;
+class InkDropHostTestApi;
} // namespace test
-// A view that provides InkDropHost functionality.
-class VIEWS_EXPORT InkDropHostView : public View {
+// TODO(crbug.com/931964): Rename this type and move this header. Also consider
+// if InkDropHost should be what implements the InkDrop interface and have that
+// be the public interface.
+// The current division of labor is roughly as follows:
+// * InkDropHost manages an InkDrop and is responsible for a lot of its
+// configuration and creating the parts of the InkDrop.
+// * InkDrop manages the parts of the ink-drop effect once it's up and running.
+// * InkDropRipple is a ripple effect that usually triggers as a result of
+// clicking or activating the button / similar which hosts this.
+// * InkDropHighlight manages the hover/focus highlight layer.
+// TODO(pbos): See if this can be the only externally visible surface for an
+// ink-drop effect, and rename this InkDrop, or consolidate with InkDrop.
+class VIEWS_EXPORT InkDropHost {
public:
- METADATA_HEADER(InkDropHostView);
-
- // Used in SetInkDropMode() to specify whether the ink drop effect is enabled
+ // Used in SetMode() to specify whether the ink drop effect is enabled
// or not for the view. In case of having an ink drop, it also specifies
// whether the default event handler for the ink drop should be installed or
// the subclass will handle ink drop events itself.
@@ -47,40 +56,59 @@ class VIEWS_EXPORT InkDropHostView : public View {
ON_NO_GESTURE_HANDLER,
};
- InkDropHostView();
- ~InkDropHostView() override;
-
- // Adds the |ink_drop_layer| in to a visible layer tree.
- virtual void AddInkDropLayer(ui::Layer* ink_drop_layer);
+ explicit InkDropHost(View* host);
+ InkDropHost(const InkDropHost&) = delete;
+ InkDropHost& operator=(const InkDropHost&) = delete;
+ virtual ~InkDropHost();
- // Removes |ink_drop_layer| from the layer tree.
- virtual void RemoveInkDropLayer(ui::Layer* ink_drop_layer);
+ // Returns a configured InkDrop. To override default behavior call
+ // SetCreateInkDropCallback().
+ std::unique_ptr<InkDrop> CreateInkDrop();
- // Returns a configured InkDrop. In general subclasses will return an
- // InkDropImpl instance that will use the CreateInkDropRipple() and
- // CreateInkDropHighlight() methods to create the visual effects.
- //
- // Subclasses should override this if they need to configure any properties
- // specific to the InkDrop instance. e.g. the AutoHighlightMode of an
- // InkDropImpl instance.
- virtual std::unique_ptr<InkDrop> CreateInkDrop();
+ // Replace CreateInkDrop() behavior.
+ void SetCreateInkDropCallback(
+ base::RepeatingCallback<std::unique_ptr<InkDrop>()> callback);
// Creates and returns the visual effect used for press. Used by InkDropImpl
// instances.
- virtual std::unique_ptr<InkDropRipple> CreateInkDropRipple() const;
+ std::unique_ptr<InkDropRipple> CreateInkDropRipple() const;
+
+ // Replaces CreateInkDropRipple() behavior.
+ void SetCreateRippleCallback(
+ base::RepeatingCallback<std::unique_ptr<InkDropRipple>()> callback);
+
+ // Returns the point of the |last_ripple_triggering_event_| if it was a
+ // LocatedEvent, otherwise the center point of the local bounds is returned.
+ // This is nominally used by the InkDropRipple.
+ gfx::Point GetInkDropCenterBasedOnLastEvent() const;
// Creates and returns the visual effect used for hover and focus. Used by
- // InkDropImpl instances.
- virtual std::unique_ptr<InkDropHighlight> CreateInkDropHighlight() const;
+ // InkDropImpl instances. To override behavior call
+ // SetCreateHighlightCallback().
+ std::unique_ptr<InkDropHighlight> CreateInkDropHighlight() const;
+
+ // Replaces CreateInkDropHighlight() behavior.
+ void SetCreateHighlightCallback(
+ base::RepeatingCallback<std::unique_ptr<InkDropHighlight>()> callback);
- // Subclasses can override to return a mask for the ink drop. By default,
- // this generates a mask based on HighlightPathGenerator.
- // TODO(pbos): Replace overrides with HighlightPathGenerator usage and remove
- // this function.
- virtual std::unique_ptr<views::InkDropMask> CreateInkDropMask() const;
+ // Callback replacement of CreateInkDropMask().
+ // TODO(pbos): Investigate removing this. It currently is only used by
+ // ToolbarButton.
+ void SetCreateMaskCallback(
+ base::RepeatingCallback<std::unique_ptr<InkDropMask>()> callback);
// Returns the base color for the ink drop.
- virtual SkColor GetInkDropBaseColor() const;
+ SkColor GetBaseColor() const;
+
+ // Sets the base color for the ink drop.
+ void SetBaseColor(SkColor color);
+
+ // Callback version of GetBaseColor(). If possible, prefer using
+ // SetBaseColor(). If a callback has been set by previous configuration
+ // and you want to use the base version of GetBaseColor() that's reading
+ // SetBaseColor(), you need to reset the callback by calling
+ // SetBaseColorCallback({}).
+ void SetBaseColorCallback(base::RepeatingCallback<SkColor()> callback);
// Toggle to enable/disable an InkDrop on this View. Descendants can override
// CreateInkDropHighlight() and CreateInkDropRipple() to change the look/feel
@@ -88,19 +116,18 @@ class VIEWS_EXPORT InkDropHostView : public View {
//
// TODO(bruthig): Add an easier mechanism than overriding functions to allow
// subclasses/clients to specify the flavor of ink drop.
- void SetInkDropMode(InkDropMode ink_drop_mode);
+ void SetMode(InkDropMode ink_drop_mode);
- void SetInkDropVisibleOpacity(float visible_opacity);
- float GetInkDropVisibleOpacity() const;
+ void SetVisibleOpacity(float visible_opacity);
+ float GetVisibleOpacity() const;
- void SetInkDropHighlightOpacity(base::Optional<float> opacity);
- base::Optional<float> GetInkDropHighlightOpacity() const;
+ void SetHighlightOpacity(absl::optional<float> opacity);
- void SetInkDropSmallCornerRadius(int small_radius);
- int GetInkDropSmallCornerRadius() const;
+ void SetSmallCornerRadius(int small_radius);
+ int GetSmallCornerRadius() const;
- void SetInkDropLargeCornerRadius(int large_radius);
- int GetInkDropLargeCornerRadius() const;
+ void SetLargeCornerRadius(int large_radius);
+ int GetLargeCornerRadius() const;
// Allows InstallableInkDrop to override our InkDropEventHandler
// instance.
@@ -119,122 +146,116 @@ class VIEWS_EXPORT InkDropHostView : public View {
// the purposes of centering ink drop ripples on located Events. Thus nullptr
// has been used by clients who do not have an Event instance available to
// them.
- void AnimateInkDrop(InkDropState state, const ui::LocatedEvent* event);
+ void AnimateToState(InkDropState state, const ui::LocatedEvent* event);
+
+ // Returns true if an ink drop instance has been created.
+ bool HasInkDrop() const;
// Provides public access to |ink_drop_| so that factory methods can configure
// the inkdrop. Implements lazy initialization of |ink_drop_| so as to avoid
// virtual method calls during construction since subclasses should be able to
- // call SetInkDropMode() during construction.
- //
- // WARNING: please don't override this; this is only virtual for the
- // InstallableInkDrop refactor. TODO(crbug.com/931964): make non-virtual when
- // this isn't necessary anymore.
- virtual InkDrop* GetInkDrop();
+ // call SetMode() during construction.
+ InkDrop* GetInkDrop();
// Returns whether the ink drop should be considered "highlighted" (in or
// animating into "highlight visible" steady state).
bool GetHighlighted() const;
base::CallbackListSubscription AddHighlightedChangedCallback(
- PropertyChangedCallback callback);
+ base::RepeatingClosure callback);
// Should be called by InkDrop implementations when their highlight state
// changes, to trigger the corresponding property change notification here.
void OnInkDropHighlightedChanged();
- protected:
- // Size used for the default SquareInkDropRipple.
- static constexpr gfx::Size kDefaultInkDropSize = gfx::Size(24, 24);
-
- // Called after a new InkDrop instance is created.
- virtual void OnInkDropCreated() {}
-
- // Returns an InkDropImpl suitable for use with a square ink drop.
- // TODO(pbos): Rename to CreateDefaultSquareInkDropImpl.
- std::unique_ptr<InkDropImpl> CreateDefaultInkDropImpl();
+ // Methods called by InkDrop for attaching its layer.
+ // TODO(pbos): Investigate using direct calls on View::AddLayerBeneathView.
+ void AddInkDropLayer(ui::Layer* ink_drop_layer);
+ void RemoveInkDropLayer(ui::Layer* ink_drop_layer);
- // Returns an InkDropImpl configured to work well with a flood-fill ink drop
- // ripple.
- std::unique_ptr<InkDropImpl> CreateDefaultFloodFillInkDropImpl();
-
- // TODO(pbos): Migrate uses to CreateSquareInkDropRipple which this calls
- // directly.
- std::unique_ptr<InkDropRipple> CreateDefaultInkDropRipple(
- const gfx::Point& center_point,
- const gfx::Size& size = kDefaultInkDropSize) const;
+ // Size used by default for the SquareInkDropRipple.
+ static constexpr gfx::Size kDefaultSquareInkDropSize = gfx::Size(24, 24);
// Creates a SquareInkDropRipple centered on |center_point|.
- std::unique_ptr<InkDropRipple> CreateSquareInkDropRipple(
+ std::unique_ptr<InkDropRipple> CreateSquareRipple(
const gfx::Point& center_point,
- const gfx::Size& size) const;
-
- // Returns true if an ink drop instance has been created.
- bool HasInkDrop() const;
-
- // Returns the point of the |last_ripple_triggering_event_| if it was a
- // LocatedEvent, otherwise the center point of the local bounds is returned.
- gfx::Point GetInkDropCenterBasedOnLastEvent() const;
+ const gfx::Size& size = kDefaultSquareInkDropSize) const;
- // Initializes and sets a mask on |ink_drop_layer|. No-op if
- // CreateInkDropMask() returns null. This will not run if |AddInkDropClip()|
- // succeeds in the default implementation of |AddInkDropLayer()|.
- void InstallInkDropMask(ui::Layer* ink_drop_layer);
-
- void ResetInkDropMask();
+ View* host_view() { return host_view_; }
+ const View* host_view() const { return host_view_; }
- // Adds a clip rect on the root layer of the ink drop impl. This is a more
- // performant alternative to using circles or rectangle mask layers. Returns
- // true if a clip was added.
- bool AddInkDropClip(ui::Layer* ink_drop_layer);
+ private:
+ friend class test::InkDropHostTestApi;
- // Returns a large ink drop size based on the |small_size| that works well
- // with the SquareInkDropRipple animation durations.
- static gfx::Size CalculateLargeInkDropSize(const gfx::Size& small_size);
+ class ViewLayerTransformObserver : public ViewObserver {
+ public:
+ ViewLayerTransformObserver(InkDropHost* ink_drop_host, View* host);
+ ~ViewLayerTransformObserver() override;
- // View:
- void OnLayerTransformed(const gfx::Transform& old_transform,
- ui::PropertyChangeReason reason) override;
+ void OnViewLayerTransformed(View* observed_view) override;
- private:
- friend class test::InkDropHostViewTestApi;
+ private:
+ base::ScopedObservation<View, ViewObserver> observation_{this};
+ InkDropHost* const ink_drop_host_;
+ };
- class InkDropHostViewEventHandlerDelegate
- : public InkDropEventHandler::Delegate {
+ class InkDropHostEventHandlerDelegate : public InkDropEventHandler::Delegate {
public:
- explicit InkDropHostViewEventHandlerDelegate(InkDropHostView* host_view);
+ explicit InkDropHostEventHandlerDelegate(InkDropHost* host);
- // InkDropEventHandler:
+ // InkDropEventHandler::Delegate:
InkDrop* GetInkDrop() override;
bool HasInkDrop() const override;
bool SupportsGestureEvents() const override;
private:
- // The host view.
- InkDropHostView* const host_view_;
+ // The host.
+ InkDropHost* const ink_drop_host_;
};
const InkDropEventHandler* GetEventHandler() const;
InkDropEventHandler* GetEventHandler();
+ // This generates a mask for the InkDrop.
+ std::unique_ptr<views::InkDropMask> CreateInkDropMask() const;
+
+ // Adds a clip rect on the root layer of the ink drop impl. This is a more
+ // performant alternative to using circles or rectangle mask layers. Returns
+ // true if a clip was added.
+ bool AddInkDropClip(ui::Layer* ink_drop_layer);
+
+ // Initializes and sets a mask on `ink_drop_layer`. This will not run if
+ // AddInkDropClip() succeeds in the default implementation of
+ // AddInkDropLayer().
+ void InstallInkDropMask(ui::Layer* ink_drop_layer);
+
+ View* const host_view_;
+
// Defines what type of |ink_drop_| to create.
- InkDropMode ink_drop_mode_ = InkDropMode::OFF;
+ InkDropMode ink_drop_mode_ = views::InkDropHost::InkDropMode::OFF;
+
+ // Used to observe View and inform the InkDrop of host-transform changes.
+ ViewLayerTransformObserver host_view_transform_observer_;
// Should not be accessed directly. Use GetInkDrop() instead.
std::unique_ptr<InkDrop> ink_drop_;
// Intentionally declared after |ink_drop_| so that it doesn't access a
// destroyed |ink_drop_| during destruction.
- InkDropHostViewEventHandlerDelegate ink_drop_event_handler_delegate_;
+ InkDropHostEventHandlerDelegate ink_drop_event_handler_delegate_;
InkDropEventHandler ink_drop_event_handler_;
InkDropEventHandler* ink_drop_event_handler_override_ = nullptr;
float ink_drop_visible_opacity_ = 0.175f;
+ // The color of the ripple and hover.
+ absl::optional<SkColor> ink_drop_base_color_;
+
// TODO(pbos): Audit call sites to make sure highlight opacity is either
// always set or using the default value. Then make this a non-optional float.
- base::Optional<float> ink_drop_highlight_opacity_;
+ absl::optional<float> ink_drop_highlight_opacity_;
// Radii used for the SquareInkDropRipple.
int ink_drop_small_corner_radius_ = 2;
@@ -244,19 +265,19 @@ class VIEWS_EXPORT InkDropHostView : public View {
std::unique_ptr<views::InkDropMask> ink_drop_mask_;
- DISALLOW_COPY_AND_ASSIGN(InkDropHostView);
-};
+ base::RepeatingCallback<std::unique_ptr<InkDrop>()> create_ink_drop_callback_;
+ base::RepeatingCallback<std::unique_ptr<InkDropRipple>()>
+ create_ink_drop_ripple_callback_;
+ base::RepeatingCallback<std::unique_ptr<InkDropHighlight>()>
+ create_ink_drop_highlight_callback_;
-BEGIN_VIEW_BUILDER(VIEWS_EXPORT, InkDropHostView, View)
-VIEW_BUILDER_PROPERTY(base::Optional<float>, InkDropHighlightOpacity)
-VIEW_BUILDER_PROPERTY(int, InkDropLargeCornerRadius)
-VIEW_BUILDER_PROPERTY(InkDropHostView::InkDropMode, InkDropMode)
-VIEW_BUILDER_PROPERTY(int, InkDropSmallCornerRadius)
-VIEW_BUILDER_PROPERTY(float, InkDropVisibleOpacity)
-END_VIEW_BUILDER
+ base::RepeatingCallback<std::unique_ptr<InkDropMask>()>
+ create_ink_drop_mask_callback_;
+ base::RepeatingCallback<SkColor()> ink_drop_base_color_callback_;
-} // namespace views
+ base::RepeatingClosureList highlighted_changed_callbacks_;
+};
-DEFINE_VIEW_BUILDER(VIEWS_EXPORT, InkDropHostView)
+} // namespace views
#endif // UI_VIEWS_ANIMATION_INK_DROP_HOST_VIEW_H_
diff --git a/chromium/ui/views/animation/ink_drop_host_view_unittest.cc b/chromium/ui/views/animation/ink_drop_host_view_unittest.cc
index f0c503a0fda..28718c423ae 100644
--- a/chromium/ui/views/animation/ink_drop_host_view_unittest.cc
+++ b/chromium/ui/views/animation/ink_drop_host_view_unittest.cc
@@ -6,6 +6,7 @@
#include <memory>
+#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
@@ -29,62 +30,59 @@
namespace views {
namespace test {
-using InkDropMode = InkDropHostViewTestApi::InkDropMode;
+using InkDropMode = InkDropHostTestApi::InkDropMode;
-class TestInkDropHostView : public InkDropHostView {
+class TestViewWithInkDrop : public View {
public:
- TestInkDropHostView() = default;
+ TestViewWithInkDrop() {
+ ink_drop()->SetCreateInkDropCallback(base::BindRepeating(
+ [](TestViewWithInkDrop* host) -> std::unique_ptr<InkDrop> {
+ auto ink_drop = std::make_unique<TestInkDrop>();
+ host->last_created_inkdrop_ = ink_drop.get();
+ return ink_drop;
+ },
+ this));
+ ink_drop()->SetBaseColor(gfx::kPlaceholderColor);
+ }
- // Accessors to InkDropHostView internals.
- ui::EventHandler* GetTargetHandler() { return target_handler(); }
+ TestViewWithInkDrop(const TestViewWithInkDrop&) = delete;
+ TestViewWithInkDrop& operator=(const TestViewWithInkDrop&) = delete;
- int on_ink_drop_created_count() const { return on_ink_drop_created_count_; }
+ // Expose EventTarget::target_handler() for testing.
+ ui::EventHandler* GetTargetHandler() { return target_handler(); }
TestInkDrop* last_created_inkdrop() const { return last_created_inkdrop_; }
- protected:
- SkColor GetInkDropBaseColor() const override {
- return gfx::kPlaceholderColor;
- }
-
- // InkDropHostView:
- void OnInkDropCreated() override { ++on_ink_drop_created_count_; }
-
- std::unique_ptr<InkDrop> CreateInkDrop() override {
- last_created_inkdrop_ = new TestInkDrop();
- return base::WrapUnique(last_created_inkdrop_);
- }
+ InkDropHost* ink_drop() { return &ink_drop_; }
private:
- int on_ink_drop_created_count_ = 0;
- TestInkDrop* last_created_inkdrop_ = nullptr;
+ InkDropHost ink_drop_{this};
- DISALLOW_COPY_AND_ASSIGN(TestInkDropHostView);
+ TestInkDrop* last_created_inkdrop_ = nullptr;
};
class InkDropHostViewTest : public testing::Test {
public:
InkDropHostViewTest();
+ InkDropHostViewTest(const InkDropHostViewTest&) = delete;
+ InkDropHostViewTest& operator=(const InkDropHostViewTest&) = delete;
~InkDropHostViewTest() override;
protected:
// Test target.
- TestInkDropHostView host_view_;
+ TestViewWithInkDrop host_view_;
// Provides internal access to |host_view_| test target.
- InkDropHostViewTestApi test_api_;
+ InkDropHostTestApi test_api_;
std::unique_ptr<base::AutoReset<gfx::Animation::RichAnimationRenderMode>>
animation_mode_reset_;
void MouseEventTriggersInkDropHelper(InkDropMode ink_drop_mode);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(InkDropHostViewTest);
};
InkDropHostViewTest::InkDropHostViewTest()
- : test_api_(&host_view_),
+ : test_api_(host_view_.ink_drop()),
animation_mode_reset_(gfx::AnimationTestApi::SetRichAnimationRenderMode(
gfx::Animation::RichAnimationRenderMode::FORCE_DISABLED)) {}
@@ -95,9 +93,10 @@ void InkDropHostViewTest::MouseEventTriggersInkDropHelper(
test_api_.SetInkDropMode(ink_drop_mode);
host_view_.SetEnabled(true);
- // Call GetInkDrop() to make sure the test CreateInkDrop() is created.
+ // Call ink_drop()->GetInkDrop() to make sure the test CreateInkDrop() is
+ // created.
test_api_.GetInkDrop();
- if (ink_drop_mode != InkDropMode::OFF)
+ if (ink_drop_mode != views::InkDropHost::InkDropMode::OFF)
EXPECT_FALSE(host_view_.last_created_inkdrop()->is_hovered());
else
EXPECT_EQ(host_view_.last_created_inkdrop(), nullptr);
@@ -108,7 +107,7 @@ void InkDropHostViewTest::MouseEventTriggersInkDropHelper(
host_view_.GetTargetHandler()->OnEvent(&mouse_event);
- if (ink_drop_mode != InkDropMode::OFF)
+ if (ink_drop_mode != views::InkDropHost::InkDropMode::OFF)
EXPECT_TRUE(host_view_.last_created_inkdrop()->is_hovered());
else
EXPECT_EQ(host_view_.last_created_inkdrop(), nullptr);
@@ -118,8 +117,9 @@ void InkDropHostViewTest::MouseEventTriggersInkDropHelper(
// Event.
TEST_F(InkDropHostViewTest, GetInkDropCenterBasedOnLastEventForNullEvent) {
host_view_.SetSize(gfx::Size(20, 20));
- test_api_.AnimateInkDrop(InkDropState::ACTION_PENDING, nullptr);
- EXPECT_EQ(gfx::Point(10, 10), test_api_.GetInkDropCenterBasedOnLastEvent());
+ test_api_.AnimateToState(InkDropState::ACTION_PENDING, nullptr);
+ EXPECT_EQ(gfx::Point(10, 10),
+ host_view_.ink_drop()->GetInkDropCenterBasedOnLastEvent());
}
// Verifies the return value of GetInkDropCenterBasedOnLastEvent() for a located
@@ -131,8 +131,9 @@ TEST_F(InkDropHostViewTest, GetInkDropCenterBasedOnLastEventForLocatedEvent) {
gfx::Point(5, 6), ui::EventTimeForNow(),
ui::EF_LEFT_MOUSE_BUTTON, 0);
- test_api_.AnimateInkDrop(InkDropState::ACTION_PENDING, &located_event);
- EXPECT_EQ(gfx::Point(5, 6), test_api_.GetInkDropCenterBasedOnLastEvent());
+ test_api_.AnimateToState(InkDropState::ACTION_PENDING, &located_event);
+ EXPECT_EQ(gfx::Point(5, 6),
+ host_view_.ink_drop()->GetInkDropCenterBasedOnLastEvent());
}
TEST_F(InkDropHostViewTest, HasInkDrop) {
@@ -141,49 +142,33 @@ TEST_F(InkDropHostViewTest, HasInkDrop) {
test_api_.GetInkDrop();
EXPECT_TRUE(test_api_.HasInkDrop());
- test_api_.SetInkDropMode(InkDropMode::OFF);
+ test_api_.SetInkDropMode(views::InkDropHost::InkDropMode::OFF);
EXPECT_FALSE(test_api_.HasInkDrop());
}
-TEST_F(InkDropHostViewTest, OnInkDropCreatedOnlyNotfiedOnCreation) {
- EXPECT_EQ(0, host_view_.on_ink_drop_created_count());
-
- test_api_.GetInkDrop();
- EXPECT_EQ(1, host_view_.on_ink_drop_created_count());
-
- test_api_.GetInkDrop();
- EXPECT_EQ(1, host_view_.on_ink_drop_created_count());
-
- test_api_.SetInkDropMode(InkDropMode::OFF);
- test_api_.SetInkDropMode(InkDropMode::ON);
- EXPECT_EQ(1, host_view_.on_ink_drop_created_count());
-
- test_api_.GetInkDrop();
- EXPECT_EQ(2, host_view_.on_ink_drop_created_count());
-}
-
// Verifies that mouse events trigger ink drops when ink drop mode is ON.
TEST_F(InkDropHostViewTest, MouseEventsTriggerInkDropsWhenInkDropIsOn) {
- MouseEventTriggersInkDropHelper(InkDropMode::ON);
+ MouseEventTriggersInkDropHelper(views::InkDropHost::InkDropMode::ON);
}
// Verifies that mouse events trigger ink drops when ink drop mode is
// ON_NO_GESTURE_HANDLER.
TEST_F(InkDropHostViewTest,
MouseEventsTriggerInkDropsWhenInkDropIsOnNoGestureHandler) {
- MouseEventTriggersInkDropHelper(InkDropMode::ON_NO_GESTURE_HANDLER);
+ MouseEventTriggersInkDropHelper(
+ views::InkDropHost::InkDropMode::ON_NO_GESTURE_HANDLER);
}
// Verifies that mouse events do not trigger ink drops when ink drop mode is
// OFF.
TEST_F(InkDropHostViewTest, MouseEventsDontTriggerInkDropsWhenInkDropIsOff) {
- MouseEventTriggersInkDropHelper(InkDropMode::OFF);
+ MouseEventTriggersInkDropHelper(views::InkDropHost::InkDropMode::OFF);
}
// Verifies that ink drops are not shown when the host is disabled.
TEST_F(InkDropHostViewTest,
GestureEventsDontTriggerInkDropsWhenHostIsDisabled) {
- test_api_.SetInkDropMode(InkDropMode::ON);
+ test_api_.SetInkDropMode(views::InkDropHost::InkDropMode::ON);
host_view_.SetEnabled(false);
ui::GestureEvent gesture_event(
@@ -201,7 +186,8 @@ TEST_F(InkDropHostViewTest,
TEST_F(InkDropHostViewTest,
GestureEventsDontTriggerInkDropsWhenInkDropModeIsNotOn) {
for (auto ink_drop_mode :
- {InkDropMode::ON_NO_GESTURE_HANDLER, InkDropMode::OFF}) {
+ {views::InkDropHost::InkDropMode::ON_NO_GESTURE_HANDLER,
+ views::InkDropHost::InkDropMode::OFF}) {
test_api_.SetInkDropMode(ink_drop_mode);
ui::GestureEvent gesture_event(
0.f, 0.f, 0, ui::EventTimeForNow(),
@@ -218,7 +204,8 @@ TEST_F(InkDropHostViewTest,
TEST_F(InkDropHostViewTest, NoInkDropOnTouchOrGestureEvents) {
host_view_.SetSize(gfx::Size(20, 20));
- test_api_.SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER);
+ test_api_.SetInkDropMode(
+ views::InkDropHost::InkDropMode::ON_NO_GESTURE_HANDLER);
// Ensure the target ink drop is in the expected state.
EXPECT_EQ(test_api_.GetInkDrop()->GetTargetInkDropState(),
@@ -228,11 +215,11 @@ TEST_F(InkDropHostViewTest, NoInkDropOnTouchOrGestureEvents) {
ui::ET_TOUCH_PRESSED, gfx::Point(5, 6), ui::EventTimeForNow(),
ui::PointerDetails(ui::EventPointerType::kTouch, 1));
- test_api_.AnimateInkDrop(InkDropState::ACTION_PENDING, &touch_event);
+ test_api_.AnimateToState(InkDropState::ACTION_PENDING, &touch_event);
EXPECT_EQ(test_api_.GetInkDrop()->GetTargetInkDropState(),
InkDropState::HIDDEN);
- test_api_.AnimateInkDrop(InkDropState::ALTERNATE_ACTION_PENDING,
+ test_api_.AnimateToState(InkDropState::ALTERNATE_ACTION_PENDING,
&touch_event);
EXPECT_EQ(test_api_.GetInkDrop()->GetTargetInkDropState(),
InkDropState::HIDDEN);
@@ -240,11 +227,11 @@ TEST_F(InkDropHostViewTest, NoInkDropOnTouchOrGestureEvents) {
ui::GestureEvent gesture_event(5.0f, 6.0f, 0, ui::EventTimeForNow(),
ui::GestureEventDetails(ui::ET_GESTURE_TAP));
- test_api_.AnimateInkDrop(InkDropState::ACTION_PENDING, &gesture_event);
+ test_api_.AnimateToState(InkDropState::ACTION_PENDING, &gesture_event);
EXPECT_EQ(test_api_.GetInkDrop()->GetTargetInkDropState(),
InkDropState::HIDDEN);
- test_api_.AnimateInkDrop(InkDropState::ALTERNATE_ACTION_PENDING,
+ test_api_.AnimateToState(InkDropState::ALTERNATE_ACTION_PENDING,
&gesture_event);
EXPECT_EQ(test_api_.GetInkDrop()->GetTargetInkDropState(),
InkDropState::HIDDEN);
@@ -258,7 +245,8 @@ TEST_F(InkDropHostViewTest, DismissInkDropOnTouchOrGestureEvents) {
host_view_.SetSize(gfx::Size(20, 20));
- test_api_.SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER);
+ test_api_.SetInkDropMode(
+ views::InkDropHost::InkDropMode::ON_NO_GESTURE_HANDLER);
// Ensure the target ink drop is in the expected state.
EXPECT_EQ(test_api_.GetInkDrop()->GetTargetInkDropState(),
@@ -268,7 +256,7 @@ TEST_F(InkDropHostViewTest, DismissInkDropOnTouchOrGestureEvents) {
gfx::Point(5, 6), ui::EventTimeForNow(),
ui::EF_LEFT_MOUSE_BUTTON, 0);
- test_api_.AnimateInkDrop(InkDropState::ACTION_PENDING, &mouse_event);
+ test_api_.AnimateToState(InkDropState::ACTION_PENDING, &mouse_event);
EXPECT_EQ(test_api_.GetInkDrop()->GetTargetInkDropState(),
InkDropState::ACTION_PENDING);
@@ -276,7 +264,7 @@ TEST_F(InkDropHostViewTest, DismissInkDropOnTouchOrGestureEvents) {
ui::ET_TOUCH_PRESSED, gfx::Point(5, 6), ui::EventTimeForNow(),
ui::PointerDetails(ui::EventPointerType::kTouch, 1));
- test_api_.AnimateInkDrop(InkDropState::ACTION_TRIGGERED, &touch_event);
+ test_api_.AnimateToState(InkDropState::ACTION_TRIGGERED, &touch_event);
EXPECT_EQ(test_api_.GetInkDrop()->GetTargetInkDropState(),
InkDropState::ACTION_TRIGGERED);
}
@@ -287,41 +275,43 @@ TEST_F(InkDropHostViewTest, DismissInkDropOnTouchOrGestureEvents) {
TEST_F(InkDropHostViewTest, HighlightedChangedFired) {
bool callback_called = false;
auto subscription =
- host_view_.AddHighlightedChangedCallback(base::BindRepeating(
+ host_view_.ink_drop()->AddHighlightedChangedCallback(base::BindRepeating(
[](bool* called) { *called = true; }, &callback_called));
- host_view_.OnInkDropHighlightedChanged();
+ host_view_.ink_drop()->OnInkDropHighlightedChanged();
EXPECT_TRUE(callback_called);
}
-// A very basic InkDropHostView that only changes the GetInkDropBaseColor to
-// avoid hitting a NOTREACHED.
-class BasicTestInkDropHostView : public InkDropHostView {
+// A very basic View that hosts an InkDrop.
+class BasicTestViewWithInkDrop : public View {
public:
- BasicTestInkDropHostView() = default;
- BasicTestInkDropHostView(const BasicTestInkDropHostView&) = delete;
- BasicTestInkDropHostView& operator=(const BasicTestInkDropHostView&) = delete;
- ~BasicTestInkDropHostView() override = default;
-
- protected:
- // InkDropHostView:
- SkColor GetInkDropBaseColor() const override {
- return gfx::kPlaceholderColor;
+ BasicTestViewWithInkDrop() {
+ // Call SetBaseColor to avoid hitting a NOTREACHED() for fetching an
+ // undefined color.
+ ink_drop()->SetBaseColor(gfx::kPlaceholderColor);
}
+ BasicTestViewWithInkDrop(const BasicTestViewWithInkDrop&) = delete;
+ BasicTestViewWithInkDrop& operator=(const BasicTestViewWithInkDrop&) = delete;
+ ~BasicTestViewWithInkDrop() override = default;
+
+ InkDropHost* ink_drop() { return &ink_drop_; }
+
+ private:
+ InkDropHost ink_drop_{this};
};
// Tests the existence of layer clipping or layer masking when certain path
// generators are applied on an InkDropHostView.
class InkDropHostViewClippingTest : public testing::Test {
public:
- InkDropHostViewClippingTest() : host_view_test_api_(&host_view_) {
+ InkDropHostViewClippingTest() : host_view_test_api_(host_view_.ink_drop()) {
// Set up an InkDropHostView. Clipping is based on the size of the view, so
// make sure the size is non empty.
- host_view_test_api_.SetInkDropMode(InkDropMode::ON);
+ host_view_test_api_.SetInkDropMode(views::InkDropHost::InkDropMode::ON);
host_view_.SetSize(gfx::Size(20, 20));
// The root layer of the ink drop is created the first time GetInkDrop is
// called and then kept alive until the host view is destroyed.
- ink_drop_ = static_cast<InkDropImpl*>(host_view_.GetInkDrop());
+ ink_drop_ = static_cast<InkDropImpl*>(host_view_.ink_drop()->GetInkDrop());
ink_drop_test_api_ = std::make_unique<test::InkDropImplTestApi>(ink_drop_);
}
InkDropHostViewClippingTest(const InkDropHostViewClippingTest&) = delete;
@@ -333,10 +323,10 @@ class InkDropHostViewClippingTest : public testing::Test {
protected:
// Test target.
- BasicTestInkDropHostView host_view_;
+ BasicTestViewWithInkDrop host_view_;
// Provides internal access to |host_view_| test target.
- InkDropHostViewTestApi host_view_test_api_;
+ InkDropHostTestApi host_view_test_api_;
InkDropImpl* ink_drop_ = nullptr;
diff --git a/chromium/ui/views/animation/ink_drop_impl.cc b/chromium/ui/views/animation/ink_drop_impl.cc
index 635e1dda4de..f375837c11d 100644
--- a/chromium/ui/views/animation/ink_drop_impl.cc
+++ b/chromium/ui/views/animation/ink_drop_impl.cc
@@ -562,20 +562,15 @@ InkDropImpl::HighlightStateFactory::CreateVisibleState(
return nullptr;
}
-InkDropImpl::InkDropImpl(InkDropHostView* ink_drop_host,
- const gfx::Size& host_size)
+InkDropImpl::InkDropImpl(InkDropHost* ink_drop_host,
+ const gfx::Size& host_size,
+ AutoHighlightMode auto_highlight_mode)
: ink_drop_host_(ink_drop_host),
- root_layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)),
- root_layer_added_to_host_(false),
- show_highlight_on_hover_(true),
- show_highlight_on_focus_(false),
- is_hovered_(false),
- is_focused_(false),
- exiting_highlight_state_(false),
- destroying_(false) {
+ highlight_state_factory_(auto_highlight_mode, this),
+ root_layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)) {
root_layer_->SetBounds(gfx::Rect(host_size));
- SetAutoHighlightMode(AutoHighlightMode::NONE);
root_layer_->SetName("InkDropImpl:RootLayer");
+ SetHighlightState(highlight_state_factory_.CreateStartState());
}
InkDropImpl::~InkDropImpl() {
@@ -590,15 +585,6 @@ InkDropImpl::~InkDropImpl() {
DestroyInkDropHighlight();
}
-void InkDropImpl::SetAutoHighlightMode(AutoHighlightMode auto_highlight_mode) {
- // Exit the current state completely first in case state tear down accesses
- // the current |highlight_state_factory_| instance.
- ExitHighlightState();
- highlight_state_factory_ =
- std::make_unique<HighlightStateFactory>(auto_highlight_mode, this);
- SetHighlightState(highlight_state_factory_->CreateStartState());
-}
-
void InkDropImpl::HostSizeChanged(const gfx::Size& new_size) {
// |root_layer_| should fill the entire host because it affects the clipping
// when a mask layer is applied to it. This will not affect clipping if no
@@ -740,7 +726,7 @@ void InkDropImpl::CreateInkDropHighlight() {
// If the platform provides HC colors, we need to show them fully on hover and
// press.
- if (views::UsingPlatformHighContrastInkDrop(ink_drop_host_))
+ if (views::UsingPlatformHighContrastInkDrop(ink_drop_host_->host_view()))
highlight_->set_visible_opacity(1.0f);
highlight_->set_observer(this);
diff --git a/chromium/ui/views/animation/ink_drop_impl.h b/chromium/ui/views/animation/ink_drop_impl.h
index 971f3548adc..9ea02353613 100644
--- a/chromium/ui/views/animation/ink_drop_impl.h
+++ b/chromium/ui/views/animation/ink_drop_impl.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/animation/ink_drop.h"
@@ -22,7 +22,7 @@ class InkDropImplTestApi;
} // namespace test
class InkDropRipple;
-class InkDropHostView;
+class InkDropHost;
class InkDropHighlight;
// A functional implementation of an InkDrop.
@@ -49,22 +49,13 @@ class VIEWS_EXPORT InkDropImpl : public InkDrop,
// |ink_drop_host|. |host_size| is used to set the size of the ink drop layer.
//
// By default the highlight will be made visible while |this| is hovered but
- // not focused and the NONE AutoHighlightMode will be used.
- InkDropImpl(InkDropHostView* ink_drop_host, const gfx::Size& host_size);
+ // not focused.
+ InkDropImpl(InkDropHost* ink_drop_host,
+ const gfx::Size& host_size,
+ AutoHighlightMode auto_highlight_mode);
~InkDropImpl() override;
- // Auto highlighting is a mechanism to show/hide the highlight based on the
- // visibility of the ripple. See the documentation of the AutoHighlightMode
- // for more info on the different modes.
- //
- // This method is intended as a configuration option to be used after
- // construction. Behavior is undefined if |this| has already handled any
- // InkDrop inherited functions.
- // TODO(pbos): Move along with AutoHighlightMode to views::InkDrop so users
- // can configure inkdrops created by parent classes.
- void SetAutoHighlightMode(AutoHighlightMode auto_highlight_mode);
-
- const base::Optional<base::TimeDelta>& hover_highlight_fade_duration() const {
+ const absl::optional<base::TimeDelta>& hover_highlight_fade_duration() const {
return hover_highlight_fade_duration_;
}
@@ -156,7 +147,7 @@ class VIEWS_EXPORT InkDropImpl : public InkDrop,
private:
// Used by |this| to create the new states to transition to.
- HighlightStateFactory* state_factory_;
+ HighlightStateFactory* const state_factory_;
DISALLOW_COPY_AND_ASSIGN(HighlightState);
};
@@ -267,7 +258,11 @@ class VIEWS_EXPORT InkDropImpl : public InkDrop,
// The host of the ink drop. Used to create the ripples and highlights, and to
// add/remove the root layer to/from it.
- InkDropHostView* ink_drop_host_;
+ InkDropHost* const ink_drop_host_;
+
+ // Used by |this| to initialize the starting |highlight_state_| and by the
+ // current |highlight_state_| to create the next state.
+ HighlightStateFactory highlight_state_factory_;
// The root Layer that parents the InkDropRipple layers and the
// InkDropHighlight layers. The |root_layer_| is the one that is added and
@@ -275,46 +270,42 @@ class VIEWS_EXPORT InkDropImpl : public InkDrop,
std::unique_ptr<ui::Layer> root_layer_;
// True when the |root_layer_| has been added to the |ink_drop_host_|.
- bool root_layer_added_to_host_;
+ bool root_layer_added_to_host_ = false;
// The current InkDropHighlight. Lazily created using
// CreateInkDropHighlight();
std::unique_ptr<InkDropHighlight> highlight_;
// True denotes the highlight should be shown when |this| is hovered.
- bool show_highlight_on_hover_;
+ bool show_highlight_on_hover_ = true;
// True denotes the highlight should be shown when |this| is focused.
- bool show_highlight_on_focus_;
+ bool show_highlight_on_focus_ = false;
// Tracks the logical hovered state of |this| as manipulated by the public
// SetHovered() function.
- bool is_hovered_;
+ bool is_hovered_ = false;
// Tracks the logical focused state of |this| as manipulated by the public
// SetFocused() function.
- bool is_focused_;
+ bool is_focused_ = false;
// The current InkDropRipple. Created on demand using CreateInkDropRipple().
std::unique_ptr<InkDropRipple> ink_drop_ripple_;
- // Used by |this| to initialize the starting |highlight_state_| and by the
- // current |highlight_state_| to create the next state.
- std::unique_ptr<HighlightStateFactory> highlight_state_factory_;
-
// The current state object that handles all inputs that affect the visibility
// of the |highlight_|.
std::unique_ptr<HighlightState> highlight_state_;
// Overrides the default hover highlight fade durations when set.
- base::Optional<base::TimeDelta> hover_highlight_fade_duration_;
+ absl::optional<base::TimeDelta> hover_highlight_fade_duration_;
// Used to ensure highlight state transitions are not triggered when exiting
// the current state.
- bool exiting_highlight_state_;
+ bool exiting_highlight_state_ = false;
// Used to fail DCHECKS to catch unexpected behavior during tear down.
- bool destroying_;
+ bool destroying_ = false;
DISALLOW_COPY_AND_ASSIGN(InkDropImpl);
};
diff --git a/chromium/ui/views/animation/ink_drop_impl_unittest.cc b/chromium/ui/views/animation/ink_drop_impl_unittest.cc
index 421da867179..7cb9e19063d 100644
--- a/chromium/ui/views/animation/ink_drop_impl_unittest.cc
+++ b/chromium/ui/views/animation/ink_drop_impl_unittest.cc
@@ -6,11 +6,13 @@
#include "ui/views/animation/ink_drop_impl.h"
+#include "base/bind.h"
#include "base/macros.h"
#include "base/test/gtest_util.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/gfx/animation/animation.h"
#include "ui/gfx/animation/animation_test_api.h"
@@ -24,7 +26,8 @@ namespace views {
// NOTE: The InkDropImpl class is also tested by the InkDropFactoryTest tests.
class InkDropImplTest : public testing::Test {
public:
- InkDropImplTest();
+ explicit InkDropImplTest(InkDropImpl::AutoHighlightMode auto_highlight_mode =
+ InkDropImpl::AutoHighlightMode::NONE);
~InkDropImplTest() override;
protected:
@@ -32,7 +35,7 @@ class InkDropImplTest : public testing::Test {
const TestInkDropHost* ink_drop_host() const { return &ink_drop_host_; }
InkDropImpl* ink_drop() {
- return static_cast<InkDropImpl*>(ink_drop_host()->GetInkDrop());
+ return static_cast<InkDropImpl*>(ink_drop_host()->ink_drop()->GetInkDrop());
}
InkDropRipple* ink_drop_ripple() {
@@ -77,8 +80,10 @@ class InkDropImplTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(InkDropImplTest);
};
-InkDropImplTest::InkDropImplTest() {
- ink_drop_host()->SetInkDropMode(InkDropHostView::InkDropMode::ON);
+InkDropImplTest::InkDropImplTest(
+ InkDropImpl::AutoHighlightMode auto_highlight_mode)
+ : ink_drop_host_(auto_highlight_mode) {
+ ink_drop_host()->ink_drop()->SetMode(views::InkDropHost::InkDropMode::ON);
test_api_ = std::make_unique<test::InkDropImplTestApi>(ink_drop());
ink_drop_host()->set_disable_timers_for_test(true);
}
@@ -96,7 +101,7 @@ bool InkDropImplTest::AreLayersAddedToHost() const {
void InkDropImplTest::DestroyInkDrop() {
test_api_.reset();
- ink_drop_host()->SetInkDropMode(InkDropHostView::InkDropMode::OFF);
+ ink_drop_host()->ink_drop()->SetMode(views::InkDropHost::InkDropMode::OFF);
}
// AutoHighlightMode parameterized test fixture.
@@ -108,24 +113,15 @@ class InkDropImplAutoHighlightTest
InkDropImplAutoHighlightTest();
~InkDropImplAutoHighlightTest() override;
- InkDropImpl::AutoHighlightMode GetAutoHighlightMode() const;
-
private:
DISALLOW_COPY_AND_ASSIGN(InkDropImplAutoHighlightTest);
};
InkDropImplAutoHighlightTest::InkDropImplAutoHighlightTest()
- : InkDropImplTest() {
- ink_drop()->SetAutoHighlightMode(GetAutoHighlightMode());
-}
+ : InkDropImplTest(testing::get<0>(GetParam())) {}
InkDropImplAutoHighlightTest::~InkDropImplAutoHighlightTest() = default;
-InkDropImpl::AutoHighlightMode
-InkDropImplAutoHighlightTest::GetAutoHighlightMode() const {
- return testing::get<0>(GetParam());
-}
-
////////////////////////////////////////////////////////////////////////////////
//
// InkDropImpl tests
@@ -315,18 +311,19 @@ TEST_F(InkDropImplTest, RippleAndHighlightRecreatedOnSizeChange) {
TEST_F(InkDropImplTest, HostTracksHighlightState) {
bool callback_called = false;
auto subscription =
- ink_drop_host()->AddHighlightedChangedCallback(base::BindRepeating(
- [](bool* called) { *called = true; }, &callback_called));
- EXPECT_FALSE(ink_drop_host()->GetHighlighted());
+ ink_drop_host()->ink_drop()->AddHighlightedChangedCallback(
+ base::BindRepeating([](bool* called) { *called = true; },
+ &callback_called));
+ EXPECT_FALSE(ink_drop_host()->ink_drop()->GetHighlighted());
test_api()->SetShouldHighlight(true);
EXPECT_TRUE(callback_called);
- EXPECT_TRUE(ink_drop_host()->GetHighlighted());
+ EXPECT_TRUE(ink_drop_host()->ink_drop()->GetHighlighted());
callback_called = false;
test_api()->SetShouldHighlight(false);
EXPECT_TRUE(callback_called);
- EXPECT_FALSE(ink_drop_host()->GetHighlighted());
+ EXPECT_FALSE(ink_drop_host()->ink_drop()->GetHighlighted());
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/ui/views/animation/ink_drop_observer.h b/chromium/ui/views/animation/ink_drop_observer.h
index 5eb51cfa6f4..b91833df598 100644
--- a/chromium/ui/views/animation/ink_drop_observer.h
+++ b/chromium/ui/views/animation/ink_drop_observer.h
@@ -5,7 +5,6 @@
#ifndef UI_VIEWS_ANIMATION_INK_DROP_OBSERVER_H_
#define UI_VIEWS_ANIMATION_INK_DROP_OBSERVER_H_
-#include <string>
#include "base/macros.h"
#include "ui/views/animation/ink_drop_state.h"
diff --git a/chromium/ui/views/animation/ink_drop_ripple_observer.h b/chromium/ui/views/animation/ink_drop_ripple_observer.h
index b294b3ae95c..fc534e5f387 100644
--- a/chromium/ui/views/animation/ink_drop_ripple_observer.h
+++ b/chromium/ui/views/animation/ink_drop_ripple_observer.h
@@ -5,7 +5,6 @@
#ifndef UI_VIEWS_ANIMATION_INK_DROP_RIPPLE_OBSERVER_H_
#define UI_VIEWS_ANIMATION_INK_DROP_RIPPLE_OBSERVER_H_
-#include <string>
#include "base/macros.h"
#include "ui/views/animation/ink_drop_animation_ended_reason.h"
diff --git a/chromium/ui/views/animation/ink_drop_unittest.cc b/chromium/ui/views/animation/ink_drop_unittest.cc
index d9cd80cd228..00fa497130a 100644
--- a/chromium/ui/views/animation/ink_drop_unittest.cc
+++ b/chromium/ui/views/animation/ink_drop_unittest.cc
@@ -56,8 +56,9 @@ InkDropTest::InkDropTest() : ink_drop_(nullptr) {
ink_drop_ = std::make_unique<InkDropStub>();
break;
case INK_DROP_IMPL:
- ink_drop_ =
- std::make_unique<InkDropImpl>(&test_ink_drop_host_, gfx::Size());
+ ink_drop_ = std::make_unique<InkDropImpl>(
+ test_ink_drop_host_.ink_drop(), gfx::Size(),
+ InkDropImpl::AutoHighlightMode::NONE);
// The Timer's used by the InkDropImpl class require a
// base::ThreadTaskRunnerHandle instance.
scoped_refptr<base::TestMockTimeTaskRunner> task_runner(
diff --git a/chromium/ui/views/animation/ink_drop_util.cc b/chromium/ui/views/animation/ink_drop_util.cc
index 51bc6a8b2a6..a3174f23ea0 100644
--- a/chromium/ui/views/animation/ink_drop_util.cc
+++ b/chromium/ui/views/animation/ink_drop_util.cc
@@ -54,9 +54,8 @@ gfx::Transform GetTransformSubpixelCorrection(const gfx::Transform& transform,
}
bool UsingPlatformHighContrastInkDrop(const View* view) {
- const ui::NativeTheme* theme = view->GetNativeTheme();
- return theme &&
- theme->GetDefaultSystemColorScheme() ==
+ return view->GetWidget() &&
+ view->GetNativeTheme()->GetDefaultSystemColorScheme() ==
ui::NativeTheme::ColorScheme::kPlatformHighContrast &&
base::FeatureList::IsEnabled(
features::kEnablePlatformHighContrastInkDrop);
diff --git a/chromium/ui/views/animation/installable_ink_drop.cc b/chromium/ui/views/animation/installable_ink_drop.cc
index dd71277ce49..6f38481f2f8 100644
--- a/chromium/ui/views/animation/installable_ink_drop.cc
+++ b/chromium/ui/views/animation/installable_ink_drop.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include <utility>
+#include "base/bind.h"
#include "base/check_op.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
@@ -82,24 +83,24 @@ InstallableInkDrop::InstallableInkDrop(View* view)
}
}
-InstallableInkDrop::InstallableInkDrop(InkDropHostView* ink_drop_host_view)
- : InstallableInkDrop(static_cast<View*>(ink_drop_host_view)) {
- // To get all events, we must override InkDropHostView's event handler.
- ink_drop_host_view->set_ink_drop_event_handler_override(&event_handler_);
- ink_drop_host_view_ = ink_drop_host_view;
+InstallableInkDrop::InstallableInkDrop(InkDropHost* ink_drop_host)
+ : InstallableInkDrop(ink_drop_host->host_view()) {
+ // To get all events, we must override InkDropHost's event handler.
+ ink_drop_host->set_ink_drop_event_handler_override(&event_handler_);
+ ink_drop_host_ = ink_drop_host;
// TODO(crbug.com/931964): When this is removed, classes relying on property
- // changed notifications from InkDropHostView for the highlighted state will
+ // changed notifications from InkDropHost for the highlighted state will
// need to register here instead.
RegisterHighlightedChangedCallback(
- base::BindRepeating(&InkDropHostView::OnInkDropHighlightedChanged,
- base::Unretained(ink_drop_host_view_)));
+ base::BindRepeating(&InkDropHost::OnInkDropHighlightedChanged,
+ base::Unretained(ink_drop_host_)));
}
InstallableInkDrop::~InstallableInkDrop() {
view_->RemoveLayerBeneathView(layer_.get());
- if (ink_drop_host_view_)
- ink_drop_host_view_->set_ink_drop_event_handler_override(nullptr);
+ if (ink_drop_host_)
+ ink_drop_host_->set_ink_drop_event_handler_override(nullptr);
if (DCHECK_IS_ON())
view_->RemoveObserver(this);
}
diff --git a/chromium/ui/views/animation/installable_ink_drop.h b/chromium/ui/views/animation/installable_ink_drop.h
index 1b91ea19e0f..512bb921bf4 100644
--- a/chromium/ui/views/animation/installable_ink_drop.h
+++ b/chromium/ui/views/animation/installable_ink_drop.h
@@ -31,7 +31,7 @@ class PaintContext;
namespace views {
-class InkDropHostView;
+class InkDropHost;
class View;
extern const VIEWS_EXPORT base::Feature kInstallableInkDropFeature;
@@ -48,11 +48,11 @@ class VIEWS_EXPORT InstallableInkDrop : public InkDrop,
// Create ink drop for |view|. Note that |view| must live longer than us.
explicit InstallableInkDrop(View* view);
- // Overload for working within the InkDropHostView hierarchy. Similar to
- // above, |ink_drop_host_view| must outlive us.
+ // Overload for working within an InkDropHost structure. Similar to above,
+ // |ink_drop_host| must outlive us.
//
// TODO(crbug.com/931964): Remove this.
- explicit InstallableInkDrop(InkDropHostView* ink_drop_host_view);
+ explicit InstallableInkDrop(InkDropHost* ink_drop_host);
InstallableInkDrop(const InstallableInkDrop&) = delete;
InstallableInkDrop(InstallableInkDrop&&) = delete;
@@ -106,9 +106,9 @@ class VIEWS_EXPORT InstallableInkDrop : public InkDrop,
// visual state.
View* const view_;
- // If we were installed on an InkDropHostView, this will be non-null. We store
+ // If we were installed on an InkDropHost, this will be non-null. We store
// this to to remove our InkDropEventHandler override.
- InkDropHostView* ink_drop_host_view_ = nullptr;
+ InkDropHost* ink_drop_host_ = nullptr;
// Contains the colors and opacities used to paint.
InstallableInkDropConfig config_;
diff --git a/chromium/ui/views/animation/installable_ink_drop_animator.h b/chromium/ui/views/animation/installable_ink_drop_animator.h
index 143dc46b685..177c9b3c4b1 100644
--- a/chromium/ui/views/animation/installable_ink_drop_animator.h
+++ b/chromium/ui/views/animation/installable_ink_drop_animator.h
@@ -6,9 +6,9 @@
#define UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_ANIMATOR_H_
#include "base/callback.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/animation/linear_animation.h"
#include "ui/gfx/animation/slide_animation.h"
diff --git a/chromium/ui/views/animation/installable_ink_drop_painter.h b/chromium/ui/views/animation/installable_ink_drop_painter.h
index 2ac1dcf0fc0..68056c66dda 100644
--- a/chromium/ui/views/animation/installable_ink_drop_painter.h
+++ b/chromium/ui/views/animation/installable_ink_drop_painter.h
@@ -5,7 +5,7 @@
#ifndef UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_PAINTER_H_
#define UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_PAINTER_H_
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/views/painter.h"
diff --git a/chromium/ui/views/animation/installable_ink_drop_unittest.cc b/chromium/ui/views/animation/installable_ink_drop_unittest.cc
index e1f0216e7d0..cf4c3a95349 100644
--- a/chromium/ui/views/animation/installable_ink_drop_unittest.cc
+++ b/chromium/ui/views/animation/installable_ink_drop_unittest.cc
@@ -10,6 +10,7 @@
#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkPath.h"
+#include "ui/compositor/layer.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/animation/ink_drop_host_view.h"
#include "ui/views/animation/ink_drop_state.h"
@@ -101,13 +102,6 @@ TEST_F(InstallableInkDropTest, HighlightStates) {
EXPECT_FALSE(ink_drop.IsHighlightFadingInOrVisible());
}
-TEST_F(InstallableInkDropTest, InstallOnHostView) {
- InkDropHostView host_view;
- InstallableInkDrop ink_drop(&host_view);
-
- EXPECT_TRUE(ink_drop.SupportsGestureEvents());
-}
-
TEST_F(InstallableInkDropTest, Paint) {
std::unique_ptr<Widget> widget = CreateTestWidget();
View* root_view = widget->SetContentsView(own_root_view());
diff --git a/chromium/ui/views/animation/scroll_animator.cc b/chromium/ui/views/animation/scroll_animator.cc
index 7f5a66f1e4f..47f3224dc51 100644
--- a/chromium/ui/views/animation/scroll_animator.cc
+++ b/chromium/ui/views/animation/scroll_animator.cc
@@ -63,6 +63,7 @@ void ScrollAnimator::Stop() {
void ScrollAnimator::AnimationEnded(const gfx::Animation* animation) {
Stop();
+ delegate_->OnFlingScrollEnded();
}
void ScrollAnimator::AnimationProgressed(const gfx::Animation* animation) {
diff --git a/chromium/ui/views/animation/scroll_animator.h b/chromium/ui/views/animation/scroll_animator.h
index f5d6c5d2639..e2c5893cf51 100644
--- a/chromium/ui/views/animation/scroll_animator.h
+++ b/chromium/ui/views/animation/scroll_animator.h
@@ -22,6 +22,9 @@ class VIEWS_EXPORT ScrollDelegate {
// Returns true if the content was actually scrolled, false otherwise.
virtual bool OnScroll(float dx, float dy) = 0;
+ // Called when the contents scrolled by the fling event ended.
+ virtual void OnFlingScrollEnded() {}
+
protected:
~ScrollDelegate() = default;
};
diff --git a/chromium/ui/views/animation/slide_out_controller_unittest.cc b/chromium/ui/views/animation/slide_out_controller_unittest.cc
index aa59421419b..473d515451f 100644
--- a/chromium/ui/views/animation/slide_out_controller_unittest.cc
+++ b/chromium/ui/views/animation/slide_out_controller_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "ui/compositor/layer.h"
#include "ui/views/animation/slide_out_controller_delegate.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/view.h"
@@ -40,10 +41,10 @@ class TestSlideOutControllerDelegate : public SlideOutControllerDelegate {
slide_started_count_ = 0;
slide_changed_count_ = 0;
slide_out_count_ = 0;
- slide_changed_last_value_ = base::nullopt;
+ slide_changed_last_value_ = absl::nullopt;
}
- base::Optional<bool> slide_changed_last_value_;
+ absl::optional<bool> slide_changed_last_value_;
int slide_started_count_ = 0;
int slide_changed_count_ = 0;
int slide_out_count_ = 0;
diff --git a/chromium/ui/views/background.cc b/chromium/ui/views/background.cc
index 3cf74b720ad..2131a57044b 100644
--- a/chromium/ui/views/background.cc
+++ b/chromium/ui/views/background.cc
@@ -99,7 +99,8 @@ class ThemedSolidBackground : public SolidBackground, public ViewObserver {
: SolidBackground(gfx::kPlaceholderColor),
color_id_(color_id) {
observation_.Observe(view);
- OnViewThemeChanged(view);
+ if (view->GetWidget())
+ OnViewThemeChanged(view);
}
~ThemedSolidBackground() override = default;
diff --git a/chromium/ui/views/border.cc b/chromium/ui/views/border.cc
index 86c96f6eb5a..12ae9361282 100644
--- a/chromium/ui/views/border.cc
+++ b/chromium/ui/views/border.cc
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "cc/paint/paint_flags.h"
+#include "ui/compositor/layer.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/insets_conversions.h"
diff --git a/chromium/ui/views/border_unittest.cc b/chromium/ui/views/border_unittest.cc
index 51504c5562e..62ce80aea1e 100644
--- a/chromium/ui/views/border_unittest.cc
+++ b/chromium/ui/views/border_unittest.cc
@@ -19,6 +19,7 @@
#include "third_party/skia/include/core/SkRefCnt.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/skia_util.h"
#include "ui/views/painter.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/view.h"
diff --git a/chromium/ui/views/bubble/bubble_border.cc b/chromium/ui/views/bubble/bubble_border.cc
index 7fb5850a438..03872cbaf0b 100644
--- a/chromium/ui/views/bubble/bubble_border.cc
+++ b/chromium/ui/views/bubble/bubble_border.cc
@@ -22,6 +22,7 @@
#include "ui/gfx/scoped_canvas.h"
#include "ui/gfx/shadow_value.h"
#include "ui/gfx/skia_paint_util.h"
+#include "ui/gfx/skia_util.h"
#include "ui/resources/grit/ui_resources.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/painter.h"
@@ -54,6 +55,40 @@ gfx::Point RightCenter(const gfx::Rect& rect) {
return gfx::Point(rect.right(), rect.CenterPoint().y());
}
+SkColor GetKeyShadowColor(int elevation, const ui::NativeTheme* theme) {
+ switch (elevation) {
+ case 3: {
+ return theme->GetSystemColor(
+ ui::NativeTheme::kColorId_ShadowValueKeyShadowElevationThree);
+ }
+ case 16: {
+ return theme->GetSystemColor(
+ ui::NativeTheme::kColorId_ShadowValueKeyShadowElevationSixteen);
+ }
+ default:
+ // This surface has not been updated for Refresh. Fall back to the
+ // deprecated style.
+ return theme->GetSystemColor(ui::NativeTheme::kColorId_ShadowBase);
+ }
+}
+
+SkColor GetAmbientShadowColor(int elevation, const ui::NativeTheme* theme) {
+ switch (elevation) {
+ case 3: {
+ return theme->GetSystemColor(
+ ui::NativeTheme::kColorId_ShadowValueAmbientShadowElevationThree);
+ }
+ case 16: {
+ return theme->GetSystemColor(
+ ui::NativeTheme::kColorId_ShadowValueAmbientShadowElevationSixteen);
+ }
+ default:
+ // This surface has not been updated for Refresh. Fall back to the
+ // deprecated style.
+ return theme->GetSystemColor(ui::NativeTheme::kColorId_ShadowBase);
+ }
+}
+
} // namespace
BubbleBorder::BubbleBorder(Arrow arrow, Shadow shadow, SkColor color)
@@ -69,10 +104,10 @@ BubbleBorder::~BubbleBorder() = default;
// static
gfx::Insets BubbleBorder::GetBorderAndShadowInsets(
- base::Optional<int> elevation) {
+ absl::optional<int> elevation) {
// Borders with custom shadow elevations do not draw the 1px border.
if (elevation.has_value())
- return -gfx::ShadowValue::GetMargin(GetShadowValues(elevation));
+ return -gfx::ShadowValue::GetMargin(GetShadowValues(nullptr, elevation));
constexpr gfx::Insets blur(kShadowBlur + kBorderThicknessDip);
constexpr gfx::Insets offset(-kShadowVerticalOffset, 0, kShadowVerticalOffset,
@@ -217,7 +252,7 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) {
true /*doAntiAlias*/);
DrawBorderAndShadow(std::move(r_rect), &cc::PaintCanvas::drawRRect, canvas,
- md_shadow_elevation_, md_shadow_color_);
+ view.GetNativeTheme(), md_shadow_elevation_);
}
gfx::Insets BubbleBorder::GetInsets() const {
@@ -236,8 +271,16 @@ gfx::Size BubbleBorder::GetMinimumSize() const {
// static
const gfx::ShadowValues& BubbleBorder::GetShadowValues(
- base::Optional<int> elevation,
- SkColor color) {
+ const ui::NativeTheme* theme,
+ absl::optional<int> elevation) {
+ // If the theme does not exist the shadow values are being created in
+ // order to calculate Insets. In that case the color plays no role so always
+ // set those colors to gfx::kPlaceholderColor.
+
+ SkColor color =
+ theme ? theme->GetSystemColor(ui::NativeTheme::kColorId_ShadowBase)
+ : gfx::kPlaceholderColor;
+
// The shadows are always the same for any elevation and color combination, so
// construct them once and cache.
static base::NoDestructor<std::map<ShadowCacheKey, gfx::ShadowValues>>
@@ -250,12 +293,25 @@ const gfx::ShadowValues& BubbleBorder::GetShadowValues(
gfx::ShadowValues shadows;
if (elevation.has_value()) {
DCHECK_GE(elevation.value(), 0);
- shadows = LayoutProvider::Get()->MakeShadowValues(elevation.value(), color);
+ SkColor key_shadow_color = theme
+ ? GetKeyShadowColor(elevation.value(), theme)
+ : gfx::kPlaceholderColor;
+ SkColor ambient_shadow_color =
+ theme ? GetAmbientShadowColor(elevation.value(), theme)
+ : gfx::kPlaceholderColor;
+ shadows = gfx::ShadowValue::MakeShadowValues(
+ elevation.value(), key_shadow_color, ambient_shadow_color);
} else {
constexpr int kSmallShadowVerticalOffset = 2;
constexpr int kSmallShadowBlur = 4;
- SkColor kSmallShadowColor = SkColorSetA(color, 0x33);
- SkColor kLargeShadowColor = SkColorSetA(color, 0x1A);
+ SkColor kSmallShadowColor =
+ theme ? theme->GetSystemColor(
+ ui::NativeTheme::kColorId_BubbleBorderShadowSmall)
+ : gfx::kPlaceholderColor;
+ SkColor kLargeShadowColor =
+ theme ? theme->GetSystemColor(
+ ui::NativeTheme::kColorId_BubbleBorderShadowLarge)
+ : gfx::kPlaceholderColor;
// gfx::ShadowValue counts blur pixels both inside and outside the shape,
// whereas these blur values only describe the outside portion, hence they
// must be doubled.
@@ -273,23 +329,24 @@ const gfx::ShadowValues& BubbleBorder::GetShadowValues(
// static
const cc::PaintFlags& BubbleBorder::GetBorderAndShadowFlags(
- base::Optional<int> elevation,
- SkColor color) {
+ const ui::NativeTheme* theme,
+ absl::optional<int> elevation) {
// The flags are always the same for any elevation and color combination, so
// construct them once and cache.
static base::NoDestructor<std::map<ShadowCacheKey, cc::PaintFlags>> flag_map;
- ShadowCacheKey key(elevation.value_or(-1), color);
+ ShadowCacheKey key(
+ elevation.value_or(-1),
+ theme->GetSystemColor(ui::NativeTheme::kColorId_ShadowBase));
if (flag_map->find(key) != flag_map->end())
return flag_map->find(key)->second;
cc::PaintFlags flags;
- constexpr SkColor kBlurredBorderColor = SkColorSetA(SK_ColorBLACK, 0x26);
- flags.setColor(kBlurredBorderColor);
+ flags.setColor(theme->GetSystemColor(
+ ui::NativeTheme::kColorId_BubbleBorderWhenShadowPresent));
flags.setAntiAlias(true);
flags.setLooper(
- gfx::CreateShadowDrawLooper(GetShadowValues(elevation, color)));
-
+ gfx::CreateShadowDrawLooper(GetShadowValues(theme, elevation)));
flag_map->insert({key, flags});
return flag_map->find(key)->second;
}
diff --git a/chromium/ui/views/bubble/bubble_border.h b/chromium/ui/views/bubble/bubble_border.h
index 6622b5b978c..8330fcb9464 100644
--- a/chromium/ui/views/bubble/bubble_border.h
+++ b/chromium/ui/views/bubble/bubble_border.h
@@ -5,7 +5,6 @@
#ifndef UI_VIEWS_BUBBLE_BUBBLE_BORDER_H_
#define UI_VIEWS_BUBBLE_BUBBLE_BORDER_H_
-#include <memory>
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
@@ -69,7 +68,7 @@ class VIEWS_EXPORT BubbleBorder : public Border {
NO_SHADOW,
SHADOW_COUNT,
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// On Mac, the native window server should provide its own shadow for
// windows that could overlap the browser window.
DIALOG_SHADOW = NO_SHADOW,
@@ -124,18 +123,19 @@ class VIEWS_EXPORT BubbleBorder : public Border {
// |shadow_elevation|. This is only used for MD bubbles. A null
// |shadow_elevation| will yield the default BubbleBorder MD insets.
static gfx::Insets GetBorderAndShadowInsets(
- base::Optional<int> shadow_elevation = base::nullopt);
+ absl::optional<int> shadow_elevation = absl::nullopt);
// Draws a border and shadow based on |shadow_elevation| outside the |rect| on
// |canvas|, using |draw| as the draw function. Templated so as to accept
- // either SkRect or SkRRect.
+ // either SkRect or SkRRect. |theme| is passed into GetBorderAndShadowFlags to
+ // obtain the shadow color.
template <typename T>
static void DrawBorderAndShadow(
T rect,
void (cc::PaintCanvas::*draw)(const T&, const cc::PaintFlags&),
gfx::Canvas* canvas,
- base::Optional<int> shadow_elevation = base::nullopt,
- SkColor shadow_base_color = SK_ColorBLACK) {
+ const ui::NativeTheme* theme,
+ absl::optional<int> shadow_elevation = absl::nullopt) {
// Borders with custom shadow elevations do not draw the 1px border.
if (!shadow_elevation.has_value()) {
// Provide a 1 px border outside the bounds.
@@ -146,7 +146,7 @@ class VIEWS_EXPORT BubbleBorder : public Border {
}
(canvas->sk_canvas()->*draw)(
- rect, GetBorderAndShadowFlags(shadow_elevation, shadow_base_color));
+ rect, GetBorderAndShadowFlags(theme, shadow_elevation));
}
// Set the corner radius, enables Material Design.
@@ -184,11 +184,6 @@ class VIEWS_EXPORT BubbleBorder : public Border {
md_shadow_elevation_ = shadow_elevation;
}
- // Sets the shadow color for MD shadows. Defaults to SK_ColorBLACK.
- void set_md_shadow_color(SkColor shadow_color) {
- md_shadow_color_ = shadow_color;
- }
-
// Set a flag to avoid the bubble's shadow overlapping the anchor.
void set_avoid_shadow_overlap(bool value) { avoid_shadow_overlap_ = value; }
@@ -216,17 +211,21 @@ class VIEWS_EXPORT BubbleBorder : public Border {
// Returns the shadows based on |shadow_elevation| to use for painting the
// border and shadow, and for getting insets. This is only used for MD
// bubbles. A null |shadow_elevation| will yield the default BubbleBorder MD
- // ShadowValues.
+ // ShadowValues. Gets the shadow colors from |theme|. |theme| may be null in
+ // the case where GetShadowValues is called from
+ // BubbleBorder::GetBorderAndShadowInsets which only uses the ShadowValue to
+ // calculate the insets.
static const gfx::ShadowValues& GetShadowValues(
- base::Optional<int> shadow_elevation = base::nullopt,
- SkColor shadow_base_color = SK_ColorBLACK);
+ const ui::NativeTheme* theme,
+ absl::optional<int> shadow_elevation = absl::nullopt);
// Returns the paint flags to use for painting the border and shadow based on
// |shadow_elevation|. This is only used for MD bubbles. A null
// |shadow_elevation| will yield the default BubbleBorder MD PaintFlags.
+ // Gets the shadow colors from |theme|.
static const cc::PaintFlags& GetBorderAndShadowFlags(
- base::Optional<int> shadow_elevation = base::nullopt,
- SkColor shadow_base_color = SK_ColorBLACK);
+ const ui::NativeTheme* theme,
+ absl::optional<int> shadow_elevation = absl::nullopt);
// The border and arrow stroke size used in image assets, in pixels.
static constexpr int kStroke = 1;
@@ -254,13 +253,11 @@ class VIEWS_EXPORT BubbleBorder : public Border {
Shadow shadow_;
// Elevation for the MD shadow.
- base::Optional<int> md_shadow_elevation_;
- // Color for the MD shadow.
- SkColor md_shadow_color_ = SK_ColorBLACK;
+ absl::optional<int> md_shadow_elevation_;
SkColor background_color_;
bool use_theme_background_color_;
bool avoid_shadow_overlap_ = false;
- base::Optional<gfx::Insets> insets_;
+ absl::optional<gfx::Insets> insets_;
DISALLOW_COPY_AND_ASSIGN(BubbleBorder);
};
diff --git a/chromium/ui/views/bubble/bubble_dialog_delegate_view.cc b/chromium/ui/views/bubble/bubble_dialog_delegate_view.cc
index 25e492a5c66..469bdc918b1 100644
--- a/chromium/ui/views/bubble/bubble_dialog_delegate_view.cc
+++ b/chromium/ui/views/bubble/bubble_dialog_delegate_view.cc
@@ -14,7 +14,9 @@
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_role_properties.h"
#include "ui/base/default_style.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_element.h"
#include "ui/display/screen.h"
#include "ui/gfx/color_utils.h"
@@ -25,7 +27,6 @@
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/layout/layout_manager.h"
#include "ui/views/layout/layout_provider.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/view_class_properties.h"
#include "ui/views/widget/widget.h"
@@ -35,7 +36,7 @@
#include "ui/base/win/shell.h"
#endif
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#include "ui/views/widget/widget_utils_mac.h"
#else
#include "ui/aura/window.h"
@@ -72,6 +73,14 @@ class BubbleWidget : public Widget {
return bubble_delegate->anchor_widget()->GetThemeProvider();
}
+ Widget* GetPrimaryWindowWidget() override {
+ BubbleDialogDelegateView* const bubble_delegate =
+ static_cast<BubbleDialogDelegateView*>(widget_delegate());
+ if (!bubble_delegate || !bubble_delegate->anchor_widget())
+ return Widget::GetPrimaryWindowWidget();
+ return bubble_delegate->anchor_widget()->GetPrimaryWindowWidget();
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(BubbleWidget);
};
@@ -102,6 +111,7 @@ bool CustomShadowsSupported() {
// Create a widget to host the bubble.
Widget* CreateBubbleWidget(BubbleDialogDelegate* bubble) {
+ DCHECK(bubble->owned_by_widget());
Widget* bubble_widget = new BubbleWidget();
Widget::InitParams bubble_params(Widget::InitParams::TYPE_BUBBLE);
bubble_params.delegate = bubble;
@@ -119,22 +129,24 @@ Widget* CreateBubbleWidget(BubbleDialogDelegate* bubble) {
bubble_params.shadow_type = Widget::InitParams::ShadowType::kNone;
else
bubble_params.shadow_type = Widget::InitParams::ShadowType::kDrop;
- if (bubble->parent_window()) {
- bubble_params.parent = bubble->parent_window();
- } else if (bubble->anchor_widget()) {
- bubble_params.parent = bubble->anchor_widget()->GetNativeView();
+ if (bubble->has_parent()) {
+ if (bubble->parent_window()) {
+ bubble_params.parent = bubble->parent_window();
+ } else if (bubble->anchor_widget()) {
+ bubble_params.parent = bubble->anchor_widget()->GetNativeView();
+ }
}
bubble_params.activatable = bubble->CanActivate()
- ? Widget::InitParams::ACTIVATABLE_YES
- : Widget::InitParams::ACTIVATABLE_NO;
+ ? Widget::InitParams::Activatable::kYes
+ : Widget::InitParams::Activatable::kNo;
bubble->OnBeforeBubbleWidgetInit(&bubble_params, bubble_widget);
- DCHECK(bubble_params.parent);
+ DCHECK(bubble_params.parent || !bubble->has_parent());
bubble_widget->Init(std::move(bubble_params));
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// On Mac, having a parent window creates a permanent stacking order, so
// there's no need to do this. Also, calling StackAbove() on Mac shows the
// bubble implicitly, for which the bubble is currently not ready.
- if (bubble_params.parent)
+ if (bubble->has_parent() && bubble_params.parent)
bubble_widget->StackAbove(bubble_params.parent);
#endif
return bubble_widget;
@@ -182,7 +194,7 @@ class BubbleDialogDelegate::AnchorViewObserver : public ViewObserver {
// This class is responsible for observing events on a BubbleDialogDelegate's
// anchor widget and notifying the BubbleDialogDelegate of them.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
class BubbleDialogDelegate::AnchorWidgetObserver : public WidgetObserver {
#else
class BubbleDialogDelegate::AnchorWidgetObserver : public WidgetObserver,
@@ -193,7 +205,7 @@ class BubbleDialogDelegate::AnchorWidgetObserver : public WidgetObserver,
AnchorWidgetObserver(BubbleDialogDelegate* owner, Widget* widget)
: owner_(owner) {
widget_observation_.Observe(widget);
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
window_observation_.Observe(widget->GetNativeWindow());
#endif
}
@@ -201,7 +213,7 @@ class BubbleDialogDelegate::AnchorWidgetObserver : public WidgetObserver,
// WidgetObserver:
void OnWidgetDestroying(Widget* widget) override {
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
DCHECK(window_observation_.IsObservingSource(widget->GetNativeWindow()));
window_observation_.Reset();
#endif
@@ -219,7 +231,7 @@ class BubbleDialogDelegate::AnchorWidgetObserver : public WidgetObserver,
owner_->OnAnchorBoundsChanged();
}
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// aura::WindowObserver:
void OnWindowTransformed(aura::Window* window,
ui::PropertyChangeReason reason) override {
@@ -239,7 +251,7 @@ class BubbleDialogDelegate::AnchorWidgetObserver : public WidgetObserver,
BubbleDialogDelegate* owner_;
base::ScopedObservation<views::Widget, views::WidgetObserver>
widget_observation_{this};
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
base::ScopedObservation<aura::Window, aura::WindowObserver>
window_observation_{this};
#endif
@@ -301,16 +313,24 @@ class BubbleDialogDelegate::BubbleWidgetObserver : public WidgetObserver {
this};
};
-BubbleDialogDelegate::BubbleDialogDelegate() = default;
BubbleDialogDelegate::BubbleDialogDelegate(View* anchor_view,
BubbleBorder::Arrow arrow,
BubbleBorder::Shadow shadow)
- : arrow_(arrow), shadow_(shadow) {}
-BubbleDialogDelegate::~BubbleDialogDelegate() = default;
+ : arrow_(arrow), shadow_(shadow) {
+ SetAnchorView(anchor_view);
+ SetOwnedByWidget(true);
+}
+
+BubbleDialogDelegate::~BubbleDialogDelegate() {
+ SetAnchorView(nullptr);
+}
// static
Widget* BubbleDialogDelegate::CreateBubble(
- BubbleDialogDelegate* bubble_delegate) {
+ std::unique_ptr<BubbleDialogDelegate> bubble_delegate_unique) {
+ BubbleDialogDelegate* const bubble_delegate = bubble_delegate_unique.get();
+ DCHECK(bubble_delegate->owned_by_widget());
+
// On Mac, MODAL_TYPE_WINDOW is implemented using sheets, which can't be
// anchored at a specific point - they are always placed near the top center
// of the window. To avoid unpleasant surprises, disallow setting an anchor
@@ -323,7 +343,8 @@ Widget* BubbleDialogDelegate::CreateBubble(
bubble_delegate->Init();
// Get the latest anchor widget from the anchor view at bubble creation time.
bubble_delegate->SetAnchorView(bubble_delegate->GetAnchorView());
- Widget* bubble_widget = CreateBubbleWidget(bubble_delegate);
+ Widget* const bubble_widget =
+ CreateBubbleWidget(bubble_delegate_unique.release());
bubble_delegate->set_adjust_if_offscreen(
PlatformStyle::kAdjustBubbleIfOffscreen);
@@ -340,10 +361,12 @@ Widget* BubbleDialogDelegate::CreateBubble(
Widget* BubbleDialogDelegateView::CreateBubble(
std::unique_ptr<BubbleDialogDelegateView> delegate) {
- return CreateBubble(delegate.release());
+ DCHECK(delegate->owned_by_client());
+ return BubbleDialogDelegate::CreateBubble(std::move(delegate));
}
+
Widget* BubbleDialogDelegateView::CreateBubble(BubbleDialogDelegateView* view) {
- return BubbleDialogDelegate::CreateBubble(view);
+ return CreateBubble(base::WrapUnique(view));
}
BubbleDialogDelegateView::BubbleDialogDelegateView()
@@ -354,23 +377,30 @@ BubbleDialogDelegateView::BubbleDialogDelegateView(View* anchor_view,
BubbleBorder::Shadow shadow)
: BubbleDialogDelegate(anchor_view, arrow, shadow) {
set_owned_by_client();
- SetOwnedByWidget(true);
WidgetDelegate::SetShowCloseButton(false);
SetArrow(arrow);
LayoutProvider* provider = LayoutProvider::Get();
// An individual bubble should override these margins if its layout differs
// from the typical title/text/buttons.
- set_margins(provider->GetDialogInsetsForContentType(TEXT, TEXT));
+ set_margins(provider->GetDialogInsetsForContentType(
+ DialogContentType::kText, DialogContentType::kText));
set_title_margins(provider->GetInsetsMetric(INSETS_DIALOG_TITLE));
- if (anchor_view)
- SetAnchorView(anchor_view);
- UpdateColorsFromTheme();
UMA_HISTOGRAM_BOOLEAN("Dialog.BubbleDialogDelegateView.Create", true);
}
BubbleDialogDelegateView::~BubbleDialogDelegateView() {
+ // TODO(pbos): Investigate if this is actually still needed, and if so
+ // document here why that's the case. If it's due to specific client layout
+ // managers, push this down to client destructors.
SetLayoutManager(nullptr);
+ // TODO(pbos): See if we can resolve this better. This currently prevents a
+ // crash that shows up in BubbleFrameViewTest.WidthSnaps. This crash seems to
+ // happen at GetWidget()->IsVisible() inside SetAnchorView(nullptr) and seems
+ // to be as a result of WidgetDelegate's widget_ not getting updated during
+ // destruction when BubbleDialogDelegateView::DeleteDelegate() doesn't delete
+ // itself, as Widget drops a reference to widget_delegate_ and can't inform it
+ // of WidgetDeleting in ~Widget.
SetAnchorView(nullptr);
}
@@ -451,7 +481,7 @@ void BubbleDialogDelegate::OnAnchorWidgetDestroying() {
}
void BubbleDialogDelegate::OnBubbleWidgetActivationChanged(bool active) {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Install |mac_bubble_closer_| the first time the widget becomes active.
if (active && !mac_bubble_closer_) {
mac_bubble_closer_ = std::make_unique<ui::BubbleCloser>(
@@ -543,9 +573,8 @@ gfx::Rect BubbleDialogDelegate::GetAnchorRect() const {
return anchor_rect_.value_or(gfx::Rect());
anchor_rect_ = GetAnchorView()->GetAnchorBoundsInScreen();
- anchor_rect_->Inset(anchor_view_insets_);
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// GetAnchorBoundsInScreen returns values that take anchor widget's
// translation into account, so undo that here. Without this, features which
// apply transforms on windows such as ChromeOS overview mode will see bubbles
@@ -654,6 +683,9 @@ gfx::Rect BubbleDialogDelegate::GetBubbleBounds() {
}
ax::mojom::Role BubbleDialogDelegate::GetAccessibleWindowRole() {
+ if (WidgetDelegate::GetAccessibleWindowRole() == ax::mojom::Role::kNone)
+ return ax::mojom::Role::kNone;
+
// If something in the dialog has initial focus, use the dialog role.
// Screen readers understand what to announce when focus moves within one.
if (GetInitiallyFocusedView())
@@ -753,7 +785,7 @@ void BubbleDialogDelegate::SetAnchorRect(const gfx::Rect& rect) {
void BubbleDialogDelegate::SizeToContents() {
gfx::Rect bubble_bounds = GetBubbleBounds();
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// GetBubbleBounds() doesn't take the Mac NativeWindow's style mask into
// account, so we need to adjust the size.
gfx::Size actual_size =
diff --git a/chromium/ui/views/bubble/bubble_dialog_delegate_view.h b/chromium/ui/views/bubble/bubble_dialog_delegate_view.h
index 922e14c6ae2..28dffe7255b 100644
--- a/chromium/ui/views/bubble/bubble_dialog_delegate_view.h
+++ b/chromium/ui/views/bubble/bubble_dialog_delegate_view.h
@@ -12,16 +12,16 @@
#include "build/build_config.h"
#include "ui/accessibility/ax_enums.mojom-forward.h"
#include "ui/base/class_property.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/bubble/bubble_frame_view.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/view_tracker.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
#include "ui/views/window/dialog_delegate.h"
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#include "ui/base/cocoa/bubble_closer.h"
#endif
@@ -36,16 +36,10 @@ class Button;
class VIEWS_EXPORT BubbleDialogDelegate : public DialogDelegate,
public ui::PropertyHandler {
public:
- enum class CloseReason {
- DEACTIVATION,
- CLOSE_BUTTON,
- UNKNOWN,
- };
-
- BubbleDialogDelegate();
- BubbleDialogDelegate(View* anchor_view,
- BubbleBorder::Arrow arrow,
- BubbleBorder::Shadow shadow);
+ BubbleDialogDelegate(
+ View* anchor_view,
+ BubbleBorder::Arrow arrow,
+ BubbleBorder::Shadow shadow = BubbleBorder::DIALOG_SHADOW);
BubbleDialogDelegate(const BubbleDialogDelegate& other) = delete;
BubbleDialogDelegate& operator=(const BubbleDialogDelegate& other) = delete;
~BubbleDialogDelegate() override;
@@ -57,6 +51,10 @@ class VIEWS_EXPORT BubbleDialogDelegate : public DialogDelegate,
ClientView* CreateClientView(Widget* widget) override;
ax::mojom::Role GetAccessibleWindowRole() override;
+ // Create and initialize the bubble Widget with proper bounds.
+ static Widget* CreateBubble(
+ std::unique_ptr<BubbleDialogDelegate> bubble_delegate);
+
//////////////////////////////////////////////////////////////////////////////
// The anchor view and rectangle:
//
@@ -79,18 +77,9 @@ class VIEWS_EXPORT BubbleDialogDelegate : public DialogDelegate,
// TODO(ellyjones): Remove overrides of GetAnchorRect() and make this not
// virtual.
virtual gfx::Rect GetAnchorRect() const;
- const base::Optional<gfx::Rect>& anchor_rect() const { return anchor_rect_; }
+ const absl::optional<gfx::Rect>& anchor_rect() const { return anchor_rect_; }
void SetAnchorRect(const gfx::Rect& rect);
- // The anchor view insets are applied to the anchor view's bounds. This is
- // used to align the bubble properly with the visual center of the anchor View
- // when the anchor View's visual center is not the same as the center of its
- // bounding box.
- // TODO(https://crbug.com/869928): Remove this concept in favor of
- // View::GetAnchorBoundsInScreen().
- const gfx::Insets& anchor_view_insets() const { return anchor_view_insets_; }
- void set_anchor_view_insets(const gfx::Insets& i) { anchor_view_insets_ = i; }
-
//////////////////////////////////////////////////////////////////////////////
// The anchor widget:
//
@@ -178,6 +167,9 @@ class VIEWS_EXPORT BubbleDialogDelegate : public DialogDelegate,
gfx::NativeView parent_window() const { return parent_window_; }
void set_parent_window(gfx::NativeView window) { parent_window_ = window; }
+ bool has_parent() { return has_parent_; }
+ void set_has_parent(bool has_parent) { has_parent_ = has_parent; }
+
// Whether the bubble accepts mouse events or not.
bool accept_events() const { return accept_events_; }
void set_accept_events(bool accept_events) { accept_events_ = accept_events; }
@@ -244,9 +236,6 @@ class VIEWS_EXPORT BubbleDialogDelegate : public DialogDelegate,
gfx::Rect screen_rect);
protected:
- // Create and initialize the bubble Widget with proper bounds.
- static Widget* CreateBubble(BubbleDialogDelegate* bubble_delegate);
-
// Override this method if you want to position the bubble regardless of its
// anchor, while retaining the other anchor view logic.
virtual gfx::Rect GetBubbleBounds();
@@ -266,6 +255,7 @@ class VIEWS_EXPORT BubbleDialogDelegate : public DialogDelegate,
// Override this to perform initialization after the Widget is created but
// before it is shown.
+ // TODO(pbos): Turn this into a (Once?)Callback and add set_init(cb).
virtual void Init() {}
// TODO(ellyjones): Replace uses of this with uses of set_color(), and/or
@@ -337,9 +327,6 @@ class VIEWS_EXPORT BubbleDialogDelegate : public DialogDelegate,
bool focus_traversable_from_anchor_view_ = true;
ViewTracker highlighted_button_tracker_;
- // Insets applied to the |anchor_view_| bounds.
- gfx::Insets anchor_view_insets_;
-
// A flag controlling bubble closure on deactivation.
bool close_on_deactivate_ = true;
@@ -347,15 +334,18 @@ class VIEWS_EXPORT BubbleDialogDelegate : public DialogDelegate,
// provided) should be highlighted when this bubble is shown.
bool highlight_button_when_shown_ = true;
- mutable base::Optional<gfx::Rect> anchor_rect_;
+ mutable absl::optional<gfx::Rect> anchor_rect_;
bool accept_events_ = true;
gfx::NativeView parent_window_ = nullptr;
+ // By default, all BubbleDialogDelegates have parent windows.
+ bool has_parent_ = true;
+
// Pointer to this bubble's ClientView.
ClientView* client_view_ = nullptr;
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Special handler for close_on_deactivate() on Mac. Window (de)activation is
// suppressed by the WindowServer when clicking rapidly, so the bubble must
// monitor clicks as well for the desired behavior.
@@ -364,8 +354,9 @@ class VIEWS_EXPORT BubbleDialogDelegate : public DialogDelegate,
};
// BubbleDialogDelegateView is a BubbleDialogDelegate that is also a View.
-// If you can, it is better to subclass View and construct a
-// BubbleDialogDelegate instance as a member of your subclass.
+// TODO(pbos): Finish moving functionality from BubbleDialogDelegateView into
+// BubbleDialogDelegate, then document here that it's better to subclass View
+// and construct a BubbleDialogDelegate.
class VIEWS_EXPORT BubbleDialogDelegateView : public BubbleDialogDelegate,
public View {
public:
diff --git a/chromium/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc b/chromium/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc
index da5c3df3d05..31647fb653c 100644
--- a/chromium/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc
+++ b/chromium/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc
@@ -298,6 +298,21 @@ TEST_F(BubbleDialogDelegateViewTest, ResetAnchorWidget) {
EXPECT_TRUE(bubble_observer.widget_closed());
}
+TEST_F(BubbleDialogDelegateViewTest, NoParentWidget) {
+ test_views_delegate()->set_use_desktop_native_widgets(true);
+#if defined(OS_CHROMEOS)
+ test_views_delegate()->set_context(GetContext());
+#endif
+ BubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(nullptr);
+ bubble_delegate->set_has_parent(false);
+ WidgetAutoclosePtr bubble_widget(
+ BubbleDialogDelegateView::CreateBubble(std::move(bubble_delegate)));
+ EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate());
+ EXPECT_EQ(bubble_widget.get(), bubble_delegate->GetWidget());
+ EXPECT_EQ(nullptr, bubble_widget->parent());
+}
+
TEST_F(BubbleDialogDelegateViewTest, InitiallyFocusedView) {
std::unique_ptr<Widget> anchor_widget =
CreateTestWidget(Widget::InitParams::TYPE_WINDOW);
@@ -359,6 +374,17 @@ TEST_F(BubbleDialogDelegateViewTest, VisibleWhenAnchorWidgetBoundsChanged) {
EXPECT_TRUE(bubble_widget->IsVisible());
}
+TEST_F(BubbleDialogDelegateViewTest, GetPrimaryWindowWidget) {
+ std::unique_ptr<Widget> anchor_widget =
+ CreateTestWidget(Widget::InitParams::TYPE_WINDOW);
+ BubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(anchor_widget->GetContentsView());
+ Widget* bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(bubble_delegate);
+ EXPECT_EQ(anchor_widget.get(), anchor_widget->GetPrimaryWindowWidget());
+ EXPECT_EQ(anchor_widget.get(), bubble_widget->GetPrimaryWindowWidget());
+}
+
// Test that setting WidgetDelegate::SetCanActivate() to false makes the
// widget created via BubbleDialogDelegateView::CreateBubble() not activatable.
TEST_F(BubbleDialogDelegateViewTest, NotActivatable) {
@@ -452,8 +478,8 @@ TEST_F(BubbleDialogDelegateViewTest, CustomTitle) {
title_view->bounds().right());
LayoutProvider* provider = LayoutProvider::Get();
- const gfx::Insets content_margins =
- provider->GetDialogInsetsForContentType(views::TEXT, views::TEXT);
+ const gfx::Insets content_margins = provider->GetDialogInsetsForContentType(
+ views::DialogContentType::kText, views::DialogContentType::kText);
const gfx::Insets title_margins =
provider->GetInsetsMetric(INSETS_DIALOG_TITLE);
EXPECT_EQ(content_margins, bubble_delegate->margins());
@@ -539,7 +565,8 @@ TEST_F(BubbleDialogDelegateViewTest, AttachedWidgetShowsInkDropWhenVisible) {
anchor_widget->SetContentsView(std::make_unique<LabelButton>(
Button::PressedCallback(), std::u16string()));
TestInkDrop* ink_drop = new TestInkDrop();
- test::InkDropHostViewTestApi(button).SetInkDrop(base::WrapUnique(ink_drop));
+ test::InkDropHostTestApi(button->ink_drop())
+ .SetInkDrop(base::WrapUnique(ink_drop));
TestBubbleDialogDelegateView* bubble_delegate =
new TestBubbleDialogDelegateView(nullptr);
bubble_delegate->set_parent_window(anchor_widget->GetNativeView());
@@ -568,7 +595,8 @@ TEST_F(BubbleDialogDelegateViewTest, VisibleWidgetShowsInkDropOnAttaching) {
anchor_widget->SetContentsView(std::make_unique<LabelButton>(
Button::PressedCallback(), std::u16string()));
TestInkDrop* ink_drop = new TestInkDrop();
- test::InkDropHostViewTestApi(button).SetInkDrop(base::WrapUnique(ink_drop));
+ test::InkDropHostTestApi(button->ink_drop())
+ .SetInkDrop(base::WrapUnique(ink_drop));
TestBubbleDialogDelegateView* bubble_delegate =
new TestBubbleDialogDelegateView(nullptr);
bubble_delegate->set_parent_window(anchor_widget->GetNativeView());
@@ -599,13 +627,13 @@ TEST_F(BubbleDialogDelegateViewTest, VisibleAnchorChanges) {
Widget* bubble_widget =
BubbleDialogDelegateView::CreateBubble(bubble_delegate);
bubble_widget->Show();
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// All child widgets make the parent paint as active on Mac.
// See https://crbug.com/1046540
EXPECT_TRUE(anchor_widget->ShouldPaintAsActive());
#else
EXPECT_FALSE(anchor_widget->ShouldPaintAsActive());
-#endif // defined(OS_APPLE)
+#endif // defined(OS_MAC)
bubble_delegate->SetAnchorView(anchor_widget->GetContentsView());
EXPECT_TRUE(anchor_widget->ShouldPaintAsActive());
diff --git a/chromium/ui/views/bubble/bubble_dialog_model_host.cc b/chromium/ui/views/bubble/bubble_dialog_model_host.cc
index 09dd2414288..cecebb97222 100644
--- a/chromium/ui/views/bubble/bubble_dialog_model_host.cc
+++ b/chromium/ui/views/bubble/bubble_dialog_model_host.cc
@@ -9,6 +9,8 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/base/class_property.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/models/combobox_model.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/button/label_button_border.h"
@@ -21,8 +23,6 @@
#include "ui/views/layout/box_layout_view.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/layout/layout_provider.h"
-#include "ui/views/metadata/metadata_header_macros.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/view_class_properties.h"
namespace views {
@@ -31,18 +31,18 @@ namespace {
DialogContentType FieldTypeToContentType(ui::DialogModelField::Type type) {
switch (type) {
case ui::DialogModelField::kButton:
- return DialogContentType::CONTROL;
+ return DialogContentType::kControl;
case ui::DialogModelField::kBodyText:
- return DialogContentType::TEXT;
+ return DialogContentType::kText;
case ui::DialogModelField::kCheckbox:
- return DialogContentType::CONTROL;
+ return DialogContentType::kControl;
case ui::DialogModelField::kTextfield:
- return DialogContentType::CONTROL;
+ return DialogContentType::kControl;
case ui::DialogModelField::kCombobox:
- return DialogContentType::CONTROL;
+ return DialogContentType::kControl;
}
NOTREACHED();
- return DialogContentType::CONTROL;
+ return DialogContentType::kControl;
}
// A subclass of Checkbox that allows using an external Label/StyledLabel view
@@ -56,9 +56,8 @@ class CheckboxControl : public Checkbox {
: label_line_height_(label_line_height) {
auto* layout = SetLayoutManager(std::make_unique<BoxLayout>());
layout->set_between_child_spacing(LayoutProvider::Get()->GetDistanceMetric(
- views::DISTANCE_RELATED_LABEL_HORIZONTAL));
- layout->set_cross_axis_alignment(
- views::BoxLayout::CrossAxisAlignment::kStart);
+ DISTANCE_RELATED_LABEL_HORIZONTAL));
+ layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStart);
SetAssociatedLabel(label.get());
@@ -254,8 +253,8 @@ BubbleDialogModelHost::BubbleDialogModelHost(
set_close_on_deactivate(model_->close_on_deactivate(GetPassKey()));
set_fixed_width(LayoutProvider::Get()->GetDistanceMetric(
- anchor_view ? views::DISTANCE_BUBBLE_PREFERRED_WIDTH
- : views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH));
+ anchor_view ? DISTANCE_BUBBLE_PREFERRED_WIDTH
+ : DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH));
AddInitialFields();
}
@@ -284,7 +283,7 @@ View* BubbleDialogModelHost::GetInitiallyFocusedView() {
if (!model_)
return BubbleDialogDelegateView::GetInitiallyFocusedView();
- base::Optional<int> unique_id = model_->initially_focused_field(GetPassKey());
+ absl::optional<int> unique_id = model_->initially_focused_field(GetPassKey());
if (!unique_id)
return BubbleDialogDelegateView::GetInitiallyFocusedView();
@@ -363,7 +362,7 @@ void BubbleDialogModelHost::AddInitialFields() {
void BubbleDialogModelHost::UpdateSpacingAndMargins() {
const DialogContentType first_field_content_type =
children().empty()
- ? DialogContentType::CONTROL
+ ? DialogContentType::kControl
: FieldTypeToContentType(FindDialogModelHostField(children().front())
.dialog_model_field->type(GetPassKey()));
DialogContentType last_field_content_type = first_field_content_type;
@@ -378,8 +377,8 @@ void BubbleDialogModelHost::UpdateSpacingAndMargins() {
} else {
int padding_margin = LayoutProvider::Get()->GetDistanceMetric(
DISTANCE_UNRELATED_CONTROL_VERTICAL);
- if (last_field_content_type == DialogContentType::CONTROL &&
- field_content_type == DialogContentType::CONTROL) {
+ if (last_field_content_type == DialogContentType::kControl &&
+ field_content_type == DialogContentType::kControl) {
// TODO(pbos): Move DISTANCE_CONTROL_LIST_VERTICAL to
// views::LayoutProvider and replace "12" here.
padding_margin = 12;
@@ -464,17 +463,19 @@ void BubbleDialogModelHost::AddOrUpdateCombobox(
combobox->SetCallback(base::BindRepeating(
[](ui::DialogModelCombobox* model_field,
base::PassKey<DialogModelHost> pass_key, Combobox* combobox) {
- // TODO(pbos): This should be a subscription through the Combobox
- // directly, but Combobox right now doesn't support listening to
- // selected-index changes.
- model_field->OnSelectedIndexChanged(pass_key,
- combobox->GetSelectedIndex());
model_field->OnPerformAction(pass_key);
},
model_field, GetPassKey(), combobox.get()));
- // TODO(pbos): Add subscription to combobox selected-index changes.
combobox->SetSelectedIndex(model_field->selected_index());
+ property_changed_subscriptions_.push_back(
+ combobox->AddSelectedIndexChangedCallback(base::BindRepeating(
+ [](ui::DialogModelCombobox* model_field,
+ base::PassKey<DialogModelHost> pass_key, Combobox* combobox) {
+ model_field->OnSelectedIndexChanged(pass_key,
+ combobox->GetSelectedIndex());
+ },
+ model_field, GetPassKey(), combobox.get())));
const gfx::FontList& font_list = combobox->GetFontList();
AddViewForLabelAndField(model_field, model_field->label(GetPassKey()),
std::move(combobox), font_list);
@@ -493,7 +494,7 @@ void BubbleDialogModelHost::AddOrUpdateTextfield(
// If this textfield is initially focused the text should be initially
// selected as well.
- base::Optional<int> initially_focused_field_id =
+ absl::optional<int> initially_focused_field_id =
model_->initially_focused_field(GetPassKey());
if (initially_focused_field_id &&
model_field->unique_id(GetPassKey()) == initially_focused_field_id) {
diff --git a/chromium/ui/views/bubble/bubble_frame_view.cc b/chromium/ui/views/bubble/bubble_frame_view.cc
index a2380fa3ac5..a6672c5b529 100644
--- a/chromium/ui/views/bubble/bubble_frame_view.cc
+++ b/chromium/ui/views/bubble/bubble_frame_view.cc
@@ -13,7 +13,9 @@
#include "ui/base/default_style.h"
#include "ui/base/hit_test.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/paint_recorder.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
@@ -33,7 +35,6 @@
#include "ui/views/controls/image_view.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/layout_provider.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/paint_info.h"
#include "ui/views/resources/grit/views_resources.h"
#include "ui/views/view_class_properties.h"
@@ -316,7 +317,7 @@ void BubbleFrameView::SetTitleView(std::unique_ptr<View> title_view) {
AddChildViewAt(title_view.release(), GetIndexOf(title_icon_) + 1);
}
-void BubbleFrameView::SetProgress(base::Optional<double> progress) {
+void BubbleFrameView::SetProgress(absl::optional<double> progress) {
bool visible = progress.has_value();
progress_indicator_->SetVisible(visible);
progress_indicator_->GetViewAccessibility().OverrideIsIgnored(!visible);
@@ -324,10 +325,10 @@ void BubbleFrameView::SetProgress(base::Optional<double> progress) {
progress_indicator_->SetValue(progress.value());
}
-base::Optional<double> BubbleFrameView::GetProgress() const {
+absl::optional<double> BubbleFrameView::GetProgress() const {
if (progress_indicator_->GetVisible())
return progress_indicator_->GetValue();
- return base::nullopt;
+ return absl::nullopt;
}
gfx::Size BubbleFrameView::CalculatePreferredSize() const {
@@ -352,7 +353,7 @@ gfx::Size BubbleFrameView::GetMaximumSize() const {
// the OS doesn't give the user controls to resize a bubble.
return gfx::Size();
#else
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Allow BubbleFrameView dialogs to be resizable on Mac.
if (GetWidget()->widget_delegate()->CanResize()) {
gfx::Size client_size = GetWidget()->client_view()->GetMaximumSize();
@@ -360,7 +361,7 @@ gfx::Size BubbleFrameView::GetMaximumSize() const {
return client_size;
return GetWindowBoundsForClientBounds(gfx::Rect(client_size)).size();
}
-#endif // OS_APPLE
+#endif // OS_MAC
// Non-dialog bubbles should be non-resizable, so its max size is its
// preferred size.
return GetPreferredSize();
@@ -391,8 +392,20 @@ void BubbleFrameView::Layout() {
header_bottom = header_view_->bounds().bottom();
}
- if (bounds.IsEmpty())
+ // Only account for footnote_container_'s height if it's visible, because
+ // content_margins_ adds extra padding even if all child views are invisible.
+ if (footnote_container_ && footnote_container_->GetVisible()) {
+ const int width = contents_bounds.width();
+ const int height = footnote_container_->GetHeightForWidth(width);
+ footnote_container_->SetBounds(
+ contents_bounds.x(), contents_bounds.bottom() - height, width, height);
+ }
+
+ NonClientFrameView::Layout();
+
+ if (bounds.IsEmpty()) {
return;
+ }
// The buttons are positioned somewhat closer to the edge of the bubble.
const int close_margin =
@@ -442,15 +455,6 @@ void BubbleFrameView::Layout() {
title_icon_->SetBounds(bounds.x(), bounds.y(), title_icon_pref_size.width(),
title_height);
-
- // Only account for footnote_container_'s height if it's visible, because
- // content_margins_ adds extra padding even if all child views are invisible.
- if (footnote_container_ && footnote_container_->GetVisible()) {
- const int width = contents_bounds.width();
- const int height = footnote_container_->GetHeightForWidth(width);
- footnote_container_->SetBounds(
- contents_bounds.x(), contents_bounds.bottom() - height, width, height);
- }
}
void BubbleFrameView::OnThemeChanged() {
@@ -469,10 +473,8 @@ void BubbleFrameView::OnThemeChanged() {
void BubbleFrameView::ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) {
- if (details.is_add && details.child == this) {
- OnThemeChanged();
+ if (details.is_add && details.child == this)
UpdateClientLayerCornerRadius();
- }
// We need to update the client view's corner radius whenever the header or
// footer are added/removed from the bubble frame so that the client view
@@ -927,16 +929,14 @@ void BubbleFrameView::UpdateClientLayerCornerRadius() {
}
BEGIN_METADATA(BubbleFrameView, NonClientFrameView)
-ADD_PROPERTY_METADATA(base::Optional<double>, Progress)
+ADD_PROPERTY_METADATA(absl::optional<double>, Progress)
ADD_PROPERTY_METADATA(gfx::Insets, ContentMargins)
ADD_PROPERTY_METADATA(gfx::Insets, FootnoteMargins)
ADD_PROPERTY_METADATA(BubbleFrameView::PreferredArrowAdjustment,
PreferredArrowAdjustment)
ADD_PROPERTY_METADATA(int, CornerRadius)
ADD_PROPERTY_METADATA(BubbleBorder::Arrow, Arrow)
-ADD_PROPERTY_METADATA(SkColor,
- BackgroundColor,
- views::metadata::SkColorConverter)
+ADD_PROPERTY_METADATA(SkColor, BackgroundColor, ui::metadata::SkColorConverter)
END_METADATA
} // namespace views
diff --git a/chromium/ui/views/bubble/bubble_frame_view.h b/chromium/ui/views/bubble/bubble_frame_view.h
index fae2a20e1af..a2963715455 100644
--- a/chromium/ui/views/bubble/bubble_frame_view.h
+++ b/chromium/ui/views/bubble/bubble_frame_view.h
@@ -10,7 +10,7 @@
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/time/time.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/bubble/bubble_border.h"
@@ -18,7 +18,6 @@
#include "ui/views/controls/label.h"
#include "ui/views/controls/progress_bar.h"
#include "ui/views/input_event_activation_protector.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/window/non_client_view.h"
namespace gfx {
@@ -72,10 +71,10 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView {
// Updates the current progress value of |progress_indicator_|. If progress is
// absent, hides |the progress_indicator|.
- void SetProgress(base::Optional<double> progress);
+ void SetProgress(absl::optional<double> progress);
// Returns the current progress value of |progress_indicator_| if
// |progress_indicator_| is visible.
- base::Optional<double> GetProgress() const;
+ absl::optional<double> GetProgress() const;
// View:
gfx::Size CalculatePreferredSize() const override;
diff --git a/chromium/ui/views/bubble/footnote_container_view.cc b/chromium/ui/views/bubble/footnote_container_view.cc
index 4c4f2c548d6..56581edb8f7 100644
--- a/chromium/ui/views/bubble/footnote_container_view.cc
+++ b/chromium/ui/views/bubble/footnote_container_view.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "cc/paint/paint_flags.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -15,7 +16,6 @@
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/layout/box_layout.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace views {
@@ -54,10 +54,10 @@ class HalfRoundedRectBackground : public Background {
FootnoteContainerView::FootnoteContainerView(const gfx::Insets& margins,
std::unique_ptr<View> child_view,
- float corner_radius) {
+ float corner_radius)
+ : corner_radius_(corner_radius) {
SetLayoutManager(std::make_unique<BoxLayout>(
BoxLayout::Orientation::kVertical, margins, 0));
- SetCornerRadius(corner_radius);
auto* child_view_ptr = AddChildView(std::move(child_view));
SetVisible(child_view_ptr->GetVisible());
}
@@ -66,7 +66,8 @@ FootnoteContainerView::~FootnoteContainerView() = default;
void FootnoteContainerView::SetCornerRadius(float corner_radius) {
corner_radius_ = corner_radius;
- ResetBackground();
+ if (GetWidget())
+ ResetBackground();
}
void FootnoteContainerView::OnThemeChanged() {
@@ -81,6 +82,8 @@ void FootnoteContainerView::ChildVisibilityChanged(View* child) {
}
void FootnoteContainerView::ResetBackground() {
+ if (!GetWidget())
+ return;
SkColor background_color = GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_BubbleFooterBackground);
SetBackground(std::make_unique<HalfRoundedRectBackground>(background_color,
@@ -88,6 +91,8 @@ void FootnoteContainerView::ResetBackground() {
}
void FootnoteContainerView::ResetBorder() {
+ if (!GetWidget())
+ return;
SetBorder(CreateSolidSidedBorder(
1, 0, 0, 0, GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_FootnoteContainerBorder)));
diff --git a/chromium/ui/views/bubble/info_bubble.cc b/chromium/ui/views/bubble/info_bubble.cc
index 8126ba8b4b0..874d69ccc0d 100644
--- a/chromium/ui/views/bubble/info_bubble.cc
+++ b/chromium/ui/views/bubble/info_bubble.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
@@ -15,7 +16,6 @@
#include "ui/views/controls/label.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/layout/layout_provider.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/widget/widget.h"
namespace views {
diff --git a/chromium/ui/views/bubble/tooltip_icon.cc b/chromium/ui/views/bubble/tooltip_icon.cc
index a28440a4194..ad55cfa5eb3 100644
--- a/chromium/ui/views/bubble/tooltip_icon.cc
+++ b/chromium/ui/views/bubble/tooltip_icon.cc
@@ -8,10 +8,10 @@
#include "components/vector_icons/vector_icons.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/bubble/info_bubble.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/mouse_watcher_view_host.h"
namespace views {
@@ -21,9 +21,7 @@ TooltipIcon::TooltipIcon(const std::u16string& tooltip, int tooltip_icon_size)
tooltip_icon_size_(tooltip_icon_size),
mouse_inside_(false),
bubble_(nullptr),
- preferred_width_(0) {
- SetDrawAsHovered(false);
-}
+ preferred_width_(0) {}
TooltipIcon::~TooltipIcon() {
for (auto& observer : observers_)
@@ -58,6 +56,11 @@ void TooltipIcon::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->SetName(tooltip_);
}
+void TooltipIcon::OnThemeChanged() {
+ ImageView::OnThemeChanged();
+ SetDrawAsHovered(false);
+}
+
void TooltipIcon::MouseMovedOutOfHost() {
if (IsMouseHovered()) {
mouse_watcher_->Start(GetWidget()->GetNativeWindow());
diff --git a/chromium/ui/views/bubble/tooltip_icon.h b/chromium/ui/views/bubble/tooltip_icon.h
index 8d42550efe7..ccc303fda33 100644
--- a/chromium/ui/views/bubble/tooltip_icon.h
+++ b/chromium/ui/views/bubble/tooltip_icon.h
@@ -47,6 +47,7 @@ class VIEWS_EXPORT TooltipIcon : public ImageView,
bool OnMousePressed(const ui::MouseEvent& event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
+ void OnThemeChanged() override;
// MouseWatcherListener:
void MouseMovedOutOfHost() override;
diff --git a/chromium/ui/views/button_drag_utils.cc b/chromium/ui/views/button_drag_utils.cc
index 1b37b17f7a6..0731cd6b9d7 100644
--- a/chromium/ui/views/button_drag_utils.cc
+++ b/chromium/ui/views/button_drag_utils.cc
@@ -9,6 +9,7 @@
#include "ui/base/models/image_model.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/canvas_painter.h"
+#include "ui/compositor/compositor.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/vector2d.h"
diff --git a/chromium/ui/views/cocoa/drag_drop_client_mac_unittest.mm b/chromium/ui/views/cocoa/drag_drop_client_mac_unittest.mm
index 0f1881bd1fe..9966491dcd4 100644
--- a/chromium/ui/views/cocoa/drag_drop_client_mac_unittest.mm
+++ b/chromium/ui/views/cocoa/drag_drop_client_mac_unittest.mm
@@ -195,7 +195,7 @@ class DragDropClientMacTest : public WidgetTest {
widget_->Show();
target_ = new DragDropView();
- widget_->GetContentsView()->AddChildView(target_);
+ widget_->non_client_view()->frame_view()->AddChildView(target_);
target_->SetBoundsRect(bounds);
drag_drop_client()->source_operation_ = ui::DragDropTypes::DRAG_COPY;
@@ -329,7 +329,7 @@ TEST_F(DragDropClientMacTest, CloseWidgetOnDrop) {
SetData(data);
target_ = new DragDropCloseView();
- widget_->GetContentsView()->AddChildView(target_);
+ widget_->non_client_view()->frame_view()->AddChildView(target_);
target_->SetBoundsRect(gfx::Rect(0, 0, 100, 100));
target_->set_formats(ui::OSExchangeData::STRING | ui::OSExchangeData::URL);
diff --git a/chromium/ui/views/cocoa/native_widget_mac_ns_window_host.h b/chromium/ui/views/cocoa/native_widget_mac_ns_window_host.h
index 69d612b69a9..b6d860060e4 100644
--- a/chromium/ui/views/cocoa/native_widget_mac_ns_window_host.h
+++ b/chromium/ui/views/cocoa/native_widget_mac_ns_window_host.h
@@ -218,6 +218,13 @@ class VIEWS_EXPORT NativeWidgetMacNSWindowHost
// Used by NativeWidgetPrivate::GetGlobalCapture.
static NSView* GetGlobalCaptureView();
+ // Add and Update the remote window controls overlay view for a PWA.
+ void AddRemoteWindowControlsOverlayView(
+ remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type);
+ void UpdateRemoteWindowControlsOverlayView(
+ const gfx::Rect& bounds,
+ remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type);
+
private:
friend class TextInputHost;
diff --git a/chromium/ui/views/cocoa/native_widget_mac_ns_window_host.mm b/chromium/ui/views/cocoa/native_widget_mac_ns_window_host.mm
index e9915323171..1de90c3bf77 100644
--- a/chromium/ui/views/cocoa/native_widget_mac_ns_window_host.mm
+++ b/chromium/ui/views/cocoa/native_widget_mac_ns_window_host.mm
@@ -21,6 +21,7 @@
#include "ui/base/cocoa/remote_layer_api.h"
#include "ui/base/hit_test.h"
#include "ui/base/ime/input_method.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/recyclable_compositor_mac.h"
#include "ui/display/screen.h"
#include "ui/events/cocoa/cocoa_event_utils.h"
@@ -333,6 +334,7 @@ void NativeWidgetMacNSWindowHost::CreateRemoteNSWindow(
in_process_view_id_mapping_ =
std::make_unique<remote_cocoa::ScopedNSViewIdMapping>(
root_view_id_, [in_process_ns_window_ contentView]);
+ [in_process_ns_window_ enforceNeverMadeVisible];
}
// Initialize |remote_ns_window_remote_| to point to a bridge created by
@@ -720,6 +722,17 @@ NSView* NativeWidgetMacNSWindowHost::GetGlobalCaptureView() {
[remote_cocoa::CocoaMouseCapture::GetGlobalCaptureWindow() contentView];
}
+void NativeWidgetMacNSWindowHost::AddRemoteWindowControlsOverlayView(
+ remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type) {
+ GetNSWindowMojo()->CreateWindowControlsOverlayNSView(overlay_type);
+}
+
+void NativeWidgetMacNSWindowHost::UpdateRemoteWindowControlsOverlayView(
+ const gfx::Rect& bounds,
+ remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type) {
+ GetNSWindowMojo()->UpdateWindowControlsOverlayNSView(bounds, overlay_type);
+}
+
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetMacNSWindowHost, remote_cocoa::BridgedNativeWidgetHostHelper:
@@ -862,14 +875,22 @@ void NativeWidgetMacNSWindowHost::SetKeyboardAccessible(bool enabled) {
void NativeWidgetMacNSWindowHost::OnIsFirstResponderChanged(
bool is_first_responder) {
accessibility_focus_overrider_.SetViewIsFirstResponder(is_first_responder);
+
+ FocusManager* focus_manager = root_view_->GetWidget()->GetFocusManager();
+ if (focus_manager->IsSettingFocusedView()) {
+ // This first responder change is not initiated by the os,
+ // but by the focus change within the browser (e.g. tab switch),
+ // so skip setting the focus.
+ return;
+ }
+
if (is_first_responder) {
- root_view_->GetWidget()->GetFocusManager()->RestoreFocusedView();
+ focus_manager->RestoreFocusedView();
} else {
// Do not call ClearNativeFocus because that will re-make the
// BridgedNativeWidget first responder (and this is called to indicate that
// it is no longer first responder).
- root_view_->GetWidget()->GetFocusManager()->StoreFocusedView(
- false /* clear_native_focus */);
+ focus_manager->StoreFocusedView(false /* clear_native_focus */);
}
}
diff --git a/chromium/ui/views/color_chooser/color_chooser_unittest.cc b/chromium/ui/views/color_chooser/color_chooser_unittest.cc
index cfd1d1fb52d..46fbc38f86a 100644
--- a/chromium/ui/views/color_chooser/color_chooser_unittest.cc
+++ b/chromium/ui/views/color_chooser/color_chooser_unittest.cc
@@ -57,7 +57,6 @@ class ColorChooserTest : public views::ViewsTestBase {
widget_->GetContentsView()->AddChildView(std::move(view));
generator_ = std::make_unique<ui::test::EventGenerator>(
views::GetRootWindow(widget_.get()), widget_->GetNativeWindow());
- generator_->set_assume_window_at_origin(false);
}
void TearDown() override {
diff --git a/chromium/ui/views/color_chooser/color_chooser_view.cc b/chromium/ui/views/color_chooser/color_chooser_view.cc
index c92dde7c56d..4fd58eeadd4 100644
--- a/chromium/ui/views/color_chooser/color_chooser_view.cc
+++ b/chromium/ui/views/color_chooser/color_chooser_view.cc
@@ -22,6 +22,8 @@
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
@@ -36,8 +38,6 @@
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/grid_layout.h"
-#include "ui/views/metadata/metadata_header_macros.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
diff --git a/chromium/ui/views/controls/button/button.cc b/chromium/ui/views/controls/button/button.cc
index b38962e9bca..8d07de719cb 100644
--- a/chromium/ui/views/controls/button/button.cc
+++ b/chromium/ui/views/controls/button/button.cc
@@ -6,10 +6,13 @@
#include <utility>
+#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/class_property.h"
+#include "ui/base/interaction/element_identifier.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/keyboard_codes.h"
@@ -27,9 +30,10 @@
#include "ui/views/controls/button/radio_button.h"
#include "ui/views/controls/button/toggle_button.h"
#include "ui/views/controls/focus_ring.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
+#include "ui/views/interaction/element_tracker_views.h"
#include "ui/views/painter.h"
#include "ui/views/style/platform_style.h"
+#include "ui/views/view_class_properties.h"
#if defined(USE_AURA)
#include "ui/aura/client/capture_client.h"
@@ -80,7 +84,7 @@ bool Button::DefaultButtonControllerDelegate::ShouldEnterHoveredState() {
}
InkDrop* Button::DefaultButtonControllerDelegate::GetInkDrop() {
- return button()->GetInkDrop();
+ return button()->ink_drop()->GetInkDrop();
}
int Button::DefaultButtonControllerDelegate::GetDragOperations(
@@ -239,7 +243,7 @@ int Button::GetTriggerableEventFlags() const {
void Button::SetRequestFocusOnPress(bool value) {
// On Mac, buttons should not request focus on a mouse press. Hence keep the
// default value i.e. false.
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
if (request_focus_on_press_ == value)
return;
request_focus_on_press_ = value;
@@ -285,13 +289,6 @@ bool Button::GetShowInkDropWhenHotTracked() const {
return show_ink_drop_when_hot_tracked_;
}
-void Button::SetInkDropBaseColor(SkColor color) {
- if (color == ink_drop_base_color_)
- return;
- ink_drop_base_color_ = color;
- OnPropertyChanged(&ink_drop_base_color_, kPropertyEffectsNone);
-}
-
void Button::SetHasInkDropActionOnClick(bool value) {
if (value == has_ink_drop_action_on_click_)
return;
@@ -323,9 +320,9 @@ void Button::SetHotTracked(bool is_hot_tracked) {
if (state_ != STATE_DISABLED) {
SetState(is_hot_tracked ? STATE_HOVERED : STATE_NORMAL);
if (show_ink_drop_when_hot_tracked_) {
- AnimateInkDrop(is_hot_tracked ? views::InkDropState::ACTIVATED
- : views::InkDropState::HIDDEN,
- nullptr);
+ ink_drop()->AnimateToState(is_hot_tracked ? views::InkDropState::ACTIVATED
+ : views::InkDropState::HIDDEN,
+ nullptr);
}
}
@@ -342,9 +339,9 @@ void Button::SetFocusPainter(std::unique_ptr<Painter> focus_painter) {
}
void Button::SetHighlighted(bool bubble_visible) {
- AnimateInkDrop(bubble_visible ? views::InkDropState::ACTIVATED
- : views::InkDropState::DEACTIVATED,
- nullptr);
+ ink_drop()->AnimateToState(bubble_visible ? views::InkDropState::ACTIVATED
+ : views::InkDropState::DEACTIVATED,
+ nullptr);
}
base::CallbackListSubscription Button::AddStateChangedCallback(
@@ -411,15 +408,17 @@ bool Button::OnMouseDragged(const ui::MouseEvent& event) {
!InDrag();
if (HitTestPoint(event.location())) {
SetState(should_enter_pushed ? STATE_PRESSED : STATE_HOVERED);
- if (should_show_pending && GetInkDrop()->GetTargetInkDropState() ==
- views::InkDropState::HIDDEN) {
- AnimateInkDrop(views::InkDropState::ACTION_PENDING, &event);
+ if (should_show_pending &&
+ ink_drop()->GetInkDrop()->GetTargetInkDropState() ==
+ views::InkDropState::HIDDEN) {
+ ink_drop()->AnimateToState(views::InkDropState::ACTION_PENDING, &event);
}
} else {
SetState(STATE_NORMAL);
- if (should_show_pending && GetInkDrop()->GetTargetInkDropState() ==
- views::InkDropState::ACTION_PENDING) {
- AnimateInkDrop(views::InkDropState::HIDDEN, &event);
+ if (should_show_pending &&
+ ink_drop()->GetInkDrop()->GetTargetInkDropState() ==
+ views::InkDropState::ACTION_PENDING) {
+ ink_drop()->AnimateToState(views::InkDropState::HIDDEN, &event);
}
}
}
@@ -436,9 +435,9 @@ void Button::OnMouseCaptureLost() {
// applies everywhere so gather any feedback and update.
if (state_ != STATE_DISABLED)
SetState(STATE_NORMAL);
- AnimateInkDrop(views::InkDropState::HIDDEN, nullptr /* event */);
- GetInkDrop()->SetHovered(false);
- InkDropHostView::OnMouseCaptureLost();
+ ink_drop()->AnimateToState(views::InkDropState::HIDDEN, nullptr /* event */);
+ ink_drop()->GetInkDrop()->SetHovered(false);
+ View::OnMouseCaptureLost();
}
void Button::OnMouseEntered(const ui::MouseEvent& event) {
@@ -492,10 +491,10 @@ void Button::ShowContextMenu(const gfx::Point& p,
if (state_ != STATE_DISABLED)
SetState(STATE_NORMAL);
if (hide_ink_drop_when_showing_context_menu_) {
- GetInkDrop()->SetHovered(false);
- AnimateInkDrop(InkDropState::HIDDEN, nullptr /* event */);
+ ink_drop()->GetInkDrop()->SetHovered(false);
+ ink_drop()->AnimateToState(InkDropState::HIDDEN, nullptr /* event */);
}
- InkDropHostView::ShowContextMenu(p, source_type);
+ View::ShowContextMenu(p, source_type);
}
void Button::OnDragDone() {
@@ -503,11 +502,11 @@ void Button::OnDragDone() {
// (since disabled buttons may still be able to be dragged).
if (state_ != STATE_DISABLED)
SetState(STATE_NORMAL);
- AnimateInkDrop(InkDropState::HIDDEN, nullptr /* event */);
+ ink_drop()->AnimateToState(InkDropState::HIDDEN, nullptr /* event */);
}
void Button::OnPaint(gfx::Canvas* canvas) {
- InkDropHostView::OnPaint(canvas);
+ View::OnPaint(canvas);
PaintButtonContents(canvas);
Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
}
@@ -540,7 +539,7 @@ void Button::GetAccessibleNodeData(ui::AXNodeData* node_data) {
}
void Button::VisibilityChanged(View* starting_from, bool visible) {
- InkDropHostView::VisibilityChanged(starting_from, visible);
+ View::VisibilityChanged(starting_from, visible);
if (state_ == STATE_DISABLED)
return;
SetState(visible && ShouldEnterHoveredState() ? STATE_HOVERED : STATE_NORMAL);
@@ -549,21 +548,23 @@ void Button::VisibilityChanged(View* starting_from, bool visible) {
void Button::ViewHierarchyChanged(const ViewHierarchyChangedDetails& details) {
if (!details.is_add && state_ != STATE_DISABLED && details.child == this)
SetState(STATE_NORMAL);
- InkDropHostView::ViewHierarchyChanged(details);
+ View::ViewHierarchyChanged(details);
}
void Button::OnFocus() {
- InkDropHostView::OnFocus();
+ View::OnFocus();
if (focus_painter_)
SchedulePaint();
}
void Button::OnBlur() {
- InkDropHostView::OnBlur();
+ View::OnBlur();
if (IsHotTracked() || state_ == STATE_PRESSED) {
SetState(STATE_NORMAL);
- if (GetInkDrop()->GetTargetInkDropState() != views::InkDropState::HIDDEN)
- AnimateInkDrop(views::InkDropState::HIDDEN, nullptr /* event */);
+ if (ink_drop()->GetInkDrop()->GetTargetInkDropState() !=
+ views::InkDropState::HIDDEN)
+ ink_drop()->AnimateToState(views::InkDropState::HIDDEN,
+ nullptr /* event */);
// TODO(bruthig) : Fix Buttons to work well when multiple input
// methods are interacting with a button. e.g. By animating to HIDDEN here
// it is possible for a Mouse Release to trigger an action however there
@@ -573,30 +574,29 @@ void Button::OnBlur() {
SchedulePaint();
}
-std::unique_ptr<InkDrop> Button::CreateInkDrop() {
- std::unique_ptr<InkDrop> ink_drop = InkDropHostView::CreateInkDrop();
- ink_drop->SetShowHighlightOnFocus(!focus_ring_);
- return ink_drop;
-}
-
-SkColor Button::GetInkDropBaseColor() const {
- return ink_drop_base_color_;
-}
-
void Button::AnimationProgressed(const gfx::Animation* animation) {
SchedulePaint();
}
Button::Button(PressedCallback callback)
- : AnimationDelegateViews(this),
- callback_(std::move(callback)),
- ink_drop_base_color_(gfx::kPlaceholderColor) {
+ : AnimationDelegateViews(this), callback_(std::move(callback)) {
SetFocusBehavior(PlatformStyle::kDefaultFocusBehavior);
SetProperty(kIsButtonProperty, true);
hover_animation_.SetSlideDuration(base::TimeDelta::FromMilliseconds(150));
SetInstallFocusRingOnFocus(true);
button_controller_ = std::make_unique<ButtonController>(
this, std::make_unique<DefaultButtonControllerDelegate>(this));
+ ink_drop()->SetCreateInkDropCallback(base::BindRepeating(
+ [](Button* button) {
+ std::unique_ptr<InkDrop> ink_drop =
+ views::InkDrop::CreateInkDropForFloodFillRipple(button->ink_drop());
+ ink_drop->SetShowHighlightOnFocus(!button->focus_ring());
+ return ink_drop;
+ },
+ base::Unretained(this)));
+ // TODO(pbos): Investigate not setting a default color so that we can DCHECK
+ // if one hasn't been set.
+ ink_drop()->SetBaseColor(gfx::kPlaceholderColor);
}
void Button::RequestFocusFromEvent() {
@@ -606,8 +606,16 @@ void Button::RequestFocusFromEvent() {
void Button::NotifyClick(const ui::Event& event) {
if (has_ink_drop_action_on_click_) {
- AnimateInkDrop(InkDropState::ACTION_TRIGGERED,
- ui::LocatedEvent::FromIfValid(&event));
+ ink_drop()->AnimateToState(InkDropState::ACTION_TRIGGERED,
+ ui::LocatedEvent::FromIfValid(&event));
+ }
+
+ // If we have an associated help context ID, notify that system that we have
+ // been activated.
+ const ui::ElementIdentifier element_id = GetProperty(kElementIdentifierKey);
+ if (element_id) {
+ views::ElementTrackerViews::GetInstance()->NotifyViewActivated(element_id,
+ this);
}
if (callback_)
@@ -616,12 +624,12 @@ void Button::NotifyClick(const ui::Event& event) {
void Button::OnClickCanceled(const ui::Event& event) {
if (ShouldUpdateInkDropOnClickCanceled()) {
- if (GetInkDrop()->GetTargetInkDropState() ==
+ if (ink_drop()->GetInkDrop()->GetTargetInkDropState() ==
views::InkDropState::ACTION_PENDING ||
- GetInkDrop()->GetTargetInkDropState() ==
+ ink_drop()->GetInkDrop()->GetTargetInkDropState() ==
views::InkDropState::ALTERNATE_ACTION_PENDING) {
- AnimateInkDrop(views::InkDropState::HIDDEN,
- ui::LocatedEvent::FromIfValid(&event));
+ ink_drop()->AnimateToState(views::InkDropState::HIDDEN,
+ ui::LocatedEvent::FromIfValid(&event));
}
}
}
@@ -675,26 +683,19 @@ void Button::OnEnabledChanged() {
if (GetEnabled()) {
bool should_enter_hover_state = ShouldEnterHoveredState();
SetState(should_enter_hover_state ? STATE_HOVERED : STATE_NORMAL);
- GetInkDrop()->SetHovered(should_enter_hover_state);
+ ink_drop()->GetInkDrop()->SetHovered(should_enter_hover_state);
} else {
SetState(STATE_DISABLED);
- GetInkDrop()->SetHovered(false);
+ ink_drop()->GetInkDrop()->SetHovered(false);
}
}
-DEFINE_ENUM_CONVERTERS(Button::ButtonState,
- {Button::STATE_NORMAL, u"STATE_NORMAL"},
- {Button::STATE_HOVERED, u"STATE_HOVERED"},
- {Button::STATE_PRESSED, u"STATE_PRESSED"},
- {Button::STATE_DISABLED, u"STATE_DISABLED"})
-
-BEGIN_METADATA(Button, InkDropHostView)
+BEGIN_METADATA(Button, View)
ADD_PROPERTY_METADATA(std::u16string, AccessibleName)
ADD_PROPERTY_METADATA(PressedCallback, Callback)
ADD_PROPERTY_METADATA(bool, AnimateOnStateChange)
ADD_PROPERTY_METADATA(bool, HasInkDropActionOnClick)
ADD_PROPERTY_METADATA(bool, HideInkDropWhenShowingContextMenu)
-ADD_PROPERTY_METADATA(SkColor, InkDropBaseColor, metadata::SkColorConverter)
ADD_PROPERTY_METADATA(bool, InstallFocusRingOnFocus)
ADD_PROPERTY_METADATA(bool, RequestFocusOnPress)
ADD_PROPERTY_METADATA(ButtonState, State)
@@ -703,3 +704,9 @@ ADD_PROPERTY_METADATA(int, TriggerableEventFlags)
END_METADATA
} // namespace views
+
+DEFINE_ENUM_CONVERTERS(views::Button::ButtonState,
+ {views::Button::STATE_NORMAL, u"STATE_NORMAL"},
+ {views::Button::STATE_HOVERED, u"STATE_HOVERED"},
+ {views::Button::STATE_PRESSED, u"STATE_PRESSED"},
+ {views::Button::STATE_DISABLED, u"STATE_DISABLED"})
diff --git a/chromium/ui/views/controls/button/button.h b/chromium/ui/views/controls/button/button.h
index 1ca1a759045..8fabab86284 100644
--- a/chromium/ui/views/controls/button/button.h
+++ b/chromium/ui/views/controls/button/button.h
@@ -33,8 +33,7 @@ class Event;
// A View representing a button. A Button is focusable by default and will
// be part of the focus chain.
-class VIEWS_EXPORT Button : public InkDropHostView,
- public AnimationDelegateViews {
+class VIEWS_EXPORT Button : public View, public AnimationDelegateViews {
public:
// Button states for various button sub-types.
enum ButtonState {
@@ -166,8 +165,6 @@ class VIEWS_EXPORT Button : public InkDropHostView,
void SetShowInkDropWhenHotTracked(bool value);
bool GetShowInkDropWhenHotTracked() const;
- void SetInkDropBaseColor(SkColor color);
-
void SetHasInkDropActionOnClick(bool value);
bool GetHasInkDropActionOnClick() const;
@@ -185,6 +182,9 @@ class VIEWS_EXPORT Button : public InkDropHostView,
base::CallbackListSubscription AddStateChangedCallback(
PropertyChangedCallback callback);
+ InkDropHost* ink_drop() { return ink_drop_.get(); }
+ const InkDropHost* ink_drop() const { return ink_drop_.get(); }
+
// Overridden from View:
bool OnMousePressed(const ui::MouseEvent& event) override;
bool OnMouseDragged(const ui::MouseEvent& event) override;
@@ -212,10 +212,6 @@ class VIEWS_EXPORT Button : public InkDropHostView,
void OnFocus() override;
void OnBlur() override;
- // Overridden from InkDropHostView:
- std::unique_ptr<InkDrop> CreateInkDrop() override;
- SkColor GetInkDropBaseColor() const override;
-
// Overridden from views::AnimationDelegateViews:
void AnimationProgressed(const gfx::Animation* animation) override;
@@ -341,8 +337,8 @@ class VIEWS_EXPORT Button : public InkDropHostView,
// tracked with SetHotTracked().
bool show_ink_drop_when_hot_tracked_ = false;
- // The color of the ripple and hover.
- SkColor ink_drop_base_color_;
+ // The InkDrop for this Button.
+ std::unique_ptr<InkDropHost> ink_drop_{std::make_unique<InkDropHost>(this)};
// The focus ring for this Button.
FocusRing* focus_ring_ = nullptr;
@@ -362,14 +358,13 @@ class VIEWS_EXPORT Button : public InkDropHostView,
DISALLOW_COPY_AND_ASSIGN(Button);
};
-BEGIN_VIEW_BUILDER(VIEWS_EXPORT, Button, InkDropHostView)
+BEGIN_VIEW_BUILDER(VIEWS_EXPORT, Button, View)
VIEW_BUILDER_PROPERTY(std::u16string, AccessibleName)
VIEW_BUILDER_PROPERTY(Button::PressedCallback, Callback)
VIEW_BUILDER_PROPERTY(base::TimeDelta, AnimationDuration)
VIEW_BUILDER_PROPERTY(bool, AnimateOnStateChange)
VIEW_BUILDER_PROPERTY(bool, HasInkDropActionOnClick)
VIEW_BUILDER_PROPERTY(bool, HideInkDropWhenShowingContextMenu)
-VIEW_BUILDER_PROPERTY(SkColor, InkDropBaseColor)
VIEW_BUILDER_PROPERTY(bool, InstallFocusRingOnFocus)
VIEW_BUILDER_PROPERTY(bool, RequestFocusOnPress)
VIEW_BUILDER_PROPERTY(Button::ButtonState, State)
diff --git a/chromium/ui/views/controls/button/button_controller.cc b/chromium/ui/views/controls/button/button_controller.cc
index e652cb11b18..77c71e4ca37 100644
--- a/chromium/ui/views/controls/button/button_controller.cc
+++ b/chromium/ui/views/controls/button/button_controller.cc
@@ -27,7 +27,8 @@ bool ButtonController::OnMousePressed(const ui::MouseEvent& event) {
button_controller_delegate_->ShouldEnterPushedState(event) &&
button_->HitTestPoint(event.location())) {
button_->SetState(Button::STATE_PRESSED);
- button_->AnimateInkDrop(views::InkDropState::ACTION_PENDING, &event);
+ button_->ink_drop()->AnimateToState(views::InkDropState::ACTION_PENDING,
+ &event);
}
button_controller_delegate_->RequestFocusFromEvent();
if (button_controller_delegate_->IsTriggerableEvent(event) &&
@@ -87,8 +88,8 @@ bool ButtonController::OnKeyPressed(const ui::KeyEvent& event) {
button_->SetState(Button::STATE_PRESSED);
if (button_controller_delegate_->GetInkDrop()->GetTargetInkDropState() !=
InkDropState::ACTION_PENDING) {
- button_->AnimateInkDrop(InkDropState::ACTION_PENDING,
- nullptr /* event */);
+ button_->ink_drop()->AnimateToState(InkDropState::ACTION_PENDING,
+ nullptr /* event */);
}
return true;
case Button::KeyClickAction::kOnKeyPress:
diff --git a/chromium/ui/views/controls/button/button_unittest.cc b/chromium/ui/views/controls/button/button_unittest.cc
index e99573deab2..b26e873d3b7 100644
--- a/chromium/ui/views/controls/button/button_unittest.cc
+++ b/chromium/ui/views/controls/button/button_unittest.cc
@@ -9,7 +9,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
@@ -50,7 +49,7 @@
namespace views {
-using test::InkDropHostViewTestApi;
+using test::InkDropHostTestApi;
using test::TestInkDrop;
namespace {
@@ -86,24 +85,11 @@ class TestButton : public Button {
return custom_key_click_action_;
}
- void OnClickCanceled(const ui::Event& event) override { canceled_ = true; }
-
// Button:
- void AddInkDropLayer(ui::Layer* ink_drop_layer) override {
- ++ink_drop_layer_add_count_;
- Button::AddInkDropLayer(ink_drop_layer);
- }
- void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override {
- ++ink_drop_layer_remove_count_;
- Button::RemoveInkDropLayer(ink_drop_layer);
- }
+ void OnClickCanceled(const ui::Event& event) override { canceled_ = true; }
bool pressed() const { return pressed_; }
bool canceled() const { return canceled_; }
- int ink_drop_layer_add_count() const { return ink_drop_layer_add_count_; }
- int ink_drop_layer_remove_count() const {
- return ink_drop_layer_remove_count_;
- }
void set_custom_key_click_action(KeyClickAction custom_key_click_action) {
custom_key_click_action_ = custom_key_click_action;
@@ -115,15 +101,12 @@ class TestButton : public Button {
}
// Raised visibility of OnFocus() to public
- void OnFocus() override { Button::OnFocus(); }
+ using Button::OnFocus;
private:
bool pressed_ = false;
bool canceled_ = false;
- int ink_drop_layer_add_count_ = 0;
- int ink_drop_layer_remove_count_ = 0;
-
KeyClickAction custom_key_click_action_ = KeyClickAction::kNone;
DISALLOW_COPY_AND_ASSIGN(TestButton);
@@ -133,7 +116,7 @@ class TestButtonObserver {
public:
explicit TestButtonObserver(Button* button) {
highlighted_changed_subscription_ =
- button->AddHighlightedChangedCallback(base::BindRepeating(
+ button->ink_drop()->AddHighlightedChangedCallback(base::BindRepeating(
[](TestButtonObserver* obs) { obs->highlighted_changed_ = true; },
base::Unretained(this)));
state_changed_subscription_ =
@@ -164,8 +147,8 @@ class TestButtonObserver {
TestInkDrop* AddTestInkDrop(TestButton* button) {
auto owned_ink_drop = std::make_unique<TestInkDrop>();
TestInkDrop* ink_drop = owned_ink_drop.get();
- button->SetInkDropMode(InkDropHostView::InkDropMode::ON);
- InkDropHostViewTestApi(button).SetInkDrop(std::move(owned_ink_drop));
+ button->ink_drop()->SetMode(views::InkDropHost::InkDropMode::ON);
+ InkDropHostTestApi(button->ink_drop()).SetInkDrop(std::move(owned_ink_drop));
return ink_drop;
}
@@ -193,7 +176,6 @@ class ButtonTest : public ViewsTestBase {
event_generator_ =
std::make_unique<ui::test::EventGenerator>(GetRootWindow(widget()));
- event_generator_->set_assume_window_at_origin(false);
}
void TearDown() override {
@@ -210,7 +192,7 @@ class ButtonTest : public ViewsTestBase {
void CreateButtonWithObserver() {
button_ = widget()->SetContentsView(std::make_unique<TestButton>(false));
- button_->SetInkDropMode(InkDropHostView::InkDropMode::ON);
+ button_->ink_drop()->SetMode(views::InkDropHost::InkDropMode::ON);
button_observer_ = std::make_unique<TestButtonObserver>(button_);
}
@@ -285,7 +267,7 @@ TEST_F(ButtonTest, HoverStateOnVisibilityChange) {
// Disabling cursor events occurs for touch events and the Ash magnifier. There
// is no touch on desktop Mac. Tracked in http://crbug.com/445520.
-#if !defined(OS_APPLE) || defined(USE_AURA)
+#if !defined(OS_MAC) || defined(USE_AURA)
aura::test::TestCursorClient cursor_client(GetRootWindow(widget()));
// In Aura views, no new hover effects are invoked if mouse events
@@ -303,7 +285,7 @@ TEST_F(ButtonTest, HoverStateOnVisibilityChange) {
button()->SetVisible(true);
EXPECT_EQ(Button::STATE_NORMAL, button()->GetState());
-#endif // !defined(OS_APPLE) || defined(USE_AURA)
+#endif // !defined(OS_MAC) || defined(USE_AURA)
}
// Tests that the hover state is preserved during a view hierarchy update of a
@@ -389,7 +371,7 @@ TEST_F(ButtonTest, NotifyActionNoClick) {
}
// No touch on desktop Mac. Tracked in http://crbug.com/445520.
-#if !defined(OS_APPLE) || defined(USE_AURA)
+#if !defined(OS_MAC) || defined(USE_AURA)
namespace {
@@ -429,7 +411,7 @@ TEST_F(ButtonTest, GestureEventsRespectDisabledState) {
EXPECT_EQ(Button::STATE_DISABLED, button()->GetState());
}
-#endif // !defined(OS_APPLE) || defined(USE_AURA)
+#endif // !defined(OS_MAC) || defined(USE_AURA)
// Ensure subclasses of Button are correctly recognized as Button.
TEST_F(ButtonTest, AsButton) {
@@ -754,15 +736,9 @@ class VisibilityTestButton : public TestButton {
ADD_FAILURE();
}
- // TestButton:
- void AddInkDropLayer(ui::Layer* ink_drop_layer) override {
- ADD_FAILURE();
- TestButton::AddInkDropLayer(ink_drop_layer);
- }
- void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override {
- ADD_FAILURE();
- TestButton::RemoveInkDropLayer(ink_drop_layer);
- }
+ void AddLayerBeneathView(ui::Layer* layer) override { ADD_FAILURE(); }
+
+ void RemoveLayerBeneathView(ui::Layer* layer) override { ADD_FAILURE(); }
};
// Test that hiding or closing a Widget doesn't attempt to add a layer due to
@@ -801,7 +777,7 @@ TEST_F(ButtonTest, ActionOnSpace) {
ui::KeyEvent space_press(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, ui::EF_NONE);
EXPECT_TRUE(button()->OnKeyPressed(space_press));
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
EXPECT_EQ(Button::STATE_NORMAL, button()->GetState());
EXPECT_TRUE(button()->pressed());
#else
@@ -811,7 +787,7 @@ TEST_F(ButtonTest, ActionOnSpace) {
ui::KeyEvent space_release(ui::ET_KEY_RELEASED, ui::VKEY_SPACE, ui::EF_NONE);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
EXPECT_FALSE(button()->OnKeyReleased(space_release));
#else
EXPECT_TRUE(button()->OnKeyReleased(space_release));
@@ -831,7 +807,7 @@ TEST_F(ButtonTest, ActionOnReturn) {
ui::KeyEvent return_press(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::EF_NONE);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
EXPECT_FALSE(button()->OnKeyPressed(return_press));
EXPECT_EQ(Button::STATE_NORMAL, button()->GetState());
EXPECT_FALSE(button()->pressed());
@@ -870,19 +846,19 @@ TEST_F(ButtonTest, CustomActionOnKeyPressedEvent) {
TEST_F(ButtonTest, ChangingHighlightStateNotifiesCallback) {
CreateButtonWithObserver();
EXPECT_FALSE(button_observer()->highlighted_changed());
- EXPECT_FALSE(button()->GetHighlighted());
+ EXPECT_FALSE(button()->ink_drop()->GetHighlighted());
button()->SetHighlighted(/*bubble_visible=*/true);
EXPECT_TRUE(button_observer()->highlighted_changed());
- EXPECT_TRUE(button()->GetHighlighted());
+ EXPECT_TRUE(button()->ink_drop()->GetHighlighted());
button_observer()->Reset();
EXPECT_FALSE(button_observer()->highlighted_changed());
- EXPECT_TRUE(button()->GetHighlighted());
+ EXPECT_TRUE(button()->ink_drop()->GetHighlighted());
button()->SetHighlighted(/*bubble_visible=*/false);
EXPECT_TRUE(button_observer()->highlighted_changed());
- EXPECT_FALSE(button()->GetHighlighted());
+ EXPECT_FALSE(button()->ink_drop()->GetHighlighted());
}
// Verifies that button state changes trigger property change callbacks.
diff --git a/chromium/ui/views/controls/button/checkbox.cc b/chromium/ui/views/controls/button/checkbox.cc
index 5c8baf551d5..5bcf4f71866 100644
--- a/chromium/ui/views/controls/button/checkbox.cc
+++ b/chromium/ui/views/controls/button/checkbox.cc
@@ -9,12 +9,15 @@
#include <memory>
#include <utility>
+#include "base/bind.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/skia_util.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/animation/ink_drop_impl.h"
@@ -23,7 +26,6 @@
#include "ui/views/controls/focus_ring.h"
#include "ui/views/controls/highlight_path_generator.h"
#include "ui/views/layout/layout_provider.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/painter.h"
#include "ui/views/resources/grit/views_resources.h"
#include "ui/views/style/platform_style.h"
@@ -50,8 +52,25 @@ Checkbox::Checkbox(const std::u16string& label, PressedCallback callback)
SetHorizontalAlignment(gfx::ALIGN_LEFT);
SetRequestFocusOnPress(false);
- SetInkDropMode(InkDropMode::ON);
+ ink_drop()->SetMode(views::InkDropHost::InkDropMode::ON);
SetHasInkDropActionOnClick(true);
+ views::InkDrop::UseInkDropWithoutAutoHighlight(ink_drop(),
+ /*highlight_on_hover=*/false);
+ ink_drop()->SetCreateRippleCallback(base::BindRepeating(
+ [](Checkbox* host) {
+ // The "small" size is 21dp, the large size is 1.33 * 21dp = 28dp.
+ return host->ink_drop()->CreateSquareRipple(
+ host->image()->GetMirroredContentsBounds().CenterPoint(),
+ gfx::Size(21, 21));
+ },
+ this));
+ ink_drop()->SetBaseColorCallback(base::BindRepeating(
+ [](Checkbox* host) {
+ // Usually ink-drop ripples match the text color. Checkboxes use the
+ // color of the unchecked, enabled icon.
+ return host->GetIconImageColor(IconState::ENABLED);
+ },
+ this));
// Limit the checkbox height to match the legacy appearance.
const gfx::Size preferred_size(LabelButton::CalculatePreferredSize());
@@ -152,25 +171,6 @@ void Checkbox::OnThemeChanged() {
UpdateImage();
}
-std::unique_ptr<InkDrop> Checkbox::CreateInkDrop() {
- std::unique_ptr<InkDropImpl> ink_drop = CreateDefaultInkDropImpl();
- ink_drop->SetShowHighlightOnHover(false);
- ink_drop->SetAutoHighlightMode(InkDropImpl::AutoHighlightMode::NONE);
- return ink_drop;
-}
-
-std::unique_ptr<InkDropRipple> Checkbox::CreateInkDropRipple() const {
- // The "small" size is 21dp, the large size is 1.33 * 21dp = 28dp.
- return CreateSquareInkDropRipple(
- image()->GetMirroredContentsBounds().CenterPoint(), gfx::Size(21, 21));
-}
-
-SkColor Checkbox::GetInkDropBaseColor() const {
- // Usually ink-drop ripples match the text color. Checkboxes use the color of
- // the unchecked, enabled icon.
- return GetIconImageColor(IconState::ENABLED);
-}
-
SkPath Checkbox::GetFocusRingPath() const {
SkPath path;
gfx::Rect bounds = image()->GetMirroredContentsBounds();
diff --git a/chromium/ui/views/controls/button/checkbox.h b/chromium/ui/views/controls/button/checkbox.h
index 1030986e2e7..f72b517faeb 100644
--- a/chromium/ui/views/controls/button/checkbox.h
+++ b/chromium/ui/views/controls/button/checkbox.h
@@ -58,9 +58,6 @@ class VIEWS_EXPORT Checkbox : public LabelButton {
// LabelButton:
void OnThemeChanged() override;
- std::unique_ptr<InkDrop> CreateInkDrop() override;
- std::unique_ptr<InkDropRipple> CreateInkDropRipple() const override;
- SkColor GetInkDropBaseColor() const override;
// Returns the path to draw the focus ring around for this Checkbox.
virtual SkPath GetFocusRingPath() const;
diff --git a/chromium/ui/views/controls/button/image_button.cc b/chromium/ui/views/controls/button/image_button.cc
index c991b5b9c12..d5cf20d88b4 100644
--- a/chromium/ui/views/controls/button/image_button.cc
+++ b/chromium/ui/views/controls/button/image_button.cc
@@ -7,14 +7,15 @@
#include <utility>
#include "base/strings/utf_string_conversions.h"
+#include "base/trace_event/trace_event.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/animation/throb_animation.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/scoped_canvas.h"
#include "ui/views/background.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/painter.h"
#include "ui/views/widget/widget.h"
@@ -334,17 +335,6 @@ void ToggleImageButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
}
}
-DEFINE_ENUM_CONVERTERS(
- ImageButton::HorizontalAlignment,
- {ImageButton::HorizontalAlignment::ALIGN_LEFT, u"ALIGN_LEFT"},
- {ImageButton::HorizontalAlignment::ALIGN_CENTER, u"ALIGN_CENTER"},
- {ImageButton::HorizontalAlignment::ALIGN_RIGHT, u"ALIGN_RIGHT"})
-DEFINE_ENUM_CONVERTERS(
- ImageButton::VerticalAlignment,
- {ImageButton::VerticalAlignment::ALIGN_TOP, u"ALIGN_TOP"},
- {ImageButton::VerticalAlignment::ALIGN_MIDDLE, u"ALIGN_MIDDLE"},
- {ImageButton::VerticalAlignment::ALIGN_BOTTOM, u"ALIGN_BOTTOM"})
-
BEGIN_METADATA(ImageButton, Button)
ADD_PROPERTY_METADATA(HorizontalAlignment, ImageHorizontalAlignment)
ADD_PROPERTY_METADATA(VerticalAlignment, ImageVerticalAlignment)
@@ -359,3 +349,14 @@ ADD_PROPERTY_METADATA(std::u16string, ToggledAccessibleName)
END_METADATA
} // namespace views
+
+DEFINE_ENUM_CONVERTERS(
+ views::ImageButton::HorizontalAlignment,
+ {views::ImageButton::HorizontalAlignment::ALIGN_LEFT, u"ALIGN_LEFT"},
+ {views::ImageButton::HorizontalAlignment::ALIGN_CENTER, u"ALIGN_CENTER"},
+ {views::ImageButton::HorizontalAlignment::ALIGN_RIGHT, u"ALIGN_RIGHT"})
+DEFINE_ENUM_CONVERTERS(
+ views::ImageButton::VerticalAlignment,
+ {views::ImageButton::VerticalAlignment::ALIGN_TOP, u"ALIGN_TOP"},
+ {views::ImageButton::VerticalAlignment::ALIGN_MIDDLE, u"ALIGN_MIDDLE"},
+ {views::ImageButton::VerticalAlignment::ALIGN_BOTTOM, u"ALIGN_BOTTOM"})
diff --git a/chromium/ui/views/controls/button/image_button_factory.cc b/chromium/ui/views/controls/button/image_button_factory.cc
index 136c1313c69..0aa69638697 100644
--- a/chromium/ui/views/controls/button/image_button_factory.cc
+++ b/chromium/ui/views/controls/button/image_button_factory.cc
@@ -10,6 +10,7 @@
#include "ui/gfx/color_utils.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/vector_icon_types.h"
+#include "ui/gfx/vector_icon_utils.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/image_button.h"
@@ -45,7 +46,7 @@ class ColorTrackingVectorImageButton : public ImageButton {
std::unique_ptr<ImageButton> CreateVectorImageButtonWithNativeTheme(
Button::PressedCallback callback,
const gfx::VectorIcon& icon,
- base::Optional<int> dip_size) {
+ absl::optional<int> dip_size) {
auto button = std::make_unique<ColorTrackingVectorImageButton>(
std::move(callback), icon,
dip_size.value_or(GetDefaultSizeOfVectorIcon(icon)));
@@ -68,7 +69,7 @@ std::unique_ptr<ToggleImageButton> CreateVectorToggleImageButton(
}
void ConfigureVectorImageButton(ImageButton* button) {
- button->SetInkDropMode(Button::InkDropMode::ON);
+ button->ink_drop()->SetMode(views::InkDropHost::InkDropMode::ON);
button->SetHasInkDropActionOnClick(true);
button->SetImageHorizontalAlignment(ImageButton::ALIGN_CENTER);
button->SetImageVerticalAlignment(ImageButton::ALIGN_MIDDLE);
@@ -112,7 +113,7 @@ void SetImageFromVectorIconWithColor(ImageButton* button,
button->SetImage(Button::STATE_NORMAL, normal_image);
button->SetImage(Button::STATE_DISABLED, disabled_image);
- button->SetInkDropBaseColor(icon_color);
+ button->ink_drop()->SetBaseColor(icon_color);
}
void SetToggledImageFromVectorIconWithColor(ToggleImageButton* button,
diff --git a/chromium/ui/views/controls/button/image_button_factory.h b/chromium/ui/views/controls/button/image_button_factory.h
index 2360ff35d72..24c03e951bb 100644
--- a/chromium/ui/views/controls/button/image_button_factory.h
+++ b/chromium/ui/views/controls/button/image_button_factory.h
@@ -26,7 +26,7 @@ VIEWS_EXPORT std::unique_ptr<ImageButton>
CreateVectorImageButtonWithNativeTheme(
Button::PressedCallback callback,
const gfx::VectorIcon& icon,
- base::Optional<int> dip_size = base::nullopt);
+ absl::optional<int> dip_size = absl::nullopt);
// Creates an ImageButton with an ink drop and a centered image in preparation
// for applying a vector icon with SetImageFromVectorIcon below.
diff --git a/chromium/ui/views/controls/button/image_button_factory_unittest.cc b/chromium/ui/views/controls/button/image_button_factory_unittest.cc
index 40f4cc89f54..6dae681c7ac 100644
--- a/chromium/ui/views/controls/button/image_button_factory_unittest.cc
+++ b/chromium/ui/views/controls/button/image_button_factory_unittest.cc
@@ -33,7 +33,7 @@ TEST_F(ImageButtonFactoryTest, SetImageFromVectorIcon) {
EXPECT_FALSE(button->GetImage(Button::STATE_NORMAL).isNull());
EXPECT_FALSE(button->GetImage(Button::STATE_DISABLED).isNull());
EXPECT_EQ(color_utils::DeriveDefaultIconColor(SK_ColorRED),
- button->GetInkDropBaseColor());
+ button->ink_drop()->GetBaseColor());
}
class ImageButtonFactoryWidgetTest : public ViewsTestBase {
@@ -81,7 +81,7 @@ TEST_F(ImageButtonFactoryWidgetTest, CreateVectorImageButtonWithNativeTheme) {
Button::PressedCallback(), vector_icons::kCloseRoundedIcon));
EXPECT_EQ(button()->GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_DefaultIconColor),
- button()->GetInkDropBaseColor());
+ button()->ink_drop()->GetBaseColor());
}
TEST_F(ImageButtonFactoryWidgetTest,
diff --git a/chromium/ui/views/controls/button/label_button.cc b/chromium/ui/views/controls/button/label_button.cc
index 7e744be3c39..86ddd3569f4 100644
--- a/chromium/ui/views/controls/button/label_button.cc
+++ b/chromium/ui/views/controls/button/label_button.cc
@@ -14,6 +14,8 @@
#include "build/build_config.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/compositor/layer.h"
#include "ui/gfx/animation/throb_animation.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_utils.h"
@@ -25,7 +27,6 @@
#include "ui/views/background.h"
#include "ui/views/controls/button/label_button_border.h"
#include "ui/views/image_model_utils.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/painter.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/view_class_properties.h"
@@ -109,7 +110,7 @@ void LabelButton::SetTextColor(ButtonState for_state, SkColor color) {
explicitly_set_colors_[for_state] = true;
}
-void LabelButton::SetEnabledTextColors(base::Optional<SkColor> color) {
+void LabelButton::SetEnabledTextColors(absl::optional<SkColor> color) {
ButtonState states[] = {STATE_NORMAL, STATE_HOVERED, STATE_PRESSED};
if (color.has_value()) {
for (auto state : states)
@@ -416,7 +417,8 @@ ui::NativeTheme::State LabelButton::GetForegroundThemeState(
}
void LabelButton::UpdateImage() {
- image_->SetImage(GetImage(GetVisualState()));
+ if (GetWidget())
+ image_->SetImage(GetImage(GetVisualState()));
}
void LabelButton::AddLayerBeneathView(ui::Layer* new_layer) {
@@ -562,12 +564,20 @@ Button::ButtonState LabelButton::GetVisualState() const {
}
void LabelButton::VisualStateChanged() {
- UpdateImage();
- UpdateBackgroundColor();
+ if (GetWidget()) {
+ UpdateImage();
+ UpdateBackgroundColor();
+ }
label_->SetEnabled(GetVisualState() != STATE_DISABLED);
}
void LabelButton::ResetColorsFromNativeTheme() {
+ if (!GetWidget()) {
+ // If there is no widget, we can't actually get the real colors here.
+ // An OnThemeChanged() will fire once a widget is available.
+ return;
+ }
+
const ui::NativeTheme* theme = GetNativeTheme();
// Since this is a LabelButton, use the label colors.
SkColor colors[STATE_COUNT] = {
diff --git a/chromium/ui/views/controls/button/label_button.h b/chromium/ui/views/controls/button/label_button.h
index 1ad627bb786..a3b83cbd720 100644
--- a/chromium/ui/views/controls/button/label_button.h
+++ b/chromium/ui/views/controls/button/label_button.h
@@ -12,7 +12,7 @@
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/controls/button/button.h"
@@ -69,7 +69,7 @@ class VIEWS_EXPORT LabelButton : public Button, public NativeThemeDelegate {
void SetTextColor(ButtonState for_state, SkColor color);
// Sets the text colors shown for the non-disabled states to |color|.
- virtual void SetEnabledTextColors(base::Optional<SkColor> color);
+ virtual void SetEnabledTextColors(absl::optional<SkColor> color);
// Gets the current state text color.
SkColor GetCurrentTextColor() const;
diff --git a/chromium/ui/views/controls/button/label_button_label.cc b/chromium/ui/views/controls/button/label_button_label.cc
index dbdb4b0cb1d..16480657b41 100644
--- a/chromium/ui/views/controls/button/label_button_label.cc
+++ b/chromium/ui/views/controls/button/label_button_label.cc
@@ -4,7 +4,7 @@
#include "ui/views/controls/button/label_button_label.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
namespace views {
@@ -37,11 +37,13 @@ void LabelButtonLabel::OnEnabledChanged() {
}
void LabelButtonLabel::SetColorForEnableState() {
- const base::Optional<SkColor>& color =
+ const absl::optional<SkColor>& color =
GetEnabled() ? requested_enabled_color_ : requested_disabled_color_;
if (color) {
Label::SetEnabledColor(*color);
- } else {
+ } else if (GetWidget()) {
+ // If there is no widget, we can't actually get the colors here.
+ // An OnThemeChanged() will fire once a widget is available.
int style = GetEnabled() ? style::STYLE_PRIMARY : style::STYLE_DISABLED;
Label::SetEnabledColor(style::GetColor(*this, GetTextContext(), style));
}
diff --git a/chromium/ui/views/controls/button/label_button_label.h b/chromium/ui/views/controls/button/label_button_label.h
index 207336cf982..11f63159472 100644
--- a/chromium/ui/views/controls/button/label_button_label.h
+++ b/chromium/ui/views/controls/button/label_button_label.h
@@ -8,11 +8,11 @@
#include <string>
#include "base/bind.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/gfx/color_palette.h"
#include "ui/views/controls/label.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/views_export.h"
namespace views {
@@ -44,8 +44,8 @@ class VIEWS_EXPORT LabelButtonLabel : public Label {
void OnEnabledChanged();
void SetColorForEnableState();
- base::Optional<SkColor> requested_disabled_color_;
- base::Optional<SkColor> requested_enabled_color_;
+ absl::optional<SkColor> requested_disabled_color_;
+ absl::optional<SkColor> requested_enabled_color_;
base::CallbackListSubscription enabled_changed_subscription_ =
AddEnabledChangedCallback(
base::BindRepeating(&LabelButtonLabel::OnEnabledChanged,
diff --git a/chromium/ui/views/controls/button/label_button_unittest.cc b/chromium/ui/views/controls/button/label_button_unittest.cc
index 7ee64533580..187b0910c1c 100644
--- a/chromium/ui/views/controls/button/label_button_unittest.cc
+++ b/chromium/ui/views/controls/button/label_button_unittest.cc
@@ -150,26 +150,26 @@ TEST_F(LabelButtonTest, FocusBehavior) {
TEST_F(LabelButtonTest, Init) {
const std::u16string text(u"abc");
- TestLabelButton button(text);
+ button_->SetText(text);
- EXPECT_TRUE(button.GetImage(Button::STATE_NORMAL).isNull());
- EXPECT_TRUE(button.GetImage(Button::STATE_HOVERED).isNull());
- EXPECT_TRUE(button.GetImage(Button::STATE_PRESSED).isNull());
- EXPECT_TRUE(button.GetImage(Button::STATE_DISABLED).isNull());
+ EXPECT_TRUE(button_->GetImage(Button::STATE_NORMAL).isNull());
+ EXPECT_TRUE(button_->GetImage(Button::STATE_HOVERED).isNull());
+ EXPECT_TRUE(button_->GetImage(Button::STATE_PRESSED).isNull());
+ EXPECT_TRUE(button_->GetImage(Button::STATE_DISABLED).isNull());
- EXPECT_EQ(text, button.GetText());
+ EXPECT_EQ(text, button_->GetText());
ui::AXNodeData accessible_node_data;
- button.GetAccessibleNodeData(&accessible_node_data);
+ button_->GetAccessibleNodeData(&accessible_node_data);
EXPECT_EQ(ax::mojom::Role::kButton, accessible_node_data.role);
EXPECT_EQ(text, accessible_node_data.GetString16Attribute(
ax::mojom::StringAttribute::kName));
- EXPECT_FALSE(button.GetIsDefault());
- EXPECT_EQ(Button::STATE_NORMAL, button.GetState());
+ EXPECT_FALSE(button_->GetIsDefault());
+ EXPECT_EQ(Button::STATE_NORMAL, button_->GetState());
- EXPECT_EQ(button.image()->parent(), &button);
- EXPECT_EQ(button.label()->parent(), &button);
+ EXPECT_EQ(button_->image()->parent(), button_);
+ EXPECT_EQ(button_->label()->parent(), button_);
}
TEST_F(LabelButtonTest, Label) {
@@ -719,7 +719,7 @@ TEST_F(LabelButtonTest, SetEnabledTextColorsResetsToThemeColors) {
// Removing the enabled text color restore colors from the new theme, not
// the original colors used before the theme changed.
- button_->SetEnabledTextColors(base::nullopt);
+ button_->SetEnabledTextColors(absl::nullopt);
EXPECT_EQ(TestNativeTheme::kSystemColor, button_->label()->GetEnabledColor());
}
@@ -794,8 +794,8 @@ class InkDropLabelButtonTest : public ViewsTestBase {
Button::PressedCallback(), std::u16string()));
test_ink_drop_ = new test::TestInkDrop();
- test::InkDropHostViewTestApi(button_).SetInkDrop(
- base::WrapUnique(test_ink_drop_));
+ test::InkDropHostTestApi(button_->ink_drop())
+ .SetInkDrop(base::WrapUnique(test_ink_drop_));
}
void TearDown() override {
@@ -819,9 +819,9 @@ class InkDropLabelButtonTest : public ViewsTestBase {
TEST_F(InkDropLabelButtonTest, HoverStateAfterMouseEnterAndExitEvents) {
ui::test::EventGenerator event_generator(GetRootWindow(widget_.get()));
- const gfx::Point out_of_bounds_point(button_->bounds().bottom_right() +
- gfx::Vector2d(1, 1));
- const gfx::Point in_bounds_point(button_->bounds().CenterPoint());
+ const gfx::Point out_of_bounds_point(
+ button_->GetBoundsInScreen().bottom_right() + gfx::Vector2d(1, 1));
+ const gfx::Point in_bounds_point(button_->GetBoundsInScreen().CenterPoint());
event_generator.MoveMouseTo(out_of_bounds_point);
EXPECT_FALSE(test_ink_drop_->is_hovered());
@@ -874,7 +874,7 @@ class LabelButtonVisualStateTest : public test::WidgetTest {
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
params.parent = parent->GetNativeView();
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.activatable = Widget::InitParams::ACTIVATABLE_YES;
+ params.activatable = Widget::InitParams::Activatable::kYes;
child->Init(std::move(params));
child->SetContentsView(std::make_unique<View>());
return child;
diff --git a/chromium/ui/views/controls/button/md_text_button.cc b/chromium/ui/views/controls/button/md_text_button.cc
index 868a79a37bd..55345eb74c4 100644
--- a/chromium/ui/views/controls/button/md_text_button.cc
+++ b/chromium/ui/views/controls/button/md_text_button.cc
@@ -8,9 +8,11 @@
#include <utility>
#include <vector>
+#include "base/bind.h"
#include "base/i18n/case_conversion.h"
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h"
@@ -23,7 +25,6 @@
#include "ui/views/border.h"
#include "ui/views/controls/focus_ring.h"
#include "ui/views/layout/layout_provider.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/painter.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/style/typography.h"
@@ -34,9 +35,16 @@ MdTextButton::MdTextButton(PressedCallback callback,
const std::u16string& text,
int button_context)
: LabelButton(std::move(callback), text, button_context) {
- SetInkDropMode(InkDropMode::ON);
+ ink_drop()->SetMode(views::InkDropHost::InkDropMode::ON);
SetHasInkDropActionOnClick(true);
SetShowInkDropWhenHotTracked(true);
+ ink_drop()->SetBaseColorCallback(base::BindRepeating(
+ [](MdTextButton* host) {
+ return color_utils::DeriveDefaultIconColor(
+ host->label()->GetEnabledColor());
+ },
+ this));
+
SetCornerRadius(LayoutProvider::Get()->GetCornerRadiusMetric(Emphasis::kLow));
SetHorizontalAlignment(gfx::ALIGN_CENTER);
@@ -72,7 +80,7 @@ bool MdTextButton::GetProminent() const {
return is_prominent_;
}
-void MdTextButton::SetBgColorOverride(const base::Optional<SkColor>& color) {
+void MdTextButton::SetBgColorOverride(const absl::optional<SkColor>& color) {
if (color == bg_color_override_)
return;
bg_color_override_ = color;
@@ -80,7 +88,7 @@ void MdTextButton::SetBgColorOverride(const base::Optional<SkColor>& color) {
OnPropertyChanged(&bg_color_override_, kPropertyEffectsNone);
}
-base::Optional<SkColor> MdTextButton::GetBgColorOverride() const {
+absl::optional<SkColor> MdTextButton::GetBgColorOverride() const {
return bg_color_override_;
}
@@ -88,8 +96,8 @@ void MdTextButton::SetCornerRadius(float radius) {
if (corner_radius_ == radius)
return;
corner_radius_ = radius;
- SetInkDropSmallCornerRadius(corner_radius_);
- SetInkDropLargeCornerRadius(corner_radius_);
+ ink_drop()->SetSmallCornerRadius(corner_radius_);
+ ink_drop()->SetLargeCornerRadius(corner_radius_);
OnPropertyChanged(&corner_radius_, kPropertyEffectsPaint);
}
@@ -102,10 +110,6 @@ void MdTextButton::OnThemeChanged() {
UpdateColors();
}
-SkColor MdTextButton::GetInkDropBaseColor() const {
- return color_utils::DeriveDefaultIconColor(label()->GetEnabledColor());
-}
-
void MdTextButton::StateChanged(ButtonState old_state) {
LabelButton::StateChanged(old_state);
UpdateColors();
@@ -121,18 +125,18 @@ void MdTextButton::OnBlur() {
UpdateColors();
}
-void MdTextButton::SetEnabledTextColors(base::Optional<SkColor> color) {
+void MdTextButton::SetEnabledTextColors(absl::optional<SkColor> color) {
LabelButton::SetEnabledTextColors(std::move(color));
UpdateColors();
}
void MdTextButton::SetCustomPadding(
- const base::Optional<gfx::Insets>& padding) {
+ const absl::optional<gfx::Insets>& padding) {
custom_padding_ = padding;
UpdatePadding();
}
-base::Optional<gfx::Insets> MdTextButton::GetCustomPadding() const {
+absl::optional<gfx::Insets> MdTextButton::GetCustomPadding() const {
return custom_padding_.value_or(CalculateDefaultPadding());
}
@@ -253,16 +257,18 @@ void MdTextButton::UpdateBackgroundColor() {
}
void MdTextButton::UpdateColors() {
- UpdateTextColor();
- UpdateBackgroundColor();
- SchedulePaint();
+ if (GetWidget()) {
+ UpdateTextColor();
+ UpdateBackgroundColor();
+ SchedulePaint();
+ }
}
BEGIN_METADATA(MdTextButton, LabelButton)
ADD_PROPERTY_METADATA(bool, Prominent)
ADD_PROPERTY_METADATA(float, CornerRadius)
-ADD_PROPERTY_METADATA(base::Optional<SkColor>, BgColorOverride)
-ADD_PROPERTY_METADATA(base::Optional<gfx::Insets>, CustomPadding)
+ADD_PROPERTY_METADATA(absl::optional<SkColor>, BgColorOverride)
+ADD_PROPERTY_METADATA(absl::optional<gfx::Insets>, CustomPadding)
END_METADATA
} // namespace views
diff --git a/chromium/ui/views/controls/button/md_text_button.h b/chromium/ui/views/controls/button/md_text_button.h
index ebe4f966fe6..ee26cada0ff 100644
--- a/chromium/ui/views/controls/button/md_text_button.h
+++ b/chromium/ui/views/controls/button/md_text_button.h
@@ -7,7 +7,7 @@
#include <memory>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/focus_ring.h"
#include "ui/views/style/typography.h"
@@ -29,8 +29,8 @@ class VIEWS_EXPORT MdTextButton : public LabelButton {
bool GetProminent() const;
// See |bg_color_override_|.
- void SetBgColorOverride(const base::Optional<SkColor>& color);
- base::Optional<SkColor> GetBgColorOverride() const;
+ void SetBgColorOverride(const absl::optional<SkColor>& color);
+ absl::optional<SkColor> GetBgColorOverride() const;
// Override the default corner radius of the round rect used for the
// background and ink drop effects.
@@ -38,13 +38,12 @@ class VIEWS_EXPORT MdTextButton : public LabelButton {
float GetCornerRadius() const;
// See |custom_padding_|.
- void SetCustomPadding(const base::Optional<gfx::Insets>& padding);
- base::Optional<gfx::Insets> GetCustomPadding() const;
+ void SetCustomPadding(const absl::optional<gfx::Insets>& padding);
+ absl::optional<gfx::Insets> GetCustomPadding() const;
// LabelButton:
void OnThemeChanged() override;
- SkColor GetInkDropBaseColor() const override;
- void SetEnabledTextColors(base::Optional<SkColor> color) override;
+ void SetEnabledTextColors(absl::optional<SkColor> color) override;
void SetText(const std::u16string& text) override;
PropertyEffects UpdateStyleToIndicateDefaultStatus() override;
void StateChanged(ButtonState old_state) override;
@@ -66,21 +65,21 @@ class VIEWS_EXPORT MdTextButton : public LabelButton {
bool is_prominent_ = false;
// When set, this provides the background color.
- base::Optional<SkColor> bg_color_override_;
+ absl::optional<SkColor> bg_color_override_;
float corner_radius_ = 0.0f;
// Used to override default padding.
- base::Optional<gfx::Insets> custom_padding_;
+ absl::optional<gfx::Insets> custom_padding_;
DISALLOW_COPY_AND_ASSIGN(MdTextButton);
};
BEGIN_VIEW_BUILDER(VIEWS_EXPORT, MdTextButton, LabelButton)
VIEW_BUILDER_PROPERTY(bool, Prominent)
-VIEW_BUILDER_PROPERTY(base::Optional<SkColor>, BgColorOverride)
+VIEW_BUILDER_PROPERTY(absl::optional<SkColor>, BgColorOverride)
VIEW_BUILDER_PROPERTY(float, CornerRadius)
-VIEW_BUILDER_PROPERTY(base::Optional<gfx::Insets>, CustomPadding)
+VIEW_BUILDER_PROPERTY(absl::optional<gfx::Insets>, CustomPadding)
END_VIEW_BUILDER
} // namespace views
diff --git a/chromium/ui/views/controls/button/menu_button.cc b/chromium/ui/views/controls/button/menu_button.cc
index 3eece12e26a..bd20d922d9a 100644
--- a/chromium/ui/views/controls/button/menu_button.cc
+++ b/chromium/ui/views/controls/button/menu_button.cc
@@ -7,10 +7,11 @@
#include <memory>
#include <utility>
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/events/event.h"
#include "ui/views/controls/button/button_controller_delegate.h"
#include "ui/views/controls/button/menu_button_controller.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
+#include "ui/views/view_class_properties.h"
namespace views {
diff --git a/chromium/ui/views/controls/button/menu_button.h b/chromium/ui/views/controls/button/menu_button.h
index eedab1ae52b..a88c2f17930 100644
--- a/chromium/ui/views/controls/button/menu_button.h
+++ b/chromium/ui/views/controls/button/menu_button.h
@@ -7,8 +7,8 @@
#include <string>
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/controls/button/label_button.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/metadata/view_factory.h"
namespace views {
diff --git a/chromium/ui/views/controls/button/menu_button_controller.cc b/chromium/ui/views/controls/button/menu_button_controller.cc
index ee45a1bf1c3..785bba4b5f4 100644
--- a/chromium/ui/views/controls/button/menu_button_controller.cc
+++ b/chromium/ui/views/controls/button/menu_button_controller.cc
@@ -6,17 +6,21 @@
#include <utility>
+#include "base/bind.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/interaction/element_identifier.h"
#include "ui/events/event_constants.h"
#include "ui/events/types/event_type.h"
#include "ui/views/animation/ink_drop.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/button_controller_delegate.h"
#include "ui/views/controls/button/menu_button.h"
+#include "ui/views/interaction/element_tracker_views.h"
#include "ui/views/mouse_constants.h"
#include "ui/views/style/platform_style.h"
+#include "ui/views/view_class_properties.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"
@@ -108,7 +112,7 @@ bool MenuButtonController::OnMousePressed(const ui::MouseEvent& event) {
// If this is an unintentional trigger do not display the inkdrop.
if (!is_intentional_menu_trigger_)
- button()->AnimateInkDrop(InkDropState::HIDDEN, &event);
+ button()->ink_drop()->AnimateToState(InkDropState::HIDDEN, &event);
return true;
}
@@ -119,7 +123,7 @@ void MenuButtonController::OnMouseReleased(const ui::MouseEvent& event) {
Activate(&event);
} else {
if (button()->GetHideInkDropWhenShowingContextMenu())
- button()->AnimateInkDrop(InkDropState::HIDDEN, &event);
+ button()->ink_drop()->AnimateToState(InkDropState::HIDDEN, &event);
ButtonController::OnMouseReleased(event);
}
}
@@ -231,6 +235,15 @@ bool MenuButtonController::Activate(const ui::Event* event) {
bool increment_pressed_lock_called = false;
increment_pressed_lock_called_ = &increment_pressed_lock_called;
+ // Since regular Button logic isn't used, we need to instead notify that the
+ // menu button was activated here.
+ const ui::ElementIdentifier id =
+ button()->GetProperty(views::kElementIdentifierKey);
+ if (id) {
+ views::ElementTrackerViews::GetInstance()->NotifyViewActivated(id,
+ button());
+ }
+
// Allow for the button callback to delete this.
auto ref = weak_factory_.GetWeakPtr();
@@ -252,8 +265,8 @@ bool MenuButtonController::Activate(const ui::Event* event) {
increment_pressed_lock_called_ = nullptr;
if (!increment_pressed_lock_called && pressed_lock_count_ == 0) {
- button()->AnimateInkDrop(InkDropState::ACTION_TRIGGERED,
- ui::LocatedEvent::FromIfValid(event));
+ button()->ink_drop()->AnimateToState(
+ InkDropState::ACTION_TRIGGERED, ui::LocatedEvent::FromIfValid(event));
}
// We must return false here so that the RootView does not get stuck
@@ -262,8 +275,8 @@ bool MenuButtonController::Activate(const ui::Event* event) {
return false;
}
- button()->AnimateInkDrop(InkDropState::HIDDEN,
- ui::LocatedEvent::FromIfValid(event));
+ button()->ink_drop()->AnimateToState(InkDropState::HIDDEN,
+ ui::LocatedEvent::FromIfValid(event));
return true;
}
@@ -306,7 +319,7 @@ void MenuButtonController::IncrementPressedLocked(
if (snap_ink_drop_to_activated)
delegate()->GetInkDrop()->SnapToActivated();
else
- button()->AnimateInkDrop(InkDropState::ACTIVATED, event);
+ button()->ink_drop()->AnimateToState(InkDropState::ACTIVATED, event);
}
button()->SetState(Button::STATE_PRESSED);
delegate()->GetInkDrop()->SetHovered(false);
@@ -334,7 +347,8 @@ void MenuButtonController::DecrementPressedLocked() {
// The widget may be null during shutdown. If so, it doesn't make sense to
// try to add an ink drop effect.
if (button()->GetWidget() && button()->GetState() != Button::STATE_PRESSED)
- button()->AnimateInkDrop(InkDropState::DEACTIVATED, nullptr /* event */);
+ button()->ink_drop()->AnimateToState(InkDropState::DEACTIVATED,
+ nullptr /* event */);
}
}
diff --git a/chromium/ui/views/controls/button/menu_button_unittest.cc b/chromium/ui/views/controls/button/menu_button_unittest.cc
index 1b0383dbf26..8e935658156 100644
--- a/chromium/ui/views/controls/button/menu_button_unittest.cc
+++ b/chromium/ui/views/controls/button/menu_button_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
@@ -30,10 +31,11 @@
#include "ui/events/event_handler.h"
#endif
-using base::ASCIIToUTF16;
-
namespace views {
+using ::base::ASCIIToUTF16;
+using ::ui::mojom::DragOperation;
+
class TestMenuButton : public MenuButton {
public:
TestMenuButton()
@@ -115,7 +117,8 @@ class MenuButtonTest : public ViewsTestBase {
auto ink_drop = std::make_unique<test::TestInkDrop>();
ink_drop_ = ink_drop.get();
- test::InkDropHostViewTestApi(button_).SetInkDrop(std::move(ink_drop));
+ test::InkDropHostTestApi(button_->ink_drop())
+ .SetInkDrop(std::move(ink_drop));
widget_->Show();
}
@@ -189,12 +192,12 @@ class TestDragDropClient : public aura::client::DragDropClient,
~TestDragDropClient() override;
// aura::client::DragDropClient:
- int StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data,
- aura::Window* root_window,
- aura::Window* source_window,
- const gfx::Point& screen_location,
- int operation,
- ui::mojom::DragEventSource source) override;
+ DragOperation StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data,
+ aura::Window* root_window,
+ aura::Window* source_window,
+ const gfx::Point& screen_location,
+ int allowed_operations,
+ ui::mojom::DragEventSource source) override;
void DragCancel() override;
bool IsDragDropInProgress() override;
void AddObserver(aura::client::DragDropClientObserver* observer) override {}
@@ -216,18 +219,18 @@ TestDragDropClient::TestDragDropClient() = default;
TestDragDropClient::~TestDragDropClient() = default;
-int TestDragDropClient::StartDragAndDrop(
+DragOperation TestDragDropClient::StartDragAndDrop(
std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& screen_location,
- int operation,
+ int allowed_operations,
ui::mojom::DragEventSource source) {
if (IsDragDropInProgress())
- return ui::DragDropTypes::DRAG_NONE;
+ return DragOperation::kNone;
drag_in_progress_ = true;
target_ = root_window;
- return operation;
+ return ui::PreferredDragOperation(allowed_operations);
}
void TestDragDropClient::DragCancel() {
@@ -260,6 +263,7 @@ void TestDragDropClient::OnMouseEvent(ui::MouseEvent* event) {
TEST_F(MenuButtonTest, ActivateDropDownOnMouseClick) {
ConfigureMenuButton(std::make_unique<TestMenuButton>());
+ generator()->MoveMouseTo(button()->GetBoundsInScreen().CenterPoint());
generator()->ClickLeftButton();
EXPECT_TRUE(button()->clicked());
@@ -287,13 +291,15 @@ TEST_F(MenuButtonTest, ActivateOnKeyPress) {
TEST_F(MenuButtonTest, InkDropCenterSetFromClick) {
ConfigureMenuButton(std::make_unique<TestMenuButton>());
- gfx::Point click_point(6, 8);
+ const gfx::Point click_point = button()->GetBoundsInScreen().CenterPoint();
generator()->MoveMouseTo(click_point);
generator()->ClickLeftButton();
EXPECT_TRUE(button()->clicked());
- EXPECT_EQ(click_point, test::InkDropHostViewTestApi(button())
- .GetInkDropCenterBasedOnLastEvent());
+ gfx::Point inkdrop_center_point =
+ button()->ink_drop()->GetInkDropCenterBasedOnLastEvent();
+ View::ConvertPointToScreen(button(), &inkdrop_center_point);
+ EXPECT_EQ(click_point, inkdrop_center_point);
}
// Tests that the ink drop center point is set from the PressedLock constructor.
@@ -307,16 +313,17 @@ TEST_F(MenuButtonTest, InkDropCenterSetFromClickWithPressedLock) {
false, &click_event);
EXPECT_EQ(Button::STATE_PRESSED, button()->GetState());
- EXPECT_EQ(click_point, test::InkDropHostViewTestApi(button())
- .GetInkDropCenterBasedOnLastEvent());
+ EXPECT_EQ(click_point,
+ button()->ink_drop()->GetInkDropCenterBasedOnLastEvent());
}
// Test that the MenuButton stays pressed while there are any PressedLocks.
TEST_F(MenuButtonTest, ButtonStateForMenuButtonsWithPressedLocks) {
ConfigureMenuButton(std::make_unique<TestMenuButton>());
+ const gfx::Rect button_bounds = button()->GetBoundsInScreen();
// Move the mouse over the button; the button should be in a hovered state.
- generator()->MoveMouseTo(gfx::Point(10, 10));
+ generator()->MoveMouseTo(button_bounds.CenterPoint());
EXPECT_EQ(Button::STATE_HOVERED, button()->GetState());
// Introduce a PressedLock, which should make the button pressed.
@@ -325,7 +332,7 @@ TEST_F(MenuButtonTest, ButtonStateForMenuButtonsWithPressedLocks) {
EXPECT_EQ(Button::STATE_PRESSED, button()->GetState());
// Even if we move the mouse outside of the button, it should remain pressed.
- generator()->MoveMouseTo(gfx::Point(300, 10));
+ generator()->MoveMouseTo(button_bounds.bottom_right() + gfx::Vector2d(1, 1));
EXPECT_EQ(Button::STATE_PRESSED, button()->GetState());
// Creating a new lock should obviously keep the button pressed.
@@ -342,7 +349,7 @@ TEST_F(MenuButtonTest, ButtonStateForMenuButtonsWithPressedLocks) {
EXPECT_EQ(Button::STATE_NORMAL, button()->GetState());
// ...And it should respond to mouse movement again.
- generator()->MoveMouseTo(gfx::Point(10, 10));
+ generator()->MoveMouseTo(button_bounds.CenterPoint());
EXPECT_EQ(Button::STATE_HOVERED, button()->GetState());
// Test that the button returns to the appropriate state after the press; if
@@ -360,7 +367,7 @@ TEST_F(MenuButtonTest, ButtonStateForMenuButtonsWithPressedLocks) {
pressed_lock1.reset();
EXPECT_EQ(Button::STATE_DISABLED, button()->GetState());
- generator()->MoveMouseTo(gfx::Point(300, 10));
+ generator()->MoveMouseTo(button_bounds.bottom_right() + gfx::Vector2d(1, 1));
// Edge case: the button is disabled, a pressed lock is added, and then the
// button is re-enabled. It should be enabled after the lock is removed.
@@ -378,6 +385,7 @@ TEST_F(MenuButtonTest, DraggableMenuButtonActivatesOnRelease) {
TestDragController drag_controller;
button()->set_drag_controller(&drag_controller);
+ generator()->MoveMouseTo(button()->GetBoundsInScreen().CenterPoint());
generator()->PressLeftButton();
EXPECT_FALSE(button()->clicked());
@@ -493,7 +501,7 @@ TEST_F(MenuButtonTest, DraggableMenuButtonDoesNotActivateOnDrag) {
#endif // USE_AURA
// No touch on desktop Mac. Tracked in http://crbug.com/445520.
-#if !defined(OS_APPLE) || defined(USE_AURA)
+#if !defined(OS_MAC) || defined(USE_AURA)
// Tests if the callback is notified correctly when a gesture tap happens on a
// MenuButton that has a callback.
@@ -540,7 +548,7 @@ TEST_F(MenuButtonTest, TouchFeedbackDuringTapCancel) {
EXPECT_FALSE(button()->clicked());
}
-#endif // !defined(OS_APPLE) || defined(USE_AURA)
+#endif // !defined(OS_MAC) || defined(USE_AURA)
TEST_F(MenuButtonTest, InkDropHoverWhenShowingMenu) {
ConfigureMenuButton(std::make_unique<PressStateButton>(false));
@@ -548,7 +556,7 @@ TEST_F(MenuButtonTest, InkDropHoverWhenShowingMenu) {
generator()->MoveMouseTo(GetOutOfButtonLocation());
EXPECT_FALSE(ink_drop()->is_hovered());
- generator()->MoveMouseTo(button()->bounds().CenterPoint());
+ generator()->MoveMouseTo(button()->GetBoundsInScreen().CenterPoint());
EXPECT_TRUE(ink_drop()->is_hovered());
generator()->PressLeftButton();
@@ -560,7 +568,7 @@ TEST_F(MenuButtonTest, InkDropIsHoveredAfterDismissingMenuWhenMouseOverButton) {
auto* test_button = press_state_button.get();
ConfigureMenuButton(std::move(press_state_button));
- generator()->MoveMouseTo(button()->bounds().CenterPoint());
+ generator()->MoveMouseTo(button()->GetBoundsInScreen().CenterPoint());
generator()->PressLeftButton();
EXPECT_FALSE(ink_drop()->is_hovered());
test_button->ReleasePressedLock();
@@ -574,7 +582,7 @@ TEST_F(MenuButtonTest,
auto* test_button = press_state_button.get();
ConfigureMenuButton(std::move(press_state_button));
- generator()->MoveMouseTo(button()->bounds().CenterPoint());
+ generator()->MoveMouseTo(button()->GetBoundsInScreen().CenterPoint());
generator()->PressLeftButton();
generator()->MoveMouseTo(GetOutOfButtonLocation());
test_button->ReleasePressedLock();
diff --git a/chromium/ui/views/controls/button/radio_button.cc b/chromium/ui/views/controls/button/radio_button.cc
index c4073ae95e5..131a8d3ee34 100644
--- a/chromium/ui/views/controls/button/radio_button.cc
+++ b/chromium/ui/views/controls/button/radio_button.cc
@@ -7,20 +7,29 @@
#include "base/check.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/events/event_utils.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/paint_vector_icon.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/native_theme/native_theme.h"
#include "ui/views/resources/grit/views_resources.h"
#include "ui/views/vector_icons.h"
#include "ui/views/widget/widget.h"
namespace views {
+namespace {
+
+constexpr int kFocusRingRadius = 16;
+
+} // namespace
+
RadioButton::RadioButton(const std::u16string& label, int group_id)
: Checkbox(label) {
SetGroup(group_id);
+ focus_ring()->SetShouldPaintFocusAura(true);
}
RadioButton::~RadioButton() = default;
@@ -52,6 +61,11 @@ void RadioButton::OnFocus() {
SetChecked(true);
}
+void RadioButton::OnThemeChanged() {
+ Checkbox::OnThemeChanged();
+ SchedulePaint();
+}
+
void RadioButton::RequestFocusFromEvent() {
Checkbox::RequestFocusFromEvent();
// Take focus only if another radio button in the group has focus.
@@ -100,7 +114,8 @@ const gfx::VectorIcon& RadioButton::GetVectorIcon() const {
SkPath RadioButton::GetFocusRingPath() const {
SkPath path;
- path.addOval(gfx::RectToSkRect(image()->GetMirroredBounds()));
+ const gfx::Point center = image()->GetMirroredBounds().CenterPoint();
+ path.addCircle(center.x(), center.y(), kFocusRingRadius);
return path;
}
diff --git a/chromium/ui/views/controls/button/radio_button.h b/chromium/ui/views/controls/button/radio_button.h
index e0f9acea9ac..59fef945fa8 100644
--- a/chromium/ui/views/controls/button/radio_button.h
+++ b/chromium/ui/views/controls/button/radio_button.h
@@ -28,6 +28,7 @@ class VIEWS_EXPORT RadioButton : public Checkbox {
View* GetSelectedViewForGroup(int group) override;
bool IsGroupFocusTraversable() const override;
void OnFocus() override;
+ void OnThemeChanged() override;
// Overridden from Button:
void RequestFocusFromEvent() override;
diff --git a/chromium/ui/views/controls/button/toggle_button.cc b/chromium/ui/views/controls/button/toggle_button.cc
index 82a636b5f36..d648b8d86a0 100644
--- a/chromium/ui/views/controls/button/toggle_button.cc
+++ b/chromium/ui/views/controls/button/toggle_button.cc
@@ -8,10 +8,12 @@
#include <utility>
#include <vector>
+#include "base/bind.h"
#include "cc/paint/paint_flags.h"
#include "third_party/skia/include/core/SkDrawLooper.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h"
@@ -22,7 +24,6 @@
#include "ui/views/animation/ink_drop_ripple.h"
#include "ui/views/border.h"
#include "ui/views/controls/highlight_path_generator.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/painter.h"
namespace views {
@@ -39,10 +40,23 @@ constexpr int kThumbInset = 2;
} // namespace
+class ToggleButton::FocusRingHighlightPathGenerator
+ : public views::HighlightPathGenerator {
+ public:
+ SkPath GetHighlightPath(const views::View* view) override {
+ return static_cast<const ToggleButton*>(view)->GetFocusRingPath();
+ }
+};
+
// Class representing the thumb (the circle that slides horizontally).
-class ToggleButton::ThumbView : public InkDropHostView {
+class ToggleButton::ThumbView : public View {
public:
- ThumbView() { views::InstallEmptyHighlightPathGenerator(this); }
+ ThumbView() {
+ // Make the thumb behave as part of the parent for event handling.
+ SetCanProcessEventsWithinSubtree(false);
+ }
+ ThumbView(const ThumbView&) = delete;
+ ThumbView& operator=(const ThumbView&) = delete;
~ThumbView() override = default;
void Update(const gfx::Rect& bounds, float color_ratio) {
@@ -58,28 +72,20 @@ class ToggleButton::ThumbView : public InkDropHostView {
.Offset(gfx::Vector2d(kShadowOffsetX, kShadowOffsetY));
}
- void SetThumbColor(bool is_on, const base::Optional<SkColor>& thumb_color) {
+ void SetThumbColor(bool is_on, const absl::optional<SkColor>& thumb_color) {
(is_on ? thumb_on_color_ : thumb_off_color_) = thumb_color;
}
- base::Optional<SkColor> GetThumbColor(bool is_on) const {
+ absl::optional<SkColor> GetThumbColor(bool is_on) const {
return is_on ? thumb_on_color_ : thumb_off_color_;
}
- protected:
- // views::View:
- bool GetCanProcessEventsWithinSubtree() const override {
- // Make the thumb behave as part of the parent for event handling.
- return false;
- }
-
private:
static constexpr int kShadowOffsetX = 0;
static constexpr int kShadowOffsetY = 1;
static constexpr int kShadowBlur = 2;
// views::View:
-
void OnPaint(gfx::Canvas* canvas) override {
const float dsf = canvas->UndoDeviceScaleFactor();
const ui::NativeTheme* theme = GetNativeTheme();
@@ -113,13 +119,11 @@ class ToggleButton::ThumbView : public InkDropHostView {
}
// Colors used for the thumb, defaults to NativeTheme if not set explicitly.
- base::Optional<SkColor> thumb_on_color_;
- base::Optional<SkColor> thumb_off_color_;
+ absl::optional<SkColor> thumb_on_color_;
+ absl::optional<SkColor> thumb_off_color_;
// Color ratio between 0 and 1 that controls the thumb color.
float color_ratio_ = 0.0f;
-
- DISALLOW_COPY_AND_ASSIGN(ThumbView);
};
ToggleButton::ToggleButton(PressedCallback callback)
@@ -127,18 +131,35 @@ ToggleButton::ToggleButton(PressedCallback callback)
slide_animation_.SetSlideDuration(base::TimeDelta::FromMilliseconds(80));
slide_animation_.SetTweenType(gfx::Tween::LINEAR);
thumb_view_ = AddChildView(std::make_unique<ThumbView>());
- SetInkDropMode(InkDropMode::ON);
- // TODO(pbos): Update the highlight-path shape so that a FocusRing can be used
- // on top of it to increase contrast. Disabling it for now addresses a
- // regression in crbug.com/1031983, but a matching FocusRing would probably be
- // desirable.
- SetInstallFocusRingOnFocus(false);
+ ink_drop()->SetMode(views::InkDropHost::InkDropMode::ON);
+ // Do not set a clip, allow the ink drop to burst out.
+ // TODO(pbos): Consider an explicit InkDrop API to not use a clip rect / mask.
+ views::InstallEmptyHighlightPathGenerator(this);
SetHasInkDropActionOnClick(true);
+ views::InkDrop::UseInkDropForSquareRipple(ink_drop(),
+ /*highlight_on_hover=*/false);
+ ink_drop()->SetCreateRippleCallback(base::BindRepeating(
+ [](ToggleButton* host) {
+ gfx::Rect rect = host->thumb_view_->GetLocalBounds();
+ rect.Inset(-ThumbView::GetShadowOutsets());
+ return host->ink_drop()->CreateSquareRipple(rect.CenterPoint());
+ },
+ this));
+ ink_drop()->SetBaseColorCallback(base::BindRepeating(
+ [](ToggleButton* host) {
+ return host->GetTrackColor(host->GetIsOn() || host->HasFocus());
+ },
+ this));
+
+ SetInstallFocusRingOnFocus(true);
+ focus_ring()->SetPathGenerator(
+ std::make_unique<FocusRingHighlightPathGenerator>());
+ focus_ring()->SetShouldPaintFocusAura(true);
}
ToggleButton::~ToggleButton() {
// Destroying ink drop early allows ink drop layer to be properly removed,
- SetInkDropMode(InkDropMode::OFF);
+ ink_drop()->SetMode(views::InkDropHost::InkDropMode::OFF);
}
void ToggleButton::AnimateIsOn(bool is_on) {
@@ -164,38 +185,38 @@ bool ToggleButton::GetIsOn() const {
}
void ToggleButton::SetThumbOnColor(
- const base::Optional<SkColor>& thumb_on_color) {
+ const absl::optional<SkColor>& thumb_on_color) {
thumb_view_->SetThumbColor(true /* is_on */, thumb_on_color);
}
-base::Optional<SkColor> ToggleButton::GetThumbOnColor() const {
+absl::optional<SkColor> ToggleButton::GetThumbOnColor() const {
return thumb_view_->GetThumbColor(true);
}
void ToggleButton::SetThumbOffColor(
- const base::Optional<SkColor>& thumb_off_color) {
+ const absl::optional<SkColor>& thumb_off_color) {
thumb_view_->SetThumbColor(false /* is_on */, thumb_off_color);
}
-base::Optional<SkColor> ToggleButton::GetThumbOffColor() const {
+absl::optional<SkColor> ToggleButton::GetThumbOffColor() const {
return thumb_view_->GetThumbColor(false);
}
void ToggleButton::SetTrackOnColor(
- const base::Optional<SkColor>& track_on_color) {
+ const absl::optional<SkColor>& track_on_color) {
track_on_color_ = track_on_color;
}
-base::Optional<SkColor> ToggleButton::GetTrackOnColor() const {
+absl::optional<SkColor> ToggleButton::GetTrackOnColor() const {
return track_on_color_;
}
void ToggleButton::SetTrackOffColor(
- const base::Optional<SkColor>& track_off_color) {
+ const absl::optional<SkColor>& track_off_color) {
track_off_color_ = track_off_color;
}
-base::Optional<SkColor> ToggleButton::GetTrackOffColor() const {
+absl::optional<SkColor> ToggleButton::GetTrackOffColor() const {
return track_off_color_;
}
@@ -210,6 +231,15 @@ bool ToggleButton::GetAcceptsEvents() const {
return accepts_events_;
}
+void ToggleButton::AddLayerBeneathView(ui::Layer* layer) {
+ // Ink-drop layers should go underneath the ThumbView.
+ thumb_view_->AddLayerBeneathView(layer);
+}
+
+void ToggleButton::RemoveLayerBeneathView(ui::Layer* layer) {
+ thumb_view_->RemoveLayerBeneathView(layer);
+}
+
gfx::Size ToggleButton::CalculatePreferredSize() const {
gfx::Rect rect(kTrackSize);
rect.Inset(gfx::Insets(-kTrackVerticalMargin, -kTrackHorizontalMargin));
@@ -239,10 +269,16 @@ gfx::Rect ToggleButton::GetThumbBounds() const {
void ToggleButton::UpdateThumb() {
thumb_view_->Update(GetThumbBounds(),
static_cast<float>(slide_animation_.GetCurrentValue()));
+ if (focus_ring()) {
+ // Updating the thumb changes the result of GetFocusRingPath(), make sure
+ // the focus ring gets updated to match this new state.
+ focus_ring()->InvalidateLayout();
+ focus_ring()->SchedulePaint();
+ }
}
SkColor ToggleButton::GetTrackColor(bool is_on) const {
- base::Optional<SkColor> color = is_on ? track_on_color_ : track_off_color_;
+ absl::optional<SkColor> color = is_on ? track_on_color_ : track_off_color_;
return color.value_or(GetNativeTheme()->GetSystemColor(
is_on ? ui::NativeTheme::kColorId_ToggleButtonTrackColorOn
: ui::NativeTheme::kColorId_ToggleButtonTrackColorOff));
@@ -261,6 +297,14 @@ void ToggleButton::OnThemeChanged() {
SchedulePaint();
}
+SkPath ToggleButton::GetFocusRingPath() const {
+ SkPath path;
+ const gfx::Point center = GetThumbBounds().CenterPoint();
+ const int kFocusRingRadius = 16;
+ path.addCircle(center.x(), center.y(), kFocusRingRadius);
+ return path;
+}
+
void ToggleButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
Button::GetAccessibleNodeData(node_data);
@@ -271,17 +315,19 @@ void ToggleButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
void ToggleButton::OnFocus() {
Button::OnFocus();
- AnimateInkDrop(views::InkDropState::ACTION_PENDING, nullptr);
+ ink_drop()->AnimateToState(views::InkDropState::ACTION_PENDING, nullptr);
+ SchedulePaint();
}
void ToggleButton::OnBlur() {
Button::OnBlur();
// The ink drop may have already gone away if the user clicked after focusing.
- if (GetInkDrop()->GetTargetInkDropState() ==
+ if (ink_drop()->GetInkDrop()->GetTargetInkDropState() ==
views::InkDropState::ACTION_PENDING) {
- AnimateInkDrop(views::InkDropState::ACTION_TRIGGERED, nullptr);
+ ink_drop()->AnimateToState(views::InkDropState::ACTION_TRIGGERED, nullptr);
}
+ SchedulePaint();
}
void ToggleButton::NotifyClick(const ui::Event& event) {
@@ -290,8 +336,8 @@ void ToggleButton::NotifyClick(const ui::Event& event) {
// Skip over Button::NotifyClick, to customize the ink drop animation.
// Leave the ripple in place when the button is activated via the keyboard.
if (!event.IsKeyEvent()) {
- AnimateInkDrop(InkDropState::ACTION_TRIGGERED,
- ui::LocatedEvent::FromIfValid(&event));
+ ink_drop()->AnimateToState(InkDropState::ACTION_TRIGGERED,
+ ui::LocatedEvent::FromIfValid(&event));
}
Button::NotifyClick(event);
@@ -315,32 +361,6 @@ void ToggleButton::PaintButtonContents(gfx::Canvas* canvas) {
canvas->Restore();
}
-void ToggleButton::AddInkDropLayer(ui::Layer* ink_drop_layer) {
- thumb_view_->AddInkDropLayer(ink_drop_layer);
-}
-
-void ToggleButton::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
- thumb_view_->RemoveInkDropLayer(ink_drop_layer);
-}
-
-std::unique_ptr<InkDrop> ToggleButton::CreateInkDrop() {
- std::unique_ptr<InkDropImpl> ink_drop = Button::CreateDefaultInkDropImpl();
- ink_drop->SetShowHighlightOnHover(false);
- ink_drop->SetAutoHighlightMode(
- InkDropImpl::AutoHighlightMode::HIDE_ON_RIPPLE);
- return std::move(ink_drop);
-}
-
-std::unique_ptr<InkDropRipple> ToggleButton::CreateInkDropRipple() const {
- gfx::Rect rect = thumb_view_->GetLocalBounds();
- rect.Inset(-ThumbView::GetShadowOutsets());
- return CreateDefaultInkDropRipple(rect.CenterPoint());
-}
-
-SkColor ToggleButton::GetInkDropBaseColor() const {
- return GetTrackColor(GetIsOn() || HasFocus());
-}
-
void ToggleButton::AnimationProgressed(const gfx::Animation* animation) {
if (animation == &slide_animation_) {
// TODO(varkha, estade): The thumb is using its own view. Investigate if
@@ -355,10 +375,10 @@ void ToggleButton::AnimationProgressed(const gfx::Animation* animation) {
BEGIN_METADATA(ToggleButton, Button)
ADD_PROPERTY_METADATA(bool, IsOn)
ADD_PROPERTY_METADATA(bool, AcceptsEvents)
-ADD_PROPERTY_METADATA(base::Optional<SkColor>, ThumbOnColor)
-ADD_PROPERTY_METADATA(base::Optional<SkColor>, ThumbOffColor)
-ADD_PROPERTY_METADATA(base::Optional<SkColor>, TrackOnColor)
-ADD_PROPERTY_METADATA(base::Optional<SkColor>, TrackOffColor)
+ADD_PROPERTY_METADATA(absl::optional<SkColor>, ThumbOnColor)
+ADD_PROPERTY_METADATA(absl::optional<SkColor>, ThumbOffColor)
+ADD_PROPERTY_METADATA(absl::optional<SkColor>, TrackOnColor)
+ADD_PROPERTY_METADATA(absl::optional<SkColor>, TrackOffColor)
END_METADATA
} // namespace views
diff --git a/chromium/ui/views/controls/button/toggle_button.h b/chromium/ui/views/controls/button/toggle_button.h
index b734019edb4..bbda0ff3073 100644
--- a/chromium/ui/views/controls/button/toggle_button.h
+++ b/chromium/ui/views/controls/button/toggle_button.h
@@ -5,9 +5,7 @@
#ifndef UI_VIEWS_CONTROLS_BUTTON_TOGGLE_BUTTON_H_
#define UI_VIEWS_CONTROLS_BUTTON_TOGGLE_BUTTON_H_
-#include <memory>
-
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/animation/slide_animation.h"
#include "ui/views/controls/button/button.h"
@@ -28,23 +26,33 @@ class VIEWS_EXPORT ToggleButton : public Button {
void SetIsOn(bool is_on);
bool GetIsOn() const;
- void SetThumbOnColor(const base::Optional<SkColor>& thumb_on_color);
- base::Optional<SkColor> GetThumbOnColor() const;
- void SetThumbOffColor(const base::Optional<SkColor>& thumb_off_color);
- base::Optional<SkColor> GetThumbOffColor() const;
- void SetTrackOnColor(const base::Optional<SkColor>& track_on_color);
- base::Optional<SkColor> GetTrackOnColor() const;
- void SetTrackOffColor(const base::Optional<SkColor>& track_off_color);
- base::Optional<SkColor> GetTrackOffColor() const;
+ void SetThumbOnColor(const absl::optional<SkColor>& thumb_on_color);
+ absl::optional<SkColor> GetThumbOnColor() const;
+ void SetThumbOffColor(const absl::optional<SkColor>& thumb_off_color);
+ absl::optional<SkColor> GetThumbOffColor() const;
+ void SetTrackOnColor(const absl::optional<SkColor>& track_on_color);
+ absl::optional<SkColor> GetTrackOnColor() const;
+ void SetTrackOffColor(const absl::optional<SkColor>& track_off_color);
+ absl::optional<SkColor> GetTrackOffColor() const;
void SetAcceptsEvents(bool accepts_events);
bool GetAcceptsEvents() const;
// views::View:
+ void AddLayerBeneathView(ui::Layer* layer) override;
+ void RemoveLayerBeneathView(ui::Layer* layer) override;
gfx::Size CalculatePreferredSize() const override;
+ protected:
+ // views::View:
+ void OnThemeChanged() override;
+
+ // Returns the path to draw the focus ring around for this ToggleButton.
+ SkPath GetFocusRingPath() const;
+
private:
friend class TestToggleButton;
+ class FocusRingHighlightPathGenerator;
class ThumbView;
// Calculates and returns the bounding box for the track.
@@ -61,7 +69,6 @@ class VIEWS_EXPORT ToggleButton : public Button {
// views::View:
bool CanAcceptEvent(const ui::Event& event) override;
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
- void OnThemeChanged() override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
void OnFocus() override;
void OnBlur() override;
@@ -69,19 +76,14 @@ class VIEWS_EXPORT ToggleButton : public Button {
// Button:
void NotifyClick(const ui::Event& event) override;
void PaintButtonContents(gfx::Canvas* canvas) override;
- void AddInkDropLayer(ui::Layer* ink_drop_layer) override;
- void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override;
- std::unique_ptr<InkDrop> CreateInkDrop() override;
- std::unique_ptr<InkDropRipple> CreateInkDropRipple() const override;
- SkColor GetInkDropBaseColor() const override;
// gfx::AnimationDelegate:
void AnimationProgressed(const gfx::Animation* animation) override;
gfx::SlideAnimation slide_animation_{this};
ThumbView* thumb_view_;
- base::Optional<SkColor> track_on_color_;
- base::Optional<SkColor> track_off_color_;
+ absl::optional<SkColor> track_on_color_;
+ absl::optional<SkColor> track_off_color_;
// When false, this button won't accept input. Different from View::SetEnabled
// in that the view retains focus when this is false but not when disabled.
diff --git a/chromium/ui/views/controls/button/toggle_button_unittest.cc b/chromium/ui/views/controls/button/toggle_button_unittest.cc
index 4daacc1a21a..6f59963f917 100644
--- a/chromium/ui/views/controls/button/toggle_button_unittest.cc
+++ b/chromium/ui/views/controls/button/toggle_button_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "base/bind.h"
#include "base/macros.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -20,29 +21,28 @@ namespace views {
class TestToggleButton : public ToggleButton {
public:
explicit TestToggleButton(int* counter) : counter_(counter) {}
+
~TestToggleButton() override {
- // Calling SetInkDropMode() in this subclass allows this class's
- // implementation of RemoveInkDropLayer() to be called. The same
+ // Calling ink_drop()->SetMode() in this subclass allows this class's
+ // implementation of RemoveLayerBeneathView() to be called. The same
// call is made in ~ToggleButton() so this is testing the general technique.
- SetInkDropMode(InkDropMode::OFF);
+ ink_drop()->SetMode(views::InkDropHost::InkDropMode::OFF);
}
- using View::Focus;
-
- protected:
- // ToggleButton:
- void AddInkDropLayer(ui::Layer* ink_drop_layer) override {
+ void AddLayerBeneathView(ui::Layer* layer) override {
++(*counter_);
- ToggleButton::AddInkDropLayer(ink_drop_layer);
+ ToggleButton::AddLayerBeneathView(layer);
}
- void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override {
- ToggleButton::RemoveInkDropLayer(ink_drop_layer);
+ void RemoveLayerBeneathView(ui::Layer* layer) override {
--(*counter_);
+ ToggleButton::RemoveLayerBeneathView(layer);
}
+ using View::Focus;
+
private:
- int* counter_;
+ int* const counter_;
DISALLOW_COPY_AND_ASSIGN(TestToggleButton);
};
@@ -112,6 +112,7 @@ TEST_F(ToggleButtonTest, ShutdownWithFocus) {
TEST_F(ToggleButtonTest, AcceptEvents) {
EXPECT_FALSE(button()->GetIsOn());
ui::test::EventGenerator generator(GetRootWindow(widget()));
+ generator.MoveMouseTo(widget()->GetClientAreaBoundsInScreen().CenterPoint());
// Clicking toggles.
generator.ClickLeftButton();
diff --git a/chromium/ui/views/controls/combobox/combobox.cc b/chromium/ui/views/controls/combobox/combobox.cc
index b0e815c8d29..cc33eed057a 100644
--- a/chromium/ui/views/controls/combobox/combobox.cc
+++ b/chromium/ui/views/controls/combobox/combobox.cc
@@ -15,6 +15,7 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/ime/input_method.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/models/image_model.h"
#include "ui/base/models/menu_model.h"
#include "ui/base/ui_base_types.h"
@@ -39,7 +40,6 @@
#include "ui/views/controls/prefix_selector.h"
#include "ui/views/image_model_utils.h"
#include "ui/views/layout/layout_provider.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/mouse_constants.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/style/typography.h"
@@ -66,13 +66,26 @@ class TransparentButton : public Button {
button_controller()->set_notify_action(
ButtonController::NotifyAction::kOnPress);
- SetInkDropMode(InkDropMode::ON);
+ ink_drop()->SetMode(views::InkDropHost::InkDropMode::ON);
SetHasInkDropActionOnClick(true);
+ InkDrop::UseInkDropForSquareRipple(ink_drop(),
+ /*highlight_on_hover=*/false);
+ ink_drop()->SetCreateRippleCallback(base::BindRepeating(
+ [](Button* host) -> std::unique_ptr<views::InkDropRipple> {
+ return std::make_unique<views::FloodFillInkDropRipple>(
+ host->size(),
+ host->ink_drop()->GetInkDropCenterBasedOnLastEvent(),
+ host->GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_LabelEnabledColor),
+ host->ink_drop()->GetVisibleOpacity());
+ },
+ this));
}
+
~TransparentButton() override = default;
bool OnMousePressed(const ui::MouseEvent& mouse_event) override {
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// On Mac, comboboxes do not take focus on mouse click, but on other
// platforms they do.
parent()->RequestFocus();
@@ -84,27 +97,11 @@ class TransparentButton : public Button {
return hover_animation().GetCurrentValue();
}
- // Overridden from InkDropHost:
- std::unique_ptr<InkDrop> CreateInkDrop() override {
- std::unique_ptr<views::InkDropImpl> ink_drop = CreateDefaultInkDropImpl();
- ink_drop->SetShowHighlightOnHover(false);
- return std::move(ink_drop);
- }
-
- std::unique_ptr<InkDropRipple> CreateInkDropRipple() const override {
- return std::unique_ptr<views::InkDropRipple>(
- new views::FloodFillInkDropRipple(
- size(), GetInkDropCenterBasedOnLastEvent(),
- GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_LabelEnabledColor),
- GetInkDropVisibleOpacity()));
- }
-
private:
DISALLOW_COPY_AND_ASSIGN(TransparentButton);
};
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// Returns the next or previous valid index (depending on |increment|'s value).
// Skips separator or disabled indices. Returns -1 if there is no valid adjacent
// index.
@@ -240,7 +237,7 @@ Combobox::Combobox(ui::ComboboxModel* model, int text_context, int text_style)
base::BindRepeating(&Combobox::ArrowButtonPressed,
base::Unretained(this)))) {
SetModel(model);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
#else
SetFocusBehavior(FocusBehavior::ALWAYS);
@@ -273,6 +270,7 @@ const gfx::FontList& Combobox::GetFontList() const {
void Combobox::SetSelectedIndex(int index) {
if (selected_index_ == index)
return;
+ // TODO(pbos): Add (D)CHECKs to validate the selected index.
selected_index_ = index;
if (size_to_largest_label_) {
OnPropertyChanged(&selected_index_, kPropertyEffectsPaint);
@@ -282,6 +280,11 @@ void Combobox::SetSelectedIndex(int index) {
}
}
+base::CallbackListSubscription Combobox::AddSelectedIndexChangedCallback(
+ views::PropertyChangedCallback callback) {
+ return AddPropertyChangedCallback(&selected_index_, std::move(callback));
+}
+
bool Combobox::SelectValue(const std::u16string& value) {
for (int i = 0; i < GetModel()->GetItemCount(); ++i) {
if (value == GetModel()->GetItemAt(i)) {
@@ -422,15 +425,17 @@ bool Combobox::OnKeyPressed(const ui::KeyEvent& e) {
// TODO(oshima): handle IME.
DCHECK_EQ(e.type(), ui::ET_KEY_PRESSED);
+ // TODO(pbos): Do we need to handle selected_index_ == -1 for unselected here?
+ // Ditto on handling an empty model?
DCHECK_GE(selected_index_, 0);
DCHECK_LT(selected_index_, GetModel()->GetItemCount());
- if (selected_index_ < 0 || selected_index_ > GetModel()->GetItemCount())
+ if (selected_index_ < 0 || selected_index_ >= GetModel()->GetItemCount())
SetSelectedIndex(0);
bool show_menu = false;
int new_index = kNoSelection;
switch (e.key_code()) {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
case ui::VKEY_DOWN:
case ui::VKEY_UP:
case ui::VKEY_SPACE:
@@ -476,7 +481,7 @@ bool Combobox::OnKeyPressed(const ui::KeyEvent& e) {
case ui::VKEY_SPACE:
show_menu = true;
break;
-#endif // OS_APPLE
+#endif // OS_MAC
default:
return false;
}
@@ -610,10 +615,13 @@ void Combobox::PaintIconAndText(gfx::Canvas* canvas) {
// Draw the text.
SkColor text_color = GetTextColorForEnableState(*this, GetEnabled());
- if (selected_index_ < 0 || selected_index_ > GetModel()->GetItemCount()) {
- NOTREACHED();
+ // TODO(pbos): Do we need to handle selected_index_ == -1 for unselected here?
+ // Ditto on handling an empty model?
+ DCHECK_GE(selected_index_, 0);
+ DCHECK_LT(selected_index_, GetModel()->GetItemCount());
+ if (selected_index_ < 0 || selected_index_ >= GetModel()->GetItemCount())
SetSelectedIndex(0);
- }
+
std::u16string text = GetModel()->GetItemAt(selected_index_);
int disclosure_arrow_offset = width() - kComboboxArrowContainerWidth;
diff --git a/chromium/ui/views/controls/combobox/combobox.h b/chromium/ui/views/controls/combobox/combobox.h
index 303b9e5d9aa..2dccca063e2 100644
--- a/chromium/ui/views/controls/combobox/combobox.h
+++ b/chromium/ui/views/controls/combobox/combobox.h
@@ -71,6 +71,8 @@ class VIEWS_EXPORT Combobox : public View,
// Gets/Sets the selected index.
int GetSelectedIndex() const { return selected_index_; }
void SetSelectedIndex(int index);
+ base::CallbackListSubscription AddSelectedIndexChangedCallback(
+ views::PropertyChangedCallback callback) WARN_UNUSED_RESULT;
// Looks for the first occurrence of |value| in |model()|. If found, selects
// the found index and returns true. Otherwise simply noops and returns false.
diff --git a/chromium/ui/views/controls/combobox/combobox_unittest.cc b/chromium/ui/views/controls/combobox/combobox_unittest.cc
index 16d992a4acf..1369007bd87 100644
--- a/chromium/ui/views/controls/combobox/combobox_unittest.cc
+++ b/chromium/ui/views/controls/combobox/combobox_unittest.cc
@@ -285,7 +285,7 @@ class ComboboxTest : public ViewsTestBase {
DISALLOW_COPY_AND_ASSIGN(ComboboxTest);
};
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Tests whether the various Mac specific keyboard shortcuts invoke the dropdown
// menu or not.
TEST_F(ComboboxTest, KeyTestMac) {
@@ -359,7 +359,7 @@ TEST_F(ComboboxTest, DisabilityTest) {
// On Mac, key events can't change the currently selected index directly for a
// combobox.
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// Tests the behavior of various keyboard shortcuts on the currently selected
// index.
@@ -504,7 +504,7 @@ TEST_F(ComboboxTest, SkipMultipleSeparatorsAtEnd) {
PressKey(ui::VKEY_END);
EXPECT_EQ(6, combobox_->GetSelectedIndex());
}
-#endif // !OS_APPLE
+#endif // !OS_MAC
TEST_F(ComboboxTest, GetTextForRowTest) {
std::set<int> separators;
@@ -839,7 +839,7 @@ TEST_F(ComboboxTest, MenuModel) {
EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR,
menu_model->GetTypeAt(kSeparatorIndex));
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Comboboxes on Mac should have checkmarks, with the selected item checked,
EXPECT_EQ(ui::MenuModel::TYPE_CHECK, menu_model->GetTypeAt(0));
EXPECT_EQ(ui::MenuModel::TYPE_CHECK, menu_model->GetTypeAt(1));
diff --git a/chromium/ui/views/controls/dot_indicator.cc b/chromium/ui/views/controls/dot_indicator.cc
index d1b3e4410d8..413bd049125 100644
--- a/chromium/ui/views/controls/dot_indicator.cc
+++ b/chromium/ui/views/controls/dot_indicator.cc
@@ -7,12 +7,12 @@
#include <algorithm>
#include <utility>
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect_f.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace views {
diff --git a/chromium/ui/views/controls/editable_combobox/editable_combobox.cc b/chromium/ui/views/controls/editable_combobox/editable_combobox.cc
index 735c20a57b5..6c67ac9e705 100644
--- a/chromium/ui/views/controls/editable_combobox/editable_combobox.cc
+++ b/chromium/ui/views/controls/editable_combobox/editable_combobox.cc
@@ -19,6 +19,8 @@
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/ime/text_input_type.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/models/combobox_model.h"
#include "ui/base/models/combobox_model_observer.h"
#include "ui/base/models/menu_model.h"
@@ -52,8 +54,6 @@
#include "ui/views/layout/fill_layout.h"
#include "ui/views/layout/layout_manager.h"
#include "ui/views/layout/layout_provider.h"
-#include "ui/views/metadata/metadata_header_macros.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/style/typography.h"
#include "ui/views/view.h"
@@ -73,8 +73,23 @@ class Arrow : public Button {
button_controller()->set_notify_action(
ButtonController::NotifyAction::kOnPress);
- SetInkDropMode(InkDropMode::ON);
+ // TODO(pbos): Share ink-drop configuration code between here and
+ // Combobox's TransparentButton.
+ // Similar to Combobox's TransparentButton.
+ ink_drop()->SetMode(views::InkDropHost::InkDropMode::ON);
SetHasInkDropActionOnClick(true);
+ InkDrop::UseInkDropForSquareRipple(ink_drop(),
+ /*highlight_on_hover=*/false);
+ ink_drop()->SetCreateRippleCallback(base::BindRepeating(
+ [](Button* host) -> std::unique_ptr<views::InkDropRipple> {
+ return std::make_unique<views::FloodFillInkDropRipple>(
+ host->size(),
+ host->ink_drop()->GetInkDropCenterBasedOnLastEvent(),
+ style::GetColor(*host, style::CONTEXT_TEXTFIELD,
+ style::STYLE_PRIMARY),
+ host->ink_drop()->GetVisibleOpacity());
+ },
+ this));
}
Arrow(const Arrow&) = delete;
Arrow& operator=(const Arrow&) = delete;
@@ -84,23 +99,8 @@ class Arrow : public Button {
return hover_animation().GetCurrentValue();
}
- // Overridden from InkDropHost:
- // Similar to Combobox's TransparentButton.
- std::unique_ptr<InkDrop> CreateInkDrop() override {
- std::unique_ptr<views::InkDropImpl> ink_drop = CreateDefaultInkDropImpl();
- ink_drop->SetShowHighlightOnHover(false);
- return std::move(ink_drop);
- }
-
- // Similar to Combobox's TransparentButton.
- std::unique_ptr<InkDropRipple> CreateInkDropRipple() const override {
- return std::make_unique<views::FloodFillInkDropRipple>(
- size(), GetInkDropCenterBasedOnLastEvent(),
- style::GetColor(*this, style::CONTEXT_TEXTFIELD, style::STYLE_PRIMARY),
- GetInkDropVisibleOpacity());
- }
-
private:
+ // Button:
void PaintButtonContents(gfx::Canvas* canvas) override {
gfx::ScopedCanvas scoped_canvas(canvas);
canvas->ClipRect(GetContentsBounds());
@@ -151,14 +151,12 @@ class EditableCombobox::EditableComboboxMenuModel
if (!update_items_shown_enabled_)
return;
items_shown_.clear();
- items_shown_enabled_.clear();
if (show_on_empty_ || !owner_->GetText().empty()) {
for (int i = 0; i < combobox_model_->GetItemCount(); ++i) {
if (!filter_on_edit_ ||
base::StartsWith(combobox_model_->GetItemAt(i), owner_->GetText(),
base::CompareCase::INSENSITIVE_ASCII)) {
- items_shown_.push_back(combobox_model_->GetItemAt(i));
- items_shown_enabled_.push_back(combobox_model_->IsItemEnabledAt(i));
+ items_shown_.push_back({i, combobox_model_->IsItemEnabledAt(i)});
}
}
}
@@ -175,12 +173,18 @@ class EditableCombobox::EditableComboboxMenuModel
}
std::u16string GetItemTextAt(int index, bool showing_password_text) const {
+ int index_in_model = items_shown_[index].index;
+ std::u16string text = combobox_model_->GetItemAt(index_in_model);
return showing_password_text
- ? items_shown_[index]
- : std::u16string(items_shown_[index].length(),
+ ? text
+ : std::u16string(text.length(),
gfx::RenderText::kPasswordReplacementChar);
}
+ ui::ImageModel GetIconAt(int index) const override {
+ return combobox_model_->GetDropDownIconAt(items_shown_[index].index);
+ }
+
void OnComboboxModelChanged(ui::ComboboxModel* model) override {
UpdateItemsShown();
}
@@ -188,6 +192,10 @@ class EditableCombobox::EditableComboboxMenuModel
int GetItemCount() const override { return items_shown_.size(); }
private:
+ struct ShownItem {
+ size_t index;
+ bool enabled;
+ };
bool HasIcons() const override {
for (int i = 0; i < GetItemCount(); ++i) {
if (!GetIconAt(i).IsEmpty())
@@ -227,21 +235,19 @@ class EditableCombobox::EditableComboboxMenuModel
}
bool IsItemCheckedAt(int index) const override {
- return UseCheckmarks() && items_shown_[index] == owner_->GetText();
+ return UseCheckmarks() &&
+ combobox_model_->GetItemAt(items_shown_[index].index) ==
+ owner_->GetText();
}
int GetGroupIdAt(int index) const override { return -1; }
- ui::ImageModel GetIconAt(int index) const override {
- return combobox_model_->GetDropDownIconAt(index);
- }
-
ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override {
return nullptr;
}
bool IsEnabledAt(int index) const override {
- return items_shown_enabled_[index];
+ return items_shown_[index].enabled;
}
void ActivatedAt(int index) override { owner_->OnItemSelected(index); }
@@ -257,9 +263,9 @@ class EditableCombobox::EditableComboboxMenuModel
// Whether to show options when the textfield is empty.
const bool show_on_empty_;
- // The items from |combobox_model_| that we are currently showing.
- std::vector<std::u16string> items_shown_;
- std::vector<bool> items_shown_enabled_;
+ // The indices of the items from |combobox_model_| that we are currently
+ // showing, and whether they are enabled.
+ std::vector<ShownItem> items_shown_;
// When false, UpdateItemsShown doesn't do anything.
bool update_items_shown_enabled_ = true;
@@ -411,6 +417,10 @@ std::u16string EditableCombobox::GetItemForTest(int index) {
return menu_model_->GetItemTextAt(index, showing_password_text_);
}
+ui::ImageModel EditableCombobox::GetIconForTest(int index) {
+ return menu_model_->GetIconAt(index);
+}
+
void EditableCombobox::Layout() {
View::Layout();
if (arrow_) {
diff --git a/chromium/ui/views/controls/editable_combobox/editable_combobox.h b/chromium/ui/views/controls/editable_combobox/editable_combobox.h
index 5d9ac83a9ea..8f4744ef5e3 100644
--- a/chromium/ui/views/controls/editable_combobox/editable_combobox.h
+++ b/chromium/ui/views/controls/editable_combobox/editable_combobox.h
@@ -13,10 +13,11 @@
#include "base/macros.h"
#include "base/scoped_observation.h"
#include "build/build_config.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/models/image_model.h"
#include "ui/base/ui_base_types.h"
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/layout/animating_layout_manager.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/style/typography.h"
#include "ui/views/view.h"
#include "ui/views/view_observer.h"
@@ -108,6 +109,7 @@ class VIEWS_EXPORT EditableCombobox
ui::ComboboxModel* GetComboboxModelForTest() { return combobox_model_.get(); }
int GetItemCountForTest();
std::u16string GetItemForTest(int index);
+ ui::ImageModel GetIconForTest(int index);
MenuRunner* GetMenuRunnerForTest() { return menu_runner_.get(); }
Textfield* GetTextfieldForTest() { return textfield_; }
diff --git a/chromium/ui/views/controls/editable_combobox/editable_combobox_unittest.cc b/chromium/ui/views/controls/editable_combobox/editable_combobox_unittest.cc
index 6e49f076fc1..26ed4ab6851 100644
--- a/chromium/ui/views/controls/editable_combobox/editable_combobox_unittest.cc
+++ b/chromium/ui/views/controls/editable_combobox/editable_combobox_unittest.cc
@@ -27,6 +27,7 @@
#include "ui/events/types/event_type.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/image/image_unittest_util.h"
#include "ui/gfx/render_text.h"
#include "ui/views/context_menu_controller.h"
#include "ui/views/controls/menu/menu_runner.h"
@@ -37,6 +38,10 @@
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_utils.h"
+#if defined(USE_OZONE)
+#include "ui/events/ozone/layout/keyboard_layout_engine_test_utils.h"
+#endif
+
namespace views {
namespace {
@@ -68,6 +73,7 @@ class EditableComboboxTest : public ViewsTestBase {
public:
EditableComboboxTest() { views::test::DisableMenuClosureAnimations(); }
+ void SetUp() override;
void TearDown() override;
// Initializes the combobox with the given number of items.
@@ -82,6 +88,12 @@ class EditableComboboxTest : public ViewsTestBase {
bool show_on_empty = true,
EditableCombobox::Type type = EditableCombobox::Type::kRegular);
+ void InitEditableCombobox(
+ const std::vector<ui::SimpleComboboxModel::Item>& items,
+ bool filter_on_edit,
+ bool show_on_empty = true,
+ EditableCombobox::Type type = EditableCombobox::Type::kRegular);
+
// Initializes the widget where the combobox and the dummy control live.
void InitWidget();
@@ -123,6 +135,17 @@ class EditableComboboxTest : public ViewsTestBase {
DISALLOW_COPY_AND_ASSIGN(EditableComboboxTest);
};
+void EditableComboboxTest::SetUp() {
+ ViewsTestBase::SetUp();
+
+#if defined(USE_OZONE)
+ // TODO(crbug.com/1209477): Wayland bots use Weston with Headless backend that
+ // sets up XkbKeyboardLayoutEngine differently. When that is fixed, remove the
+ // workaround below.
+ ui::WaitUntilLayoutEngineIsReadyForTest();
+#endif
+}
+
void EditableComboboxTest::TearDown() {
if (IsMenuOpen()) {
combobox_->GetMenuRunnerForTest()->Cancel();
@@ -137,15 +160,26 @@ void EditableComboboxTest::TearDown() {
void EditableComboboxTest::InitEditableCombobox(const int item_count,
const bool filter_on_edit,
const bool show_on_empty) {
- std::vector<std::u16string> items;
+ std::vector<ui::SimpleComboboxModel::Item> items;
for (int i = 0; i < item_count; ++i)
- items.push_back(ASCIIToUTF16(base::StringPrintf("item[%i]", i)));
+ items.emplace_back(ASCIIToUTF16(base::StringPrintf("item[%i]", i)));
InitEditableCombobox(items, filter_on_edit, show_on_empty);
}
+void EditableComboboxTest::InitEditableCombobox(
+ const std::vector<std::u16string>& strings,
+ bool filter_on_edit,
+ bool show_on_empty,
+ EditableCombobox::Type type) {
+ std::vector<ui::SimpleComboboxModel::Item> items;
+ for (const auto& item_str : strings)
+ items.emplace_back(item_str);
+ InitEditableCombobox(items, filter_on_edit, show_on_empty, type);
+}
+
// Initializes the combobox with the given items.
void EditableComboboxTest::InitEditableCombobox(
- const std::vector<std::u16string>& items,
+ const std::vector<ui::SimpleComboboxModel::Item>& items,
const bool filter_on_edit,
const bool show_on_empty,
const EditableCombobox::Type type) {
@@ -180,7 +214,7 @@ void EditableComboboxTest::InitWidget() {
container->AddChildView(dummy_focusable_view_);
widget_->Show();
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// The event loop needs to be flushed here, otherwise in various tests:
// 1. The actual showing of the native window backing the widget gets delayed
// until a spin of the event loop.
@@ -252,7 +286,7 @@ void EditableComboboxTest::SendKeyEvent(ui::KeyboardCode key_code,
const bool alt,
const bool shift,
const bool ctrl_cmd) {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
bool command = ctrl_cmd;
bool control = false;
#else
@@ -389,7 +423,7 @@ TEST_F(EditableComboboxTest, EndOrHomeMovesToBeginningOrEndOfText) {
EXPECT_EQ(u"xabcy", combobox_->GetText());
}
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
TEST_F(EditableComboboxTest, AltLeftOrRightMovesToNextWords) {
InitEditableCombobox();
@@ -551,9 +585,15 @@ TEST_F(EditableComboboxTest, ClickOnMenuItemSelectsItAndClosesMenu) {
EXPECT_EQ(u"item[0]", combobox_->GetText());
}
+// This is failing on Linux (Ozone Wayland). https://crbug.com/1204302.
+#if defined(OS_LINUX)
+#define MAYBE_SpaceIsReflectedInTextfield DISABLED_SpaceIsReflectedInTextfield
+#else
+#define MAYBE_SpaceIsReflectedInTextfield SpaceIsReflectedInTextfield
+#endif
// This is different from the regular read-only Combobox, where SPACE
// opens/closes the menu.
-TEST_F(EditableComboboxTest, SpaceIsReflectedInTextfield) {
+TEST_F(EditableComboboxTest, MAYBE_SpaceIsReflectedInTextfield) {
InitEditableCombobox();
combobox_->GetTextfieldForTest()->RequestFocus();
SendKeyEvent(ui::VKEY_A);
@@ -563,8 +603,8 @@ TEST_F(EditableComboboxTest, SpaceIsReflectedInTextfield) {
EXPECT_EQ(u"a b", combobox_->GetText());
}
-#if defined(OS_WIN)
-// Flaky on Windows. https://crbug.com/965601
+#if defined(OS_WIN) || defined(OS_LINUX)
+// Flaky on Windows and Linux. https://crbug.com/965601
#define MAYBE_MenuCanAdaptToContentChange DISABLED_MenuCanAdaptToContentChange
#else
#define MAYBE_MenuCanAdaptToContentChange MenuCanAdaptToContentChange
@@ -599,7 +639,15 @@ TEST_F(EditableComboboxTest, MAYBE_MenuCanAdaptToContentChange) {
EXPECT_EQ(menu_runner1, menu_runner2);
}
-TEST_F(EditableComboboxTest, RefocusingReopensMenuBasedOnLatestContent) {
+#if defined(OS_LINUX)
+// Flaky on Linux. https://crbug.com/1204584
+#define MAYBE_RefocusingReopensMenuBasedOnLatestContent \
+ DISABLED_RefocusingReopensMenuBasedOnLatestContent
+#else
+#define MAYBE_RefocusingReopensMenuBasedOnLatestContent \
+ RefocusingReopensMenuBasedOnLatestContent
+#endif
+TEST_F(EditableComboboxTest, MAYBE_RefocusingReopensMenuBasedOnLatestContent) {
std::vector<std::u16string> items = {u"abc", u"abd", u"bac", u"bad", u"bac2"};
InitEditableCombobox(items, /*filter_on_edit=*/true);
combobox_->GetTextfieldForTest()->RequestFocus();
@@ -658,6 +706,34 @@ TEST_F(EditableComboboxTest, FilteringEffectOnGetItems) {
ASSERT_EQ(u"bad", combobox_->GetItemForTest(3));
}
+TEST_F(EditableComboboxTest, FilteringEffectOnIcons) {
+ ui::SimpleComboboxModel::Item item1(
+ u"abc", std::u16string(),
+ ui::ImageModel::FromImage(gfx::test::CreateImage(16, 16)));
+
+ ui::SimpleComboboxModel::Item item2(
+ u"def", std::u16string(),
+ ui::ImageModel::FromImage(gfx::test::CreateImage(20, 20)));
+
+ InitEditableCombobox({item1, item2},
+ /*filter_on_edit=*/true,
+ /*show_on_empty=*/true);
+
+ ASSERT_EQ(2, combobox_->GetItemCountForTest());
+ EXPECT_EQ(16,
+ combobox_->GetComboboxModelForTest()->GetIconAt(0).Size().width());
+ EXPECT_EQ(20,
+ combobox_->GetComboboxModelForTest()->GetIconAt(1).Size().width());
+
+ combobox_->SetText(u"a");
+ ASSERT_EQ(1, combobox_->GetItemCountForTest());
+ EXPECT_EQ(16, combobox_->GetIconForTest(0).Size().width());
+
+ combobox_->SetText(u"d");
+ ASSERT_EQ(1, combobox_->GetItemCountForTest());
+ EXPECT_EQ(20, combobox_->GetIconForTest(0).Size().width());
+}
+
TEST_F(EditableComboboxTest, FilteringWithMismatchedCase) {
std::vector<std::u16string> items = {u"AbCd", u"aBcD", u"xyz"};
InitEditableCombobox(items, /*filter_on_edit=*/true, /*show_on_empty=*/true);
@@ -802,7 +878,9 @@ TEST_F(EditableComboboxTest, DragToSelectDoesntOpenTheMenu) {
}
TEST_F(EditableComboboxTest, NoCrashWithoutWidget) {
- std::vector<std::u16string> items = {u"item0", u"item1"};
+ std::vector<ui::SimpleComboboxModel::Item> items = {
+ ui::SimpleComboboxModel::Item(u"item0"),
+ ui::SimpleComboboxModel::Item(u"item1")};
auto combobox = std::make_unique<EditableCombobox>(
std::make_unique<ui::SimpleComboboxModel>(items),
/*filter_on_edit=*/false,
diff --git a/chromium/ui/views/controls/focus_ring.cc b/chromium/ui/views/controls/focus_ring.cc
index 95d55d5347a..4bb8b51ae58 100644
--- a/chromium/ui/views/controls/focus_ring.cc
+++ b/chromium/ui/views/controls/focus_ring.cc
@@ -7,14 +7,18 @@
#include <memory>
#include <utility>
+#include "base/i18n/rtl.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/compositor/layer.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/skia_util.h"
#include "ui/views/controls/focusable_border.h"
#include "ui/views/controls/highlight_path_generator.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/view_class_properties.h"
#include "ui/views/view_utils.h"
@@ -76,6 +80,7 @@ FocusRing::~FocusRing() = default;
void FocusRing::SetPathGenerator(
std::unique_ptr<HighlightPathGenerator> generator) {
path_generator_ = std::move(generator);
+ InvalidateLayout();
SchedulePaint();
}
@@ -89,15 +94,30 @@ void FocusRing::SetHasFocusPredicate(const ViewPredicate& predicate) {
RefreshLayer();
}
-void FocusRing::SetColor(base::Optional<SkColor> color) {
+void FocusRing::SetColor(absl::optional<SkColor> color) {
color_ = color;
SchedulePaint();
}
+void FocusRing::SetShouldPaintFocusAura(bool should_paint_focus_aura) {
+ should_paint_focus_aura_ = should_paint_focus_aura;
+ SchedulePaint();
+}
+
void FocusRing::Layout() {
// The focus ring handles its own sizing, which is simply to fill the parent
// and extend a little beyond its borders.
gfx::Rect focus_bounds = parent()->GetLocalBounds();
+
+ // Make sure the focus-ring path fits.
+ // TODO(pbos): Chase down use cases where this path is not in a usable state
+ // by the time layout happens. This may be due to synchronous Layout() calls.
+ const SkPath path = GetPath();
+ if (IsPathUsable(path)) {
+ focus_bounds.Union(
+ gfx::ToEnclosingRect(gfx::SkRectToRectF(path.getBounds())));
+ }
+
focus_bounds.Inset(gfx::Insets(PlatformStyle::kFocusHaloInset));
SetBoundsRect(focus_bounds);
@@ -133,6 +153,18 @@ void FocusRing::OnPaint(gfx::Canvas* canvas) {
return;
}
+ const SkRRect ring_rect = GetRingRoundRect();
+
+ if (should_paint_focus_aura_) {
+ cc::PaintFlags flags;
+ flags.setAntiAlias(true);
+ flags.setColor(GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_FocusAuraColor));
+ flags.setStyle(cc::PaintFlags::kFill_Style);
+
+ canvas->sk_canvas()->drawRRect(ring_rect, flags);
+ }
+
cc::PaintFlags paint;
paint.setAntiAlias(true);
paint.setColor(color_.value_or(
@@ -140,30 +172,32 @@ void FocusRing::OnPaint(gfx::Canvas* canvas) {
paint.setStyle(cc::PaintFlags::kStroke_Style);
paint.setStrokeWidth(PlatformStyle::kFocusHaloThickness);
- SkPath path;
- if (path_generator_)
- path = path_generator_->GetHighlightPath(parent());
+ canvas->sk_canvas()->drawRRect(ring_rect, paint);
+}
- // If there's no path generator or the generated path is unusable, fall back
- // to the default.
- if (!IsPathUsable(path))
- path = GetHighlightPathInternal(parent());
+SkRRect FocusRing::GetRingRoundRect() const {
+ const SkPath path = GetPath();
DCHECK(IsPathUsable(path));
DCHECK_EQ(GetFlipCanvasOnPaintForRTLUI(),
parent()->GetFlipCanvasOnPaintForRTLUI());
+
SkRect bounds;
SkRRect rbounds;
- if (path.isRect(&bounds)) {
- canvas->sk_canvas()->drawRRect(RingRectFromPathRect(bounds), paint);
- } else if (path.isOval(&bounds)) {
+ if (path.isRect(&bounds))
+ return RingRectFromPathRect(bounds);
+
+ if (path.isOval(&bounds)) {
gfx::RectF rect = gfx::SkRectToRectF(bounds);
View::ConvertRectToTarget(parent(), this, &rect);
- canvas->sk_canvas()->drawRRect(SkRRect::MakeOval(gfx::RectFToSkRect(rect)),
- paint);
- } else if (path.isRRect(&rbounds)) {
- canvas->sk_canvas()->drawRRect(RingRectFromPathRect(rbounds), paint);
+ return SkRRect::MakeOval(gfx::RectFToSkRect(rect));
}
+
+ if (path.isRRect(&rbounds))
+ return RingRectFromPathRect(rbounds);
+
+ NOTREACHED();
+ return SkRRect();
}
void FocusRing::GetAccessibleNodeData(ui::AXNodeData* node_data) {
@@ -185,6 +219,19 @@ FocusRing::FocusRing() {
SetCanProcessEventsWithinSubtree(false);
}
+SkPath FocusRing::GetPath() const {
+ SkPath path;
+ if (path_generator_) {
+ path = path_generator_->GetHighlightPath(parent());
+ if (IsPathUsable(path))
+ return path;
+ }
+
+ // If there's no path generator or the generated path is unusable, fall back
+ // to the default.
+ return GetHighlightPathInternal(parent());
+}
+
void FocusRing::RefreshLayer() {
// TODO(pbos): This always keeps the layer alive if |has_focus_predicate_| is
// set. This is done because we're not notified when the predicate might
diff --git a/chromium/ui/views/controls/focus_ring.h b/chromium/ui/views/controls/focus_ring.h
index 7882505d6ec..86030abbb45 100644
--- a/chromium/ui/views/controls/focus_ring.h
+++ b/chromium/ui/views/controls/focus_ring.h
@@ -57,7 +57,11 @@ class VIEWS_EXPORT FocusRing : public View, public ViewObserver {
// focus, but the FocusRing sits on the parent instead of the inner view.
void SetHasFocusPredicate(const ViewPredicate& predicate);
- void SetColor(base::Optional<SkColor> color);
+ void SetColor(absl::optional<SkColor> color);
+
+ // Sets |should_paint_focus_aura_| and repaints the focus ring so that it may
+ // or may not include the focus aura.
+ void SetShouldPaintFocusAura(bool should_paint_focus_aura);
// View:
void Layout() override;
@@ -73,6 +77,9 @@ class VIEWS_EXPORT FocusRing : public View, public ViewObserver {
private:
FocusRing();
+ SkPath GetPath() const;
+ SkRRect GetRingRoundRect() const;
+
void RefreshLayer();
// Translates the provided SkRect or SkRRect, which is in the parent's
@@ -90,11 +97,16 @@ class VIEWS_EXPORT FocusRing : public View, public ViewObserver {
// the focus ring shows an invalid appearance (usually a different color).
bool invalid_ = false;
+ // If true, paint the focus aura (the inside area of the focus ring) with the
+ // color |kColorId_FocusAuraColor|. The focus aura is not painted by default
+ // and can be painted or unpainted by SetShouldSetFocusAura.
+ bool should_paint_focus_aura_ = false;
+
// Overriding color for the focus ring.
- base::Optional<SkColor> color_;
+ absl::optional<SkColor> color_;
// The predicate used to determine whether the parent has focus.
- base::Optional<ViewPredicate> has_focus_predicate_;
+ absl::optional<ViewPredicate> has_focus_predicate_;
base::ScopedObservation<View, ViewObserver> view_observation_{this};
diff --git a/chromium/ui/views/controls/focusable_border.cc b/chromium/ui/views/controls/focusable_border.cc
index d71c9e1f839..75de2c315ee 100644
--- a/chromium/ui/views/controls/focusable_border.cc
+++ b/chromium/ui/views/controls/focusable_border.cc
@@ -28,7 +28,7 @@ FocusableBorder::FocusableBorder() : insets_(kInsetSize) {}
FocusableBorder::~FocusableBorder() = default;
void FocusableBorder::SetColorId(
- const base::Optional<ui::NativeTheme::ColorId>& color_id) {
+ const absl::optional<ui::NativeTheme::ColorId>& color_id) {
override_color_id_ = color_id;
}
diff --git a/chromium/ui/views/controls/focusable_border.h b/chromium/ui/views/controls/focusable_border.h
index 5cfbc7f8bb6..2e2e3e0be81 100644
--- a/chromium/ui/views/controls/focusable_border.h
+++ b/chromium/ui/views/controls/focusable_border.h
@@ -7,7 +7,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/border.h"
#include "ui/views/view.h"
@@ -33,7 +33,7 @@ class VIEWS_EXPORT FocusableBorder : public Border {
// Sets the color id to use for this border. When unsupplied, the color will
// depend on the focus state.
- void SetColorId(const base::Optional<ui::NativeTheme::ColorId>& color_id);
+ void SetColorId(const absl::optional<ui::NativeTheme::ColorId>& color_id);
// Overridden from Border:
void Paint(const View& view, gfx::Canvas* canvas) override;
@@ -46,7 +46,7 @@ class VIEWS_EXPORT FocusableBorder : public Border {
private:
gfx::Insets insets_;
- base::Optional<ui::NativeTheme::ColorId> override_color_id_;
+ absl::optional<ui::NativeTheme::ColorId> override_color_id_;
DISALLOW_COPY_AND_ASSIGN(FocusableBorder);
};
diff --git a/chromium/ui/views/controls/highlight_path_generator.cc b/chromium/ui/views/controls/highlight_path_generator.cc
index 7899b1affc0..fd7ebce92ec 100644
--- a/chromium/ui/views/controls/highlight_path_generator.cc
+++ b/chromium/ui/views/controls/highlight_path_generator.cc
@@ -30,26 +30,26 @@ void HighlightPathGenerator::Install(
}
// static
-base::Optional<gfx::RRectF> HighlightPathGenerator::GetRoundRectForView(
+absl::optional<gfx::RRectF> HighlightPathGenerator::GetRoundRectForView(
const View* view) {
HighlightPathGenerator* path_generator =
view->GetProperty(kHighlightPathGeneratorKey);
- return path_generator ? path_generator->GetRoundRect(view) : base::nullopt;
+ return path_generator ? path_generator->GetRoundRect(view) : absl::nullopt;
}
SkPath HighlightPathGenerator::GetHighlightPath(const View* view) {
// A rounded rectangle must be supplied if using this default implementation.
- base::Optional<gfx::RRectF> round_rect = GetRoundRect(view);
+ absl::optional<gfx::RRectF> round_rect = GetRoundRect(view);
DCHECK(round_rect);
return SkPath().addRRect(SkRRect{*round_rect});
}
-base::Optional<gfx::RRectF> HighlightPathGenerator::GetRoundRect(
+absl::optional<gfx::RRectF> HighlightPathGenerator::GetRoundRect(
const gfx::RectF& rect) {
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<gfx::RRectF> HighlightPathGenerator::GetRoundRect(
+absl::optional<gfx::RRectF> HighlightPathGenerator::GetRoundRect(
const View* view) {
gfx::Rect bounds =
use_contents_bounds_ ? view->GetContentsBounds() : view->GetLocalBounds();
@@ -59,7 +59,7 @@ base::Optional<gfx::RRectF> HighlightPathGenerator::GetRoundRect(
return GetRoundRect(gfx::RectF(bounds));
}
-base::Optional<gfx::RRectF> EmptyHighlightPathGenerator::GetRoundRect(
+absl::optional<gfx::RRectF> EmptyHighlightPathGenerator::GetRoundRect(
const gfx::RectF& rect) {
return gfx::RRectF();
}
@@ -69,7 +69,7 @@ void InstallEmptyHighlightPathGenerator(View* view) {
view, std::make_unique<EmptyHighlightPathGenerator>());
}
-base::Optional<gfx::RRectF> RectHighlightPathGenerator::GetRoundRect(
+absl::optional<gfx::RRectF> RectHighlightPathGenerator::GetRoundRect(
const gfx::RectF& rect) {
return gfx::RRectF(rect);
}
@@ -83,7 +83,7 @@ CircleHighlightPathGenerator::CircleHighlightPathGenerator(
const gfx::Insets& insets)
: HighlightPathGenerator(insets) {}
-base::Optional<gfx::RRectF> CircleHighlightPathGenerator::GetRoundRect(
+absl::optional<gfx::RRectF> CircleHighlightPathGenerator::GetRoundRect(
const gfx::RectF& rect) {
gfx::RectF bounds = rect;
const float corner_radius = std::min(bounds.width(), bounds.height()) / 2.f;
@@ -102,7 +102,7 @@ void InstallCircleHighlightPathGenerator(View* view,
view, std::make_unique<CircleHighlightPathGenerator>(insets));
}
-base::Optional<gfx::RRectF> PillHighlightPathGenerator::GetRoundRect(
+absl::optional<gfx::RRectF> PillHighlightPathGenerator::GetRoundRect(
const gfx::RectF& rect) {
gfx::RectF bounds = rect;
const float corner_radius = std::min(bounds.width(), bounds.height()) / 2.f;
@@ -118,7 +118,7 @@ FixedSizeCircleHighlightPathGenerator::FixedSizeCircleHighlightPathGenerator(
int radius)
: radius_(radius) {}
-base::Optional<gfx::RRectF> FixedSizeCircleHighlightPathGenerator::GetRoundRect(
+absl::optional<gfx::RRectF> FixedSizeCircleHighlightPathGenerator::GetRoundRect(
const gfx::RectF& rect) {
gfx::RectF bounds = rect;
bounds.ClampToCenteredSize(gfx::SizeF(radius_ * 2, radius_ * 2));
@@ -135,7 +135,7 @@ RoundRectHighlightPathGenerator::RoundRectHighlightPathGenerator(
int corner_radius)
: HighlightPathGenerator(insets), corner_radius_(corner_radius) {}
-base::Optional<gfx::RRectF> RoundRectHighlightPathGenerator::GetRoundRect(
+absl::optional<gfx::RRectF> RoundRectHighlightPathGenerator::GetRoundRect(
const gfx::RectF& rect) {
return gfx::RRectF(rect, corner_radius_);
}
diff --git a/chromium/ui/views/controls/highlight_path_generator.h b/chromium/ui/views/controls/highlight_path_generator.h
index f5415715209..fcb260f3ab9 100644
--- a/chromium/ui/views/controls/highlight_path_generator.h
+++ b/chromium/ui/views/controls/highlight_path_generator.h
@@ -7,7 +7,7 @@
#include <memory>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -35,7 +35,7 @@ class VIEWS_EXPORT HighlightPathGenerator {
static void Install(View* host,
std::unique_ptr<HighlightPathGenerator> generator);
- static base::Optional<gfx::RRectF> GetRoundRectForView(const View* view);
+ static absl::optional<gfx::RRectF> GetRoundRectForView(const View* view);
// TODO(http://crbug.com/1056490): Deprecate |GetHighlightPath()| in favor of
// |GetRoundRect()|.
@@ -45,8 +45,8 @@ class VIEWS_EXPORT HighlightPathGenerator {
// highlight. Note that |rect| is in the coordinate system of the view.
// TODO(http://crbug.com/1056490): Once |GetHighlightPath()| is deprecated,
// make this a pure virtual function and make the return not optional.
- virtual base::Optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect);
- base::Optional<gfx::RRectF> GetRoundRect(const View* view);
+ virtual absl::optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect);
+ absl::optional<gfx::RRectF> GetRoundRect(const View* view);
void set_use_contents_bounds(bool use_contents_bounds) {
use_contents_bounds_ = use_contents_bounds;
@@ -83,7 +83,7 @@ class VIEWS_EXPORT EmptyHighlightPathGenerator : public HighlightPathGenerator {
delete;
// HighlightPathGenerator:
- base::Optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override;
+ absl::optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override;
};
void VIEWS_EXPORT InstallEmptyHighlightPathGenerator(View* view);
@@ -98,7 +98,7 @@ class VIEWS_EXPORT RectHighlightPathGenerator : public HighlightPathGenerator {
delete;
// HighlightPathGenerator:
- base::Optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override;
+ absl::optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override;
};
void VIEWS_EXPORT InstallRectHighlightPathGenerator(View* view);
@@ -114,7 +114,7 @@ class VIEWS_EXPORT CircleHighlightPathGenerator
delete;
// HighlightPathGenerator:
- base::Optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override;
+ absl::optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override;
};
void VIEWS_EXPORT InstallCircleHighlightPathGenerator(View* view);
@@ -131,7 +131,7 @@ class VIEWS_EXPORT PillHighlightPathGenerator : public HighlightPathGenerator {
delete;
// HighlightPathGenerator:
- base::Optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override;
+ absl::optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override;
};
void VIEWS_EXPORT InstallPillHighlightPathGenerator(View* view);
@@ -148,7 +148,7 @@ class VIEWS_EXPORT FixedSizeCircleHighlightPathGenerator
const FixedSizeCircleHighlightPathGenerator&) = delete;
// HighlightPathGenerator:
- base::Optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override;
+ absl::optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override;
private:
const int radius_;
@@ -169,7 +169,7 @@ class VIEWS_EXPORT RoundRectHighlightPathGenerator
const RoundRectHighlightPathGenerator&) = delete;
// HighlightPathGenerator:
- base::Optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override;
+ absl::optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override;
private:
const int corner_radius_;
diff --git a/chromium/ui/views/controls/image_view.cc b/chromium/ui/views/controls/image_view.cc
index 5cba06ef133..de82fb1fe47 100644
--- a/chromium/ui/views/controls/image_view.cc
+++ b/chromium/ui/views/controls/image_view.cc
@@ -7,21 +7,26 @@
#include <utility>
#include "base/check_op.h"
+#include "base/i18n/rtl.h"
+#include "base/numerics/safe_conversions.h"
#include "cc/paint/paint_flags.h"
#include "skia/ext/image_operations.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/canvas.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/native_theme/themed_vector_icon.h"
+#include "ui/views/image_model_utils.h"
namespace views {
namespace {
// Returns the pixels for the bitmap in |image| at scale |image_scale|.
-void* GetBitmapPixels(const gfx::ImageSkia& img, float image_scale) {
+void* GetBitmapPixels(const gfx::ImageSkia& image, float image_scale) {
DCHECK_NE(0.0f, image_scale);
- return img.GetRepresentation(image_scale).GetBitmap().getPixels();
+ return image.GetRepresentation(image_scale).GetBitmap().getPixels();
}
} // namespace
@@ -30,28 +35,18 @@ ImageView::ImageView() = default;
ImageView::~ImageView() = default;
-void ImageView::SetImage(const gfx::ImageSkia& img) {
- if (IsImageEqual(img))
+void ImageView::SetImage(const ui::ImageModel& image_model) {
+ if (IsImageEqual(image_model))
return;
- last_painted_bitmap_pixels_ = nullptr;
- gfx::Size pref_size(GetPreferredSize());
- image_ = img;
+ const gfx::Size pref_size = GetPreferredSize();
+ image_model_ = image_model;
scaled_image_ = gfx::ImageSkia();
if (pref_size != GetPreferredSize())
PreferredSizeChanged();
SchedulePaint();
}
-void ImageView::SetImage(const gfx::ImageSkia* image_skia) {
- if (image_skia) {
- SetImage(*image_skia);
- } else {
- gfx::ImageSkia t;
- SetImage(t);
- }
-}
-
void ImageView::SetImageSize(const gfx::Size& image_size) {
image_size_ = image_size;
PreferredSizeChanged();
@@ -66,8 +61,8 @@ gfx::Rect ImageView::GetImageBounds() const {
return gfx::Rect(image_origin_, GetImageSize());
}
-const gfx::ImageSkia& ImageView::GetImage() const {
- return image_;
+gfx::ImageSkia ImageView::GetImage() const {
+ return views::GetImageSkiaFromImageModel(image_model_, GetNativeTheme());
}
void ImageView::SetHorizontalAlignment(Alignment alignment) {
@@ -115,14 +110,22 @@ const std::u16string& ImageView::GetTooltipText() const {
return tooltip_text_;
}
-bool ImageView::IsImageEqual(const gfx::ImageSkia& img) const {
- // Even though we copy ImageSkia in SetImage() the backing store
- // (ImageSkiaStorage) is not copied and may have changed since the last call
- // to SetImage(). The expectation is that SetImage() with different pixels is
- // treated as though the image changed. For this reason we compare not only
- // the backing store but also the pixels of the last image we painted.
- return image_.BackedBySameObjectAs(img) && last_paint_scale_ != 0.0f &&
- last_painted_bitmap_pixels_ == GetBitmapPixels(img, last_paint_scale_);
+bool ImageView::IsImageEqual(const ui::ImageModel& image_model) const {
+ if (image_model != image_model_)
+ return false;
+
+ if (!image_model.IsImage())
+ return true;
+
+ // An ImageModel's Image holds a handle to a backing store, which may have
+ // changed since the last call to SetImage(). The expectation is that
+ // SetImage() with different pixels is treated as though the image changed.
+ // For this reason we compare not only the Image but also the pixels we last
+ // painted.
+ return last_paint_scale_ != 0.0f &&
+ last_painted_bitmap_pixels_ ==
+ GetBitmapPixels(image_model.GetImage().AsImageSkia(),
+ last_paint_scale_);
}
void ImageView::UpdateImageOrigin() {
@@ -169,7 +172,7 @@ void ImageView::UpdateImageOrigin() {
}
gfx::Size ImageView::GetImageSize() const {
- return image_size_.value_or(image_.size());
+ return image_size_.value_or(image_model_.Size());
}
void ImageView::OnPaint(gfx::Canvas* canvas) {
@@ -180,7 +183,7 @@ void ImageView::OnPaint(gfx::Canvas* canvas) {
void ImageView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
const std::u16string& name = GetAccessibleName();
if (name.empty()) {
- node_data->role = ax::mojom::Role::kIgnored;
+ node_data->role = ax::mojom::Role::kNone;
return;
}
@@ -220,6 +223,14 @@ void ImageView::PreferredSizeChanged() {
UpdateImageOrigin();
}
+void ImageView::OnThemeChanged() {
+ View::OnThemeChanged();
+ if (!image_model_.IsVectorIcon() || image_model_.GetVectorIcon().has_color())
+ return; // Bitmaps don't need updating on theme changes.
+ scaled_image_ = gfx::ImageSkia();
+ SchedulePaint();
+}
+
void ImageView::OnPaintImage(gfx::Canvas* canvas) {
last_paint_scale_ = canvas->image_scale();
last_painted_bitmap_pixels_ = nullptr;
@@ -247,34 +258,38 @@ void ImageView::OnPaintImage(gfx::Canvas* canvas) {
}
gfx::ImageSkia ImageView::GetPaintImage(float scale) {
- if (image_.isNull())
- return image_;
-
- const gfx::ImageSkiaRep& rep = image_.GetRepresentation(scale);
- if (rep.scale() == scale)
- return image_;
-
- if (scaled_image_.HasRepresentation(scale))
- return scaled_image_;
-
- // Only caches one image rep for the current scale.
- scaled_image_ = gfx::ImageSkia();
-
- gfx::Size scaled_size =
- gfx::ScaleToCeiledSize(rep.pixel_size(), scale / rep.scale());
- scaled_image_.AddRepresentation(gfx::ImageSkiaRep(
- skia::ImageOperations::Resize(rep.GetBitmap(),
- skia::ImageOperations::RESIZE_BEST,
- scaled_size.width(), scaled_size.height()),
- scale));
+ if (image_model_.IsEmpty())
+ return gfx::ImageSkia();
+
+ if (image_model_.IsImage()) {
+ const gfx::ImageSkia& image = image_model_.GetImage().AsImageSkia();
+ if (image.isNull())
+ return image;
+
+ const gfx::ImageSkiaRep& rep = image.GetRepresentation(scale);
+ if (rep.scale() == scale)
+ return image;
+
+ if (scaled_image_.HasRepresentation(scale))
+ return scaled_image_;
+
+ // Only caches one image rep for the current scale.
+ scaled_image_ = gfx::ImageSkia();
+
+ gfx::Size scaled_size =
+ gfx::ScaleToCeiledSize(rep.pixel_size(), scale / rep.scale());
+ scaled_image_.AddRepresentation(gfx::ImageSkiaRep(
+ skia::ImageOperations::Resize(
+ rep.GetBitmap(), skia::ImageOperations::RESIZE_BEST,
+ scaled_size.width(), scaled_size.height()),
+ scale));
+ } else if (scaled_image_.isNull()) {
+ scaled_image_ =
+ views::GetImageSkiaFromImageModel(image_model_, GetNativeTheme());
+ }
return scaled_image_;
}
-DEFINE_ENUM_CONVERTERS(ImageView::Alignment,
- {ImageView::Alignment::kLeading, u"kLeading"},
- {ImageView::Alignment::kCenter, u"kCenter"},
- {ImageView::Alignment::kTrailing, u"kTrailing"})
-
BEGIN_METADATA(ImageView, View)
ADD_PROPERTY_METADATA(Alignment, HorizontalAlignment)
ADD_PROPERTY_METADATA(Alignment, VerticalAlignment)
@@ -283,3 +298,8 @@ ADD_PROPERTY_METADATA(std::u16string, TooltipText)
END_METADATA
} // namespace views
+
+DEFINE_ENUM_CONVERTERS(views::ImageView::Alignment,
+ {views::ImageView::Alignment::kLeading, u"kLeading"},
+ {views::ImageView::Alignment::kCenter, u"kCenter"},
+ {views::ImageView::Alignment::kTrailing, u"kTrailing"})
diff --git a/chromium/ui/views/controls/image_view.h b/chromium/ui/views/controls/image_view.h
index c5e07825078..9ba9d3f820d 100644
--- a/chromium/ui/views/controls/image_view.h
+++ b/chromium/ui/views/controls/image_view.h
@@ -9,8 +9,9 @@
#include <utility>
#include "base/macros.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/models/image_model.h"
#include "ui/gfx/image/image_skia.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/view.h"
#include "ui/views/views_export.h"
@@ -41,12 +42,20 @@ class VIEWS_EXPORT ImageView : public View {
~ImageView() override;
// Set the image that should be displayed.
- void SetImage(const gfx::ImageSkia& img);
+ // TODO(pkasting): Change callers to pass an ImageModel and eliminate this.
+ void SetImage(const gfx::ImageSkia& image) {
+ SetImage(ui::ImageModel::FromImageSkia(image));
+ }
// Set the image that should be displayed from a pointer. Reset the image
- // if the pointer is NULL. The pointer contents is copied in the receiver's
- // image.
- void SetImage(const gfx::ImageSkia* image_skia);
+ // if the pointer is NULL.
+ // TODO(pkasting): Change callers to pass an ImageModel and eliminate this.
+ void SetImage(const gfx::ImageSkia* image_skia) {
+ SetImage(image_skia ? *image_skia : gfx::ImageSkia());
+ }
+
+ // Sets the image that should be displayed.
+ void SetImage(const ui::ImageModel& image_model);
// Sets the desired size of the image to be displayed.
void SetImageSize(const gfx::Size& size);
@@ -58,8 +67,8 @@ class VIEWS_EXPORT ImageView : public View {
gfx::Rect GetImageBounds() const;
// Returns the image currently displayed, which can be empty if not set.
- // The returned image is still owned by the ImageView.
- const gfx::ImageSkia& GetImage() const;
+ // TODO(pkasting): Convert to an ImageModel getter.
+ gfx::ImageSkia GetImage() const;
// Set / Get the horizontal alignment.
void SetHorizontalAlignment(Alignment ha);
@@ -86,6 +95,9 @@ class VIEWS_EXPORT ImageView : public View {
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
void PreferredSizeChanged() override;
+ protected:
+ void OnThemeChanged() override;
+
private:
friend class ImageViewTest;
@@ -96,10 +108,10 @@ class VIEWS_EXPORT ImageView : public View {
// operation to create one. The resize may be time consuming for a big image.
gfx::ImageSkia GetPaintImage(float scale);
- // Returns true if |img| is the same as the last image we painted. This is
- // intended to be a quick check, not exhaustive. In other words it's possible
- // for this to return false even though the images are in fact equal.
- bool IsImageEqual(const gfx::ImageSkia& img) const;
+ // Returns true if |image_model| is the same as the last image we painted.
+ // This is intended to be a quick check, not exhaustive. In other words it's
+ // possible for this to return false even though the images are in fact equal.
+ bool IsImageEqual(const ui::ImageModel& image_model) const;
// Recomputes and updates the |image_origin_|.
void UpdateImageOrigin();
@@ -122,7 +134,7 @@ class VIEWS_EXPORT ImageView : public View {
Alignment vertical_alignment_ = Alignment::kCenter;
// The underlying image.
- gfx::ImageSkia image_;
+ ui::ImageModel image_model_;
// Caches the scaled image reps.
gfx::ImageSkia scaled_image_;
@@ -135,7 +147,7 @@ class VIEWS_EXPORT ImageView : public View {
void* last_painted_bitmap_pixels_ = nullptr;
// The requested image size.
- base::Optional<gfx::Size> image_size_;
+ absl::optional<gfx::Size> image_size_;
DISALLOW_COPY_AND_ASSIGN(ImageView);
};
diff --git a/chromium/ui/views/controls/label.cc b/chromium/ui/views/controls/label.cc
index 382b0ea115a..70d319e79c6 100644
--- a/chromium/ui/views/controls/label.cc
+++ b/chromium/ui/views/controls/label.cc
@@ -20,9 +20,12 @@
#include "build/chromeos_buildflags.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/default_style.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/compositor/layer.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/geometry/insets.h"
@@ -33,7 +36,6 @@
#include "ui/views/background.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/focus/focus_manager.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/native_cursor.h"
#include "ui/views/selection_controller.h"
@@ -132,7 +134,8 @@ void Label::SetTextContext(int text_context) {
full_text_->SetFontList(style::GetFont(text_context_, text_style_));
full_text_->SetMinLineHeight(GetLineHeight());
ClearDisplayText();
- UpdateColorsFromTheme();
+ if (GetWidget())
+ UpdateColorsFromTheme();
OnPropertyChanged(&text_context_, kPropertyEffectsPreferredSizeChanged);
}
@@ -148,7 +151,8 @@ void Label::SetTextStyle(int style) {
full_text_->SetFontList(style::GetFont(text_context_, text_style_));
full_text_->SetMinLineHeight(GetLineHeight());
ClearDisplayText();
- UpdateColorsFromTheme();
+ if (GetWidget())
+ UpdateColorsFromTheme();
OnPropertyChanged(&text_style_, kPropertyEffectsPreferredSizeChanged);
}
@@ -625,16 +629,15 @@ int Label::GetHeightForWidth(int w) const {
height = std::max(GetMaxLines(), 1) * base_line_height;
} else {
// SetDisplayRect() has a side effect for later calls of GetStringSize().
- // Be careful to invoke |full_text_->SetDisplayRect(gfx::Rect())| to
+ // Be careful to invoke full_text_->SetDisplayRect(gfx::Rect()) to
// cancel this effect before the next time GetStringSize() is called.
- // It would be beneficial not to cancel here, considering that some layout
- // managers invoke GetHeightForWidth() for the same width multiple times
- // and |full_text_| can cache the height.
+ // It's beneficial not to cancel here, considering that some layout managers
+ // invoke GetHeightForWidth() for the same width multiple times and
+ // |full_text_| can cache the height.
full_text_->SetDisplayRect(gfx::Rect(0, 0, w, 0));
int string_height = full_text_->GetStringSize().height();
- // Cap the number of lines to |GetMaxLines()| if multi-line and non-zero
- // |GetMaxLines()|.
- height = GetMultiLine() && GetMaxLines() > 0
+ // Cap the number of lines to GetMaxLines() if that's set.
+ height = GetMaxLines() > 0
? std::min(GetMaxLines() * base_line_height, string_height)
: string_height;
}
@@ -815,12 +818,11 @@ bool Label::OnMousePressed(const ui::MouseEvent& event) {
GetFocusManager()->SetFocusedView(this);
}
-// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
-// of lacros-chrome is complete.
-#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
- if (event.IsOnlyMiddleMouseButton() && GetFocusManager() && !had_focus)
- GetFocusManager()->SetFocusedView(this);
-#endif
+ if (ui::Clipboard::IsSupportedClipboardBuffer(
+ ui::ClipboardBuffer::kSelection)) {
+ if (event.IsOnlyMiddleMouseButton() && GetFocusManager() && !had_focus)
+ GetFocusManager()->SetFocusedView(this);
+ }
return selection_controller_->OnMousePressed(
event, false,
@@ -1004,14 +1006,13 @@ bool Label::PasteSelectionClipboard() {
}
void Label::UpdateSelectionClipboard() {
-// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
-// of lacros-chrome is complete.
-#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
- if (!GetObscured()) {
- ui::ScopedClipboardWriter(ui::ClipboardBuffer::kSelection)
- .WriteText(GetSelectedText());
+ if (ui::Clipboard::IsSupportedClipboardBuffer(
+ ui::ClipboardBuffer::kSelection)) {
+ if (!GetObscured()) {
+ ui::ScopedClipboardWriter(ui::ClipboardBuffer::kSelection)
+ .WriteText(GetSelectedText());
+ }
}
-#endif
}
bool Label::IsCommandIdChecked(int command_id) const {
@@ -1246,13 +1247,15 @@ ADD_PROPERTY_METADATA(std::u16string, Text)
ADD_PROPERTY_METADATA(int, TextContext)
ADD_PROPERTY_METADATA(int, TextStyle)
ADD_PROPERTY_METADATA(bool, AutoColorReadabilityEnabled)
-ADD_PROPERTY_METADATA(SkColor, EnabledColor, metadata::SkColorConverter)
+ADD_PROPERTY_METADATA(SkColor, EnabledColor, ui::metadata::SkColorConverter)
ADD_PROPERTY_METADATA(gfx::ElideBehavior, ElideBehavior)
-ADD_PROPERTY_METADATA(SkColor, BackgroundColor, metadata::SkColorConverter)
-ADD_PROPERTY_METADATA(SkColor, SelectionTextColor, metadata::SkColorConverter)
+ADD_PROPERTY_METADATA(SkColor, BackgroundColor, ui::metadata::SkColorConverter)
+ADD_PROPERTY_METADATA(SkColor,
+ SelectionTextColor,
+ ui::metadata::SkColorConverter)
ADD_PROPERTY_METADATA(SkColor,
SelectionBackgroundColor,
- metadata::SkColorConverter)
+ ui::metadata::SkColorConverter)
ADD_PROPERTY_METADATA(bool, SubpixelRenderingEnabled)
ADD_PROPERTY_METADATA(bool, SkipSubpixelRenderingOpacityCheck)
ADD_PROPERTY_METADATA(gfx::ShadowValues, Shadows)
diff --git a/chromium/ui/views/controls/label.h b/chromium/ui/views/controls/label.h
index 269425ed7c0..0e8b88dc404 100644
--- a/chromium/ui/views/controls/label.h
+++ b/chromium/ui/views/controls/label.h
@@ -11,13 +11,13 @@
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/render_text.h"
#include "ui/gfx/text_constants.h"
#include "ui/views/context_menu_controller.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/selection_controller_delegate.h"
#include "ui/views/style/typography.h"
@@ -428,7 +428,7 @@ class VIEWS_EXPORT Label : public View,
int text_context_;
int text_style_;
- base::Optional<int> line_height_;
+ absl::optional<int> line_height_;
// An un-elided and single-line RenderText object used for preferred sizing.
std::unique_ptr<gfx::RenderText> full_text_;
diff --git a/chromium/ui/views/controls/label_unittest.cc b/chromium/ui/views/controls/label_unittest.cc
index 0e52095fc09..c71d0fcf4cf 100644
--- a/chromium/ui/views/controls/label_unittest.cc
+++ b/chromium/ui/views/controls/label_unittest.cc
@@ -23,6 +23,7 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/ui_base_switches.h"
#include "ui/compositor/canvas_painter.h"
+#include "ui/compositor/layer.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/test/event_generator.h"
#include "ui/gfx/canvas.h"
@@ -42,16 +43,13 @@
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_utils.h"
-using base::ASCIIToUTF16;
using base::WideToUTF16;
-#define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
-
namespace views {
namespace {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
const int kControlCommandModifier = ui::EF_COMMAND_DOWN;
#else
const int kControlCommandModifier = ui::EF_CONTROL_DOWN;
@@ -789,8 +787,8 @@ TEST_F(LabelTest, MultiLineSizing) {
required_size.width() + border.width());
}
-#if !defined(OS_APPLE)
-// TODO(warx): Remove !defined(OS_APPLE) once SetMaxLines() is applied to MAC
+#if !defined(OS_MAC)
+// TODO(warx): Remove !defined(OS_MAC) once SetMaxLines() is applied to MAC
// (crbug.com/758720).
TEST_F(LabelTest, MultiLineSetMaxLines) {
// Ensure SetMaxLines clamps the line count of a string with returns.
@@ -1216,7 +1214,7 @@ TEST_F(LabelSelectionTest, DoubleTripleClick) {
// Double clicking should select the word under cursor.
PerformClick(GetCursorPoint(0));
- EXPECT_STR_EQ("Label", GetSelectedText());
+ EXPECT_EQ(u"Label", GetSelectedText());
// Triple clicking should select all the text.
PerformClick(GetCursorPoint(0));
@@ -1224,13 +1222,13 @@ TEST_F(LabelSelectionTest, DoubleTripleClick) {
// Clicking again should alternate to double click.
PerformClick(GetCursorPoint(0));
- EXPECT_STR_EQ("Label", GetSelectedText());
+ EXPECT_EQ(u"Label", GetSelectedText());
// Clicking at another location should clear the selection.
PerformClick(GetCursorPoint(8));
EXPECT_TRUE(GetSelectedText().empty());
PerformClick(GetCursorPoint(8));
- EXPECT_STR_EQ("double", GetSelectedText());
+ EXPECT_EQ(u"double", GetSelectedText());
}
// Verify label text selection behavior on mouse drag.
@@ -1241,18 +1239,17 @@ TEST_F(LabelSelectionTest, MouseDrag) {
PerformMousePress(GetCursorPoint(5));
PerformMouseDragTo(GetCursorPoint(0));
- EXPECT_STR_EQ("Label", GetSelectedText());
+ EXPECT_EQ(u"Label", GetSelectedText());
PerformMouseDragTo(GetCursorPoint(8));
- EXPECT_STR_EQ(" mo", GetSelectedText());
+ EXPECT_EQ(u" mo", GetSelectedText());
PerformMouseDragTo(gfx::Point(200, GetCursorPoint(0).y()));
PerformMouseRelease(gfx::Point(200, GetCursorPoint(0).y()));
- EXPECT_STR_EQ(" mouse drag", GetSelectedText());
+ EXPECT_EQ(u" mouse drag", GetSelectedText());
event_generator()->PressKey(ui::VKEY_C, kControlCommandModifier);
- EXPECT_STR_EQ(" mouse drag",
- GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ EXPECT_EQ(u" mouse drag", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
}
TEST_F(LabelSelectionTest, MouseDragMultilineLTR) {
@@ -1264,16 +1261,16 @@ TEST_F(LabelSelectionTest, MouseDragMultilineLTR) {
PerformMousePress(GetCursorPoint(2));
PerformMouseDragTo(GetCursorPoint(0));
- EXPECT_STR_EQ("ab", GetSelectedText());
+ EXPECT_EQ(u"ab", GetSelectedText());
PerformMouseDragTo(GetCursorPoint(7));
- EXPECT_STR_EQ("cd\nef", GetSelectedText());
+ EXPECT_EQ(u"cd\nef", GetSelectedText());
PerformMouseDragTo(gfx::Point(-5, GetCursorPoint(6).y()));
- EXPECT_STR_EQ("cd\n", GetSelectedText());
+ EXPECT_EQ(u"cd\n", GetSelectedText());
PerformMouseDragTo(gfx::Point(100, GetCursorPoint(6).y()));
- EXPECT_STR_EQ("cd\nefgh", GetSelectedText());
+ EXPECT_EQ(u"cd\nefgh", GetSelectedText());
const gfx::Point points[] = {
{GetCursorPoint(1).x(), -5}, // NW.
@@ -1283,22 +1280,22 @@ TEST_F(LabelSelectionTest, MouseDragMultilineLTR) {
{GetCursorPoint(7).x(), 100}, // SOUTH.
{GetCursorPoint(6).x(), 100}, // SW.
};
- constexpr const char* kExtendLeft = "ab";
- constexpr const char* kExtendRight = "cd\nefgh";
+ constexpr const char16_t* kExtendLeft = u"ab";
+ constexpr const char16_t* kExtendRight = u"cd\nefgh";
// For multiline, N* extends left, S* extends right.
PerformMouseDragTo(points[NW]);
- EXPECT_STR_EQ(kExtends ? kExtendLeft : "b", GetSelectedText());
+ EXPECT_EQ(kExtends ? kExtendLeft : u"b", GetSelectedText());
PerformMouseDragTo(points[NORTH]);
- EXPECT_STR_EQ(kExtends ? kExtendLeft : "", GetSelectedText());
+ EXPECT_EQ(kExtends ? kExtendLeft : u"", GetSelectedText());
PerformMouseDragTo(points[NE]);
- EXPECT_STR_EQ(kExtends ? kExtendLeft : "c", GetSelectedText());
+ EXPECT_EQ(kExtends ? kExtendLeft : u"c", GetSelectedText());
PerformMouseDragTo(points[SE]);
- EXPECT_STR_EQ(kExtends ? kExtendRight : "cd\nefg", GetSelectedText());
+ EXPECT_EQ(kExtends ? kExtendRight : u"cd\nefg", GetSelectedText());
PerformMouseDragTo(points[SOUTH]);
- EXPECT_STR_EQ(kExtends ? kExtendRight : "cd\nef", GetSelectedText());
+ EXPECT_EQ(kExtends ? kExtendRight : u"cd\nef", GetSelectedText());
PerformMouseDragTo(points[SW]);
- EXPECT_STR_EQ(kExtends ? kExtendRight : "cd\ne", GetSelectedText());
+ EXPECT_EQ(kExtends ? kExtendRight : u"cd\ne", GetSelectedText());
}
// Single line fields consider the x offset as well. Ties go to the right.
@@ -1315,22 +1312,22 @@ TEST_F(LabelSelectionTest, MouseDragSingleLineLTR) {
{GetCursorPoint(2).x(), 100}, // SOUTH.
{GetCursorPoint(1).x(), 100}, // SW.
};
- constexpr const char* kExtendLeft = "ab";
- constexpr const char* kExtendRight = "cdef";
+ constexpr const char16_t* kExtendLeft = u"ab";
+ constexpr const char16_t* kExtendRight = u"cdef";
// For single line, western directions extend left, all others extend right.
PerformMouseDragTo(points[NW]);
- EXPECT_STR_EQ(kExtends ? kExtendLeft : "b", GetSelectedText());
+ EXPECT_EQ(kExtends ? kExtendLeft : u"b", GetSelectedText());
PerformMouseDragTo(points[NORTH]);
- EXPECT_STR_EQ(kExtends ? kExtendRight : "", GetSelectedText());
+ EXPECT_EQ(kExtends ? kExtendRight : u"", GetSelectedText());
PerformMouseDragTo(points[NE]);
- EXPECT_STR_EQ(kExtends ? kExtendRight : "c", GetSelectedText());
+ EXPECT_EQ(kExtends ? kExtendRight : u"c", GetSelectedText());
PerformMouseDragTo(points[SE]);
- EXPECT_STR_EQ(kExtends ? kExtendRight : "c", GetSelectedText());
+ EXPECT_EQ(kExtends ? kExtendRight : u"c", GetSelectedText());
PerformMouseDragTo(points[SOUTH]);
- EXPECT_STR_EQ(kExtends ? kExtendRight : "", GetSelectedText());
+ EXPECT_EQ(kExtends ? kExtendRight : u"", GetSelectedText());
PerformMouseDragTo(points[SW]);
- EXPECT_STR_EQ(kExtends ? kExtendLeft : "b", GetSelectedText());
+ EXPECT_EQ(kExtends ? kExtendLeft : u"b", GetSelectedText());
}
TEST_F(LabelSelectionTest, MouseDragMultilineRTL) {
@@ -1427,21 +1424,28 @@ TEST_F(LabelSelectionTest, MouseDragWord) {
PerformClick(GetCursorPoint(8));
PerformMousePress(GetCursorPoint(8));
- EXPECT_STR_EQ("drag", GetSelectedText());
+ EXPECT_EQ(u"drag", GetSelectedText());
PerformMouseDragTo(GetCursorPoint(0));
- EXPECT_STR_EQ("Label drag", GetSelectedText());
+ EXPECT_EQ(u"Label drag", GetSelectedText());
PerformMouseDragTo(gfx::Point(200, GetCursorPoint(0).y()));
PerformMouseRelease(gfx::Point(200, GetCursorPoint(0).y()));
- EXPECT_STR_EQ("drag word", GetSelectedText());
+ EXPECT_EQ(u"drag word", GetSelectedText());
}
+// TODO(crbug.com/1201128): LabelSelectionTest.SelectionClipboard is failing on
+// linux-lacros.
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#define MAYBE_SelectionClipboard DISABLED_SelectionClipboard
+#else
+#define MAYBE_SelectionClipboard SelectionClipboard
+#endif
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
// Verify selection clipboard behavior on text selection.
-TEST_F(LabelSelectionTest, SelectionClipboard) {
+TEST_F(LabelSelectionTest, MAYBE_SelectionClipboard) {
label()->SetText(u"Label selection clipboard");
label()->SizeToPreferredSize();
ASSERT_TRUE(label()->SetSelectable(true));
@@ -1449,15 +1453,15 @@ TEST_F(LabelSelectionTest, SelectionClipboard) {
// Verify programmatic modification of selection, does not modify the
// selection clipboard.
label()->SelectRange(gfx::Range(2, 5));
- EXPECT_STR_EQ("bel", GetSelectedText());
+ EXPECT_EQ(u"bel", GetSelectedText());
EXPECT_TRUE(GetClipboardText(ui::ClipboardBuffer::kSelection).empty());
// Verify text selection using the mouse updates the selection clipboard.
PerformMousePress(GetCursorPoint(5));
PerformMouseDragTo(GetCursorPoint(0));
PerformMouseRelease(GetCursorPoint(0));
- EXPECT_STR_EQ("Label", GetSelectedText());
- EXPECT_STR_EQ("Label", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"Label", GetSelectedText());
+ EXPECT_EQ(u"Label", GetClipboardText(ui::ClipboardBuffer::kSelection));
}
#endif
diff --git a/chromium/ui/views/controls/link.cc b/chromium/ui/views/controls/link.cc
index f4885be4973..b1330bd0108 100644
--- a/chromium/ui/views/controls/link.cc
+++ b/chromium/ui/views/controls/link.cc
@@ -11,13 +11,13 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/cursor/cursor.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/font_list.h"
#include "ui/native_theme/native_theme.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/native_cursor.h"
#include "ui/views/style/platform_style.h"
@@ -149,7 +149,7 @@ void Link::GetAccessibleNodeData(ui::AXNodeData* node_data) {
Label::GetAccessibleNodeData(node_data);
// Prevent invisible links from being announced by screen reader.
node_data->role =
- GetText().empty() ? ax::mojom::Role::kIgnored : ax::mojom::Role::kLink;
+ GetText().empty() ? ax::mojom::Role::kNone : ax::mojom::Role::kLink;
}
void Link::OnFocus() {
@@ -183,7 +183,8 @@ void Link::OnThemeChanged() {
void Link::SetEnabledColor(SkColor color) {
requested_enabled_color_ = color;
- Label::SetEnabledColor(GetColor());
+ if (GetWidget())
+ Label::SetEnabledColor(GetColor());
}
bool Link::IsSelectionSupported() const {
@@ -221,7 +222,7 @@ void Link::ConfigureFocus() {
if (GetText().empty()) {
SetFocusBehavior(FocusBehavior::NEVER);
} else {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
#else
SetFocusBehavior(FocusBehavior::ALWAYS);
@@ -230,9 +231,7 @@ void Link::ConfigureFocus() {
}
BEGIN_METADATA(Link, Label)
-ADD_READONLY_PROPERTY_METADATA(SkColor,
- Color,
- views::metadata::SkColorConverter)
+ADD_READONLY_PROPERTY_METADATA(SkColor, Color, ui::metadata::SkColorConverter)
END_METADATA
} // namespace views
diff --git a/chromium/ui/views/controls/link.h b/chromium/ui/views/controls/link.h
index 7585b8b6173..54e9e143645 100644
--- a/chromium/ui/views/controls/link.h
+++ b/chromium/ui/views/controls/link.h
@@ -10,7 +10,7 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/color_palette.h"
#include "ui/views/controls/label.h"
@@ -94,7 +94,7 @@ class VIEWS_EXPORT Link : public Label {
bool pressed_ = false;
// The color when the link is neither pressed nor disabled.
- base::Optional<SkColor> requested_enabled_color_;
+ absl::optional<SkColor> requested_enabled_color_;
base::CallbackListSubscription enabled_changed_subscription_;
diff --git a/chromium/ui/views/controls/link_unittest.cc b/chromium/ui/views/controls/link_unittest.cc
index d3c2c7900b8..b84cd7ad993 100644
--- a/chromium/ui/views/controls/link_unittest.cc
+++ b/chromium/ui/views/controls/link_unittest.cc
@@ -37,7 +37,6 @@ class LinkTest : public test::BaseControlTestWidget {
event_generator_ = std::make_unique<ui::test::EventGenerator>(
GetContext(), widget()->GetNativeWindow());
- event_generator_->set_assume_window_at_origin(false);
}
protected:
diff --git a/chromium/ui/views/controls/menu/menu_controller.cc b/chromium/ui/views/controls/menu/menu_controller.cc
index 7c081b7d8a4..e9edd19929a 100644
--- a/chromium/ui/views/controls/menu/menu_controller.cc
+++ b/chromium/ui/views/controls/menu/menu_controller.cc
@@ -42,8 +42,10 @@
#include "ui/views/controls/menu/menu_scroll_view_container.h"
#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/drag_utils.h"
+#include "ui/views/interaction/element_tracker_views.h"
#include "ui/views/mouse_constants.h"
#include "ui/views/view.h"
+#include "ui/views/view_class_properties.h"
#include "ui/views/view_constants.h"
#include "ui/views/view_tracker.h"
#include "ui/views/views_delegate.h"
@@ -77,7 +79,7 @@ namespace views {
namespace {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
bool AcceleratorShouldCancelMenu(const ui::Accelerator& accelerator) {
// Since AcceleratorShouldCancelMenu() is called quite early in key
// event handling, it is actually invoked for modifier keys themselves
@@ -522,7 +524,7 @@ void MenuController::Run(Widget* parent,
menu_pre_target_handler_ = MenuPreTargetHandler::Create(this, owner_);
}
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
menu_cocoa_watcher_ = std::make_unique<MenuCocoaWatcherMac>(base::BindOnce(
&MenuController::Cancel, this->AsWeakPtr(), ExitType::kAll));
#endif
@@ -554,7 +556,7 @@ void MenuController::Run(Widget* parent,
}
void MenuController::Cancel(ExitType type) {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
menu_closure_animation_.reset();
#endif
@@ -1205,7 +1207,7 @@ ui::PostDispatchAction MenuController::OnWillDispatchKeyEvent(
base::WeakPtr<MenuController> this_ref = AsWeakPtr();
if (event->type() == ui::ET_KEY_PRESSED) {
bool key_handled = false;
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Special handling for Option-Up and Option-Down, which should behave like
// Home and End respectively in menus.
if ((event->flags() & ui::EF_ALT_DOWN)) {
@@ -1252,7 +1254,7 @@ ui::PostDispatchAction MenuController::OnWillDispatchKeyEvent(
ui::Accelerator accelerator(*event);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
if (AcceleratorShouldCancelMenu(accelerator)) {
Cancel(ExitType::kAll);
return ui::POST_DISPATCH_PERFORM_DEFAULT;
@@ -1319,7 +1321,7 @@ void MenuController::TurnOffMenuSelectionHoldForTest() {
}
void MenuController::OnMenuItemDestroying(MenuItemView* menu_item) {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
if (menu_closure_animation_ && menu_closure_animation_->item() == menu_item)
menu_closure_animation_.reset();
#endif
@@ -1564,7 +1566,7 @@ bool MenuController::OnKeyPressed(const ui::KeyEvent& event) {
break;
// On Mac, treat space the same as return.
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
case ui::VKEY_SPACE:
SendAcceleratorToHotTrackedView(event.flags());
break;
@@ -1576,7 +1578,7 @@ bool MenuController::OnKeyPressed(const ui::KeyEvent& event) {
// Fallthrough to accept or dismiss combobox menus on F4, like windows.
FALLTHROUGH;
case ui::VKEY_RETURN:
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
case ui::VKEY_SPACE:
#endif
// An odd special case: if a prefix selection is in flight, space should
@@ -1620,7 +1622,7 @@ bool MenuController::OnKeyPressed(const ui::KeyEvent& event) {
CloseSubmenu();
break;
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
case ui::VKEY_APPS: {
Button* hot_view = GetFirstHotTrackedView(pending_state_.item);
if (hot_view) {
@@ -1728,7 +1730,17 @@ void MenuController::UpdateInitialLocation(const gfx::Rect& bounds,
}
void MenuController::Accept(MenuItemView* item, int event_flags) {
-#if defined(OS_APPLE)
+ // This counts as activation of a menu item. We don't put this logic in
+ // ReallyAccept() because we expect activation to happen while the element is
+ // visible to the user, but ReallyAccept() is called on Mac *after* the menu
+ // is closed.
+ if (item) {
+ const ui::ElementIdentifier id = item->GetProperty(kElementIdentifierKey);
+ if (id)
+ views::ElementTrackerViews::GetInstance()->NotifyViewActivated(id, item);
+ }
+
+#if defined(OS_MAC)
menu_closure_animation_ = std::make_unique<MenuClosureAnimationMac>(
item, item->GetParentMenuItem()->GetSubmenu(),
base::BindOnce(&MenuController::ReallyAccept, base::Unretained(this),
@@ -1742,7 +1754,7 @@ void MenuController::Accept(MenuItemView* item, int event_flags) {
void MenuController::ReallyAccept(MenuItemView* item, int event_flags) {
DCHECK(!for_drop_);
result_ = item;
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Reset the closure animation since it's now finished - this also unblocks
// input events for the menu.
menu_closure_animation_.reset();
@@ -2915,7 +2927,7 @@ void MenuController::RepostEventAndCancel(SubmenuView* source,
if (last_part.type != MenuPart::Type::kNone)
exit_type = ExitType::kOutermost;
}
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// When doing a menu closure animation, target the deepest submenu - that way
// MenuClosureAnimationMac will fade out all the menus in sync, rather than
// the shallowest menu only.
@@ -3243,7 +3255,7 @@ void MenuController::UnregisterAlertedItem(MenuItemView* item) {
}
bool MenuController::CanProcessInputEvents() const {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
return !menu_closure_animation_;
#else
return true;
diff --git a/chromium/ui/views/controls/menu/menu_controller.h b/chromium/ui/views/controls/menu/menu_controller.h
index 5c93ce1dbfa..d61f4891794 100644
--- a/chromium/ui/views/controls/menu/menu_controller.h
+++ b/chromium/ui/views/controls/menu/menu_controller.h
@@ -29,7 +29,7 @@
#include "ui/views/controls/menu/menu_delegate.h"
#include "ui/views/widget/widget_observer.h"
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#include "ui/views/controls/menu/menu_closure_animation_mac.h"
#include "ui/views/controls/menu/menu_cocoa_watcher_mac.h"
#endif
@@ -751,7 +751,7 @@ class VIEWS_EXPORT MenuController
// location. Otherwise it will be null. This is used to ignore mouse move
// events triggered by the menu opening, to avoid selecting the menu item
// over the mouse.
- base::Optional<gfx::Point> menu_open_mouse_loc_;
+ absl::optional<gfx::Point> menu_open_mouse_loc_;
// Controls behavior differences between a combobox and other types of menu
// (like a context menu).
@@ -778,7 +778,7 @@ class VIEWS_EXPORT MenuController
// A mask of the EventFlags for the mouse buttons currently pressed.
int current_mouse_pressed_state_ = 0;
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
std::unique_ptr<MenuClosureAnimationMac> menu_closure_animation_;
std::unique_ptr<MenuCocoaWatcherMac> menu_cocoa_watcher_;
#endif
diff --git a/chromium/ui/views/controls/menu/menu_controller_unittest.cc b/chromium/ui/views/controls/menu/menu_controller_unittest.cc
index 23d0bd6f82a..edf2becc6e6 100644
--- a/chromium/ui/views/controls/menu/menu_controller_unittest.cc
+++ b/chromium/ui/views/controls/menu/menu_controller_unittest.cc
@@ -69,9 +69,10 @@
namespace views {
namespace test {
-
namespace {
+using ::ui::mojom::DragOperation;
+
bool ShouldIgnoreScreenBoundsForMenus() {
#if defined(USE_OZONE)
if (features::IsUsingOzonePlatform()) {
@@ -205,12 +206,12 @@ class TestDragDropClient : public aura::client::DragDropClient {
~TestDragDropClient() override = default;
// aura::client::DragDropClient:
- int StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data,
- aura::Window* root_window,
- aura::Window* source_window,
- const gfx::Point& screen_location,
- int operation,
- ui::mojom::DragEventSource source) override;
+ DragOperation StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data,
+ aura::Window* root_window,
+ aura::Window* source_window,
+ const gfx::Point& screen_location,
+ int allowed_operations,
+ ui::mojom::DragEventSource source) override;
void DragCancel() override;
bool IsDragDropInProgress() override;
@@ -225,16 +226,16 @@ class TestDragDropClient : public aura::client::DragDropClient {
DISALLOW_COPY_AND_ASSIGN(TestDragDropClient);
};
-int TestDragDropClient::StartDragAndDrop(
+DragOperation TestDragDropClient::StartDragAndDrop(
std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& screen_location,
- int operation,
+ int allowed_operations,
ui::mojom::DragEventSource source) {
drag_in_progress_ = true;
start_drag_and_drop_callback_.Run();
- return 0;
+ return DragOperation::kNone;
}
void TestDragDropClient::DragCancel() {
@@ -2794,7 +2795,7 @@ TEST_F(MenuControllerTest, AccessibilityEmitsSelectChildrenChanged) {
EXPECT_EQ(ax_counter.GetCount(ax::mojom::Event::kSelectedChildrenChanged), 2);
}
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// This test exercises a Mac-specific behavior, by which hotkeys using modifiers
// cause menus to close and the hotkeys to be handled by the browser window.
// This specific test case tries using cmd-ctrl-f, which normally means
diff --git a/chromium/ui/views/controls/menu/menu_host.cc b/chromium/ui/views/controls/menu/menu_host.cc
index 31b7422d882..f133223259b 100644
--- a/chromium/ui/views/controls/menu/menu_host.cc
+++ b/chromium/ui/views/controls/menu/menu_host.cc
@@ -24,7 +24,7 @@
#include "ui/views/widget/native_widget_private.h"
#include "ui/views/widget/widget.h"
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
#include "ui/aura/window.h"
#endif
@@ -32,7 +32,7 @@ namespace views {
namespace internal {
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// This class adds itself as the pre target handler for the |window|
// passed in. It currently handles touch events and forwards them to the
// controller. Reason for this approach is views does not get raw touch
@@ -79,7 +79,7 @@ class PreMenuEventDispatchHandler : public ui::EventHandler,
DISALLOW_COPY_AND_ASSIGN(PreMenuEventDispatchHandler);
};
-#endif // OS_APPLE
+#endif // OS_MAC
void TransferGesture(ui::GestureRecognizer* gesture_recognizer,
gfx::NativeView source,
@@ -136,7 +136,7 @@ void MenuHost::InitMenuHost(Widget* parent,
// Activatable, so that calling Show in ShowMenuHost will
// get keyboard focus.
if (parent == nullptr)
- params.activatable = Widget::InitParams::ACTIVATABLE_YES;
+ params.activatable = Widget::InitParams::Activatable::kYes;
#if defined(OS_WIN)
// On Windows use the software compositor to ensure that we don't block
// the UI thread blocking issue during command buffer creation. We can
@@ -145,7 +145,7 @@ void MenuHost::InitMenuHost(Widget* parent,
#endif
Init(std::move(params));
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
pre_dispatch_handler_ =
std::make_unique<internal::PreMenuEventDispatchHandler>(
menu_controller, submenu_, GetNativeView());
@@ -215,7 +215,7 @@ void MenuHost::DestroyMenuHost() {
HideMenuHost();
destroying_ = true;
static_cast<MenuHostRootView*>(GetRootView())->ClearSubmenu();
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
pre_dispatch_handler_.reset();
#endif
Close();
@@ -305,6 +305,11 @@ void MenuHost::OnDragComplete() {
native_widget_private()->SetCapture();
}
+Widget* MenuHost::GetPrimaryWindowWidget() {
+ return owner_ ? owner_->GetPrimaryWindowWidget()
+ : Widget::GetPrimaryWindowWidget();
+}
+
void MenuHost::OnWidgetDestroying(Widget* widget) {
DCHECK_EQ(owner_, widget);
owner_->RemoveObserver(this);
diff --git a/chromium/ui/views/controls/menu/menu_host.h b/chromium/ui/views/controls/menu/menu_host.h
index 4797d16e887..1840826578a 100644
--- a/chromium/ui/views/controls/menu/menu_host.h
+++ b/chromium/ui/views/controls/menu/menu_host.h
@@ -80,6 +80,7 @@ class MenuHost : public Widget, public WidgetObserver {
void OnOwnerClosing() override;
void OnDragWillStart() override;
void OnDragComplete() override;
+ Widget* GetPrimaryWindowWidget() override;
// WidgetObserver:
void OnWidgetDestroying(Widget* widget) override;
@@ -98,7 +99,7 @@ class MenuHost : public Widget, public WidgetObserver {
// If true and capture is lost we don't notify the delegate.
bool ignore_capture_lost_;
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// Handles raw touch events at the moment.
std::unique_ptr<internal::PreMenuEventDispatchHandler> pre_dispatch_handler_;
#endif
diff --git a/chromium/ui/views/controls/menu/menu_host_root_view.cc b/chromium/ui/views/controls/menu/menu_host_root_view.cc
index 83a09ec24f0..7ce11795201 100644
--- a/chromium/ui/views/controls/menu/menu_host_root_view.cc
+++ b/chromium/ui/views/controls/menu/menu_host_root_view.cc
@@ -4,10 +4,10 @@
#include "ui/views/controls/menu/menu_host_root_view.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/submenu_view.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace views {
diff --git a/chromium/ui/views/controls/menu/menu_image_util.cc b/chromium/ui/views/controls/menu/menu_image_util.cc
index 80673906f76..4ee5f26d28e 100644
--- a/chromium/ui/views/controls/menu/menu_image_util.cc
+++ b/chromium/ui/views/controls/menu/menu_image_util.cc
@@ -4,6 +4,7 @@
#include "ui/views/controls/menu/menu_image_util.h"
+#include "components/vector_icons/vector_icons.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/vector_icon_types.h"
@@ -16,7 +17,7 @@ gfx::ImageSkia GetMenuCheckImage(SkColor icon_color) {
}
gfx::ImageSkia GetSubmenuArrowImage(SkColor icon_color) {
- return gfx::CreateVectorIcon(kSubmenuArrowIcon, icon_color);
+ return gfx::CreateVectorIcon(vector_icons::kSubmenuArrowIcon, icon_color);
}
} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_item_view.cc b/chromium/ui/views/controls/menu/menu_item_view.cc
index ef778c706f6..3232a9147d8 100644
--- a/chromium/ui/views/controls/menu/menu_item_view.cc
+++ b/chromium/ui/views/controls/menu/menu_item_view.cc
@@ -21,8 +21,9 @@
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/platform/ax_platform_node.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/models/menu_model.h"
-#include "ui/base/ui_base_features.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/gfx/animation/animation.h"
@@ -45,22 +46,21 @@
#include "ui/views/controls/menu/new_badge.h"
#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/controls/separator.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
+#include "ui/views/image_model_utils.h"
#include "ui/views/style/typography.h"
#include "ui/views/vector_icons.h"
#include "ui/views/view_class_properties.h"
-#include "ui/views/views_features.h"
#include "ui/views/widget/widget.h"
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#include "ui/views/accessibility/view_accessibility.h"
-#endif // defined(OS_APPLE)
+#endif // defined(OS_MAC)
namespace views {
namespace {
-// EmptyMenuMenuItem ---------------------------------------------------------
+// EmptyMenuMenuItem ----------------------------------------------------------
// EmptyMenuMenuItem is used when a menu has no menu items. EmptyMenuMenuItem
// is itself a MenuItemView, but it uses a different ID so that it isn't
@@ -85,6 +85,38 @@ class EmptyMenuMenuItem : public MenuItemView {
DISALLOW_COPY_AND_ASSIGN(EmptyMenuMenuItem);
};
+// VerticalSeparator ----------------------------------------------------------
+
+class VerticalSeparator : public Separator {
+ public:
+ METADATA_HEADER(VerticalSeparator);
+ VerticalSeparator();
+ VerticalSeparator(const VerticalSeparator&) = delete;
+ VerticalSeparator& operator=(const VerticalSeparator&) = delete;
+ ~VerticalSeparator() override = default;
+
+ // Separator:
+ void OnThemeChanged() override;
+};
+
+VerticalSeparator::VerticalSeparator() {
+ SetFocusBehavior(FocusBehavior::NEVER);
+ const MenuConfig& config = MenuConfig::instance();
+ SetPreferredSize(
+ gfx::Size(config.actionable_submenu_vertical_separator_width,
+ config.actionable_submenu_vertical_separator_height));
+ SetCanProcessEventsWithinSubtree(false);
+}
+
+void VerticalSeparator::OnThemeChanged() {
+ Separator::OnThemeChanged();
+ SetColor(GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_MenuSeparatorColor));
+}
+
+BEGIN_METADATA(VerticalSeparator, Separator)
+END_METADATA
+
} // namespace
// Padding between child views.
@@ -250,8 +282,7 @@ View::FocusBehavior MenuItemView::GetFocusBehavior() const {
// The rest of the MenuItemView types are presumably focusable, at least by
// assistive technologies. But if they lack presentable information, then
// there won't be anything for ATs to convey to the user. Filter those out.
- if (title_.empty() && secondary_title_.empty() && minor_text_.empty() &&
- vector_icon_.empty()) {
+ if (title_.empty() && secondary_title_.empty() && minor_text_.empty()) {
return FocusBehavior::NEVER;
}
@@ -313,9 +344,8 @@ MenuItemView* MenuItemView::AddMenuItemAt(
const std::u16string& label,
const std::u16string& secondary_label,
const std::u16string& minor_text,
- const ui::ThemedVectorIcon& minor_icon,
- const gfx::ImageSkia& icon,
- const ui::ThemedVectorIcon& vector_icon,
+ const ui::ImageModel& minor_icon,
+ const ui::ImageModel& icon,
Type type,
ui::MenuSeparatorType separator_style) {
DCHECK_NE(type, Type::kEmpty);
@@ -336,12 +366,7 @@ MenuItemView* MenuItemView::AddMenuItemAt(
item->SetSecondaryTitle(secondary_label);
item->SetMinorText(minor_text);
item->SetMinorIcon(minor_icon);
- if (!vector_icon.empty()) {
- DCHECK(icon.isNull());
- item->SetIcon(vector_icon);
- }
- if (!icon.isNull())
- item->SetIcon(icon);
+ item->SetIcon(icon);
if (type == Type::kSubMenu || type == Type::kActionableSubMenu)
item->CreateSubmenu();
if (type == Type::kHighlighted) {
@@ -391,9 +416,8 @@ void MenuItemView::AddSeparatorAt(int index) {
AddMenuItemAt(index, /*item_id=*/0, /*label=*/std::u16string(),
/*secondary_label=*/std::u16string(),
/*minor_text=*/std::u16string(),
- /*minor_icon=*/ui::ThemedVectorIcon(),
- /*icon=*/gfx::ImageSkia(),
- /*vector_icon=*/ui::ThemedVectorIcon(),
+ /*minor_icon=*/ui::ImageModel(),
+ /*icon=*/ui::ImageModel(),
/*type=*/Type::kSeparator,
/*separator_style=*/ui::NORMAL_SEPARATOR);
}
@@ -404,15 +428,16 @@ MenuItemView* MenuItemView::AppendMenuItemImpl(int item_id,
Type type) {
const int index = submenu_ ? int{submenu_->children().size()} : 0;
return AddMenuItemAt(index, item_id, label, std::u16string(),
- std::u16string(), ui::ThemedVectorIcon(), icon,
- ui::ThemedVectorIcon(), type, ui::NORMAL_SEPARATOR);
+ std::u16string(), ui::ImageModel(),
+ ui::ImageModel::FromImageSkia(icon), type,
+ ui::NORMAL_SEPARATOR);
}
SubmenuView* MenuItemView::CreateSubmenu() {
if (!submenu_) {
submenu_ = new SubmenuView(this);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// All MenuItemViews of Type kSubMenu have a respective SubmenuView.
// However, in the Views hierarchy, this SubmenuView is not a child of the
// MenuItemView. This confuses VoiceOver, because it expects the submenu
@@ -422,7 +447,7 @@ SubmenuView* MenuItemView::CreateSubmenu() {
std::make_unique<AXVirtualView>();
virtual_child->GetCustomData().role = ax::mojom::Role::kMenu;
GetViewAccessibility().AddVirtualChildView(std::move(virtual_child));
-#endif // defined(OS_APPLE)
+#endif // defined(OS_MAC)
// Initialize the submenu indicator icon (arrow).
submenu_arrow_image_view_ = AddChildView(std::make_unique<ImageView>());
@@ -458,7 +483,7 @@ void MenuItemView::SetMinorText(const std::u16string& minor_text) {
invalidate_dimensions(); // Triggers preferred size recalculation.
}
-void MenuItemView::SetMinorIcon(const ui::ThemedVectorIcon& minor_icon) {
+void MenuItemView::SetMinorIcon(const ui::ImageModel& minor_icon) {
minor_icon_ = minor_icon;
invalidate_dimensions(); // Triggers preferred size recalculation.
}
@@ -492,36 +517,14 @@ void MenuItemView::SetTooltip(const std::u16string& tooltip, int item_id) {
item->tooltip_ = tooltip;
}
-void MenuItemView::SetIcon(const gfx::ImageSkia& icon, int item_id) {
- MenuItemView* item = GetMenuItemByID(item_id);
- DCHECK(item);
- item->SetIcon(icon);
-}
-
-void MenuItemView::SetIcon(const gfx::ImageSkia& icon) {
- vector_icon_.clear();
-
- if (icon.isNull()) {
+void MenuItemView::SetIcon(const ui::ImageModel& icon) {
+ if (icon.IsEmpty()) {
SetIconView(nullptr);
return;
}
auto icon_view = std::make_unique<ImageView>();
- icon_view->SetImage(&icon);
- SetIconView(std::move(icon_view));
-}
-
-void MenuItemView::SetIcon(const ui::ThemedVectorIcon& icon) {
- vector_icon_ = icon;
- UpdateIconViewFromVectorIconAndTheme();
-}
-
-void MenuItemView::UpdateIconViewFromVectorIconAndTheme() {
- if (vector_icon_.empty())
- return;
-
- auto icon_view = std::make_unique<ImageView>();
- icon_view->SetImage(vector_icon_.GetImageSkia(GetNativeTheme()));
+ icon_view->SetImage(icon);
SetIconView(std::move(icon_view));
}
@@ -563,11 +566,6 @@ int MenuItemView::GetHeightForWidth(int width) const {
return height;
}
-void MenuItemView::OnThemeChanged() {
- View::OnThemeChanged();
- UpdateIconViewFromVectorIconAndTheme();
-}
-
gfx::Rect MenuItemView::GetSubmenuAreaOfActionableSubmenu() const {
DCHECK_EQ(Type::kActionableSubMenu, type_);
const MenuConfig& config = MenuConfig::instance();
@@ -779,9 +777,7 @@ void MenuItemView::SetAlerted() {
}
bool MenuItemView::ShouldShowNewBadge() const {
- static const bool feature_enabled =
- base::FeatureList::IsEnabled(features::kEnableNewBadgeOnMenuItems);
- return feature_enabled && is_new_;
+ return is_new_;
}
bool MenuItemView::IsTraversableByKeyboard() const {
@@ -835,8 +831,6 @@ void MenuItemView::UpdateMenuPartSizes() {
EmptyMenuMenuItem menu_item(this);
menu_item.set_controller(GetMenuController());
pref_menu_height_ = menu_item.GetPreferredSize().height();
-
- UpdateIconViewFromVectorIconAndTheme();
}
void MenuItemView::Init(MenuItemView* parent,
@@ -858,18 +852,8 @@ void MenuItemView::Init(MenuItemView* parent,
radio_check_image_view_->SetCanProcessEventsWithinSubtree(false);
}
- if (type_ == Type::kActionableSubMenu) {
- vertical_separator_ = AddChildView(std::make_unique<Separator>());
- vertical_separator_->SetVisible(true);
- vertical_separator_->SetFocusBehavior(FocusBehavior::NEVER);
- const MenuConfig& config = MenuConfig::instance();
- vertical_separator_->SetColor(GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_MenuSeparatorColor));
- vertical_separator_->SetPreferredSize(
- gfx::Size(config.actionable_submenu_vertical_separator_width,
- config.actionable_submenu_vertical_separator_height));
- vertical_separator_->SetCanProcessEventsWithinSubtree(false);
- }
+ if (type_ == Type::kActionableSubMenu)
+ vertical_separator_ = AddChildView(std::make_unique<VerticalSeparator>());
if (submenu_arrow_image_view_)
submenu_arrow_image_view_->SetVisible(HasSubmenu());
@@ -1110,8 +1094,8 @@ void MenuItemView::PaintMinorIconAndText(
gfx::Canvas* canvas,
const MenuDelegate::LabelStyle& style) {
std::u16string minor_text = GetMinorText();
- const ui::ThemedVectorIcon minor_icon = GetMinorIcon();
- if (minor_text.empty() && minor_icon.empty())
+ const ui::ImageModel minor_icon = GetMinorIcon();
+ if (minor_text.empty() && minor_icon.IsEmpty())
return;
int available_height = height() - GetTopMargin() - GetBottomMargin();
@@ -1138,8 +1122,9 @@ void MenuItemView::PaintMinorIconAndText(
render_text->Draw(canvas);
}
- if (!minor_icon.empty()) {
- const gfx::ImageSkia image = minor_icon.GetImageSkia(GetNativeTheme());
+ if (!minor_icon.IsEmpty()) {
+ const gfx::ImageSkia image =
+ GetImageSkiaFromImageModel(minor_icon, GetNativeTheme());
int image_x = GetMirroredRect(minor_text_bounds).right() -
render_text->GetContentWidth() -
@@ -1376,7 +1361,7 @@ std::u16string MenuItemView::GetMinorText() const {
return minor_text_;
}
-ui::ThemedVectorIcon MenuItemView::GetMinorIcon() const {
+ui::ImageModel MenuItemView::GetMinorIcon() const {
return minor_icon_;
}
diff --git a/chromium/ui/views/controls/menu/menu_item_view.h b/chromium/ui/views/controls/menu/menu_item_view.h
index 0b1abd6f8c5..939a20dc5ed 100644
--- a/chromium/ui/views/controls/menu/menu_item_view.h
+++ b/chromium/ui/views/controls/menu/menu_item_view.h
@@ -12,8 +12,8 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/models/menu_separator_types.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/image/image_skia.h"
@@ -151,9 +151,8 @@ class VIEWS_EXPORT MenuItemView : public View {
const std::u16string& label,
const std::u16string& secondary_label,
const std::u16string& minor_text,
- const ui::ThemedVectorIcon& minor_icon,
- const gfx::ImageSkia& icon,
- const ui::ThemedVectorIcon& vector_icon,
+ const ui::ImageModel& minor_icon,
+ const ui::ImageModel& icon,
Type type,
ui::MenuSeparatorType separator_style);
@@ -225,7 +224,7 @@ class VIEWS_EXPORT MenuItemView : public View {
void SetMinorText(const std::u16string& minor_text);
// Sets the minor icon.
- void SetMinorIcon(const ui::ThemedVectorIcon& minor_icon);
+ void SetMinorIcon(const ui::ImageModel& minor_icon);
// Returns the type of this menu.
const Type& GetType() const { return type_; }
@@ -254,22 +253,13 @@ class VIEWS_EXPORT MenuItemView : public View {
// Sets the |tooltip| for a menu item view with |item_id| identifier.
void SetTooltip(const std::u16string& tooltip, int item_id);
- // Sets the icon for the descendant identified by item_id.
- void SetIcon(const gfx::ImageSkia& icon, int item_id);
-
// Sets the icon of this menu item.
- void SetIcon(const gfx::ImageSkia& icon);
-
- // Sets the icon as a vector icon which gets its color from the NativeTheme or
- // the included color.
- void SetIcon(const ui::ThemedVectorIcon& icon);
+ void SetIcon(const ui::ImageModel& icon);
// Sets the view used to render the icon. This clobbers any icon set via
// SetIcon(). MenuItemView takes ownership of |icon_view|.
void SetIconView(std::unique_ptr<ImageView> icon_view);
- void UpdateIconViewFromVectorIconAndTheme();
-
// Sets the command id of this menu item.
void SetCommand(int command) { command_ = command; }
@@ -295,8 +285,6 @@ class VIEWS_EXPORT MenuItemView : public View {
// dimensions.
int GetHeightForWidth(int width) const override;
- void OnThemeChanged() override;
-
// Returns the bounds of the submenu part of the ACTIONABLE_SUBMENU.
gfx::Rect GetSubmenuAreaOfActionableSubmenu() const;
@@ -452,7 +440,7 @@ class VIEWS_EXPORT MenuItemView : public View {
std::u16string GetMinorText() const;
// Returns the icon that should be displayed to the left of the minor text.
- ui::ThemedVectorIcon GetMinorIcon() const;
+ ui::ImageModel GetMinorIcon() const;
// Returns the text color for the current state. |minor| specifies if the
// minor text or the normal text is desired.
@@ -549,11 +537,7 @@ class VIEWS_EXPORT MenuItemView : public View {
std::u16string title_;
std::u16string secondary_title_;
std::u16string minor_text_;
- ui::ThemedVectorIcon minor_icon_;
-
- // The icon used for |icon_view_| when a vector icon has been set instead of a
- // gfx::Image.
- ui::ThemedVectorIcon vector_icon_;
+ ui::ImageModel minor_icon_;
// Does the title have a mnemonic? Only useful on the root menu item.
bool has_mnemonics_ = false;
@@ -614,7 +598,7 @@ class VIEWS_EXPORT MenuItemView : public View {
ImageView* submenu_arrow_image_view_ = nullptr;
// The forced visual selection state of this item, if any.
- base::Optional<bool> forced_visual_selection_;
+ absl::optional<bool> forced_visual_selection_;
// The vertical separator that separates the actionable and submenu regions of
// an ACTIONABLE_SUBMENU.
diff --git a/chromium/ui/views/controls/menu/menu_item_view_unittest.cc b/chromium/ui/views/controls/menu/menu_item_view_unittest.cc
index 32f5619c8b4..e03e2c5af20 100644
--- a/chromium/ui/views/controls/menu/menu_item_view_unittest.cc
+++ b/chromium/ui/views/controls/menu/menu_item_view_unittest.cc
@@ -251,9 +251,10 @@ TEST_F(TouchableMenuItemViewTest, MinAndMaxWidth) {
EXPECT_LT(item2_size.width(), max_menu_width);
// Test a title which is longer than the max touchable menu width.
- gfx::Size item3_size = AppendItemAndGetSize(
- 3, base::ASCIIToUTF16("Item3 Title that is longer than the maximum "
- "allowed context menu width"));
+ gfx::Size item3_size =
+ AppendItemAndGetSize(3,
+ u"Item3 Title that is longer than the maximum "
+ u"allowed context menu width");
EXPECT_EQ(item3_size.width(), max_menu_width);
}
@@ -400,27 +401,29 @@ class MenuItemViewPaintUnitTest : public ViewsTestBase {
TEST_F(MenuItemViewPaintUnitTest, MinorTextAndIconAssertionCoverage) {
auto AddItem = [this](auto label, auto secondary_label, auto minor_label,
auto minor_icon) {
- menu_item_view()->AddMenuItemAt(
- 0, 1000, base::ASCIIToUTF16(label), secondary_label, minor_label,
- minor_icon, gfx::ImageSkia(), ui::ThemedVectorIcon(),
- views::MenuItemView::Type::kNormal, ui::NORMAL_SEPARATOR);
+ menu_item_view()->AddMenuItemAt(0, 1000, label, secondary_label,
+ minor_label, minor_icon, ui::ImageModel(),
+ views::MenuItemView::Type::kNormal,
+ ui::NORMAL_SEPARATOR);
};
- AddItem("No secondary label, no minor content", std::u16string(),
- std::u16string(), ui::ThemedVectorIcon());
- AddItem("No secondary label, minor text only", std::u16string(),
- u"minor text", ui::ThemedVectorIcon());
- AddItem("No secondary label, minor icon only", std::u16string(),
- std::u16string(), ui::ThemedVectorIcon(&views::kMenuCheckIcon));
- AddItem("No secondary label, minor text and icon", std::u16string(),
- u"minor text", ui::ThemedVectorIcon(&views::kMenuCheckIcon));
- AddItem("Secondary label, no minor content", u"secondary label",
- std::u16string(), ui::ThemedVectorIcon());
- AddItem("Secondary label, minor text only", u"secondary label", u"minor text",
- ui::ThemedVectorIcon());
- AddItem("Secondary label, minor icon only", u"secondary label",
- std::u16string(), ui::ThemedVectorIcon(&views::kMenuCheckIcon));
- AddItem("Secondary label, minor text and icon", u"secondary label",
- u"minor text", ui::ThemedVectorIcon(&views::kMenuCheckIcon));
+ AddItem(u"No secondary label, no minor content", std::u16string(),
+ std::u16string(), ui::ImageModel());
+ AddItem(u"No secondary label, minor text only", std::u16string(),
+ u"minor text", ui::ImageModel());
+ AddItem(u"No secondary label, minor icon only", std::u16string(),
+ std::u16string(),
+ ui::ImageModel::FromVectorIcon(views::kMenuCheckIcon));
+ AddItem(u"No secondary label, minor text and icon", std::u16string(),
+ u"minor text", ui::ImageModel::FromVectorIcon(views::kMenuCheckIcon));
+ AddItem(u"Secondary label, no minor content", u"secondary label",
+ std::u16string(), ui::ImageModel());
+ AddItem(u"Secondary label, minor text only", u"secondary label",
+ u"minor text", ui::ImageModel());
+ AddItem(u"Secondary label, minor icon only", u"secondary label",
+ std::u16string(),
+ ui::ImageModel::FromVectorIcon(views::kMenuCheckIcon));
+ AddItem(u"Secondary label, minor text and icon", u"secondary label",
+ u"minor text", ui::ImageModel::FromVectorIcon(views::kMenuCheckIcon));
menu_runner()->RunMenuAt(widget(), nullptr, gfx::Rect(),
MenuAnchorPosition::kTopLeft,
diff --git a/chromium/ui/views/controls/menu/menu_model_adapter.cc b/chromium/ui/views/controls/menu/menu_model_adapter.cc
index fbd30c4914b..6dcbba931eb 100644
--- a/chromium/ui/views/controls/menu/menu_model_adapter.cc
+++ b/chromium/ui/views/controls/menu/menu_model_adapter.cc
@@ -4,15 +4,19 @@
#include "ui/views/controls/menu/menu_model_adapter.h"
+#include <list>
+#include <memory>
#include <utility>
#include "base/check.h"
#include "base/notreached.h"
+#include "ui/base/interaction/element_identifier.h"
#include "ui/base/models/menu_model.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/submenu_view.h"
+#include "ui/views/view_class_properties.h"
namespace views {
@@ -68,7 +72,7 @@ MenuItemView* MenuModelAdapter::AddMenuItemFromModelAt(ui::MenuModel* model,
MenuItemView* menu,
int menu_index,
int item_id) {
- base::Optional<MenuItemView::Type> type;
+ absl::optional<MenuItemView::Type> type;
ui::MenuModel::ItemType menu_type = model->GetTypeAt(model_index);
switch (menu_type) {
case ui::MenuModel::TYPE_TITLE:
@@ -99,31 +103,29 @@ MenuItemView* MenuModelAdapter::AddMenuItemFromModelAt(ui::MenuModel* model,
}
if (*type == MenuItemView::Type::kSeparator) {
- return menu->AddMenuItemAt(
- menu_index, item_id, std::u16string(), std::u16string(),
- std::u16string(), ui::ThemedVectorIcon(), gfx::ImageSkia(),
- ui::ThemedVectorIcon(), *type, model->GetSeparatorTypeAt(model_index));
+ return menu->AddMenuItemAt(menu_index, item_id, std::u16string(),
+ std::u16string(), std::u16string(),
+ ui::ImageModel(), ui::ImageModel(), *type,
+ model->GetSeparatorTypeAt(model_index));
}
ui::ImageModel icon = model->GetIconAt(model_index);
ui::ImageModel minor_icon = model->GetMinorIconAt(model_index);
- auto* menu_item_view = menu->AddMenuItemAt(
- menu_index, item_id, model->GetLabelAt(model_index),
- model->GetSecondaryLabelAt(model_index),
- model->GetMinorTextAt(model_index),
- minor_icon.IsVectorIcon()
- ? ui::ThemedVectorIcon(minor_icon.GetVectorIcon())
- : ui::ThemedVectorIcon(),
- icon.IsImage() ? *icon.GetImage().ToImageSkia() : gfx::ImageSkia(),
- icon.IsVectorIcon() ? ui::ThemedVectorIcon(icon.GetVectorIcon())
- : ui::ThemedVectorIcon(),
- *type, ui::NORMAL_SEPARATOR);
+ auto* menu_item_view =
+ menu->AddMenuItemAt(menu_index, item_id, model->GetLabelAt(model_index),
+ model->GetSecondaryLabelAt(model_index),
+ model->GetMinorTextAt(model_index), minor_icon, icon,
+ *type, ui::NORMAL_SEPARATOR);
if (model->IsAlertedAt(model_index))
menu_item_view->SetAlerted();
menu_item_view->set_is_new(model->IsNewFeatureAt(model_index));
menu_item_view->set_may_have_mnemonics(
model->MayHaveMnemonicsAt(model_index));
+ const ui::ElementIdentifier element_id =
+ model->GetElementIdentifierAt(model_index);
+ if (element_id)
+ menu_item_view->SetProperty(kElementIdentifierKey, element_id);
return menu_item_view;
}
diff --git a/chromium/ui/views/controls/menu/menu_runner.cc b/chromium/ui/views/controls/menu/menu_runner.cc
index 8ece8cc7058..31716d454d1 100644
--- a/chromium/ui/views/controls/menu/menu_runner.cc
+++ b/chromium/ui/views/controls/menu/menu_runner.cc
@@ -45,8 +45,17 @@ void MenuRunner::RunMenuAt(Widget* parent,
// If we are shown on mouse press, we will eat the subsequent mouse down and
// the parent widget will not be able to reset its state (it might have mouse
// capture from the mouse down). So we clear its state here.
- if (parent && parent->GetRootView())
- parent->GetRootView()->SetMouseAndGestureHandler(nullptr);
+ if (parent && parent->GetRootView()) {
+ auto* root_view = parent->GetRootView();
+ if (run_types_ & MenuRunner::SEND_GESTURE_EVENTS_TO_OWNER) {
+ // In this case, the menu owner instead of the menu should handle the
+ // incoming gesture events. Therefore we do not need to reset the gesture
+ // handler of `root_view`.
+ root_view->SetMouseHandler(nullptr);
+ } else {
+ root_view->SetMouseAndGestureHandler(nullptr);
+ }
+ }
if (runner_handler_.get()) {
runner_handler_->RunMenuAt(parent, button_controller, bounds, anchor,
diff --git a/chromium/ui/views/controls/menu/menu_runner_cocoa_unittest.mm b/chromium/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
index 2a88b2b4b2e..960601e1431 100644
--- a/chromium/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
+++ b/chromium/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
@@ -7,6 +7,7 @@
#import <Cocoa/Cocoa.h>
#include "base/bind.h"
+#include "base/i18n/rtl.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/chromium/ui/views/controls/menu/menu_runner_impl.cc b/chromium/ui/views/controls/menu/menu_runner_impl.cc
index e328789aac7..6e54d8d3c40 100644
--- a/chromium/ui/views/controls/menu/menu_runner_impl.cc
+++ b/chromium/ui/views/controls/menu/menu_runner_impl.cc
@@ -8,7 +8,6 @@
#include <utility>
#include "build/build_config.h"
-#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/platform/ax_platform_node_base.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/accessibility/view_accessibility.h"
@@ -74,7 +73,7 @@ bool IsAltPressed() {
namespace internal {
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
MenuRunnerImplInterface* MenuRunnerImplInterface::Create(
ui::MenuModel* menu_model,
int32_t run_types,
@@ -271,7 +270,7 @@ bool MenuRunnerImpl::ShouldShowMnemonics(int32_t run_types) {
show_mnemonics |= ui::win::IsAltPressed();
#elif defined(USE_X11) || defined(USE_OZONE)
show_mnemonics |= IsAltPressed();
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
show_mnemonics = false;
#endif
return show_mnemonics;
diff --git a/chromium/ui/views/controls/menu/menu_runner_impl_cocoa.mm b/chromium/ui/views/controls/menu/menu_runner_impl_cocoa.mm
index 1c6a01e65a9..d312eba7362 100644
--- a/chromium/ui/views/controls/menu/menu_runner_impl_cocoa.mm
+++ b/chromium/ui/views/controls/menu/menu_runner_impl_cocoa.mm
@@ -4,6 +4,7 @@
#import "ui/views/controls/menu/menu_runner_impl_cocoa.h"
+#include "base/i18n/rtl.h"
#include "base/mac/mac_util.h"
#import "base/message_loop/message_pump_mac.h"
#import "skia/ext/skia_utils_mac.h"
@@ -197,9 +198,7 @@ NSMutableAttributedString* MutableAttributedStringForMenuItemTitleString(
- (void)controllerWillAddItem:(NSMenuItem*)menuItem
fromModel:(ui::MenuModel*)model
atIndex:(NSInteger)index {
- static const bool newBadgeFeatureEnabled =
- base::FeatureList::IsEnabled(views::features::kEnableNewBadgeOnMenuItems);
- if (newBadgeFeatureEnabled && model->IsNewFeatureAt(index)) {
+ if (model->IsNewFeatureAt(index)) {
// /!\ WARNING /!\ Do not update this to use NSTextAttachment.image until
// macOS 10.15 is the minimum required OS. See the details on the class
// comment above.
diff --git a/chromium/ui/views/controls/menu/menu_runner_unittest.cc b/chromium/ui/views/controls/menu/menu_runner_unittest.cc
index dc01f76057c..bfc5b3dc72f 100644
--- a/chromium/ui/views/controls/menu/menu_runner_unittest.cc
+++ b/chromium/ui/views/controls/menu/menu_runner_unittest.cc
@@ -266,7 +266,7 @@ TEST_F(MenuRunnerTest, PrefixSelect) {
// This test is Mac-specific: Mac is the only platform where VKEY_SPACE
// activates menu items.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
TEST_F(MenuRunnerTest, SpaceActivatesItem) {
if (!MenuConfig::instance().all_menus_use_prefix_selection)
return;
@@ -291,7 +291,7 @@ TEST_F(MenuRunnerTest, SpaceActivatesItem) {
EXPECT_EQ(1, delegate->on_menu_closed_called());
EXPECT_NE(nullptr, delegate->on_menu_closed_menu());
}
-#endif // OS_APPLE
+#endif // OS_MAC
// Tests that attempting to nest a menu within a drag-and-drop menu does not
// cause a crash. Instead the drag and drop action should be canceled, and the
@@ -403,6 +403,7 @@ TEST_F(MenuRunnerWidgetTest, WidgetDoesntTakeCapture) {
internal::NativeWidgetPrivate::GetGlobalCapture(
widget()->GetNativeView()));
auto generator(EventGeneratorForWidget(widget()));
+ generator->MoveMouseTo(widget()->GetClientAreaBoundsInScreen().CenterPoint());
// Implicit capture should not be held by |widget|.
generator->PressLeftButton();
EXPECT_EQ(1, event_count_view()->GetEventCount(ui::ET_MOUSE_PRESSED));
@@ -435,7 +436,7 @@ TEST_F(MenuRunnerWidgetTest, ClearsMouseHandlerOnRun) {
// Click on the first view to show the menu.
auto generator(EventGeneratorForWidget(widget()));
- generator->MoveMouseTo(event_count_view()->bounds().CenterPoint());
+ generator->MoveMouseTo(event_count_view()->GetBoundsInScreen().CenterPoint());
generator->PressLeftButton();
// Pretend we dismissed the menu using normal means, as it doesn't matter.
@@ -449,7 +450,8 @@ TEST_F(MenuRunnerWidgetTest, ClearsMouseHandlerOnRun) {
generator.reset();
generator = EventGeneratorForWidget(widget());
- generator->MoveMouseTo(second_event_count_view->bounds().CenterPoint());
+ generator->MoveMouseTo(
+ second_event_count_view->GetBoundsInScreen().CenterPoint());
generator->PressLeftButton();
EXPECT_EQ(1, second_event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED));
}
diff --git a/chromium/ui/views/controls/menu/menu_scroll_view_container.cc b/chromium/ui/views/controls/menu/menu_scroll_view_container.cc
index 3f9f76315de..8522b0b4bb7 100644
--- a/chromium/ui/views/controls/menu/menu_scroll_view_container.cc
+++ b/chromium/ui/views/controls/menu/menu_scroll_view_container.cc
@@ -15,6 +15,8 @@
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/views/border.h"
@@ -24,8 +26,6 @@
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/layout/flex_layout.h"
-#include "ui/views/metadata/metadata_header_macros.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/round_rect_painter.h"
#include "ui/views/view.h"
#include "ui/views/view_class_properties.h"
@@ -237,6 +237,9 @@ MenuScrollViewContainer::MenuScrollViewContainer(SubmenuView* content_view)
arrow_ = BubbleBorderTypeFromAnchor(
content_view_->GetMenuItem()->GetMenuController()->GetAnchorPosition());
+ // The correct insets must be set before returning, since the menu creation
+ // code needs to know the final size of the menu. Calling CreateBorder() is
+ // the easiest way to do that.
CreateBorder();
}
@@ -264,8 +267,7 @@ gfx::Size MenuScrollViewContainer::CalculatePreferredSize() const {
void MenuScrollViewContainer::OnThemeChanged() {
View::OnThemeChanged();
- if (!HasBubbleBorder())
- CreateDefaultBorder();
+ CreateBorder();
}
void MenuScrollViewContainer::OnPaintBackground(gfx::Canvas* canvas) {
@@ -293,7 +295,7 @@ void MenuScrollViewContainer::GetAccessibleNodeData(ui::AXNodeData* node_data) {
// number of items inside it, we ignore the MenuScrollViewContainer (which
// holds the menu itself: the SubmenuView).
#if defined(OS_MAC)
- node_data->role = ax::mojom::Role::kIgnored;
+ node_data->role = ax::mojom::Role::kNone;
#else
node_data->role = ax::mojom::Role::kMenuBar;
#endif
@@ -361,10 +363,9 @@ void MenuScrollViewContainer::CreateDefaultBorder() {
int bottom_inset = GetFootnote() ? 0 : vertical_inset;
if (menu_config.use_outer_border) {
- SkColor color = GetNativeTheme()
- ? GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_MenuBorderColor)
- : gfx::kPlaceholderColor;
+ SkColor color = GetWidget() ? GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_MenuBorderColor)
+ : gfx::kPlaceholderColor;
SetBorder(views::CreateBorderPainter(
std::make_unique<views::RoundRectPainter>(color, corner_radius_),
gfx::Insets(vertical_inset, horizontal_inset, bottom_inset,
@@ -376,8 +377,10 @@ void MenuScrollViewContainer::CreateDefaultBorder() {
}
void MenuScrollViewContainer::CreateBubbleBorder() {
- const SkColor color = GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_MenuBackgroundColor);
+ const SkColor color = GetWidget()
+ ? GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_MenuBackgroundColor)
+ : gfx::kPlaceholderColor;
bubble_border_ =
new BubbleBorder(arrow_, BubbleBorder::STANDARD_SHADOW, color);
if (content_view_->GetMenuItem()
diff --git a/chromium/ui/views/controls/menu/menu_separator.cc b/chromium/ui/views/controls/menu/menu_separator.cc
index 98343f884a3..4ecf738a33e 100644
--- a/chromium/ui/views/controls/menu/menu_separator.cc
+++ b/chromium/ui/views/controls/menu/menu_separator.cc
@@ -8,10 +8,10 @@
#include "third_party/skia/include/core/SkColor.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/canvas.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/controls/menu/menu_config.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#if defined(OS_WIN)
#include "ui/display/win/dpi.h"
diff --git a/chromium/ui/views/controls/menu/menu_separator.h b/chromium/ui/views/controls/menu/menu_separator.h
index edf5c249212..73d160b4905 100644
--- a/chromium/ui/views/controls/menu/menu_separator.h
+++ b/chromium/ui/views/controls/menu/menu_separator.h
@@ -7,8 +7,8 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/models/menu_separator_types.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/view.h"
#include "ui/views/views_export.h"
diff --git a/chromium/ui/views/controls/menu/submenu_view.cc b/chromium/ui/views/controls/menu/submenu_view.cc
index 21d195a8a52..bd268333ce3 100644
--- a/chromium/ui/views/controls/menu/submenu_view.cc
+++ b/chromium/ui/views/controls/menu/submenu_view.cc
@@ -13,6 +13,7 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/ime/input_method.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/compositor/paint_recorder.h"
#include "ui/events/event.h"
#include "ui/gfx/canvas.h"
@@ -22,7 +23,6 @@
#include "ui/views/controls/menu/menu_host.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_scroll_view_container.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"
diff --git a/chromium/ui/views/controls/message_box_view.cc b/chromium/ui/views/controls/message_box_view.cc
index e585e4b557f..bfd76aceef7 100644
--- a/chromium/ui/views/controls/message_box_view.cc
+++ b/chromium/ui/views/controls/message_box_view.cc
@@ -13,10 +13,10 @@
#include "base/i18n/rtl.h"
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
-#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/border.h"
@@ -28,7 +28,6 @@
#include "ui/views/layout/fill_layout.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/layout/layout_provider.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/client_view.h"
#include "ui/views/window/dialog_delegate.h"
@@ -110,11 +109,11 @@ MessageBoxView::MessageBoxView(const std::u16string& message,
} else {
add_label(message, true, gfx::ALIGN_LEFT);
}
- auto scroll_view = std::make_unique<ScrollView>();
- scroll_view->ClipHeightTo(0, provider->GetDistanceMetric(
- DISTANCE_DIALOG_SCROLLABLE_AREA_MAX_HEIGHT));
- scroll_view->SetContents(std::move(message_contents));
- scroll_view_ = AddChildView(std::move(scroll_view));
+ scroll_view_ = AddChildView(std::make_unique<ScrollView>());
+ scroll_view_->ClipHeightTo(
+ 0,
+ provider->GetDistanceMetric(DISTANCE_DIALOG_SCROLLABLE_AREA_MAX_HEIGHT));
+ scroll_view_->SetContents(std::move(message_contents));
// Don't enable text selection if multiple labels are used, since text
// selection can't span multiple labels.
if (message_labels_.size() == 1u)
@@ -278,30 +277,31 @@ void MessageBoxView::ResetLayoutManager() {
layout->StartRow(0, kMessageViewColumnSetId);
layout->AddExistingView(scroll_view_);
- views::DialogContentType trailing_content_type = views::TEXT;
+ views::DialogContentType trailing_content_type =
+ views::DialogContentType::kText;
if (prompt_field_->GetVisible()) {
layout->AddPaddingRow(0, inter_row_vertical_spacing_);
layout->StartRow(0, kExtraViewColumnSetId);
layout->AddExistingView(prompt_field_);
- trailing_content_type = views::CONTROL;
+ trailing_content_type = views::DialogContentType::kControl;
}
if (checkbox_->GetVisible()) {
layout->AddPaddingRow(0, inter_row_vertical_spacing_);
layout->StartRow(0, kExtraViewColumnSetId);
layout->AddExistingView(checkbox_);
- trailing_content_type = views::TEXT;
+ trailing_content_type = views::DialogContentType::kText;
}
if (link_->GetVisible()) {
layout->AddPaddingRow(0, inter_row_vertical_spacing_);
layout->StartRow(0, kExtraViewColumnSetId);
layout->AddExistingView(link_);
- trailing_content_type = views::TEXT;
+ trailing_content_type = views::DialogContentType::kText;
}
gfx::Insets border_insets = provider->GetDialogInsetsForContentType(
- views::TEXT, trailing_content_type);
+ views::DialogContentType::kText, trailing_content_type);
// Horizontal insets have already been applied to the message contents and
// controls as padding columns. Only apply the missing vertical insets.
border_insets.Set(border_insets.top(), 0, border_insets.bottom(), 0);
diff --git a/chromium/ui/views/controls/message_box_view_unittest.cc b/chromium/ui/views/controls/message_box_view_unittest.cc
index d149ec813e9..481c128fd48 100644
--- a/chromium/ui/views/controls/message_box_view_unittest.cc
+++ b/chromium/ui/views/controls/message_box_view_unittest.cc
@@ -50,8 +50,8 @@ class MessageBoxViewTest : public ViewsTestBase {
TEST_F(MessageBoxViewTest, CheckMessageOnlySize) {
message_box_->SizeToPreferredSize();
- gfx::Insets box_border =
- provider_->GetDialogInsetsForContentType(views::TEXT, views::TEXT);
+ gfx::Insets box_border = provider_->GetDialogInsetsForContentType(
+ views::DialogContentType::kText, views::DialogContentType::kText);
gfx::Size scroll_size = message_box_->scroll_view_->size();
scroll_size.Enlarge(0, box_border.top() + box_border.bottom());
EXPECT_EQ(scroll_size, message_box_->size());
@@ -61,8 +61,8 @@ TEST_F(MessageBoxViewTest, CheckWithOptionalViewsSize) {
message_box_->SetPromptField(std::u16string());
message_box_->SizeToPreferredSize();
- gfx::Insets box_border =
- provider_->GetDialogInsetsForContentType(views::TEXT, views::CONTROL);
+ gfx::Insets box_border = provider_->GetDialogInsetsForContentType(
+ views::DialogContentType::kText, views::DialogContentType::kControl);
gfx::Size scroll_size = message_box_->scroll_view_->size();
gfx::Size prompt_size = message_box_->prompt_field_->size();
gfx::Size content_size(std::max(scroll_size.width(), prompt_size.width()),
@@ -76,8 +76,8 @@ TEST_F(MessageBoxViewTest, CheckWithOptionalViewsSize) {
message_box_->SetLink(u"Link to display", base::DoNothing());
message_box_->SizeToPreferredSize();
- box_border =
- provider_->GetDialogInsetsForContentType(views::TEXT, views::TEXT);
+ box_border = provider_->GetDialogInsetsForContentType(
+ views::DialogContentType::kText, views::DialogContentType::kText);
gfx::Size checkbox_size = message_box_->checkbox_->size();
gfx::Size link_size = message_box_->link_->size();
content_size =
@@ -106,8 +106,8 @@ TEST_F(MessageBoxViewTest, CheckInterRowHeightChange) {
int scroll_height = message_box_->scroll_view_->height();
int prompt_height = message_box_->prompt_field_->height();
- gfx::Insets box_border =
- provider_->GetDialogInsetsForContentType(views::TEXT, views::CONTROL);
+ gfx::Insets box_border = provider_->GetDialogInsetsForContentType(
+ views::DialogContentType::kText, views::DialogContentType::kControl);
int inter_row_spacing = message_box_->inter_row_vertical_spacing_;
EXPECT_EQ(
scroll_height + inter_row_spacing + prompt_height + box_border.height(),
diff --git a/chromium/ui/views/controls/native/native_view_host.cc b/chromium/ui/views/controls/native/native_view_host.cc
index 52f9b871022..1a85a7b4a83 100644
--- a/chromium/ui/views/controls/native/native_view_host.cc
+++ b/chromium/ui/views/controls/native/native_view_host.cc
@@ -10,9 +10,9 @@
#include "base/check.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/base/cursor/cursor.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/canvas.h"
#include "ui/views/controls/native/native_view_host_wrapper.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/painter.h"
#include "ui/views/widget/widget.h"
diff --git a/chromium/ui/views/controls/native/native_view_host_aura.cc b/chromium/ui/views/controls/native/native_view_host_aura.cc
index 740a26c2c82..aed3e3b1e64 100644
--- a/chromium/ui/views/controls/native/native_view_host_aura.cc
+++ b/chromium/ui/views/controls/native/native_view_host_aura.cc
@@ -8,8 +8,8 @@
#include <utility>
#include "base/check.h"
-#include "base/optional.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/window.h"
@@ -18,6 +18,7 @@
#include "ui/aura/window_targeter.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/hit_test.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/paint_recorder.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/controls/native/native_view_host.h"
@@ -120,7 +121,7 @@ void NativeViewHostAura::NativeViewDetaching(bool destroyed) {
// This method causes a succession of window tree changes. ScopedPause ensures
// that occlusion is recomputed at the end of the method instead of after each
// change.
- base::Optional<aura::WindowOcclusionTracker::ScopedPause> pause_occlusion;
+ absl::optional<aura::WindowOcclusionTracker::ScopedPause> pause_occlusion;
if (clipping_window_)
pause_occlusion.emplace();
diff --git a/chromium/ui/views/controls/native/native_view_host_mac.mm b/chromium/ui/views/controls/native/native_view_host_mac.mm
index ec20dd5e820..8335094fe36 100644
--- a/chromium/ui/views/controls/native/native_view_host_mac.mm
+++ b/chromium/ui/views/controls/native/native_view_host_mac.mm
@@ -8,6 +8,7 @@
#include "base/mac/foundation_util.h"
#import "ui/accessibility/platform/ax_platform_node_mac.h"
+#include "ui/compositor/layer.h"
#import "ui/views/cocoa/native_widget_mac_ns_window_host.h"
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/widget/native_widget_mac.h"
diff --git a/chromium/ui/views/controls/prefix_selector.cc b/chromium/ui/views/controls/prefix_selector.cc
index 014e9fd4a77..5ba1fdda8f5 100644
--- a/chromium/ui/views/controls/prefix_selector.cc
+++ b/chromium/ui/views/controls/prefix_selector.cc
@@ -87,6 +87,11 @@ gfx::Rect PrefixSelector::GetCaretBounds() const {
return rect;
}
+gfx::Rect PrefixSelector::GetSelectionBoundingBox() const {
+ NOTIMPLEMENTED_LOG_ONCE();
+ return gfx::Rect();
+}
+
bool PrefixSelector::GetCompositionCharacterBounds(uint32_t index,
gfx::Rect* rect) const {
// TextInputClient::GetCompositionCharacterBounds is expected to fill |rect|
@@ -201,8 +206,8 @@ void PrefixSelector::SetActiveCompositionForAccessibility(
bool is_composition_committed) {}
void PrefixSelector::GetActiveTextInputControlLayoutBounds(
- base::Optional<gfx::Rect>* control_bounds,
- base::Optional<gfx::Rect>* selection_bounds) {}
+ absl::optional<gfx::Rect>* control_bounds,
+ absl::optional<gfx::Rect>* selection_bounds) {}
#endif
void PrefixSelector::OnTextInput(const std::u16string& text) {
diff --git a/chromium/ui/views/controls/prefix_selector.h b/chromium/ui/views/controls/prefix_selector.h
index 390b23fca20..077dbe13226 100644
--- a/chromium/ui/views/controls/prefix_selector.h
+++ b/chromium/ui/views/controls/prefix_selector.h
@@ -56,6 +56,7 @@ class VIEWS_EXPORT PrefixSelector : public ui::TextInputClient {
int GetTextInputFlags() const override;
bool CanComposeInline() const override;
gfx::Rect GetCaretBounds() const override;
+ gfx::Rect GetSelectionBoundingBox() const override;
bool GetCompositionCharacterBounds(uint32_t index,
gfx::Rect* rect) const override;
bool HasCompositionText() const override;
@@ -92,8 +93,8 @@ class VIEWS_EXPORT PrefixSelector : public ui::TextInputClient {
#if defined(OS_WIN)
void GetActiveTextInputControlLayoutBounds(
- base::Optional<gfx::Rect>* control_bounds,
- base::Optional<gfx::Rect>* selection_bounds) override;
+ absl::optional<gfx::Rect>* control_bounds,
+ absl::optional<gfx::Rect>* selection_bounds) override;
void SetActiveCompositionForAccessibility(
const gfx::Range& range,
const std::u16string& active_composition_text,
diff --git a/chromium/ui/views/controls/progress_bar.cc b/chromium/ui/views/controls/progress_bar.cc
index 00b38aa71de..a4d431ae3f7 100644
--- a/chromium/ui/views/controls/progress_bar.cc
+++ b/chromium/ui/views/controls/progress_bar.cc
@@ -17,11 +17,12 @@
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/animation/linear_animation.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_utils.h"
+#include "ui/gfx/skia_util.h"
#include "ui/native_theme/native_theme.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/widget/widget.h"
namespace views {
@@ -264,8 +265,8 @@ void ProgressBar::MaybeNotifyAccessibilityValueChanged() {
}
BEGIN_METADATA(ProgressBar, View)
-ADD_PROPERTY_METADATA(SkColor, ForegroundColor, metadata::SkColorConverter)
-ADD_PROPERTY_METADATA(SkColor, BackgroundColor, metadata::SkColorConverter)
+ADD_PROPERTY_METADATA(SkColor, ForegroundColor, ui::metadata::SkColorConverter)
+ADD_PROPERTY_METADATA(SkColor, BackgroundColor, ui::metadata::SkColorConverter)
END_METADATA
} // namespace views
diff --git a/chromium/ui/views/controls/progress_bar.h b/chromium/ui/views/controls/progress_bar.h
index b57af1f1355..1f8a24dbecc 100644
--- a/chromium/ui/views/controls/progress_bar.h
+++ b/chromium/ui/views/controls/progress_bar.h
@@ -9,7 +9,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/views/view.h"
@@ -72,8 +72,8 @@ class VIEWS_EXPORT ProgressBar : public View, public gfx::AnimationDelegate {
const bool allow_round_corner_;
- base::Optional<SkColor> foreground_color_;
- base::Optional<SkColor> background_color_;
+ absl::optional<SkColor> foreground_color_;
+ absl::optional<SkColor> background_color_;
std::unique_ptr<gfx::LinearAnimation> indeterminate_bar_animation_;
diff --git a/chromium/ui/views/controls/resize_area.cc b/chromium/ui/views/controls/resize_area.cc
index 10d404f623a..18fa5c11bcb 100644
--- a/chromium/ui/views/controls/resize_area.cc
+++ b/chromium/ui/views/controls/resize_area.cc
@@ -4,11 +4,12 @@
#include "ui/views/controls/resize_area.h"
+#include "base/i18n/rtl.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/cursor/cursor.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/views/controls/resize_area_delegate.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/native_cursor.h"
namespace views {
diff --git a/chromium/ui/views/controls/resize_area.h b/chromium/ui/views/controls/resize_area.h
index 77567910b90..fd951515c12 100644
--- a/chromium/ui/views/controls/resize_area.h
+++ b/chromium/ui/views/controls/resize_area.h
@@ -5,7 +5,6 @@
#ifndef UI_VIEWS_CONTROLS_RESIZE_AREA_H_
#define UI_VIEWS_CONTROLS_RESIZE_AREA_H_
-#include <string>
#include "base/macros.h"
#include "ui/views/view.h"
diff --git a/chromium/ui/views/controls/resize_area_unittest.cc b/chromium/ui/views/controls/resize_area_unittest.cc
index fc382447e4c..300a6751c21 100644
--- a/chromium/ui/views/controls/resize_area_unittest.cc
+++ b/chromium/ui/views/controls/resize_area_unittest.cc
@@ -17,7 +17,7 @@
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_utils.h"
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
#include "ui/aura/window.h"
#endif
@@ -147,7 +147,7 @@ void ResizeAreaTest::TearDown() {
}
// TODO(tdanderson): Enable these tests on OSX. See crbug.com/710475.
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// Verifies the correct calls have been made to
// TestResizeAreaDelegate::OnResize() for a sequence of mouse events
// corresponding to a successful resize operation.
@@ -201,6 +201,6 @@ TEST_F(ResizeAreaTest, NoDragOnGestureTap) {
EXPECT_EQ(0, resize_amount());
}
-#endif // !defined(OS_APPLE)
+#endif // !defined(OS_MAC)
} // namespace views
diff --git a/chromium/ui/views/controls/scroll_view.cc b/chromium/ui/views/controls/scroll_view.cc
index dd9827ffe0e..df0bde713d7 100644
--- a/chromium/ui/views/controls/scroll_view.cc
+++ b/chromium/ui/views/controls/scroll_view.cc
@@ -9,13 +9,17 @@
#include "base/bind.h"
#include "base/check_op.h"
#include "base/feature_list.h"
+#include "base/i18n/rtl.h"
#include "base/macros.h"
#include "base/numerics/ranges.h"
#include "build/build_config.h"
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/ui_base_features.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/overscroll/scroll_input_handler.h"
#include "ui/events/event.h"
#include "ui/gfx/canvas.h"
@@ -23,8 +27,6 @@
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/focus_ring.h"
-#include "ui/views/metadata/metadata_header_macros.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
@@ -157,13 +159,6 @@ class ScrollView::Viewport : public View {
scroll_view_->ScrollContentsRegionToBeVisible(scroll_rect);
}
- // TODO(https://crbug.com/947053): this override should not be necessary, but
- // there are some assumptions that this calls Layout().
- void ChildPreferredSizeChanged(View* child) override {
- if (parent())
- parent()->Layout();
- }
-
void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) override {
if (details.is_add && GetIsContentsViewport() && Contains(details.parent))
@@ -194,8 +189,8 @@ ScrollView::ScrollView()
: ScrollWithLayers::kDisabled) {}
ScrollView::ScrollView(ScrollWithLayers scroll_with_layers)
- : horiz_sb_(PlatformStyle::CreateScrollBar(true)),
- vert_sb_(PlatformStyle::CreateScrollBar(false)),
+ : horiz_sb_(AddChildView(PlatformStyle::CreateScrollBar(true))),
+ vert_sb_(AddChildView(PlatformStyle::CreateScrollBar(false))),
corner_view_(std::make_unique<ScrollCornerView>()),
scroll_with_layers_enabled_(scroll_with_layers ==
ScrollWithLayers::kEnabled) {
@@ -205,11 +200,11 @@ ScrollView::ScrollView(ScrollWithLayers scroll_with_layers)
// sure the field is initialized.
auto contents_viewport = std::make_unique<Viewport>(this);
contents_viewport_ = contents_viewport.get();
- AddChildView(std::move(contents_viewport));
+ // Add content view port as the first child, so that the scollbars can
+ // overlay it.
+ AddChildViewAt(std::move(contents_viewport), 0);
header_viewport_ = AddChildView(std::make_unique<Viewport>(this));
- // Don't add the scrollbars as children until we discover we need them
- // (ShowOrHideScrollBar).
horiz_sb_->SetVisible(false);
horiz_sb_->set_controller(this);
vert_sb_->SetVisible(false);
@@ -234,7 +229,6 @@ ScrollView::ScrollView(ScrollWithLayers scroll_with_layers)
more_content_right_->SetPaintToLayer();
more_content_bottom_->SetPaintToLayer();
}
- UpdateBackground();
focus_ring_ = FocusRing::Install(this);
focus_ring_->SetHasFocusPredicate([](View* view) -> bool {
@@ -302,21 +296,21 @@ void ScrollView::SetHeader(std::nullptr_t) {
SetHeaderImpl(nullptr);
}
-void ScrollView::SetBackgroundColor(const base::Optional<SkColor>& color) {
+void ScrollView::SetBackgroundColor(const absl::optional<SkColor>& color) {
if (background_color_ == color && !background_color_id_)
return;
background_color_ = color;
- background_color_id_ = base::nullopt;
+ background_color_id_ = absl::nullopt;
UpdateBackground();
OnPropertyChanged(&background_color_, kPropertyEffectsPaint);
}
void ScrollView::SetBackgroundThemeColorId(
- const base::Optional<ui::NativeTheme::ColorId>& color_id) {
+ const absl::optional<ui::NativeTheme::ColorId>& color_id) {
if (background_color_id_ == color_id && !background_color_)
return;
background_color_id_ = color_id;
- background_color_ = base::nullopt;
+ background_color_ = absl::nullopt;
UpdateBackground();
OnPropertyChanged(&background_color_id_, kPropertyEffectsPaint);
}
@@ -416,27 +410,28 @@ View* ScrollView::SetCustomOverflowIndicator(OverflowIndicatorAlignment side,
}
void ScrollView::ClipHeightTo(int min_height, int max_height) {
+ if (min_height != min_height_ || max_height != max_height_)
+ PreferredSizeChanged();
+
min_height_ = min_height;
max_height_ = max_height;
}
int ScrollView::GetScrollBarLayoutWidth() const {
- return vert_sb_ && !vert_sb_->OverlapsContent() ? vert_sb_->GetThickness()
- : 0;
+ return vert_sb_->OverlapsContent() ? 0 : vert_sb_->GetThickness();
}
int ScrollView::GetScrollBarLayoutHeight() const {
- return horiz_sb_ && !horiz_sb_->OverlapsContent() ? horiz_sb_->GetThickness()
- : 0;
+ return horiz_sb_->OverlapsContent() ? 0 : horiz_sb_->GetThickness();
}
ScrollBar* ScrollView::SetHorizontalScrollBar(
std::unique_ptr<ScrollBar> horiz_sb) {
- DCHECK(horiz_sb);
horiz_sb->SetVisible(horiz_sb_->GetVisible());
horiz_sb->set_controller(this);
- horiz_sb_ = std::move(horiz_sb);
- return horiz_sb_.get();
+ RemoveChildViewT(horiz_sb_);
+ horiz_sb_ = AddChildView(std::move(horiz_sb));
+ return horiz_sb_;
}
ScrollBar* ScrollView::SetVerticalScrollBar(
@@ -444,8 +439,9 @@ ScrollBar* ScrollView::SetVerticalScrollBar(
DCHECK(vert_sb);
vert_sb->SetVisible(vert_sb_->GetVisible());
vert_sb->set_controller(this);
- vert_sb_ = std::move(vert_sb);
- return vert_sb_.get();
+ RemoveChildViewT(vert_sb_);
+ vert_sb_ = AddChildView(std::move(vert_sb));
+ return vert_sb_;
}
void ScrollView::SetHasFocusIndicator(bool has_focus_indicator) {
@@ -467,12 +463,11 @@ void ScrollView::RemoveScrollViewObserver(Observer* observer) {
}
gfx::Size ScrollView::CalculatePreferredSize() const {
- if (!is_bounded())
- return View::CalculatePreferredSize();
-
- gfx::Size size = contents_->GetPreferredSize();
- size.SetToMax(gfx::Size(size.width(), min_height_));
- size.SetToMin(gfx::Size(size.width(), max_height_));
+ gfx::Size size = contents_ ? contents_->GetPreferredSize() : gfx::Size();
+ if (is_bounded()) {
+ size.SetToMax(gfx::Size(size.width(), min_height_));
+ size.SetToMin(gfx::Size(size.width(), max_height_));
+ }
gfx::Insets insets = GetInsets();
size.Enlarge(insets.width(), insets.height());
return size;
@@ -484,7 +479,8 @@ int ScrollView::GetHeightForWidth(int width) const {
gfx::Insets insets = GetInsets();
width = std::max(0, width - insets.width());
- int height = contents_->GetHeightForWidth(width) + insets.height();
+ int height = contents_ ? contents_->GetHeightForWidth(width) + insets.height()
+ : insets.height();
return base::ClampToRange(height, min_height_, max_height_);
}
@@ -493,7 +489,7 @@ void ScrollView::Layout() {
// if its OverlapsContent matches other bar's.
if (horizontal_scroll_bar_mode_ == ScrollBarMode::kEnabled &&
vertical_scroll_bar_mode_ == ScrollBarMode::kEnabled) {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// On Mac, scrollbars may update their style one at a time, so they may
// temporarily be of different types. Refuse to lay out at this point.
if (horiz_sb_->OverlapsContent() != vert_sb_->OverlapsContent())
@@ -509,7 +505,7 @@ void ScrollView::Layout() {
if (is_bounded()) {
int content_width = available_rect.width();
int content_height = contents_->GetHeightForWidth(content_width);
- if (content_height > height()) {
+ if (content_height > available_rect.height()) {
content_width = std::max(content_width - GetScrollBarLayoutWidth(), 0);
content_height = contents_->GetHeightForWidth(content_width);
}
@@ -579,8 +575,8 @@ void ScrollView::Layout() {
bool corner_view_required =
horiz_sb_required && vert_sb_required && !vert_sb_->OverlapsContent();
// Take action.
- SetControlVisibility(horiz_sb_.get(), horiz_sb_required);
- SetControlVisibility(vert_sb_.get(), vert_sb_required);
+ horiz_sb_->SetVisible(horiz_sb_required);
+ vert_sb_->SetVisible(vert_sb_required);
SetControlVisibility(corner_view_.get(), corner_view_required);
// Default.
@@ -748,10 +744,8 @@ void ScrollView::OnScrollEvent(ui::ScrollEvent* event) {
// A direction might not be known when the event stream starts, notify both
// scrollbars that they may be about scroll, or that they may need to cancel
// UI feedback once the scrolling direction is known.
- if (horiz_sb_)
- horiz_sb_->ObserveScrollEvent(e);
- if (vert_sb_)
- vert_sb_->ObserveScrollEvent(e);
+ horiz_sb_->ObserveScrollEvent(e);
+ vert_sb_->ObserveScrollEvent(e);
// Need to copy state back to original event.
if (e.handled())
@@ -789,8 +783,7 @@ void ScrollView::OnGestureEvent(ui::GestureEvent* event) {
void ScrollView::OnThemeChanged() {
View::OnThemeChanged();
UpdateBorder();
- if (background_color_id_)
- UpdateBackground();
+ UpdateBackground();
}
void ScrollView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
@@ -798,55 +791,34 @@ void ScrollView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
if (!contents_)
return;
- ScrollBar* horizontal = horizontal_scroll_bar();
- if (horizontal) {
- node_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollX,
- CurrentOffset().x());
- node_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollXMin,
- horizontal->GetMinPosition());
- node_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollXMax,
- horizontal->GetMaxPosition());
- }
- ScrollBar* vertical = vertical_scroll_bar();
- if (vertical) {
- node_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollY,
- CurrentOffset().y());
- node_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollYMin,
- vertical->GetMinPosition());
- node_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollYMax,
- vertical->GetMaxPosition());
- }
- if (horizontal || vertical)
- node_data->AddBoolAttribute(ax::mojom::BoolAttribute::kScrollable, true);
+ node_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollX,
+ CurrentOffset().x());
+ node_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollXMin,
+ horiz_sb_->GetMinPosition());
+ node_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollXMax,
+ horiz_sb_->GetMaxPosition());
+ node_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollY,
+ CurrentOffset().y());
+ node_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollYMin,
+ vert_sb_->GetMinPosition());
+ node_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollYMax,
+ vert_sb_->GetMaxPosition());
+ node_data->AddBoolAttribute(ax::mojom::BoolAttribute::kScrollable, true);
}
bool ScrollView::HandleAccessibleAction(const ui::AXActionData& action_data) {
if (!contents_)
return View::HandleAccessibleAction(action_data);
- ScrollBar* horizontal = horizontal_scroll_bar();
- ScrollBar* vertical = vertical_scroll_bar();
switch (action_data.action) {
case ax::mojom::Action::kScrollLeft:
- if (horizontal)
- return horizontal->ScrollByAmount(ScrollBar::ScrollAmount::kPrevPage);
- else
- return false;
+ return horiz_sb_->ScrollByAmount(ScrollBar::ScrollAmount::kPrevPage);
case ax::mojom::Action::kScrollRight:
- if (horizontal)
- return horizontal->ScrollByAmount(ScrollBar::ScrollAmount::kNextPage);
- else
- return false;
+ return horiz_sb_->ScrollByAmount(ScrollBar::ScrollAmount::kNextPage);
case ax::mojom::Action::kScrollUp:
- if (vertical)
- return vertical->ScrollByAmount(ScrollBar::ScrollAmount::kPrevPage);
- else
- return false;
+ return vert_sb_->ScrollByAmount(ScrollBar::ScrollAmount::kPrevPage);
case ax::mojom::Action::kScrollDown:
- if (vertical)
- return vertical->ScrollByAmount(ScrollBar::ScrollAmount::kNextPage);
- else
- return false;
+ return vert_sb_->ScrollByAmount(ScrollBar::ScrollAmount::kNextPage);
case ax::mojom::Action::kSetScrollOffset:
ScrollToOffset(gfx::ScrollOffset(action_data.target_point.x(),
action_data.target_point.y()));
@@ -862,13 +834,13 @@ void ScrollView::ScrollToPosition(ScrollBar* source, int position) {
return;
gfx::ScrollOffset offset = CurrentOffset();
- if (source == horiz_sb_.get() && IsHorizontalScrollEnabled()) {
+ if (source == horiz_sb_ && IsHorizontalScrollEnabled()) {
position = AdjustPosition(offset.x(), position, contents_->width(),
contents_viewport_->width());
if (offset.x() == position)
return;
offset.set_x(position);
- } else if (source == vert_sb_.get() && IsVerticalScrollEnabled()) {
+ } else if (source == vert_sb_ && IsVerticalScrollEnabled()) {
position = AdjustPosition(offset.y(), position, contents_->height(),
contents_viewport_->height());
if (offset.y() == position)
@@ -893,6 +865,11 @@ int ScrollView::GetScrollIncrement(ScrollBar* source,
: contents_viewport_->height() / 5;
}
+void ScrollView::OnScrollEnded() {
+ for (auto& observer : observers_)
+ observer.OnContentsScrollEnded();
+}
+
bool ScrollView::DoesViewportOrScrollViewHaveLayer() const {
return layer() || contents_viewport_->layer();
}
@@ -916,13 +893,10 @@ void ScrollView::SetHeaderOrContents(View* parent,
View** member) {
delete *member;
if (new_view.get())
- *member = parent->AddChildView(std::move(new_view));
+ *member = parent->AddChildViewAt(std::move(new_view), 0);
else
*member = nullptr;
- // TODO(https://crbug.com/947053): this should call InvalidateLayout(), but
- // there are some assumptions that it call Layout(). These assumptions should
- // be updated.
- Layout();
+ InvalidateLayout();
}
void ScrollView::ScrollContentsRegionToBeVisible(const gfx::Rect& rect) {
@@ -1067,25 +1041,15 @@ bool ScrollView::ScrollsWithLayers() const {
}
bool ScrollView::IsHorizontalScrollEnabled() const {
- switch (horizontal_scroll_bar_mode_) {
- case ScrollBarMode::kDisabled:
- return false;
- case ScrollBarMode::kHiddenButEnabled:
- return bool{horiz_sb_};
- case ScrollBarMode::kEnabled:
- return horiz_sb_ && horiz_sb_->GetVisible();
- }
+ return horizontal_scroll_bar_mode_ == ScrollBarMode::kHiddenButEnabled ||
+ (horizontal_scroll_bar_mode_ == ScrollBarMode::kEnabled &&
+ horiz_sb_->GetVisible());
}
bool ScrollView::IsVerticalScrollEnabled() const {
- switch (vertical_scroll_bar_mode_) {
- case ScrollBarMode::kDisabled:
- return false;
- case ScrollBarMode::kHiddenButEnabled:
- return bool{vert_sb_};
- case ScrollBarMode::kEnabled:
- return vert_sb_ && vert_sb_->GetVisible();
- }
+ return vertical_scroll_bar_mode_ == ScrollBarMode::kHiddenButEnabled ||
+ (vertical_scroll_bar_mode_ == ScrollBarMode::kEnabled &&
+ vert_sb_->GetVisible());
}
void ScrollView::EnableViewportLayer() {
@@ -1143,7 +1107,10 @@ void ScrollView::UpdateBorder() {
}
void ScrollView::UpdateBackground() {
- const base::Optional<SkColor> background_color = GetBackgroundColor();
+ if (!GetWidget())
+ return;
+
+ const absl::optional<SkColor> background_color = GetBackgroundColor();
auto create_background = [background_color]() {
return background_color ? CreateSolidBackground(background_color.value())
@@ -1160,16 +1127,15 @@ void ScrollView::UpdateBackground() {
if (contents_viewport_->layer()) {
contents_viewport_->layer()->SetFillsBoundsOpaquely(!!background_color);
}
- SchedulePaint();
}
-base::Optional<SkColor> ScrollView::GetBackgroundColor() const {
+absl::optional<SkColor> ScrollView::GetBackgroundColor() const {
return background_color_id_
? GetNativeTheme()->GetSystemColor(background_color_id_.value())
: background_color_;
}
-base::Optional<ui::NativeTheme::ColorId> ScrollView::GetBackgroundThemeColorId()
+absl::optional<ui::NativeTheme::ColorId> ScrollView::GetBackgroundThemeColorId()
const {
return background_color_id_;
}
@@ -1218,8 +1184,8 @@ void ScrollView::UpdateOverflowIndicatorVisibility(
BEGIN_METADATA(ScrollView, View)
ADD_READONLY_PROPERTY_METADATA(int, MinHeight)
ADD_READONLY_PROPERTY_METADATA(int, MaxHeight)
-ADD_PROPERTY_METADATA(base::Optional<SkColor>, BackgroundColor)
-ADD_PROPERTY_METADATA(base::Optional<ui::NativeTheme::ColorId>,
+ADD_PROPERTY_METADATA(absl::optional<SkColor>, BackgroundColor)
+ADD_PROPERTY_METADATA(absl::optional<ui::NativeTheme::ColorId>,
BackgroundThemeColorId)
ADD_PROPERTY_METADATA(bool, DrawOverflowIndicator)
ADD_PROPERTY_METADATA(bool, HasFocusIndicator)
diff --git a/chromium/ui/views/controls/scroll_view.h b/chromium/ui/views/controls/scroll_view.h
index c7227c266b7..3667b2b896c 100644
--- a/chromium/ui/views/controls/scroll_view.h
+++ b/chromium/ui/views/controls/scroll_view.h
@@ -12,12 +12,16 @@
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/controls/focus_ring.h"
#include "ui/views/controls/scrollbar/scroll_bar.h"
#include "ui/views/controls/separator.h"
+namespace cc {
+struct ElementId;
+}
+
namespace gfx {
class ScrollOffset;
}
@@ -65,8 +69,25 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
class Observer {
public:
- // Called when |contents_| scrolled.
+ // Called when |contents_| scrolled. This can be triggered by each single
+ // event that is able to scroll the contents. KeyEvents like ui::VKEY_LEFT,
+ // ui::VKEY_RIGHT, or only ui::ET_MOUSEWHEEL will only trigger this function
+ // but not OnContentsScrollEnded below, since they do not belong to any
+ // events sequence. This function will also be triggered by each
+ // ui::ET_GESTURE_SCROLL_UPDATE event in the gesture scroll sequence or
+ // each ui::ET_MOUSEWHEEL event that associated with the ScrollEvent in the
+ // scroll events sequence while the OnContentsScrollEnded below will only be
+ // triggered once at the end of the events sequence.
virtual void OnContentsScrolled() {}
+
+ // Called at the end of a sequence of events that are generated to scroll
+ // the contents. The gesture scroll sequence {ui::ET_GESTURE_SCROLL_BEGIN,
+ // ui::ET_GESTURE_SCROLL_UPDATE, ..., ui::ET_GESTURE_SCROLL_UPDATE,
+ // ui::ET_GESTURE_SCROLL_END or ui::ET_SCROLL_FLING_START} or the scroll
+ // events sequence {ui::ET_SCROLL_FLING_CANCEL, ui::ET_SCROLL, ...,
+ // ui::ET_SCROLL, ui::ET_SCROLL_FLING_START} both will trigger this function
+ // on the events sequence end.
+ virtual void OnContentsScrollEnded() {}
};
ScrollView();
@@ -115,14 +136,14 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
// called the background color comes from the theme (and changes if the
// theme changes).
// . By way of setting an explicit color, i.e. SetBackgroundColor(). Use
- // base::nullopt if you don't want any color, but be warned this
+ // absl::nullopt if you don't want any color, but be warned this
// produces awful results when layers are used with subpixel rendering.
- base::Optional<SkColor> GetBackgroundColor() const;
- void SetBackgroundColor(const base::Optional<SkColor>& color);
+ absl::optional<SkColor> GetBackgroundColor() const;
+ void SetBackgroundColor(const absl::optional<SkColor>& color);
- base::Optional<ui::NativeTheme::ColorId> GetBackgroundThemeColorId() const;
+ absl::optional<ui::NativeTheme::ColorId> GetBackgroundThemeColorId() const;
void SetBackgroundThemeColorId(
- const base::Optional<ui::NativeTheme::ColorId>& color_id);
+ const absl::optional<ui::NativeTheme::ColorId>& color_id);
// Returns the visible region of the content View.
gfx::Rect GetVisibleRect() const;
@@ -163,11 +184,11 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
int GetScrollBarLayoutWidth() const;
int GetScrollBarLayoutHeight() const;
- // Returns the horizontal/vertical scrollbar. This may return null.
- ScrollBar* horizontal_scroll_bar() { return horiz_sb_.get(); }
- const ScrollBar* horizontal_scroll_bar() const { return horiz_sb_.get(); }
- ScrollBar* vertical_scroll_bar() { return vert_sb_.get(); }
- const ScrollBar* vertical_scroll_bar() const { return vert_sb_.get(); }
+ // Returns the horizontal/vertical scrollbar.
+ ScrollBar* horizontal_scroll_bar() { return horiz_sb_; }
+ const ScrollBar* horizontal_scroll_bar() const { return horiz_sb_; }
+ ScrollBar* vertical_scroll_bar() { return vert_sb_; }
+ const ScrollBar* vertical_scroll_bar() const { return vert_sb_; }
// Customize the scrollbar design. |horiz_sb| and |vert_sb| cannot be null.
ScrollBar* SetHorizontalScrollBar(std::unique_ptr<ScrollBar> horiz_sb);
@@ -197,6 +218,11 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
int GetScrollIncrement(ScrollBar* source,
bool is_page,
bool is_positive) override;
+ void OnScrollEnded() override;
+
+ bool is_scrolling() const {
+ return horiz_sb_->is_scrolling() || vert_sb_->is_scrolling();
+ }
private:
friend class test::ScrollViewTestApi;
@@ -287,10 +313,10 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
View* header_viewport_ = nullptr;
// Horizontal scrollbar.
- std::unique_ptr<ScrollBar> horiz_sb_;
+ ScrollBar* horiz_sb_;
// Vertical scrollbar.
- std::unique_ptr<ScrollBar> vert_sb_;
+ ScrollBar* vert_sb_;
// Corner view.
std::unique_ptr<View> corner_view_;
@@ -313,8 +339,8 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
int max_height_ = -1;
// See description of SetBackgroundColor() for details.
- base::Optional<SkColor> background_color_;
- base::Optional<ui::NativeTheme::ColorId> background_color_id_ =
+ absl::optional<SkColor> background_color_;
+ absl::optional<ui::NativeTheme::ColorId> background_color_id_ =
ui::NativeTheme::kColorId_DialogBackground;
// How to handle the case when the contents overflow the viewport.
@@ -351,13 +377,13 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
BEGIN_VIEW_BUILDER(VIEWS_EXPORT, ScrollView, View)
VIEW_BUILDER_VIEW_TYPE_PROPERTY(View, Contents)
VIEW_BUILDER_VIEW_TYPE_PROPERTY(View, Header)
-VIEW_BUILDER_PROPERTY(base::Optional<ui::NativeTheme::ColorId>,
+VIEW_BUILDER_PROPERTY(absl::optional<ui::NativeTheme::ColorId>,
BackgroundThemeColorId)
VIEW_BUILDER_PROPERTY(ScrollView::ScrollBarMode, HorizontalScrollBarMode)
VIEW_BUILDER_PROPERTY(ScrollView::ScrollBarMode, VerticalScrollBarMode)
VIEW_BUILDER_PROPERTY(bool, TreatAllScrollEventsAsHorizontal)
VIEW_BUILDER_PROPERTY(bool, DrawOverflowIndicator)
-VIEW_BUILDER_PROPERTY(base::Optional<SkColor>, BackgroundColor)
+VIEW_BUILDER_PROPERTY(absl::optional<SkColor>, BackgroundColor)
VIEW_BUILDER_VIEW_PROPERTY(ScrollBar, HorizontalScrollBar)
VIEW_BUILDER_VIEW_PROPERTY(ScrollBar, VerticalScrollBar)
VIEW_BUILDER_PROPERTY(bool, HasFocusIndicator)
diff --git a/chromium/ui/views/controls/scroll_view_unittest.cc b/chromium/ui/views/controls/scroll_view_unittest.cc
index 2e6aa82878c..6823b9633dd 100644
--- a/chromium/ui/views/controls/scroll_view_unittest.cc
+++ b/chromium/ui/views/controls/scroll_view_unittest.cc
@@ -9,7 +9,6 @@
#include <utility>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/icu_test_util.h"
#include "base/test/scoped_feature_list.h"
@@ -18,7 +17,9 @@
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/ui_base_features.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/events/test/event_generator.h"
#include "ui/views/border.h"
@@ -30,7 +31,7 @@
#include "ui/views/test/widget_test.h"
#include "ui/views/view_test_api.h"
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#include "ui/base/test/scoped_preferred_scroller_style_mac.h"
#endif
@@ -247,7 +248,7 @@ class ScrollViewTest : public ViewsTestBase {
}
protected:
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
void SetOverlayScrollersEnabled(bool enabled) {
// Ensure the old scroller override is destroyed before creating a new one.
// Otherwise, the swizzlers are interleaved and restore incorrect methods.
@@ -295,7 +296,7 @@ class WidgetScrollViewTest : public test::WidgetTest,
// Adds a ScrollView with the given |contents_view| and does layout.
ScrollView* AddScrollViewWithContents(std::unique_ptr<View> contents,
bool commit_layers = true) {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
scroller_style_ = std::make_unique<ui::test::ScopedPreferredScrollerStyle>(
use_overlay_scrollers_);
#endif
@@ -371,7 +372,7 @@ class WidgetScrollViewTest : public test::WidgetTest,
base::RepeatingClosure quit_closure_;
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
std::unique_ptr<ui::test::ScopedPreferredScrollerStyle> scroller_style_;
#endif
@@ -633,12 +634,14 @@ TEST_F(ScrollViewTest, ScrollBars) {
}
// Assertions around adding a header.
-TEST_F(ScrollViewTest, Header) {
- auto* header = scroll_view_->SetHeader(std::make_unique<CustomView>());
+TEST_F(WidgetScrollViewTest, Header) {
+ auto contents_ptr = std::make_unique<View>();
+ auto* contents = contents_ptr.get();
+ ScrollView* scroll_view = AddScrollViewWithContents(std::move(contents_ptr));
+ auto* header = scroll_view->SetHeader(std::make_unique<CustomView>());
View* header_parent = header->parent();
- View* contents = InstallContents();
- scroll_view_->Layout();
+ widget()->LayoutRootViewIfNecessary();
// |header|s preferred size is empty, which should result in all space going
// to contents.
EXPECT_EQ("0,0 100x0", header->parent()->bounds().ToString());
@@ -656,8 +659,8 @@ TEST_F(ScrollViewTest, Header) {
// Get the header a height of 20.
header->SetPreferredSize(gfx::Size(10, 20));
- EXPECT_TRUE(ViewTestApi(scroll_view_.get()).needs_layout());
- scroll_view_->Layout();
+ EXPECT_TRUE(ViewTestApi(scroll_view).needs_layout());
+ widget()->LayoutRootViewIfNecessary();
EXPECT_EQ("0,0 100x20", header->parent()->bounds().ToString());
EXPECT_EQ("0,20 100x80", contents->parent()->bounds().ToString());
if (contents->layer()) {
@@ -667,9 +670,10 @@ TEST_F(ScrollViewTest, Header) {
EXPECT_EQ("0,0 0x0", contents->bounds().ToString());
// Remove the header.
- scroll_view_->SetHeader(nullptr);
+ scroll_view->SetHeader(nullptr);
// SetHeader(nullptr) deletes header.
header = nullptr;
+ widget()->LayoutRootViewIfNecessary();
EXPECT_EQ("0,0 100x0", header_parent->bounds().ToString());
EXPECT_EQ("0,0 100x100", contents->parent()->bounds().ToString());
}
@@ -1092,6 +1096,25 @@ TEST_F(ScrollViewTest, ClipHeightToScrollbarUsesWidth) {
EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroll_view_->size());
}
+// Verifies ClipHeightTo() updates the ScrollView's preferred size.
+TEST_F(ScrollViewTest, ClipHeightToUpdatesPreferredSize) {
+ auto contents_view = std::make_unique<View>();
+ contents_view->SetPreferredSize({100, 100});
+ scroll_view_->SetContents(std::move(contents_view));
+ EXPECT_FALSE(scroll_view_->is_bounded());
+
+ constexpr int kMinHeight1 = 20;
+ constexpr int kMaxHeight1 = 80;
+ scroll_view_->ClipHeightTo(kMinHeight1, kMaxHeight1);
+ EXPECT_TRUE(scroll_view_->is_bounded());
+ EXPECT_EQ(scroll_view_->GetPreferredSize().height(), kMaxHeight1);
+
+ constexpr int kMinHeight2 = 200;
+ constexpr int kMaxHeight2 = 300;
+ scroll_view_->ClipHeightTo(kMinHeight2, kMaxHeight2);
+ EXPECT_EQ(scroll_view_->GetPreferredSize().height(), kMinHeight2);
+}
+
TEST_F(ScrollViewTest, CornerViewVisibility) {
View* contents = InstallContents();
View* corner_view = ScrollViewTestApi(scroll_view_.get()).corner_view();
@@ -1137,9 +1160,12 @@ TEST_F(ScrollViewTest, CornerViewVisibility) {
EXPECT_TRUE(corner_view->GetVisible());
}
-TEST_F(ScrollViewTest, ChildWithLayerTest) {
- View* contents = InstallContents();
- ScrollViewTestApi test_api(scroll_view_.get());
+// This test needs a widget so that color changes will be reflected.
+TEST_F(WidgetScrollViewTest, ChildWithLayerTest) {
+ auto contents_ptr = std::make_unique<View>();
+ auto* contents = contents_ptr.get();
+ ScrollView* scroll_view = AddScrollViewWithContents(std::move(contents_ptr));
+ ScrollViewTestApi test_api(scroll_view);
if (test_api.contents_viewport()->layer())
return;
@@ -1152,8 +1178,8 @@ TEST_F(ScrollViewTest, ChildWithLayerTest) {
// should be true.
EXPECT_TRUE(test_api.contents_viewport()->layer()->fills_bounds_opaquely());
- // Setting a base::nullopt color should make fills opaquely false.
- scroll_view_->SetBackgroundColor(base::nullopt);
+ // Setting a absl::nullopt color should make fills opaquely false.
+ scroll_view->SetBackgroundColor(absl::nullopt);
EXPECT_FALSE(test_api.contents_viewport()->layer()->fills_bounds_opaquely());
child->DestroyLayer();
@@ -1182,7 +1208,7 @@ TEST_F(ScrollViewTest, DontCreateLayerOnViewportIfLayerOnScrollViewCreated) {
EXPECT_FALSE(test_api.contents_viewport()->layer());
}
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Tests the overlay scrollbars on Mac. Ensure that they show up properly and
// do not overlap each other.
TEST_F(ScrollViewTest, CocoaOverlayScrollBars) {
@@ -1348,7 +1374,7 @@ TEST_F(WidgetScrollViewTest, ScrollersOnRest) {
EXPECT_EQ(gfx::ScrollOffset(x_offset, y_offset), test_api.CurrentOffset());
}
-#endif // OS_APPLE
+#endif // OS_MAC
// Test that increasing the size of the viewport "below" scrolled content causes
// the content to scroll up so that it still fills the viewport.
@@ -2266,6 +2292,21 @@ TEST_F(WidgetScrollViewTest,
EXPECT_EQ(gfx::ScrollOffset(10, 0), test_api.CurrentOffset());
}
+TEST_F(WidgetScrollViewTest, UnboundedScrollViewUsesContentPreferredSize) {
+ auto contents = std::make_unique<View>();
+ constexpr gfx::Size kContentsPreferredSize(500, 500);
+ contents->SetPreferredSize(kContentsPreferredSize);
+ ScrollView* scroll_view =
+ AddScrollViewWithContents(std::move(contents), true);
+ EXPECT_EQ(kContentsPreferredSize, scroll_view->GetPreferredSize());
+
+ constexpr gfx::Insets kInsets(20);
+ scroll_view->SetBorder(CreateEmptyBorder(kInsets));
+ gfx::Size preferred_size_with_insets(kContentsPreferredSize);
+ preferred_size_with_insets.Enlarge(kInsets.width(), kInsets.height());
+ EXPECT_EQ(preferred_size_with_insets, scroll_view->GetPreferredSize());
+}
+
INSTANTIATE_TEST_SUITE_P(All,
WidgetScrollViewTestRTLAndLayers,
::testing::Values(UiConfig::kLtr,
diff --git a/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc b/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc
deleted file mode 100644
index b8099acc9b6..00000000000
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/controls/scrollbar/base_scroll_bar_button.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "ui/display/screen.h"
-#include "ui/events/event_utils.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
-
-namespace views {
-
-BaseScrollBarButton::BaseScrollBarButton(PressedCallback callback,
- const base::TickClock* tick_clock)
- : Button(std::move(callback)),
- repeater_(base::BindRepeating(&BaseScrollBarButton::RepeaterNotifyClick,
- base::Unretained(this)),
- tick_clock) {
- // Not focusable by default.
- SetFocusBehavior(FocusBehavior::NEVER);
-}
-
-BaseScrollBarButton::~BaseScrollBarButton() = default;
-
-bool BaseScrollBarButton::OnMousePressed(const ui::MouseEvent& event) {
- Button::NotifyClick(event);
- repeater_.Start();
- return true;
-}
-
-void BaseScrollBarButton::OnMouseReleased(const ui::MouseEvent& event) {
- OnMouseCaptureLost();
-}
-
-void BaseScrollBarButton::OnMouseCaptureLost() {
- repeater_.Stop();
-}
-
-void BaseScrollBarButton::RepeaterNotifyClick() {
- // TODO(sky): See if we can convert to using |Screen| everywhere.
- gfx::Point cursor_point =
- display::Screen::GetScreen()->GetCursorScreenPoint();
- ui::MouseEvent event(ui::ET_MOUSE_RELEASED, cursor_point, cursor_point,
- ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
- ui::EF_LEFT_MOUSE_BUTTON);
- Button::NotifyClick(event);
-}
-
-BEGIN_METADATA(BaseScrollBarButton, Button)
-END_METADATA
-
-} // namespace views
diff --git a/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.h b/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.h
deleted file mode 100644
index 09635d6ce35..00000000000
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_CONTROLS_SCROLLBAR_BASE_SCROLL_BAR_BUTTON_H_
-#define UI_VIEWS_CONTROLS_SCROLLBAR_BASE_SCROLL_BAR_BUTTON_H_
-
-#include "ui/views/controls/button/button.h"
-
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "ui/views/repeat_controller.h"
-
-namespace base {
-class TickClock;
-}
-
-namespace views {
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// ScrollBarButton
-//
-// A button that activates on mouse pressed rather than released, and that
-// continues to fire the clicked action as the mouse button remains pressed
-// down on the button.
-//
-///////////////////////////////////////////////////////////////////////////////
-class VIEWS_EXPORT BaseScrollBarButton : public Button {
- public:
- METADATA_HEADER(BaseScrollBarButton);
-
- explicit BaseScrollBarButton(PressedCallback callback,
- const base::TickClock* tick_clock = nullptr);
- ~BaseScrollBarButton() override;
-
- protected:
- bool OnMousePressed(const ui::MouseEvent& event) override;
- void OnMouseReleased(const ui::MouseEvent& event) override;
- void OnMouseCaptureLost() override;
-
- private:
- void RepeaterNotifyClick();
-
- // The repeat controller that we use to repeatedly click the button when the
- // mouse button is down.
- RepeatController repeater_;
-
- DISALLOW_COPY_AND_ASSIGN(BaseScrollBarButton);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_CONTROLS_SCROLLBAR_BASE_SCROLL_BAR_BUTTON_H_
diff --git a/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc b/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc
index 0c222e30d9b..5a5dc144ed2 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc
@@ -4,10 +4,11 @@
#include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
+#include "base/i18n/rtl.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/controls/scrollbar/scroll_bar.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace {
// The distance the mouse can be dragged outside the bounds of the thumb during
diff --git a/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm b/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
index e2fd6a5eab7..f39d1dbcb7e 100644
--- a/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
+++ b/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
@@ -5,16 +5,17 @@
#import "ui/views/controls/scrollbar/cocoa_scroll_bar.h"
#include "base/bind.h"
+#include "base/i18n/rtl.h"
#include "base/stl_util.h"
#include "cc/paint/paint_shader.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/canvas.h"
#include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace views {
diff --git a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc
index b3d3d8b73bc..36ea80bc43f 100644
--- a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc
+++ b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc
@@ -7,16 +7,18 @@
#include <memory>
#include "base/bind.h"
+#include "base/i18n/rtl.h"
#include "base/macros.h"
#include "cc/paint/paint_flags.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/canvas.h"
#include "ui/native_theme/overlay_scrollbar_constants_aura.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/layout/fill_layout.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace views {
namespace {
diff --git a/chromium/ui/views/controls/scrollbar/scroll_bar.cc b/chromium/ui/views/controls/scrollbar/scroll_bar.cc
index afdb732bfdf..ced16b036c6 100644
--- a/chromium/ui/views/controls/scrollbar/scroll_bar.cc
+++ b/chromium/ui/views/controls/scrollbar/scroll_bar.cc
@@ -21,6 +21,7 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
@@ -29,7 +30,6 @@
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/scroll_view.h"
#include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/widget/widget.h"
namespace views {
@@ -148,13 +148,32 @@ void ScrollBar::OnGestureEvent(ui::GestureEvent* event) {
return;
}
- if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
- event->type() == ui::ET_GESTURE_SCROLL_END) {
+ if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN) {
+ scroll_status_ = ScrollStatus::kScrollStarted;
event->SetHandled();
return;
}
+ if (event->type() == ui::ET_GESTURE_SCROLL_END) {
+ scroll_status_ = ScrollStatus::kScrollEnded;
+ controller()->OnScrollEnded();
+ event->SetHandled();
+ return;
+ }
+
+ // Update the |scroll_status_| to |kScrollEnded| in case the gesture sequence
+ // ends incorrectly.
+ if (event->type() == ui::ET_GESTURE_END &&
+ scroll_status_ == ScrollStatus::kScrollInEnding &&
+ scroll_status_ == ScrollStatus::kScrollEnded) {
+ scroll_status_ = ScrollStatus::kScrollEnded;
+ controller()->OnScrollEnded();
+ }
+
if (event->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
+ if (scroll_status_ == ScrollStatus::kScrollStarted)
+ scroll_status_ = ScrollStatus::kScrollInProgress;
+
float scroll_amount_f;
int scroll_amount;
if (IsHorizontal()) {
@@ -172,6 +191,7 @@ void ScrollBar::OnGestureEvent(ui::GestureEvent* event) {
}
if (event->type() == ui::ET_SCROLL_FLING_START) {
+ scroll_status_ = ScrollStatus::kScrollInEnding;
if (!scroll_animator_)
scroll_animator_ = std::make_unique<ScrollAnimator>(this);
scroll_animator_->Start(
@@ -189,6 +209,11 @@ bool ScrollBar::OnScroll(float dx, float dy) {
: ScrollByContentsOffset(dy);
}
+void ScrollBar::OnFlingScrollEnded() {
+ scroll_status_ = ScrollStatus::kScrollEnded;
+ controller()->OnScrollEnded();
+}
+
///////////////////////////////////////////////////////////////////////////////
// ScrollBar, ContextMenuController implementation:
@@ -332,7 +357,29 @@ int ScrollBar::GetScrollIncrement(bool is_page, bool is_positive) {
return controller()->GetScrollIncrement(this, is_page, is_positive);
}
-void ScrollBar::ObserveScrollEvent(const ui::ScrollEvent& event) {}
+void ScrollBar::ObserveScrollEvent(const ui::ScrollEvent& event) {
+ switch (event.type()) {
+ case ui::ET_SCROLL_FLING_CANCEL:
+ scroll_status_ = ScrollStatus::kScrollStarted;
+ break;
+ case ui::ET_SCROLL:
+ if (scroll_status_ == ScrollStatus::kScrollStarted)
+ scroll_status_ = ScrollStatus::kScrollInProgress;
+ break;
+ case ui::ET_SCROLL_FLING_START:
+ scroll_status_ = ScrollStatus::kScrollEnded;
+ controller()->OnScrollEnded();
+ break;
+ case ui::ET_GESTURE_END:
+ if (scroll_status_ != ScrollStatus::kScrollEnded) {
+ scroll_status_ = ScrollStatus::kScrollEnded;
+ controller()->OnScrollEnded();
+ }
+ break;
+ default:
+ break;
+ }
+}
ScrollBar::ScrollBar(bool is_horiz)
: is_horiz_(is_horiz),
@@ -344,7 +391,7 @@ ScrollBar::ScrollBar(bool is_horiz)
///////////////////////////////////////////////////////////////////////////////
// ScrollBar, private:
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// static
base::RetainingOneShotTimer* ScrollBar::GetHideTimerForTesting(
ScrollBar* scroll_bar) {
@@ -442,7 +489,7 @@ ScrollBar::ScrollAmount ScrollBar::DetermineScrollAmountByKeyCode(
return (i == kMap->end()) ? ScrollAmount::kNone : i->second;
}
-base::Optional<int> ScrollBar::GetDesiredScrollOffset(ScrollAmount amount) {
+absl::optional<int> ScrollBar::GetDesiredScrollOffset(ScrollAmount amount) {
switch (amount) {
case ScrollAmount::kStart:
return GetMinPosition();
@@ -457,7 +504,7 @@ base::Optional<int> ScrollBar::GetDesiredScrollOffset(ScrollAmount amount) {
case ScrollAmount::kNextPage:
return contents_scroll_offset_ + GetScrollIncrement(true, true);
default:
- return base::nullopt;
+ return absl::nullopt;
}
}
diff --git a/chromium/ui/views/controls/scrollbar/scroll_bar.h b/chromium/ui/views/controls/scrollbar/scroll_bar.h
index 264db19019e..b1d2a6d935b 100644
--- a/chromium/ui/views/controls/scrollbar/scroll_bar.h
+++ b/chromium/ui/views/controls/scrollbar/scroll_bar.h
@@ -10,7 +10,7 @@
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/views/animation/scroll_animator.h"
#include "ui/views/context_menu_controller.h"
@@ -47,6 +47,10 @@ class VIEWS_EXPORT ScrollBarController {
// position which is in the GetMinPosition() / GetMaxPosition range.
virtual void ScrollToPosition(ScrollBar* source, int position) = 0;
+ // Called when the scroll that triggered by gesture or scroll events sequence
+ // ended.
+ virtual void OnScrollEnded() {}
+
// Returns the amount to scroll. The amount to scroll may be requested in
// two different amounts. If is_page is true the 'page scroll' amount is
// requested. The page scroll amount typically corresponds to the
@@ -132,6 +136,7 @@ class VIEWS_EXPORT ScrollBar : public View,
// ScrollDelegate:
bool OnScroll(float dx, float dy) override;
+ void OnFlingScrollEnded() override;
// ContextMenuController:
void ShowContextMenuForViewImpl(View* source,
@@ -166,6 +171,10 @@ class VIEWS_EXPORT ScrollBar : public View,
// scrollbar.
virtual int GetThickness() const = 0;
+ bool is_scrolling() const {
+ return scroll_status_ == ScrollStatus::kScrollInProgress;
+ }
+
protected:
// Create new scrollbar, either horizontal or vertical. These are protected
// since you need to be creating either a NativeScrollBar or a
@@ -225,7 +234,7 @@ class VIEWS_EXPORT ScrollBar : public View,
ScrollAmount DetermineScrollAmountByKeyCode(
const ui::KeyboardCode& keycode) const;
- base::Optional<int> GetDesiredScrollOffset(ScrollAmount amount);
+ absl::optional<int> GetDesiredScrollOffset(ScrollAmount amount);
// The size of the scrolled contents, in pixels.
int contents_size_ = 0;
@@ -264,6 +273,22 @@ class VIEWS_EXPORT ScrollBar : public View,
// is enabled. See crbug.com/329354.
gfx::Vector2dF roundoff_error_;
+ // The enumeration keeps track of the current status of the scroll. Used when
+ // the contents scrolled by the gesture or scroll events sequence.
+ enum class ScrollStatus {
+ kScrollNone,
+ kScrollStarted,
+ kScrollInProgress,
+
+ // The contents will keep scrolling for a while if the events sequence ends
+ // with ui::ET_SCROLL_FLING_START. Set the status to kScrollInEnding if it
+ // happens, and set it to kScrollEnded while the scroll really ended.
+ kScrollInEnding,
+ kScrollEnded,
+ };
+
+ ScrollStatus scroll_status_ = ScrollStatus::kScrollNone;
+
std::unique_ptr<ui::SimpleMenuModel> menu_model_;
std::unique_ptr<MenuRunner> menu_runner_;
std::unique_ptr<ScrollAnimator> scroll_animator_;
diff --git a/chromium/ui/views/controls/scrollbar/scroll_bar_button.cc b/chromium/ui/views/controls/scrollbar/scroll_bar_button.cc
new file mode 100644
index 00000000000..4be4a3af075
--- /dev/null
+++ b/chromium/ui/views/controls/scrollbar/scroll_bar_button.cc
@@ -0,0 +1,120 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/scrollbar/scroll_bar_button.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/time/tick_clock.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/display/screen.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/event_constants.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace views {
+
+ScrollBarButton::ScrollBarButton(PressedCallback callback,
+ Type type,
+ const base::TickClock* tick_clock)
+ : Button(std::move(callback)),
+ type_(type),
+ repeater_(base::BindRepeating(&ScrollBarButton::RepeaterNotifyClick,
+ base::Unretained(this)),
+ tick_clock) {
+ SetFlipCanvasOnPaintForRTLUI(true);
+ // Not focusable by default.
+ SetFocusBehavior(FocusBehavior::NEVER);
+}
+
+ScrollBarButton::~ScrollBarButton() = default;
+
+gfx::Size ScrollBarButton::CalculatePreferredSize() const {
+ if (!GetWidget())
+ return gfx::Size();
+ return GetNativeTheme()->GetPartSize(
+ GetNativeThemePart(), GetNativeThemeState(), GetNativeThemeParams());
+}
+
+bool ScrollBarButton::OnMousePressed(const ui::MouseEvent& event) {
+ Button::NotifyClick(event);
+ repeater_.Start();
+ return true;
+}
+
+void ScrollBarButton::OnMouseReleased(const ui::MouseEvent& event) {
+ OnMouseCaptureLost();
+}
+
+void ScrollBarButton::OnMouseCaptureLost() {
+ repeater_.Stop();
+}
+
+void ScrollBarButton::OnThemeChanged() {
+ Button::OnThemeChanged();
+ PreferredSizeChanged();
+}
+
+void ScrollBarButton::PaintButtonContents(gfx::Canvas* canvas) {
+ gfx::Rect bounds(GetPreferredSize());
+ GetNativeTheme()->Paint(canvas->sk_canvas(), GetNativeThemePart(),
+ GetNativeThemeState(), bounds,
+ GetNativeThemeParams());
+}
+
+ui::NativeTheme::ExtraParams ScrollBarButton::GetNativeThemeParams() const {
+ ui::NativeTheme::ExtraParams params;
+ params.scrollbar_arrow.is_hovering = GetState() == Button::STATE_HOVERED;
+ return params;
+}
+
+ui::NativeTheme::Part ScrollBarButton::GetNativeThemePart() const {
+ switch (type_) {
+ case Type::kUp:
+ return ui::NativeTheme::kScrollbarUpArrow;
+ case Type::kDown:
+ return ui::NativeTheme::kScrollbarDownArrow;
+ case Type::kLeft:
+ return ui::NativeTheme::kScrollbarLeftArrow;
+ case Type::kRight:
+ return ui::NativeTheme::kScrollbarRightArrow;
+ }
+
+ NOTREACHED();
+ return ui::NativeTheme::kScrollbarUpArrow;
+}
+
+ui::NativeTheme::State ScrollBarButton::GetNativeThemeState() const {
+ switch (GetState()) {
+ case Button::STATE_HOVERED:
+ return ui::NativeTheme::kHovered;
+ case Button::STATE_PRESSED:
+ return ui::NativeTheme::kPressed;
+ case Button::STATE_DISABLED:
+ return ui::NativeTheme::kDisabled;
+ case Button::STATE_NORMAL:
+ return ui::NativeTheme::kNormal;
+ case Button::STATE_COUNT:
+ break;
+ }
+
+ NOTREACHED();
+ return ui::NativeTheme::kNormal;
+}
+
+void ScrollBarButton::RepeaterNotifyClick() {
+ gfx::Point cursor_point =
+ display::Screen::GetScreen()->GetCursorScreenPoint();
+ ui::MouseEvent event(ui::ET_MOUSE_RELEASED, cursor_point, cursor_point,
+ ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON);
+ Button::NotifyClick(event);
+}
+
+BEGIN_METADATA(ScrollBarButton, Button)
+END_METADATA
+
+} // namespace views
diff --git a/chromium/ui/views/controls/scrollbar/scroll_bar_button.h b/chromium/ui/views/controls/scrollbar/scroll_bar_button.h
new file mode 100644
index 00000000000..37e14f84d51
--- /dev/null
+++ b/chromium/ui/views/controls/scrollbar/scroll_bar_button.h
@@ -0,0 +1,72 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_CONTROLS_SCROLLBAR_SCROLL_BAR_BUTTON_H_
+#define UI_VIEWS_CONTROLS_SCROLLBAR_SCROLL_BAR_BUTTON_H_
+
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/events/event.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/native_theme/native_theme.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/repeat_controller.h"
+#include "ui/views/views_export.h"
+
+namespace base {
+class TickClock;
+}
+
+namespace gfx {
+class Canvas;
+}
+
+namespace views {
+
+// A button that activates on mouse pressed rather than released, and that
+// continues to fire the clicked action as the mouse button remains pressed
+// down on the button.
+class VIEWS_EXPORT ScrollBarButton : public Button {
+ public:
+ METADATA_HEADER(ScrollBarButton);
+
+ enum class Type {
+ kUp,
+ kDown,
+ kLeft,
+ kRight,
+ };
+
+ ScrollBarButton(PressedCallback callback,
+ Type type,
+ const base::TickClock* tick_clock = nullptr);
+ ScrollBarButton(const ScrollBarButton&) = delete;
+ ScrollBarButton& operator=(const ScrollBarButton&) = delete;
+ ~ScrollBarButton() override;
+
+ gfx::Size CalculatePreferredSize() const override;
+
+ protected:
+ // Button
+ bool OnMousePressed(const ui::MouseEvent& event) override;
+ void OnMouseReleased(const ui::MouseEvent& event) override;
+ void OnMouseCaptureLost() override;
+ void OnThemeChanged() override;
+ void PaintButtonContents(gfx::Canvas* canvas) override;
+
+ private:
+ ui::NativeTheme::ExtraParams GetNativeThemeParams() const;
+ ui::NativeTheme::Part GetNativeThemePart() const;
+ ui::NativeTheme::State GetNativeThemeState() const;
+ void RepeaterNotifyClick();
+
+ Type type_;
+
+ // The repeat controller that we use to repeatedly click the button when the
+ // mouse button is down.
+ RepeatController repeater_;
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_CONTROLS_SCROLLBAR_SCROLL_BAR_BUTTON_H_
diff --git a/chromium/ui/views/controls/scrollbar/base_scroll_bar_button_unittest.cc b/chromium/ui/views/controls/scrollbar/scroll_bar_button_unittest.cc
index 86721694c08..42b23df58ff 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar_button_unittest.cc
+++ b/chromium/ui/views/controls/scrollbar/scroll_bar_button_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/views/controls/scrollbar/base_scroll_bar_button.h"
+#include "ui/views/controls/scrollbar/scroll_bar_button.h"
#include <memory>
@@ -34,15 +34,18 @@ class MockButtonCallback {
MOCK_METHOD(void, ButtonPressed, ());
};
-class BaseScrollBarButtonTest : public testing::Test {
+class ScrollBarButtonTest : public testing::Test {
public:
- BaseScrollBarButtonTest()
- : button_(std::make_unique<BaseScrollBarButton>(
+ ScrollBarButtonTest()
+ : button_(std::make_unique<ScrollBarButton>(
base::BindRepeating(&MockButtonCallback::ButtonPressed,
base::Unretained(&callback_)),
+ ScrollBarButton::Type::kLeft,
task_environment_.GetMockTickClock())) {}
- ~BaseScrollBarButtonTest() override = default;
+ ScrollBarButtonTest(const ScrollBarButtonTest&) = delete;
+ ScrollBarButtonTest& operator=(const ScrollBarButtonTest&) = delete;
+ ~ScrollBarButtonTest() override = default;
protected:
testing::StrictMock<MockButtonCallback>& callback() { return callback_; }
@@ -64,15 +67,15 @@ class BaseScrollBarButtonTest : public testing::Test {
} // namespace
-TEST_F(BaseScrollBarButtonTest, Metadata) {
+TEST_F(ScrollBarButtonTest, Metadata) {
test::TestViewMetadata(button());
}
-TEST_F(BaseScrollBarButtonTest, FocusBehavior) {
+TEST_F(ScrollBarButtonTest, FocusBehavior) {
EXPECT_EQ(View::FocusBehavior::NEVER, button()->GetFocusBehavior());
}
-TEST_F(BaseScrollBarButtonTest, CallbackFiresOnMouseDown) {
+TEST_F(ScrollBarButtonTest, CallbackFiresOnMouseDown) {
EXPECT_CALL(callback(), ButtonPressed());
// By default the button should notify its callback on mouse release.
@@ -81,7 +84,7 @@ TEST_F(BaseScrollBarButtonTest, CallbackFiresOnMouseDown) {
ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
}
-TEST_F(BaseScrollBarButtonTest, CallbackFiresMultipleTimesMouseHeldDown) {
+TEST_F(ScrollBarButtonTest, CallbackFiresMultipleTimesMouseHeldDown) {
EXPECT_CALL(callback(), ButtonPressed()).Times(AtLeast(2));
// By default the button should notify its callback on mouse release.
@@ -92,7 +95,7 @@ TEST_F(BaseScrollBarButtonTest, CallbackFiresMultipleTimesMouseHeldDown) {
AdvanceTime(RepeatController::GetInitialWaitForTesting() * 10);
}
-TEST_F(BaseScrollBarButtonTest, CallbackStopsFiringAfterMouseReleased) {
+TEST_F(ScrollBarButtonTest, CallbackStopsFiringAfterMouseReleased) {
EXPECT_CALL(callback(), ButtonPressed()).Times(AtLeast(2));
// By default the button should notify its callback on mouse release.
@@ -113,7 +116,7 @@ TEST_F(BaseScrollBarButtonTest, CallbackStopsFiringAfterMouseReleased) {
EXPECT_CALL(callback(), ButtonPressed()).Times(AtMost(0));
}
-TEST_F(BaseScrollBarButtonTest, CallbackStopsFiringAfterMouseCaptureReleased) {
+TEST_F(ScrollBarButtonTest, CallbackStopsFiringAfterMouseCaptureReleased) {
EXPECT_CALL(callback(), ButtonPressed()).Times(AtLeast(2));
// By default the button should notify its callback on mouse release.
diff --git a/chromium/ui/views/controls/scrollbar/scroll_bar_views.cc b/chromium/ui/views/controls/scrollbar/scroll_bar_views.cc
index 45683aa9de2..60c221b1000 100644
--- a/chromium/ui/views/controls/scrollbar/scroll_bar_views.cc
+++ b/chromium/ui/views/controls/scrollbar/scroll_bar_views.cc
@@ -10,47 +10,21 @@
#include "base/check.h"
#include "base/notreached.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/focusable_border.h"
-#include "ui/views/controls/scrollbar/base_scroll_bar_button.h"
#include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
#include "ui/views/controls/scrollbar/scroll_bar.h"
+#include "ui/views/controls/scrollbar/scroll_bar_button.h"
#include "ui/views/layout/flex_layout.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/view_class_properties.h"
namespace views {
namespace {
-// Wrapper for the scroll buttons.
-class ScrollBarButton : public BaseScrollBarButton {
- public:
- enum class Type {
- kUp,
- kDown,
- kLeft,
- kRight,
- };
-
- ScrollBarButton(PressedCallback callback, Type type);
- ~ScrollBarButton() override;
-
- gfx::Size CalculatePreferredSize() const override;
-
- protected:
- void PaintButtonContents(gfx::Canvas* canvas) override;
-
- private:
- ui::NativeTheme::ExtraParams GetNativeThemeParams() const;
- ui::NativeTheme::Part GetNativeThemePart() const;
- ui::NativeTheme::State GetNativeThemeState() const;
-
- Type type_;
-};
-
// Wrapper for the scroll thumb
class ScrollBarThumb : public BaseScrollBarThumb {
public:
@@ -61,6 +35,7 @@ class ScrollBarThumb : public BaseScrollBarThumb {
protected:
void OnPaint(gfx::Canvas* canvas) override;
+ void OnThemeChanged() override;
private:
ui::NativeTheme::ExtraParams GetNativeThemeParams() const;
@@ -70,81 +45,14 @@ class ScrollBarThumb : public BaseScrollBarThumb {
ScrollBar* scroll_bar_;
};
-ScrollBarButton::ScrollBarButton(PressedCallback callback, Type type)
- : BaseScrollBarButton(std::move(callback)), type_(type) {
- SetFlipCanvasOnPaintForRTLUI(true);
- DCHECK_EQ(FocusBehavior::NEVER, GetFocusBehavior());
-}
-
-ScrollBarButton::~ScrollBarButton() = default;
-
-gfx::Size ScrollBarButton::CalculatePreferredSize() const {
- return GetNativeTheme()->GetPartSize(
- GetNativeThemePart(), GetNativeThemeState(), GetNativeThemeParams());
-}
-
-void ScrollBarButton::PaintButtonContents(gfx::Canvas* canvas) {
- gfx::Rect bounds(GetPreferredSize());
- GetNativeTheme()->Paint(canvas->sk_canvas(), GetNativeThemePart(),
- GetNativeThemeState(), bounds,
- GetNativeThemeParams());
-}
-
-ui::NativeTheme::ExtraParams ScrollBarButton::GetNativeThemeParams() const {
- ui::NativeTheme::ExtraParams params;
-
- switch (GetState()) {
- case Button::STATE_HOVERED:
- params.scrollbar_arrow.is_hovering = true;
- break;
- default:
- params.scrollbar_arrow.is_hovering = false;
- break;
- }
-
- return params;
-}
-
-ui::NativeTheme::Part ScrollBarButton::GetNativeThemePart() const {
- switch (type_) {
- case Type::kUp:
- return ui::NativeTheme::kScrollbarUpArrow;
- case Type::kDown:
- return ui::NativeTheme::kScrollbarDownArrow;
- case Type::kLeft:
- return ui::NativeTheme::kScrollbarLeftArrow;
- case Type::kRight:
- return ui::NativeTheme::kScrollbarRightArrow;
- }
-
- NOTREACHED();
- return ui::NativeTheme::kScrollbarUpArrow;
-}
-
-ui::NativeTheme::State ScrollBarButton::GetNativeThemeState() const {
- switch (GetState()) {
- case Button::STATE_HOVERED:
- return ui::NativeTheme::kHovered;
- case Button::STATE_PRESSED:
- return ui::NativeTheme::kPressed;
- case Button::STATE_DISABLED:
- return ui::NativeTheme::kDisabled;
- case Button::STATE_NORMAL:
- return ui::NativeTheme::kNormal;
- case Button::STATE_COUNT:
- break;
- }
-
- NOTREACHED();
- return ui::NativeTheme::kNormal;
-}
-
ScrollBarThumb::ScrollBarThumb(ScrollBar* scroll_bar)
: BaseScrollBarThumb(scroll_bar), scroll_bar_(scroll_bar) {}
ScrollBarThumb::~ScrollBarThumb() = default;
gfx::Size ScrollBarThumb::CalculatePreferredSize() const {
+ if (!GetWidget())
+ return gfx::Size();
return GetNativeTheme()->GetPartSize(
GetNativeThemePart(), GetNativeThemeState(), GetNativeThemeParams());
}
@@ -162,6 +70,11 @@ void ScrollBarThumb::OnPaint(gfx::Canvas* canvas) {
local_bounds, extra_params);
}
+void ScrollBarThumb::OnThemeChanged() {
+ BaseScrollBarThumb::OnThemeChanged();
+ PreferredSizeChanged();
+}
+
ui::NativeTheme::ExtraParams ScrollBarThumb::GetNativeThemeParams() const {
// This gives the behavior we want.
ui::NativeTheme::ExtraParams params;
diff --git a/chromium/ui/views/controls/scrollbar/scroll_bar_views.h b/chromium/ui/views/controls/scrollbar/scroll_bar_views.h
index a08f89b2f2b..448353e7a06 100644
--- a/chromium/ui/views/controls/scrollbar/scroll_bar_views.h
+++ b/chromium/ui/views/controls/scrollbar/scroll_bar_views.h
@@ -7,7 +7,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "ui/gfx/geometry/point.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/scrollbar/scroll_bar.h"
#include "ui/views/view.h"
diff --git a/chromium/ui/views/controls/scrollbar/scrollbar_unittest.cc b/chromium/ui/views/controls/scrollbar/scrollbar_unittest.cc
index 2d74d2ac50c..0dbd82f7414 100644
--- a/chromium/ui/views/controls/scrollbar/scrollbar_unittest.cc
+++ b/chromium/ui/views/controls/scrollbar/scrollbar_unittest.cc
@@ -220,7 +220,7 @@ TEST_F(ScrollBarViewsTest, RightClickOpensMenu) {
EXPECT_NE(nullptr, scrollbar_->menu_runner_);
}
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
TEST_F(ScrollBarViewsTest, TestPageScrollingByPress) {
ui::test::EventGenerator generator(GetRootWindow(widget_.get()));
EXPECT_EQ(0, scrollbar_->GetPosition());
diff --git a/chromium/ui/views/controls/separator.cc b/chromium/ui/views/controls/separator.cc
index d3d985bb758..3acf5bb4918 100644
--- a/chromium/ui/views/controls/separator.cc
+++ b/chromium/ui/views/controls/separator.cc
@@ -6,12 +6,10 @@
#include <algorithm>
-#include "ui/accessibility/ax_enums.mojom.h"
-#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/scoped_canvas.h"
#include "ui/native_theme/native_theme.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace views {
@@ -97,7 +95,7 @@ void Separator::OnPaint(gfx::Canvas* canvas) {
}
BEGIN_METADATA(Separator, View)
-ADD_PROPERTY_METADATA(SkColor, Color, metadata::SkColorConverter)
+ADD_PROPERTY_METADATA(SkColor, Color, ui::metadata::SkColorConverter)
ADD_PROPERTY_METADATA(int, PreferredHeight)
END_METADATA
diff --git a/chromium/ui/views/controls/separator.h b/chromium/ui/views/controls/separator.h
index 6e1a20c32f0..6a2b01cae40 100644
--- a/chromium/ui/views/controls/separator.h
+++ b/chromium/ui/views/controls/separator.h
@@ -5,10 +5,9 @@
#ifndef UI_VIEWS_CONTROLS_SEPARATOR_H_
#define UI_VIEWS_CONTROLS_SEPARATOR_H_
-#include <string>
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/view.h"
@@ -38,7 +37,7 @@ class VIEWS_EXPORT Separator : public View {
private:
int preferred_height_ = kThickness;
- base::Optional<SkColor> overridden_color_;
+ absl::optional<SkColor> overridden_color_;
DISALLOW_COPY_AND_ASSIGN(Separator);
};
diff --git a/chromium/ui/views/controls/separator_unittest.cc b/chromium/ui/views/controls/separator_unittest.cc
index 20db4de0fc8..8e9b154de6f 100644
--- a/chromium/ui/views/controls/separator_unittest.cc
+++ b/chromium/ui/views/controls/separator_unittest.cc
@@ -4,6 +4,8 @@
#include "ui/views/controls/separator.h"
+#include <memory>
+
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image_unittest_util.h"
#include "ui/views/border.h"
@@ -12,17 +14,21 @@
namespace views {
// Base test fixture for Separator tests.
-class SeparatorTest : public views::ViewsTestBase {
+class SeparatorTest : public ViewsTestBase {
public:
SeparatorTest() = default;
~SeparatorTest() override = default;
protected:
- void ExpectDrawAtLeastOnePixel(float image_scale);
+ // views::ViewsTestBase:
+ void SetUp() override;
+ void TearDown() override;
SkBitmap PaintToCanvas(float image_scale);
+ void ExpectDrawAtLeastOnePixel(float image_scale);
- Separator separator_;
+ std::unique_ptr<Widget> widget_;
+ Separator* separator_;
static const SkColor kBackgroundColor;
static const SkColor kForegroundColor;
@@ -36,10 +42,21 @@ const SkColor SeparatorTest::kBackgroundColor = SK_ColorRED;
const SkColor SeparatorTest::kForegroundColor = SK_ColorGRAY;
const gfx::Size SeparatorTest::kTestImageSize{24, 24};
+void SeparatorTest::SetUp() {
+ ViewsTestBase::SetUp();
+ widget_ = CreateTestWidget();
+ separator_ = widget_->SetContentsView(std::make_unique<Separator>());
+}
+
+void SeparatorTest::TearDown() {
+ widget_.reset();
+ ViewsTestBase::TearDown();
+}
+
SkBitmap SeparatorTest::PaintToCanvas(float image_scale) {
gfx::Canvas canvas(kTestImageSize, image_scale, true);
canvas.DrawColor(kBackgroundColor);
- separator_.OnPaint(&canvas);
+ separator_->OnPaint(&canvas);
return canvas.GetBitmap();
}
@@ -54,20 +71,20 @@ void SeparatorTest::ExpectDrawAtLeastOnePixel(float image_scale) {
TEST_F(SeparatorTest, ImageScaleBelowOne) {
// Vertical line with 1[dp] thickness by default.
- separator_.SetPreferredHeight(8);
+ separator_->SetPreferredHeight(8);
ExpectDrawAtLeastOnePixel(0.4);
}
TEST_F(SeparatorTest, ImageScaleBelowOne_HorizontalLine) {
const int kThickness = 1;
// Use Separator as a horizontal line with 1[dp] thickness.
- separator_.SetBounds(4, 5, 8, kThickness);
+ separator_->SetBounds(4, 5, 8, kThickness);
ExpectDrawAtLeastOnePixel(0.4);
}
TEST_F(SeparatorTest, Paint_NoInsets_FillsCanvas_Scale100) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
SkBitmap painted = PaintToCanvas(1.0f);
EXPECT_EQ(kForegroundColor, painted.getColor(0, 0));
@@ -77,8 +94,8 @@ TEST_F(SeparatorTest, Paint_NoInsets_FillsCanvas_Scale100) {
}
TEST_F(SeparatorTest, Paint_NoInsets_FillsCanvas_Scale125) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
SkBitmap painted = PaintToCanvas(1.25f);
EXPECT_EQ(kForegroundColor, painted.getColor(0, 0));
@@ -88,8 +105,8 @@ TEST_F(SeparatorTest, Paint_NoInsets_FillsCanvas_Scale125) {
}
TEST_F(SeparatorTest, Paint_NoInsets_FillsCanvas_Scale150) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
SkBitmap painted = PaintToCanvas(1.5f);
EXPECT_EQ(kForegroundColor, painted.getColor(0, 0));
@@ -99,9 +116,9 @@ TEST_F(SeparatorTest, Paint_NoInsets_FillsCanvas_Scale150) {
}
TEST_F(SeparatorTest, Paint_TopInset_Scale100) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
- separator_.SetBorder(CreateEmptyBorder(1, 0, 0, 0));
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
+ separator_->SetBorder(CreateEmptyBorder(1, 0, 0, 0));
SkBitmap painted = PaintToCanvas(1.0f);
EXPECT_EQ(kBackgroundColor, painted.getColor(0, 0));
@@ -113,9 +130,9 @@ TEST_F(SeparatorTest, Paint_TopInset_Scale100) {
}
TEST_F(SeparatorTest, Paint_TopInset_Scale125) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
- separator_.SetBorder(CreateEmptyBorder(1, 0, 0, 0));
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
+ separator_->SetBorder(CreateEmptyBorder(1, 0, 0, 0));
SkBitmap painted = PaintToCanvas(1.25f);
EXPECT_EQ(kBackgroundColor, painted.getColor(0, 1));
@@ -127,9 +144,9 @@ TEST_F(SeparatorTest, Paint_TopInset_Scale125) {
}
TEST_F(SeparatorTest, Paint_LeftInset_Scale100) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
- separator_.SetBorder(CreateEmptyBorder(0, 1, 0, 0));
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
+ separator_->SetBorder(CreateEmptyBorder(0, 1, 0, 0));
SkBitmap painted = PaintToCanvas(1.0f);
EXPECT_EQ(kBackgroundColor, painted.getColor(0, 0));
@@ -141,9 +158,9 @@ TEST_F(SeparatorTest, Paint_LeftInset_Scale100) {
}
TEST_F(SeparatorTest, Paint_LeftInset_Scale125) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
- separator_.SetBorder(CreateEmptyBorder(0, 1, 0, 0));
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
+ separator_->SetBorder(CreateEmptyBorder(0, 1, 0, 0));
SkBitmap painted = PaintToCanvas(1.25f);
EXPECT_EQ(kBackgroundColor, painted.getColor(1, 0));
@@ -155,9 +172,9 @@ TEST_F(SeparatorTest, Paint_LeftInset_Scale125) {
}
TEST_F(SeparatorTest, Paint_BottomInset_Scale100) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
- separator_.SetBorder(CreateEmptyBorder(0, 0, 1, 0));
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
+ separator_->SetBorder(CreateEmptyBorder(0, 0, 1, 0));
SkBitmap painted = PaintToCanvas(1.0f);
EXPECT_EQ(kForegroundColor, painted.getColor(0, 0));
@@ -169,9 +186,9 @@ TEST_F(SeparatorTest, Paint_BottomInset_Scale100) {
}
TEST_F(SeparatorTest, Paint_BottomInset_Scale125) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
- separator_.SetBorder(CreateEmptyBorder(0, 0, 1, 0));
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
+ separator_->SetBorder(CreateEmptyBorder(0, 0, 1, 0));
SkBitmap painted = PaintToCanvas(1.25f);
EXPECT_EQ(kForegroundColor, painted.getColor(0, 0));
@@ -183,9 +200,9 @@ TEST_F(SeparatorTest, Paint_BottomInset_Scale125) {
}
TEST_F(SeparatorTest, Paint_RightInset_Scale100) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
- separator_.SetBorder(CreateEmptyBorder(0, 0, 0, 1));
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
+ separator_->SetBorder(CreateEmptyBorder(0, 0, 0, 1));
SkBitmap painted = PaintToCanvas(1.0f);
EXPECT_EQ(kForegroundColor, painted.getColor(0, 0));
@@ -197,9 +214,9 @@ TEST_F(SeparatorTest, Paint_RightInset_Scale100) {
}
TEST_F(SeparatorTest, Paint_RightInset_Scale125) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
- separator_.SetBorder(CreateEmptyBorder(0, 0, 0, 1));
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
+ separator_->SetBorder(CreateEmptyBorder(0, 0, 0, 1));
SkBitmap painted = PaintToCanvas(1.25f);
EXPECT_EQ(kForegroundColor, painted.getColor(0, 0));
@@ -211,9 +228,9 @@ TEST_F(SeparatorTest, Paint_RightInset_Scale125) {
}
TEST_F(SeparatorTest, Paint_Vertical_Scale100) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
- separator_.SetBorder(CreateEmptyBorder(0, 4, 0, 5));
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
+ separator_->SetBorder(CreateEmptyBorder(0, 4, 0, 5));
SkBitmap painted = PaintToCanvas(1.0f);
EXPECT_EQ(kBackgroundColor, painted.getColor(3, 0));
@@ -225,9 +242,9 @@ TEST_F(SeparatorTest, Paint_Vertical_Scale100) {
}
TEST_F(SeparatorTest, Paint_Vertical_Scale125) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
- separator_.SetBorder(CreateEmptyBorder(0, 4, 0, 5));
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
+ separator_->SetBorder(CreateEmptyBorder(0, 4, 0, 5));
SkBitmap painted = PaintToCanvas(1.25f);
EXPECT_EQ(kBackgroundColor, painted.getColor(4, 0));
@@ -239,9 +256,9 @@ TEST_F(SeparatorTest, Paint_Vertical_Scale125) {
}
TEST_F(SeparatorTest, Paint_Horizontal_Scale100) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
- separator_.SetBorder(CreateEmptyBorder(4, 0, 5, 0));
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
+ separator_->SetBorder(CreateEmptyBorder(4, 0, 5, 0));
SkBitmap painted = PaintToCanvas(1.0f);
EXPECT_EQ(kBackgroundColor, painted.getColor(0, 3));
@@ -253,9 +270,9 @@ TEST_F(SeparatorTest, Paint_Horizontal_Scale100) {
}
TEST_F(SeparatorTest, Paint_Horizontal_Scale125) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
- separator_.SetBorder(CreateEmptyBorder(4, 0, 5, 0));
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
+ separator_->SetBorder(CreateEmptyBorder(4, 0, 5, 0));
SkBitmap painted = PaintToCanvas(1.25f);
EXPECT_EQ(kBackgroundColor, painted.getColor(0, 4));
@@ -269,9 +286,9 @@ TEST_F(SeparatorTest, Paint_Horizontal_Scale125) {
// Ensure that the separator is always at least 1px, even if insets would reduce
// it to zero.
TEST_F(SeparatorTest, Paint_MinimumSize_Scale100) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
- separator_.SetBorder(CreateEmptyBorder(5, 5, 5, 5));
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
+ separator_->SetBorder(CreateEmptyBorder(5, 5, 5, 5));
SkBitmap painted = PaintToCanvas(1.0f);
EXPECT_EQ(kForegroundColor, painted.getColor(5, 5));
@@ -284,9 +301,9 @@ TEST_F(SeparatorTest, Paint_MinimumSize_Scale100) {
// Ensure that the separator is always at least 1px, even if insets would reduce
// it to zero (with scale factor > 1).
TEST_F(SeparatorTest, Paint_MinimumSize_Scale125) {
- separator_.SetSize({10, 10});
- separator_.SetColor(kForegroundColor);
- separator_.SetBorder(CreateEmptyBorder(5, 5, 5, 5));
+ separator_->SetSize({10, 10});
+ separator_->SetColor(kForegroundColor);
+ separator_->SetBorder(CreateEmptyBorder(5, 5, 5, 5));
SkBitmap painted = PaintToCanvas(1.25f);
EXPECT_EQ(kForegroundColor, painted.getColor(7, 7));
diff --git a/chromium/ui/views/controls/slider.cc b/chromium/ui/views/controls/slider.cc
index 30ca1a58332..bb5530b3671 100644
--- a/chromium/ui/views/controls/slider.cc
+++ b/chromium/ui/views/controls/slider.cc
@@ -10,6 +10,7 @@
#include <utility>
#include "base/check_op.h"
+#include "base/i18n/rtl.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/current_thread.h"
@@ -21,13 +22,13 @@
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/events/event.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/native_theme/native_theme.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/widget/widget.h"
namespace views {
@@ -74,7 +75,7 @@ float GetNearestAllowedValue(const base::flat_set<float>& allowed_values,
Slider::Slider(SliderListener* listener) : listener_(listener) {
highlight_animation_.SetSlideDuration(base::TimeDelta::FromMilliseconds(150));
SetFlipCanvasOnPaintForRTLUI(true);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
#else
SetFocusBehavior(FocusBehavior::ALWAYS);
diff --git a/chromium/ui/views/controls/slider_unittest.cc b/chromium/ui/views/controls/slider_unittest.cc
index 54dd5fb02db..a5003428c89 100644
--- a/chromium/ui/views/controls/slider_unittest.cc
+++ b/chromium/ui/views/controls/slider_unittest.cc
@@ -176,7 +176,8 @@ class SliderTest : public views::ViewsTestBase,
};
void SliderTest::ClickAt(int x, int y) {
- gfx::Point point(x, y);
+ gfx::Point point =
+ slider_->GetBoundsInScreen().origin() + gfx::Vector2d(x, y);
event_generator_->MoveMouseTo(point);
event_generator_->ClickLeftButton();
}
@@ -285,7 +286,7 @@ TEST_P(SliderTest, NukeAllowedValues) {
}
// No touch on desktop Mac. Tracked in http://crbug.com/445520.
-#if !defined(OS_APPLE) || defined(USE_AURA)
+#if !defined(OS_MAC) || defined(USE_AURA)
// Test the slider location after a tap gesture.
TEST_P(SliderTest, SliderValueForTapGesture) {
@@ -458,7 +459,7 @@ TEST_P(SliderTest, SliderRaisesA11yEvents) {
EXPECT_EQ(1, ax_counter.GetCount(ax::mojom::Event::kValueChanged));
}
-#endif // !defined(OS_APPLE) || defined(USE_AURA)
+#endif // !defined(OS_MAC) || defined(USE_AURA)
INSTANTIATE_TEST_SUITE_P(All,
SliderTest,
diff --git a/chromium/ui/views/controls/styled_label.cc b/chromium/ui/views/controls/styled_label.cc
index 74491ff02f0..bd6c47474cf 100644
--- a/chromium/ui/views/controls/styled_label.cc
+++ b/chromium/ui/views/controls/styled_label.cc
@@ -15,12 +15,12 @@
#include "base/strings/string_util.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/text_elider.h"
#include "ui/gfx/text_utils.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/controls/label.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/view_class_properties.h"
namespace views {
@@ -158,12 +158,12 @@ void StyledLabel::SetLineHeight(int line_height) {
OnPropertyChanged(&line_height_, kPropertyEffectsPreferredSizeChanged);
}
-base::Optional<SkColor> StyledLabel::GetDisplayedOnBackgroundColor() const {
+absl::optional<SkColor> StyledLabel::GetDisplayedOnBackgroundColor() const {
return displayed_on_background_color_;
}
void StyledLabel::SetDisplayedOnBackgroundColor(
- const base::Optional<SkColor>& color) {
+ const absl::optional<SkColor>& color) {
if (displayed_on_background_color_ == color)
return;
@@ -579,7 +579,7 @@ ADD_PROPERTY_METADATA(int, TextContext)
ADD_PROPERTY_METADATA(int, DefaultTextStyle)
ADD_PROPERTY_METADATA(int, LineHeight)
ADD_PROPERTY_METADATA(bool, AutoColorReadabilityEnabled)
-ADD_PROPERTY_METADATA(base::Optional<SkColor>, DisplayedOnBackgroundColor)
+ADD_PROPERTY_METADATA(absl::optional<SkColor>, DisplayedOnBackgroundColor)
END_METADATA
} // namespace views
diff --git a/chromium/ui/views/controls/styled_label.h b/chromium/ui/views/controls/styled_label.h
index cabba66f67d..1d1880cb0a4 100644
--- a/chromium/ui/views/controls/styled_label.h
+++ b/chromium/ui/views/controls/styled_label.h
@@ -14,7 +14,7 @@
#include "base/callback_forward.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/class_property.h"
#include "ui/gfx/font_list.h"
@@ -52,14 +52,14 @@ class VIEWS_EXPORT StyledLabel : public View {
// Allows full customization of the font used in the range. Ignores the
// StyledLabel's default text context and |text_style|.
- base::Optional<gfx::FontList> custom_font;
+ absl::optional<gfx::FontList> custom_font;
// The style::TextStyle for this range.
- base::Optional<int> text_style;
+ absl::optional<int> text_style;
// Overrides the text color given by |text_style| for this range.
// DEPRECATED: Use TextStyle.
- base::Optional<SkColor> override_color;
+ absl::optional<SkColor> override_color;
// A callback to be called when this link is clicked. Only used if
// |text_style| is style::STYLE_LINK.
@@ -137,8 +137,8 @@ class VIEWS_EXPORT StyledLabel : public View {
// Gets/Sets the color of the background on which the label is drawn. This
// won't be explicitly drawn, but the label will force the text color to be
// readable over it.
- base::Optional<SkColor> GetDisplayedOnBackgroundColor() const;
- void SetDisplayedOnBackgroundColor(const base::Optional<SkColor>& color);
+ absl::optional<SkColor> GetDisplayedOnBackgroundColor() const;
+ void SetDisplayedOnBackgroundColor(const absl::optional<SkColor>& color);
bool GetAutoColorReadabilityEnabled() const;
void SetAutoColorReadabilityEnabled(bool auto_color_readability);
@@ -222,7 +222,7 @@ class VIEWS_EXPORT StyledLabel : public View {
int text_context_ = style::CONTEXT_LABEL;
int default_text_style_ = style::STYLE_PRIMARY;
- base::Optional<int> line_height_;
+ absl::optional<int> line_height_;
// The ranges that should be linkified, sorted by start position.
StyleRanges style_ranges_;
@@ -239,7 +239,7 @@ class VIEWS_EXPORT StyledLabel : public View {
mutable std::unique_ptr<LayoutViews> layout_views_;
// Background color on which the label is drawn, for auto color readability.
- base::Optional<SkColor> displayed_on_background_color_;
+ absl::optional<SkColor> displayed_on_background_color_;
// Controls whether the text is automatically re-colored to be readable on the
// background.
diff --git a/chromium/ui/views/controls/styled_label_unittest.cc b/chromium/ui/views/controls/styled_label_unittest.cc
index 6e7ab1b8e2a..8e807a73593 100644
--- a/chromium/ui/views/controls/styled_label_unittest.cc
+++ b/chromium/ui/views/controls/styled_label_unittest.cc
@@ -565,8 +565,8 @@ TEST_F(StyledLabelTest, CacheSize) {
const int preferred_height = 50;
const int preferred_width = 100;
const std::string text("This is a test block of text.");
- const std::u16string another_text(base::ASCIIToUTF16(
- "This is a test block of text. This text is much longer than previous"));
+ const std::u16string another_text(
+ u"This is a test block of text. This text is much longer than previous");
InitStyledLabel(text);
diff --git a/chromium/ui/views/controls/tabbed_pane/DIR_METADATA b/chromium/ui/views/controls/tabbed_pane/DIR_METADATA
deleted file mode 100644
index d1a66307bfa..00000000000
--- a/chromium/ui/views/controls/tabbed_pane/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail: {
- component: "Internals>Views"
-}
diff --git a/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc b/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc
index 15352cf4468..4e8a167ec94 100644
--- a/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc
+++ b/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc
@@ -17,6 +17,7 @@
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/default_style.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/animation/tween.h"
@@ -24,6 +25,7 @@
#include "ui/gfx/color_palette.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/skia_util.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/border.h"
@@ -33,7 +35,6 @@
#include "ui/views/layout/fill_layout.h"
#include "ui/views/layout/flex_layout.h"
#include "ui/views/layout/layout_manager.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/view_class_properties.h"
#include "ui/views/widget/widget.h"
@@ -78,7 +79,7 @@ void Tab::SetSelected(bool selected) {
contents_->SetVisible(selected);
contents_->parent()->InvalidateLayout();
SetState(selected ? State::kActive : State::kInactive);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
SetFocusBehavior(selected ? FocusBehavior::ACCESSIBLE_ONLY
: FocusBehavior::NEVER);
#else
@@ -310,7 +311,7 @@ TabStrip::TabStrip(TabbedPane::Orientation orientation,
}
SetLayoutManager(std::move(layout));
- GetViewAccessibility().OverrideRole(ax::mojom::Role::kIgnored);
+ GetViewAccessibility().OverrideRole(ax::mojom::Role::kNone);
// These durations are taken from the Paper Tabs source:
// https://github.com/PolymerElements/paper-tabs/blob/master/paper-tabs.html
@@ -488,14 +489,6 @@ void TabStrip::OnPaintBorder(gfx::Canvas* canvas) {
ui::NativeTheme::kColorId_TabSelectedBorderColor));
}
-DEFINE_ENUM_CONVERTERS(TabbedPane::Orientation,
- {TabbedPane::Orientation::kHorizontal, u"HORIZONTAL"},
- {TabbedPane::Orientation::kVertical, u"VERTICAL"})
-
-DEFINE_ENUM_CONVERTERS(TabbedPane::TabStripStyle,
- {TabbedPane::TabStripStyle::kBorder, u"BORDER"},
- {TabbedPane::TabStripStyle::kHighlight, u"HIGHLIGHT"})
-
BEGIN_METADATA(TabStrip, View)
ADD_READONLY_PROPERTY_METADATA(int, SelectedTabIndex)
ADD_READONLY_PROPERTY_METADATA(TabbedPane::Orientation, Orientation)
@@ -628,3 +621,13 @@ BEGIN_METADATA(TabbedPane, View)
END_METADATA
} // namespace views
+
+DEFINE_ENUM_CONVERTERS(views::TabbedPane::Orientation,
+ {views::TabbedPane::Orientation::kHorizontal,
+ u"HORIZONTAL"},
+ {views::TabbedPane::Orientation::kVertical, u"VERTICAL"})
+
+DEFINE_ENUM_CONVERTERS(views::TabbedPane::TabStripStyle,
+ {views::TabbedPane::TabStripStyle::kBorder, u"BORDER"},
+ {views::TabbedPane::TabStripStyle::kHighlight,
+ u"HIGHLIGHT"})
diff --git a/chromium/ui/views/controls/table/table_header.cc b/chromium/ui/views/controls/table/table_header.cc
index 113ed48a5e2..e6cb0de3a24 100644
--- a/chromium/ui/views/controls/table/table_header.cc
+++ b/chromium/ui/views/controls/table/table_header.cc
@@ -10,17 +10,18 @@
#include <memory>
#include <vector>
+#include "base/i18n/rtl.h"
#include "cc/paint/paint_flags.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/base/cursor/cursor.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/text_utils.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/background.h"
#include "ui/views/controls/table/table_utils.h"
#include "ui/views/controls/table/table_view.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/native_cursor.h"
namespace views {
diff --git a/chromium/ui/views/controls/table/table_header.h b/chromium/ui/views/controls/table/table_header.h
index a79cd242a1e..a7e975c18d6 100644
--- a/chromium/ui/views/controls/table/table_header.h
+++ b/chromium/ui/views/controls/table/table_header.h
@@ -8,9 +8,9 @@
#include <memory>
#include "base/macros.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/gfx/font_list.h"
#include "ui/views/controls/table/table_view.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/view.h"
#include "ui/views/views_export.h"
diff --git a/chromium/ui/views/controls/table/table_view.cc b/chromium/ui/views/controls/table/table_view.cc
index 436bc7aa5e7..d5690e68a06 100644
--- a/chromium/ui/views/controls/table/table_view.cc
+++ b/chromium/ui/views/controls/table/table_view.cc
@@ -17,12 +17,13 @@
#include "base/i18n/rtl.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/ranges.h"
-#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "cc/paint/paint_flags.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/events/event.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/rect_conversions.h"
@@ -41,7 +42,6 @@
#include "ui/views/controls/table/table_utils.h"
#include "ui/views/controls/table/table_view_observer.h"
#include "ui/views/layout/layout_provider.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/style/typography.h"
@@ -86,7 +86,7 @@ ui::NativeTheme::ColorId selected_text_color_id(bool has_focus) {
// Whether the platform "command" key is down.
bool IsCmdOrCtrl(const ui::Event& event) {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
return event.IsCommandDown();
#else
return event.IsControlDown();
@@ -160,7 +160,7 @@ class TableView::HighlightPathGenerator : public views::HighlightPathGenerator {
DISALLOW_COPY_AND_ASSIGN(HighlightPathGenerator);
};
-TableView::TableView() {
+TableView::TableView() : weak_factory_(this) {
constexpr int kTextContext = style::CONTEXT_TABLE_ROW;
constexpr int kTextStyle = style::STYLE_PRIMARY;
font_list_ = style::GetFont(kTextContext, kTextStyle);
@@ -503,7 +503,7 @@ bool TableView::OnKeyPressed(const ui::KeyEvent& event) {
return true;
case ui::VKEY_UP:
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
if (event.IsAltDown()) {
if (GetRowCount())
SelectByViewIndex(0);
@@ -516,7 +516,7 @@ bool TableView::OnKeyPressed(const ui::KeyEvent& event) {
return true;
case ui::VKEY_DOWN:
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
if (event.IsAltDown()) {
if (GetRowCount())
SelectByViewIndex(GetRowCount() - 1);
@@ -789,7 +789,6 @@ void TableView::OnItemsRemoved(int start, int length) {
selection_model_.set_active(GetFirstSelectedRow());
if (!selection_model_.empty() && selection_model_.anchor() == -1)
selection_model_.set_anchor(GetFirstSelectedRow());
- NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true);
// Remove the virtual views that are no longer needed.
auto& virtual_children = GetViewAccessibility().virtual_children();
@@ -824,19 +823,17 @@ gfx::Point TableView::GetKeyboardContextMenuLocation() {
void TableView::OnFocus() {
SchedulePaintForSelection();
focus_ring_->SchedulePaint();
- needs_update_accessibility_focus_ = true;
+ ScheduleUpdateAccessibilityFocusIfNeeded();
}
void TableView::OnBlur() {
SchedulePaintForSelection();
focus_ring_->SchedulePaint();
- needs_update_accessibility_focus_ = true;
+ ScheduleUpdateAccessibilityFocusIfNeeded();
}
void TableView::OnPaint(gfx::Canvas* canvas) {
OnPaintImpl(canvas);
- if (needs_update_accessibility_focus_)
- UpdateAccessibilityFocus();
}
void TableView::OnPaintImpl(gfx::Canvas* canvas) {
@@ -1177,7 +1174,7 @@ void TableView::SetActiveVisibleColumnIndex(int index) {
}
focus_ring_->SchedulePaint();
- needs_update_accessibility_focus_ = true;
+ ScheduleUpdateAccessibilityFocusIfNeeded();
OnPropertyChanged(&active_visible_column_index_, kPropertyEffectsNone);
}
@@ -1218,8 +1215,7 @@ void TableView::SetSelectionModel(ui::ListSelectionModel new_selection) {
}
focus_ring_->SchedulePaint();
- needs_update_accessibility_focus_ = true;
- NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true);
+ ScheduleUpdateAccessibilityFocusIfNeeded();
if (observer_)
observer_->OnSelectionChanged();
}
@@ -1390,10 +1386,10 @@ std::unique_ptr<AXVirtualView> TableView::CreateCellAccessibilityView(
cell_data.SetTextDirection(ax::mojom::WritingDirection::kRtl);
auto sort_direction = ax::mojom::SortDirection::kUnsorted;
- const base::Optional<int> primary_sorted_column_id =
+ const absl::optional<int> primary_sorted_column_id =
sort_descriptors().empty()
- ? base::nullopt
- : base::make_optional(sort_descriptors()[0].column_id);
+ ? absl::nullopt
+ : absl::make_optional(sort_descriptors()[0].column_id);
if (column.sortable && primary_sorted_column_id.has_value() &&
column.id == primary_sorted_column_id.value()) {
@@ -1466,18 +1462,21 @@ void TableView::PopulateAccessibilityCellData(AXVirtualView* ax_cell,
std::u16string new_name =
model()->GetText(model_index, GetVisibleColumn(column_index).column.id);
data->SetName(new_name);
- if (current_name != new_name)
- NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, true);
+ if (current_name != new_name) {
+ ui::AXNodeData& cell_data = ax_cell->GetCustomData();
+ cell_data.SetName(new_name);
+ ax_cell->NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged);
+ }
}
std::unique_ptr<AXVirtualView> TableView::CreateHeaderAccessibilityView() {
DCHECK(header_) << "header_ needs to be instantiated before setting its"
"accessibility view.";
- const base::Optional<int> primary_sorted_column_id =
+ const absl::optional<int> primary_sorted_column_id =
sort_descriptors().empty()
- ? base::nullopt
- : base::make_optional(sort_descriptors()[0].column_id);
+ ? absl::nullopt
+ : absl::make_optional(sort_descriptors()[0].column_id);
auto ax_header = std::make_unique<AXVirtualView>();
ui::AXNodeData& header_data = ax_header->GetCustomData();
@@ -1628,8 +1627,22 @@ gfx::Rect TableView::CalculateTableCellAccessibilityBounds(
return cell_bounds;
}
-void TableView::UpdateAccessibilityFocus() {
- needs_update_accessibility_focus_ = false;
+void TableView::ScheduleUpdateAccessibilityFocusIfNeeded() {
+ if (update_accessibility_focus_pending_)
+ return;
+
+ update_accessibility_focus_pending_ = true;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&TableView::UpdateAccessibilityFocus,
+ weak_factory_.GetWeakPtr(),
+ UpdateAccessibilityFocusPassKey()));
+}
+
+void TableView::UpdateAccessibilityFocus(
+ UpdateAccessibilityFocusPassKey pass_key) {
+ DCHECK(update_accessibility_focus_pending_);
+ update_accessibility_focus_pending_ = false;
+
if (!HasFocus())
return;
@@ -1642,13 +1655,17 @@ void TableView::UpdateAccessibilityFocus() {
int active_row = ModelToView(selection_model_.active());
if (!PlatformStyle::kTableViewSupportsKeyboardNavigationByCell) {
AXVirtualView* ax_row = GetVirtualAccessibilityRow(active_row);
- if (ax_row)
+ if (ax_row) {
+ ax_row->NotifyAccessibilityEvent(ax::mojom::Event::kSelection);
GetViewAccessibility().OverrideFocus(ax_row);
+ }
} else {
AXVirtualView* ax_cell =
GetVirtualAccessibilityCell(active_row, active_visible_column_index_);
- if (ax_cell)
+ if (ax_cell) {
+ ax_cell->NotifyAccessibilityEvent(ax::mojom::Event::kSelection);
GetViewAccessibility().OverrideFocus(ax_cell);
+ }
}
}
@@ -1690,10 +1707,6 @@ AXVirtualView* TableView::GetVirtualAccessibilityCell(
return i->get();
}
-DEFINE_ENUM_CONVERTERS(TableTypes,
- {TableTypes::TEXT_ONLY, u"TEXT_ONLY"},
- {TableTypes::ICON_AND_TEXT, u"ICON_AND_TEXT"})
-
BEGIN_METADATA(TableView, View)
ADD_READONLY_PROPERTY_METADATA(int, RowCount)
ADD_READONLY_PROPERTY_METADATA(int, FirstSelectedRow)
@@ -1707,3 +1720,7 @@ ADD_PROPERTY_METADATA(bool, SortOnPaint)
END_METADATA
} // namespace views
+
+DEFINE_ENUM_CONVERTERS(views::TableTypes,
+ {views::TableTypes::TEXT_ONLY, u"TEXT_ONLY"},
+ {views::TableTypes::ICON_AND_TEXT, u"ICON_AND_TEXT"})
diff --git a/chromium/ui/views/controls/table/table_view.h b/chromium/ui/views/controls/table/table_view.h
index ec0f68b4dba..db6cc5b8c6e 100644
--- a/chromium/ui/views/controls/table/table_view.h
+++ b/chromium/ui/views/controls/table/table_view.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "ui/base/models/list_selection_model.h"
#include "ui/base/models/table_model.h"
#include "ui/base/models/table_model_observer.h"
@@ -380,10 +381,28 @@ class VIEWS_EXPORT TableView : public views::View,
const int row_index,
const int visible_column_index) const;
+ // Schedule a future call UpdateAccessibilityFocus if not already pending.
+ void ScheduleUpdateAccessibilityFocusIfNeeded();
+
+ // A PassKey so that no other code can call UpdateAccessibilityFocus
+ // directly, only ScheduleUpdateAccessibilityFocusIfNeeded.
+ class UpdateAccessibilityFocusPassKey {
+ public:
+ ~UpdateAccessibilityFocusPassKey() = default;
+
+ private:
+ friend void TableView::ScheduleUpdateAccessibilityFocusIfNeeded();
+
+ // Avoid =default to disallow creation by uniform initialization.
+ UpdateAccessibilityFocusPassKey() {} // NOLINT
+ };
+
// Updates the internal accessibility state and fires the required
// accessibility events to indicate to assistive software which row is active
- // and which cell is focused, if any.
- void UpdateAccessibilityFocus();
+ // and which cell is focused, if any. Don't call this directly; call
+ // ScheduleUpdateAccessibilityFocusIfNeeded to ensure that only one call
+ // is made and that it happens after all changes have been made.
+ void UpdateAccessibilityFocus(UpdateAccessibilityFocusPassKey pass_key);
// Returns the virtual accessibility view corresponding to the specified row.
// |row| should be a view index, not a model index.
@@ -480,13 +499,12 @@ class VIEWS_EXPORT TableView : public views::View,
// True if in SetVisibleColumnWidth().
bool in_set_visible_column_width_ = false;
- // Keeps track whether a focus change has occurred so that the accessibility
- // focus would be updated after all the virtual accessibility children. Some
- // screen readers don't process the accessibility focus event right away and
- // by the time they do the focused virtual accessibility child is no longer
- // there. We need to fire the accessibility focus event after the virtual
- // accessibility children have been updated.
- bool needs_update_accessibility_focus_ = false;
+ // Keeps track whether a call to UpdateAccessibilityFocus is already
+ // pending or not.
+ bool update_accessibility_focus_pending_ = false;
+
+ // Weak pointer factory, enables using PostTask safely.
+ base::WeakPtrFactory<TableView> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(TableView);
};
diff --git a/chromium/ui/views/controls/table/table_view_unittest.cc b/chromium/ui/views/controls/table/table_view_unittest.cc
index 12cb14b36c6..85922dbaf6a 100644
--- a/chromium/ui/views/controls/table/table_view_unittest.cc
+++ b/chromium/ui/views/controls/table/table_view_unittest.cc
@@ -13,6 +13,7 @@
#include "base/numerics/ranges.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/bind.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/accessibility/ax_enums.mojom.h"
@@ -131,7 +132,7 @@ class TableViewTestHelper {
namespace {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
constexpr int kCtrlOrCmdMask = ui::EF_COMMAND_DOWN;
#else
constexpr int kCtrlOrCmdMask = ui::EF_CONTROL_DOWN;
@@ -185,7 +186,7 @@ class TestTableModel2 : public ui::TableModel {
private:
ui::TableModelObserver* observer_ = nullptr;
- base::Optional<std::u16string> tooltip_;
+ absl::optional<std::u16string> tooltip_;
// The data.
std::vector<std::vector<int>> rows_;
@@ -444,12 +445,13 @@ class TableViewTest : public ViewsTestBase,
helper_ = std::make_unique<TableViewTestHelper>(table_);
widget_ = std::make_unique<Widget>();
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ Widget::InitParams params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.bounds = gfx::Rect(0, 0, 650, 650);
params.delegate = GetWidgetDelegate(widget_.get());
widget_->Init(std::move(params));
- widget_->GetContentsView()->AddChildView(std::move(scroll_view));
+ widget_->GetRootView()->AddChildView(std::move(scroll_view));
widget_->Show();
}
@@ -460,7 +462,6 @@ class TableViewTest : public ViewsTestBase,
void ClickOnRow(int row, int flags) {
ui::test::EventGenerator generator(GetRootWindow(widget_.get()));
- generator.set_assume_window_at_origin(false);
generator.set_flags(flags);
generator.set_current_screen_location(GetPointForRow(row));
generator.PressLeftButton();
@@ -736,6 +737,29 @@ TEST_P(TableViewTest, GetVirtualAccessibilityCell) {
}
}
+TEST_P(TableViewTest, ChangingCellFiresAccessibilityEvent) {
+ int text_changed_count = 0;
+ table_->GetViewAccessibility().set_accessibility_events_callback(
+ base::BindLambdaForTesting(
+ [&](const ui::AXPlatformNodeDelegate*, const ax::mojom::Event event) {
+ if (event == ax::mojom::Event::kTextChanged)
+ ++text_changed_count;
+ }));
+
+ // A kTextChanged event is fired when a cell's data is accessed and
+ // its computed accessible text isn't the same as the previously cached
+ // value. Ensure that the cached value is correctly updated so that
+ // retrieving the data multiple times doesn't result in firing additional
+ // kTextChanged events.
+ const AXVirtualView* cell = helper_->GetVirtualAccessibilityCell(0, 0);
+ ASSERT_TRUE(cell);
+ ui::AXNodeData cell_data;
+ for (int i = 0; i < 100; ++i)
+ cell_data = cell->GetData();
+
+ EXPECT_EQ(1, text_changed_count);
+}
+
// Verifies SetColumnVisibility().
TEST_P(TableViewTest, ColumnVisibility) {
// Two columns should be visible.
@@ -1440,7 +1464,7 @@ TEST_P(TableViewTest, SelectionNoSelectOnRemove) {
}
// No touch on desktop Mac. Tracked in http://crbug.com/445520.
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// Verifies selection works by way of a gesture.
TEST_P(TableViewTest, SelectOnTap) {
// Initially no selection.
diff --git a/chromium/ui/views/controls/textarea/textarea.cc b/chromium/ui/views/controls/textarea/textarea.cc
index de01539052c..b2a2947b423 100644
--- a/chromium/ui/views/controls/textarea/textarea.cc
+++ b/chromium/ui/views/controls/textarea/textarea.cc
@@ -6,9 +6,9 @@
#include "base/logging.h"
#include "ui/base/ime/text_edit_commands.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace views {
diff --git a/chromium/ui/views/controls/textarea/textarea_unittest.cc b/chromium/ui/views/controls/textarea/textarea_unittest.cc
index 065576027cd..4ad3d7ff041 100644
--- a/chromium/ui/views/controls/textarea/textarea_unittest.cc
+++ b/chromium/ui/views/controls/textarea/textarea_unittest.cc
@@ -8,6 +8,8 @@
#include <string>
#include <vector>
+#include "base/format_macros.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "ui/events/event.h"
@@ -90,17 +92,17 @@ TEST_F(TextareaTest, MAYBE_InsertNewlineTest) {
SendKeyEvent(static_cast<ui::KeyboardCode>(ui::VKEY_A + i));
SendKeyEvent(ui::VKEY_RETURN);
}
- EXPECT_STR_EQ("a\nb\nc\nd\ne\n", textarea_->GetText());
+ EXPECT_EQ(u"a\nb\nc\nd\ne\n", textarea_->GetText());
}
TEST_F(TextareaTest, PasteNewlineTest) {
- const std::string& kText = "abc\n \n";
- textarea_->SetText(base::ASCIIToUTF16(kText));
+ const std::u16string kText = u"abc\n \n";
+ textarea_->SetText(kText);
textarea_->SelectAll(false);
textarea_->ExecuteCommand(Textfield::kCopy, 0);
textarea_->SetText(std::u16string());
textarea_->ExecuteCommand(Textfield::kPaste, 0);
- EXPECT_STR_EQ(kText, textarea_->GetText());
+ EXPECT_EQ(kText, textarea_->GetText());
}
// Re-enable when crbug.com/1163587 is fixed.
@@ -163,16 +165,16 @@ TEST_F(TextareaTest, LineSelection) {
// Select line towards right.
SendEndEvent(true);
- EXPECT_STR_EQ("67 89", textarea_->GetSelectedText());
+ EXPECT_EQ(u"67 89", textarea_->GetSelectedText());
// Select line towards left. On Mac, the existing selection should be extended
// to cover the whole line.
SendHomeEvent(true);
if (Textarea::kLineSelectionBehavior == gfx::SELECTION_EXTEND)
- EXPECT_STR_EQ("34567 89", textarea_->GetSelectedText());
+ EXPECT_EQ(u"34567 89", textarea_->GetSelectedText());
else
- EXPECT_STR_EQ("345", textarea_->GetSelectedText());
+ EXPECT_EQ(u"345", textarea_->GetSelectedText());
EXPECT_TRUE(textarea_->GetSelectedRange().is_reversed());
@@ -180,9 +182,9 @@ TEST_F(TextareaTest, LineSelection) {
SendEndEvent(true);
if (Textarea::kLineSelectionBehavior == gfx::SELECTION_EXTEND)
- EXPECT_STR_EQ("34567 89", textarea_->GetSelectedText());
+ EXPECT_EQ(u"34567 89", textarea_->GetSelectedText());
else
- EXPECT_STR_EQ("67 89", textarea_->GetSelectedText());
+ EXPECT_EQ(u"67 89", textarea_->GetSelectedText());
EXPECT_FALSE(textarea_->GetSelectedRange().is_reversed());
}
diff --git a/chromium/ui/views/controls/textfield/DIR_METADATA b/chromium/ui/views/controls/textfield/DIR_METADATA
deleted file mode 100644
index d1a66307bfa..00000000000
--- a/chromium/ui/views/controls/textfield/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail: {
- component: "Internals>Views"
-}
diff --git a/chromium/ui/views/controls/textfield/textfield.cc b/chromium/ui/views/controls/textfield/textfield.cc
index 6de25634ed3..cec2b1d3434 100644
--- a/chromium/ui/views/controls/textfield/textfield.cc
+++ b/chromium/ui/views/controls/textfield/textfield.cc
@@ -24,6 +24,7 @@
#include "build/chromeos_buildflags.h"
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/default_style.h"
@@ -31,10 +32,12 @@
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/base/ime/constants.h"
#include "ui/base/ime/input_method.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_switches.h"
#include "ui/base/ui_base_switches_util.h"
#include "ui/compositor/canvas_painter.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
@@ -57,7 +60,6 @@
#include "ui/views/controls/views_text_services_context_menu.h"
#include "ui/views/drag_utils.h"
#include "ui/views/layout/layout_provider.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/native_cursor.h"
#include "ui/views/painter.h"
#include "ui/views/style/platform_style.h"
@@ -86,7 +88,7 @@
#include "ui/wm/core/ime_util_chromeos.h"
#endif
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#include "ui/base/cocoa/defaults_utils.h"
#include "ui/base/cocoa/secure_password_input.h"
#endif
@@ -210,7 +212,7 @@ base::TimeDelta Textfield::GetCaretBlinkInterval() {
? base::TimeDelta()
: base::TimeDelta::FromMilliseconds(system_value);
}
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
base::TimeDelta system_value;
if (ui::TextInsertionCaretBlinkPeriod(&system_value))
return system_value;
@@ -232,7 +234,6 @@ Textfield::Textfield()
set_drag_controller(this);
auto cursor_view = std::make_unique<View>();
cursor_view->SetPaintToLayer(ui::LAYER_SOLID_COLOR);
- cursor_view->layer()->SetColor(GetTextColor());
cursor_view->GetViewAccessibility().OverrideIsIgnored(true);
cursor_view_ = AddChildView(std::move(cursor_view));
GetRenderText()->SetFontList(GetDefaultFontList());
@@ -242,7 +243,7 @@ Textfield::Textfield()
if (use_focus_ring_)
focus_ring_ = FocusRing::Install(this);
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// Do not map accelerators on Mac. E.g. They might not reflect custom
// keybindings that a user has set. But also on Mac, these commands dispatch
// via the "responder chain" when the OS searches through menu items in the
@@ -302,8 +303,10 @@ void Textfield::SetReadOnly(bool read_only) {
read_only_ = read_only;
if (GetInputMethod())
GetInputMethod()->OnTextInputTypeChanged(this);
- SetColor(GetTextColor());
- UpdateBackgroundColor();
+ if (GetWidget()) {
+ SetColor(GetTextColor());
+ UpdateBackgroundColor();
+ }
OnPropertyChanged(&read_only_, kPropertyEffectsPaint);
}
@@ -400,7 +403,8 @@ SkColor Textfield::GetTextColor() const {
void Textfield::SetTextColor(SkColor color) {
text_color_ = color;
- SetColor(color);
+ if (GetWidget())
+ SetColor(color);
}
SkColor Textfield::GetBackgroundColor() const {
@@ -412,7 +416,8 @@ SkColor Textfield::GetBackgroundColor() const {
void Textfield::SetBackgroundColor(SkColor color) {
background_color_ = color;
- UpdateBackgroundColor();
+ if (GetWidget())
+ UpdateBackgroundColor();
}
SkColor Textfield::GetSelectionTextColor() const {
@@ -673,12 +678,11 @@ bool Textfield::OnMousePressed(const ui::MouseEvent& event) {
#endif
}
-// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
-// of lacros-chrome is complete.
-#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
- if (!handled && !had_focus && event.IsOnlyMiddleMouseButton())
- RequestFocusWithPointer(ui::EventPointerType::kMouse);
-#endif
+ if (ui::Clipboard::IsSupportedClipboardBuffer(
+ ui::ClipboardBuffer::kSelection)) {
+ if (!handled && !had_focus && event.IsOnlyMiddleMouseButton())
+ RequestFocusWithPointer(ui::EventPointerType::kMouse);
+ }
return selection_controller_.OnMousePressed(
event, handled,
@@ -759,19 +763,9 @@ bool Textfield::OnKeyReleased(const ui::KeyEvent& event) {
}
void Textfield::OnGestureEvent(ui::GestureEvent* event) {
- static const bool kTakeFocusOnTapUp =
- base::FeatureList::IsEnabled(features::kTextfieldFocusOnTapUp);
-
switch (event->type()) {
- case ui::ET_GESTURE_TAP_DOWN:
- if (!kTakeFocusOnTapUp) {
- RequestFocusForGesture(event->details());
- event->SetHandled();
- }
- break;
case ui::ET_GESTURE_TAP:
- if (kTakeFocusOnTapUp)
- RequestFocusForGesture(event->details());
+ RequestFocusForGesture(event->details());
if (controller_ && controller_->HandleGestureEvent(this, *event)) {
event->SetHandled();
return;
@@ -877,7 +871,7 @@ bool Textfield::CanHandleAccelerators() const {
}
void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) {
- SelectAll(PlatformStyle::kTextfieldScrollsToStartOnFocusChange);
+ SelectAll(false);
}
bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
@@ -1076,11 +1070,11 @@ void Textfield::OnFocus() {
if (focus_reason_ == ui::TextInputClient::FOCUS_REASON_NONE)
focus_reason_ = ui::TextInputClient::FOCUS_REASON_OTHER;
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD)
password_input_enabler_ =
std::make_unique<ui::ScopedPasswordInputEnabler>();
-#endif // defined(OS_APPLE)
+#endif // defined(OS_MAC)
GetRenderText()->set_focused(true);
if (GetInputMethod())
@@ -1095,11 +1089,6 @@ void Textfield::OnBlur() {
gfx::RenderText* render_text = GetRenderText();
render_text->set_focused(false);
- // If necessary, yank the cursor to the logical start of the textfield.
- if (PlatformStyle::kTextfieldScrollsToStartOnFocusChange &&
- !render_text->multiline())
- model_->MoveCursorTo(gfx::SelectionModel(0, gfx::CURSOR_FORWARD));
-
if (GetInputMethod()) {
GetInputMethod()->DetachTextInputClient(this);
#if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -1115,9 +1104,9 @@ void Textfield::OnBlur() {
SchedulePaint();
View::OnBlur();
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
password_input_enabler_.reset();
-#endif // defined(OS_APPLE)
+#endif // defined(OS_MAC)
}
gfx::Point Textfield::GetKeyboardContextMenuLocation() {
@@ -1505,6 +1494,11 @@ gfx::Rect Textfield::GetCaretBounds() const {
return rect;
}
+gfx::Rect Textfield::GetSelectionBoundingBox() const {
+ NOTIMPLEMENTED_LOG_ONCE();
+ return gfx::Rect();
+}
+
bool Textfield::GetCompositionCharacterBounds(uint32_t index,
gfx::Rect* rect) const {
DCHECK(rect);
@@ -1724,7 +1718,7 @@ bool Textfield::IsTextEditCommandEnabled(ui::TextEditCommand command) const {
case ui::TextEditCommand::SCROLL_PAGE_UP:
// On Mac, the textfield should respond to Up/Down arrows keys and
// PageUp/PageDown.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
return true;
#else
return GetRenderText()->multiline();
@@ -1819,8 +1813,8 @@ bool Textfield::SetAutocorrectRange(const gfx::Range& range) {
#if defined(OS_WIN)
void Textfield::GetActiveTextInputControlLayoutBounds(
- base::Optional<gfx::Rect>* control_bounds,
- base::Optional<gfx::Rect>* selection_bounds) {
+ absl::optional<gfx::Rect>* control_bounds,
+ absl::optional<gfx::Rect>* selection_bounds) {
gfx::Rect origin = GetContentsBounds();
ConvertRectToScreen(this, &origin);
*control_bounds = origin;
@@ -2155,7 +2149,7 @@ ui::TextEditCommand Textfield::GetCommandForKeyEvent(
return ui::TextEditCommand::INVALID_COMMAND;
const bool shift = event.IsShiftDown();
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
const bool command = event.IsCommandDown();
#endif
const bool control = event.IsControlDown() || event.IsCommandDown();
@@ -2206,7 +2200,7 @@ ui::TextEditCommand Textfield::GetCommandForKeyEvent(
return ui::TextEditCommand::
MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION;
}
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
return ui::TextEditCommand::SCROLL_TO_BEGINNING_OF_DOCUMENT;
#else
return ui::TextEditCommand::MOVE_TO_BEGINNING_OF_LINE;
@@ -2214,13 +2208,13 @@ ui::TextEditCommand Textfield::GetCommandForKeyEvent(
case ui::VKEY_END:
if (shift)
return ui::TextEditCommand::MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION;
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
return ui::TextEditCommand::SCROLL_TO_END_OF_DOCUMENT;
#else
return ui::TextEditCommand::MOVE_TO_END_OF_LINE;
#endif
case ui::VKEY_UP:
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
if (control && shift) {
return ui::TextEditCommand::
MOVE_PARAGRAPH_BACKWARD_AND_MODIFY_SELECTION;
@@ -2236,7 +2230,7 @@ ui::TextEditCommand Textfield::GetCommandForKeyEvent(
: ui::TextEditCommand::INVALID_COMMAND;
#endif
case ui::VKEY_DOWN:
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
if (control && shift) {
return ui::TextEditCommand::MOVE_PARAGRAPH_FORWARD_AND_MODIFY_SELECTION;
}
@@ -2355,16 +2349,15 @@ bool Textfield::PasteSelectionClipboard() {
}
void Textfield::UpdateSelectionClipboard() {
-// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
-// of lacros-chrome is complete.
-#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
- if (text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) {
- ui::ScopedClipboardWriter(ui::ClipboardBuffer::kSelection)
- .WriteText(GetSelectedText());
- if (controller_)
- controller_->OnAfterCutOrCopy(ui::ClipboardBuffer::kSelection);
+ if (ui::Clipboard::IsSupportedClipboardBuffer(
+ ui::ClipboardBuffer::kSelection)) {
+ if (text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) {
+ ui::ScopedClipboardWriter(ui::ClipboardBuffer::kSelection)
+ .WriteText(GetSelectedText());
+ if (controller_)
+ controller_->OnAfterCutOrCopy(ui::ClipboardBuffer::kSelection);
+ }
}
-#endif
}
void Textfield::UpdateBackgroundColor() {
@@ -2413,7 +2406,7 @@ void Textfield::UpdateSelectionBackgroundColor() {
void Textfield::UpdateAfterChange(
TextChangeType text_change_type,
bool cursor_changed,
- base::Optional<bool> notify_caret_bounds_changed) {
+ absl::optional<bool> notify_caret_bounds_changed) {
if (text_change_type != TextChangeType::kNone) {
if ((text_change_type == TextChangeType::kUserTriggered) && controller_)
controller_->ContentsChanged(this, GetText());
@@ -2659,12 +2652,14 @@ ADD_PROPERTY_METADATA(bool, ReadOnly)
ADD_PROPERTY_METADATA(std::u16string, Text)
ADD_PROPERTY_METADATA(ui::TextInputType, TextInputType)
ADD_PROPERTY_METADATA(int, TextInputFlags)
-ADD_PROPERTY_METADATA(SkColor, TextColor, metadata::SkColorConverter)
-ADD_PROPERTY_METADATA(SkColor, SelectionTextColor, metadata::SkColorConverter)
-ADD_PROPERTY_METADATA(SkColor, BackgroundColor, metadata::SkColorConverter)
+ADD_PROPERTY_METADATA(SkColor, TextColor, ui::metadata::SkColorConverter)
+ADD_PROPERTY_METADATA(SkColor,
+ SelectionTextColor,
+ ui::metadata::SkColorConverter)
+ADD_PROPERTY_METADATA(SkColor, BackgroundColor, ui::metadata::SkColorConverter)
ADD_PROPERTY_METADATA(SkColor,
SelectionBackgroundColor,
- metadata::SkColorConverter)
+ ui::metadata::SkColorConverter)
ADD_PROPERTY_METADATA(bool, CursorEnabled)
ADD_PROPERTY_METADATA(std::u16string, PlaceholderText)
ADD_PROPERTY_METADATA(bool, Invalid)
diff --git a/chromium/ui/views/controls/textfield/textfield.h b/chromium/ui/views/controls/textfield/textfield.h
index 126daceed2d..cb75724d8de 100644
--- a/chromium/ui/views/controls/textfield/textfield.h
+++ b/chromium/ui/views/controls/textfield/textfield.h
@@ -21,11 +21,11 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/ime/text_edit_commands.h"
#include "ui/base/ime/text_input_client.h"
@@ -53,11 +53,11 @@ namespace base {
class TimeDelta;
}
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
namespace ui {
class ScopedPasswordInputEnabler;
}
-#endif // defined(OS_APPLE)
+#endif // defined(OS_MAC)
namespace views {
@@ -85,7 +85,7 @@ class VIEWS_EXPORT Textfield : public View,
kLastCommandId = kSelectAll,
};
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
static constexpr gfx::SelectionBehavior kLineSelectionBehavior =
gfx::SELECTION_EXTEND;
static constexpr gfx::SelectionBehavior kWordSelectionBehavior =
@@ -416,6 +416,7 @@ class VIEWS_EXPORT Textfield : public View,
int GetTextInputFlags() const override;
bool CanComposeInline() const override;
gfx::Rect GetCaretBounds() const override;
+ gfx::Rect GetSelectionBoundingBox() const override;
bool GetCompositionCharacterBounds(uint32_t index,
gfx::Rect* rect) const override;
bool HasCompositionText() const override;
@@ -454,8 +455,8 @@ class VIEWS_EXPORT Textfield : public View,
#if defined(OS_WIN)
void GetActiveTextInputControlLayoutBounds(
- base::Optional<gfx::Rect>* control_bounds,
- base::Optional<gfx::Rect>* selection_bounds) override;
+ absl::optional<gfx::Rect>* control_bounds,
+ absl::optional<gfx::Rect>* selection_bounds) override;
void SetActiveCompositionForAccessibility(
const gfx::Range& range,
const std::u16string& active_composition_text,
@@ -564,7 +565,7 @@ class VIEWS_EXPORT Textfield : public View,
void UpdateAfterChange(
TextChangeType text_change_type,
bool cursor_changed,
- base::Optional<bool> notify_caret_bounds_changed = base::nullopt);
+ absl::optional<bool> notify_caret_bounds_changed = absl::nullopt);
// Updates cursor visibility and blinks the cursor if needed.
void ShowCursor();
@@ -669,10 +670,10 @@ class VIEWS_EXPORT Textfield : public View,
int minimum_width_in_chars_ = -1;
// Colors which override default system colors.
- base::Optional<SkColor> text_color_;
- base::Optional<SkColor> background_color_;
- base::Optional<SkColor> selection_text_color_;
- base::Optional<SkColor> selection_background_color_;
+ absl::optional<SkColor> text_color_;
+ absl::optional<SkColor> background_color_;
+ absl::optional<SkColor> selection_text_color_;
+ absl::optional<SkColor> selection_background_color_;
// Text to display when empty.
std::u16string placeholder_text_;
@@ -681,14 +682,14 @@ class VIEWS_EXPORT Textfield : public View,
// TODO(newcomer): Use NativeTheme to define different default placeholder
// text colors for chrome/CrOS when harmony is enabled by default
// (https://crbug.com/803279).
- base::Optional<SkColor> placeholder_text_color_;
+ absl::optional<SkColor> placeholder_text_color_;
// The draw flags specified for |placeholder_text_|.
int placeholder_text_draw_flags_;
// The font used for the placeholder text. If this value is null, the
// placeholder text uses the same font list as the underlying RenderText.
- base::Optional<gfx::FontList> placeholder_font_list_;
+ absl::optional<gfx::FontList> placeholder_font_list_;
// True when the contents are deemed unacceptable and should be indicated as
// such.
@@ -745,7 +746,7 @@ class VIEWS_EXPORT Textfield : public View,
bool show_rejection_ui_if_any_ = false;
// Whether the text should be used to improve typing suggestions.
- base::Optional<bool> should_do_learning_;
+ absl::optional<bool> should_do_learning_;
// Context menu related members.
std::unique_ptr<ui::SimpleMenuModel> context_menu_contents_;
@@ -755,10 +756,10 @@ class VIEWS_EXPORT Textfield : public View,
// View containing the text cursor.
View* cursor_view_ = nullptr;
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Used to track active password input sessions.
std::unique_ptr<ui::ScopedPasswordInputEnabler> password_input_enabler_;
-#endif // defined(OS_APPLE)
+#endif // defined(OS_MAC)
// How this textfield was focused.
ui::TextInputClient::FocusReason focus_reason_ =
diff --git a/chromium/ui/views/controls/textfield/textfield_model_unittest.cc b/chromium/ui/views/controls/textfield/textfield_model_unittest.cc
index 309892fc372..e6c504e9f4e 100644
--- a/chromium/ui/views/controls/textfield/textfield_model_unittest.cc
+++ b/chromium/ui/views/controls/textfield/textfield_model_unittest.cc
@@ -23,8 +23,6 @@
#include "ui/views/test/test_views_delegate.h"
#include "ui/views/test/views_test_base.h"
-#define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(base::ASCIIToUTF16(ascii), utf16)
-
namespace {
struct WordAndCursor {
@@ -71,11 +69,11 @@ class TextfieldModelTest : public ViewsTestBase,
void VerifyAllSelectionTexts(
TextfieldModel* model,
- std::vector<std::string> expected_selected_texts) const {
+ std::vector<std::u16string> expected_selected_texts) const {
std::vector<std::u16string> selected_texts = GetAllSelectionTexts(model);
EXPECT_EQ(expected_selected_texts.size(), selected_texts.size());
for (size_t i = 0; i < selected_texts.size(); ++i)
- EXPECT_STR_EQ(expected_selected_texts[i], selected_texts[i]);
+ EXPECT_EQ(expected_selected_texts[i], selected_texts[i]);
}
bool composition_text_confirmed_or_cleared_ = false;
@@ -88,43 +86,43 @@ TEST_F(TextfieldModelTest, EditString) {
TextfieldModel model(nullptr);
// Append two strings.
model.Append(u"HILL");
- EXPECT_STR_EQ("HILL", model.text());
+ EXPECT_EQ(u"HILL", model.text());
model.Append(u"WORLD");
- EXPECT_STR_EQ("HILLWORLD", model.text());
+ EXPECT_EQ(u"HILLWORLD", model.text());
// Insert "E" and replace "I" with "L" to make "HELLO".
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT,
gfx::SELECTION_NONE);
model.InsertChar('E');
- EXPECT_STR_EQ("HEILLWORLD", model.text());
+ EXPECT_EQ(u"HEILLWORLD", model.text());
model.ReplaceChar('L');
- EXPECT_STR_EQ("HELLLWORLD", model.text());
+ EXPECT_EQ(u"HELLLWORLD", model.text());
model.ReplaceChar('L');
model.ReplaceChar('O');
- EXPECT_STR_EQ("HELLOWORLD", model.text());
+ EXPECT_EQ(u"HELLOWORLD", model.text());
// Delete 6th char "W", then delete 5th char "O".
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_TRUE(model.Delete());
- EXPECT_STR_EQ("HELLOORLD", model.text());
+ EXPECT_EQ(u"HELLOORLD", model.text());
EXPECT_TRUE(model.Backspace());
EXPECT_EQ(4U, model.GetCursorPosition());
- EXPECT_STR_EQ("HELLORLD", model.text());
+ EXPECT_EQ(u"HELLORLD", model.text());
// Move the cursor to start; backspace should fail.
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_NONE);
EXPECT_FALSE(model.Backspace());
- EXPECT_STR_EQ("HELLORLD", model.text());
+ EXPECT_EQ(u"HELLORLD", model.text());
// Move the cursor to the end; delete should fail, but backspace should work.
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
EXPECT_FALSE(model.Delete());
- EXPECT_STR_EQ("HELLORLD", model.text());
+ EXPECT_EQ(u"HELLORLD", model.text());
EXPECT_TRUE(model.Backspace());
- EXPECT_STR_EQ("HELLORL", model.text());
+ EXPECT_EQ(u"HELLORL", model.text());
model.MoveCursorTo(5);
model.ReplaceText(u" WOR");
- EXPECT_STR_EQ("HELLO WORL", model.text());
+ EXPECT_EQ(u"HELLO WORL", model.text());
}
TEST_F(TextfieldModelTest, EditString_SimpleRTL) {
@@ -236,7 +234,7 @@ TEST_F(TextfieldModelTest, EditString_ComplexScript) {
model.SetText(u"ABC\xFF80\xFF9E", 0);
model.MoveCursorTo(model.text().length());
model.Backspace();
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// On Mac, the entire cluster should be deleted to match
// NSTextField behavior.
EXPECT_EQ(u"ABC", model.text());
@@ -251,7 +249,7 @@ TEST_F(TextfieldModelTest, EditString_ComplexScript) {
model.SetText(u"\U0001F466\U0001F3FE", 0);
model.MoveCursorTo(model.text().length());
model.Backspace();
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// On Mac, the entire emoji should be deleted to match NSTextField
// behavior.
EXPECT_EQ(u"", model.text());
@@ -288,31 +286,31 @@ TEST_F(TextfieldModelTest, Selection) {
gfx::SELECTION_NONE);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT,
gfx::SELECTION_RETAIN);
- EXPECT_STR_EQ("E", model.GetSelectedText());
+ EXPECT_EQ(u"E", model.GetSelectedText());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT,
gfx::SELECTION_RETAIN);
- EXPECT_STR_EQ("EL", model.GetSelectedText());
+ EXPECT_EQ(u"EL", model.GetSelectedText());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_RETAIN);
- EXPECT_STR_EQ("H", model.GetSelectedText());
+ EXPECT_EQ(u"H", model.GetSelectedText());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_RETAIN);
- EXPECT_STR_EQ("ELLO", model.GetSelectedText());
+ EXPECT_EQ(u"ELLO", model.GetSelectedText());
model.ClearSelection();
EXPECT_EQ(std::u16string(), model.GetSelectedText());
// SelectAll(false) selects towards the end.
model.SelectAll(false);
- EXPECT_STR_EQ("HELLO", model.GetSelectedText());
+ EXPECT_EQ(u"HELLO", model.GetSelectedText());
EXPECT_EQ(gfx::Range(0, 5), model.render_text()->selection());
// SelectAll(true) selects towards the beginning.
model.SelectAll(true);
- EXPECT_STR_EQ("HELLO", model.GetSelectedText());
+ EXPECT_EQ(u"HELLO", model.GetSelectedText());
EXPECT_EQ(gfx::Range(5, 0), model.render_text()->selection());
// Select and move cursor.
model.SelectRange(gfx::Range(1U, 3U));
- EXPECT_STR_EQ("EL", model.GetSelectedText());
+ EXPECT_EQ(u"EL", model.GetSelectedText());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_NONE);
EXPECT_EQ(1U, model.GetCursorPosition());
model.SelectRange(gfx::Range(1U, 3U));
@@ -323,7 +321,7 @@ TEST_F(TextfieldModelTest, Selection) {
// Select multiple ranges and move cursor.
model.SelectRange(gfx::Range(1U, 3U));
model.SelectRange(gfx::Range(5U, 4U), false);
- EXPECT_STR_EQ("EL", model.GetSelectedText());
+ EXPECT_EQ(u"EL", model.GetSelectedText());
EXPECT_EQ(3U, model.GetCursorPosition());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_NONE);
EXPECT_TRUE(model.GetSelectedText().empty());
@@ -478,7 +476,7 @@ TEST_F(TextfieldModelTest, SelectionAndEdit) {
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT,
gfx::SELECTION_RETAIN); // "EL"
EXPECT_TRUE(model.Backspace());
- EXPECT_STR_EQ("HLO", model.text());
+ EXPECT_EQ(u"HLO", model.text());
model.Append(u"ILL");
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT,
@@ -486,24 +484,24 @@ TEST_F(TextfieldModelTest, SelectionAndEdit) {
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT,
gfx::SELECTION_RETAIN); // "LO"
EXPECT_TRUE(model.Delete());
- EXPECT_STR_EQ("HILL", model.text());
+ EXPECT_EQ(u"HILL", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT,
gfx::SELECTION_RETAIN); // "I"
model.InsertChar('E');
- EXPECT_STR_EQ("HELL", model.text());
+ EXPECT_EQ(u"HELL", model.text());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_NONE);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT,
gfx::SELECTION_RETAIN); // "H"
model.ReplaceChar('B');
- EXPECT_STR_EQ("BELL", model.text());
+ EXPECT_EQ(u"BELL", model.text());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT,
gfx::SELECTION_RETAIN);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT,
gfx::SELECTION_RETAIN); // "ELL"
model.ReplaceChar('E');
- EXPECT_STR_EQ("BEE", model.text());
+ EXPECT_EQ(u"BEE", model.text());
}
TEST_F(TextfieldModelTest, SelectionAndEdit_WithSecondarySelection) {
@@ -515,7 +513,7 @@ TEST_F(TextfieldModelTest, SelectionAndEdit_WithSecondarySelection) {
model.SelectRange(gfx::Range(15U, 7U), false);
model.SelectRange(gfx::Range(41U, 20U), false);
EXPECT_TRUE(model.Backspace());
- EXPECT_STR_EQ("chrome", model.text());
+ EXPECT_EQ(u"chrome", model.text());
EXPECT_TRUE(model.GetSelectedText().empty());
EXPECT_EQ(0U, model.GetCursorPosition());
EXPECT_TRUE(model.render_text()->secondary_selections().empty());
@@ -527,7 +525,7 @@ TEST_F(TextfieldModelTest, SelectionAndEdit_WithSecondarySelection) {
model.SelectRange(gfx::Range(26U, 23U), false);
model.SelectRange(gfx::Range(27U, 38U), false);
EXPECT_TRUE(model.Delete());
- EXPECT_STR_EQ("chrome is cool", model.text());
+ EXPECT_EQ(u"chrome is cool", model.text());
EXPECT_TRUE(model.GetSelectedText().empty());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_TRUE(model.render_text()->secondary_selections().empty());
@@ -538,7 +536,7 @@ TEST_F(TextfieldModelTest, SelectionAndEdit_WithSecondarySelection) {
model.SelectRange(gfx::Range(41U, 34U), false);
model.SelectRange(gfx::Range(42U, 43U), false);
model.InsertChar('n');
- EXPECT_STR_EQ("chrome is cool and classy", model.text());
+ EXPECT_EQ(u"chrome is cool and classy", model.text());
EXPECT_TRUE(model.GetSelectedText().empty());
EXPECT_EQ(17U, model.GetCursorPosition());
EXPECT_TRUE(model.render_text()->secondary_selections().empty());
@@ -549,7 +547,7 @@ TEST_F(TextfieldModelTest, SelectionAndEdit_WithSecondarySelection) {
model.SelectRange(gfx::Range(30U, 70U), false);
model.SelectRange(gfx::Range(29U, 25U), false);
model.ReplaceChar('!');
- EXPECT_STR_EQ("chrome is cool and classy!!!", model.text());
+ EXPECT_EQ(u"chrome is cool and classy!!!", model.text());
EXPECT_TRUE(model.GetSelectedText().empty());
EXPECT_EQ(28U, model.GetCursorPosition());
EXPECT_TRUE(model.render_text()->secondary_selections().empty());
@@ -570,16 +568,16 @@ TEST_F(TextfieldModelTest, Word) {
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_RETAIN);
EXPECT_EQ(24U, model.GetCursorPosition());
- EXPECT_STR_EQ("the ", model.GetSelectedText());
+ EXPECT_EQ(u"the ", model.GetSelectedText());
// Move to the end.
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_RETAIN);
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_RETAIN);
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_RETAIN);
- EXPECT_STR_EQ("the Universe, and Everything", model.GetSelectedText());
+ EXPECT_EQ(u"the Universe, and Everything", model.GetSelectedText());
// Should be safe to go next word at the end.
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_RETAIN);
- EXPECT_STR_EQ("the Universe, and Everything", model.GetSelectedText());
+ EXPECT_EQ(u"the Universe, and Everything", model.GetSelectedText());
model.InsertChar('2');
EXPECT_EQ(21U, model.GetCursorPosition());
@@ -588,20 +586,20 @@ TEST_F(TextfieldModelTest, Word) {
gfx::SELECTION_NONE); // leave 2.
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_RETAIN);
EXPECT_EQ(14U, model.GetCursorPosition());
- EXPECT_STR_EQ("Life, ", model.GetSelectedText());
+ EXPECT_EQ(u"Life, ", model.GetSelectedText());
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_RETAIN);
- EXPECT_STR_EQ("to Life, ", model.GetSelectedText());
+ EXPECT_EQ(u"to Life, ", model.GetSelectedText());
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_RETAIN);
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_RETAIN);
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT,
gfx::SELECTION_RETAIN); // Now at start.
- EXPECT_STR_EQ("The answer to Life, ", model.GetSelectedText());
+ EXPECT_EQ(u"The answer to Life, ", model.GetSelectedText());
// Should be safe to go to the previous word at the beginning.
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_RETAIN);
- EXPECT_STR_EQ("The answer to Life, ", model.GetSelectedText());
+ EXPECT_EQ(u"The answer to Life, ", model.GetSelectedText());
model.ReplaceChar('4');
EXPECT_EQ(std::u16string(), model.GetSelectedText());
- EXPECT_STR_EQ("42", model.text());
+ EXPECT_EQ(u"42", model.text());
#else // Non-Windows: move right by word does NOT include space/punctuation.
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
EXPECT_EQ(3U, model.GetCursorPosition());
@@ -614,16 +612,16 @@ TEST_F(TextfieldModelTest, Word) {
// Should passes the non word char ','
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_RETAIN);
EXPECT_EQ(23U, model.GetCursorPosition());
- EXPECT_STR_EQ(", the", model.GetSelectedText());
+ EXPECT_EQ(u", the", model.GetSelectedText());
// Move to the end.
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_RETAIN);
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_RETAIN);
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_RETAIN);
- EXPECT_STR_EQ(", the Universe, and Everything", model.GetSelectedText());
+ EXPECT_EQ(u", the Universe, and Everything", model.GetSelectedText());
// Should be safe to go next word at the end.
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_RETAIN);
- EXPECT_STR_EQ(", the Universe, and Everything", model.GetSelectedText());
+ EXPECT_EQ(u", the Universe, and Everything", model.GetSelectedText());
model.InsertChar('2');
EXPECT_EQ(19U, model.GetCursorPosition());
@@ -632,20 +630,20 @@ TEST_F(TextfieldModelTest, Word) {
gfx::SELECTION_NONE); // leave 2.
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_RETAIN);
EXPECT_EQ(14U, model.GetCursorPosition());
- EXPECT_STR_EQ("Life", model.GetSelectedText());
+ EXPECT_EQ(u"Life", model.GetSelectedText());
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_RETAIN);
- EXPECT_STR_EQ("to Life", model.GetSelectedText());
+ EXPECT_EQ(u"to Life", model.GetSelectedText());
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_RETAIN);
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_RETAIN);
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT,
gfx::SELECTION_RETAIN); // Now at start.
- EXPECT_STR_EQ("The answer to Life", model.GetSelectedText());
+ EXPECT_EQ(u"The answer to Life", model.GetSelectedText());
// Should be safe to go to the previous word at the beginning.
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_RETAIN);
- EXPECT_STR_EQ("The answer to Life", model.GetSelectedText());
+ EXPECT_EQ(u"The answer to Life", model.GetSelectedText());
model.ReplaceChar('4');
EXPECT_EQ(std::u16string(), model.GetSelectedText());
- EXPECT_STR_EQ("42", model.text());
+ EXPECT_EQ(u"42", model.text());
#endif
}
@@ -656,19 +654,19 @@ TEST_F(TextfieldModelTest, SetText) {
// SetText moves cursor to the indicated position.
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
model.SetText(u"GOODBYE", 6);
- EXPECT_STR_EQ("GOODBYE", model.text());
+ EXPECT_EQ(u"GOODBYE", model.text());
EXPECT_EQ(6U, model.GetCursorPosition());
model.SetText(u"SUNSET", 6);
- EXPECT_STR_EQ("SUNSET", model.text());
+ EXPECT_EQ(u"SUNSET", model.text());
EXPECT_EQ(6U, model.GetCursorPosition());
model.SelectAll(false);
- EXPECT_STR_EQ("SUNSET", model.GetSelectedText());
+ EXPECT_EQ(u"SUNSET", model.GetSelectedText());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
EXPECT_EQ(6U, model.GetCursorPosition());
// Setting text to the current text should not modify the cursor position.
model.SetText(u"SUNSET", 3);
- EXPECT_STR_EQ("SUNSET", model.text());
+ EXPECT_EQ(u"SUNSET", model.text());
EXPECT_EQ(6U, model.GetCursorPosition());
// Setting text that's shorter than the indicated cursor moves the cursor to
@@ -698,7 +696,7 @@ TEST_F(TextfieldModelTest, Clipboard) {
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
EXPECT_EQ(initial_clipboard_text, clipboard_text);
- EXPECT_STR_EQ("HELLO WORLD", model.text());
+ EXPECT_EQ(u"HELLO WORLD", model.text());
EXPECT_EQ(11U, model.GetCursorPosition());
// Copy with an empty selection should do nothing.
@@ -706,7 +704,7 @@ TEST_F(TextfieldModelTest, Clipboard) {
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
EXPECT_EQ(initial_clipboard_text, clipboard_text);
- EXPECT_STR_EQ("HELLO WORLD", model.text());
+ EXPECT_EQ(u"HELLO WORLD", model.text());
EXPECT_EQ(11U, model.GetCursorPosition());
// Cut on obscured (password) text should do nothing.
@@ -716,8 +714,8 @@ TEST_F(TextfieldModelTest, Clipboard) {
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
EXPECT_EQ(initial_clipboard_text, clipboard_text);
- EXPECT_STR_EQ("HELLO WORLD", model.text());
- EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText());
+ EXPECT_EQ(u"HELLO WORLD", model.text());
+ EXPECT_EQ(u"HELLO WORLD", model.GetSelectedText());
// Copy on obscured (password) text should do nothing.
model.SelectAll(false);
@@ -725,8 +723,8 @@ TEST_F(TextfieldModelTest, Clipboard) {
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
EXPECT_EQ(initial_clipboard_text, clipboard_text);
- EXPECT_STR_EQ("HELLO WORLD", model.text());
- EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText());
+ EXPECT_EQ(u"HELLO WORLD", model.text());
+ EXPECT_EQ(u"HELLO WORLD", model.GetSelectedText());
// Cut with non-empty selection.
model.render_text()->SetObscured(false);
@@ -735,8 +733,8 @@ TEST_F(TextfieldModelTest, Clipboard) {
EXPECT_TRUE(model.Cut());
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
- EXPECT_STR_EQ("WORLD", clipboard_text);
- EXPECT_STR_EQ("HELLO ", model.text());
+ EXPECT_EQ(u"WORLD", clipboard_text);
+ EXPECT_EQ(u"HELLO ", model.text());
EXPECT_EQ(6U, model.GetCursorPosition());
// Copy with non-empty selection.
@@ -744,19 +742,19 @@ TEST_F(TextfieldModelTest, Clipboard) {
EXPECT_TRUE(model.Copy());
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
- EXPECT_STR_EQ("HELLO ", clipboard_text);
- EXPECT_STR_EQ("HELLO ", model.text());
+ EXPECT_EQ(u"HELLO ", clipboard_text);
+ EXPECT_EQ(u"HELLO ", model.text());
EXPECT_EQ(6U, model.GetCursorPosition());
// Test that paste works regardless of the obscured bit. Please note that
// trailing spaces and tabs in clipboard strings will be stripped.
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
EXPECT_TRUE(model.Paste());
- EXPECT_STR_EQ("HELLO HELLO", model.text());
+ EXPECT_EQ(u"HELLO HELLO", model.text());
EXPECT_EQ(11U, model.GetCursorPosition());
model.render_text()->SetObscured(true);
EXPECT_TRUE(model.Paste());
- EXPECT_STR_EQ("HELLO HELLOHELLO", model.text());
+ EXPECT_EQ(u"HELLO HELLOHELLO", model.text());
EXPECT_EQ(16U, model.GetCursorPosition());
// Paste should replace the selection.
@@ -766,8 +764,8 @@ TEST_F(TextfieldModelTest, Clipboard) {
EXPECT_TRUE(model.Paste());
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
- EXPECT_STR_EQ("HELLO ", clipboard_text);
- EXPECT_STR_EQ("It's time to say HELLO.", model.text());
+ EXPECT_EQ(u"HELLO ", clipboard_text);
+ EXPECT_EQ(u"It's time to say HELLO.", model.text());
EXPECT_EQ(22U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_TRUE(model.render_text()->secondary_selections().empty());
@@ -779,9 +777,9 @@ TEST_F(TextfieldModelTest, Clipboard) {
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
EXPECT_TRUE(clipboard_text.empty());
- EXPECT_STR_EQ("It's time to say HELLO.", model.text());
+ EXPECT_EQ(u"It's time to say HELLO.", model.text());
EXPECT_EQ(8U, model.GetCursorPosition());
- EXPECT_STR_EQ("tim", model.GetSelectedText());
+ EXPECT_EQ(u"tim", model.GetSelectedText());
}
TEST_F(TextfieldModelTest, Clipboard_WithSecondarySelections) {
@@ -801,8 +799,8 @@ TEST_F(TextfieldModelTest, Clipboard_WithSecondarySelections) {
EXPECT_TRUE(model.Cut());
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
- EXPECT_STR_EQ("It's ", clipboard_text);
- EXPECT_STR_EQ("time to HELLO.", model.text());
+ EXPECT_EQ(u"It's ", clipboard_text);
+ EXPECT_EQ(u"time to HELLO.", model.text());
EXPECT_EQ(0U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_TRUE(model.render_text()->secondary_selections().empty());
@@ -814,11 +812,11 @@ TEST_F(TextfieldModelTest, Clipboard_WithSecondarySelections) {
EXPECT_TRUE(model.Copy());
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
- EXPECT_STR_EQ("HELLO", clipboard_text);
- EXPECT_STR_EQ("time to HELLO.", model.text());
+ EXPECT_EQ(u"HELLO", clipboard_text);
+ EXPECT_EQ(u"time to HELLO.", model.text());
EXPECT_EQ(8U, model.GetCursorPosition());
EXPECT_TRUE(model.HasSelection());
- VerifyAllSelectionTexts(&model, {"HELLO", "time"});
+ VerifyAllSelectionTexts(&model, {u"HELLO", u"time"});
// Paste with multiple selections should paste at the primary selection and
// delete all selections.
@@ -828,8 +826,8 @@ TEST_F(TextfieldModelTest, Clipboard_WithSecondarySelections) {
EXPECT_TRUE(model.Paste());
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
- EXPECT_STR_EQ("HELLO", clipboard_text);
- EXPECT_STR_EQ("HELLOime HELLO.", model.text());
+ EXPECT_EQ(u"HELLO", clipboard_text);
+ EXPECT_EQ(u"HELLOime HELLO.", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_TRUE(model.render_text()->secondary_selections().empty());
@@ -843,9 +841,9 @@ TEST_F(TextfieldModelTest, Clipboard_WithSecondarySelections) {
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
EXPECT_TRUE(clipboard_text.empty());
- EXPECT_STR_EQ("HELLOime HELLO.", model.text());
+ EXPECT_EQ(u"HELLOime HELLO.", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
- VerifyAllSelectionTexts(&model, {"E", "O"});
+ VerifyAllSelectionTexts(&model, {u"E", u"O"});
// Cut with an empty primary selection and nonempty secondary selections
// should neither delete the secondary selection nor replace the clipboard.
@@ -856,20 +854,20 @@ TEST_F(TextfieldModelTest, Clipboard_WithSecondarySelections) {
EXPECT_FALSE(model.Cut());
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
- EXPECT_STR_EQ("initial text", clipboard_text);
- EXPECT_STR_EQ("HELLOime HELLO.", model.text());
+ EXPECT_EQ(u"initial text", clipboard_text);
+ EXPECT_EQ(u"HELLOime HELLO.", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
- VerifyAllSelectionTexts(&model, {"", "O"});
+ VerifyAllSelectionTexts(&model, {u"", u"O"});
// Copy with an empty primary selection and nonempty secondary selections
// should not replace the clipboard.
EXPECT_FALSE(model.Copy());
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
- EXPECT_STR_EQ("initial text", clipboard_text);
- EXPECT_STR_EQ("HELLOime HELLO.", model.text());
+ EXPECT_EQ(u"initial text", clipboard_text);
+ EXPECT_EQ(u"HELLOime HELLO.", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
- VerifyAllSelectionTexts(&model, {"", "O"});
+ VerifyAllSelectionTexts(&model, {u"", u"O"});
// Paste with an empty primary selection, nonempty secondary selection, and
// empty clipboard should change neither the text nor the selections.
@@ -878,9 +876,9 @@ TEST_F(TextfieldModelTest, Clipboard_WithSecondarySelections) {
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
EXPECT_TRUE(clipboard_text.empty());
- EXPECT_STR_EQ("HELLOime HELLO.", model.text());
+ EXPECT_EQ(u"HELLOime HELLO.", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
- VerifyAllSelectionTexts(&model, {"", "O"});
+ VerifyAllSelectionTexts(&model, {u"", u"O"});
// Paste with an empty primary selection and nonempty secondary selections
// should paste at the primary selection and delete the secondary selections.
@@ -889,8 +887,8 @@ TEST_F(TextfieldModelTest, Clipboard_WithSecondarySelections) {
EXPECT_TRUE(model.Paste());
clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
&clipboard_text);
- EXPECT_STR_EQ("initial text", clipboard_text);
- EXPECT_STR_EQ("HEinitial textLLime HELLO.", model.text());
+ EXPECT_EQ(u"initial text", clipboard_text);
+ EXPECT_EQ(u"HEinitial textLLime HELLO.", model.text());
EXPECT_EQ(14U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
}
@@ -1100,25 +1098,25 @@ TEST_F(TextfieldModelTest, SelectRangeTest) {
EXPECT_FALSE(range.is_reversed());
model.SelectRange(range);
EXPECT_TRUE(model.HasSelection());
- EXPECT_STR_EQ("HELLO ", model.GetSelectedText());
+ EXPECT_EQ(u"HELLO ", model.GetSelectedText());
range = gfx::Range(6, 1);
EXPECT_TRUE(range.is_reversed());
model.SelectRange(range);
EXPECT_TRUE(model.HasSelection());
- EXPECT_STR_EQ("ELLO ", model.GetSelectedText());
+ EXPECT_EQ(u"ELLO ", model.GetSelectedText());
range = gfx::Range(2, 1000);
EXPECT_FALSE(range.is_reversed());
model.SelectRange(range);
EXPECT_TRUE(model.HasSelection());
- EXPECT_STR_EQ("LLO WORLD", model.GetSelectedText());
+ EXPECT_EQ(u"LLO WORLD", model.GetSelectedText());
range = gfx::Range(1000, 3);
EXPECT_TRUE(range.is_reversed());
model.SelectRange(range);
EXPECT_TRUE(model.HasSelection());
- EXPECT_STR_EQ("LO WORLD", model.GetSelectedText());
+ EXPECT_EQ(u"LO WORLD", model.GetSelectedText());
range = gfx::Range(0, 0);
EXPECT_TRUE(range.is_empty());
@@ -1148,8 +1146,8 @@ TEST_F(TextfieldModelTest, SelectRangeTest) {
model.SelectRange({1, 5});
model.SelectRange({100, 7}, false);
EXPECT_TRUE(model.HasSelection());
- EXPECT_STR_EQ("ELLO", model.GetSelectedText());
- VerifyAllSelectionTexts(&model, {"ELLO", "ORLD"});
+ EXPECT_EQ(u"ELLO", model.GetSelectedText());
+ VerifyAllSelectionTexts(&model, {u"ELLO", u"ORLD"});
}
TEST_F(TextfieldModelTest, SelectionTest) {
@@ -1211,19 +1209,19 @@ TEST_F(TextfieldModelTest, SelectSelectionModelTest) {
model.Append(u"HELLO WORLD");
model.SelectSelectionModel(
gfx::SelectionModel(gfx::Range(0, 6), gfx::CURSOR_BACKWARD));
- EXPECT_STR_EQ("HELLO ", model.GetSelectedText());
+ EXPECT_EQ(u"HELLO ", model.GetSelectedText());
model.SelectSelectionModel(
gfx::SelectionModel(gfx::Range(6, 1), gfx::CURSOR_FORWARD));
- EXPECT_STR_EQ("ELLO ", model.GetSelectedText());
+ EXPECT_EQ(u"ELLO ", model.GetSelectedText());
model.SelectSelectionModel(
gfx::SelectionModel(gfx::Range(2, 1000), gfx::CURSOR_BACKWARD));
- EXPECT_STR_EQ("LLO WORLD", model.GetSelectedText());
+ EXPECT_EQ(u"LLO WORLD", model.GetSelectedText());
model.SelectSelectionModel(
gfx::SelectionModel(gfx::Range(1000, 3), gfx::CURSOR_FORWARD));
- EXPECT_STR_EQ("LO WORLD", model.GetSelectedText());
+ EXPECT_EQ(u"LO WORLD", model.GetSelectedText());
model.SelectSelectionModel(gfx::SelectionModel(0, gfx::CURSOR_FORWARD));
EXPECT_TRUE(model.GetSelectedText().empty());
@@ -1245,8 +1243,8 @@ TEST_F(TextfieldModelTest, SelectSelectionModelTest) {
mutliselection_selection_model.AddSecondarySelection({20, 9});
mutliselection_selection_model.AddSecondarySelection({6, 6});
model.SelectSelectionModel(mutliselection_selection_model);
- EXPECT_STR_EQ("L", model.GetSelectedText());
- VerifyAllSelectionTexts(&model, {"L", "O", "H", "LD", ""});
+ EXPECT_EQ(u"L", model.GetSelectedText());
+ VerifyAllSelectionTexts(&model, {u"L", u"O", u"H", u"LD", u""});
}
TEST_F(TextfieldModelTest, CompositionTextTest) {
@@ -1301,12 +1299,12 @@ TEST_F(TextfieldModelTest, CompositionTextTest) {
model.GetTextRange(&range);
EXPECT_EQ(10U, range.end());
- EXPECT_STR_EQ("1234567890", model.text());
+ EXPECT_EQ(u"1234567890", model.text());
model.GetCompositionTextRange(&range);
EXPECT_EQ(gfx::Range(5, 8), range);
// Check the composition text.
- EXPECT_STR_EQ("456", model.GetTextFromRange(gfx::Range(3, 6)));
+ EXPECT_EQ(u"456", model.GetTextFromRange(gfx::Range(3, 6)));
EXPECT_FALSE(composition_text_confirmed_or_cleared_);
model.CancelCompositionText();
@@ -1317,7 +1315,7 @@ TEST_F(TextfieldModelTest, CompositionTextTest) {
EXPECT_EQ(5U, model.GetCursorPosition());
model.SetCompositionText(composition);
- EXPECT_STR_EQ("1234567890", model.text());
+ EXPECT_EQ(u"1234567890", model.text());
EXPECT_TRUE(model.SetText(u"1234567890", 0));
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
@@ -1327,7 +1325,7 @@ TEST_F(TextfieldModelTest, CompositionTextTest) {
composition.selection = gfx::Range(0, 1);
composition.ime_text_spans.clear();
model.SetCompositionText(composition);
- EXPECT_STR_EQ("1234567890678", model.text());
+ EXPECT_EQ(u"1234567890678", model.text());
EXPECT_TRUE(model.HasSelection());
#if !BUILDFLAG(IS_CHROMEOS_ASH)
EXPECT_EQ(gfx::Range(10, 11), model.render_text()->selection());
@@ -1341,20 +1339,20 @@ TEST_F(TextfieldModelTest, CompositionTextTest) {
model.InsertText(u"-");
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("1234567890-", model.text());
+ EXPECT_EQ(u"1234567890-", model.text());
EXPECT_FALSE(model.HasCompositionText());
EXPECT_FALSE(model.HasSelection());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT,
gfx::SELECTION_RETAIN);
- EXPECT_STR_EQ("-", model.GetSelectedText());
+ EXPECT_EQ(u"-", model.GetSelectedText());
model.SetCompositionText(composition);
- EXPECT_STR_EQ("1234567890678", model.text());
+ EXPECT_EQ(u"1234567890678", model.text());
model.ReplaceText(u"-");
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("1234567890-", model.text());
+ EXPECT_EQ(u"1234567890-", model.text());
EXPECT_FALSE(model.HasCompositionText());
EXPECT_FALSE(model.HasSelection());
@@ -1362,26 +1360,26 @@ TEST_F(TextfieldModelTest, CompositionTextTest) {
model.Append(u"-");
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("1234567890-678-", model.text());
+ EXPECT_EQ(u"1234567890-678-", model.text());
model.SetCompositionText(composition);
model.Delete();
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("1234567890-678-", model.text());
+ EXPECT_EQ(u"1234567890-678-", model.text());
model.SetCompositionText(composition);
model.Backspace();
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("1234567890-678-", model.text());
+ EXPECT_EQ(u"1234567890-678-", model.text());
model.SetText(std::u16string(), 0);
model.SetCompositionText(composition);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_NONE);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("678", model.text());
+ EXPECT_EQ(u"678", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
model.SetCompositionText(composition);
@@ -1389,14 +1387,14 @@ TEST_F(TextfieldModelTest, CompositionTextTest) {
gfx::SELECTION_NONE);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("676788", model.text());
+ EXPECT_EQ(u"676788", model.text());
EXPECT_EQ(6U, model.GetCursorPosition());
model.SetCompositionText(composition);
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_NONE);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("676788678", model.text());
+ EXPECT_EQ(u"676788678", model.text());
model.SetText(std::u16string(), 0);
model.SetCompositionText(composition);
@@ -1408,13 +1406,13 @@ TEST_F(TextfieldModelTest, CompositionTextTest) {
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_RETAIN);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("678678", model.text());
+ EXPECT_EQ(u"678678", model.text());
model.SetCompositionText(composition);
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("678", model.text());
+ EXPECT_EQ(u"678", model.text());
model.SetCompositionText(composition);
gfx::SelectionModel sel(
@@ -1423,25 +1421,25 @@ TEST_F(TextfieldModelTest, CompositionTextTest) {
model.MoveCursorTo(sel);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("678678", model.text());
+ EXPECT_EQ(u"678678", model.text());
model.SetCompositionText(composition);
model.SelectRange(gfx::Range(0, 3));
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("678", model.text());
+ EXPECT_EQ(u"678", model.text());
model.SetCompositionText(composition);
model.SelectAll(false);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("678", model.text());
+ EXPECT_EQ(u"678", model.text());
model.SetCompositionText(composition);
model.SelectWord();
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("678", model.text());
+ EXPECT_EQ(u"678", model.text());
model.SetCompositionText(composition);
model.ClearSelection();
@@ -1458,66 +1456,66 @@ TEST_F(TextfieldModelTest, UndoRedo_BasicTest) {
model.InsertChar('a');
EXPECT_FALSE(model.Redo()); // There is nothing to redo.
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("a", model.text());
+ EXPECT_EQ(u"a", model.text());
// Continuous inserts are treated as one edit.
model.InsertChar('b');
model.InsertChar('c');
- EXPECT_STR_EQ("abc", model.text());
+ EXPECT_EQ(u"abc", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("a", model.text());
+ EXPECT_EQ(u"a", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
EXPECT_EQ(0U, model.GetCursorPosition());
// Undoing further shouldn't change the text.
EXPECT_FALSE(model.Undo());
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
EXPECT_FALSE(model.Undo());
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
EXPECT_EQ(0U, model.GetCursorPosition());
// Redoing to the latest text.
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("a", model.text());
+ EXPECT_EQ(u"a", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("abc", model.text());
+ EXPECT_EQ(u"abc", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
// Backspace ===============================
EXPECT_TRUE(model.Backspace());
- EXPECT_STR_EQ("ab", model.text());
+ EXPECT_EQ(u"ab", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("abc", model.text());
+ EXPECT_EQ(u"abc", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ab", model.text());
+ EXPECT_EQ(u"ab", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
// Continous backspaces are treated as one edit.
EXPECT_TRUE(model.Backspace());
EXPECT_TRUE(model.Backspace());
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
// Extra backspace shouldn't affect the history.
EXPECT_FALSE(model.Backspace());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ab", model.text());
+ EXPECT_EQ(u"ab", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("abc", model.text());
+ EXPECT_EQ(u"abc", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("a", model.text());
+ EXPECT_EQ(u"a", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
// Clear history
model.ClearEditHistory();
EXPECT_FALSE(model.Undo());
EXPECT_FALSE(model.Redo());
- EXPECT_STR_EQ("a", model.text());
+ EXPECT_EQ(u"a", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
// Delete ===============================
@@ -1525,28 +1523,28 @@ TEST_F(TextfieldModelTest, UndoRedo_BasicTest) {
model.ClearEditHistory();
model.MoveCursorTo(2);
EXPECT_TRUE(model.Delete());
- EXPECT_STR_EQ("ABDE", model.text());
+ EXPECT_EQ(u"ABDE", model.text());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_NONE);
EXPECT_TRUE(model.Delete());
- EXPECT_STR_EQ("BDE", model.text());
+ EXPECT_EQ(u"BDE", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABDE", model.text());
+ EXPECT_EQ(u"ABDE", model.text());
EXPECT_EQ(0U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCDE", model.text());
+ EXPECT_EQ(u"ABCDE", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABDE", model.text());
+ EXPECT_EQ(u"ABDE", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
// Continous deletes are treated as one edit.
EXPECT_TRUE(model.Delete());
EXPECT_TRUE(model.Delete());
- EXPECT_STR_EQ("AB", model.text());
+ EXPECT_EQ(u"AB", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABDE", model.text());
+ EXPECT_EQ(u"ABDE", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("AB", model.text());
+ EXPECT_EQ(u"AB", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
}
@@ -1556,63 +1554,63 @@ TEST_F(TextfieldModelTest, UndoRedo_SetText) {
// Simulate typing www.y while www.google.com and www.youtube.com are
// autocompleted.
model.InsertChar('w'); // w|
- EXPECT_STR_EQ("w", model.text());
+ EXPECT_EQ(u"w", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
model.SetText(u"www.google.com", 1); // w|ww.google.com
model.SelectRange(gfx::Range(14, 1)); // w[ww.google.com]
EXPECT_EQ(1U, model.GetCursorPosition());
- EXPECT_STR_EQ("www.google.com", model.text());
+ EXPECT_EQ(u"www.google.com", model.text());
model.InsertChar('w'); // ww|
- EXPECT_STR_EQ("ww", model.text());
+ EXPECT_EQ(u"ww", model.text());
model.SetText(u"www.google.com", 2); // ww|w.google.com
model.SelectRange(gfx::Range(14, 2)); // ww[w.google.com]
model.InsertChar('w'); // www|
- EXPECT_STR_EQ("www", model.text());
+ EXPECT_EQ(u"www", model.text());
model.SetText(u"www.google.com", 3); // www|.google.com
model.SelectRange(gfx::Range(14, 3)); // www[.google.com]
model.InsertChar('.'); // www.|
- EXPECT_STR_EQ("www.", model.text());
+ EXPECT_EQ(u"www.", model.text());
model.SetText(u"www.google.com", 4); // www.|google.com
model.SelectRange(gfx::Range(14, 4)); // www.[google.com]
model.InsertChar('y'); // www.y|
- EXPECT_STR_EQ("www.y", model.text());
+ EXPECT_EQ(u"www.y", model.text());
model.SetText(u"www.youtube.com", 5); // www.y|outube.com
- EXPECT_STR_EQ("www.youtube.com", model.text());
+ EXPECT_EQ(u"www.youtube.com", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
// Undo until the initial edit.
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("www.google.com", model.text());
+ EXPECT_EQ(u"www.google.com", model.text());
EXPECT_EQ(4U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("www.google.com", model.text());
+ EXPECT_EQ(u"www.google.com", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("www.google.com", model.text());
+ EXPECT_EQ(u"www.google.com", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("www.google.com", model.text());
+ EXPECT_EQ(u"www.google.com", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
EXPECT_EQ(0U, model.GetCursorPosition());
EXPECT_FALSE(model.Undo());
// Redo until the last edit.
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("www.google.com", model.text());
+ EXPECT_EQ(u"www.google.com", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("www.google.com", model.text());
+ EXPECT_EQ(u"www.google.com", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("www.google.com", model.text());
+ EXPECT_EQ(u"www.google.com", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("www.google.com", model.text());
+ EXPECT_EQ(u"www.google.com", model.text());
EXPECT_EQ(4U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("www.youtube.com", model.text());
+ EXPECT_EQ(u"www.youtube.com", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_FALSE(model.Redo());
}
@@ -1621,25 +1619,25 @@ TEST_F(TextfieldModelTest, UndoRedo_BackspaceThenSetText) {
// This is to test the undo/redo behavior of omnibox.
TextfieldModel model(nullptr);
model.InsertChar('w');
- EXPECT_STR_EQ("w", model.text());
+ EXPECT_EQ(u"w", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
model.SetText(u"www.google.com", 1);
- EXPECT_STR_EQ("www.google.com", model.text());
+ EXPECT_EQ(u"www.google.com", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
EXPECT_EQ(14U, model.GetCursorPosition());
EXPECT_TRUE(model.Backspace());
EXPECT_TRUE(model.Backspace());
- EXPECT_STR_EQ("www.google.c", model.text());
+ EXPECT_EQ(u"www.google.c", model.text());
// Autocomplete sets the text.
model.SetText(u"www.google.com/search=www.google.c", 12);
- EXPECT_STR_EQ("www.google.com/search=www.google.c", model.text());
+ EXPECT_EQ(u"www.google.com/search=www.google.c", model.text());
EXPECT_EQ(12U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("www.google.c", model.text());
+ EXPECT_EQ(u"www.google.c", model.text());
EXPECT_EQ(12U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("www.google.com", model.text());
+ EXPECT_EQ(u"www.google.com", model.text());
EXPECT_EQ(14U, model.GetCursorPosition());
}
@@ -1651,142 +1649,142 @@ TEST_F(TextfieldModelTest, UndoRedo_CutCopyPasteTest) {
model.SelectRange(gfx::Range(1, 3)); // A[BC]DE
EXPECT_EQ(3U, model.GetCursorPosition());
model.Cut(); // A|DE
- EXPECT_STR_EQ("ADE", model.text());
+ EXPECT_EQ(u"ADE", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo()); // A[BC]DE
- EXPECT_STR_EQ("ABCDE", model.text());
+ EXPECT_EQ(u"ABCDE", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.render_text()->selection().EqualsIgnoringDirection(
gfx::Range(1, 3)));
EXPECT_TRUE(model.Undo()); // |
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
EXPECT_EQ(0U, model.GetCursorPosition());
EXPECT_FALSE(model.Undo()); // There is no more to undo. |
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
EXPECT_TRUE(model.Redo()); // ABCDE|
- EXPECT_STR_EQ("ABCDE", model.text());
+ EXPECT_EQ(u"ABCDE", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo()); // A|DE
- EXPECT_STR_EQ("ADE", model.text());
+ EXPECT_EQ(u"ADE", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_FALSE(model.Redo()); // There is no more to redo. A|DE
- EXPECT_STR_EQ("ADE", model.text());
+ EXPECT_EQ(u"ADE", model.text());
model.Paste(); // ABC|DE
model.Paste(); // ABCBC|DE
model.Paste(); // ABCBCBC|DE
- EXPECT_STR_EQ("ABCBCBCDE", model.text());
+ EXPECT_EQ(u"ABCBCBCDE", model.text());
EXPECT_EQ(7U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo()); // ABCBC|DE
- EXPECT_STR_EQ("ABCBCDE", model.text());
+ EXPECT_EQ(u"ABCBCDE", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo()); // ABC|DE
- EXPECT_STR_EQ("ABCDE", model.text());
+ EXPECT_EQ(u"ABCDE", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo()); // A|DE
- EXPECT_STR_EQ("ADE", model.text());
+ EXPECT_EQ(u"ADE", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo()); // A[BC]DE
- EXPECT_STR_EQ("ABCDE", model.text());
+ EXPECT_EQ(u"ABCDE", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.render_text()->selection().EqualsIgnoringDirection(
gfx::Range(1, 3)));
EXPECT_TRUE(model.Undo()); // |
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
EXPECT_EQ(0U, model.GetCursorPosition());
EXPECT_FALSE(model.Undo()); // |
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABCDE", model.text()); // ABCDE|
+ EXPECT_EQ(u"ABCDE", model.text()); // ABCDE|
EXPECT_EQ(5U, model.GetCursorPosition());
// Test Redo.
EXPECT_TRUE(model.Redo()); // A|DE
- EXPECT_STR_EQ("ADE", model.text());
+ EXPECT_EQ(u"ADE", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo()); // ABC|DE
- EXPECT_STR_EQ("ABCDE", model.text());
+ EXPECT_EQ(u"ABCDE", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo()); // ABCBC|DE
- EXPECT_STR_EQ("ABCBCDE", model.text());
+ EXPECT_EQ(u"ABCBCDE", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo()); // ABCBCBC|DE
- EXPECT_STR_EQ("ABCBCBCDE", model.text());
+ EXPECT_EQ(u"ABCBCBCDE", model.text());
EXPECT_EQ(7U, model.GetCursorPosition());
EXPECT_FALSE(model.Redo()); // ABCBCBC|DE
// Test using SelectRange.
model.SelectRange(gfx::Range(1, 3)); // A[BC]BCBCDE
EXPECT_TRUE(model.Cut()); // A|BCBCDE
- EXPECT_STR_EQ("ABCBCDE", model.text());
+ EXPECT_EQ(u"ABCBCDE", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
model.SelectRange(gfx::Range(1, 1)); // A|BCBCDE
EXPECT_FALSE(model.Cut()); // A|BCBCDE
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
// ABCBCDE|
EXPECT_TRUE(model.Paste()); // ABCBCDEBC|
- EXPECT_STR_EQ("ABCBCDEBC", model.text());
+ EXPECT_EQ(u"ABCBCDEBC", model.text());
EXPECT_EQ(9U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo()); // ABCBCDE|
- EXPECT_STR_EQ("ABCBCDE", model.text());
+ EXPECT_EQ(u"ABCBCDE", model.text());
EXPECT_EQ(7U, model.GetCursorPosition());
// An empty cut shouldn't create an edit.
EXPECT_TRUE(model.Undo()); // ABC|BCBCDE
- EXPECT_STR_EQ("ABCBCBCDE", model.text());
+ EXPECT_EQ(u"ABCBCBCDE", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.render_text()->selection().EqualsIgnoringDirection(
gfx::Range(1, 3)));
// Test Copy.
ResetModel(&model);
model.SetText(u"12345", 5); // 12345|
- EXPECT_STR_EQ("12345", model.text());
+ EXPECT_EQ(u"12345", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
model.SelectRange(gfx::Range(1, 3)); // 1[23]45
model.Copy(); // Copy "23". // 1[23]45
- EXPECT_STR_EQ("12345", model.text());
+ EXPECT_EQ(u"12345", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
model.Paste(); // Paste "23" into "23". // 123|45
- EXPECT_STR_EQ("12345", model.text());
+ EXPECT_EQ(u"12345", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
model.Paste(); // 12323|45
- EXPECT_STR_EQ("1232345", model.text());
+ EXPECT_EQ(u"1232345", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo()); // 123|45
- EXPECT_STR_EQ("12345", model.text());
+ EXPECT_EQ(u"12345", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
// TODO(oshima): Change the return type from bool to enum.
EXPECT_FALSE(model.Undo()); // No text change. 1[23]45
- EXPECT_STR_EQ("12345", model.text());
+ EXPECT_EQ(u"12345", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.render_text()->selection().EqualsIgnoringDirection(
gfx::Range(1, 3)));
EXPECT_TRUE(model.Undo()); // |
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
EXPECT_FALSE(model.Undo()); // |
// Test Redo.
EXPECT_TRUE(model.Redo()); // 12345|
- EXPECT_STR_EQ("12345", model.text());
+ EXPECT_EQ(u"12345", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo()); // 12|345
- EXPECT_STR_EQ("12345", model.text()); // For 1st paste
+ EXPECT_EQ(u"12345", model.text()); // For 1st paste
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo()); // 12323|45
- EXPECT_STR_EQ("1232345", model.text());
+ EXPECT_EQ(u"1232345", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_FALSE(model.Redo()); // 12323|45
- EXPECT_STR_EQ("1232345", model.text());
+ EXPECT_EQ(u"1232345", model.text());
// Test using SelectRange.
model.SelectRange(gfx::Range(1, 3)); // 1[23]2345
model.Copy(); // 1[23]2345
- EXPECT_STR_EQ("1232345", model.text());
+ EXPECT_EQ(u"1232345", model.text());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
// 1232345|
EXPECT_TRUE(model.Paste()); // 123234523|
- EXPECT_STR_EQ("123234523", model.text());
+ EXPECT_EQ(u"123234523", model.text());
EXPECT_EQ(9U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo()); // 1232345|
- EXPECT_STR_EQ("1232345", model.text());
+ EXPECT_EQ(u"1232345", model.text());
EXPECT_EQ(7U, model.GetCursorPosition());
}
@@ -1798,14 +1796,14 @@ TEST_F(TextfieldModelTest, UndoRedo_CursorTest) {
gfx::SELECTION_NONE);
model.InsertChar('b');
// Moving the cursor shouldn't create a new edit.
- EXPECT_STR_EQ("ab", model.text());
+ EXPECT_EQ(u"ab", model.text());
EXPECT_FALSE(model.Redo());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
EXPECT_FALSE(model.Undo());
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ab", model.text());
+ EXPECT_EQ(u"ab", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
EXPECT_FALSE(model.Redo());
}
@@ -1819,12 +1817,12 @@ TEST_F(TextfieldModelTest, Undo_SelectionTest) {
// Deleting the selected text should change the text and the range.
EXPECT_TRUE(model.Backspace());
- EXPECT_STR_EQ("abef", model.text());
+ EXPECT_EQ(u"abef", model.text());
EXPECT_EQ(model.render_text()->selection(), gfx::Range(2, 2));
// Undoing the deletion should restore the former range.
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("abcdef", model.text());
+ EXPECT_EQ(u"abcdef", model.text());
EXPECT_EQ(model.render_text()->selection(), range);
// When range.start = range.end, nothing is selected and
@@ -1834,12 +1832,12 @@ TEST_F(TextfieldModelTest, Undo_SelectionTest) {
// Deleting a single character should change the text and cursor location.
EXPECT_TRUE(model.Backspace());
- EXPECT_STR_EQ("acdef", model.text());
+ EXPECT_EQ(u"acdef", model.text());
EXPECT_EQ(model.render_text()->selection(), gfx::Range(1, 1));
// Undoing the deletion should restore the former range.
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("abcdef", model.text());
+ EXPECT_EQ(u"abcdef", model.text());
EXPECT_EQ(model.render_text()->selection(), gfx::Range(2, 2));
model.MoveCursorTo(model.text().length());
@@ -1847,7 +1845,7 @@ TEST_F(TextfieldModelTest, Undo_SelectionTest) {
model.SelectRange(gfx::Range(1, 3));
model.SetText(u"[set]", 0);
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("abcde", model.text());
+ EXPECT_EQ(u"abcde", model.text());
EXPECT_EQ(model.render_text()->selection(), gfx::Range(1, 3));
}
@@ -1856,20 +1854,20 @@ void RunInsertReplaceTest(TextfieldModel* model) {
model->InsertChar('1');
model->InsertChar('2');
model->InsertChar('3');
- EXPECT_STR_EQ("a123d", model->text());
+ EXPECT_EQ(u"a123d", model->text());
EXPECT_EQ(4U, model->GetCursorPosition());
EXPECT_TRUE(model->Undo());
- EXPECT_STR_EQ("abcd", model->text());
+ EXPECT_EQ(u"abcd", model->text());
EXPECT_EQ(reverse ? 1U : 3U, model->GetCursorPosition());
EXPECT_TRUE(model->Undo());
- EXPECT_STR_EQ("", model->text());
+ EXPECT_EQ(u"", model->text());
EXPECT_EQ(0U, model->GetCursorPosition());
EXPECT_FALSE(model->Undo());
EXPECT_TRUE(model->Redo());
- EXPECT_STR_EQ("abcd", model->text());
+ EXPECT_EQ(u"abcd", model->text());
EXPECT_EQ(4U, model->GetCursorPosition());
EXPECT_TRUE(model->Redo());
- EXPECT_STR_EQ("a123d", model->text());
+ EXPECT_EQ(u"a123d", model->text());
EXPECT_EQ(4U, model->GetCursorPosition());
EXPECT_FALSE(model->Redo());
}
@@ -1880,20 +1878,20 @@ void RunOverwriteReplaceTest(TextfieldModel* model) {
model->ReplaceChar('2');
model->ReplaceChar('3');
model->ReplaceChar('4');
- EXPECT_STR_EQ("a1234", model->text());
+ EXPECT_EQ(u"a1234", model->text());
EXPECT_EQ(5U, model->GetCursorPosition());
EXPECT_TRUE(model->Undo());
- EXPECT_STR_EQ("abcd", model->text());
+ EXPECT_EQ(u"abcd", model->text());
EXPECT_EQ(reverse ? 1U : 3U, model->GetCursorPosition());
EXPECT_TRUE(model->Undo());
- EXPECT_STR_EQ("", model->text());
+ EXPECT_EQ(u"", model->text());
EXPECT_EQ(0U, model->GetCursorPosition());
EXPECT_FALSE(model->Undo());
EXPECT_TRUE(model->Redo());
- EXPECT_STR_EQ("abcd", model->text());
+ EXPECT_EQ(u"abcd", model->text());
EXPECT_EQ(4U, model->GetCursorPosition());
EXPECT_TRUE(model->Redo());
- EXPECT_STR_EQ("a1234", model->text());
+ EXPECT_EQ(u"a1234", model->text());
EXPECT_EQ(5U, model->GetCursorPosition());
EXPECT_FALSE(model->Redo());
}
@@ -1942,39 +1940,39 @@ TEST_F(TextfieldModelTest, UndoRedo_CompositionText) {
model.SetText(u"ABCDE", 0);
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
model.InsertChar('x');
- EXPECT_STR_EQ("ABCDEx", model.text());
+ EXPECT_EQ(u"ABCDEx", model.text());
EXPECT_TRUE(model.Undo()); // set composition should forget undone edit.
model.SetCompositionText(composition);
EXPECT_TRUE(model.HasCompositionText());
EXPECT_TRUE(model.HasSelection());
- EXPECT_STR_EQ("ABCDEabc", model.text());
+ EXPECT_EQ(u"ABCDEabc", model.text());
// Confirm the composition.
uint32_t composition_text_length = model.ConfirmCompositionText();
EXPECT_EQ(composition_text_length, static_cast<uint32_t>(3));
- EXPECT_STR_EQ("ABCDEabc", model.text());
+ EXPECT_EQ(u"ABCDEabc", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCDE", model.text());
+ EXPECT_EQ(u"ABCDE", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABCDE", model.text());
+ EXPECT_EQ(u"ABCDE", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABCDEabc", model.text());
+ EXPECT_EQ(u"ABCDEabc", model.text());
EXPECT_FALSE(model.Redo());
// Cancel the composition.
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_NONE);
model.SetCompositionText(composition);
- EXPECT_STR_EQ("abcABCDEabc", model.text());
+ EXPECT_EQ(u"abcABCDEabc", model.text());
model.CancelCompositionText();
- EXPECT_STR_EQ("ABCDEabc", model.text());
+ EXPECT_EQ(u"ABCDEabc", model.text());
EXPECT_FALSE(model.Redo());
- EXPECT_STR_EQ("ABCDEabc", model.text());
+ EXPECT_EQ(u"ABCDEabc", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCDE", model.text());
+ EXPECT_EQ(u"ABCDE", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABCDEabc", model.text());
+ EXPECT_EQ(u"ABCDEabc", model.text());
EXPECT_FALSE(model.Redo());
// Call SetText with the same text as the result.
@@ -1982,13 +1980,13 @@ TEST_F(TextfieldModelTest, UndoRedo_CompositionText) {
model.SetText(u"ABCDE", 0);
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
model.SetCompositionText(composition);
- EXPECT_STR_EQ("ABCDEabc", model.text());
+ EXPECT_EQ(u"ABCDEabc", model.text());
model.SetText(u"ABCDEabc", 0);
- EXPECT_STR_EQ("ABCDEabc", model.text());
+ EXPECT_EQ(u"ABCDEabc", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCDE", model.text());
+ EXPECT_EQ(u"ABCDE", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABCDEabc", model.text());
+ EXPECT_EQ(u"ABCDEabc", model.text());
EXPECT_FALSE(model.Redo());
// Call SetText with a different result; the composition should be forgotten.
@@ -1996,13 +1994,13 @@ TEST_F(TextfieldModelTest, UndoRedo_CompositionText) {
model.SetText(u"ABCDE", 0);
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
model.SetCompositionText(composition);
- EXPECT_STR_EQ("ABCDEabc", model.text());
+ EXPECT_EQ(u"ABCDEabc", model.text());
model.SetText(u"1234", 0);
- EXPECT_STR_EQ("1234", model.text());
+ EXPECT_EQ(u"1234", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCDE", model.text());
+ EXPECT_EQ(u"ABCDE", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("1234", model.text());
+ EXPECT_EQ(u"1234", model.text());
EXPECT_FALSE(model.Redo());
// TODO(oshima): Test the behavior with an IME.
@@ -2045,33 +2043,33 @@ TEST_F(TextfieldModelTest, UndoRedo_TypingWithSecondarySelections) {
// Undo 3 times
EXPECT_TRUE(model.Undo()); // [prefix ]ab c[d suffix]
- EXPECT_STR_EQ("prefix ab cd suffix", model.text());
+ EXPECT_EQ(u"prefix ab cd suffix", model.text());
EXPECT_EQ(11U, model.GetCursorPosition());
- VerifyAllSelectionTexts(&model, {"d suffix", "prefix "});
+ VerifyAllSelectionTexts(&model, {u"d suffix", u"prefix "});
EXPECT_TRUE(model.Undo()); // [prefix ]ab [xy suffix]
- EXPECT_STR_EQ("prefix ab xy suffix", model.text());
+ EXPECT_EQ(u"prefix ab xy suffix", model.text());
EXPECT_EQ(10U, model.GetCursorPosition());
- VerifyAllSelectionTexts(&model, {"xy suffix", "prefix "});
+ VerifyAllSelectionTexts(&model, {u"xy suffix", u"prefix "});
EXPECT_TRUE(model.Undo()); // [prefix ]ab[ xy suffix]
- EXPECT_STR_EQ("prefix ab xy suffix", model.text());
+ EXPECT_EQ(u"prefix ab xy suffix", model.text());
EXPECT_EQ(9U, model.GetCursorPosition());
- VerifyAllSelectionTexts(&model, {" xy suffix", "prefix "});
+ VerifyAllSelectionTexts(&model, {u" xy suffix", u"prefix "});
// Redo 3 times
EXPECT_TRUE(model.Redo()); // [prefix ]ab [xy suffix]
- EXPECT_STR_EQ("prefix ab xy suffix", model.text());
+ EXPECT_EQ(u"prefix ab xy suffix", model.text());
EXPECT_EQ(10U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_TRUE(model.Redo()); // [prefix ]ab c[d suffix]
- EXPECT_STR_EQ("prefix ab cd suffix", model.text());
+ EXPECT_EQ(u"prefix ab cd suffix", model.text());
EXPECT_EQ(11U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_TRUE(model.Redo()); // [prefix ]ab cd[ suffix]
- EXPECT_STR_EQ("prefix ab cd suffix", model.text());
+ EXPECT_EQ(u"prefix ab cd suffix", model.text());
EXPECT_EQ(12U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
}
@@ -2104,27 +2102,27 @@ TEST_F(TextfieldModelTest, UndoRedo_MergingEditsWithSecondarySelections) {
// Discontinuous insert (should not merge)
model.SelectRange({9, 9}); // p infix 1|3x
model.InsertChar('2'); // p infix 12|3x
- EXPECT_STR_EQ("p infix 123x", model.text());
+ EXPECT_EQ(u"p infix 123x", model.text());
EXPECT_FALSE(model.HasSelection());
// Edit history should be
// p[refix] infix [suffi]x -> p infix 13|x
// p infix 1|3x -> p infix 12|3x
// Undo 2 times
EXPECT_TRUE(model.Undo()); // p infix 1|3x
- EXPECT_STR_EQ("p infix 13x", model.text());
+ EXPECT_EQ(u"p infix 13x", model.text());
EXPECT_EQ(9U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_TRUE(model.Undo()); // p[refix] infix [suffi]x
- EXPECT_STR_EQ("prefix infix suffix", model.text());
+ EXPECT_EQ(u"prefix infix suffix", model.text());
EXPECT_EQ(13U, model.GetCursorPosition());
- VerifyAllSelectionTexts(&model, {"suffi", "refix"});
+ VerifyAllSelectionTexts(&model, {u"suffi", u"refix"});
// Redo 2 times
EXPECT_TRUE(model.Redo()); // p infix 13|x
- EXPECT_STR_EQ("p infix 13x", model.text());
+ EXPECT_EQ(u"p infix 13x", model.text());
EXPECT_EQ(10U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_TRUE(model.Redo()); // p infix 12|3x
- EXPECT_STR_EQ("p infix 123x", model.text());
+ EXPECT_EQ(u"p infix 123x", model.text());
EXPECT_EQ(10U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_FALSE(model.Redo());
@@ -2141,27 +2139,27 @@ TEST_F(TextfieldModelTest, UndoRedo_MergingEditsWithSecondarySelections) {
// Discontinuous but adjacent replace (should not merge)
model.SelectRange({10, 9}); // p infix 1[3]ix
model.InsertChar('2'); // p infix 12|ix
- EXPECT_STR_EQ("p infix 12ix", model.text());
+ EXPECT_EQ(u"p infix 12ix", model.text());
EXPECT_FALSE(model.HasSelection());
// Edit history should be
// p[refix] infix [su]ffix -> p infix 13|ix
// p infix 1[3]ix -> p infix 12|ix
// Undo 2 times
EXPECT_TRUE(model.Undo()); // p infix 1[3]ix
- EXPECT_STR_EQ("p infix 13ix", model.text());
+ EXPECT_EQ(u"p infix 13ix", model.text());
EXPECT_EQ(9U, model.GetCursorPosition());
- VerifyAllSelectionTexts(&model, {"3"});
+ VerifyAllSelectionTexts(&model, {u"3"});
EXPECT_TRUE(model.Undo()); // p[refix] infix [su]ffix
- EXPECT_STR_EQ("prefix infix suffix", model.text());
+ EXPECT_EQ(u"prefix infix suffix", model.text());
EXPECT_EQ(13U, model.GetCursorPosition());
- VerifyAllSelectionTexts(&model, {"su", "refix"});
+ VerifyAllSelectionTexts(&model, {u"su", u"refix"});
// Redo 2 times
EXPECT_TRUE(model.Redo()); // p infix 13|ix
- EXPECT_STR_EQ("p infix 13ix", model.text());
+ EXPECT_EQ(u"p infix 13ix", model.text());
EXPECT_EQ(10U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_TRUE(model.Redo()); // p infix 12|ix
- EXPECT_STR_EQ("p infix 12ix", model.text());
+ EXPECT_EQ(u"p infix 12ix", model.text());
EXPECT_EQ(10U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_FALSE(model.Redo());
@@ -2174,27 +2172,27 @@ TEST_F(TextfieldModelTest, UndoRedo_MergingEditsWithSecondarySelections) {
model.InsertChar('1'); // p infix 1|ffix
// Continuous delete (should not merge)
model.Delete(false); // p infix 1|fix
- EXPECT_STR_EQ("p infix 1fix", model.text());
+ EXPECT_EQ(u"p infix 1fix", model.text());
EXPECT_FALSE(model.HasSelection());
// Edit history should be
// p[refix] infix [su]ffix -> p infix 1|ffix
// p infix 1|ffix -> p infix 1|fix
// Undo 2 times
EXPECT_TRUE(model.Undo()); // p infix 1|ffix
- EXPECT_STR_EQ("p infix 1ffix", model.text());
+ EXPECT_EQ(u"p infix 1ffix", model.text());
EXPECT_EQ(9U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_TRUE(model.Undo()); // p[refix] infix [su]ffix
- EXPECT_STR_EQ("prefix infix suffix", model.text());
+ EXPECT_EQ(u"prefix infix suffix", model.text());
EXPECT_EQ(13U, model.GetCursorPosition());
- VerifyAllSelectionTexts(&model, {"su", "refix"});
+ VerifyAllSelectionTexts(&model, {u"su", u"refix"});
// Redo 2 times
EXPECT_TRUE(model.Redo()); // p infix 1|ffix
- EXPECT_STR_EQ("p infix 1ffix", model.text());
+ EXPECT_EQ(u"p infix 1ffix", model.text());
EXPECT_EQ(9U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_TRUE(model.Redo()); // p infix 1|fix
- EXPECT_STR_EQ("p infix 1fix", model.text());
+ EXPECT_EQ(u"p infix 1fix", model.text());
EXPECT_EQ(9U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_FALSE(model.Redo());
@@ -2207,27 +2205,27 @@ TEST_F(TextfieldModelTest, UndoRedo_MergingEditsWithSecondarySelections) {
model.Delete(false); // p infix |ffix
// Continuous insert (should not merge)
model.InsertChar('1'); // p infix 1|ffix
- EXPECT_STR_EQ("p infix 1ffix", model.text());
+ EXPECT_EQ(u"p infix 1ffix", model.text());
EXPECT_FALSE(model.HasSelection());
// Edit history should be
// p[refix] infix [su]ffix -> p infix |ffix
// p infix |ffix -> p infix 1|ffix
// Undo 2 times
EXPECT_TRUE(model.Undo()); // p infix |ffix
- EXPECT_STR_EQ("p infix ffix", model.text());
+ EXPECT_EQ(u"p infix ffix", model.text());
EXPECT_EQ(8U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_TRUE(model.Undo()); // p[refix] infix [su]ffix
- EXPECT_STR_EQ("prefix infix suffix", model.text());
+ EXPECT_EQ(u"prefix infix suffix", model.text());
EXPECT_EQ(13U, model.GetCursorPosition());
- VerifyAllSelectionTexts(&model, {"su", "refix"});
+ VerifyAllSelectionTexts(&model, {u"su", u"refix"});
// Redo 2 times
EXPECT_TRUE(model.Redo()); // p infix |ffix
- EXPECT_STR_EQ("p infix ffix", model.text());
+ EXPECT_EQ(u"p infix ffix", model.text());
EXPECT_EQ(8U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_TRUE(model.Redo()); // p infix 1|ffix
- EXPECT_STR_EQ("p infix 1ffix", model.text());
+ EXPECT_EQ(u"p infix 1ffix", model.text());
EXPECT_EQ(9U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_FALSE(model.Redo());
@@ -2241,27 +2239,27 @@ TEST_F(TextfieldModelTest, UndoRedo_MergingEditsWithSecondarySelections) {
// Continuous replacement (should not merge)
model.SelectRange({8, 9}); // p infix [f]fix
model.InsertChar('1'); // p infix 1|fix
- EXPECT_STR_EQ("p infix 1fix", model.text());
+ EXPECT_EQ(u"p infix 1fix", model.text());
EXPECT_FALSE(model.HasSelection());
// Edit history should be
// p[refix] infix [su]ffix -> p infix |ffix
// p infix [f]fix -> p infix 1|fix
// Undo 2 times
EXPECT_TRUE(model.Undo()); // p infix [f]fix
- EXPECT_STR_EQ("p infix ffix", model.text());
+ EXPECT_EQ(u"p infix ffix", model.text());
EXPECT_EQ(9U, model.GetCursorPosition());
- VerifyAllSelectionTexts(&model, {"f"});
+ VerifyAllSelectionTexts(&model, {u"f"});
EXPECT_TRUE(model.Undo()); // p[refix] infix [su]ffix
- EXPECT_STR_EQ("prefix infix suffix", model.text());
+ EXPECT_EQ(u"prefix infix suffix", model.text());
EXPECT_EQ(13U, model.GetCursorPosition());
- VerifyAllSelectionTexts(&model, {"su", "refix"});
+ VerifyAllSelectionTexts(&model, {u"su", u"refix"});
// Redo 2 times
EXPECT_TRUE(model.Redo()); // p infix |ffix
- EXPECT_STR_EQ("p infix ffix", model.text());
+ EXPECT_EQ(u"p infix ffix", model.text());
EXPECT_EQ(8U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_TRUE(model.Redo()); // p infix 1|fix
- EXPECT_STR_EQ("p infix 1fix", model.text());
+ EXPECT_EQ(u"p infix 1fix", model.text());
EXPECT_EQ(9U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_FALSE(model.Redo());
@@ -2274,27 +2272,27 @@ TEST_F(TextfieldModelTest, UndoRedo_MergingEditsWithSecondarySelections) {
model.Delete(false); // p infix |ffix
// Continuous delete (should not merge)
model.Delete(false); // p infix |fix
- EXPECT_STR_EQ("p infix fix", model.text());
+ EXPECT_EQ(u"p infix fix", model.text());
EXPECT_FALSE(model.HasSelection());
// Edit history should be
// p[refix] infix [su]ffix -> p infix |ffix
// p infix |ffix -> p infix |fix
// Undo 2 times
EXPECT_TRUE(model.Undo()); // p infix |ffix
- EXPECT_STR_EQ("p infix ffix", model.text());
+ EXPECT_EQ(u"p infix ffix", model.text());
EXPECT_EQ(8U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_TRUE(model.Undo()); // p[refix] infix [su]ffix
- EXPECT_STR_EQ("prefix infix suffix", model.text());
+ EXPECT_EQ(u"prefix infix suffix", model.text());
EXPECT_EQ(13U, model.GetCursorPosition());
- VerifyAllSelectionTexts(&model, {"su", "refix"});
+ VerifyAllSelectionTexts(&model, {u"su", u"refix"});
// Redo 2 times
EXPECT_TRUE(model.Redo()); // p infix |ffix
- EXPECT_STR_EQ("p infix ffix", model.text());
+ EXPECT_EQ(u"p infix ffix", model.text());
EXPECT_EQ(8U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_TRUE(model.Redo()); // p infix |fix
- EXPECT_STR_EQ("p infix fix", model.text());
+ EXPECT_EQ(u"p infix fix", model.text());
EXPECT_EQ(8U, model.GetCursorPosition());
EXPECT_FALSE(model.HasSelection());
EXPECT_FALSE(model.Redo());
@@ -2311,16 +2309,16 @@ TEST_F(TextfieldModelTest, Clipboard_WhiteSpaceStringTest) {
TextfieldModel model(nullptr);
model.Append(u"HELLO WORLD");
- EXPECT_STR_EQ("HELLO WORLD", model.text());
+ EXPECT_EQ(u"HELLO WORLD", model.text());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
EXPECT_EQ(11U, model.GetCursorPosition());
EXPECT_TRUE(model.Paste());
- EXPECT_STR_EQ("HELLO WORLDB", model.text());
+ EXPECT_EQ(u"HELLO WORLDB", model.text());
model.SelectAll(false);
model.DeleteSelection();
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
// Test 2
// Clipboard text with multiple leading tabs and spaces should be pasted with
@@ -2329,15 +2327,15 @@ TEST_F(TextfieldModelTest, Clipboard_WhiteSpaceStringTest) {
.WriteText(u"\t\t\t B");
model.Append(u"HELLO WORLD");
- EXPECT_STR_EQ("HELLO WORLD", model.text());
+ EXPECT_EQ(u"HELLO WORLD", model.text());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
EXPECT_EQ(11U, model.GetCursorPosition());
EXPECT_TRUE(model.Paste());
- EXPECT_STR_EQ("HELLO WORLDB", model.text());
+ EXPECT_EQ(u"HELLO WORLDB", model.text());
model.SelectAll(false);
model.DeleteSelection();
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
// Test 3
// Clipboard text with multiple tabs separating the words should be pasted
@@ -2346,15 +2344,15 @@ TEST_F(TextfieldModelTest, Clipboard_WhiteSpaceStringTest) {
.WriteText(u"FOO \t\t BAR");
model.Append(u"HELLO WORLD");
- EXPECT_STR_EQ("HELLO WORLD", model.text());
+ EXPECT_EQ(u"HELLO WORLD", model.text());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
EXPECT_EQ(11U, model.GetCursorPosition());
EXPECT_TRUE(model.Paste());
- EXPECT_STR_EQ("HELLO WORLDFOO \t\t BAR", model.text());
+ EXPECT_EQ(u"HELLO WORLDFOO \t\t BAR", model.text());
model.SelectAll(false);
model.DeleteSelection();
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
// Test 4
// Clipboard text with multiple leading tabs and multiple tabs separating
@@ -2363,11 +2361,11 @@ TEST_F(TextfieldModelTest, Clipboard_WhiteSpaceStringTest) {
.WriteText(u"\t\tFOO \t\t BAR");
EXPECT_TRUE(model.Paste());
- EXPECT_STR_EQ("FOO \t\t BAR", model.text());
+ EXPECT_EQ(u"FOO \t\t BAR", model.text());
model.SelectAll(false);
model.DeleteSelection();
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
// Test 5
// Clipboard text with multiple trailing tabs should be pasted with all
@@ -2375,11 +2373,11 @@ TEST_F(TextfieldModelTest, Clipboard_WhiteSpaceStringTest) {
ui::ScopedClipboardWriter(ui::ClipboardBuffer::kCopyPaste)
.WriteText(u"FOO BAR\t\t\t");
EXPECT_TRUE(model.Paste());
- EXPECT_STR_EQ("FOO BAR", model.text());
+ EXPECT_EQ(u"FOO BAR", model.text());
model.SelectAll(false);
model.DeleteSelection();
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
// Test 6
// Clipboard text with only spaces and tabs should be pasted as a single
@@ -2387,18 +2385,18 @@ TEST_F(TextfieldModelTest, Clipboard_WhiteSpaceStringTest) {
ui::ScopedClipboardWriter(ui::ClipboardBuffer::kCopyPaste)
.WriteText(u" \t\t");
EXPECT_TRUE(model.Paste());
- EXPECT_STR_EQ(" ", model.text());
+ EXPECT_EQ(u" ", model.text());
model.SelectAll(false);
model.DeleteSelection();
- EXPECT_STR_EQ("", model.text());
+ EXPECT_EQ(u"", model.text());
// Test 7
// Clipboard text with lots of spaces between words should be pasted as-is.
ui::ScopedClipboardWriter(ui::ClipboardBuffer::kCopyPaste)
.WriteText(u"FOO BAR");
EXPECT_TRUE(model.Paste());
- EXPECT_STR_EQ("FOO BAR", model.text());
+ EXPECT_EQ(u"FOO BAR", model.text());
}
TEST_F(TextfieldModelTest, Transpose) {
@@ -2472,62 +2470,62 @@ TEST_F(TextfieldModelTest, Yank) {
// Delete selection but don't add to kill buffer.
model.Delete(false);
- EXPECT_STR_EQ("adefgh", model.text());
+ EXPECT_EQ(u"adefgh", model.text());
// Since the kill buffer is empty, yank should cause no change.
EXPECT_FALSE(model.Yank());
- EXPECT_STR_EQ("adefgh", model.text());
+ EXPECT_EQ(u"adefgh", model.text());
// With a nonempty selection and an empty kill buffer, yank should delete the
// selection.
model.SelectRange(gfx::Range(4, 5));
EXPECT_TRUE(model.Yank());
- EXPECT_STR_EQ("adefh", model.text());
+ EXPECT_EQ(u"adefh", model.text());
// With multiple selections and an empty kill buffer, yank should delete the
// selections.
model.SelectRange(gfx::Range(2, 3));
model.SelectRange(gfx::Range(4, 5), false);
EXPECT_TRUE(model.Yank());
- EXPECT_STR_EQ("adf", model.text());
+ EXPECT_EQ(u"adf", model.text());
// The kill buffer should remain empty after yanking without a kill buffer.
EXPECT_FALSE(model.Yank());
- EXPECT_STR_EQ("adf", model.text());
+ EXPECT_EQ(u"adf", model.text());
// Delete selection and add to kill buffer.
model.SelectRange(gfx::Range(0, 1));
model.Delete(true);
- EXPECT_STR_EQ("df", model.text());
+ EXPECT_EQ(u"df", model.text());
// Yank twice.
EXPECT_TRUE(model.Yank());
EXPECT_TRUE(model.Yank());
- EXPECT_STR_EQ("aadf", model.text());
+ EXPECT_EQ(u"aadf", model.text());
// Ensure an empty deletion does not modify the kill buffer.
model.SelectRange(gfx::Range(4));
model.Delete(true);
EXPECT_TRUE(model.Yank());
- EXPECT_STR_EQ("aadfa", model.text());
+ EXPECT_EQ(u"aadfa", model.text());
// Backspace twice but don't add to kill buffer.
model.Backspace(false);
model.Backspace(false);
- EXPECT_STR_EQ("aad", model.text());
+ EXPECT_EQ(u"aad", model.text());
// Ensure kill buffer is not modified.
EXPECT_TRUE(model.Yank());
- EXPECT_STR_EQ("aada", model.text());
+ EXPECT_EQ(u"aada", model.text());
// Backspace twice, each time modifying the kill buffer.
model.Backspace(true);
model.Backspace(true);
- EXPECT_STR_EQ("aa", model.text());
+ EXPECT_EQ(u"aa", model.text());
// Ensure yanking inserts the modified kill buffer text.
EXPECT_TRUE(model.Yank());
- EXPECT_STR_EQ("aad", model.text());
+ EXPECT_EQ(u"aad", model.text());
}
TEST_F(TextfieldModelTest, SetCompositionFromExistingText) {
@@ -2543,7 +2541,7 @@ TEST_F(TextfieldModelTest, SetCompositionFromExistingText) {
ui::CompositionText composition;
composition.text = u"123";
model.SetCompositionText(composition);
- EXPECT_STR_EQ("a123de", model.text());
+ EXPECT_EQ(u"a123de", model.text());
}
TEST_F(TextfieldModelTest, SetCompositionFromExistingText_Empty) {
@@ -2555,7 +2553,7 @@ TEST_F(TextfieldModelTest, SetCompositionFromExistingText_Empty) {
model.SetCompositionFromExistingText(gfx::Range(1, 1));
EXPECT_FALSE(model.HasCompositionText());
- EXPECT_STR_EQ("abc", model.text());
+ EXPECT_EQ(u"abc", model.text());
}
TEST_F(TextfieldModelTest, SetCompositionFromExistingText_OutOfBounds) {
diff --git a/chromium/ui/views/controls/textfield/textfield_unittest.cc b/chromium/ui/views/controls/textfield/textfield_unittest.cc
index e0974e57494..788e8538868 100644
--- a/chromium/ui/views/controls/textfield/textfield_unittest.cc
+++ b/chromium/ui/views/controls/textfield/textfield_unittest.cc
@@ -72,22 +72,18 @@
#include "ui/wm/core/ime_util_chromeos.h"
#endif
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#include "ui/base/cocoa/secure_password_input.h"
#include "ui/base/cocoa/text_services_context_menu.h"
#endif
-using base::ASCIIToUTF16;
-using base::UTF8ToUTF16;
+#if defined(USE_OZONE)
+#include "ui/events/ozone/layout/keyboard_layout_engine_test_utils.h"
+#endif
namespace views {
namespace test {
-const ui::EventType kFocusEvent =
- base::FeatureList::IsEnabled(features::kTextfieldFocusOnTapUp)
- ? ui::ET_GESTURE_TAP
- : ui::ET_GESTURE_TAP_DOWN;
-
const char16_t kHebrewLetterSamekh = 0x05E1;
// Convenience to make constructing a GestureEvent simpler.
@@ -218,7 +214,7 @@ ui::EventDispatchDetails MockInputMethod::DispatchKeyEvent(ui::KeyEvent* key) {
// On Mac, emulate InputMethodMac behavior for character events. Composition
// still needs to be mocked, since it's not possible to generate test events
// which trigger the appropriate NSResponder action messages for composition.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
if (key->is_char())
return DispatchKeyEventPostIME(key);
#endif
@@ -335,7 +331,7 @@ class TestTextfield : public views::Textfield {
// ui::TextInputClient:
void InsertChar(const ui::KeyEvent& e) override {
views::Textfield::InsertChar(e);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// On Mac, characters are inserted directly rather than attempting to get a
// unicode character from the ui::KeyEvent (which isn't always possible).
key_received_ = true;
@@ -404,6 +400,13 @@ void TextfieldTest::SetUp() {
ui::Clipboard::SetClipboardForCurrentThread(
std::make_unique<ui::TestClipboard>());
ViewsTestBase::SetUp();
+
+#if defined(USE_OZONE)
+ // TODO(crbug.com/1209477): Wayland bots use Weston with Headless backend that
+ // sets up XkbKeyboardLayoutEngine differently. When that is fixed, remove the
+ // workaround below.
+ ui::WaitUntilLayoutEngineIsReadyForTest();
+#endif
}
void TextfieldTest::TearDown() {
@@ -428,8 +431,8 @@ std::u16string TextfieldTest::GetClipboardText(
}
void TextfieldTest::SetClipboardText(ui::ClipboardBuffer clipboard_buffer,
- const std::string& text) {
- ui::ScopedClipboardWriter(clipboard_buffer).WriteText(ASCIIToUTF16(text));
+ const std::u16string& text) {
+ ui::ScopedClipboardWriter(clipboard_buffer).WriteText(text);
}
void TextfieldTest::ContentsChanged(Textfield* sender,
@@ -498,7 +501,7 @@ ui::MenuModel* TextfieldTest::GetContextMenuModel() {
}
bool TextfieldTest::TestingNativeMac() const {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
return true;
#else
return false;
@@ -574,7 +577,7 @@ void TextfieldTest::SendKeyEvent(char16_t ch, int flags, bool from_vk) {
std::vector<uint8_t>(ui::kPropertyFromVKSize);
event.SetProperties(properties);
}
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
event_generator_->Dispatch(&event);
#else
input_method_->DispatchKeyEvent(&event);
@@ -724,7 +727,7 @@ void TextfieldTest::VerifyTextfieldContextMenuContents(
int menu_index = 0;
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
if (textfield_has_selection) {
EXPECT_TRUE(menu->IsEnabledAt(menu_index++ /* Look Up "Selection" */));
EXPECT_TRUE(menu->IsEnabledAt(menu_index++ /* Separator */));
@@ -812,23 +815,23 @@ TEST_F(TextfieldTest, ModelChangesTest) {
// text programmatically.
last_contents_.clear();
textfield_->SetText(u"this is");
- EXPECT_STR_EQ("this is", model_->text());
- EXPECT_STR_EQ("this is", textfield_->GetText());
+ EXPECT_EQ(u"this is", model_->text());
+ EXPECT_EQ(u"this is", textfield_->GetText());
EXPECT_TRUE(last_contents_.empty());
textfield_->AppendText(u" a test");
- EXPECT_STR_EQ("this is a test", model_->text());
- EXPECT_STR_EQ("this is a test", textfield_->GetText());
+ EXPECT_EQ(u"this is a test", model_->text());
+ EXPECT_EQ(u"this is a test", textfield_->GetText());
EXPECT_TRUE(last_contents_.empty());
EXPECT_EQ(std::u16string(), textfield_->GetSelectedText());
textfield_->SelectAll(false);
- EXPECT_STR_EQ("this is a test", textfield_->GetSelectedText());
+ EXPECT_EQ(u"this is a test", textfield_->GetSelectedText());
EXPECT_TRUE(last_contents_.empty());
textfield_->SetTextWithoutCaretBoundsChangeNotification(u"another test", 3);
- EXPECT_STR_EQ("another test", model_->text());
- EXPECT_STR_EQ("another test", textfield_->GetText());
+ EXPECT_EQ(u"another test", model_->text());
+ EXPECT_EQ(u"another test", textfield_->GetText());
EXPECT_EQ(textfield_->GetCursorPosition(), 3u);
EXPECT_TRUE(last_contents_.empty());
}
@@ -950,9 +953,9 @@ TEST_F(TextfieldTest, KeyTest) {
// On Mac, Caps+Shift remains uppercase.
if (TestingNativeMac())
- EXPECT_STR_EQ("TeXT!1!1", textfield_->GetText());
+ EXPECT_EQ(u"TeXT!1!1", textfield_->GetText());
else
- EXPECT_STR_EQ("TexT!1!1", textfield_->GetText());
+ EXPECT_EQ(u"TexT!1!1", textfield_->GetText());
}
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
@@ -977,7 +980,7 @@ TEST_F(TextfieldTest, KeyTestControlModifier) {
}
#endif
-#if defined(OS_WIN) || defined(OS_APPLE)
+#if defined(OS_WIN) || defined(OS_MAC)
#define MAYBE_KeysWithModifiersTest KeysWithModifiersTest
#else
// TODO(crbug.com/645104): Implement keyboard layout changing for other
@@ -1014,11 +1017,11 @@ TEST_F(TextfieldTest, MAYBE_KeysWithModifiersTest) {
SendKeyPress(ui::VKEY_OEM_MINUS, ctrl | shift);
if (TestingNativeCrOs())
- EXPECT_STR_EQ("TeTEx34", textfield_->GetText());
+ EXPECT_EQ(u"TeTEx34", textfield_->GetText());
else if (TestingNativeMac())
- EXPECT_STR_EQ("TheTxE134", textfield_->GetText());
+ EXPECT_EQ(u"TheTxE134", textfield_->GetText());
else
- EXPECT_STR_EQ("TeTEx234", textfield_->GetText());
+ EXPECT_EQ(u"TeTEx234", textfield_->GetText());
}
TEST_F(TextfieldTest, ControlAndSelectTest) {
@@ -1030,23 +1033,23 @@ TEST_F(TextfieldTest, ControlAndSelectTest) {
SendKeyEvent(ui::VKEY_RIGHT, true, false);
SendKeyEvent(ui::VKEY_RIGHT, true, false);
- EXPECT_STR_EQ("one", textfield_->GetSelectedText());
+ EXPECT_EQ(u"one", textfield_->GetSelectedText());
// Test word select.
SendWordEvent(ui::VKEY_RIGHT, true);
#if defined(OS_WIN) // Windows breaks on word starts and includes spaces.
- EXPECT_STR_EQ("one ", textfield_->GetSelectedText());
+ EXPECT_EQ(u"one ", textfield_->GetSelectedText());
SendWordEvent(ui::VKEY_RIGHT, true);
- EXPECT_STR_EQ("one two ", textfield_->GetSelectedText());
+ EXPECT_EQ(u"one two ", textfield_->GetSelectedText());
#else // Non-Windows breaks on word ends and does NOT include spaces.
- EXPECT_STR_EQ("one two", textfield_->GetSelectedText());
+ EXPECT_EQ(u"one two", textfield_->GetSelectedText());
#endif
SendWordEvent(ui::VKEY_RIGHT, true);
- EXPECT_STR_EQ("one two three", textfield_->GetSelectedText());
+ EXPECT_EQ(u"one two three", textfield_->GetSelectedText());
SendWordEvent(ui::VKEY_LEFT, true);
- EXPECT_STR_EQ("one two ", textfield_->GetSelectedText());
+ EXPECT_EQ(u"one two ", textfield_->GetSelectedText());
SendWordEvent(ui::VKEY_LEFT, true);
- EXPECT_STR_EQ("one ", textfield_->GetSelectedText());
+ EXPECT_EQ(u"one ", textfield_->GetSelectedText());
// Replace the selected text.
SendKeyEvent(ui::VKEY_Z, true, false);
@@ -1054,17 +1057,17 @@ TEST_F(TextfieldTest, ControlAndSelectTest) {
SendKeyEvent(ui::VKEY_R, true, false);
SendKeyEvent(ui::VKEY_O, true, false);
SendKeyEvent(ui::VKEY_SPACE, false, false);
- EXPECT_STR_EQ("ZERO two three", textfield_->GetText());
+ EXPECT_EQ(u"ZERO two three", textfield_->GetText());
SendEndEvent(true);
- EXPECT_STR_EQ("two three", textfield_->GetSelectedText());
+ EXPECT_EQ(u"two three", textfield_->GetSelectedText());
SendHomeEvent(true);
// On Mac, the existing selection should be extended.
-#if defined(OS_APPLE)
- EXPECT_STR_EQ("ZERO two three", textfield_->GetSelectedText());
+#if defined(OS_MAC)
+ EXPECT_EQ(u"ZERO two three", textfield_->GetSelectedText());
#else
- EXPECT_STR_EQ("ZERO ", textfield_->GetSelectedText());
+ EXPECT_EQ(u"ZERO ", textfield_->GetSelectedText());
#endif
}
@@ -1078,37 +1081,37 @@ TEST_F(TextfieldTest, WordSelection) {
// Select word towards right.
SendWordEvent(ui::VKEY_RIGHT, true);
#if defined(OS_WIN) // Select word right includes space/punctuation.
- EXPECT_STR_EQ("67 ", textfield_->GetSelectedText());
+ EXPECT_EQ(u"67 ", textfield_->GetSelectedText());
#else // Non-Win: select word right does NOT include space/punctuation.
- EXPECT_STR_EQ("67", textfield_->GetSelectedText());
+ EXPECT_EQ(u"67", textfield_->GetSelectedText());
#endif
SendWordEvent(ui::VKEY_RIGHT, true);
- EXPECT_STR_EQ("67 89", textfield_->GetSelectedText());
+ EXPECT_EQ(u"67 89", textfield_->GetSelectedText());
// Select word towards left.
SendWordEvent(ui::VKEY_LEFT, true);
- EXPECT_STR_EQ("67 ", textfield_->GetSelectedText());
+ EXPECT_EQ(u"67 ", textfield_->GetSelectedText());
SendWordEvent(ui::VKEY_LEFT, true);
// On Mac, the selection should reduce to a caret when the selection direction
// changes for a word selection.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
EXPECT_EQ(gfx::Range(6), textfield_->GetSelectedRange());
#else
- EXPECT_STR_EQ("345", textfield_->GetSelectedText());
+ EXPECT_EQ(u"345", textfield_->GetSelectedText());
EXPECT_EQ(gfx::Range(6, 3), textfield_->GetSelectedRange());
#endif
SendWordEvent(ui::VKEY_LEFT, true);
-#if defined(OS_APPLE)
- EXPECT_STR_EQ("345", textfield_->GetSelectedText());
+#if defined(OS_MAC)
+ EXPECT_EQ(u"345", textfield_->GetSelectedText());
#else
- EXPECT_STR_EQ("12 345", textfield_->GetSelectedText());
+ EXPECT_EQ(u"12 345", textfield_->GetSelectedText());
#endif
EXPECT_TRUE(textfield_->GetSelectedRange().is_reversed());
SendWordEvent(ui::VKEY_LEFT, true);
- EXPECT_STR_EQ("12 345", textfield_->GetSelectedText());
+ EXPECT_EQ(u"12 345", textfield_->GetSelectedText());
}
TEST_F(TextfieldTest, LineSelection) {
@@ -1120,24 +1123,24 @@ TEST_F(TextfieldTest, LineSelection) {
// Select line towards right.
SendEndEvent(true);
- EXPECT_STR_EQ("67 89", textfield_->GetSelectedText());
+ EXPECT_EQ(u"67 89", textfield_->GetSelectedText());
// Select line towards left. On Mac, the existing selection should be extended
// to cover the whole line.
SendHomeEvent(true);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
EXPECT_EQ(textfield_->GetText(), textfield_->GetSelectedText());
#else
- EXPECT_STR_EQ("12 345", textfield_->GetSelectedText());
+ EXPECT_EQ(u"12 345", textfield_->GetSelectedText());
#endif
EXPECT_TRUE(textfield_->GetSelectedRange().is_reversed());
// Select line towards right.
SendEndEvent(true);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
EXPECT_EQ(textfield_->GetText(), textfield_->GetSelectedText());
#else
- EXPECT_STR_EQ("67 89", textfield_->GetSelectedText());
+ EXPECT_EQ(u"67 89", textfield_->GetSelectedText());
#endif
EXPECT_FALSE(textfield_->GetSelectedRange().is_reversed());
}
@@ -1151,7 +1154,7 @@ TEST_F(TextfieldTest, MoveUpDownAndModifySelection) {
// commands.
SendKeyEvent(ui::VKEY_UP);
EXPECT_TRUE(textfield_->key_received());
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
EXPECT_TRUE(textfield_->key_handled());
EXPECT_EQ(gfx::Range(0), textfield_->GetSelectedRange());
#else
@@ -1161,7 +1164,7 @@ TEST_F(TextfieldTest, MoveUpDownAndModifySelection) {
SendKeyEvent(ui::VKEY_DOWN);
EXPECT_TRUE(textfield_->key_received());
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
EXPECT_TRUE(textfield_->key_handled());
EXPECT_EQ(gfx::Range(11), textfield_->GetSelectedRange());
#else
@@ -1191,7 +1194,7 @@ TEST_F(TextfieldTest, MovePageUpDownAndModifySelection) {
// MOVE_PAGE_[UP/DOWN] and the associated selection commands should only be
// enabled on Mac.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
textfield_->SetText(u"12 34567 89");
textfield_->SetEditableSelectionRange(gfx::Range(6));
@@ -1243,7 +1246,7 @@ TEST_F(TextfieldTest, MoveParagraphForwardBackwardAndModifySelection) {
ui::TextEditCommand::MOVE_PARAGRAPH_BACKWARD_AND_MODIFY_SELECTION);
// On Mac, the selection should reduce to a caret when the selection direction
// is reversed for MOVE_PARAGRAPH_[FORWARD/BACKWARD]_AND_MODIFY_SELECTION.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
EXPECT_EQ(gfx::Range(6), textfield_->GetSelectedRange());
#else
EXPECT_EQ(gfx::Range(6, 0), textfield_->GetSelectedRange());
@@ -1255,7 +1258,7 @@ TEST_F(TextfieldTest, MoveParagraphForwardBackwardAndModifySelection) {
test_api_->ExecuteTextEditCommand(
ui::TextEditCommand::MOVE_PARAGRAPH_FORWARD_AND_MODIFY_SELECTION);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
EXPECT_EQ(gfx::Range(6), textfield_->GetSelectedRange());
#else
EXPECT_EQ(gfx::Range(6, 11), textfield_->GetSelectedRange());
@@ -1280,28 +1283,28 @@ TEST_F(TextfieldTest, InsertionDeletionTest) {
InitTextfield();
for (size_t i = 0; i < 10; ++i)
SendKeyEvent(static_cast<ui::KeyboardCode>(ui::VKEY_A + i));
- EXPECT_STR_EQ("abcdefghij", textfield_->GetText());
+ EXPECT_EQ(u"abcdefghij", textfield_->GetText());
// Test the delete and backspace keys.
textfield_->SetSelectedRange(gfx::Range(5));
for (size_t i = 0; i < 3; ++i)
SendKeyEvent(ui::VKEY_BACK);
- EXPECT_STR_EQ("abfghij", textfield_->GetText());
+ EXPECT_EQ(u"abfghij", textfield_->GetText());
for (size_t i = 0; i < 3; ++i)
SendKeyEvent(ui::VKEY_DELETE);
- EXPECT_STR_EQ("abij", textfield_->GetText());
+ EXPECT_EQ(u"abij", textfield_->GetText());
// Select all and replace with "k".
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_K);
- EXPECT_STR_EQ("k", textfield_->GetText());
+ EXPECT_EQ(u"k", textfield_->GetText());
// Delete the previous word from cursor.
bool shift = false;
textfield_->SetText(u"one two three four");
SendEndEvent(shift);
SendWordEvent(ui::VKEY_BACK, shift);
- EXPECT_STR_EQ("one two three ", textfield_->GetText());
+ EXPECT_EQ(u"one two three ", textfield_->GetText());
// Delete to a line break on Linux and ChromeOS, to a word break on Windows
// and Mac.
@@ -1309,9 +1312,9 @@ TEST_F(TextfieldTest, InsertionDeletionTest) {
shift = true;
SendWordEvent(ui::VKEY_BACK, shift);
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
- EXPECT_STR_EQ("three ", textfield_->GetText());
+ EXPECT_EQ(u"three ", textfield_->GetText());
#else
- EXPECT_STR_EQ("one three ", textfield_->GetText());
+ EXPECT_EQ(u"one three ", textfield_->GetText());
#endif
// Delete the next word from cursor.
@@ -1320,9 +1323,9 @@ TEST_F(TextfieldTest, InsertionDeletionTest) {
SendHomeEvent(shift);
SendWordEvent(ui::VKEY_DELETE, shift);
#if defined(OS_WIN) // Delete word incldes space/punctuation.
- EXPECT_STR_EQ("two three four", textfield_->GetText());
+ EXPECT_EQ(u"two three four", textfield_->GetText());
#else // Non-Windows: delete word does NOT include space/punctuation.
- EXPECT_STR_EQ(" two three four", textfield_->GetText());
+ EXPECT_EQ(u" two three four", textfield_->GetText());
#endif
// Delete to a line break on Linux and ChromeOS, to a word break on Windows
// and Mac.
@@ -1330,11 +1333,11 @@ TEST_F(TextfieldTest, InsertionDeletionTest) {
shift = true;
SendWordEvent(ui::VKEY_DELETE, shift);
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
- EXPECT_STR_EQ(" two", textfield_->GetText());
+ EXPECT_EQ(u" two", textfield_->GetText());
#elif defined(OS_WIN)
- EXPECT_STR_EQ("two four", textfield_->GetText());
+ EXPECT_EQ(u"two four", textfield_->GetText());
#else
- EXPECT_STR_EQ(" two four", textfield_->GetText());
+ EXPECT_EQ(u" two four", textfield_->GetText());
#endif
}
@@ -1360,7 +1363,7 @@ TEST_F(TextfieldTest, DeletionWithSelection) {
// Make selection as - on|e tw|o three.
SendWordEvent(cases[i].key, cases[i].shift);
// Verify state is on|o three.
- EXPECT_STR_EQ("ono three", textfield_->GetText());
+ EXPECT_EQ(u"ono three", textfield_->GetText());
EXPECT_EQ(gfx::Range(2), textfield_->GetSelectedRange());
}
}
@@ -1388,7 +1391,7 @@ TEST_F(TextfieldTest, DeletionWithMultipleSelections) {
textfield_->AddSecondarySelectedRange(gfx::Range(10, 12));
textfield_->AddSecondarySelectedRange(gfx::Range(1, 3));
SendWordEvent(cases[i].key, cases[i].shift);
- EXPECT_STR_EQ("o the", textfield_->GetText());
+ EXPECT_EQ(u"o the", textfield_->GetText());
EXPECT_EQ(gfx::Range(2), textfield_->GetSelectedRange());
EXPECT_EQ(0U,
textfield_->GetSelectionModel().secondary_selections().size());
@@ -1399,12 +1402,12 @@ TEST_F(TextfieldTest, DeletionWithMultipleSelections) {
TEST_F(TextfieldTest, DeletionWithEditCommands) {
struct {
ui::TextEditCommand command;
- const char* expected;
+ const char16_t* expected;
} cases[] = {
- {ui::TextEditCommand::DELETE_TO_BEGINNING_OF_LINE, "two three"},
- {ui::TextEditCommand::DELETE_TO_BEGINNING_OF_PARAGRAPH, "two three"},
- {ui::TextEditCommand::DELETE_TO_END_OF_LINE, "one "},
- {ui::TextEditCommand::DELETE_TO_END_OF_PARAGRAPH, "one "},
+ {ui::TextEditCommand::DELETE_TO_BEGINNING_OF_LINE, u"two three"},
+ {ui::TextEditCommand::DELETE_TO_BEGINNING_OF_PARAGRAPH, u"two three"},
+ {ui::TextEditCommand::DELETE_TO_END_OF_LINE, u"one "},
+ {ui::TextEditCommand::DELETE_TO_END_OF_PARAGRAPH, u"one "},
};
InitTextfield();
@@ -1413,7 +1416,7 @@ TEST_F(TextfieldTest, DeletionWithEditCommands) {
textfield_->SetText(u"one two three");
textfield_->SetSelectedRange(gfx::Range(4));
test_api_->ExecuteTextEditCommand(cases[i].command);
- EXPECT_STR_EQ(cases[i].expected, textfield_->GetText());
+ EXPECT_EQ(cases[i].expected, textfield_->GetText());
}
}
@@ -1427,10 +1430,10 @@ TEST_F(TextfieldTest, PasswordTest) {
last_contents_.clear();
textfield_->SetText(u"password");
// Ensure GetText() and the callback returns the actual text instead of "*".
- EXPECT_STR_EQ("password", textfield_->GetText());
+ EXPECT_EQ(u"password", textfield_->GetText());
EXPECT_TRUE(last_contents_.empty());
model_->SelectAll(false);
- SetClipboardText(ui::ClipboardBuffer::kCopyPaste, "foo");
+ SetClipboardText(ui::ClipboardBuffer::kCopyPaste, u"foo");
// Cut and copy should be disabled.
EXPECT_FALSE(textfield_->IsCommandIdEnabled(Textfield::kCut));
@@ -1440,8 +1443,8 @@ TEST_F(TextfieldTest, PasswordTest) {
textfield_->ExecuteCommand(Textfield::kCopy, 0);
SendKeyEvent(ui::VKEY_C, false, true);
SendAlternateCopy();
- EXPECT_STR_EQ("foo", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
- EXPECT_STR_EQ("password", textfield_->GetText());
+ EXPECT_EQ(u"foo", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ EXPECT_EQ(u"password", textfield_->GetText());
// [Shift]+[Delete] should just delete without copying text to the clipboard.
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_DELETE, true, false);
@@ -1451,8 +1454,8 @@ TEST_F(TextfieldTest, PasswordTest) {
textfield_->ExecuteCommand(Textfield::kPaste, 0);
SendKeyEvent(ui::VKEY_V, false, true);
SendAlternatePaste();
- EXPECT_STR_EQ("foo", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
- EXPECT_STR_EQ("foofoofoo", textfield_->GetText());
+ EXPECT_EQ(u"foo", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ EXPECT_EQ(u"foofoofoo", textfield_->GetText());
}
// Check that text insertion works appropriately for password and read-only
@@ -1465,7 +1468,7 @@ TEST_F(TextfieldTest, TextInputType_InsertionTest) {
SendKeyEvent(ui::VKEY_A);
EXPECT_EQ(-1, textfield_->GetPasswordCharRevealIndex());
SendKeyEvent(kHebrewLetterSamekh, ui::EF_NONE, true /* from_vk */);
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// Don't verifies the password character reveal on MacOS, because on MacOS,
// the text insertion is not done through TextInputClient::InsertChar().
EXPECT_EQ(1, textfield_->GetPasswordCharRevealIndex());
@@ -1593,7 +1596,7 @@ TEST_F(TextfieldTest, OnKeyPressBinding) {
#endif
SendKeyEvent(ui::VKEY_A, false, false);
- EXPECT_STR_EQ("a", textfield_->GetText());
+ EXPECT_EQ(u"a", textfield_->GetText());
textfield_->clear();
// Undo/Redo command keys are handled by the textfield.
@@ -1606,7 +1609,7 @@ TEST_F(TextfieldTest, OnKeyPressBinding) {
SendKeyEvent(ui::VKEY_Z, true, true);
EXPECT_TRUE(textfield_->key_received());
EXPECT_TRUE(textfield_->key_handled());
- EXPECT_STR_EQ("a", textfield_->GetText());
+ EXPECT_EQ(u"a", textfield_->GetText());
textfield_->clear();
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
@@ -1629,34 +1632,34 @@ TEST_F(TextfieldTest, CursorMovement) {
const bool shift = false;
SendWordEvent(ui::VKEY_LEFT, shift);
SendKeyEvent(ui::VKEY_T);
- EXPECT_STR_EQ("one two thre ", textfield_->GetText());
- EXPECT_STR_EQ("one two thre ", last_contents_);
+ EXPECT_EQ(u"one two thre ", textfield_->GetText());
+ EXPECT_EQ(u"one two thre ", last_contents_);
#if defined(OS_WIN) // Move right by word includes space/punctuation.
// Ctrl+Right should move the cursor to the end of the last word.
SendWordEvent(ui::VKEY_RIGHT, shift);
SendKeyEvent(ui::VKEY_E);
- EXPECT_STR_EQ("one two thre e", textfield_->GetText());
- EXPECT_STR_EQ("one two thre e", last_contents_);
+ EXPECT_EQ(u"one two thre e", textfield_->GetText());
+ EXPECT_EQ(u"one two thre e", last_contents_);
// Ctrl+Right again should not move the cursor, because
// it is aleady at the end.
SendWordEvent(ui::VKEY_RIGHT, shift);
SendKeyEvent(ui::VKEY_BACK);
- EXPECT_STR_EQ("one two thre ", textfield_->GetText());
- EXPECT_STR_EQ("one two thre ", last_contents_);
+ EXPECT_EQ(u"one two thre ", textfield_->GetText());
+ EXPECT_EQ(u"one two thre ", last_contents_);
#else // Non-Windows: move right by word does NOT include space/punctuation.
// Ctrl+Right should move the cursor to the end of the last word.
SendWordEvent(ui::VKEY_RIGHT, shift);
SendKeyEvent(ui::VKEY_E);
- EXPECT_STR_EQ("one two three ", textfield_->GetText());
- EXPECT_STR_EQ("one two three ", last_contents_);
+ EXPECT_EQ(u"one two three ", textfield_->GetText());
+ EXPECT_EQ(u"one two three ", last_contents_);
// Ctrl+Right again should move the cursor to the end.
SendWordEvent(ui::VKEY_RIGHT, shift);
SendKeyEvent(ui::VKEY_BACK);
- EXPECT_STR_EQ("one two three", textfield_->GetText());
- EXPECT_STR_EQ("one two three", last_contents_);
+ EXPECT_EQ(u"one two three", textfield_->GetText());
+ EXPECT_EQ(u"one two three", last_contents_);
#endif
// Test with leading whitespace.
textfield_->SetText(u" ne two");
@@ -1672,16 +1675,16 @@ TEST_F(TextfieldTest, CursorMovement) {
#endif
SendWordEvent(ui::VKEY_LEFT, shift);
SendKeyEvent(ui::VKEY_O);
- EXPECT_STR_EQ(" one two", textfield_->GetText());
- EXPECT_STR_EQ(" one two", last_contents_);
+ EXPECT_EQ(u" one two", textfield_->GetText());
+ EXPECT_EQ(u" one two", last_contents_);
// Ctrl+Left to move the cursor to the beginning of the first word.
SendWordEvent(ui::VKEY_LEFT, shift);
// Ctrl+Left again should move the cursor back to the very beginning.
SendWordEvent(ui::VKEY_LEFT, shift);
SendKeyEvent(ui::VKEY_DELETE);
- EXPECT_STR_EQ("one two", textfield_->GetText());
- EXPECT_STR_EQ("one two", last_contents_);
+ EXPECT_EQ(u"one two", textfield_->GetText());
+ EXPECT_EQ(u"one two", last_contents_);
}
TEST_F(TextfieldTest, CursorMovementWithMultipleSelections) {
@@ -1794,7 +1797,7 @@ TEST_F(TextfieldTest, ContextMenuDisplayTest) {
VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
// Exercise the "paste enabled?" check in the verifier.
- SetClipboardText(ui::ClipboardBuffer::kCopyPaste, "Test");
+ SetClipboardText(ui::ClipboardBuffer::kCopyPaste, u"Test");
VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
}
@@ -1807,15 +1810,15 @@ TEST_F(TextfieldTest, DoubleAndTripleClickTest) {
ClickLeftMouseButton();
EXPECT_TRUE(textfield_->GetSelectedText().empty());
ClickLeftMouseButton();
- EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
+ EXPECT_EQ(u"hello", textfield_->GetSelectedText());
// Test for triple click.
ClickLeftMouseButton();
- EXPECT_STR_EQ("hello world", textfield_->GetSelectedText());
+ EXPECT_EQ(u"hello world", textfield_->GetSelectedText());
// Another click should reset back to double click.
ClickLeftMouseButton();
- EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
+ EXPECT_EQ(u"hello", textfield_->GetSelectedText());
}
// Tests text selection behavior on a right click.
@@ -1825,19 +1828,19 @@ TEST_F(TextfieldTest, SelectionOnRightClick) {
// Verify right clicking within the selection does not alter the selection.
textfield_->SetSelectedRange(gfx::Range(1, 5));
- EXPECT_STR_EQ("ello", textfield_->GetSelectedText());
+ EXPECT_EQ(u"ello", textfield_->GetSelectedText());
const int cursor_y = GetCursorYForTesting();
MoveMouseTo(gfx::Point(GetCursorPositionX(3), cursor_y));
ClickRightMouseButton();
- EXPECT_STR_EQ("ello", textfield_->GetSelectedText());
+ EXPECT_EQ(u"ello", textfield_->GetSelectedText());
// Verify right clicking outside the selection, selects the word under the
// cursor on platforms where this is expected.
MoveMouseTo(gfx::Point(GetCursorPositionX(8), cursor_y));
- const char* expected_right_click_word =
- PlatformStyle::kSelectWordOnRightClick ? "world" : "ello";
+ const char16_t* expected_right_click_word =
+ PlatformStyle::kSelectWordOnRightClick ? u"world" : u"ello";
ClickRightMouseButton();
- EXPECT_STR_EQ(expected_right_click_word, textfield_->GetSelectedText());
+ EXPECT_EQ(expected_right_click_word, textfield_->GetSelectedText());
// Verify right clicking inside an unfocused textfield selects all the text on
// platforms where this is expected. Else the older selection is retained.
@@ -1846,11 +1849,11 @@ TEST_F(TextfieldTest, SelectionOnRightClick) {
MoveMouseTo(gfx::Point(GetCursorPositionX(0), cursor_y));
ClickRightMouseButton();
EXPECT_TRUE(textfield_->HasFocus());
- const char* expected_right_click_unfocused =
+ const char16_t* expected_right_click_unfocused =
PlatformStyle::kSelectAllOnRightClickWhenUnfocused
- ? "hello world"
+ ? u"hello world"
: expected_right_click_word;
- EXPECT_STR_EQ(expected_right_click_unfocused, textfield_->GetSelectedText());
+ EXPECT_EQ(expected_right_click_unfocused, textfield_->GetSelectedText());
}
TEST_F(TextfieldTest, DragToSelect) {
@@ -1869,12 +1872,12 @@ TEST_F(TextfieldTest, DragToSelect) {
// Check that dragging left selects the beginning of the string.
DragMouseTo(gfx::Point(0, cursor_y));
std::u16string text_left = textfield_->GetSelectedText();
- EXPECT_STR_EQ("hello", text_left);
+ EXPECT_EQ(u"hello", text_left);
// Check that dragging right selects the rest of the string.
DragMouseTo(end_point);
std::u16string text_right = textfield_->GetSelectedText();
- EXPECT_STR_EQ(" world", text_right);
+ EXPECT_EQ(u" world", text_right);
// Check that releasing in the same location does not alter the selection.
ReleaseLeftMouseButton();
@@ -1893,10 +1896,10 @@ TEST_F(TextfieldTest, DragToSelect) {
TEST_F(TextfieldTest, DragUpOrDownSelectsToEnd) {
InitTextfield();
textfield_->SetText(u"hello world");
- const std::u16string expected_left = base::ASCIIToUTF16(
- gfx::RenderText::kDragToEndIfOutsideVerticalBounds ? "hello" : "lo");
- const std::u16string expected_right = base::ASCIIToUTF16(
- gfx::RenderText::kDragToEndIfOutsideVerticalBounds ? " world" : " w");
+ const std::u16string expected_left =
+ gfx::RenderText::kDragToEndIfOutsideVerticalBounds ? u"hello" : u"lo";
+ const std::u16string expected_right =
+ gfx::RenderText::kDragToEndIfOutsideVerticalBounds ? u" world" : u" w";
const int right_x = GetCursorPositionX(7);
const int left_x = GetCursorPositionX(3);
@@ -1954,7 +1957,7 @@ TEST_F(TextfieldTest, DragAndDrop_AcceptDrop) {
EXPECT_EQ(ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE,
textfield_->OnDragUpdated(drop));
EXPECT_EQ(ui::mojom::DragOperation::kCopy, textfield_->OnPerformDrop(drop));
- EXPECT_STR_EQ("hello string world", textfield_->GetText());
+ EXPECT_EQ(u"hello string world", textfield_->GetText());
// Ensure that textfields do not accept non-OSExchangeData::STRING types.
ui::OSExchangeData bad_data;
@@ -2047,22 +2050,22 @@ TEST_F(TextfieldTest, DragAndDrop_ToTheRight) {
ui::DropTargetEvent drop_a(data, kDropPoint, kDropPoint, operations);
EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop_a));
EXPECT_EQ(ui::mojom::DragOperation::kMove, textfield_->OnPerformDrop(drop_a));
- EXPECT_STR_EQ("h welloorld", textfield_->GetText());
+ EXPECT_EQ(u"h welloorld", textfield_->GetText());
textfield_->OnDragDone();
// Undo/Redo the drag&drop change.
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("hello world", textfield_->GetText());
+ EXPECT_EQ(u"hello world", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("", textfield_->GetText());
+ EXPECT_EQ(u"", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("", textfield_->GetText());
+ EXPECT_EQ(u"", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("hello world", textfield_->GetText());
+ EXPECT_EQ(u"hello world", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("h welloorld", textfield_->GetText());
+ EXPECT_EQ(u"h welloorld", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("h welloorld", textfield_->GetText());
+ EXPECT_EQ(u"h welloorld", textfield_->GetText());
}
TEST_F(TextfieldTest, DragAndDrop_ToTheLeft) {
@@ -2098,22 +2101,22 @@ TEST_F(TextfieldTest, DragAndDrop_ToTheLeft) {
ui::DropTargetEvent drop_a(data, drop_point, drop_point, operations);
EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop_a));
EXPECT_EQ(ui::mojom::DragOperation::kMove, textfield_->OnPerformDrop(drop_a));
- EXPECT_STR_EQ("h worlellod", textfield_->GetText());
+ EXPECT_EQ(u"h worlellod", textfield_->GetText());
textfield_->OnDragDone();
// Undo/Redo the drag&drop change.
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("hello world", textfield_->GetText());
+ EXPECT_EQ(u"hello world", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("", textfield_->GetText());
+ EXPECT_EQ(u"", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("", textfield_->GetText());
+ EXPECT_EQ(u"", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("hello world", textfield_->GetText());
+ EXPECT_EQ(u"hello world", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("h worlellod", textfield_->GetText());
+ EXPECT_EQ(u"h worlellod", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("h worlellod", textfield_->GetText());
+ EXPECT_EQ(u"h worlellod", textfield_->GetText());
}
TEST_F(TextfieldTest, DragAndDrop_Canceled) {
@@ -2161,52 +2164,52 @@ TEST_F(TextfieldTest, ReadOnlyTest) {
shift = true;
SendWordEvent(ui::VKEY_LEFT, shift);
EXPECT_EQ(0U, textfield_->GetCursorPosition());
- EXPECT_STR_EQ("read ", textfield_->GetSelectedText());
+ EXPECT_EQ(u"read ", textfield_->GetSelectedText());
textfield_->SelectAll(false);
- EXPECT_STR_EQ("read only", textfield_->GetSelectedText());
+ EXPECT_EQ(u"read only", textfield_->GetSelectedText());
// Cut should be disabled.
- SetClipboardText(ui::ClipboardBuffer::kCopyPaste, "Test");
+ SetClipboardText(ui::ClipboardBuffer::kCopyPaste, u"Test");
EXPECT_FALSE(textfield_->IsCommandIdEnabled(Textfield::kCut));
textfield_->ExecuteCommand(Textfield::kCut, 0);
SendKeyEvent(ui::VKEY_X, false, true);
SendAlternateCut();
- EXPECT_STR_EQ("Test", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
- EXPECT_STR_EQ("read only", textfield_->GetText());
+ EXPECT_EQ(u"Test", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ EXPECT_EQ(u"read only", textfield_->GetText());
// Paste should be disabled.
EXPECT_FALSE(textfield_->IsCommandIdEnabled(Textfield::kPaste));
textfield_->ExecuteCommand(Textfield::kPaste, 0);
SendKeyEvent(ui::VKEY_V, false, true);
SendAlternatePaste();
- EXPECT_STR_EQ("read only", textfield_->GetText());
+ EXPECT_EQ(u"read only", textfield_->GetText());
// Copy should work normally.
- SetClipboardText(ui::ClipboardBuffer::kCopyPaste, "Test");
+ SetClipboardText(ui::ClipboardBuffer::kCopyPaste, u"Test");
EXPECT_TRUE(textfield_->IsCommandIdEnabled(Textfield::kCopy));
textfield_->ExecuteCommand(Textfield::kCopy, 0);
- EXPECT_STR_EQ("read only", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
- SetClipboardText(ui::ClipboardBuffer::kCopyPaste, "Test");
+ EXPECT_EQ(u"read only", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ SetClipboardText(ui::ClipboardBuffer::kCopyPaste, u"Test");
SendKeyEvent(ui::VKEY_C, false, true);
- EXPECT_STR_EQ("read only", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
- SetClipboardText(ui::ClipboardBuffer::kCopyPaste, "Test");
+ EXPECT_EQ(u"read only", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ SetClipboardText(ui::ClipboardBuffer::kCopyPaste, u"Test");
SendAlternateCopy();
- EXPECT_STR_EQ("read only", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ EXPECT_EQ(u"read only", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
// SetText should work even in read only mode.
textfield_->SetText(u" four five six ");
- EXPECT_STR_EQ(" four five six ", textfield_->GetText());
+ EXPECT_EQ(u" four five six ", textfield_->GetText());
textfield_->SelectAll(false);
- EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
+ EXPECT_EQ(u" four five six ", textfield_->GetSelectedText());
// Text field is unmodifiable and selection shouldn't change.
SendKeyEvent(ui::VKEY_DELETE);
- EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
+ EXPECT_EQ(u" four five six ", textfield_->GetSelectedText());
SendKeyEvent(ui::VKEY_BACK);
- EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
+ EXPECT_EQ(u" four five six ", textfield_->GetSelectedText());
SendKeyEvent(ui::VKEY_T);
- EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
+ EXPECT_EQ(u" four five six ", textfield_->GetSelectedText());
}
TEST_F(TextfieldTest, TextInputClientTest) {
@@ -2227,10 +2230,10 @@ TEST_F(TextfieldTest, TextInputClientTest) {
std::u16string substring;
EXPECT_TRUE(client->GetTextFromRange(range, &substring));
- EXPECT_STR_EQ("123", substring);
+ EXPECT_EQ(u"123", substring);
EXPECT_TRUE(client->DeleteRange(range));
- EXPECT_STR_EQ("0456789", textfield_->GetText());
+ EXPECT_EQ(u"0456789", textfield_->GetText());
ui::CompositionText composition;
composition.text = u"321";
@@ -2246,7 +2249,7 @@ TEST_F(TextfieldTest, TextInputClientTest) {
EXPECT_FALSE(textfield_->key_handled());
EXPECT_TRUE(client->HasCompositionText());
EXPECT_TRUE(client->GetCompositionTextRange(&range));
- EXPECT_STR_EQ("0321456789", textfield_->GetText());
+ EXPECT_EQ(u"0321456789", textfield_->GetText());
EXPECT_EQ(gfx::Range(1, 4), range);
EXPECT_EQ(1, on_before_user_action_);
EXPECT_EQ(1, on_after_user_action_);
@@ -2259,7 +2262,7 @@ TEST_F(TextfieldTest, TextInputClientTest) {
EXPECT_FALSE(textfield_->key_handled());
EXPECT_FALSE(client->HasCompositionText());
EXPECT_FALSE(input_method_->cancel_composition_called());
- EXPECT_STR_EQ("0123456789", textfield_->GetText());
+ EXPECT_EQ(u"0123456789", textfield_->GetText());
EXPECT_EQ(1, on_before_user_action_);
EXPECT_EQ(1, on_after_user_action_);
@@ -2268,7 +2271,7 @@ TEST_F(TextfieldTest, TextInputClientTest) {
textfield_->clear();
DispatchMockInputMethodKeyEvent();
EXPECT_TRUE(client->HasCompositionText());
- EXPECT_STR_EQ("0123321456789", textfield_->GetText());
+ EXPECT_EQ(u"0123321456789", textfield_->GetText());
on_before_user_action_ = on_after_user_action_ = 0;
textfield_->clear();
@@ -2277,7 +2280,7 @@ TEST_F(TextfieldTest, TextInputClientTest) {
EXPECT_TRUE(input_method_->cancel_composition_called());
EXPECT_TRUE(textfield_->key_received());
EXPECT_TRUE(textfield_->key_handled());
- EXPECT_STR_EQ("0123321456789", textfield_->GetText());
+ EXPECT_EQ(u"0123321456789", textfield_->GetText());
EXPECT_EQ(8U, textfield_->GetCursorPosition());
EXPECT_EQ(1, on_before_user_action_);
EXPECT_EQ(1, on_after_user_action_);
@@ -2286,7 +2289,7 @@ TEST_F(TextfieldTest, TextInputClientTest) {
textfield_->SetText(u"0123456789");
EXPECT_TRUE(client->SetEditableSelectionRange(gfx::Range(5, 5)));
client->ExtendSelectionAndDelete(4, 2);
- EXPECT_STR_EQ("0789", textfield_->GetText());
+ EXPECT_EQ(u"0789", textfield_->GetText());
// On{Before,After}UserAction should be called by whatever user action
// triggers clearing or setting a selection if appropriate.
@@ -2321,123 +2324,123 @@ TEST_F(TextfieldTest, TextInputClientTest) {
TEST_F(TextfieldTest, UndoRedoTest) {
InitTextfield();
SendKeyEvent(ui::VKEY_A);
- EXPECT_STR_EQ("a", textfield_->GetText());
+ EXPECT_EQ(u"a", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("", textfield_->GetText());
+ EXPECT_EQ(u"", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("", textfield_->GetText());
+ EXPECT_EQ(u"", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("a", textfield_->GetText());
+ EXPECT_EQ(u"a", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("a", textfield_->GetText());
+ EXPECT_EQ(u"a", textfield_->GetText());
// AppendText
textfield_->AppendText(u"b");
last_contents_.clear(); // AppendText doesn't call ContentsChanged.
- EXPECT_STR_EQ("ab", textfield_->GetText());
+ EXPECT_EQ(u"ab", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("a", textfield_->GetText());
+ EXPECT_EQ(u"a", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("ab", textfield_->GetText());
+ EXPECT_EQ(u"ab", textfield_->GetText());
// SetText
SendKeyEvent(ui::VKEY_C);
// Undo'ing append moves the cursor to the end for now.
// A no-op SetText won't add a new edit; see TextfieldModel::SetText.
- EXPECT_STR_EQ("abc", textfield_->GetText());
+ EXPECT_EQ(u"abc", textfield_->GetText());
textfield_->SetText(u"abc");
- EXPECT_STR_EQ("abc", textfield_->GetText());
+ EXPECT_EQ(u"abc", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("ab", textfield_->GetText());
+ EXPECT_EQ(u"ab", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("abc", textfield_->GetText());
+ EXPECT_EQ(u"abc", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("abc", textfield_->GetText());
+ EXPECT_EQ(u"abc", textfield_->GetText());
textfield_->SetText(u"123");
textfield_->SetText(u"123");
- EXPECT_STR_EQ("123", textfield_->GetText());
+ EXPECT_EQ(u"123", textfield_->GetText());
SendKeyEvent(ui::VKEY_END, false, false);
SendKeyEvent(ui::VKEY_4, false, false);
- EXPECT_STR_EQ("1234", textfield_->GetText());
+ EXPECT_EQ(u"1234", textfield_->GetText());
last_contents_.clear();
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("123", textfield_->GetText());
+ EXPECT_EQ(u"123", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
// the insert edit "c" and set edit "123" are merged to single edit,
// so text becomes "ab" after undo.
- EXPECT_STR_EQ("ab", textfield_->GetText());
+ EXPECT_EQ(u"ab", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("a", textfield_->GetText());
+ EXPECT_EQ(u"a", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("ab", textfield_->GetText());
+ EXPECT_EQ(u"ab", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("123", textfield_->GetText());
+ EXPECT_EQ(u"123", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("1234", textfield_->GetText());
+ EXPECT_EQ(u"1234", textfield_->GetText());
// Undoing to the same text shouldn't call ContentsChanged.
SendKeyEvent(ui::VKEY_A, false, true); // select all
SendKeyEvent(ui::VKEY_A);
- EXPECT_STR_EQ("a", textfield_->GetText());
+ EXPECT_EQ(u"a", textfield_->GetText());
SendKeyEvent(ui::VKEY_B);
SendKeyEvent(ui::VKEY_C);
- EXPECT_STR_EQ("abc", textfield_->GetText());
+ EXPECT_EQ(u"abc", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("1234", textfield_->GetText());
+ EXPECT_EQ(u"1234", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("abc", textfield_->GetText());
+ EXPECT_EQ(u"abc", textfield_->GetText());
// Delete/Backspace
SendKeyEvent(ui::VKEY_BACK);
- EXPECT_STR_EQ("ab", textfield_->GetText());
+ EXPECT_EQ(u"ab", textfield_->GetText());
SendHomeEvent(false);
SendKeyEvent(ui::VKEY_DELETE);
- EXPECT_STR_EQ("b", textfield_->GetText());
+ EXPECT_EQ(u"b", textfield_->GetText());
SendKeyEvent(ui::VKEY_A, false, true);
SendKeyEvent(ui::VKEY_DELETE);
- EXPECT_STR_EQ("", textfield_->GetText());
+ EXPECT_EQ(u"", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("b", textfield_->GetText());
+ EXPECT_EQ(u"b", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("ab", textfield_->GetText());
+ EXPECT_EQ(u"ab", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("abc", textfield_->GetText());
+ EXPECT_EQ(u"abc", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("ab", textfield_->GetText());
+ EXPECT_EQ(u"ab", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("b", textfield_->GetText());
+ EXPECT_EQ(u"b", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("", textfield_->GetText());
+ EXPECT_EQ(u"", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("", textfield_->GetText());
+ EXPECT_EQ(u"", textfield_->GetText());
}
// Most platforms support Ctrl+Y as an alternative to Ctrl+Shift+Z, but on Mac
// Ctrl+Y is bound to "Yank" and Cmd+Y is bound to "Show full history". So, on
// Mac, Cmd+Shift+Z is sent for the tests above and the Ctrl+Y test below is
// skipped.
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// Test that Ctrl+Y works for Redo, as well as Ctrl+Shift+Z.
TEST_F(TextfieldTest, RedoWithCtrlY) {
InitTextfield();
SendKeyEvent(ui::VKEY_A);
- EXPECT_STR_EQ("a", textfield_->GetText());
+ EXPECT_EQ(u"a", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("", textfield_->GetText());
+ EXPECT_EQ(u"", textfield_->GetText());
SendKeyEvent(ui::VKEY_Y, false, true);
- EXPECT_STR_EQ("a", textfield_->GetText());
+ EXPECT_EQ(u"a", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, false, true);
- EXPECT_STR_EQ("", textfield_->GetText());
+ EXPECT_EQ(u"", textfield_->GetText());
SendKeyEvent(ui::VKEY_Z, true, true);
- EXPECT_STR_EQ("a", textfield_->GetText());
+ EXPECT_EQ(u"a", textfield_->GetText());
}
-#endif // !defined(OS_APPLE)
+#endif // !defined(OS_MAC)
// Non-Mac platforms don't have a key binding for Yank. Since this test is only
// run on Mac, it uses some Mac specific key bindings.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
TEST_F(TextfieldTest, Yank) {
InitTextfield(2);
@@ -2449,26 +2452,26 @@ TEST_F(TextfieldTest, Yank) {
// Initially the kill buffer should be empty. Hence yanking should delete the
// selected text.
- EXPECT_STR_EQ("abef", textfield_->GetText());
+ EXPECT_EQ(u"abef", textfield_->GetText());
EXPECT_EQ(gfx::Range(2), textfield_->GetSelectedRange());
// Press Ctrl+K to delete to end of paragraph. This should place the deleted
// text in the kill buffer.
SendKeyPress(ui::VKEY_K, ui::EF_CONTROL_DOWN);
- EXPECT_STR_EQ("ab", textfield_->GetText());
+ EXPECT_EQ(u"ab", textfield_->GetText());
EXPECT_EQ(gfx::Range(2), textfield_->GetSelectedRange());
// Yank twice.
SendKeyPress(ui::VKEY_Y, ui::EF_CONTROL_DOWN);
SendKeyPress(ui::VKEY_Y, ui::EF_CONTROL_DOWN);
- EXPECT_STR_EQ("abefef", textfield_->GetText());
+ EXPECT_EQ(u"abefef", textfield_->GetText());
EXPECT_EQ(gfx::Range(6), textfield_->GetSelectedRange());
// Verify pressing backspace does not modify the kill buffer.
SendKeyEvent(ui::VKEY_BACK);
SendKeyPress(ui::VKEY_Y, ui::EF_CONTROL_DOWN);
- EXPECT_STR_EQ("abefeef", textfield_->GetText());
+ EXPECT_EQ(u"abefeef", textfield_->GetText());
EXPECT_EQ(gfx::Range(7), textfield_->GetSelectedRange());
// Move focus to next textfield.
@@ -2481,7 +2484,7 @@ TEST_F(TextfieldTest, Yank) {
// into a password textfield works.
textfield2->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
SendKeyPress(ui::VKEY_Y, ui::EF_CONTROL_DOWN);
- EXPECT_STR_EQ("ef", textfield2->GetText());
+ EXPECT_EQ(u"ef", textfield2->GetText());
EXPECT_EQ(gfx::Range(2), textfield2->GetSelectedRange());
// Verify deletion in a password textfield does not modify the kill buffer.
@@ -2493,10 +2496,10 @@ TEST_F(TextfieldTest, Yank) {
textfield_->RequestFocus();
textfield_->SetSelectedRange(gfx::Range(0));
SendKeyPress(ui::VKEY_Y, ui::EF_CONTROL_DOWN);
- EXPECT_STR_EQ("efabefeef", textfield_->GetText());
+ EXPECT_EQ(u"efabefeef", textfield_->GetText());
}
-#endif // defined(OS_APPLE)
+#endif // defined(OS_MAC)
TEST_F(TextfieldTest, CutCopyPaste) {
InitTextfield();
@@ -2505,39 +2508,39 @@ TEST_F(TextfieldTest, CutCopyPaste) {
textfield_->SelectAll(false);
EXPECT_TRUE(textfield_->IsCommandIdEnabled(Textfield::kCut));
textfield_->ExecuteCommand(Textfield::kCut, 0);
- EXPECT_STR_EQ("123", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
- EXPECT_STR_EQ("", textfield_->GetText());
+ EXPECT_EQ(u"123", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ EXPECT_EQ(u"", textfield_->GetText());
EXPECT_EQ(ui::ClipboardBuffer::kCopyPaste, GetAndResetCopiedToClipboard());
// Ensure [Ctrl]+[x] cuts and [Ctrl]+[Alt][x] does nothing.
textfield_->SetText(u"456");
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_X, true, false, true, false);
- EXPECT_STR_EQ("123", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
- EXPECT_STR_EQ("456", textfield_->GetText());
+ EXPECT_EQ(u"123", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ EXPECT_EQ(u"456", textfield_->GetText());
EXPECT_EQ(ui::ClipboardBuffer::kMaxValue, GetAndResetCopiedToClipboard());
SendKeyEvent(ui::VKEY_X, false, true);
- EXPECT_STR_EQ("456", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
- EXPECT_STR_EQ("", textfield_->GetText());
+ EXPECT_EQ(u"456", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ EXPECT_EQ(u"", textfield_->GetText());
EXPECT_EQ(ui::ClipboardBuffer::kCopyPaste, GetAndResetCopiedToClipboard());
// Ensure [Shift]+[Delete] cuts.
textfield_->SetText(u"123");
textfield_->SelectAll(false);
SendAlternateCut();
- EXPECT_STR_EQ("123", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
- EXPECT_STR_EQ("", textfield_->GetText());
+ EXPECT_EQ(u"123", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ EXPECT_EQ(u"", textfield_->GetText());
EXPECT_EQ(ui::ClipboardBuffer::kCopyPaste, GetAndResetCopiedToClipboard());
// Reset clipboard text.
- SetClipboardText(ui::ClipboardBuffer::kCopyPaste, "");
+ SetClipboardText(ui::ClipboardBuffer::kCopyPaste, u"");
// Ensure [Shift]+[Delete] is a no-op in case there is no selection.
textfield_->SetText(u"123");
textfield_->SetSelectedRange(gfx::Range(0));
SendAlternateCut();
- EXPECT_STR_EQ("", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
- EXPECT_STR_EQ("123", textfield_->GetText());
+ EXPECT_EQ(u"", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ EXPECT_EQ(u"123", textfield_->GetText());
EXPECT_EQ(ui::ClipboardBuffer::kMaxValue, GetAndResetCopiedToClipboard());
// Ensure kCopy copies.
@@ -2545,46 +2548,46 @@ TEST_F(TextfieldTest, CutCopyPaste) {
textfield_->SelectAll(false);
EXPECT_TRUE(textfield_->IsCommandIdEnabled(Textfield::kCopy));
textfield_->ExecuteCommand(Textfield::kCopy, 0);
- EXPECT_STR_EQ("789", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ EXPECT_EQ(u"789", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
EXPECT_EQ(ui::ClipboardBuffer::kCopyPaste, GetAndResetCopiedToClipboard());
// Ensure [Ctrl]+[c] copies and [Ctrl]+[Alt][c] does nothing.
textfield_->SetText(u"012");
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_C, true, false, true, false);
- EXPECT_STR_EQ("789", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ EXPECT_EQ(u"789", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
EXPECT_EQ(ui::ClipboardBuffer::kMaxValue, GetAndResetCopiedToClipboard());
SendKeyEvent(ui::VKEY_C, false, true);
- EXPECT_STR_EQ("012", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ EXPECT_EQ(u"012", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
EXPECT_EQ(ui::ClipboardBuffer::kCopyPaste, GetAndResetCopiedToClipboard());
// Ensure [Ctrl]+[Insert] copies.
textfield_->SetText(u"345");
textfield_->SelectAll(false);
SendAlternateCopy();
- EXPECT_STR_EQ("345", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
- EXPECT_STR_EQ("345", textfield_->GetText());
+ EXPECT_EQ(u"345", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ EXPECT_EQ(u"345", textfield_->GetText());
EXPECT_EQ(ui::ClipboardBuffer::kCopyPaste, GetAndResetCopiedToClipboard());
// Ensure kPaste, [Ctrl]+[V], and [Shift]+[Insert] pastes;
// also ensure that [Ctrl]+[Alt]+[V] does nothing.
- SetClipboardText(ui::ClipboardBuffer::kCopyPaste, "abc");
+ SetClipboardText(ui::ClipboardBuffer::kCopyPaste, u"abc");
textfield_->SetText(std::u16string());
EXPECT_TRUE(textfield_->IsCommandIdEnabled(Textfield::kPaste));
textfield_->ExecuteCommand(Textfield::kPaste, 0);
- EXPECT_STR_EQ("abc", textfield_->GetText());
+ EXPECT_EQ(u"abc", textfield_->GetText());
SendKeyEvent(ui::VKEY_V, false, true);
- EXPECT_STR_EQ("abcabc", textfield_->GetText());
+ EXPECT_EQ(u"abcabc", textfield_->GetText());
SendAlternatePaste();
- EXPECT_STR_EQ("abcabcabc", textfield_->GetText());
+ EXPECT_EQ(u"abcabcabc", textfield_->GetText());
SendKeyEvent(ui::VKEY_V, true, false, true, false);
- EXPECT_STR_EQ("abcabcabc", textfield_->GetText());
+ EXPECT_EQ(u"abcabcabc", textfield_->GetText());
// Ensure [Ctrl]+[Shift]+[Insert] is a no-op.
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_INSERT, true, true);
- EXPECT_STR_EQ("abc", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
- EXPECT_STR_EQ("abcabcabc", textfield_->GetText());
+ EXPECT_EQ(u"abc", GetClipboardText(ui::ClipboardBuffer::kCopyPaste));
+ EXPECT_EQ(u"abcabcabc", textfield_->GetText());
EXPECT_EQ(ui::ClipboardBuffer::kMaxValue, GetAndResetCopiedToClipboard());
}
@@ -2601,14 +2604,14 @@ TEST_F(TextfieldTest, CutCopyPasteWithEditCommand) {
SendKeyEvent(ui::VKEY_A, false, true); // Select it.
SendKeyEvent(ui::VKEY_C, false, true); // Copy it.
SendKeyEvent(ui::VKEY_RIGHT, false, false); // Deselect and navigate to end.
- EXPECT_STR_EQ("o", textfield_->GetText());
+ EXPECT_EQ(u"o", textfield_->GetText());
SendKeyEvent(ui::VKEY_V, false, true); // Paste it.
- EXPECT_STR_EQ("oo", textfield_->GetText());
+ EXPECT_EQ(u"oo", textfield_->GetText());
SendKeyEvent(ui::VKEY_H, false, false); // Type "h".
- EXPECT_STR_EQ("ooh", textfield_->GetText());
+ EXPECT_EQ(u"ooh", textfield_->GetText());
SendKeyEvent(ui::VKEY_LEFT, true, false); // Select "h".
SendKeyEvent(ui::VKEY_X, false, true); // Cut it.
- EXPECT_STR_EQ("oo", textfield_->GetText());
+ EXPECT_EQ(u"oo", textfield_->GetText());
}
TEST_F(TextfieldTest, OvertypeMode) {
@@ -2622,19 +2625,19 @@ TEST_F(TextfieldTest, OvertypeMode) {
// However, there's no enable-overtype equivalent key combination on OSX.
SendKeyEvent(ui::VKEY_INSERT);
SendKeyEvent(ui::VKEY_1, false, false);
- EXPECT_STR_EQ("12", textfield_->GetText());
+ EXPECT_EQ(u"12", textfield_->GetText());
}
TEST_F(TextfieldTest, TextCursorDisplayTest) {
InitTextfield();
// LTR-RTL string in LTR context.
SendKeyEvent('a');
- EXPECT_STR_EQ("a", textfield_->GetText());
+ EXPECT_EQ(u"a", textfield_->GetText());
int x = GetCursorBounds().x();
int prev_x = x;
SendKeyEvent('b');
- EXPECT_STR_EQ("ab", textfield_->GetText());
+ EXPECT_EQ(u"ab", textfield_->GetText());
x = GetCursorBounds().x();
EXPECT_LT(prev_x, x);
prev_x = x;
@@ -2690,13 +2693,13 @@ TEST_F(TextfieldTest, TextCursorDisplayInRTLTest) {
InitTextfield();
// LTR-RTL string in RTL context.
SendKeyEvent('a');
- EXPECT_STR_EQ("a", textfield_->GetText());
+ EXPECT_EQ(u"a", textfield_->GetText());
int x = GetCursorBounds().x();
EXPECT_EQ(GetDisplayRect().right() - 1, x);
int prev_x = x;
SendKeyEvent('b');
- EXPECT_STR_EQ("ab", textfield_->GetText());
+ EXPECT_EQ(u"ab", textfield_->GetText());
x = GetCursorBounds().x();
EXPECT_GE(1, std::abs(x - prev_x));
@@ -2757,7 +2760,7 @@ TEST_F(TextfieldTest, TextCursorPositionInRTLTest) {
int text_cursor_position_prev = test_api_->GetCursorViewRect().x();
SendKeyEvent('a');
SendKeyEvent('b');
- EXPECT_STR_EQ("ab", textfield_->GetText());
+ EXPECT_EQ(u"ab", textfield_->GetText());
int text_cursor_position_new = test_api_->GetCursorViewRect().x();
// Text cursor stays at same place after inserting new charactors in RTL mode.
EXPECT_EQ(text_cursor_position_prev, text_cursor_position_new);
@@ -2773,7 +2776,7 @@ TEST_F(TextfieldTest, TextCursorPositionInLTRTest) {
int text_cursor_position_prev = test_api_->GetCursorViewRect().x();
SendKeyEvent('a');
SendKeyEvent('b');
- EXPECT_STR_EQ("ab", textfield_->GetText());
+ EXPECT_EQ(u"ab", textfield_->GetText());
int text_cursor_position_new = test_api_->GetCursorViewRect().x();
// Text cursor moves to right after inserting new charactors in LTR mode.
EXPECT_LT(text_cursor_position_prev, text_cursor_position_new);
@@ -3192,12 +3195,12 @@ TEST_F(TextfieldTest, SelectionClipboard) {
ui::EF_LEFT_MOUSE_BUTTON);
textfield_->OnMouseReleased(release);
EXPECT_EQ(gfx::Range(1, 3), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("12", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"12", GetClipboardText(ui::ClipboardBuffer::kSelection));
// Select-all should update the selection clipboard.
SendKeyEvent(ui::VKEY_A, false, true);
EXPECT_EQ(gfx::Range(0, 4), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("0123", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"0123", GetClipboardText(ui::ClipboardBuffer::kSelection));
EXPECT_EQ(ui::ClipboardBuffer::kSelection, GetAndResetCopiedToClipboard());
// Shift-click selection modifications should update the clipboard.
@@ -3212,24 +3215,24 @@ TEST_F(TextfieldTest, SelectionClipboard) {
ui::EF_LEFT_MOUSE_BUTTON);
textfield_->OnMouseReleased(release_2);
EXPECT_EQ(gfx::Range(0, 2), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("01", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"01", GetClipboardText(ui::ClipboardBuffer::kSelection));
EXPECT_EQ(ui::ClipboardBuffer::kSelection, GetAndResetCopiedToClipboard());
// Shift-Left/Right should update the selection clipboard.
SendKeyEvent(ui::VKEY_RIGHT, true, false);
- EXPECT_STR_EQ("012", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"012", GetClipboardText(ui::ClipboardBuffer::kSelection));
EXPECT_EQ(ui::ClipboardBuffer::kSelection, GetAndResetCopiedToClipboard());
SendKeyEvent(ui::VKEY_LEFT, true, false);
- EXPECT_STR_EQ("01", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"01", GetClipboardText(ui::ClipboardBuffer::kSelection));
EXPECT_EQ(ui::ClipboardBuffer::kSelection, GetAndResetCopiedToClipboard());
SendKeyEvent(ui::VKEY_RIGHT, true, true);
- EXPECT_STR_EQ("0123", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"0123", GetClipboardText(ui::ClipboardBuffer::kSelection));
EXPECT_EQ(ui::ClipboardBuffer::kSelection, GetAndResetCopiedToClipboard());
// Moving the cursor without a selection should not change the clipboard.
SendKeyEvent(ui::VKEY_LEFT, false, false);
EXPECT_EQ(gfx::Range(0, 0), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("0123", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"0123", GetClipboardText(ui::ClipboardBuffer::kSelection));
EXPECT_EQ(ui::ClipboardBuffer::kMaxValue, GetAndResetCopiedToClipboard());
// Middle clicking should paste at the mouse (not cursor) location.
@@ -3238,38 +3241,38 @@ TEST_F(TextfieldTest, SelectionClipboard) {
ui::EventTimeForNow(), ui::EF_MIDDLE_MOUSE_BUTTON,
ui::EF_MIDDLE_MOUSE_BUTTON);
textfield_->OnMousePressed(middle);
- EXPECT_STR_EQ("01230123", textfield_->GetText());
+ EXPECT_EQ(u"01230123", textfield_->GetText());
EXPECT_EQ(gfx::Range(8, 8), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("0123", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"0123", GetClipboardText(ui::ClipboardBuffer::kSelection));
// Middle clicking on an unfocused textfield should focus it and paste.
textfield_->GetFocusManager()->ClearFocus();
EXPECT_FALSE(textfield_->HasFocus());
textfield_->OnMousePressed(middle);
EXPECT_TRUE(textfield_->HasFocus());
- EXPECT_STR_EQ("012301230123", textfield_->GetText());
+ EXPECT_EQ(u"012301230123", textfield_->GetText());
EXPECT_EQ(gfx::Range(8, 8), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("0123", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"0123", GetClipboardText(ui::ClipboardBuffer::kSelection));
// Middle clicking with an empty selection clipboard should still focus.
- SetClipboardText(ui::ClipboardBuffer::kSelection, std::string());
+ SetClipboardText(ui::ClipboardBuffer::kSelection, std::u16string());
textfield_->GetFocusManager()->ClearFocus();
EXPECT_FALSE(textfield_->HasFocus());
textfield_->OnMousePressed(middle);
EXPECT_TRUE(textfield_->HasFocus());
- EXPECT_STR_EQ("012301230123", textfield_->GetText());
+ EXPECT_EQ(u"012301230123", textfield_->GetText());
EXPECT_EQ(gfx::Range(4, 4), textfield_->GetSelectedRange());
EXPECT_TRUE(GetClipboardText(ui::ClipboardBuffer::kSelection).empty());
// Middle clicking in the selection should insert the selection clipboard
// contents into the middle of the selection, and move the cursor to the end
// of the pasted content.
- SetClipboardText(ui::ClipboardBuffer::kCopyPaste, "foo");
+ SetClipboardText(ui::ClipboardBuffer::kCopyPaste, u"foo");
textfield_->SetSelectedRange(gfx::Range(2, 6));
textfield_->OnMousePressed(middle);
- EXPECT_STR_EQ("0123foo01230123", textfield_->GetText());
+ EXPECT_EQ(u"0123foo01230123", textfield_->GetText());
EXPECT_EQ(gfx::Range(7, 7), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("foo", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"foo", GetClipboardText(ui::ClipboardBuffer::kSelection));
// Double and triple clicking should update the clipboard contents.
textfield_->SetText(u"ab cd ef");
@@ -3289,24 +3292,24 @@ TEST_F(TextfieldTest, SelectionClipboard) {
textfield_->OnMousePressed(double_click);
textfield_->OnMouseReleased(release_word);
EXPECT_EQ(gfx::Range(3, 5), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("cd", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"cd", GetClipboardText(ui::ClipboardBuffer::kSelection));
EXPECT_EQ(ui::ClipboardBuffer::kSelection, GetAndResetCopiedToClipboard());
textfield_->OnMousePressed(press_word);
textfield_->OnMouseReleased(release_word);
EXPECT_EQ(gfx::Range(0, 8), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"ab cd ef", GetClipboardText(ui::ClipboardBuffer::kSelection));
EXPECT_EQ(ui::ClipboardBuffer::kSelection, GetAndResetCopiedToClipboard());
// Selecting a range of text without any user interaction should not change
// the clipboard content.
textfield_->SetSelectedRange(gfx::Range(0, 3));
- EXPECT_STR_EQ("ab ", textfield_->GetSelectedText());
- EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"ab ", textfield_->GetSelectedText());
+ EXPECT_EQ(u"ab cd ef", GetClipboardText(ui::ClipboardBuffer::kSelection));
EXPECT_EQ(ui::ClipboardBuffer::kMaxValue, GetAndResetCopiedToClipboard());
- SetClipboardText(ui::ClipboardBuffer::kSelection, "other");
+ SetClipboardText(ui::ClipboardBuffer::kSelection, u"other");
textfield_->SelectAll(false);
- EXPECT_STR_EQ("other", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"other", GetClipboardText(ui::ClipboardBuffer::kSelection));
EXPECT_EQ(ui::ClipboardBuffer::kMaxValue, GetAndResetCopiedToClipboard());
}
@@ -3320,7 +3323,7 @@ TEST_F(TextfieldTest, SelectionClipboard_Password) {
// textfield.
SendKeyEvent(ui::VKEY_A, false, true);
EXPECT_EQ(gfx::Range(0, 4), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("abcd", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"abcd", GetClipboardText(ui::ClipboardBuffer::kSelection));
EXPECT_EQ(ui::ClipboardBuffer::kSelection, GetAndResetCopiedToClipboard());
// Move focus to the next textfield.
@@ -3334,19 +3337,19 @@ TEST_F(TextfieldTest, SelectionClipboard_Password) {
textfield2->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
SendKeyEvent(ui::VKEY_A, false, true);
EXPECT_EQ(gfx::Range(0, 4), textfield2->GetSelectedRange());
- EXPECT_STR_EQ("abcd", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"abcd", GetClipboardText(ui::ClipboardBuffer::kSelection));
EXPECT_EQ(ui::ClipboardBuffer::kMaxValue, GetAndResetCopiedToClipboard());
// Shift-Left/Right should not modify the selection clipboard for a password
// textfield.
SendKeyEvent(ui::VKEY_LEFT, true, false);
EXPECT_EQ(gfx::Range(0, 3), textfield2->GetSelectedRange());
- EXPECT_STR_EQ("abcd", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"abcd", GetClipboardText(ui::ClipboardBuffer::kSelection));
EXPECT_EQ(ui::ClipboardBuffer::kMaxValue, GetAndResetCopiedToClipboard());
SendKeyEvent(ui::VKEY_RIGHT, true, false);
EXPECT_EQ(gfx::Range(0, 4), textfield2->GetSelectedRange());
- EXPECT_STR_EQ("abcd", GetClipboardText(ui::ClipboardBuffer::kSelection));
+ EXPECT_EQ(u"abcd", GetClipboardText(ui::ClipboardBuffer::kSelection));
EXPECT_EQ(ui::ClipboardBuffer::kMaxValue, GetAndResetCopiedToClipboard());
}
#endif
@@ -3380,7 +3383,7 @@ TEST_F(TextfieldTest, GetTextfieldBaseline_FontFallbackTest) {
// Set text which may fall back to a font which has taller baseline than
// the default font.
- textfield_->SetText(UTF8ToUTF16("\xE0\xB9\x91"));
+ textfield_->SetText(u"๑");
const int new_baseline = textfield_->GetBaseline();
// Regardless of the text, the baseline must be the same.
@@ -3425,7 +3428,7 @@ TEST_F(TextfieldTest, SetAccessibleNameNotifiesAccessibilityEvent) {
textfield_->GetAccessibleNodeData(&data);
const std::string& name =
data.GetStringAttribute(ax::mojom::StringAttribute::kName);
- EXPECT_EQ(test_tooltip_text, ASCIIToUTF16(name));
+ EXPECT_EQ(test_tooltip_text, base::ASCIIToUTF16(name));
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -3517,7 +3520,7 @@ TEST_F(TextfieldTouchSelectionTest, TouchSelectionAndDraggingTest) {
GestureEventForTest long_press_1(
x, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
textfield_->OnGestureEvent(&long_press_1);
- EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
+ EXPECT_EQ(u"hello", textfield_->GetSelectedText());
EXPECT_TRUE(test_api_->touch_selection_controller());
EXPECT_TRUE(long_press_1.handled());
@@ -3527,7 +3530,7 @@ TEST_F(TextfieldTouchSelectionTest, TouchSelectionAndDraggingTest) {
GestureEventForTest long_press_2(
x, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
textfield_->OnGestureEvent(&long_press_2);
- EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
+ EXPECT_EQ(u"hello", textfield_->GetSelectedText());
EXPECT_FALSE(test_api_->touch_selection_controller());
EXPECT_FALSE(long_press_2.handled());
@@ -3539,7 +3542,7 @@ TEST_F(TextfieldTouchSelectionTest, TouchSelectionAndDraggingTest) {
GestureEventForTest long_press_3(
x, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
textfield_->OnGestureEvent(&long_press_3);
- EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
+ EXPECT_EQ(u"hello", textfield_->GetSelectedText());
EXPECT_FALSE(test_api_->touch_selection_controller());
EXPECT_FALSE(long_press_3.handled());
}
@@ -3567,7 +3570,7 @@ TEST_F(TextfieldTouchSelectionTest, TouchSelectionInUnfocusableTextfield) {
}
// No touch on desktop Mac. Tracked in http://crbug.com/445520.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#define MAYBE_TapOnSelection DISABLED_TapOnSelection
#else
#define MAYBE_TapOnSelection TapOnSelection
@@ -3767,34 +3770,6 @@ TEST_F(TextfieldTest, SwitchFocusInKeyDown) {
EXPECT_EQ(u" ", textfield_->GetText());
}
-TEST_F(TextfieldTest, FocusChangesScrollToStart) {
- const std::string& kText = "abcdef";
- InitTextfield();
- textfield_->SetText(ASCIIToUTF16(kText));
- EXPECT_EQ(base::ASCIIToUTF16(std::string()), textfield_->GetSelectedText());
- textfield_->AboutToRequestFocusFromTabTraversal(false);
- EXPECT_EQ(base::ASCIIToUTF16(kText), textfield_->GetSelectedText());
- if (PlatformStyle::kTextfieldScrollsToStartOnFocusChange)
- EXPECT_EQ(0U, textfield_->GetCursorPosition());
- else
- EXPECT_EQ(kText.size(), textfield_->GetCursorPosition());
-
- // The OnBlur() behavior below is only meaningful on platforms where textfield
- // focus moves on focus change.
- if (!PlatformStyle::kTextfieldScrollsToStartOnFocusChange)
- return;
-
- // The cursor is at the start (so that it scrolls in to view), but the
- // "Select All" is currently undirected. Shift+right will give it a direction
- // and scroll to the end.
- SendKeyEvent(ui::VKEY_RIGHT, true, false);
- EXPECT_EQ(kText.size(), textfield_->GetCursorPosition());
-
- // And a focus loss should scroll back to the start.
- textfield_->OnBlur();
- EXPECT_EQ(0U, textfield_->GetCursorPosition());
-}
-
TEST_F(TextfieldTest, SendingDeletePreservesShiftFlag) {
InitTextfield();
SendKeyPress(ui::VKEY_DELETE, 0);
@@ -3839,7 +3814,7 @@ TEST_F(TextfieldTest, EmojiItem_FieldWithText) {
InitTextfield();
EXPECT_TRUE(textfield_->context_menu_controller());
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// On Mac, when there is text, the "Look up" item (+ separator) takes the top
// position, and emoji comes after.
constexpr int kExpectedEmojiIndex = 2;
@@ -3859,7 +3834,7 @@ TEST_F(TextfieldTest, EmojiItem_FieldWithText) {
l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_EMOJI));
}
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Tests to see if the BiDi submenu items are updated correctly when the
// textfield's text direction is changed.
TEST_F(TextfieldTest, TextServicesContextMenuTextDirectionTest) {
@@ -3926,12 +3901,12 @@ TEST_F(TextfieldTest, SecurePasswordInput) {
textfield_->OnBlur();
EXPECT_FALSE(ui::ScopedPasswordInputEnabler::IsPasswordInputEnabled());
}
-#endif // defined(OS_APPLE)
+#endif // defined(OS_MAC)
TEST_F(TextfieldTest, AccessibilitySelectionEvents) {
- const std::string& kText = "abcdef";
+ const std::u16string kText = u"abcdef";
InitTextfield();
- textfield_->SetText(ASCIIToUTF16(kText));
+ textfield_->SetText(kText);
EXPECT_TRUE(textfield_->HasFocus());
int previous_selection_fired_count =
textfield_->GetAccessibilitySelectionFiredCount();
@@ -4115,7 +4090,7 @@ TEST_F(TextfieldTest, ScrollCommands) {
InitTextfield();
// Scroll commands are only available on Mac.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
textfield_->SetText(u"12 34567 89");
textfield_->SetEditableSelectionRange(gfx::Range(6));
diff --git a/chromium/ui/views/controls/textfield/textfield_unittest.h b/chromium/ui/views/controls/textfield/textfield_unittest.h
index 3aa4f3ba846..fef1348c2d3 100644
--- a/chromium/ui/views/controls/textfield/textfield_unittest.h
+++ b/chromium/ui/views/controls/textfield/textfield_unittest.h
@@ -16,8 +16,6 @@
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/test/views_test_base.h"
-#define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(base::ASCIIToUTF16(ascii), utf16)
-
namespace ui {
namespace test {
class EventGenerator;
@@ -44,7 +42,7 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
ui::ClipboardBuffer GetAndResetCopiedToClipboard();
std::u16string GetClipboardText(ui::ClipboardBuffer type);
- void SetClipboardText(ui::ClipboardBuffer type, const std::string& text);
+ void SetClipboardText(ui::ClipboardBuffer type, const std::u16string& text);
// TextfieldController:
void ContentsChanged(Textfield* sender,
@@ -151,7 +149,7 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
void TapAtCursor(ui::EventPointerType pointer_type);
// We need widget to populate wrapper class.
- std::unique_ptr<Widget> widget_ = nullptr;
+ std::unique_ptr<Widget> widget_;
TestTextfield* textfield_ = nullptr;
std::unique_ptr<TextfieldTestApi> test_api_;
diff --git a/chromium/ui/views/controls/theme_tracking_image_view.cc b/chromium/ui/views/controls/theme_tracking_image_view.cc
index 18895f6609c..660ce102c04 100644
--- a/chromium/ui/views/controls/theme_tracking_image_view.cc
+++ b/chromium/ui/views/controls/theme_tracking_image_view.cc
@@ -4,9 +4,9 @@
#include "ui/views/controls/theme_tracking_image_view.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/color_utils.h"
#include "ui/native_theme/native_theme.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace views {
diff --git a/chromium/ui/views/controls/throbber.cc b/chromium/ui/views/controls/throbber.cc
index 924a718afc8..8d46b6b4842 100644
--- a/chromium/ui/views/controls/throbber.cc
+++ b/chromium/ui/views/controls/throbber.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/location.h"
#include "components/vector_icons/vector_icons.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/canvas.h"
@@ -16,7 +17,6 @@
#include "ui/gfx/paint_vector_icon.h"
#include "ui/native_theme/common_theme.h"
#include "ui/native_theme/native_theme.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace views {
diff --git a/chromium/ui/views/controls/tree/tree_view.cc b/chromium/ui/views/controls/tree/tree_view.cc
index ea3c28e610c..d23eea96d72 100644
--- a/chromium/ui/views/controls/tree/tree_view.cc
+++ b/chromium/ui/views/controls/tree/tree_view.cc
@@ -17,6 +17,7 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/ime/input_method.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
@@ -41,9 +42,7 @@
#include "ui/views/controls/scroll_view.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/controls/tree/tree_view_controller.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/style/platform_style.h"
-#include "ui/views/vector_icons.h"
using ui::TreeModel;
using ui::TreeModelNode;
@@ -85,7 +84,7 @@ TreeView::TreeView()
drawing_provider_(std::make_unique<TreeViewDrawingProvider>()) {
// Always focusable, even on Mac (consistent with NSOutlineView).
SetFocusBehavior(FocusBehavior::ALWAYS);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
constexpr bool kUseMdIcons = true;
#else
constexpr bool kUseMdIcons = false;
@@ -245,7 +244,7 @@ TreeModelNode* TreeView::GetEditingNode() {
}
void TreeView::SetSelectedNode(TreeModelNode* model_node) {
- UpdateSelection(model_node, kActiveAndSelected);
+ UpdateSelection(model_node, SelectionType::kActiveAndSelected);
}
const TreeModelNode* TreeView::GetSelectedNode() const {
@@ -253,7 +252,7 @@ const TreeModelNode* TreeView::GetSelectedNode() const {
}
void TreeView::SetActiveNode(TreeModelNode* model_node) {
- UpdateSelection(model_node, kActive);
+ UpdateSelection(model_node, SelectionType::kActive);
}
const TreeModelNode* TreeView::GetActiveNode() const {
@@ -272,9 +271,9 @@ void TreeView::Collapse(ui::TreeModelNode* model_node) {
bool was_expanded = IsExpanded(model_node);
if (node->is_expanded()) {
if (selected_node_ && selected_node_->HasAncestor(node))
- UpdateSelection(model_node, kActiveAndSelected);
+ UpdateSelection(model_node, SelectionType::kActiveAndSelected);
else if (active_node_ && active_node_->HasAncestor(node))
- UpdateSelection(model_node, kActive);
+ UpdateSelection(model_node, SelectionType::kActive);
node->set_is_expanded(false);
}
if (was_expanded) {
@@ -355,9 +354,9 @@ void TreeView::SetRootShown(bool root_shown) {
const auto& children = model_->GetChildren(root_.model_node());
TreeModelNode* first_child = children.empty() ? nullptr : children.front();
if (selected_node_ == &root_)
- UpdateSelection(first_child, kActiveAndSelected);
+ UpdateSelection(first_child, SelectionType::kActiveAndSelected);
else if (active_node_ == &root_)
- UpdateSelection(first_child, kActive);
+ UpdateSelection(first_child, SelectionType::kActive);
}
AXVirtualView* ax_view = root_.accessibility_view();
@@ -581,9 +580,9 @@ void TreeView::TreeNodesRemoved(TreeModel* model,
nearest_node = parent;
}
if (reset_selected_node)
- UpdateSelection(nearest_node, kActiveAndSelected);
+ UpdateSelection(nearest_node, SelectionType::kActiveAndSelected);
else if (reset_active_node)
- UpdateSelection(nearest_node, kActive);
+ UpdateSelection(nearest_node, SelectionType::kActive);
}
if (IsExpanded(parent)) {
@@ -699,8 +698,9 @@ bool TreeView::OnKeyPressed(const ui::KeyEvent& event) {
case ui::VKEY_UP:
case ui::VKEY_DOWN:
- IncrementSelection(event.key_code() == ui::VKEY_UP ? INCREMENT_PREVIOUS
- : INCREMENT_NEXT);
+ IncrementSelection(event.key_code() == ui::VKEY_UP
+ ? IncrementType::kPrevious
+ : IncrementType::kNext);
return true;
case ui::VKEY_LEFT:
@@ -788,8 +788,9 @@ void TreeView::UpdateSelection(TreeModelNode* model_node,
// Force update if old value was nullptr to handle case of TreeNodesRemoved
// explicitly resetting selected_node_ or active_node_ before invoking this.
bool active_changed = (!active_node_ || active_node_ != node);
- bool selection_changed = (selection_type == kActiveAndSelected &&
- (!selected_node_ || selected_node_ != node));
+ bool selection_changed =
+ (selection_type == SelectionType::kActiveAndSelected &&
+ (!selected_node_ || selected_node_ != node));
// Update tree view states to new values.
if (active_changed)
@@ -1117,7 +1118,7 @@ void TreeView::PaintExpandControl(gfx::Canvas* canvas,
const gfx::Rect& node_bounds,
bool expanded) {
gfx::ImageSkia arrow = gfx::CreateVectorIcon(
- kSubmenuArrowIcon,
+ vector_icons::kSubmenuArrowIcon,
color_utils::DeriveDefaultIconColor(
drawing_provider()->GetTextColorForNode(this, nullptr)));
if (expanded) {
@@ -1322,7 +1323,7 @@ void TreeView::IncrementSelection(IncrementType type) {
// If nothing is selected select the first or last node.
if (root_.children().empty())
return;
- if (type == INCREMENT_PREVIOUS) {
+ if (type == IncrementType::kPrevious) {
int row_count = GetRowCount();
int depth = 0;
DCHECK(row_count);
@@ -1337,7 +1338,7 @@ void TreeView::IncrementSelection(IncrementType type) {
}
int depth = 0;
- int delta = type == INCREMENT_PREVIOUS ? -1 : 1;
+ int delta = type == IncrementType::kPrevious ? -1 : 1;
int row = GetRowForInternalNode(active_node_, &depth);
int new_row = base::ClampToRange(row + delta, 0, GetRowCount() - 1);
if (new_row == row)
diff --git a/chromium/ui/views/controls/tree/tree_view.h b/chromium/ui/views/controls/tree/tree_view.h
index 73d19febf41..9b3cbf461a2 100644
--- a/chromium/ui/views/controls/tree/tree_view.h
+++ b/chromium/ui/views/controls/tree/tree_view.h
@@ -215,7 +215,7 @@ class VIEWS_EXPORT TreeView : public View,
friend class TreeViewTest;
// Enumeration of possible changes to tree view state when the UI is updated.
- enum SelectionType {
+ enum class SelectionType {
// Active state is being set to a tree item.
kActive,
@@ -307,12 +307,12 @@ class VIEWS_EXPORT TreeView : public View,
};
// Used by IncrementSelection.
- enum IncrementType {
+ enum class IncrementType {
// Selects the next node.
- INCREMENT_NEXT,
+ kNext,
// Selects the previous node.
- INCREMENT_PREVIOUS
+ kPrevious
};
// Row of the root node. This varies depending upon whether the root is
diff --git a/chromium/ui/views/controls/tree/tree_view_unittest.cc b/chromium/ui/views/controls/tree/tree_view_unittest.cc
index df91103922b..891495bfc50 100644
--- a/chromium/ui/views/controls/tree/tree_view_unittest.cc
+++ b/chromium/ui/views/controls/tree/tree_view_unittest.cc
@@ -329,8 +329,8 @@ const AXVirtualView* TreeViewTest::GetAccessibilityViewByName(
}
void TreeViewTest::IncrementSelection(bool next) {
- tree_->IncrementSelection(next ? TreeView::INCREMENT_NEXT
- : TreeView::INCREMENT_PREVIOUS);
+ tree_->IncrementSelection(next ? TreeView::IncrementType::kNext
+ : TreeView::IncrementType::kPrevious);
}
void TreeViewTest::CollapseOrSelectParent() {
diff --git a/chromium/ui/views/controls/views_text_services_context_menu_base.cc b/chromium/ui/views/controls/views_text_services_context_menu_base.cc
index 531ebe33d19..62fac34fc06 100644
--- a/chromium/ui/views/controls/views_text_services_context_menu_base.cc
+++ b/chromium/ui/views/controls/views_text_services_context_menu_base.cc
@@ -50,12 +50,15 @@ bool ViewsTextServicesContextMenuBase::GetAcceleratorForCommandId(
#if defined(OS_WIN)
*accelerator = ui::Accelerator(ui::VKEY_OEM_PERIOD, ui::EF_COMMAND_DOWN);
return true;
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
*accelerator = ui::Accelerator(ui::VKEY_SPACE,
ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN);
return true;
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
+ *accelerator = ui::Accelerator(ui::VKEY_SPACE,
+ ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN);
+ return true;
#else
- // TODO(crbug.com/887660): Add accelerator key for Chrome OS.
return false;
#endif
}
@@ -85,7 +88,7 @@ bool ViewsTextServicesContextMenuBase::SupportsCommand(int command_id) const {
return command_id == IDS_CONTENT_CONTEXT_EMOJI;
}
-#if !defined(OS_APPLE) && !BUILDFLAG(IS_CHROMEOS_ASH)
+#if !defined(OS_MAC) && !BUILDFLAG(IS_CHROMEOS_ASH)
// static
std::unique_ptr<ViewsTextServicesContextMenu>
ViewsTextServicesContextMenu::Create(ui::SimpleMenuModel* menu,
diff --git a/chromium/ui/views/controls/views_text_services_context_menu_base.h b/chromium/ui/views/controls/views_text_services_context_menu_base.h
index 4651047e6b7..34fa409221f 100644
--- a/chromium/ui/views/controls/views_text_services_context_menu_base.h
+++ b/chromium/ui/views/controls/views_text_services_context_menu_base.h
@@ -34,7 +34,7 @@ class VIEWS_EXPORT ViewsTextServicesContextMenuBase
bool SupportsCommand(int command_id) const override;
protected:
-#if defined(OS_APPLE) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH)
Textfield* client() { return client_; }
const Textfield* client() const { return client_; }
#endif
diff --git a/chromium/ui/views/controls/webview/web_dialog_view.cc b/chromium/ui/views/controls/webview/web_dialog_view.cc
index 9b312a0604c..cd3f3c88490 100644
--- a/chromium/ui/views/controls/webview/web_dialog_view.cc
+++ b/chromium/ui/views/controls/webview/web_dialog_view.cc
@@ -16,11 +16,11 @@
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/views/controls/webview/webview.h"
#include "ui/views/layout/fill_layout.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/widget/native_widget_private.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"
diff --git a/chromium/ui/views/controls/webview/web_dialog_view.h b/chromium/ui/views/controls/webview/web_dialog_view.h
index 8c5edd6b46b..96896f56004 100644
--- a/chromium/ui/views/controls/webview/web_dialog_view.h
+++ b/chromium/ui/views/controls/webview/web_dialog_view.h
@@ -13,11 +13,11 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
#include "ui/views/controls/webview/webview.h"
#include "ui/views/controls/webview/webview_export.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/window/client_view.h"
#include "ui/web_dialogs/web_dialog_delegate.h"
diff --git a/chromium/ui/views/controls/webview/webview.cc b/chromium/ui/views/controls/webview/webview.cc
index 9cb29421a3d..75c1f03c6ef 100644
--- a/chromium/ui/views/controls/webview/webview.cc
+++ b/chromium/ui/views/controls/webview/webview.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/no_destructor.h"
+#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "content/public/browser/browser_accessibility_state.h"
#include "content/public/browser/browser_context.h"
@@ -19,10 +20,10 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/platform/ax_platform_node.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/events/event.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/focus/focus_manager.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/views_delegate.h"
namespace views {
diff --git a/chromium/ui/views/corewm/DEPS b/chromium/ui/views/corewm/DEPS
index 15ef6f5085a..e862b1270f1 100644
--- a/chromium/ui/views/corewm/DEPS
+++ b/chromium/ui/views/corewm/DEPS
@@ -14,10 +14,10 @@ specific_include_rules = {
],
"tooltip_aura.cc": [
+ "+ui/base/metadata/metadata_header_macros.h",
+ "+ui/base/metadata/metadata_impl_macros.h",
"+ui/views/background.h",
"+ui/views/border.h",
- "+ui/views/metadata/metadata_header_macros.h",
- "+ui/views/metadata/metadata_impl_macros.h",
"+ui/views/painter.h",
"+ui/views/widget/widget.h",
"+ui/views/view.h",
diff --git a/chromium/ui/views/corewm/tooltip_aura.cc b/chromium/ui/views/corewm/tooltip_aura.cc
index 3e4fcf2cdee..22a883bf8af 100644
--- a/chromium/ui/views/corewm/tooltip_aura.cc
+++ b/chromium/ui/views/corewm/tooltip_aura.cc
@@ -16,6 +16,8 @@
#include "ui/accessibility/ax_node_data.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/canvas.h"
@@ -26,8 +28,6 @@
#include "ui/native_theme/native_theme.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
-#include "ui/views/metadata/metadata_header_macros.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/painter.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
@@ -158,6 +158,9 @@ END_METADATA
namespace views {
namespace corewm {
+// static
+const char TooltipAura::kWidgetName[] = "TooltipAura";
+
TooltipAura::~TooltipAura() {
DestroyWidget();
CHECK(!IsInObserverList());
@@ -246,6 +249,7 @@ void TooltipAura::CreateTooltipWidget(const gfx::Rect& bounds) {
// Use software compositing to avoid using unnecessary hardware resources
// which just amount to overkill for this UI.
params.force_software_compositing = true;
+ params.name = kWidgetName;
widget_->Init(std::move(params));
}
diff --git a/chromium/ui/views/corewm/tooltip_aura.h b/chromium/ui/views/corewm/tooltip_aura.h
index 86b2cce6a17..30cc370c4f6 100644
--- a/chromium/ui/views/corewm/tooltip_aura.h
+++ b/chromium/ui/views/corewm/tooltip_aura.h
@@ -32,6 +32,7 @@ class TooltipAuraTestApi;
// Implementation of Tooltip that shows the tooltip using a Widget and Label.
class VIEWS_EXPORT TooltipAura : public Tooltip, public WidgetObserver {
public:
+ static const char kWidgetName[];
// FIXME: get cursor offset from actual cursor size.
static constexpr int kCursorOffsetX = 10;
static constexpr int kCursorOffsetY = 15;
diff --git a/chromium/ui/views/corewm/tooltip_controller.cc b/chromium/ui/views/corewm/tooltip_controller.cc
index 284cb8dddd7..da39df72ce7 100644
--- a/chromium/ui/views/corewm/tooltip_controller.cc
+++ b/chromium/ui/views/corewm/tooltip_controller.cc
@@ -127,11 +127,18 @@ int TooltipController::GetMaxWidth(const gfx::Point& location) const {
void TooltipController::UpdateTooltip(aura::Window* target) {
// The |tooltip_parent_window_| is only set when the tooltip is visible or
// its |will_show_tooltip_timer_| is running.
- if (observed_window_ == target && state_manager_->tooltip_parent_window()) {
- // Since this is an update on an already (or about to be) visible tooltip,
- // assume that the trigger is the same as the one that initiated the current
- // tooltip and reuse it.
- UpdateIfRequired(state_manager_->tooltip_trigger());
+ if (target && observed_window_ == target) {
+ // This is either an update on an already (or about to be) visible tooltip
+ // or a call to UpdateIfRequired that will potentially trigger a tooltip
+ // caused by a tooltip text update.
+ //
+ // If there's no active tooltip, it's appropriate to assume that the trigger
+ // is kCursor because a tooltip text update triggered from the keyboard
+ // would always happen in UpdateTooltipFromKeyboard, not from here.
+ if (state_manager_->tooltip_parent_window())
+ UpdateIfRequired(state_manager_->tooltip_trigger());
+ else if (IsTooltipTextUpdateNeeded())
+ UpdateIfRequired(TooltipTrigger::kCursor);
}
ResetWindowAtMousePressedIfNeeded(target, /* force_reset */ false);
@@ -142,6 +149,13 @@ void TooltipController::UpdateTooltipFromKeyboard(const gfx::Rect& bounds,
anchor_point_ = bounds.bottom_center();
SetObservedWindow(target);
+ // Update the position of the active but not yet visible keyboard triggered
+ // tooltip, if any.
+ if (state_manager_->tooltip_parent_window()) {
+ state_manager_->UpdatePositionIfNeeded(anchor_point_,
+ TooltipTrigger::kKeyboard);
+ }
+
// This function is always only called for keyboard-triggered tooltips.
UpdateIfRequired(TooltipTrigger::kKeyboard);
@@ -161,7 +175,9 @@ void TooltipController::SetTooltipsEnabled(bool enable) {
}
void TooltipController::OnKeyEvent(ui::KeyEvent* event) {
- // Always hide a tooltip on a key event. Since this controller is a pre-target
+ if (event->type() != ui::ET_KEY_PRESSED)
+ return;
+ // Always hide a tooltip on a key press. Since this controller is a pre-target
// handler (i.e. the events are received here before the target act on them),
// hiding the tooltip will not cancel any action supposed to show it triggered
// by a key press.
@@ -176,16 +192,25 @@ void TooltipController::OnMouseEvent(ui::MouseEvent* event) {
return;
}
switch (event->type()) {
- case ui::ET_MOUSE_CAPTURE_CHANGED:
case ui::ET_MOUSE_EXITED:
- // TODO(bebeaudr): Keyboard-triggered tooltips that show up right where the
- // cursor currently is are hidden as soon as they show up because of this
- // event. Handle this case differently to fix the issue.
+ // TODO(bebeaudr): Keyboard-triggered tooltips that show up right where
+ // the cursor currently is are hidden as soon as they show up because of
+ // this event. Handle this case differently to fix the issue.
+ //
+ // Whenever a tooltip is closed, an ET_MOUSE_EXITED event is fired, even
+ // if the cursor is not in the tooltip's window. Make sure that these
+ // mouse exited events don't interfere with keyboard triggered tooltips by
+ // returning early.
+ if (state_manager_->tooltip_parent_window() &&
+ state_manager_->tooltip_trigger() == TooltipTrigger::kKeyboard) {
+ return;
+ }
+ SetObservedWindow(nullptr);
+ break;
+ case ui::ET_MOUSE_CAPTURE_CHANGED:
case ui::ET_MOUSE_MOVED:
case ui::ET_MOUSE_DRAGGED: {
last_mouse_loc_ = event->location();
- state_manager_->UpdatePositionIfWillShowTooltipTimerIsRunning(
- last_mouse_loc_);
aura::Window* target = nullptr;
// Avoid a call to display::Screen::GetWindowAtScreenPoint() since it can
// be very expensive on X11 in cases when the tooltip is hidden anyway.
@@ -193,6 +218,10 @@ void TooltipController::OnMouseEvent(ui::MouseEvent* event) {
!IsDragDropInProgress()) {
target = GetTooltipTarget(*event, &last_mouse_loc_);
}
+ // This needs to be called after the |last_mouse_loc_| is converted to the
+ // target's screen coordinates.
+ state_manager_->UpdatePositionIfNeeded(last_mouse_loc_,
+ TooltipTrigger::kCursor);
SetObservedWindow(target);
if (state_manager_->IsVisible() ||
diff --git a/chromium/ui/views/corewm/tooltip_controller_unittest.cc b/chromium/ui/views/corewm/tooltip_controller_unittest.cc
index 9ab8a56aba9..b6429adb5d7 100644
--- a/chromium/ui/views/corewm/tooltip_controller_unittest.cc
+++ b/chromium/ui/views/corewm/tooltip_controller_unittest.cc
@@ -48,8 +48,6 @@
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#endif
-using base::ASCIIToUTF16;
-
namespace views {
namespace corewm {
namespace test {
@@ -136,7 +134,7 @@ class TooltipControllerTest : public ViewsTestBase {
delegate
? delegate
: aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate());
- window->set_id(id);
+ window->SetId(id);
window->Init(ui::LAYER_TEXTURED);
parent->AddChild(window);
window->SetBounds(gfx::Rect(0, 0, 100, 100));
@@ -241,9 +239,9 @@ TEST_F(TooltipControllerTest, DontShowTooltipOnTouch) {
#if !BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_WIN)
// crbug.com/664370.
TEST_F(TooltipControllerTest, MaxWidth) {
- std::u16string text = base::ASCIIToUTF16(
- "Really really realy long long long long long tooltips that exceeds max "
- "width");
+ std::u16string text =
+ u"Really, really, really, really, really, really long tooltip that "
+ u"exceeds max width";
view_->set_tooltip_text(text);
gfx::Point center = GetWindow()->bounds().CenterPoint();
@@ -539,6 +537,23 @@ TEST_F(TooltipControllerTest, TooltipHidesOnKeyPressAndStaysHiddenUntilChange) {
EXPECT_EQ(window, helper_->GetTooltipParentWindow());
}
+TEST_F(TooltipControllerTest, TooltipStaysVisibleOnKeyRelease) {
+ view_->set_tooltip_text(u"my tooltip");
+ EXPECT_EQ(std::u16string(), helper_->GetTooltipText());
+ EXPECT_EQ(nullptr, helper_->GetTooltipParentWindow());
+
+ generator_->MoveMouseRelativeTo(GetWindow(), view_->bounds().CenterPoint());
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+
+ // This shouldn't hide the tooltip.
+ generator_->ReleaseKey(ui::VKEY_1, 0);
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+
+ // This should hide the tooltip.
+ generator_->PressKey(ui::VKEY_1, 0);
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+}
+
TEST_F(TooltipControllerTest, TooltipHidesOnTimeoutAndStaysHiddenUntilChange) {
view_->set_tooltip_text(u"Tooltip Text for view 1");
EXPECT_EQ(std::u16string(), helper_->GetTooltipText());
@@ -667,6 +682,52 @@ TEST_F(TooltipControllerTest, ShowAndHideTooltipTriggeredFromKeyboard) {
EXPECT_EQ(nullptr, helper_->GetTooltipParentWindow());
}
+TEST_F(TooltipControllerTest,
+ KeyboardTriggeredTooltipStaysVisibleOnMouseExitedEvent) {
+ std::u16string expected_tooltip = u"Tooltip Text";
+
+ wm::SetTooltipText(GetWindow(), &expected_tooltip);
+ view_->set_tooltip_text(expected_tooltip);
+ EXPECT_EQ(std::u16string(), helper_->GetTooltipText());
+ EXPECT_EQ(nullptr, helper_->GetTooltipParentWindow());
+
+ // For this test to execute properly, make sure that the cursor location is
+ // somewhere out of the |view_|, different than (0, 0). This shouldn't show
+ // the tooltip.
+ gfx::Point off_view_point = view_->bounds().bottom_right();
+ off_view_point.Offset(1, 1);
+ generator_->MoveMouseRelativeTo(widget_->GetNativeWindow(), off_view_point);
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+
+ // Trigger the tooltip from the keyboard.
+ helper_->controller()->UpdateTooltipFromKeyboard(
+ view_->ConvertRectToWidget(view_->bounds()), GetWindow());
+
+ EXPECT_EQ(expected_tooltip, wm::GetTooltipText(GetWindow()));
+ EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
+ EXPECT_EQ(GetWindow(), helper_->GetTooltipParentWindow());
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_EQ(helper_->state_manager()->tooltip_trigger(),
+ TooltipTrigger::kKeyboard);
+
+ // Sending a mouse exited event shouldn't hide a keyboard triggered tooltip.
+ generator_->SendMouseExit();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+
+ helper_->HideAndReset();
+ expected_tooltip = u"Tooltip Text 2";
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+
+ // However, a cursor triggered tooltip should still be hidden by a mouse
+ // exited event.
+ generator_->MoveMouseRelativeTo(widget_->GetNativeWindow(),
+ view_->bounds().CenterPoint());
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+
+ generator_->SendMouseExit();
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+}
+
namespace {
// Returns the index of |window| in its parent's children.
@@ -752,6 +813,101 @@ TEST_F(TooltipControllerTest, MAYBE_Capture) {
widget2.reset();
}
+TEST_F(TooltipControllerTest, ShowTooltipOnTooltipTextUpdate) {
+ std::u16string expected_tooltip;
+
+ wm::SetTooltipText(GetWindow(), &expected_tooltip);
+
+ // Create a mouse event. This event shouldn't trigger the tooltip to show
+ // since the tooltip text is empty, but should set the |observed_window_|
+ // correctly.
+ gfx::Point point(1, 1);
+ View::ConvertPointToWidget(view_, &point);
+ generator_->MoveMouseRelativeTo(GetWindow(), point);
+
+ EXPECT_EQ(std::u16string(), helper_->GetTooltipText());
+ EXPECT_EQ(nullptr, helper_->GetTooltipParentWindow());
+ EXPECT_EQ(GetWindow(), helper_->GetObservedWindow());
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+
+ // This is the heart of the test: we update the tooltip text and call
+ // UpdateTooltip. It should trigger the tooltip to show up because the
+ // |observed_window_| will be set to GetWindow() and the tooltip text on the
+ // window will be different than it previously was.
+ expected_tooltip = u"Tooltip text";
+ helper_->controller()->UpdateTooltip(GetWindow());
+
+ EXPECT_EQ(expected_tooltip, wm::GetTooltipText(GetWindow()));
+ EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
+ EXPECT_EQ(GetWindow(), helper_->GetTooltipParentWindow());
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_EQ(helper_->state_manager()->tooltip_trigger(),
+ TooltipTrigger::kCursor);
+
+ helper_->HideAndReset();
+
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+ EXPECT_EQ(nullptr, helper_->GetTooltipParentWindow());
+}
+
+// This test validates that the TooltipController correctly triggers a position
+// update for a tooltip that is about to be shown.
+TEST_F(TooltipControllerTest, TooltipPositionUpdatedWhenTimerRunning) {
+ EXPECT_EQ(nullptr, helper_->state_manager()->tooltip_parent_window());
+ EXPECT_EQ(std::u16string(), helper_->state_manager()->tooltip_text());
+
+ std::u16string expected_text = u"Tooltip Text";
+ view_->set_tooltip_text(expected_text);
+
+ helper_->SetTooltipShowDelayEnable(true);
+
+ // Testing that the position will be updated when triggered from cursor.
+ {
+ gfx::Point position = view_->bounds().CenterPoint();
+ generator_->MoveMouseRelativeTo(GetWindow(), position);
+
+ EXPECT_EQ(expected_text, wm::GetTooltipText(GetWindow()));
+ EXPECT_EQ(expected_text, helper_->GetTooltipText());
+ EXPECT_EQ(GetWindow(), helper_->GetTooltipParentWindow());
+ EXPECT_EQ(helper_->state_manager()->tooltip_trigger(),
+ TooltipTrigger::kCursor);
+ EXPECT_EQ(position, helper_->GetTooltipPosition());
+
+ // Since the |will_show_tooltip_timer_| is running, this should update the
+ // position of the already active tooltip.
+ generator_->MoveMouseBy(2, 0);
+
+ position.Offset(2, 0);
+ EXPECT_EQ(position, helper_->GetTooltipPosition());
+
+ helper_->HideAndReset();
+ }
+
+ // Testing that the position will be updated when triggered from cursor.
+ {
+ gfx::Rect bounds = view_->ConvertRectToWidget(view_->bounds());
+ helper_->controller()->UpdateTooltipFromKeyboard(bounds, GetWindow());
+
+ EXPECT_EQ(expected_text, wm::GetTooltipText(GetWindow()));
+ EXPECT_EQ(expected_text, helper_->GetTooltipText());
+ EXPECT_EQ(GetWindow(), helper_->GetTooltipParentWindow());
+ EXPECT_EQ(helper_->state_manager()->tooltip_trigger(),
+ TooltipTrigger::kKeyboard);
+ EXPECT_EQ(bounds.bottom_center(), helper_->GetTooltipPosition());
+
+ // Since the |will_show_tooltip_timer_| is running, this should update the
+ // position of the already active tooltip.
+ bounds.Offset(2, 0);
+ helper_->controller()->UpdateTooltipFromKeyboard(bounds, GetWindow());
+
+ EXPECT_EQ(bounds.bottom_center(), helper_->GetTooltipPosition());
+
+ helper_->HideAndReset();
+ }
+
+ helper_->SetTooltipShowDelayEnable(false);
+}
+
namespace {
class TestTooltip : public Tooltip {
@@ -1109,8 +1265,7 @@ TEST_F(TooltipStateManagerTest, ShowTooltipWithDelay) {
// |will_show_tooltip_timer_| has been started. This is needed because the
// cursor might still move between the moment Show is called and the timer
// fires.
-TEST_F(TooltipStateManagerTest,
- UpdatePositionWhileWillShowTooltipTimerIsRunning) {
+TEST_F(TooltipStateManagerTest, UpdatePositionIfNeeded) {
EXPECT_EQ(nullptr, helper_->state_manager()->tooltip_parent_window());
EXPECT_EQ(std::u16string(), helper_->state_manager()->tooltip_text());
@@ -1118,29 +1273,77 @@ TEST_F(TooltipStateManagerTest,
helper_->SetTooltipShowDelayEnable(true);
- gfx::Point position(0, 0);
- // 1. When the |will_show_tooltip_timer_| is running, validate that we can
- // update the position.
- helper_->state_manager()->Show(GetRootWindow(), expected_text, position,
- TooltipTrigger::kCursor, {});
- EXPECT_EQ(GetRootWindow(), helper_->state_manager()->tooltip_parent_window());
- EXPECT_EQ(expected_text, helper_->state_manager()->tooltip_text());
- EXPECT_EQ(position, helper_->GetTooltipPosition());
- EXPECT_FALSE(helper_->IsTooltipVisible());
- EXPECT_TRUE(helper_->state_manager()->IsWillShowTooltipTimerRunning());
-
- position = gfx::Point(10, 10);
- helper_->state_manager()->UpdatePositionIfWillShowTooltipTimerIsRunning(
- position);
- EXPECT_EQ(position, helper_->GetTooltipPosition());
-
- // 2. Validate that we can't update the position when the timer isn't running.
- helper_->HideAndReset();
- position = gfx::Point(20, 20);
- helper_->state_manager()->UpdatePositionIfWillShowTooltipTimerIsRunning(
- position);
- EXPECT_NE(position, helper_->GetTooltipPosition());
+ {
+ gfx::Point position(0, 0);
+ // 1. When the |will_show_tooltip_timer_| is running, validate that we can
+ // update the position.
+ helper_->state_manager()->Show(GetRootWindow(), expected_text, position,
+ TooltipTrigger::kCursor, {});
+ EXPECT_EQ(GetRootWindow(),
+ helper_->state_manager()->tooltip_parent_window());
+ EXPECT_EQ(expected_text, helper_->state_manager()->tooltip_text());
+ EXPECT_EQ(position, helper_->GetTooltipPosition());
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+ EXPECT_TRUE(helper_->state_manager()->IsWillShowTooltipTimerRunning());
+
+ gfx::Point new_position = gfx::Point(10, 10);
+ // Because the tooltip was triggered by the cursor, the position should be
+ // updated by a keyboard triggered modification.
+ helper_->state_manager()->UpdatePositionIfNeeded(new_position,
+ TooltipTrigger::kKeyboard);
+ EXPECT_EQ(position, helper_->GetTooltipPosition());
+
+ // But it should be updated when the position's update is triggered by the
+ // cursor.
+ helper_->state_manager()->UpdatePositionIfNeeded(new_position,
+ TooltipTrigger::kCursor);
+ EXPECT_EQ(new_position, helper_->GetTooltipPosition());
+
+ // 2. Validate that we can't update the position when the timer isn't
+ // running.
+ helper_->HideAndReset();
+ position = new_position;
+ new_position = gfx::Point(20, 20);
+ helper_->state_manager()->UpdatePositionIfNeeded(new_position,
+ TooltipTrigger::kCursor);
+ EXPECT_EQ(position, helper_->GetTooltipPosition());
+ }
+ {
+ gfx::Point position(0, 0);
+ // 1. When the |will_show_tooltip_timer_| is running, validate that we can
+ // update the position.
+ helper_->state_manager()->Show(GetRootWindow(), expected_text, position,
+ TooltipTrigger::kKeyboard, {});
+ EXPECT_EQ(GetRootWindow(),
+ helper_->state_manager()->tooltip_parent_window());
+ EXPECT_EQ(expected_text, helper_->state_manager()->tooltip_text());
+ EXPECT_EQ(position, helper_->GetTooltipPosition());
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+ EXPECT_TRUE(helper_->state_manager()->IsWillShowTooltipTimerRunning());
+
+ gfx::Point new_position = gfx::Point(10, 10);
+ // Because the tooltip was triggered by the keyboard, the position shouldn't
+ // be updated by a cursor triggered modification.
+ helper_->state_manager()->UpdatePositionIfNeeded(new_position,
+ TooltipTrigger::kCursor);
+ EXPECT_EQ(position, helper_->GetTooltipPosition());
+
+ // But it should be updated when the position's update is triggered by a
+ // keyboard action.
+ helper_->state_manager()->UpdatePositionIfNeeded(new_position,
+ TooltipTrigger::kKeyboard);
+ EXPECT_EQ(new_position, helper_->GetTooltipPosition());
+
+ // 2. Validate that we can't update the position when the timer isn't
+ // running.
+ helper_->HideAndReset();
+ position = new_position;
+ new_position = gfx::Point(20, 20);
+ helper_->state_manager()->UpdatePositionIfNeeded(new_position,
+ TooltipTrigger::kKeyboard);
+ EXPECT_EQ(position, helper_->GetTooltipPosition());
+ }
helper_->SetTooltipShowDelayEnable(false);
}
diff --git a/chromium/ui/views/corewm/tooltip_state_manager.cc b/chromium/ui/views/corewm/tooltip_state_manager.cc
index 2991c8763da..83a5630fcb5 100644
--- a/chromium/ui/views/corewm/tooltip_state_manager.cc
+++ b/chromium/ui/views/corewm/tooltip_state_manager.cc
@@ -10,6 +10,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "ui/gfx/text_elider.h"
@@ -89,9 +90,15 @@ void TooltipStateManager::StopWillShowTooltipTimer() {
will_show_tooltip_timer_.Stop();
}
-void TooltipStateManager::UpdatePositionIfWillShowTooltipTimerIsRunning(
- const gfx::Point& position) {
- if (!will_show_tooltip_timer_.IsRunning())
+void TooltipStateManager::UpdatePositionIfNeeded(const gfx::Point& position,
+ TooltipTrigger trigger) {
+ // The position should only be updated when the tooltip has been triggered but
+ // is not yet visible. Also, we only want to allow the update when it's set
+ // off by the same trigger that started the |will_show_tooltip_timer_| in
+ // the first place. Otherwise, for example, the position of a keyboard
+ // triggered tooltip could be updated by an unrelated mouse exited event. The
+ // tooltip would then show up at the wrong location.
+ if (!will_show_tooltip_timer_.IsRunning() || trigger != tooltip_trigger_)
return;
position_ = position;
diff --git a/chromium/ui/views/corewm/tooltip_state_manager.h b/chromium/ui/views/corewm/tooltip_state_manager.h
index e0abbcd3962..6c37ef304ac 100644
--- a/chromium/ui/views/corewm/tooltip_state_manager.h
+++ b/chromium/ui/views/corewm/tooltip_state_manager.h
@@ -75,11 +75,11 @@ class VIEWS_EXPORT TooltipStateManager {
TooltipTrigger tooltip_trigger() const { return tooltip_trigger_; }
// Update the |position_| if we're about to show the tooltip. This is to
- // ensure that the tooltip's position is aligned with the latest cursor
- // location, even when the cursor moves inside the same view after the show
- // timer has started.
- void UpdatePositionIfWillShowTooltipTimerIsRunning(
- const gfx::Point& position);
+ // ensure that the tooltip's position is aligned with either the latest cursor
+ // location for a cursor triggered tooltip or the most recent position
+ // received for a keyboard triggered tooltip.
+ void UpdatePositionIfNeeded(const gfx::Point& position,
+ TooltipTrigger trigger);
private:
friend class test::TooltipControllerTestHelper;
diff --git a/chromium/ui/views/corewm/tooltip_win.h b/chromium/ui/views/corewm/tooltip_win.h
index be9088d2dc2..f8b6c269b0b 100644
--- a/chromium/ui/views/corewm/tooltip_win.h
+++ b/chromium/ui/views/corewm/tooltip_win.h
@@ -13,8 +13,8 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/win/scoped_gdi_object.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/point.h"
#include "ui/views/corewm/tooltip.h"
diff --git a/chromium/ui/views/debug/debugger_utils.cc b/chromium/ui/views/debug/debugger_utils.cc
index a4660a36daa..ea70ea2e966 100644
--- a/chromium/ui/views/debug/debugger_utils.cc
+++ b/chromium/ui/views/debug/debugger_utils.cc
@@ -49,7 +49,7 @@ void AddAttributeString(AttributeStrings& attributes,
void AddPtrAttributeString(AttributeStrings& attributes,
const std::string& name,
- const base::Optional<intptr_t>& value) {
+ const absl::optional<intptr_t>& value) {
if (!value)
return;
@@ -131,8 +131,8 @@ void PrintViewHierarchyImpl(std::ostream* out,
} // namespace
-base::Optional<intptr_t> ViewDebugWrapper::GetAddress() {
- return base::nullopt;
+absl::optional<intptr_t> ViewDebugWrapper::GetAddress() {
+ return absl::nullopt;
}
void PrintViewHierarchy(std::ostream* out,
diff --git a/chromium/ui/views/debug/debugger_utils.h b/chromium/ui/views/debug/debugger_utils.h
index 02cf56623b6..be9ca33a619 100644
--- a/chromium/ui/views/debug/debugger_utils.h
+++ b/chromium/ui/views/debug/debugger_utils.h
@@ -11,7 +11,7 @@
#include <vector>
#include "base/callback.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace views {
namespace debug {
@@ -39,7 +39,7 @@ class ViewDebugWrapper {
virtual bool GetEnabled() = 0;
virtual std::vector<ViewDebugWrapper*> GetChildren() = 0;
virtual void ForAllProperties(PropCallback callback) {}
- virtual base::Optional<intptr_t> GetAddress();
+ virtual absl::optional<intptr_t> GetAddress();
};
void PrintViewHierarchy(std::ostream* out,
diff --git a/chromium/ui/views/debug_utils.cc b/chromium/ui/views/debug_utils.cc
index 63355b3b6f4..97ce8b05ea5 100644
--- a/chromium/ui/views/debug_utils.cc
+++ b/chromium/ui/views/debug_utils.cc
@@ -7,6 +7,7 @@
#include <ostream>
#include "base/logging.h"
+#include "ui/compositor/layer.h"
#include "ui/views/view.h"
#if !defined(NDEBUG)
diff --git a/chromium/ui/views/examples/BUILD.gn b/chromium/ui/views/examples/BUILD.gn
index 59d9cff023b..348ea49ddc7 100644
--- a/chromium/ui/views/examples/BUILD.gn
+++ b/chromium/ui/views/examples/BUILD.gn
@@ -11,6 +11,8 @@ component("views_examples_lib") {
testonly = true
sources = [
+ "animation_example.cc",
+ "animation_example.h",
"ax_example.cc",
"ax_example.h",
"box_layout_example.cc",
diff --git a/chromium/ui/views/examples/animation_example.cc b/chromium/ui/views/examples/animation_example.cc
new file mode 100644
index 00000000000..cff22c58d99
--- /dev/null
+++ b/chromium/ui/views/examples/animation_example.cc
@@ -0,0 +1,161 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/examples/animation_example.h"
+
+#include <algorithm>
+#include <memory>
+
+#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animation_element.h"
+#include "ui/compositor/layer_animation_sequence.h"
+#include "ui/compositor/layer_animator.h"
+#include "ui/compositor/layer_delegate.h"
+#include "ui/compositor/paint_recorder.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/views/background.h"
+#include "ui/views/layout/animating_layout_manager.h"
+#include "ui/views/layout/layout_manager_base.h"
+#include "ui/views/layout/layout_provider.h"
+#include "ui/views/style/typography.h"
+#include "ui/views/style/typography_provider.h"
+#include "ui/views/view.h"
+
+namespace views {
+namespace examples {
+
+AnimationExample::AnimationExample() : ExampleBase("Animation") {}
+
+AnimationExample::~AnimationExample() = default;
+
+class AnimatingSquare : public View {
+ public:
+ explicit AnimatingSquare(size_t index);
+ AnimatingSquare(const AnimatingSquare&) = delete;
+ AnimatingSquare& operator=(const AnimatingSquare&) = delete;
+ ~AnimatingSquare() override = default;
+
+ protected:
+ // views::View override
+ void OnPaint(gfx::Canvas* canvas) override;
+
+ private:
+ int index_;
+ int paint_counter_ = 0;
+ gfx::FontList font_list_ =
+ LayoutProvider::Get()->GetTypographyProvider().GetFont(
+ style::CONTEXT_DIALOG_TITLE,
+ style::STYLE_PRIMARY);
+};
+
+AnimatingSquare::AnimatingSquare(size_t index) : index_(index) {
+ SetPaintToLayer();
+ layer()->SetFillsBoundsOpaquely(false);
+ layer()->SetFillsBoundsCompletely(false);
+ layer()->SetAnimator(new ui::LayerAnimator(base::TimeDelta::FromSeconds(1)));
+ layer()->GetAnimator()->set_tween_type(gfx::Tween::EASE_IN_OUT);
+ layer()->GetAnimator()->set_preemption_strategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+
+ auto opacity_sequence = std::make_unique<ui::LayerAnimationSequence>();
+ opacity_sequence->set_is_repeating(true);
+ opacity_sequence->AddElement(ui::LayerAnimationElement::CreateOpacityElement(
+ 0.4f, base::TimeDelta::FromSeconds(2)));
+ opacity_sequence->AddElement(ui::LayerAnimationElement::CreateOpacityElement(
+ 0.9f, base::TimeDelta::FromSeconds(2)));
+ layer()->GetAnimator()->StartAnimation(opacity_sequence.release());
+}
+
+void AnimatingSquare::OnPaint(gfx::Canvas* canvas) {
+ View::OnPaint(canvas);
+ const SkColor color = SkColorSetRGB((5 - index_) * 51, 0, index_ * 51);
+ const SkColor colors[2] = {color,
+ color_utils::HSLShift(color, {-1.0, -1.0, 0.75})};
+ cc::PaintFlags flags;
+ gfx::Rect local_bounds = gfx::Rect(layer()->size());
+ const float dsf = canvas->UndoDeviceScaleFactor();
+ gfx::RectF local_bounds_f = gfx::RectF(local_bounds);
+ local_bounds_f.Scale(dsf);
+ SkRect bounds = gfx::RectToSkRect(gfx::ToEnclosingRect(local_bounds_f));
+ flags.setAntiAlias(true);
+ flags.setShader(cc::PaintShader::MakeRadialGradient(
+ SkPoint::Make(bounds.centerX(), bounds.centerY()), bounds.width() / 2,
+ colors, nullptr, 2, SkTileMode::kClamp));
+ canvas->DrawRect(gfx::ToEnclosingRect(local_bounds_f), flags);
+ int width = 0;
+ int height = 0;
+ std::u16string counter = base::NumberToString16(++paint_counter_);
+ canvas->SizeStringInt(counter, font_list_, &width, &height, 0,
+ gfx::Canvas::TEXT_ALIGN_CENTER);
+ local_bounds.ClampToCenteredSize(gfx::Size(width, height));
+ canvas->DrawStringRectWithFlags(counter, font_list_, SK_ColorBLACK,
+ local_bounds, gfx::Canvas::TEXT_ALIGN_CENTER);
+}
+
+class SquaresLayoutManager : public LayoutManagerBase {
+ public:
+ SquaresLayoutManager() = default;
+ ~SquaresLayoutManager() override = default;
+
+ protected:
+ // LayoutManagerBase:
+ ProposedLayout CalculateProposedLayout(
+ const SizeBounds& size_bounds) const override;
+
+ private:
+ static constexpr int kPadding = 25;
+ static constexpr gfx::Size kSize = gfx::Size(100, 100);
+};
+
+// static
+constexpr gfx::Size SquaresLayoutManager::kSize;
+
+ProposedLayout SquaresLayoutManager::CalculateProposedLayout(
+ const SizeBounds& size_bounds) const {
+ ProposedLayout layout;
+
+ const auto& children = host_view()->children();
+ const int item_width = kSize.width() + kPadding;
+ const int item_height = kSize.height() + kPadding;
+ const int max_width = kPadding + (children.size() * item_width);
+ const int bounds_width =
+ std::max(kPadding + item_width, size_bounds.width().min_of(max_width));
+ const int views_per_row = (bounds_width - kPadding) / item_width;
+
+ for (size_t i = 0; i < children.size(); ++i) {
+ const size_t row = i / views_per_row;
+ const size_t column = i % views_per_row;
+ const gfx::Point origin(kPadding + column * item_width,
+ kPadding + row * item_height);
+ layout.child_layouts.push_back(
+ {children[i], true, gfx::Rect(origin, kSize), SizeBounds(kSize)});
+ }
+
+ const size_t num_rows = (children.size() + views_per_row - 1) / views_per_row;
+ const int max_height = kPadding + (num_rows * item_height);
+ const int bounds_height =
+ std::max(kPadding + item_height, size_bounds.height().min_of(max_height));
+ layout.host_size = {bounds_width, bounds_height};
+ return layout;
+}
+
+void AnimationExample::CreateExampleView(View* container) {
+ container->SetBackground(CreateSolidBackground(SK_ColorWHITE));
+ container->SetPaintToLayer();
+ container->layer()->SetMasksToBounds(true);
+ container->layer()->SetFillsBoundsOpaquely(true);
+
+ container->SetLayoutManager(std::make_unique<SquaresLayoutManager>());
+ for (size_t i = 0; i < 5; ++i)
+ container->AddChildView(std::make_unique<AnimatingSquare>(i));
+}
+
+} // namespace examples
+} // namespace views
diff --git a/chromium/ui/views/examples/animation_example.h b/chromium/ui/views/examples/animation_example.h
new file mode 100644
index 00000000000..42d45c5886a
--- /dev/null
+++ b/chromium/ui/views/examples/animation_example.h
@@ -0,0 +1,27 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_EXAMPLES_ANIMATION_EXAMPLE_H_
+#define UI_VIEWS_EXAMPLES_ANIMATION_EXAMPLE_H_
+
+#include "ui/views/examples/example_base.h"
+
+namespace views {
+namespace examples {
+
+class VIEWS_EXAMPLES_EXPORT AnimationExample : public ExampleBase {
+ public:
+ AnimationExample();
+ AnimationExample(const AnimationExample&) = delete;
+ AnimationExample& operator=(const AnimationExample&) = delete;
+ ~AnimationExample() override;
+
+ // ExampleBase:
+ void CreateExampleView(View* container) override;
+};
+
+} // namespace examples
+} // namespace views
+
+#endif // UI_VIEWS_EXAMPLES_ANIMATION_EXAMPLE_H_
diff --git a/chromium/ui/views/examples/button_example.cc b/chromium/ui/views/examples/button_example.cc
index f52f2c14126..3df54747c8b 100644
--- a/chromium/ui/views/examples/button_example.cc
+++ b/chromium/ui/views/examples/button_example.cc
@@ -28,11 +28,11 @@
using base::ASCIIToUTF16;
namespace {
-const char kLabelButton[] = "Label Button";
-const char kLongText[] =
- "Start of Really Really Really Really Really Really "
- "Really Really Really Really Really Really Really "
- "Really Really Really Really Really Long Button Text";
+const char16_t kLabelButton[] = u"Label Button";
+const char16_t kLongText[] =
+ u"Start of Really Really Really Really Really Really "
+ u"Really Really Really Really Really Really Really "
+ u"Really Really Really Really Really Long Button Text";
} // namespace
namespace views {
@@ -61,7 +61,7 @@ void ButtonExample::CreateExampleView(View* container) {
.SetBackground(CreateSolidBackground(SK_ColorWHITE))
.AddChildren({Builder<LabelButton>()
.CopyAddressTo(&label_button_)
- .SetText(ASCIIToUTF16(kLabelButton))
+ .SetText(kLabelButton)
.SetRequestFocusOnPress(true)
.SetCallback(base::BindRepeating(
&ButtonExample::LabelButtonPressed,
@@ -106,10 +106,10 @@ void ButtonExample::LabelButtonPressed(LabelButton* label_button,
PrintStatus("Label Button Pressed! count: %d", ++count_);
if (event.IsControlDown()) {
if (event.IsShiftDown()) {
- label_button->SetText(ASCIIToUTF16(
+ label_button->SetText(
label_button->GetText().empty()
? kLongText
- : label_button->GetText().length() > 50 ? kLabelButton : ""));
+ : label_button->GetText().length() > 50 ? kLabelButton : u"");
} else if (event.IsAltDown()) {
label_button->SetImageModel(
Button::STATE_NORMAL,
diff --git a/chromium/ui/views/examples/checkbox_example.cc b/chromium/ui/views/examples/checkbox_example.cc
index 2d1b89e6b3e..972331539a5 100644
--- a/chromium/ui/views/examples/checkbox_example.cc
+++ b/chromium/ui/views/examples/checkbox_example.cc
@@ -7,7 +7,6 @@
#include <memory>
#include "base/bind.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/button/radio_button.h"
diff --git a/chromium/ui/views/examples/colored_dialog_example.cc b/chromium/ui/views/examples/colored_dialog_example.cc
index daa7082d0c6..aa52409bbfd 100644
--- a/chromium/ui/views/examples/colored_dialog_example.cc
+++ b/chromium/ui/views/examples/colored_dialog_example.cc
@@ -84,7 +84,7 @@ ColoredDialog::ColoredDialog(AcceptCallback accept_callback) {
SetLayoutManager(std::make_unique<views::FillLayout>());
set_margins(views::LayoutProvider::Get()->GetDialogInsetsForContentType(
- views::CONTROL, views::CONTROL));
+ views::DialogContentType::kControl, views::DialogContentType::kControl));
textfield_ = AddChildView(std::make_unique<views::Textfield>());
textfield_->SetPlaceholderText(
diff --git a/chromium/ui/views/examples/create_examples.cc b/chromium/ui/views/examples/create_examples.cc
index 91524e08c6c..ee56b81a5a1 100644
--- a/chromium/ui/views/examples/create_examples.cc
+++ b/chromium/ui/views/examples/create_examples.cc
@@ -4,8 +4,10 @@
#include "ui/views/examples/create_examples.h"
+#include <memory>
#include <utility>
+#include "ui/views/examples/animation_example.h"
#include "ui/views/examples/ax_example.h"
#include "ui/views/examples/box_layout_example.h"
#include "ui/views/examples/bubble_example.h"
@@ -45,6 +47,7 @@ namespace examples {
// Creates the default set of examples.
ExampleVector CreateExamples(ExampleVector extra_examples) {
ExampleVector examples = std::move(extra_examples);
+ examples.push_back(std::make_unique<AnimationExample>());
examples.push_back(std::make_unique<AxExample>());
examples.push_back(std::make_unique<BoxLayoutExample>());
examples.push_back(std::make_unique<BubbleExample>());
diff --git a/chromium/ui/views/examples/create_examples.h b/chromium/ui/views/examples/create_examples.h
index 39f1d02181e..1c035bec7d3 100644
--- a/chromium/ui/views/examples/create_examples.h
+++ b/chromium/ui/views/examples/create_examples.h
@@ -5,8 +5,6 @@
#ifndef UI_VIEWS_EXAMPLES_CREATE_EXAMPLES_H_
#define UI_VIEWS_EXAMPLES_CREATE_EXAMPLES_H_
-#include <memory>
-#include <vector>
#include "ui/views/examples/example_base.h"
#include "ui/views/examples/views_examples_export.h"
diff --git a/chromium/ui/views/examples/dialog_example.cc b/chromium/ui/views/examples/dialog_example.cc
index 7676d6a3947..e3a1dab871b 100644
--- a/chromium/ui/views/examples/dialog_example.cc
+++ b/chromium/ui/views/examples/dialog_example.cc
@@ -110,11 +110,11 @@ class DialogExample::Dialog : public Delegate<DialogDelegateView> {
DialogExample::DialogExample()
: ExampleBase("Dialog"),
mode_model_({
- u"Modeless",
- u"Window Modal",
- u"Child Modal",
- u"System Modal",
- u"Fake Modeless (non-bubbles)",
+ ui::SimpleComboboxModel::Item(u"Modeless"),
+ ui::SimpleComboboxModel::Item(u"Window Modal"),
+ ui::SimpleComboboxModel::Item(u"Child Modal"),
+ ui::SimpleComboboxModel::Item(u"System Modal"),
+ ui::SimpleComboboxModel::Item(u"Fake Modeless (non-bubbles)"),
}) {}
DialogExample::~DialogExample() = default;
@@ -317,7 +317,7 @@ void DialogExample::ContentsChanged(Textfield* sender,
void DialogExample::OnPerformAction() {
bool enable = bubble_->GetChecked() || GetModalType() != ui::MODAL_TYPE_CHILD;
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
enable = enable && GetModalType() != ui::MODAL_TYPE_SYSTEM;
#endif
show_->SetEnabled(enable);
diff --git a/chromium/ui/views/examples/examples_main_proc.cc b/chromium/ui/views/examples/examples_main_proc.cc
index 883b4485071..0f0ff431478 100644
--- a/chromium/ui/views/examples/examples_main_proc.cc
+++ b/chromium/ui/views/examples/examples_main_proc.cc
@@ -172,7 +172,7 @@ ExamplesExitCode ExamplesMainProc(bool under_test) {
#endif
#if BUILDFLAG(ENABLE_DESKTOP_AURA)
std::unique_ptr<display::Screen> desktop_screen =
- base::WrapUnique(views::CreateDesktopScreen());
+ views::CreateDesktopScreen();
#endif
base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
diff --git a/chromium/ui/views/examples/examples_window.cc b/chromium/ui/views/examples/examples_window.cc
index 11b011afe7a..2ffa4f395e9 100644
--- a/chromium/ui/views/examples/examples_window.cc
+++ b/chromium/ui/views/examples/examples_window.cc
@@ -200,6 +200,7 @@ class ExamplesWindowContents : public WidgetDelegateView {
}
return size;
}
+ gfx::Size GetMinimumSize() const override { return gfx::Size(50, 50); }
void ComboboxChanged() {
int index = combobox_->GetSelectedIndex();
diff --git a/chromium/ui/views/examples/examples_with_content_main.cc b/chromium/ui/views/examples/examples_with_content_main.cc
index 31fac3aef46..7fca765ef46 100644
--- a/chromium/ui/views/examples/examples_with_content_main.cc
+++ b/chromium/ui/views/examples/examples_with_content_main.cc
@@ -13,7 +13,7 @@
#include "ui/views/examples/examples_window_with_content.h"
#include "ui/views_content_client/views_content_client.h"
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#include "sandbox/mac/seatbelt_exec.h"
#endif
@@ -48,7 +48,7 @@ void ShowContentExampleWindow(ui::ViewsContentClient* views_content_client,
// dlsym search path, which breaks (usually valid) assumptions made in
// sandbox::InitLibcUrandomOverrides(). See http://crbug.com/374712.
if (!browser_context) {
- content::BrowserContext::SaveSessionState(nullptr);
+ browser_context->SaveSessionState();
NOTREACHED();
}
}
@@ -69,7 +69,7 @@ int main(int argc, const char** argv) {
if (views::examples::CheckCommandLineUsage())
return 0;
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
// ViewsContentClient expects a const char** argv and
// CreateFromArgumentsResult expects a regular char** argv. Given this is a
diff --git a/chromium/ui/views/examples/label_example.cc b/chromium/ui/views/examples/label_example.cc
index e90dcfd13ed..7ddbc9bc8d5 100644
--- a/chromium/ui/views/examples/label_example.cc
+++ b/chromium/ui/views/examples/label_example.cc
@@ -96,15 +96,15 @@ void LabelExample::CreateExampleView(View* container) {
label = std::make_unique<ExamplePreferredSizeLabel>();
label->SetText(
- ASCIIToUTF16("A long label will elide toward its logical end "
- "if the text's width exceeds the label's available width."));
+ u"A long label will elide toward its logical end if the text's width "
+ u"exceeds the label's available width.");
container->AddChildView(std::move(label));
label = std::make_unique<ExamplePreferredSizeLabel>();
- label->SetText(ASCIIToUTF16(
- "A multi-line label will wrap onto subsequent "
- "lines if the text's width exceeds the label's available width, which is "
- "helpful for extemely long text used to demonstrate line wrapping."));
+ label->SetText(
+ u"A multi-line label will wrap onto subsequent lines if the text's width "
+ u"exceeds the label's available width, which is helpful for extemely "
+ u"long text used to demonstrate line wrapping.");
label->SetMultiLine(true);
container->AddChildView(std::move(label));
@@ -161,8 +161,8 @@ void LabelExample::AddCustomLabel(View* container) {
layout->AddView(std::make_unique<Label>(u"Content: "));
auto textfield = std::make_unique<Textfield>();
textfield->SetText(
- ASCIIToUTF16("Use the provided controls to configure the "
- "content and presentation of this custom label."));
+ u"Use the provided controls to configure the content and presentation of "
+ u"this custom label.");
textfield->SetEditableSelectionRange(gfx::Range());
textfield->set_controller(this);
textfield_ = layout->AddView(std::move(textfield));
diff --git a/chromium/ui/views/examples/layout_example_base.cc b/chromium/ui/views/examples/layout_example_base.cc
index f61e0392d5b..db68590925c 100644
--- a/chromium/ui/views/examples/layout_example_base.cc
+++ b/chromium/ui/views/examples/layout_example_base.cc
@@ -32,6 +32,16 @@ constexpr int kLayoutExampleVerticalSpacing = 3;
constexpr int kLayoutExampleLeftPadding = 8;
constexpr gfx::Size kLayoutExampleDefaultChildSize(180, 90);
+class LayoutPanel : public View {
+ protected:
+ void OnThemeChanged() override {
+ View::OnThemeChanged();
+ SetBorder(CreateSolidBorder(
+ 1, GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_UnfocusedBorderColor)));
+ }
+};
+
// This View holds two other views which consists of a view on the left onto
// which the BoxLayout is attached for demonstrating its features. The view
// on the right contains all the various controls which allow the user to
@@ -241,10 +251,7 @@ void LayoutExampleBase::CreateExampleView(View* container) {
auto* const manager = full_panel->SetLayoutManager(
std::make_unique<BoxLayout>(views::BoxLayout::Orientation::kHorizontal));
- layout_panel_ = full_panel->AddChildView(std::make_unique<View>());
- layout_panel_->SetBorder(CreateSolidBorder(
- 1, layout_panel_->GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_UnfocusedBorderColor)));
+ layout_panel_ = full_panel->AddChildView(std::make_unique<LayoutPanel>());
manager->SetFlexForView(layout_panel_, 3);
control_panel_ = full_panel->AddChildView(std::make_unique<View>());
diff --git a/chromium/ui/views/examples/login_bubble_dialog_example.cc b/chromium/ui/views/examples/login_bubble_dialog_example.cc
index 297ea549b59..5d9f2ba3a6e 100644
--- a/chromium/ui/views/examples/login_bubble_dialog_example.cc
+++ b/chromium/ui/views/examples/login_bubble_dialog_example.cc
@@ -9,7 +9,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/callback_forward.h"
#include "base/strings/strcat.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/border.h"
@@ -89,8 +88,8 @@ LoginBubbleDialogView::LoginBubbleDialogView(
l10n_util::GetStringUTF16(IDS_LOGIN_OK_BUTTON_LABEL));
const LayoutProvider* provider = LayoutProvider::Get();
- set_margins(
- provider->GetDialogInsetsForContentType(views::CONTROL, views::CONTROL));
+ set_margins(provider->GetDialogInsetsForContentType(
+ views::DialogContentType::kControl, views::DialogContentType::kControl));
const int related_control_padding =
provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL);
const int label_padding =
diff --git a/chromium/ui/views/examples/menu_example.cc b/chromium/ui/views/examples/menu_example.cc
index 63bb3183294..5849133ee9c 100644
--- a/chromium/ui/views/examples/menu_example.cc
+++ b/chromium/ui/views/examples/menu_example.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <set>
+#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/l10n/l10n_util.h"
diff --git a/chromium/ui/views/examples/message_box_example.cc b/chromium/ui/views/examples/message_box_example.cc
index 8f663a6055a..2ea5c479e5c 100644
--- a/chromium/ui/views/examples/message_box_example.cc
+++ b/chromium/ui/views/examples/message_box_example.cc
@@ -49,7 +49,8 @@ void MessageBoxExample::CreateExampleView(View* container) {
button_panel->AddChildView(std::make_unique<LabelButton>(
base::BindRepeating(
[](MessageBoxView* message_box) {
- message_box->SetCheckBoxSelected(message_box->IsCheckBoxSelected());
+ message_box->SetCheckBoxSelected(
+ !message_box->IsCheckBoxSelected());
},
base::Unretained(message_box_view_)),
GetStringUTF16(IDS_MESSAGE_TOGGLE_LABEL)));
diff --git a/chromium/ui/views/examples/message_box_example.h b/chromium/ui/views/examples/message_box_example.h
index d8648c583ef..0319ac2dc74 100644
--- a/chromium/ui/views/examples/message_box_example.h
+++ b/chromium/ui/views/examples/message_box_example.h
@@ -5,7 +5,6 @@
#ifndef UI_VIEWS_EXAMPLES_MESSAGE_BOX_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_MESSAGE_BOX_EXAMPLE_H_
-#include <string>
#include "base/macros.h"
#include "ui/views/examples/example_base.h"
diff --git a/chromium/ui/views/examples/multiline_example.cc b/chromium/ui/views/examples/multiline_example.cc
index 62c90f38ca9..c3d66d44a58 100644
--- a/chromium/ui/views/examples/multiline_example.cc
+++ b/chromium/ui/views/examples/multiline_example.cc
@@ -8,12 +8,13 @@
#include <algorithm>
#include <memory>
+#include <string>
#include <utility>
-#include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/events/event.h"
+#include "ui/gfx/range/range.h"
#include "ui/gfx/render_text.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
@@ -61,6 +62,8 @@ class MultilineExample::RenderTextView : public View {
RenderTextView() : render_text_(gfx::RenderText::CreateRenderText()) {
render_text_->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
render_text_->SetColor(SK_ColorBLACK);
+ render_text_->set_selection_color(SK_ColorBLACK);
+ render_text_->set_selection_background_focused_color(SK_ColorGRAY);
render_text_->SetMultiline(true);
SetBorder(CreateSolidBorder(2, SK_ColorGRAY));
}
diff --git a/chromium/ui/views/examples/native_theme_example.cc b/chromium/ui/views/examples/native_theme_example.cc
index 266233cae58..28eb3390266 100644
--- a/chromium/ui/views/examples/native_theme_example.cc
+++ b/chromium/ui/views/examples/native_theme_example.cc
@@ -28,11 +28,10 @@ namespace examples {
namespace {
-// Argument utility macro that expands |label| to both a string as the first
-// argument and the corresponding ui::NativeTheme::ColorId as the second
+// Argument utility macro that expands |label| to both a UTF16 string as the
+// first argument and the corresponding ui::NativeTheme::ColorId as the second
// argument.
-#define COLOR_LABEL_ARGS(label) \
- base::ASCIIToUTF16(#label), ui::NativeTheme::ColorId::label
+#define COLOR_LABEL_ARGS(label) u## #label, ui::NativeTheme::ColorId::label
// Starts a new row and adds two columns to |layout|, the first displaying
// |label_string| and the second displaying |color_id| with its color and
@@ -40,11 +39,13 @@ namespace {
void InsertColorRow(GridLayout* layout,
base::StringPiece16 label_string,
ui::NativeTheme::ColorId color_id) {
- auto label_view = std::make_unique<Label>(std::u16string(label_string));
+ layout->StartRow(GridLayout::kFixedSize, 0);
+ auto* label_view =
+ layout->AddView(std::make_unique<Label>(std::u16string(label_string)));
label_view->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
label_view->SetSelectable(true);
- auto color_view = std::make_unique<Label>();
+ auto* color_view = layout->AddView(std::make_unique<Label>());
color_view->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
auto background_color =
color_view->GetNativeTheme()->GetSystemColor(color_id);
@@ -58,16 +59,12 @@ void InsertColorRow(GridLayout* layout,
color_view->SetBackgroundColor(background_color);
color_view->SetBackground(CreateSolidBackground(background_color));
color_view->SetSelectable(true);
-
- layout->StartRow(GridLayout::kFixedSize, 0);
- layout->AddView(std::move(label_view));
- layout->AddView(std::move(color_view));
}
// Returns a view of two columns where the first contains the identifier names
// of ui::NativeTheme::ColorId and the second contains the color.
-std::unique_ptr<View> CreateAllColorsView() {
- auto container = std::make_unique<View>();
+void CreateAllColorsView(ScrollView* scroll_view) {
+ auto* container = scroll_view->SetContents(std::make_unique<View>());
auto* layout = container->SetLayoutManager(std::make_unique<GridLayout>());
auto* column_set = layout->AddColumnSet(0);
column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1.0,
@@ -164,9 +161,22 @@ std::unique_ptr<View> CreateAllColorsView() {
InsertColorRow(layout, COLOR_LABEL_ARGS(kColorId_DefaultIconColor));
// Expands the view to allow for scrolling.
container->SizeToPreferredSize();
- return container;
}
+class AllColorsScrollView : public ScrollView {
+ public:
+ AllColorsScrollView() {
+ constexpr int kMaxHeight = 300;
+ ClipHeightTo(0, kMaxHeight);
+ }
+
+ protected:
+ void OnThemeChanged() override {
+ ScrollView::OnThemeChanged();
+ CreateAllColorsView(this);
+ }
+};
+
} // namespace
NativeThemeExample::NativeThemeExample()
@@ -176,9 +186,7 @@ NativeThemeExample::~NativeThemeExample() = default;
void NativeThemeExample::CreateExampleView(View* container) {
container->SetLayoutManager(std::make_unique<FillLayout>());
- auto scroll_view = std::make_unique<ScrollView>();
- scroll_view->SetContents(CreateAllColorsView());
- container->AddChildView(std::move(scroll_view));
+ container->AddChildView(std::make_unique<AllColorsScrollView>());
}
} // namespace examples
diff --git a/chromium/ui/views/examples/radio_button_example.cc b/chromium/ui/views/examples/radio_button_example.cc
index 76de2e9f78e..fca16b25260 100644
--- a/chromium/ui/views/examples/radio_button_example.cc
+++ b/chromium/ui/views/examples/radio_button_example.cc
@@ -10,6 +10,7 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/controls/button/label_button.h"
diff --git a/chromium/ui/views/examples/scroll_view_example.cc b/chromium/ui/views/examples/scroll_view_example.cc
index 3e4b9c8ae98..a930d971df1 100644
--- a/chromium/ui/views/examples/scroll_view_example.cc
+++ b/chromium/ui/views/examples/scroll_view_example.cc
@@ -8,7 +8,6 @@
#include <utility>
#include "base/macros.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "cc/paint/paint_flags.h"
#include "ui/base/l10n/l10n_util.h"
diff --git a/chromium/ui/views/examples/scroll_view_example.h b/chromium/ui/views/examples/scroll_view_example.h
index 9283b145c94..89fec4333e2 100644
--- a/chromium/ui/views/examples/scroll_view_example.h
+++ b/chromium/ui/views/examples/scroll_view_example.h
@@ -5,7 +5,6 @@
#ifndef UI_VIEWS_EXAMPLES_SCROLL_VIEW_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_SCROLL_VIEW_EXAMPLE_H_
-#include <string>
#include "base/macros.h"
#include "ui/views/controls/scroll_view.h"
diff --git a/chromium/ui/views/examples/tabbed_pane_example.cc b/chromium/ui/views/examples/tabbed_pane_example.cc
index a4b81e06602..573b8d3c98f 100644
--- a/chromium/ui/views/examples/tabbed_pane_example.cc
+++ b/chromium/ui/views/examples/tabbed_pane_example.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "base/format_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/controls/button/label_button.h"
diff --git a/chromium/ui/views/examples/text_example.cc b/chromium/ui/views/examples/text_example.cc
index 678a0f8bd5a..f3438f59f83 100644
--- a/chromium/ui/views/examples/text_example.cc
+++ b/chromium/ui/views/examples/text_example.cc
@@ -83,6 +83,14 @@ class TextExample::TextExampleView : public View {
SchedulePaint();
}
+ protected:
+ void OnThemeChanged() override {
+ View::OnThemeChanged();
+ SetBorder(CreateSolidBorder(
+ 1, GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_UnfocusedBorderColor)));
+ }
+
private:
// The font used for drawing the text.
gfx::FontList font_list_;
@@ -201,9 +209,6 @@ void TextExample::CreateExampleView(View* container) {
layout->StartRow(1, 1);
text_view_ = layout->AddView(std::make_unique<TextExampleView>());
- text_view_->SetBorder(CreateSolidBorder(
- 1, text_view_->GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_UnfocusedBorderColor)));
layout->AddPaddingRow(0, 8);
TextComboboxChanged(); // Sets initial text content.
@@ -247,20 +252,19 @@ void TextExample::TextComboboxChanged() {
text_view_->SetText(u"The quick brown fox jumps over the lazy dog.");
break;
case 1:
- text_view_->SetText(base::ASCIIToUTF16(
- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
- "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim "
- "ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut "
- "aliquip ex ea commodo consequat.\n"
- "Duis aute irure dolor in reprehenderit in voluptate velit esse "
- "cillum dolore eu fugiat nulla pariatur.\n"
- "\n"
- "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui "
- "officia deserunt mollit anim id est laborum."));
+ text_view_->SetText(
+ u"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
+ u"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
+ u"enim ad minim veniam, quis nostrud exercitation ullamco laboris "
+ u"nisi ut aliquip ex ea commodo consequat.\n"
+ u"Duis aute irure dolor in reprehenderit in voluptate velit esse "
+ u"cillum dolore eu fugiat nulla pariatur.\n"
+ u"\n"
+ u"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui "
+ u"officia deserunt mollit anim id est laborum.");
break;
case 2:
- text_view_->SetText(base::ASCIIToUTF16(
- "The quick && &brown fo&x jumps over the lazy dog."));
+ text_view_->SetText(u"The quick && &brown fo&x jumps over the lazy dog.");
break;
case 3:
text_view_->SetText(
diff --git a/chromium/ui/views/examples/text_example.h b/chromium/ui/views/examples/text_example.h
index eb76a150211..27ee0d11e78 100644
--- a/chromium/ui/views/examples/text_example.h
+++ b/chromium/ui/views/examples/text_example.h
@@ -5,8 +5,6 @@
#ifndef UI_VIEWS_EXAMPLES_TEXT_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_TEXT_EXAMPLE_H_
-#include <memory>
-#include <vector>
#include "base/macros.h"
#include "ui/views/examples/example_base.h"
diff --git a/chromium/ui/views/examples/textarea_example.cc b/chromium/ui/views/examples/textarea_example.cc
index cf1ddf2a2bb..d3205e91797 100644
--- a/chromium/ui/views/examples/textarea_example.cc
+++ b/chromium/ui/views/examples/textarea_example.cc
@@ -18,16 +18,16 @@ namespace examples {
TextareaExample::TextareaExample() : ExampleBase("Textarea") {}
void TextareaExample::CreateExampleView(View* container) {
- constexpr char kLongText[] =
- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod"
- " tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
- "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
- "commodo consequat.\nDuis aute irure dolor in reprehenderit in voluptate "
- "velit esse cillum dolore eu fugiat nulla pariatur.\n\nExcepteur sint "
- "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
- "mollit anim id est laborum.";
+ constexpr char16_t kLongText[] =
+ u"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
+ u"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad "
+ u"minim veniam, quis nostrud exercitation ullamco laboris nisi ut "
+ u"aliquip ex ea commodo consequat.\nDuis aute irure dolor in "
+ u"reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla "
+ u"pariatur.\n\nExcepteur sint occaecat cupidatat non proident, sunt in "
+ u"culpa qui officia deserunt mollit anim id est laborum.";
auto textarea = std::make_unique<Textarea>();
- textarea->SetText(base::UTF8ToUTF16(kLongText));
+ textarea->SetText(kLongText);
container->SetLayoutManager(std::make_unique<views::FillLayout>());
container->AddChildView(std::move(textarea));
}
diff --git a/chromium/ui/views/examples/textfield_example.h b/chromium/ui/views/examples/textfield_example.h
index 90a437145f3..f6d35bb727b 100644
--- a/chromium/ui/views/examples/textfield_example.h
+++ b/chromium/ui/views/examples/textfield_example.h
@@ -5,7 +5,6 @@
#ifndef UI_VIEWS_EXAMPLES_TEXTFIELD_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_TEXTFIELD_EXAMPLE_H_
-#include <string>
#include "base/macros.h"
#include "ui/views/controls/textfield/textfield_controller.h"
diff --git a/chromium/ui/views/examples/toggle_button_example.cc b/chromium/ui/views/examples/toggle_button_example.cc
index 66c14f545dc..5d3f080a1fa 100644
--- a/chromium/ui/views/examples/toggle_button_example.cc
+++ b/chromium/ui/views/examples/toggle_button_example.cc
@@ -7,7 +7,6 @@
#include <memory>
#include <utility>
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/insets.h"
diff --git a/chromium/ui/views/focus/focus_manager.cc b/chromium/ui/views/focus/focus_manager.cc
index 0727f741b40..128a3bf946c 100644
--- a/chromium/ui/views/focus/focus_manager.cc
+++ b/chromium/ui/views/focus/focus_manager.cc
@@ -334,6 +334,10 @@ void FocusManager::SetKeyboardAccessible(bool keyboard_accessible) {
AdvanceFocusIfNecessary();
}
+bool FocusManager::IsSettingFocusedView() const {
+ return setting_focused_view_entrance_count > 0;
+}
+
void FocusManager::SetFocusedViewWithReason(View* view,
FocusChangeReason reason) {
if (focused_view_ == view)
@@ -343,9 +347,9 @@ void FocusManager::SetFocusedViewWithReason(View* view,
// Change this to DCHECK once it's resolved.
CHECK(!view || ContainsView(view));
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// TODO(warx): There are some AccessiblePaneViewTest failed on macosx.
- // crbug.com/650859. Remove !defined(OS_APPLE) once that is fixed.
+ // crbug.com/650859. Remove !defined(OS_MAC) once that is fixed.
//
// If the widget isn't active store the focused view and then attempt to
// activate the widget. If activation succeeds |view| will be focused.
@@ -366,6 +370,10 @@ void FocusManager::SetFocusedViewWithReason(View* view,
View* old_focused_view = focused_view_;
focused_view_ = view;
+ base::AutoReset<int> entrance_count_resetter(
+ &setting_focused_view_entrance_count,
+ setting_focused_view_entrance_count + 1);
+
if (old_focused_view) {
old_focused_view->RemoveObserver(this);
old_focused_view->Blur();
@@ -532,7 +540,7 @@ bool FocusManager::ProcessAccelerator(const ui::Accelerator& accelerator) {
if (delegate_ && delegate_->ProcessAccelerator(accelerator))
return true;
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// On MacOS accelerators are processed when a bubble is opened without
// manual redirection to bubble anchor widget. Including redirect on MacOS
// breaks processing accelerators by the bubble itself.
@@ -597,7 +605,7 @@ bool FocusManager::IsFocusable(View* view) const {
DCHECK(view);
// |keyboard_accessible_| is only used on Mac.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
return keyboard_accessible_ ? view->IsAccessibilityFocusable()
: view->IsFocusable();
#else
diff --git a/chromium/ui/views/focus/focus_manager.h b/chromium/ui/views/focus/focus_manager.h
index 6175b8ecd74..eb9939b7040 100644
--- a/chromium/ui/views/focus/focus_manager.h
+++ b/chromium/ui/views/focus/focus_manager.h
@@ -302,6 +302,9 @@ class VIEWS_EXPORT FocusManager : public ViewObserver {
// necessary.
void SetKeyboardAccessible(bool keyboard_accessible);
+ // Checks if a focused view is being set.
+ bool IsSettingFocusedView() const;
+
private:
// Returns the focusable view found in the FocusTraversable specified starting
// at the specified view. This traverses down along the FocusTraversable
@@ -369,6 +372,11 @@ class VIEWS_EXPORT FocusManager : public ViewObserver {
// Whether FocusManager is currently trying to restore a focused view.
bool in_restoring_focused_view_ = false;
+
+ // Count of SetFocusedViewWithReason() in the current stack.
+ // This value is ideally 0 or 1, i.e. no nested focus change.
+ // See crbug.com/1203960.
+ int setting_focused_view_entrance_count = 0;
};
} // namespace views
diff --git a/chromium/ui/views/focus/focus_manager_unittest.cc b/chromium/ui/views/focus/focus_manager_unittest.cc
index a18f119c70a..749d785d75c 100644
--- a/chromium/ui/views/focus/focus_manager_unittest.cc
+++ b/chromium/ui/views/focus/focus_manager_unittest.cc
@@ -765,7 +765,7 @@ TEST_F(FocusManagerTest, StoreFocusedView) {
GetFocusManager()->ClearFocus();
}
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Test that the correct view is restored if full keyboard access is changed.
TEST_F(FocusManagerTest, StoreFocusedViewFullKeyboardAccess) {
View* view1 = new View;
diff --git a/chromium/ui/views/focus/focus_search.cc b/chromium/ui/views/focus/focus_search.cc
index 1443f3ec604..e71e5e2c58b 100644
--- a/chromium/ui/views/focus/focus_search.cc
+++ b/chromium/ui/views/focus/focus_search.cc
@@ -16,7 +16,7 @@ namespace views {
FocusSearch::FocusSearch(View* root, bool cycle, bool accessibility_mode)
: root_(root), cycle_(cycle), accessibility_mode_(accessibility_mode) {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// On Mac, only the keyboard accessibility mode defined in FocusManager is
// used. No special accessibility mode should be applicable for a
// FocusTraversable.
diff --git a/chromium/ui/views/focus/focus_traversal_unittest.cc b/chromium/ui/views/focus/focus_traversal_unittest.cc
index 55f5ca1c2b4..c8c18a1410b 100644
--- a/chromium/ui/views/focus/focus_traversal_unittest.cc
+++ b/chromium/ui/views/focus/focus_traversal_unittest.cc
@@ -625,7 +625,7 @@ TEST_F(FocusTraversalTest, NormalTraversal) {
AdvanceEntireFocusLoop(kTraversalIDs, true);
}
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Test focus traversal with full keyboard access off on Mac.
TEST_F(FocusTraversalTest, NormalTraversalMac) {
GetFocusManager()->SetKeyboardAccessible(false);
@@ -681,7 +681,7 @@ TEST_F(FocusTraversalTest, FullKeyboardToggle) {
EXPECT_EQ(THUMBNAIL_CONTAINER_ID,
GetFocusManager()->GetFocusedView()->GetID());
}
-#endif // OS_APPLE
+#endif // OS_MAC
TEST_F(FocusTraversalTest, TraversalWithNonEnabledViews) {
const int kDisabledIDs[] = {
diff --git a/chromium/ui/views/interaction/OWNERS b/chromium/ui/views/interaction/OWNERS
new file mode 100644
index 00000000000..767e4fce318
--- /dev/null
+++ b/chromium/ui/views/interaction/OWNERS
@@ -0,0 +1 @@
+file://ui/base/interaction/OWNERS
diff --git a/chromium/ui/views/interaction/element_tracker_views.cc b/chromium/ui/views/interaction/element_tracker_views.cc
new file mode 100644
index 00000000000..7757b89265d
--- /dev/null
+++ b/chromium/ui/views/interaction/element_tracker_views.cc
@@ -0,0 +1,256 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/interaction/element_tracker_views.h"
+
+#include <list>
+#include <map>
+
+#include "base/containers/contains.h"
+#include "base/logging.h"
+#include "base/no_destructor.h"
+#include "base/scoped_multi_source_observation.h"
+#include "ui/base/interaction/element_identifier.h"
+#include "ui/base/interaction/element_tracker.h"
+#include "ui/views/view.h"
+#include "ui/views/view_class_properties.h"
+#include "ui/views/view_observer.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_observer.h"
+
+namespace views {
+
+namespace {
+
+// Returns whether the specified view is visible to the user. Takes the view
+// hierarchy and widget into account.
+bool IsViewVisibleToUser(View* view, bool force_widget_visible = false) {
+ const Widget* const widget = view->GetWidget();
+ if (!widget || (!force_widget_visible && !widget->IsVisible()))
+ return false;
+ for (; view; view = view->parent()) {
+ if (!view->GetVisible())
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+TrackedElementViews::TrackedElementViews(View* view,
+ ui::ElementIdentifier identifier,
+ ui::ElementContext context)
+ : TrackedElement(identifier, context), view_(view) {}
+
+TrackedElementViews::~TrackedElementViews() = default;
+
+DEFINE_ELEMENT_TRACKER_METADATA(TrackedElementViews)
+
+class ElementTrackerViews::ElementDataViews : public ViewObserver,
+ public WidgetObserver {
+ public:
+ ElementDataViews(ElementTrackerViews* tracker,
+ ui::ElementIdentifier identifier)
+ : tracker_(tracker), id_(identifier) {}
+ ~ElementDataViews() override = default;
+
+ void AddView(View* view) {
+ if (base::Contains(view_data_lookup_, view))
+ return;
+
+ const auto it = view_data_.insert(view_data_.end(),
+ ViewData(view, GetContextForView(view)));
+ view_data_lookup_.emplace(view, it);
+ view_observer_.AddObservation(view);
+ tracker_->MaybeObserveWidget(view->GetWidget());
+ UpdateVisible(view);
+ }
+
+ void RemoveView(View* view) {
+ const auto it = view_data_lookup_.find(view);
+ if (it == view_data_lookup_.end())
+ return;
+ if (it->second->visible()) {
+ ui::ElementTracker::GetFrameworkDelegate()->NotifyElementHidden(
+ it->second->element.get());
+ }
+ view_observer_.RemoveObservation(view);
+ view_data_.erase(it->second);
+ view_data_lookup_.erase(it);
+ if (view_data_.empty())
+ tracker_->element_data_.erase(id_);
+ }
+
+ TrackedElementViews* GetElementForView(View* view) {
+ const auto it = view_data_lookup_.find(view);
+ DCHECK(it != view_data_lookup_.end());
+ return it->second->element.get();
+ }
+
+ void NotifyViewActivated(View* view) {
+ const auto it = view_data_lookup_.find(view);
+ DCHECK(it != view_data_lookup_.end());
+ if (it->second->visible()) {
+ ui::ElementTracker::GetFrameworkDelegate()->NotifyElementActivated(
+ it->second->element.get());
+ } else {
+ DLOG(WARNING)
+ << "View " << view->GetClassName()
+ << " activated before it was made visible. This probably happened"
+ " during a test; it should never happen in a live browser.";
+ }
+ }
+
+ // When a widget we were previously watching because it had not yet been shown
+ // becomes visible, we manually update the visibility of any view on that
+ // widget.
+ void UpdateViewVisibilityForWidget(Widget* widget) {
+ for (auto& entry : view_data_) {
+ if (!entry.visible() && entry.view->GetWidget() == widget)
+ UpdateVisible(entry.view, /* is_remove */ false,
+ /* force_widget_visible */ true);
+ }
+ }
+
+ private:
+ struct ViewData {
+ explicit ViewData(View* v, ui::ElementContext initial_context)
+ : view(v), context(initial_context) {}
+ bool visible() const { return static_cast<bool>(element); }
+ View* const view;
+ ui::ElementContext context;
+ std::unique_ptr<TrackedElementViews> element;
+ };
+
+ using ViewDataList = std::list<ViewData>;
+
+ // ViewObserver:
+ void OnViewVisibilityChanged(View* observed_view,
+ View* starting_view) override {
+ UpdateVisible(observed_view);
+ }
+
+ void OnViewAddedToWidget(View* observed_view) override {
+ tracker_->MaybeObserveWidget(observed_view->GetWidget());
+ UpdateVisible(observed_view);
+ }
+
+ void OnViewRemovedFromWidget(View* observed_view) override {
+ UpdateVisible(observed_view, /* is_remove */ true);
+ }
+
+ void OnViewIsDeleting(View* observed_view) override {
+ RemoveView(observed_view);
+ }
+
+ void UpdateVisible(View* view,
+ bool is_remove = false,
+ bool force_widget_visible = false) {
+ const auto it = view_data_lookup_.find(view);
+ DCHECK(it != view_data_lookup_.end());
+ ViewData& data = *it->second;
+ const ui::ElementContext old_context = data.context;
+ data.context = is_remove ? ui::ElementContext() : GetContextForView(view);
+ const bool was_visible = data.visible();
+ const bool visible =
+ it->second->context && IsViewVisibleToUser(view, force_widget_visible);
+ if (visible && !was_visible) {
+ data.element =
+ std::make_unique<TrackedElementViews>(view, id_, data.context);
+ ui::ElementTracker::GetFrameworkDelegate()->NotifyElementShown(
+ data.element.get());
+ } else if (!visible && was_visible) {
+ ui::ElementTracker::GetFrameworkDelegate()->NotifyElementHidden(
+ data.element.get());
+ data.element.reset();
+ }
+ DCHECK(!visible || !was_visible || old_context == data.context)
+ << "We should always get a removed-from-widget notification before an "
+ "added-to-widget notification, the context should never change "
+ "while a view is visible.";
+ }
+
+ ElementTrackerViews* const tracker_;
+ const ui::ElementIdentifier id_;
+ ViewDataList view_data_;
+ std::map<View*, ViewDataList::iterator> view_data_lookup_;
+ base::ScopedMultiSourceObservation<View, ViewObserver> view_observer_{this};
+};
+
+ElementTrackerViews::ElementTrackerViews() = default;
+ElementTrackerViews::~ElementTrackerViews() = default;
+
+// static
+ElementTrackerViews* ElementTrackerViews::GetInstance() {
+ static base::NoDestructor<ElementTrackerViews> instance;
+ return instance.get();
+}
+
+// static
+ui::ElementContext ElementTrackerViews::GetContextForView(View* view) {
+ const Widget* const widget = view->GetWidget();
+ return widget ? ui::ElementContext(widget->GetPrimaryWindowWidget())
+ : ui::ElementContext();
+}
+
+TrackedElementViews* ElementTrackerViews::GetElementForView(View* view) {
+ const auto identifier = view->GetProperty(kElementIdentifierKey);
+ if (!identifier)
+ return nullptr;
+ const auto it = element_data_.find(identifier);
+ if (it == element_data_.end())
+ return nullptr;
+ return it->second->GetElementForView(view);
+}
+
+void ElementTrackerViews::RegisterView(ui::ElementIdentifier element_id,
+ View* view) {
+ auto it = element_data_.find(element_id);
+ if (it == element_data_.end()) {
+ it = element_data_
+ .emplace(element_id,
+ std::make_unique<ElementDataViews>(this, element_id))
+ .first;
+ }
+ it->second->AddView(view);
+}
+
+void ElementTrackerViews::UnregisterView(ui::ElementIdentifier element_id,
+ View* view) {
+ DCHECK(view);
+ const auto it = element_data_.find(element_id);
+ DCHECK(it != element_data_.end());
+ it->second->RemoveView(view);
+}
+
+void ElementTrackerViews::NotifyViewActivated(ui::ElementIdentifier element_id,
+ View* view) {
+ DCHECK(view);
+ const auto it = element_data_.find(element_id);
+ DCHECK(it != element_data_.end());
+ it->second->NotifyViewActivated(view);
+}
+
+void ElementTrackerViews::OnWidgetVisibilityChanged(Widget* widget,
+ bool visible) {
+ if (!visible)
+ return;
+ for (auto& entry : element_data_)
+ entry.second->UpdateViewVisibilityForWidget(widget);
+ widget_observer_.RemoveObservation(widget);
+}
+
+void ElementTrackerViews::OnWidgetDestroying(Widget* widget) {
+ widget_observer_.RemoveObservation(widget);
+}
+
+void ElementTrackerViews::MaybeObserveWidget(Widget* widget) {
+ if (!widget || widget->IsVisible() ||
+ widget_observer_.IsObservingSource(widget)) {
+ return;
+ }
+ widget_observer_.AddObservation(widget);
+}
+
+} // namespace views
diff --git a/chromium/ui/views/interaction/element_tracker_views.h b/chromium/ui/views/interaction/element_tracker_views.h
new file mode 100644
index 00000000000..7da7fad8d16
--- /dev/null
+++ b/chromium/ui/views/interaction/element_tracker_views.h
@@ -0,0 +1,97 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_INTERACTION_ELEMENT_TRACKER_VIEWS_H_
+#define UI_VIEWS_INTERACTION_ELEMENT_TRACKER_VIEWS_H_
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "base/scoped_multi_source_observation.h"
+#include "ui/base/interaction/element_identifier.h"
+#include "ui/base/interaction/element_tracker.h"
+#include "ui/views/views_export.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_observer.h"
+
+namespace views {
+
+class View;
+
+// Wraps a View in an ui::TrackedElement.
+class VIEWS_EXPORT TrackedElementViews : public ui::TrackedElement {
+ public:
+ TrackedElementViews(View* view,
+ ui::ElementIdentifier identifier,
+ ui::ElementContext context);
+ ~TrackedElementViews() override;
+
+ View* view() { return view_; }
+ const View* view() const { return view_; }
+
+ DECLARE_ELEMENT_TRACKER_METADATA()
+
+ private:
+ View* const view_;
+};
+
+// Manages TrackedElements associated with View objects.
+class VIEWS_EXPORT ElementTrackerViews : private WidgetObserver {
+ public:
+ using ViewList = std::vector<View*>;
+
+ // Gets the global instance of the tracker for Views.
+ static ElementTrackerViews* GetInstance();
+
+ // Returns the context associated with a particular View. The context will be
+ // the same across all Views associated with a root Widget (such as an
+ // application window).
+ static ui::ElementContext GetContextForView(View* view);
+
+ // Returns the corresponding TrackedElementViews for the given view, or
+ // null if none exists. Note that views which are not visible or not added to
+ // a Widget may not have associated elements, and that the returned object
+ // may be transient.
+ TrackedElementViews* GetElementForView(View* view);
+ const TrackedElementViews* GetElementForView(const View* view) const;
+
+ // Called by View after the kUniqueElementKey property is set.
+ void RegisterView(ui::ElementIdentifier element_id, View* view);
+
+ // Called by View if the kUniqueElementKey property is changed from a non-null
+ // value.
+ void UnregisterView(ui::ElementIdentifier element_id, View* view);
+
+ // Called by a View when the user activates it (clicks a button, selects a
+ // menu item, etc.)
+ void NotifyViewActivated(ui::ElementIdentifier element_id, View* view);
+
+ private:
+ friend class base::NoDestructor<ElementTrackerViews>;
+ class ElementDataViews;
+
+ ElementTrackerViews();
+ ~ElementTrackerViews() override;
+
+ // WidgetObserver:
+ void OnWidgetVisibilityChanged(Widget* widget, bool visible) override;
+ void OnWidgetDestroying(Widget* widget) override;
+
+ // We do not get notified at the View level if a view's widget has not yet
+ // been shown. We need this notification to know when the view is actually
+ // visible to the user. So if a view is added to the trakcer or is added to
+ // a widget, and its widget is not visible, we watch it until it is (or it is
+ // destroyed).
+ void MaybeObserveWidget(Widget* widget);
+
+ std::map<ui::ElementIdentifier, std::unique_ptr<ElementDataViews>>
+ element_data_;
+ base::ScopedMultiSourceObservation<Widget, WidgetObserver> widget_observer_{
+ this};
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_INTERACTION_ELEMENT_TRACKER_VIEWS_H_
diff --git a/chromium/ui/views/interaction/element_tracker_views_unittest.cc b/chromium/ui/views/interaction/element_tracker_views_unittest.cc
new file mode 100644
index 00000000000..d5ba875d15a
--- /dev/null
+++ b/chromium/ui/views/interaction/element_tracker_views_unittest.cc
@@ -0,0 +1,986 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/interaction/element_tracker_views.h"
+
+#include <algorithm>
+#include <iterator>
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/test/bind.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/interaction/element_identifier.h"
+#include "ui/base/interaction/element_tracker.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/event.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/types/event_type.h"
+#include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/button/menu_button.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/view_class_properties.h"
+#include "ui/views/widget/widget.h"
+
+namespace views {
+
+DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTestElementID);
+DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTestElementID2);
+
+namespace {
+
+enum ElementEventType { kShown, kActivated, kHidden };
+
+View* ElementToView(ui::TrackedElement* element) {
+ auto* const view_element = element->AsA<TrackedElementViews>();
+ return view_element ? view_element->view() : nullptr;
+}
+
+// Watches events on the ElementTracker and converts the resulting values back
+// into Views from the original ui::TrackedElement objects. Monitoring
+// callbacks in this way could be done with gmock but the boilerplate would be
+// unfortunately complicated (for some events, the correct parameters are not
+// known until after the call is made, since the call itself might create the
+// element in question). So instead we use this helper class.
+class ElementEventWatcher {
+ public:
+ // Watches the specified `event_type` on Views with identifier `id` in
+ // `context`.
+ ElementEventWatcher(ui::ElementIdentifier id,
+ ui::ElementContext context,
+ ElementEventType event_type)
+ : id_(id) {
+ auto callback = base::BindRepeating(&ElementEventWatcher::OnEvent,
+ base::Unretained(this));
+ ui::ElementTracker* const tracker = ui::ElementTracker::GetElementTracker();
+ switch (event_type) {
+ case ElementEventType::kShown:
+ subscription_ = tracker->AddElementShownCallback(id, context, callback);
+ break;
+ case ElementEventType::kActivated:
+ subscription_ =
+ tracker->AddElementActivatedCallback(id, context, callback);
+ break;
+ case ElementEventType::kHidden:
+ subscription_ =
+ tracker->AddElementHiddenCallback(id, context, callback);
+ break;
+ }
+ }
+
+ int event_count() const { return event_count_; }
+ View* last_view() { return last_view_; }
+
+ private:
+ void OnEvent(ui::TrackedElement* element) {
+ EXPECT_EQ(id_.raw_value(), element->identifier().raw_value());
+ last_view_ = ElementToView(element);
+ ++event_count_;
+ }
+
+ const ui::ElementIdentifier id_;
+ ui::ElementTracker::Subscription subscription_;
+ int event_count_ = 0;
+ View* last_view_ = nullptr;
+};
+
+ElementTrackerViews::ViewList ElementsToViews(
+ ui::ElementTracker::ElementList elements) {
+ ElementTrackerViews::ViewList result;
+ std::transform(elements.begin(), elements.end(), std::back_inserter(result),
+ [](ui::TrackedElement* element) {
+ return element->AsA<TrackedElementViews>()->view();
+ });
+ return result;
+}
+
+} // namespace
+
+class ElementTrackerViewsTest : public ViewsTestBase {
+ public:
+ ElementTrackerViewsTest() = default;
+ ~ElementTrackerViewsTest() override = default;
+
+ void SetUp() override {
+ ViewsTestBase::SetUp();
+ widget_ = CreateWidget();
+ widget_->Show();
+ }
+
+ void TearDown() override {
+ widget_.reset();
+ ViewsTestBase::TearDown();
+ }
+
+ ui::ElementContext context() const {
+ return ui::ElementContext(widget_.get());
+ }
+
+ std::unique_ptr<Widget> CreateWidget() {
+ auto widget = std::make_unique<Widget>();
+ Widget::InitParams params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.bounds = gfx::Rect(0, 0, 650, 650);
+ widget->Init(std::move(params));
+ return widget;
+ }
+
+ protected:
+ std::unique_ptr<Widget> widget_;
+};
+
+TEST_F(ElementTrackerViewsTest, ViewShownByAddingToWidgetSendsNotification) {
+ ElementEventWatcher watcher(kTestElementID, context(),
+ ElementEventType::kShown);
+ auto button_ptr = std::make_unique<LabelButton>();
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_EQ(0, watcher.event_count());
+ auto* const button = widget_->SetContentsView(std::move(button_ptr));
+ EXPECT_EQ(1, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+}
+
+TEST_F(ElementTrackerViewsTest,
+ ViewHiddenByRemovingFromWidgetSendsNotification) {
+ ElementEventWatcher watcher(kTestElementID, context(),
+ ElementEventType::kHidden);
+ auto button_ptr = std::make_unique<LabelButton>();
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_EQ(0, watcher.event_count());
+ auto* const view = widget_->SetContentsView(std::make_unique<View>());
+ auto* const button = view->AddChildView(std::move(button_ptr));
+ EXPECT_EQ(0, watcher.event_count());
+ view->RemoveChildViewT(button);
+ EXPECT_EQ(1, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+}
+
+TEST_F(ElementTrackerViewsTest, ViewShownAfterAddingToWidgetSendsNotification) {
+ ElementEventWatcher watcher(kTestElementID, context(),
+ ElementEventType::kShown);
+ auto button_ptr = std::make_unique<LabelButton>();
+ button_ptr->SetVisible(false);
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto* const button = widget_->SetContentsView(std::move(button_ptr));
+ EXPECT_EQ(0, watcher.event_count());
+ button->SetVisible(true);
+ EXPECT_EQ(1, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+}
+
+TEST_F(ElementTrackerViewsTest,
+ ViewHiddenAfterAddingToWidgetSendsNotification) {
+ ElementEventWatcher watcher(kTestElementID, context(),
+ ElementEventType::kHidden);
+ auto button_ptr = std::make_unique<LabelButton>();
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto* const button = widget_->SetContentsView(std::move(button_ptr));
+ EXPECT_EQ(0, watcher.event_count());
+ button->SetVisible(false);
+ EXPECT_EQ(1, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+}
+
+TEST_F(ElementTrackerViewsTest, SettingIDOnVisibleViewSendsNotification) {
+ ElementEventWatcher watcher(kTestElementID, context(),
+ ElementEventType::kShown);
+ auto button_ptr = std::make_unique<LabelButton>();
+ auto* const button = widget_->SetContentsView(std::move(button_ptr));
+ EXPECT_EQ(0, watcher.event_count());
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_EQ(1, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+}
+
+TEST_F(ElementTrackerViewsTest, ClearingIDOnVisibleViewSendsNotification) {
+ ElementEventWatcher watcher(kTestElementID, context(),
+ ElementEventType::kHidden);
+ auto button_ptr = std::make_unique<LabelButton>();
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto* const button = widget_->SetContentsView(std::move(button_ptr));
+ EXPECT_EQ(0, watcher.event_count());
+ button->ClearProperty(kElementIdentifierKey);
+ EXPECT_EQ(1, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+}
+
+TEST_F(ElementTrackerViewsTest, ChangingIDOnVisibleViewSendsNotification) {
+ ElementEventWatcher shown(kTestElementID, context(),
+ ElementEventType::kShown);
+ ElementEventWatcher hidden(kTestElementID, context(),
+ ElementEventType::kHidden);
+ ElementEventWatcher shown2(kTestElementID2, context(),
+ ElementEventType::kShown);
+ ElementEventWatcher hidden2(kTestElementID2, context(),
+ ElementEventType::kHidden);
+ auto button_ptr = std::make_unique<LabelButton>();
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto* const button = widget_->SetContentsView(std::move(button_ptr));
+ EXPECT_EQ(1, shown.event_count());
+ EXPECT_EQ(0, hidden.event_count());
+ EXPECT_EQ(0, shown2.event_count());
+ EXPECT_EQ(0, hidden2.event_count());
+ button->SetProperty(kElementIdentifierKey, kTestElementID2);
+ EXPECT_EQ(1, shown.event_count());
+ EXPECT_EQ(1, hidden.event_count());
+ EXPECT_EQ(1, shown2.event_count());
+ EXPECT_EQ(0, hidden2.event_count());
+ button->SetVisible(false);
+ EXPECT_EQ(1, shown.event_count());
+ EXPECT_EQ(1, hidden.event_count());
+ EXPECT_EQ(1, shown2.event_count());
+ EXPECT_EQ(1, hidden2.event_count());
+}
+
+TEST_F(ElementTrackerViewsTest, ButtonPressedSendsActivatedSignal) {
+ ElementEventWatcher watcher(kTestElementID, context(),
+ ElementEventType::kActivated);
+ auto button_ptr = std::make_unique<LabelButton>();
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_EQ(0, watcher.event_count());
+ auto* const button = widget_->SetContentsView(std::move(button_ptr));
+ EXPECT_EQ(0, watcher.event_count());
+
+ // Test mouse click.
+ constexpr gfx::Point kPressPoint(10, 10);
+ button->OnMousePressed(ui::MouseEvent(
+ ui::ET_MOUSE_PRESSED, kPressPoint, kPressPoint, ui::EventTimeForNow(),
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
+ button->OnMouseReleased(ui::MouseEvent(
+ ui::ET_MOUSE_PRESSED, kPressPoint, kPressPoint, ui::EventTimeForNow(),
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
+ EXPECT_EQ(1, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+
+ // Test accessible keypress.
+ button->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ button->OnKeyReleased(ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ EXPECT_EQ(2, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+}
+
+TEST_F(ElementTrackerViewsTest, MenuButtonPressedSendsActivatedSignal) {
+ ElementEventWatcher watcher(kTestElementID, context(),
+ ElementEventType::kActivated);
+ size_t pressed_count = 0;
+ auto button_ptr = std::make_unique<MenuButton>(
+ base::BindLambdaForTesting([&](const ui::Event&) { ++pressed_count; }));
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_EQ(0, watcher.event_count());
+ auto* const button = widget_->SetContentsView(std::move(button_ptr));
+ EXPECT_EQ(0, watcher.event_count());
+
+ // Test mouse click.
+ constexpr gfx::Point kPressPoint(10, 10);
+ button->OnMousePressed(ui::MouseEvent(
+ ui::ET_MOUSE_PRESSED, kPressPoint, kPressPoint, ui::EventTimeForNow(),
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
+ EXPECT_EQ(1U, pressed_count);
+ EXPECT_EQ(1, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+
+ // Test accessible keypress.
+ button->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ button->OnKeyReleased(ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ EXPECT_EQ(2U, pressed_count);
+ EXPECT_EQ(2, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+}
+
+TEST_F(ElementTrackerViewsTest, HandlesCreateWithTheSameIDMultipleTimes) {
+ ElementEventWatcher watcher(kTestElementID, context(),
+ ElementEventType::kShown);
+
+ auto button_ptr = std::make_unique<LabelButton>();
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto* const button = widget_->SetContentsView(std::move(button_ptr));
+ EXPECT_EQ(1, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+ widget_->GetRootView()->RemoveChildViewT(button);
+
+ button_ptr = std::make_unique<LabelButton>();
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto* const button2 = widget_->SetContentsView(std::move(button_ptr));
+ EXPECT_EQ(2, watcher.event_count());
+ EXPECT_EQ(button2, watcher.last_view());
+}
+
+TEST_F(ElementTrackerViewsTest, HandlesReshowingTheSameView) {
+ ElementEventWatcher watcher(kTestElementID, context(),
+ ElementEventType::kShown);
+
+ auto button_ptr = std::make_unique<LabelButton>();
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto* const button = widget_->SetContentsView(std::move(button_ptr));
+ EXPECT_EQ(1, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+
+ button->SetVisible(false);
+ EXPECT_EQ(1, watcher.event_count());
+
+ button->SetVisible(true);
+ EXPECT_EQ(2, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+}
+
+TEST_F(ElementTrackerViewsTest, CanLookupViewByIdentifier) {
+ // Should initially be null.
+ EXPECT_EQ(nullptr, ui::ElementTracker::GetElementTracker()->GetUniqueElement(
+ kTestElementID, context()));
+
+ auto button_ptr = std::make_unique<LabelButton>();
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+
+ // Because the button is not attached to a widget, it will not be returned for
+ // the current context (which is associated with a widget).
+ EXPECT_EQ(nullptr, ui::ElementTracker::GetElementTracker()->GetUniqueElement(
+ kTestElementID, context()));
+
+ // Adding the view to a widget will cause it to be returned in the current
+ // context.
+ auto* button = widget_->SetContentsView(std::move(button_ptr));
+ EXPECT_EQ(
+ button,
+ ElementToView(ui::ElementTracker::GetElementTracker()->GetUniqueElement(
+ kTestElementID, context())));
+
+ // Once the view is destroyed, however, the result should be null again.
+ widget_->GetRootView()->RemoveChildViewT(button);
+ EXPECT_EQ(nullptr, ui::ElementTracker::GetElementTracker()->GetUniqueElement(
+ kTestElementID, context()));
+
+ // Create a second view with the same ID and verify that the new pointer is
+ // returned.
+ button = widget_->SetContentsView(std::make_unique<LabelButton>());
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_EQ(
+ button,
+ ElementToView(ui::ElementTracker::GetElementTracker()->GetUniqueElement(
+ kTestElementID, context())));
+
+ // When the view is deleted, the result once again becomes null.
+ widget_->GetRootView()->RemoveChildViewT(button);
+ EXPECT_EQ(nullptr, ui::ElementTracker::GetElementTracker()->GetUniqueElement(
+ kTestElementID, context()));
+}
+
+TEST_F(ElementTrackerViewsTest, CanLookUpElementByIdentifier) {
+ // Should initially be null.
+ EXPECT_EQ(nullptr, ui::ElementTracker::GetElementTracker()->GetUniqueElement(
+ kTestElementID, context()));
+
+ auto button_ptr = std::make_unique<LabelButton>();
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+
+ // Because the button is not attached to a widget, it will not be returned for
+ // the current context (which is associated with a widget).
+ EXPECT_EQ(nullptr, ui::ElementTracker::GetElementTracker()->GetUniqueElement(
+ kTestElementID, context()));
+
+ // Adding the view to a widget will cause it to be returned in the current
+ // context.
+ auto* button = widget_->SetContentsView(std::move(button_ptr));
+ EXPECT_EQ(button, ui::ElementTracker::GetElementTracker()
+ ->GetUniqueElement(kTestElementID, context())
+ ->AsA<TrackedElementViews>()
+ ->view());
+
+ // Hiding the view will make the view not findable through the base element
+ // tracker.
+ button->SetVisible(false);
+ EXPECT_EQ(nullptr, ui::ElementTracker::GetElementTracker()->GetUniqueElement(
+ kTestElementID, context()));
+
+ // Showing the view will bring it back.
+ button->SetVisible(true);
+ EXPECT_EQ(button, ui::ElementTracker::GetElementTracker()
+ ->GetUniqueElement(kTestElementID, context())
+ ->AsA<TrackedElementViews>()
+ ->view());
+
+ // Once the view is destroyed, however, the result should be null again.
+ widget_->GetRootView()->RemoveChildViewT(button);
+ EXPECT_EQ(nullptr, ui::ElementTracker::GetElementTracker()->GetUniqueElement(
+ kTestElementID, context()));
+
+ // Create a second view with the same ID and verify that the new pointer is
+ // returned.
+ button = widget_->SetContentsView(std::make_unique<LabelButton>());
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_EQ(button, ui::ElementTracker::GetElementTracker()
+ ->GetUniqueElement(kTestElementID, context())
+ ->AsA<TrackedElementViews>()
+ ->view());
+
+ // When the view is deleted, the result once again becomes null.
+ widget_->GetRootView()->RemoveChildViewT(button);
+ EXPECT_EQ(nullptr, ui::ElementTracker::GetElementTracker()->GetUniqueElement(
+ kTestElementID, context()));
+}
+
+TEST_F(ElementTrackerViewsTest, CanGetFirstViewByIdentifier) {
+ // Should initially be null.
+ EXPECT_EQ(nullptr,
+ ui::ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kTestElementID, context()));
+
+ // Add two buttons with the same identifier.
+ auto* contents = widget_->SetContentsView(std::make_unique<View>());
+ auto* button = contents->AddChildView(std::make_unique<LabelButton>());
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto* button2 = contents->AddChildView(std::make_unique<LabelButton>());
+ button2->SetProperty(kElementIdentifierKey, kTestElementID);
+
+ // The first button should be returned.
+ EXPECT_EQ(
+ button,
+ ElementToView(
+ ui::ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kTestElementID, context())));
+
+ // Remove the first button. The second should now be returned.
+ contents->RemoveChildViewT(button);
+ EXPECT_EQ(
+ button2,
+ ElementToView(
+ ui::ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kTestElementID, context())));
+
+ // Remove the second button. There will be no matching views.
+ contents->RemoveChildViewT(button2);
+ EXPECT_EQ(nullptr,
+ ui::ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kTestElementID, context()));
+}
+
+TEST_F(ElementTrackerViewsTest, CanGetFirstElementByIdentifier) {
+ // Should initially be null.
+ EXPECT_EQ(nullptr,
+ ui::ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kTestElementID, context()));
+
+ // Add two buttons with the same identifier.
+ auto* contents = widget_->SetContentsView(std::make_unique<View>());
+ auto* button = contents->AddChildView(std::make_unique<LabelButton>());
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto* button2 = contents->AddChildView(std::make_unique<LabelButton>());
+ button2->SetProperty(kElementIdentifierKey, kTestElementID);
+
+ // The first button should be returned.
+ EXPECT_EQ(button, ui::ElementTracker::GetElementTracker()
+ ->GetFirstMatchingElement(kTestElementID, context())
+ ->AsA<TrackedElementViews>()
+ ->view());
+
+ // Set the buttons' visibility; this should change whether the element tracker
+ // sees them.
+ button->SetVisible(false);
+ EXPECT_EQ(button2, ui::ElementTracker::GetElementTracker()
+ ->GetFirstMatchingElement(kTestElementID, context())
+ ->AsA<TrackedElementViews>()
+ ->view());
+ button2->SetVisible(false);
+ EXPECT_EQ(nullptr,
+ ui::ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kTestElementID, context()));
+
+ // The second button is now the first to become visible in the base tracker.
+ button2->SetVisible(true);
+ button->SetVisible(true);
+ EXPECT_EQ(button2, ui::ElementTracker::GetElementTracker()
+ ->GetFirstMatchingElement(kTestElementID, context())
+ ->AsA<TrackedElementViews>()
+ ->view());
+
+ // Remove the second button. The first should now be returned.
+ contents->RemoveChildViewT(button2);
+ EXPECT_EQ(button, ui::ElementTracker::GetElementTracker()
+ ->GetFirstMatchingElement(kTestElementID, context())
+ ->AsA<TrackedElementViews>()
+ ->view());
+
+ // Remove the first button. There will be no matching views.
+ contents->RemoveChildViewT(button);
+ EXPECT_EQ(nullptr,
+ ui::ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ kTestElementID, context()));
+}
+
+TEST_F(ElementTrackerViewsTest, CanGetAllViewsByIdentifier) {
+ // Should initially be empty.
+ ElementTrackerViews::ViewList expected;
+ EXPECT_EQ(expected,
+ ElementsToViews(
+ ui::ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kTestElementID, context())));
+
+ // Add two buttons with the same identifier.
+ auto* contents = widget_->SetContentsView(std::make_unique<View>());
+ auto* button = contents->AddChildView(std::make_unique<LabelButton>());
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto* button2 = contents->AddChildView(std::make_unique<LabelButton>());
+ button2->SetProperty(kElementIdentifierKey, kTestElementID);
+
+ // All buttons should be returned.
+ expected = ElementTrackerViews::ViewList{button, button2};
+ EXPECT_EQ(expected,
+ ElementsToViews(
+ ui::ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kTestElementID, context())));
+
+ // Remove the first button. The second should now be returned.
+ contents->RemoveChildViewT(button);
+ expected = ElementTrackerViews::ViewList{button2};
+ EXPECT_EQ(expected,
+ ElementsToViews(
+ ui::ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kTestElementID, context())));
+
+ // Remove the second button. There will be no matching views.
+ contents->RemoveChildViewT(button2);
+ expected.clear();
+ EXPECT_EQ(expected,
+ ElementsToViews(
+ ui::ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kTestElementID, context())));
+}
+
+TEST_F(ElementTrackerViewsTest, CanGetAllElementsByIdentifier) {
+ // Should initially be empty.
+ ElementTrackerViews::ViewList expected;
+ EXPECT_EQ(expected,
+ ElementsToViews(
+ ui::ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kTestElementID, context())));
+
+ // Add two buttons with the same identifier.
+ auto* contents = widget_->SetContentsView(std::make_unique<View>());
+ auto* button = contents->AddChildView(std::make_unique<LabelButton>());
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto* button2 = contents->AddChildView(std::make_unique<LabelButton>());
+ button2->SetProperty(kElementIdentifierKey, kTestElementID);
+
+ // Both buttons should be returned.
+ expected = ElementTrackerViews::ViewList{button, button2};
+ EXPECT_EQ(expected,
+ ElementsToViews(
+ ui::ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kTestElementID, context())));
+
+ // Set the buttons' visibility; this should change whether the element tracker
+ // sees them.
+ button->SetVisible(false);
+ expected = ElementTrackerViews::ViewList{button2};
+ EXPECT_EQ(expected,
+ ElementsToViews(
+ ui::ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kTestElementID, context())));
+ button2->SetVisible(false);
+ expected.clear();
+ EXPECT_EQ(expected,
+ ElementsToViews(
+ ui::ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kTestElementID, context())));
+
+ // The second button is now the first to become visible in the base tracker.
+ button2->SetVisible(true);
+ button->SetVisible(true);
+ expected = ElementTrackerViews::ViewList{button2, button};
+ EXPECT_EQ(expected,
+ ElementsToViews(
+ ui::ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kTestElementID, context())));
+
+ // Remove the second button. Only the first should now be returned.
+ contents->RemoveChildViewT(button2);
+ expected = ElementTrackerViews::ViewList{button};
+ EXPECT_EQ(expected,
+ ElementsToViews(
+ ui::ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kTestElementID, context())));
+
+ // Remove the first button. There will be no matching views.
+ contents->RemoveChildViewT(button);
+ expected.clear();
+ EXPECT_EQ(expected,
+ ElementsToViews(
+ ui::ElementTracker::GetElementTracker()->GetAllMatchingElements(
+ kTestElementID, context())));
+}
+
+TEST_F(ElementTrackerViewsTest, CanGetVisibilityByIdentifier) {
+ // Should initially be false.
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+
+ auto button_ptr = std::make_unique<LabelButton>();
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+
+ // Because the button is not attached to a widget, it will not be counted as
+ // visible.
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+
+ // Adding the view to a widget will cause it to be counted as visible.
+ auto* button = widget_->SetContentsView(std::move(button_ptr));
+ EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+
+ // Once the view is destroyed, however, the result should be false again.
+ widget_->GetRootView()->RemoveChildViewT(button);
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+
+ // Create a second view with the same ID but start it as not visible.
+ button = widget_->SetContentsView(std::make_unique<LabelButton>());
+ button->SetVisible(false);
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+
+ // Now set the visibility to true.
+ button->SetVisible(true);
+ EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+
+ // Set visibility to false again.
+ button->SetVisible(false);
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+}
+
+TEST_F(ElementTrackerViewsTest, CanLookupElementByView) {
+ // Should initially be false.
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+
+ auto button_ptr = std::make_unique<LabelButton>();
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+
+ // The button is not attached to a widget so there is no associated element
+ // object.
+ EXPECT_EQ(nullptr, ElementTrackerViews::GetInstance()->GetElementForView(
+ button_ptr.get()));
+
+ // Adding the (visible) view to a widget will cause an element to be
+ // generated.
+ auto* button = widget_->SetContentsView(std::move(button_ptr));
+ EXPECT_NE(nullptr,
+ ElementTrackerViews::GetInstance()->GetElementForView(button));
+
+ // Once the view is destroyed, however, the result should be false again.
+ widget_->GetRootView()->RemoveChildView(button);
+ EXPECT_EQ(nullptr,
+ ElementTrackerViews::GetInstance()->GetElementForView(button));
+ delete button;
+
+ // Create a second view with the same ID but start it as not visible.
+ button = widget_->SetContentsView(std::make_unique<LabelButton>());
+ button->SetVisible(false);
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_EQ(nullptr,
+ ElementTrackerViews::GetInstance()->GetElementForView(button));
+
+ // Now set the visibility to true.
+ button->SetVisible(true);
+ EXPECT_NE(nullptr,
+ ElementTrackerViews::GetInstance()->GetElementForView(button));
+
+ // Set visibility to false again.
+ button->SetVisible(false);
+ EXPECT_EQ(nullptr,
+ ElementTrackerViews::GetInstance()->GetElementForView(button));
+}
+
+// The following tests ensure conformity with the different platforms' Views
+// implementation to ensure that Views are reported as visible to the user at
+// the correct times, including during Widget close/delete.
+
+TEST_F(ElementTrackerViewsTest, ParentNotVisibleWhenAddedToWidget) {
+ View* const contents = widget_->SetContentsView(std::make_unique<View>());
+ contents->SetVisible(false);
+ auto child_ptr = std::make_unique<View>();
+ child_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+ contents->AddChildView(std::move(child_ptr));
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+ contents->SetVisible(true);
+ EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+}
+
+TEST_F(ElementTrackerViewsTest, WidgetNotVisibleWhenAddedToWidget) {
+ View* const contents = widget_->SetContentsView(std::make_unique<View>());
+ widget_->Hide();
+ auto child_ptr = std::make_unique<View>();
+ child_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+ contents->AddChildView(std::move(child_ptr));
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+ widget_->Show();
+ EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+}
+
+TEST_F(ElementTrackerViewsTest, ParentHidden) {
+ View* const contents = widget_->SetContentsView(std::make_unique<View>());
+ auto child_ptr = std::make_unique<View>();
+ child_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+ contents->AddChildView(std::move(child_ptr));
+ EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+ contents->SetVisible(false);
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+}
+
+TEST_F(ElementTrackerViewsTest, WidgetHidden) {
+ View* const contents = widget_->SetContentsView(std::make_unique<View>());
+ auto child_ptr = std::make_unique<View>();
+ child_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+ contents->AddChildView(std::move(child_ptr));
+ EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+ widget_->Hide();
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+}
+
+TEST_F(ElementTrackerViewsTest, WidgetClosed) {
+ View* const contents = widget_->SetContentsView(std::make_unique<View>());
+ auto child_ptr = std::make_unique<View>();
+ child_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+ contents->AddChildView(std::move(child_ptr));
+ EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+ widget_->Close();
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+}
+
+TEST_F(ElementTrackerViewsTest, WidgetDestroyed) {
+ View* const contents = widget_->SetContentsView(std::make_unique<View>());
+ auto child_ptr = std::make_unique<View>();
+ child_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+ contents->AddChildView(std::move(child_ptr));
+ EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+ widget_.reset();
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context()));
+}
+
+TEST_F(ElementTrackerViewsTest, WidgetShownAfterAdd) {
+ auto widget = CreateWidget();
+ View* const contents = widget->SetContentsView(std::make_unique<View>());
+ const ui::ElementContext context =
+ ElementTrackerViews::GetContextForView(contents);
+ auto child_ptr = std::make_unique<View>();
+ child_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context));
+ contents->AddChildView(std::move(child_ptr));
+ EXPECT_FALSE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context));
+ widget->Show();
+ EXPECT_TRUE(ui::ElementTracker::GetElementTracker()->IsElementVisible(
+ kTestElementID, context));
+}
+
+// Verifies that Views on different Widgets are differentiated by the system.
+class ElementTrackerTwoWidgetTest : public ElementTrackerViewsTest {
+ public:
+ ElementTrackerTwoWidgetTest() = default;
+ ~ElementTrackerTwoWidgetTest() override = default;
+
+ void SetUp() override {
+ ElementTrackerViewsTest::SetUp();
+
+ widget2_ = CreateWidget();
+ widget2_->Show();
+ }
+
+ void TearDown() override {
+ widget2_.reset();
+ ElementTrackerViewsTest::TearDown();
+ }
+
+ ui::ElementContext context2() const {
+ return ui::ElementContext(widget2_.get());
+ }
+
+ protected:
+ std::unique_ptr<Widget> widget2_;
+};
+
+TEST_F(ElementTrackerTwoWidgetTest, ViewMovedToDifferentWidgetGeneratesEvents) {
+ ElementEventWatcher shown(kTestElementID, context(),
+ ElementEventType::kShown);
+ ElementEventWatcher hidden(kTestElementID, context(),
+ ElementEventType::kHidden);
+ ElementEventWatcher shown2(kTestElementID, context2(),
+ ElementEventType::kShown);
+ ElementEventWatcher hidden2(kTestElementID, context2(),
+ ElementEventType::kHidden);
+ auto* const view = widget_->SetContentsView(std::make_unique<View>());
+ auto* const view2 = widget2_->SetContentsView(std::make_unique<View>());
+ auto button_ptr = std::make_unique<LabelButton>();
+ button_ptr->SetProperty(kElementIdentifierKey, kTestElementID);
+ // Add to first widget.
+ auto* const button = view->AddChildView(std::move(button_ptr));
+ EXPECT_EQ(1, shown.event_count());
+ EXPECT_EQ(0, hidden.event_count());
+ EXPECT_EQ(0, shown2.event_count());
+ EXPECT_EQ(0, hidden2.event_count());
+ // Move to second widget.
+ view2->AddChildView(button);
+ EXPECT_EQ(1, shown.event_count());
+ EXPECT_EQ(1, hidden.event_count());
+ EXPECT_EQ(1, shown2.event_count());
+ EXPECT_EQ(0, hidden2.event_count());
+ // Destroy the second widget.
+ widget2_.reset();
+ EXPECT_EQ(1, shown.event_count());
+ EXPECT_EQ(1, hidden.event_count());
+ EXPECT_EQ(1, shown2.event_count());
+ EXPECT_EQ(1, hidden2.event_count());
+}
+
+TEST_F(ElementTrackerTwoWidgetTest, CanLookUpViewsOnMultipleWidgets) {
+ auto* button = widget_->SetContentsView(std::make_unique<LabelButton>());
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto* button2 = widget2_->SetContentsView(std::make_unique<LabelButton>());
+ button2->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_EQ(
+ button,
+ ElementToView(ui::ElementTracker::GetElementTracker()->GetUniqueElement(
+ kTestElementID, context())));
+ EXPECT_EQ(
+ button2,
+ ElementToView(ui::ElementTracker::GetElementTracker()->GetUniqueElement(
+ kTestElementID, context2())));
+ widget_->GetRootView()->RemoveChildViewT(button);
+ widget2_->GetRootView()->RemoveChildViewT(button2);
+ EXPECT_EQ(nullptr, ui::ElementTracker::GetElementTracker()->GetUniqueElement(
+ kTestElementID, context()));
+ EXPECT_EQ(nullptr, ui::ElementTracker::GetElementTracker()->GetUniqueElement(
+ kTestElementID, context2()));
+}
+
+TEST_F(ElementTrackerTwoWidgetTest,
+ MakingViewsVisibleSendsNotificationsToCorrectListeners) {
+ ElementEventWatcher watcher(kTestElementID, context(),
+ ElementEventType::kShown);
+ ElementEventWatcher watcher2(kTestElementID, context2(),
+ ElementEventType::kShown);
+ auto* const button =
+ widget_->SetContentsView(std::make_unique<LabelButton>());
+ auto* const button2 =
+ widget2_->SetContentsView(std::make_unique<LabelButton>());
+ EXPECT_EQ(0, watcher.event_count());
+ EXPECT_EQ(0, watcher2.event_count());
+
+ // Each listener should be notified when the appropriate button is shown.
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_EQ(1, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+ EXPECT_EQ(0, watcher2.event_count());
+ button2->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_EQ(1, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+ EXPECT_EQ(1, watcher2.event_count());
+ EXPECT_EQ(button2, watcher2.last_view());
+
+ // Each listener should be notified when the appropriate button is shown.
+ button->SetVisible(false);
+ button->SetVisible(true);
+ EXPECT_EQ(2, watcher.event_count());
+ EXPECT_EQ(1, watcher2.event_count());
+
+ // Hide and show several times to verify events are still set.
+ button->SetVisible(false);
+ button2->SetVisible(false);
+ EXPECT_EQ(2, watcher.event_count());
+ EXPECT_EQ(1, watcher2.event_count());
+ button2->SetVisible(true);
+ EXPECT_EQ(2, watcher.event_count());
+ EXPECT_EQ(2, watcher2.event_count());
+ button->SetVisible(true);
+ EXPECT_EQ(3, watcher.event_count());
+ EXPECT_EQ(2, watcher2.event_count());
+}
+
+TEST_F(ElementTrackerTwoWidgetTest,
+ ButtonPressedSendsNotificationsToCorrectListeners) {
+ ElementEventWatcher watcher(kTestElementID, context(),
+ ElementEventType::kActivated);
+ ElementEventWatcher watcher2(kTestElementID, context2(),
+ ElementEventType::kActivated);
+ auto* const button =
+ widget_->SetContentsView(std::make_unique<LabelButton>());
+ auto* const button2 =
+ widget2_->SetContentsView(std::make_unique<LabelButton>());
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ button2->SetProperty(kElementIdentifierKey, kTestElementID);
+ EXPECT_EQ(0, watcher.event_count());
+ EXPECT_EQ(0, watcher2.event_count());
+
+ // Test mouse click.
+ constexpr gfx::Point kPressPoint(10, 10);
+ button->OnMousePressed(ui::MouseEvent(
+ ui::ET_MOUSE_PRESSED, kPressPoint, kPressPoint, ui::EventTimeForNow(),
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
+ button->OnMouseReleased(ui::MouseEvent(
+ ui::ET_MOUSE_PRESSED, kPressPoint, kPressPoint, ui::EventTimeForNow(),
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
+ EXPECT_EQ(1, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+ EXPECT_EQ(0, watcher2.event_count());
+
+ // Click other button.
+ button2->OnMousePressed(ui::MouseEvent(
+ ui::ET_MOUSE_PRESSED, kPressPoint, kPressPoint, ui::EventTimeForNow(),
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
+ button2->OnMouseReleased(ui::MouseEvent(
+ ui::ET_MOUSE_PRESSED, kPressPoint, kPressPoint, ui::EventTimeForNow(),
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
+ EXPECT_EQ(1, watcher.event_count());
+ EXPECT_EQ(button, watcher.last_view());
+ EXPECT_EQ(1, watcher2.event_count());
+ EXPECT_EQ(button2, watcher2.last_view());
+
+ // Test accessible keypress.
+ button2->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ button2->OnKeyReleased(ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ EXPECT_EQ(1, watcher.event_count());
+ EXPECT_EQ(2, watcher2.event_count());
+ button->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ button->OnKeyReleased(ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ EXPECT_EQ(2, watcher.event_count());
+ EXPECT_EQ(2, watcher2.event_count());
+}
+
+} // namespace views
diff --git a/chromium/ui/views/interaction/interaction_sequence_views.cc b/chromium/ui/views/interaction/interaction_sequence_views.cc
new file mode 100644
index 00000000000..99323124e8e
--- /dev/null
+++ b/chromium/ui/views/interaction/interaction_sequence_views.cc
@@ -0,0 +1,44 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/interaction/interaction_sequence_views.h"
+
+#include <utility>
+
+#include "ui/base/interaction/element_identifier.h"
+#include "ui/views/interaction/element_tracker_views.h"
+#include "ui/views/view.h"
+#include "ui/views/view_class_properties.h"
+
+namespace views {
+
+// static
+std::unique_ptr<ui::InteractionSequence::Step>
+InteractionSequenceViews::WithInitialView(
+ View* view,
+ ui::InteractionSequence::StepCallback start_callback,
+ ui::InteractionSequence::StepCallback end_callback) {
+ // If there's already an element associated with this view, then explicitly
+ // key off of that element.
+ auto* const element =
+ ElementTrackerViews::GetInstance()->GetElementForView(view);
+ if (element)
+ return ui::InteractionSequence::WithInitialElement(
+ element, std::move(start_callback), std::move(end_callback));
+
+ // Otherwise, use the element's identifier and context.
+ ui::ElementContext context = ElementTrackerViews::GetContextForView(view);
+ ui::ElementIdentifier identifier = view->GetProperty(kElementIdentifierKey);
+ return ui::InteractionSequence::StepBuilder()
+ .SetContext(context)
+ .SetElementID(identifier)
+ .SetType(ui::InteractionSequence::StepType::kShown)
+ .SetMustBeVisibleAtStart(true)
+ .SetMustRemainVisible(true)
+ .SetStartCallback(std::move(start_callback))
+ .SetEndCallback(std::move(end_callback))
+ .Build();
+}
+
+} // namespace views
diff --git a/chromium/ui/views/interaction/interaction_sequence_views.h b/chromium/ui/views/interaction/interaction_sequence_views.h
new file mode 100644
index 00000000000..4442b3825bd
--- /dev/null
+++ b/chromium/ui/views/interaction/interaction_sequence_views.h
@@ -0,0 +1,33 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_INTERACTION_INTERACTION_SEQUENCE_VIEWS_H_
+#define UI_VIEWS_INTERACTION_INTERACTION_SEQUENCE_VIEWS_H_
+
+#include <memory>
+
+#include "ui/base/interaction/interaction_sequence.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+class View;
+
+// Provides utility methods for using ui::InteractionsSequence with Views.
+class VIEWS_EXPORT InteractionSequenceViews {
+ public:
+ // Not constructible.
+ InteractionSequenceViews() = delete;
+
+ static std::unique_ptr<ui::InteractionSequence::Step> WithInitialView(
+ View* view,
+ ui::InteractionSequence::StepCallback start_callback =
+ ui::InteractionSequence::StepCallback(),
+ ui::InteractionSequence::StepCallback end_callback =
+ ui::InteractionSequence::StepCallback());
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_INTERACTION_INTERACTION_SEQUENCE_VIEWS_H_
diff --git a/chromium/ui/views/interaction/interaction_sequence_views_unittest.cc b/chromium/ui/views/interaction/interaction_sequence_views_unittest.cc
new file mode 100644
index 00000000000..38275086e8c
--- /dev/null
+++ b/chromium/ui/views/interaction/interaction_sequence_views_unittest.cc
@@ -0,0 +1,618 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/interaction/interaction_sequence_views.h"
+
+// This suite contains tests which integrate the functionality of
+// ui::InteractionSequence with Views elements like Widgets and menus.
+// Similar suites should be created for other platforms.
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/test/mock_callback.h"
+#include "build/build_config.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/interaction/element_tracker.h"
+#include "ui/base/interaction/expect_call_in_scope.h"
+#include "ui/base/interaction/interaction_sequence.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/base/ui_base_types.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/event.h"
+#include "ui/events/test/event_generator.h"
+#include "ui/events/types/event_type.h"
+#include "ui/views/bubble/bubble_dialog_delegate_view.h"
+#include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/button/menu_button.h"
+#include "ui/views/controls/menu/menu_item_view.h"
+#include "ui/views/controls/menu/menu_runner.h"
+#include "ui/views/interaction/element_tracker_views.h"
+#include "ui/views/layout/flex_layout.h"
+#include "ui/views/layout/flex_layout_types.h"
+#include "ui/views/layout/layout_types.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/test/widget_test.h"
+#include "ui/views/view.h"
+#include "ui/views/view_class_properties.h"
+#include "ui/views/widget/widget.h"
+
+namespace views {
+
+namespace {
+
+DECLARE_ELEMENT_IDENTIFIER_VALUE(kContentsElementID);
+DECLARE_ELEMENT_IDENTIFIER_VALUE(kTestElementID);
+DECLARE_ELEMENT_IDENTIFIER_VALUE(kTestElementID2);
+DECLARE_ELEMENT_IDENTIFIER_VALUE(kTestElementID3);
+DEFINE_ELEMENT_IDENTIFIER_VALUE(kContentsElementID);
+DEFINE_ELEMENT_IDENTIFIER_VALUE(kTestElementID);
+DEFINE_ELEMENT_IDENTIFIER_VALUE(kTestElementID2);
+DEFINE_ELEMENT_IDENTIFIER_VALUE(kTestElementID3);
+const char16_t kMenuItem1[] = u"Menu item";
+const char16_t kMenuItem2[] = u"Menu item 2";
+constexpr int kMenuID1 = 1;
+constexpr int kMenuID2 = 2;
+
+} // namespace
+
+class InteractionSequenceViewsTest : public ViewsTestBase {
+ public:
+ InteractionSequenceViewsTest() = default;
+ ~InteractionSequenceViewsTest() override = default;
+
+ static View* ElementToView(ui::TrackedElement* element) {
+ return element ? element->AsA<TrackedElementViews>()->view() : nullptr;
+ }
+
+ static ui::TrackedElement* ViewToElement(View* view) {
+ return view ? ElementTrackerViews::GetInstance()->GetElementForView(view)
+ : nullptr;
+ }
+
+ std::unique_ptr<Widget> CreateWidget() {
+ auto widget = std::make_unique<Widget>();
+ Widget::InitParams params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.bounds = gfx::Rect(0, 0, 650, 650);
+ widget->Init(std::move(params));
+ auto* contents = widget->SetContentsView(std::make_unique<View>());
+ auto* layout = contents->SetLayoutManager(std::make_unique<FlexLayout>());
+ layout->SetOrientation(LayoutOrientation::kHorizontal);
+ layout->SetDefault(kFlexBehaviorKey,
+ FlexSpecification(MinimumFlexSizeRule::kPreferred,
+ MaximumFlexSizeRule::kUnbounded));
+ test::WidgetVisibleWaiter visible_waiter(widget.get());
+ widget->Show();
+ visible_waiter.Wait();
+ return widget;
+ }
+
+ void ShowMenu(ui::ElementIdentifier id) {
+ CreateAndRunMenu(id);
+
+ View* const view = ElementToView(
+ ui::ElementTracker::GetElementTracker()->GetFirstMatchingElement(
+ id, ElementTrackerViews::GetContextForView(contents_)));
+ Widget* const menu_widget = view->GetWidget();
+ test::WidgetVisibleWaiter visible_waiter(menu_widget);
+ visible_waiter.Wait();
+ DCHECK(strstr(view->GetClassName(), "MenuItemView"));
+ menu_item_ = static_cast<MenuItemView*>(view);
+ EXPECT_TRUE(menu_item_->GetVisible());
+ EXPECT_TRUE(menu_item_->GetWidget()->IsVisible());
+ }
+
+ void CloseMenu() {
+ menu_runner_.reset();
+ menu_model_.reset();
+ menu_item_ = nullptr;
+ }
+
+ void ShowBubble(ui::ElementIdentifier id) {
+ auto delegate = std::make_unique<BubbleDialogDelegateView>(
+ contents_, BubbleBorder::Arrow::TOP_LEFT);
+ bubble_view_ = delegate->AddChildView(std::make_unique<LabelButton>());
+ bubble_view_->SetProperty(kElementIdentifierKey, id);
+ bubble_widget_ =
+ BubbleDialogDelegateView::CreateBubble(std::move(delegate));
+ test::WidgetVisibleWaiter visible_waiter(bubble_widget_);
+ bubble_widget_->Show();
+ visible_waiter.Wait();
+ }
+
+ void CloseBubble() {
+ DCHECK(bubble_widget_);
+ bubble_widget_->CloseNow();
+ bubble_widget_ = nullptr;
+ bubble_view_ = nullptr;
+ }
+
+ void Activate(View* view) {
+ ui::ElementTracker::GetFrameworkDelegate()->NotifyElementActivated(
+ ElementTrackerViews::GetInstance()->GetElementForView(view));
+ }
+
+ void SetUp() override {
+ ViewsTestBase::SetUp();
+ widget_ = CreateWidget();
+ contents_ = widget_->GetContentsView();
+ contents_->SetProperty(kElementIdentifierKey, kContentsElementID);
+ }
+
+ void TearDown() override {
+ if (bubble_widget_)
+ CloseBubble();
+ if (menu_runner_)
+ CloseMenu();
+ widget_.reset();
+ contents_ = nullptr;
+ ViewsTestBase::TearDown();
+ }
+
+ protected:
+ ui::ElementContext context() const {
+ return ui::ElementContext(widget_.get());
+ }
+
+ virtual void CreateAndRunMenu(ui::ElementIdentifier id) {
+ menu_model_ = std::make_unique<ui::SimpleMenuModel>(nullptr);
+ menu_model_->AddItem(kMenuID1, kMenuItem1);
+ menu_model_->AddItem(kMenuID2, kMenuItem2);
+ menu_model_->SetElementIdentifierAt(
+ menu_model_->GetIndexOfCommandId(kMenuID2), id);
+
+ menu_runner_ =
+ std::make_unique<MenuRunner>(menu_model_.get(), MenuRunner::NO_FLAGS);
+ menu_runner_->RunMenuAt(
+ widget_.get(), nullptr, gfx::Rect(gfx::Point(), gfx::Size(200, 200)),
+ MenuAnchorPosition::kTopLeft, ui::MENU_SOURCE_MOUSE);
+ }
+
+ std::unique_ptr<Widget> widget_;
+ View* contents_ = nullptr;
+ Widget* bubble_widget_ = nullptr;
+ View* bubble_view_ = nullptr;
+ std::unique_ptr<ui::SimpleMenuModel> menu_model_;
+ std::unique_ptr<MenuRunner> menu_runner_;
+ MenuItemView* menu_item_ = nullptr;
+};
+
+TEST_F(InteractionSequenceViewsTest, DestructWithInitialViewAborts) {
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed);
+ auto* const starting_view = contents_->AddChildView(std::make_unique<View>());
+ starting_view->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto tracker =
+ ui::InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequenceViews::WithInitialView(starting_view))
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ .Build())
+ .Build();
+ tracker->Start();
+ EXPECT_CALL_IN_SCOPE(aborted, Run,
+ contents_->RemoveChildViewT(starting_view));
+}
+
+TEST_F(InteractionSequenceViewsTest, DestructWithInitialViewBeforeStartAborts) {
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed);
+ auto* const starting_view = contents_->AddChildView(std::make_unique<View>());
+ starting_view->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto tracker =
+ ui::InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequenceViews::WithInitialView(starting_view))
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ .Build())
+ .Build();
+ contents_->RemoveChildViewT(starting_view);
+ EXPECT_CALL_IN_SCOPE(aborted, Run, tracker->Start());
+}
+
+TEST_F(InteractionSequenceViewsTest, WrongWithInitialViewDoesNotStartSequence) {
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed);
+ auto* const starting_view = contents_->AddChildView(std::make_unique<View>());
+ starting_view->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto* const other_view = contents_->AddChildView(std::make_unique<View>());
+ other_view->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto tracker =
+ ui::InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequenceViews::WithInitialView(starting_view))
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ .Build())
+ .Build();
+ starting_view->SetVisible(false);
+ EXPECT_CALL_IN_SCOPE(aborted, Run, tracker->Start());
+}
+
+TEST_F(InteractionSequenceViewsTest,
+ SequenceNotCanceledDueToViewDestroyedIfRequirementChanged) {
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step2_start);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step2_end);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step3_start);
+ auto* const starting_view = contents_->AddChildView(std::make_unique<View>());
+ starting_view->SetProperty(kElementIdentifierKey, kTestElementID);
+ auto tracker =
+ ui::InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequenceViews::WithInitialView(starting_view))
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID2)
+ .SetType(ui::InteractionSequence::StepType::kShown)
+ .Build())
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID2)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ // Specify that this step doesn't abort on the view
+ // becoming hidden.
+ .SetMustRemainVisible(false)
+ .SetStartCallback(step2_start.Get())
+ .SetEndCallback(step2_end.Get())
+ .Build())
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID3)
+ .SetType(ui::InteractionSequence::StepType::kShown)
+ .SetStartCallback(step3_start.Get())
+ .Build())
+ .Build();
+ tracker->Start();
+ auto* const second_view = contents_->AddChildView(std::make_unique<View>());
+ second_view->SetProperty(kElementIdentifierKey, kTestElementID2);
+ auto* const third_view = contents_->AddChildView(std::make_unique<View>());
+ third_view->SetProperty(kElementIdentifierKey, kTestElementID3);
+ third_view->SetVisible(false);
+
+ // Simulate the view being activated to do the second step.
+ EXPECT_CALL_IN_SCOPE(step2_start,
+ Run(ViewToElement(second_view), kTestElementID2,
+ ui::InteractionSequence::StepType::kActivated),
+ Activate(second_view));
+
+ // Destroying the second view should NOT break the sequence.
+ contents_->RemoveChildViewT(second_view);
+
+ // Showing the third view at this point continues the sequence.
+ EXPECT_CALLS_IN_SCOPE_3(step2_end, Run, step3_start, Run, completed, Run,
+ third_view->SetVisible(true));
+}
+
+TEST_F(InteractionSequenceViewsTest, TransitionToBubble) {
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step2);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step3);
+ auto tracker =
+ ui::InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequenceViews::WithInitialView(contents_))
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step.Get())
+ .Build())
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID2)
+ .SetType(ui::InteractionSequence::StepType::kShown)
+ .SetStartCallback(step2.Get())
+ .Build())
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID2)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step3.Get())
+ .Build())
+ .Build();
+ auto* const button = contents_->AddChildView(
+ std::make_unique<LabelButton>(Button::PressedCallback(
+ base::BindRepeating(&InteractionSequenceViewsTest::ShowBubble,
+ base::Unretained(this), kTestElementID2))));
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ tracker->Start();
+
+ EXPECT_CALLS_IN_SCOPE_2(step, Run, step2, Run, {
+ button->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ button->OnKeyReleased(ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ });
+
+ EXPECT_CALLS_IN_SCOPE_2(step3, Run, completed, Run, {
+ bubble_view_->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE,
+ ui::EF_NONE,
+ ui::EventTimeForNow()));
+ bubble_view_->OnKeyReleased(ui::KeyEvent(ui::ET_KEY_RELEASED,
+ ui::VKEY_SPACE, ui::EF_NONE,
+ ui::EventTimeForNow()));
+ });
+}
+
+TEST_F(InteractionSequenceViewsTest, TransitionToBubbleThenAbort) {
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step2);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step3);
+ auto tracker =
+ ui::InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequenceViews::WithInitialView(contents_))
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step.Get())
+ .Build())
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID2)
+ .SetType(ui::InteractionSequence::StepType::kShown)
+ .SetStartCallback(step2.Get())
+ .Build())
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID2)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step3.Get())
+ .Build())
+ .Build();
+ auto* const button = contents_->AddChildView(
+ std::make_unique<LabelButton>(Button::PressedCallback(
+ base::BindRepeating(&InteractionSequenceViewsTest::ShowBubble,
+ base::Unretained(this), kTestElementID2))));
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ tracker->Start();
+
+ EXPECT_CALLS_IN_SCOPE_2(step, Run, step2, Run, {
+ button->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ button->OnKeyReleased(ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ });
+
+ EXPECT_CALL_IN_SCOPE(aborted, Run, CloseBubble());
+}
+
+TEST_F(InteractionSequenceViewsTest, TransitionToMenuAndViewMenuItem) {
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step2);
+ auto tracker =
+ ui::InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequenceViews::WithInitialView(contents_))
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step.Get())
+ .Build())
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID2)
+ .SetType(ui::InteractionSequence::StepType::kShown)
+ .SetStartCallback(step2.Get())
+ .Build())
+ .Build();
+ auto* const button = contents_->AddChildView(
+ std::make_unique<LabelButton>(Button::PressedCallback(
+ base::BindRepeating(&InteractionSequenceViewsTest::ShowMenu,
+ base::Unretained(this), kTestElementID2))));
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ tracker->Start();
+
+ EXPECT_CALLS_IN_SCOPE_3(step, Run, step2, Run, completed, Run, {
+ button->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ button->OnKeyReleased(ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ });
+}
+
+TEST_F(InteractionSequenceViewsTest, TransitionToMenuThenCloseMenuToCancel) {
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step2);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step3);
+ auto tracker =
+ ui::InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequenceViews::WithInitialView(contents_))
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step.Get())
+ .Build())
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID2)
+ .SetType(ui::InteractionSequence::StepType::kShown)
+ .SetStartCallback(step2.Get())
+ .Build())
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID2)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step3.Get())
+ .Build())
+ .Build();
+ auto* const button = contents_->AddChildView(
+ std::make_unique<LabelButton>(Button::PressedCallback(
+ base::BindRepeating(&InteractionSequenceViewsTest::ShowMenu,
+ base::Unretained(this), kTestElementID2))));
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ tracker->Start();
+
+ EXPECT_CALLS_IN_SCOPE_2(step, Run, step2, Run, {
+ button->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ button->OnKeyReleased(ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ });
+
+ EXPECT_CALL_IN_SCOPE(aborted, Run, CloseMenu());
+}
+
+// Menu button uses different event-handling architecture than standard Button,
+// so test it separately here.
+TEST_F(InteractionSequenceViewsTest, TransitionToMenuWithMenuButton) {
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step2);
+ auto tracker =
+ ui::InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequenceViews::WithInitialView(contents_))
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step.Get())
+ .Build())
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID2)
+ .SetType(ui::InteractionSequence::StepType::kShown)
+ .SetStartCallback(step2.Get())
+ .Build())
+ .Build();
+
+ auto* const button = contents_->AddChildView(
+ std::make_unique<MenuButton>(Button::PressedCallback(
+ base::BindRepeating(&InteractionSequenceViewsTest::ShowMenu,
+ base::Unretained(this), kTestElementID2))));
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ tracker->Start();
+
+ EXPECT_CALLS_IN_SCOPE_3(step, Run, step2, Run, completed, Run, {
+ button->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ button->OnKeyReleased(ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ });
+}
+
+#if !defined(OS_MAC)
+// Because Mac does not use Aura, mouse event delivery to Views menus on Mac
+// doesn't work the same as on other platforms. We still test that activation of
+// Mac menus is correctly communicated through ui::ElementTracker in the
+// following test.
+TEST_F(InteractionSequenceViewsTest, TransitionToMenuAndActivateMenuItem) {
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step2);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step3);
+ auto tracker =
+ ui::InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequenceViews::WithInitialView(contents_))
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step.Get())
+ .Build())
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID2)
+ .SetType(ui::InteractionSequence::StepType::kShown)
+ .SetStartCallback(step2.Get())
+ .Build())
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID2)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step3.Get())
+ .Build())
+ .Build();
+ auto* const button = contents_->AddChildView(
+ std::make_unique<LabelButton>(Button::PressedCallback(
+ base::BindRepeating(&InteractionSequenceViewsTest::ShowMenu,
+ base::Unretained(this), kTestElementID2))));
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ tracker->Start();
+
+ EXPECT_CALLS_IN_SCOPE_2(step, Run, step2, Run, {
+ button->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ button->OnKeyReleased(ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ });
+
+ EXPECT_CALLS_IN_SCOPE_2(step3, Run, completed, Run, {
+ ui::test::EventGenerator generator(GetContext(),
+ widget_->GetNativeWindow());
+ generator.MoveMouseTo(menu_item_->GetBoundsInScreen().CenterPoint());
+ generator.ClickLeftButton();
+ });
+}
+
+#endif // !defined(OS_MAC)
+
+TEST_F(InteractionSequenceViewsTest, TransitionOnKeyboardMenuActivation) {
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step2);
+ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::StepCallback, step3);
+ auto tracker =
+ ui::InteractionSequence::Builder()
+ .SetAbortedCallback(aborted.Get())
+ .SetCompletedCallback(completed.Get())
+ .AddStep(InteractionSequenceViews::WithInitialView(contents_))
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step.Get())
+ .Build())
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID2)
+ .SetType(ui::InteractionSequence::StepType::kShown)
+ .SetStartCallback(step2.Get())
+ .Build())
+ .AddStep(ui::InteractionSequence::StepBuilder()
+ .SetElementID(kTestElementID2)
+ .SetType(ui::InteractionSequence::StepType::kActivated)
+ .SetStartCallback(step3.Get())
+ .Build())
+ .Build();
+ auto* const button = contents_->AddChildView(
+ std::make_unique<LabelButton>(Button::PressedCallback(
+ base::BindRepeating(&InteractionSequenceViewsTest::ShowMenu,
+ base::Unretained(this), kTestElementID2))));
+ button->SetProperty(kElementIdentifierKey, kTestElementID);
+ tracker->Start();
+
+ EXPECT_CALLS_IN_SCOPE_2(step, Run, step2, Run, {
+ button->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ button->OnKeyReleased(ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SPACE,
+ ui::EF_NONE, ui::EventTimeForNow()));
+ });
+
+ EXPECT_CALLS_IN_SCOPE_2(step3, Run, completed, Run, {
+ ui::test::EventGenerator generator(GetContext(),
+ widget_->GetNativeWindow());
+ generator.PressKey(ui::VKEY_DOWN, 0);
+ generator.PressKey(ui::VKEY_DOWN, 0);
+ generator.PressKey(ui::VKEY_RETURN, 0);
+ });
+}
+
+} // namespace views
diff --git a/chromium/ui/views/layout/animating_layout_manager.cc b/chromium/ui/views/layout/animating_layout_manager.cc
index cc67d166b9b..0dc811feb0e 100644
--- a/chromium/ui/views/layout/animating_layout_manager.cc
+++ b/chromium/ui/views/layout/animating_layout_manager.cc
@@ -13,6 +13,7 @@
#include "base/auto_reset.h"
#include "base/containers/contains.h"
#include "base/stl_util.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "ui/gfx/animation/animation_container.h"
#include "ui/gfx/animation/slide_animation.h"
#include "ui/views/animation/animation_delegate_views.h"
@@ -529,11 +530,13 @@ void AnimatingLayoutManager::LayoutImpl() {
const gfx::Size host_size = host_view()->size();
if (bounds_animation_mode_ == BoundsAnimationMode::kUseHostBounds) {
- if (!cached_layout_size() || host_size != *cached_layout_size()) {
- // Host size changed, so reset the layout.
+ if (!cached_layout_size()) {
+ // No previous layout, so snap to the target.
ResetLayoutToTargetSize();
+ } else if (host_size != *cached_layout_size()) {
+ // Host size changed, so animate.
+ RecalculateTarget();
}
-
} else {
const SizeBounds available_size = GetAvailableHostSize();
@@ -554,8 +557,8 @@ void AnimatingLayoutManager::LayoutImpl() {
const int current_main =
GetMainAxis(orientation(), current_layout_.host_size);
if ((current_main > host_main) || (current_main > bounds_main)) {
- // Reset the layout immediately if the current or target layout exceeds
- // the host size or the available space.
+ // Reset the layout immediately if the current layout exceeds the host
+ // size or the available space.
last_available_host_size_ = available_size;
ResetLayoutToSize(host_size);
} else if (available_size != last_available_host_size_) {
@@ -619,19 +622,6 @@ bool AnimatingLayoutManager::RecalculateTarget() {
}
const gfx::Size target_size = GetAvailableTargetLayoutSize();
-
- // For layouts that are confined to available space, changing the available
- // space causes a fresh layout, not an animation.
- // TODO(dfried): define a way for views to animate into and out of empty
- // space as adjacent child views appear/disappear. This will be useful in
- // animating tab titles, which currently slide over when the favicon
- // disappears.
- if (bounds_animation_mode_ == BoundsAnimationMode::kUseHostBounds &&
- *cached_layout_size() != target_size) {
- ResetLayoutToSize(target_size);
- return true;
- }
-
set_cached_layout_size(target_size);
// If there has been no appreciable change in layout, there's no reason to
@@ -802,10 +792,10 @@ void AnimatingLayoutManager::CalculateFadeInfos() {
fade_infos_.clear();
struct ChildInfo {
- base::Optional<size_t> start;
+ absl::optional<size_t> start;
NormalizedRect start_bounds;
bool start_visible = false;
- base::Optional<size_t> target;
+ absl::optional<size_t> target;
NormalizedRect target_bounds;
bool target_visible = false;
};
diff --git a/chromium/ui/views/layout/animating_layout_manager_unittest.cc b/chromium/ui/views/layout/animating_layout_manager_unittest.cc
index 02f66e60f65..e7106bfbdd3 100644
--- a/chromium/ui/views/layout/animating_layout_manager_unittest.cc
+++ b/chromium/ui/views/layout/animating_layout_manager_unittest.cc
@@ -10,6 +10,7 @@
#include "base/scoped_observation.h"
#include "base/test/task_environment.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/animation/animation_test_api.h"
@@ -57,7 +58,7 @@ class TestView : public View {
}
private:
- base::Optional<gfx::Size> minimum_size_;
+ absl::optional<gfx::Size> minimum_size_;
bool fix_area_ = false;
};
@@ -339,11 +340,11 @@ TEST_F(AnimatingLayoutManagerTest, HostInvalidate_NoAnimateBounds_NoAnimation) {
auto* const test_layout =
layout()->SetTargetLayoutManager(std::make_unique<TestLayoutManager>());
test_layout->SetLayout(layout1());
- layout()->ResetLayout();
SizeAndLayout();
+ layout()->ResetLayout();
+ view()->Layout();
// First layout. Should not be animating.
- view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EXPECT_EQ(layout1().host_size, view()->size());
EnsureLayout(layout1());
@@ -355,30 +356,6 @@ TEST_F(AnimatingLayoutManagerTest, HostInvalidate_NoAnimateBounds_NoAnimation) {
EnsureLayout(layout1());
}
-TEST_F(AnimatingLayoutManagerTest, HostResize_NoAnimateBounds_NoAnimation) {
- layout()->SetBoundsAnimationMode(
- AnimatingLayoutManager::BoundsAnimationMode::kUseHostBounds);
- auto* const test_layout =
- layout()->SetTargetLayoutManager(std::make_unique<TestLayoutManager>());
- test_layout->SetLayout(layout1());
- layout()->ResetLayout();
- SizeAndLayout();
-
- // First layout. Should not be animating.
- view()->Layout();
- EXPECT_FALSE(layout()->is_animating());
- EXPECT_EQ(layout1().host_size, view()->size());
- EnsureLayout(layout1());
-
- // Because the size of the host view changed, there is no animation.
- test_layout->SetLayout(layout2());
- SizeAndLayout();
- view()->Layout();
- EXPECT_FALSE(layout()->is_animating());
- EXPECT_EQ(layout2().host_size, view()->size());
- EnsureLayout(layout2());
-}
-
TEST_F(AnimatingLayoutManagerTest,
HostInvalidate_NoAnimateBounds_NewLayoutTriggersAnimation) {
layout()->SetBoundsAnimationMode(
@@ -386,11 +363,11 @@ TEST_F(AnimatingLayoutManagerTest,
auto* const test_layout =
layout()->SetTargetLayoutManager(std::make_unique<TestLayoutManager>());
test_layout->SetLayout(layout1());
- layout()->ResetLayout();
SizeAndLayout();
+ layout()->ResetLayout();
+ view()->Layout();
// First layout. Should not be animating.
- view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EXPECT_EQ(layout1().host_size, view()->size());
EnsureLayout(layout1());
@@ -412,11 +389,11 @@ TEST_F(AnimatingLayoutManagerTest,
auto* const test_layout =
layout()->SetTargetLayoutManager(std::make_unique<TestLayoutManager>());
test_layout->SetLayout(layout1());
- layout()->ResetLayout();
SizeAndLayout();
+ layout()->ResetLayout();
+ view()->Layout();
// First layout. Should not be animating.
- view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EXPECT_EQ(layout1().host_size, view()->size());
EnsureLayout(layout1());
@@ -865,6 +842,7 @@ TEST_F(AnimatingLayoutManagerTest,
.SetDefault(kFlexBehaviorKey, kDropOut);
view()->SetSize({20, 35});
layout()->ResetLayout();
+ view()->Layout();
// Sanity check...
const ProposedLayout initial_layout{{20, 50},
@@ -908,6 +886,7 @@ TEST_F(AnimatingLayoutManagerTest,
.SetDefault(kFlexBehaviorKey, kDropOut);
view()->SetSize({20, 35});
layout()->ResetLayout();
+ view()->Layout();
// Sanity check...
const ProposedLayout initial_layout{{20, 50},
@@ -944,6 +923,7 @@ TEST_F(AnimatingLayoutManagerTest,
.SetDefault(kFlexBehaviorKey, kDropOut);
view()->SetSize({20, 35});
layout()->ResetLayout();
+ view()->Layout();
// Sanity check...
const ProposedLayout initial_layout{{20, 50},
@@ -1242,6 +1222,8 @@ TEST_F(AnimatingLayoutManagerTest, FlexLayout_FadeOutOnVisibilitySet) {
// Set up the initial state of the host view and children.
SizeAndLayout();
+ layout()->ResetLayout();
+ view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EnsureLayout(expected_start);
@@ -1300,6 +1282,8 @@ TEST_F(AnimatingLayoutManagerTest, FlexLayout_FadeInOnVisibilitySet) {
// Set up the initial state of the host view and children.
view()->SetSize(expected_end.host_size);
+ layout()->ResetLayout();
+ view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EnsureLayout(expected_start);
@@ -1328,7 +1312,7 @@ TEST_F(AnimatingLayoutManagerTest, FlexLayout_FadeInOnVisibilitySet) {
// Regression test for issues: crbug.com/1021332, crbug.com/1003500
TEST_F(AnimatingLayoutManagerTest,
- FlexLayout_AnimateOutOnDescendentVisbilitySet) {
+ FlexLayout_AnimateOutOnDescendentVisibilitySet) {
constexpr gfx::Insets kChildMargins(5);
layout()->SetBoundsAnimationMode(
AnimatingLayoutManager::BoundsAnimationMode::kUseHostBounds);
@@ -1363,6 +1347,8 @@ TEST_F(AnimatingLayoutManagerTest,
// Set up the initial state of the host view and children.
SizeAndLayout();
+ layout()->ResetLayout();
+ view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EnsureLayout(expected_start);
@@ -1391,7 +1377,7 @@ TEST_F(AnimatingLayoutManagerTest,
// Regression test for issues: crbug.com/1021332, crbug.com/1003500
TEST_F(AnimatingLayoutManagerTest,
- FlexLayout_AnimateInOnDescendentVisbilitySet) {
+ FlexLayout_AnimateInOnDescendentVisibilitySet) {
constexpr gfx::Insets kChildMargins(5);
layout()->SetBoundsAnimationMode(
AnimatingLayoutManager::BoundsAnimationMode::kUseHostBounds);
@@ -1427,6 +1413,8 @@ TEST_F(AnimatingLayoutManagerTest,
// Set up the initial state of the host view and children.
view()->SetSize(expected_end.host_size);
+ layout()->ResetLayout();
+ view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EnsureLayout(expected_start);
@@ -1475,6 +1463,8 @@ TEST_F(AnimatingLayoutManagerTest, FlexLayout_RemoveFadingViewDoesNotCrash) {
// Set up the initial state of the host view and children.
SizeAndLayout();
+ layout()->ResetLayout();
+ view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EnsureLayout(expected_start);
@@ -1514,6 +1504,8 @@ TEST_F(AnimatingLayoutManagerTest, FlexLayout_RemoveShowingViewDoesNotCrash) {
// Set up the initial state of the host view and children.
SizeAndLayout();
+ layout()->ResetLayout();
+ view()->Layout();
EXPECT_FALSE(layout()->is_animating());
layout()->FadeIn(child(1));
@@ -1877,6 +1869,8 @@ TEST_F(AnimatingLayoutManagerTest, FlexLayout_FadeInOnAdded) {
// Set up the initial state of the host view and children.
view()->SetSize(expected_end.host_size);
+ layout()->ResetLayout();
+ view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EnsureLayout(expected_start);
@@ -1934,6 +1928,8 @@ TEST_F(AnimatingLayoutManagerTest, FlexLayout_FadeIn) {
// Set up the initial state of the host view and children.
view()->SetSize(expected_end.host_size);
+ layout()->ResetLayout();
+ view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EnsureLayout(expected_start);
@@ -1991,6 +1987,8 @@ TEST_F(AnimatingLayoutManagerTest, FlexLayout_FadeOut) {
// Set up the initial state of the host view and children.
SizeAndLayout();
+ layout()->ResetLayout();
+ view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EnsureLayout(expected_start);
@@ -2052,6 +2050,8 @@ TEST_F(AnimatingLayoutManagerTest, FlexLayout_FadeOut_NoCrashOnRemove) {
// Set up the initial state of the host view and children.
SizeAndLayout();
+ layout()->ResetLayout();
+ view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EnsureLayout(expected_start);
@@ -2107,6 +2107,8 @@ TEST_F(AnimatingLayoutManagerTest, FlexLayout_FadeOut_IgnoreChildView) {
// Set up the initial state of the host view and children.
SizeAndLayout();
+ layout()->ResetLayout();
+ view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EnsureLayout(expected_start);
@@ -2159,6 +2161,8 @@ TEST_F(AnimatingLayoutManagerTest, FlexLayout_SlideAfterViewHidden) {
// Set up the initial state of the host view and children.
SizeAndLayout();
+ layout()->ResetLayout();
+ view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EnsureLayout(expected_start);
@@ -2211,6 +2215,8 @@ TEST_F(AnimatingLayoutManagerTest, FlexLayout_SlideAfterViewRemoved) {
// Set up the initial state of the host view and children.
SizeAndLayout();
+ layout()->ResetLayout();
+ view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EnsureLayout(expected_start);
@@ -2269,6 +2275,8 @@ TEST_F(AnimatingLayoutManagerTest, FlexLayout_RedirectAnimation) {
// Set up the initial state of the host view and children.
SizeAndLayout();
+ layout()->ResetLayout();
+ view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EnsureLayout(expected_start);
@@ -2329,6 +2337,8 @@ TEST_F(AnimatingLayoutManagerTest, FlexLayout_ResetAnimation) {
// Set up the initial state of the host view and children.
SizeAndLayout();
+ layout()->ResetLayout();
+ view()->Layout();
EXPECT_FALSE(layout()->is_animating());
EnsureLayout(expected_start);
@@ -3925,7 +3935,7 @@ class AnimatingLayoutManagerFlexRuleTest : public AnimatingLayoutManagerTest {
public:
void InitLayout(LayoutOrientation orientation,
const FlexSpecification& default_flex,
- const base::Optional<gfx::Size>& minimum_size,
+ const absl::optional<gfx::Size>& minimum_size,
bool fix_child_size) {
for (size_t i = 0; i < num_children(); ++i) {
if (minimum_size)
@@ -4789,7 +4799,7 @@ TEST_F(AnimatingLayoutManagerRealtimeTest,
// TODO(dfried): figure out why these tests absolutely do not animate properly
// on Mac. Whatever magic makes the compositor animation runner go doesn't seem
// to want to work on Mac in non-browsertests :(
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// Test fixture for testing sequences of the following four actions:
// * animating layout manager configured on host view
@@ -4984,6 +4994,6 @@ TEST_F(AnimatingLayoutManagerSequenceTest,
ExpectResetToLayout();
}
-#endif // !defined(OS_APPLE)
+#endif // !defined(OS_MAC)
} // namespace views
diff --git a/chromium/ui/views/layout/box_layout_view.cc b/chromium/ui/views/layout/box_layout_view.cc
index 1133609e5cf..2291e367852 100644
--- a/chromium/ui/views/layout/box_layout_view.cc
+++ b/chromium/ui/views/layout/box_layout_view.cc
@@ -6,9 +6,9 @@
#include <memory>
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/layout/layout_manager.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace views {
@@ -133,21 +133,6 @@ void BoxLayoutView::ClearFlexForView(const View* view) {
InvalidateLayout();
}
-DEFINE_ENUM_CONVERTERS(BoxLayout::Orientation,
- {BoxLayout::Orientation::kHorizontal, u"kHorizontal"},
- {BoxLayout::Orientation::kVertical, u"kVertical"})
-
-DEFINE_ENUM_CONVERTERS(BoxLayout::MainAxisAlignment,
- {BoxLayout::MainAxisAlignment::kStart, u"kStart"},
- {BoxLayout::MainAxisAlignment::kCenter, u"kCenter"},
- {BoxLayout::MainAxisAlignment::kEnd, u"kEnd"})
-
-DEFINE_ENUM_CONVERTERS(BoxLayout::CrossAxisAlignment,
- {BoxLayout::CrossAxisAlignment::kStretch, u"kStretch"},
- {BoxLayout::CrossAxisAlignment::kStart, u"kStart"},
- {BoxLayout::CrossAxisAlignment::kCenter, u"kCenter"},
- {BoxLayout::CrossAxisAlignment::kEnd, u"kEnd"})
-
BEGIN_METADATA(BoxLayoutView, View)
ADD_PROPERTY_METADATA(BoxLayout::Orientation, Orientation)
ADD_PROPERTY_METADATA(BoxLayout::MainAxisAlignment, MainAxisAlignment)
@@ -160,3 +145,21 @@ ADD_PROPERTY_METADATA(int, DefaultFlex)
END_METADATA
} // namespace views
+
+DEFINE_ENUM_CONVERTERS(views::BoxLayout::Orientation,
+ {views::BoxLayout::Orientation::kHorizontal,
+ u"kHorizontal"},
+ {views::BoxLayout::Orientation::kVertical, u"kVertical"})
+
+DEFINE_ENUM_CONVERTERS(views::BoxLayout::MainAxisAlignment,
+ {views::BoxLayout::MainAxisAlignment::kStart, u"kStart"},
+ {views::BoxLayout::MainAxisAlignment::kCenter,
+ u"kCenter"},
+ {views::BoxLayout::MainAxisAlignment::kEnd, u"kEnd"})
+
+DEFINE_ENUM_CONVERTERS(
+ views::BoxLayout::CrossAxisAlignment,
+ {views::BoxLayout::CrossAxisAlignment::kStretch, u"kStretch"},
+ {views::BoxLayout::CrossAxisAlignment::kStart, u"kStart"},
+ {views::BoxLayout::CrossAxisAlignment::kCenter, u"kCenter"},
+ {views::BoxLayout::CrossAxisAlignment::kEnd, u"kEnd"})
diff --git a/chromium/ui/views/layout/box_layout_view.h b/chromium/ui/views/layout/box_layout_view.h
index 36dc2ec07c8..9536b31c51c 100644
--- a/chromium/ui/views/layout/box_layout_view.h
+++ b/chromium/ui/views/layout/box_layout_view.h
@@ -5,8 +5,8 @@
#ifndef UI_VIEWS_LAYOUT_BOX_LAYOUT_VIEW_H_
#define UI_VIEWS_LAYOUT_BOX_LAYOUT_VIEW_H_
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/layout/box_layout.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/view.h"
diff --git a/chromium/ui/views/layout/composite_layout_tests.cc b/chromium/ui/views/layout/composite_layout_tests.cc
index 7052e2578ef..0b0c2884984 100644
--- a/chromium/ui/views/layout/composite_layout_tests.cc
+++ b/chromium/ui/views/layout/composite_layout_tests.cc
@@ -220,7 +220,7 @@ class SimulatedExtensionsContainer : public SimulatedToolbarElement {
// If |expected_num_icons| is specified:
// - while animating, serves as a lower bound on the number of icons displayed
// - while not animating, must match the number of visible icons exactly
- void EnsureLayout(base::Optional<int> expected_num_icons) const {
+ void EnsureLayout(absl::optional<int> expected_num_icons) const {
if (layout()->is_animating()) {
// For animating layouts, we ensure that icons are the correct size and
// appear between the left edge of the container and exactly overlapping
@@ -344,7 +344,7 @@ class SimulatedToolbar : public View {
//
// The parameter |expected_num_extension_icons| is passed to
// SimulatedExtensionsContainer::EnsureLayout().
- void EnsureLayout(base::Optional<int> expected_num_extension_icons) const {
+ void EnsureLayout(absl::optional<int> expected_num_extension_icons) const {
EXPECT_EQ(kIconDimension, height());
EXPECT_EQ(gfx::Rect(gfx::Point(), kIconSize), children()[0]->bounds());
EXPECT_EQ(gfx::Point(kIconDimension, 0), location()->origin());
@@ -445,7 +445,7 @@ class CompositeLayoutTest : public testing::Test {
// at minimum that many if animating) simulated extension icons must be
// visible.
void EnsureLayout(
- base::Optional<int> expected_num_extension_icons = base::nullopt) {
+ absl::optional<int> expected_num_extension_icons = absl::nullopt) {
toolbar_->EnsureLayout(expected_num_extension_icons);
}
diff --git a/chromium/ui/views/layout/flex_layout.cc b/chromium/ui/views/layout/flex_layout.cc
index b4845e6ee62..f5f9bddcba4 100644
--- a/chromium/ui/views/layout/flex_layout.cc
+++ b/chromium/ui/views/layout/flex_layout.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include <functional>
#include <numeric>
+#include <sstream>
#include <string>
#include <utility>
#include <vector>
@@ -17,7 +18,6 @@
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "base/ranges/algorithm.h"
-#include "base/strings/stringprintf.h"
#include "ui/base/class_property.h"
#include "ui/events/event_target.h"
#include "ui/events/event_target_iterator.h"
@@ -105,8 +105,8 @@ class FlexLayout::ChildViewSpacing {
// absent, uses the left edge of the parent container. If the second index is
// absent, uses the right edge of the parent container.
using GetViewSpacingCallback =
- base::RepeatingCallback<int(base::Optional<size_t>,
- base::Optional<size_t>)>;
+ base::RepeatingCallback<int(absl::optional<size_t>,
+ absl::optional<size_t>)>;
explicit ChildViewSpacing(GetViewSpacingCallback get_view_spacing);
ChildViewSpacing(const ChildViewSpacing& other) = default;
@@ -139,8 +139,8 @@ class FlexLayout::ChildViewSpacing {
int* new_trailing = nullptr);
private:
- base::Optional<size_t> GetPreviousViewIndex(size_t view_index) const;
- base::Optional<size_t> GetNextViewIndex(size_t view_index) const;
+ absl::optional<size_t> GetPreviousViewIndex(size_t view_index) const;
+ absl::optional<size_t> GetNextViewIndex(size_t view_index) const;
// Returns the change in space required if the specified view index were
// added. The view must not already be present.
@@ -156,7 +156,7 @@ class FlexLayout::ChildViewSpacing {
FlexLayout::ChildViewSpacing::ChildViewSpacing(
GetViewSpacingCallback get_view_spacing)
: get_view_spacing_(std::move(get_view_spacing)),
- trailing_space_(get_view_spacing_.Run(base::nullopt, base::nullopt)) {}
+ trailing_space_(get_view_spacing_.Run(absl::nullopt, absl::nullopt)) {}
bool FlexLayout::ChildViewSpacing::HasViewIndex(size_t view_index) const {
return leading_spacings_.find(view_index) != leading_spacings_.end();
@@ -217,8 +217,8 @@ void FlexLayout::ChildViewSpacing::AddViewIndex(size_t view_index,
int* new_leading,
int* new_trailing) {
DCHECK(!HasViewIndex(view_index));
- base::Optional<size_t> prev = GetPreviousViewIndex(view_index);
- base::Optional<size_t> next = GetNextViewIndex(view_index);
+ absl::optional<size_t> prev = GetPreviousViewIndex(view_index);
+ absl::optional<size_t> next = GetNextViewIndex(view_index);
const int leading_space = get_view_spacing_.Run(prev, view_index);
const int trailing_space = get_view_spacing_.Run(view_index, next);
@@ -234,26 +234,26 @@ void FlexLayout::ChildViewSpacing::AddViewIndex(size_t view_index,
*new_trailing = trailing_space;
}
-base::Optional<size_t> FlexLayout::ChildViewSpacing::GetPreviousViewIndex(
+absl::optional<size_t> FlexLayout::ChildViewSpacing::GetPreviousViewIndex(
size_t view_index) const {
const auto it = leading_spacings_.lower_bound(view_index);
if (it == leading_spacings_.begin())
- return base::nullopt;
+ return absl::nullopt;
return std::prev(it)->first;
}
-base::Optional<size_t> FlexLayout::ChildViewSpacing::GetNextViewIndex(
+absl::optional<size_t> FlexLayout::ChildViewSpacing::GetNextViewIndex(
size_t view_index) const {
const auto it = leading_spacings_.upper_bound(view_index);
if (it == leading_spacings_.end())
- return base::nullopt;
+ return absl::nullopt;
return it->first;
}
int FlexLayout::ChildViewSpacing::GetAddDelta(size_t view_index) const {
DCHECK(!HasViewIndex(view_index));
- base::Optional<size_t> prev = GetPreviousViewIndex(view_index);
- base::Optional<size_t> next = GetNextViewIndex(view_index);
+ absl::optional<size_t> prev = GetPreviousViewIndex(view_index);
+ absl::optional<size_t> next = GetNextViewIndex(view_index);
const int old_spacing = next ? GetLeadingSpace(*next) : GetTrailingInset();
const int new_spacing = get_view_spacing_.Run(prev, view_index) +
get_view_spacing_.Run(view_index, next);
@@ -692,8 +692,8 @@ SizeBound FlexLayout::GetAvailableCrossAxisSize(
int FlexLayout::CalculateChildSpacing(
const FlexLayoutData& layout,
- base::Optional<size_t> child1_index,
- base::Optional<size_t> child2_index) const {
+ absl::optional<size_t> child1_index,
+ absl::optional<size_t> child2_index) const {
const FlexChildData* const child1 =
child1_index ? &layout.child_data[*child1_index] : nullptr;
const FlexChildData* const child2 =
diff --git a/chromium/ui/views/layout/flex_layout.h b/chromium/ui/views/layout/flex_layout.h
index a68e3d399de..3fd69fe185d 100644
--- a/chromium/ui/views/layout/flex_layout.h
+++ b/chromium/ui/views/layout/flex_layout.h
@@ -15,7 +15,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/class_property.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/layout/flex_layout_types.h"
@@ -202,8 +202,8 @@ class VIEWS_EXPORT FlexLayout : public LayoutManagerBase {
// Calculates the preferred spacing between two child views, or between a
// view edge and the first or last visible child views.
int CalculateChildSpacing(const FlexLayoutData& layout,
- base::Optional<size_t> child1_index,
- base::Optional<size_t> child2_index) const;
+ absl::optional<size_t> child1_index,
+ absl::optional<size_t> child2_index) const;
// Calculates the position of each child view and the size of the overall
// layout based on tentative visibilities and sizes for each child.
diff --git a/chromium/ui/views/layout/flex_layout_types.cc b/chromium/ui/views/layout/flex_layout_types.cc
index 5d3eec98beb..e28242dbe5b 100644
--- a/chromium/ui/views/layout/flex_layout_types.cc
+++ b/chromium/ui/views/layout/flex_layout_types.cc
@@ -9,6 +9,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/strings/stringprintf.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/view.h"
@@ -88,7 +89,7 @@ class LazyMinimumSize {
private:
const View* const view_;
- mutable base::Optional<gfx::Size> size_;
+ mutable absl::optional<gfx::Size> size_;
};
gfx::Size GetPreferredSize(MinimumFlexSizeRule minimum_width_rule,
diff --git a/chromium/ui/views/layout/flex_layout_types.h b/chromium/ui/views/layout/flex_layout_types.h
index 509d230ea98..e311805de16 100644
--- a/chromium/ui/views/layout/flex_layout_types.h
+++ b/chromium/ui/views/layout/flex_layout_types.h
@@ -10,7 +10,7 @@
#include <string>
#include "base/callback.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/views/layout/layout_types.h"
#include "ui/views/views_export.h"
diff --git a/chromium/ui/views/layout/flex_layout_unittest.cc b/chromium/ui/views/layout/flex_layout_unittest.cc
index 6c9d86a18b6..9e629816782 100644
--- a/chromium/ui/views/layout/flex_layout_unittest.cc
+++ b/chromium/ui/views/layout/flex_layout_unittest.cc
@@ -11,8 +11,8 @@
#include <vector>
#include "base/bind.h"
-#include "base/optional.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/border.h"
#include "ui/views/controls/label.h"
@@ -26,7 +26,7 @@ namespace views {
namespace {
-using base::Optional;
+using absl::optional;
using gfx::Insets;
using gfx::Point;
using gfx::Rect;
@@ -68,7 +68,7 @@ class MockView : public View {
void ResetCounts() { set_visible_count_ = 0; }
private:
- Optional<Size> minimum_size_;
+ optional<Size> minimum_size_;
int set_visible_count_ = 0;
SizeMode size_mode_ = SizeMode::kUsePreferredSize;
};
@@ -101,7 +101,7 @@ class FlexLayoutTest : public testing::Test {
}
MockView* AddChild(const Size& preferred_size,
- const Optional<Size>& minimum_size = Optional<Size>(),
+ const optional<Size>& minimum_size = optional<Size>(),
bool visible = true) {
return AddChild(host_.get(), preferred_size, minimum_size, visible);
}
@@ -109,7 +109,7 @@ class FlexLayoutTest : public testing::Test {
static MockView* AddChild(
View* parent,
const Size& preferred_size,
- const Optional<Size>& minimum_size = Optional<Size>(),
+ const optional<Size>& minimum_size = optional<Size>(),
bool visible = true) {
MockView* const child = new MockView();
child->SetPreferredSize(preferred_size);
@@ -316,9 +316,9 @@ TEST_F(FlexLayoutTest, Layout_VisibilitySetBeforeInstall) {
// away, we need to create our own for this test.
std::unique_ptr<views::View> host = std::make_unique<views::View>();
View* child1 =
- AddChild(host.get(), Size(10, 10), base::Optional<Size>(), false);
+ AddChild(host.get(), Size(10, 10), absl::optional<Size>(), false);
View* child2 =
- AddChild(host.get(), Size(10, 10), base::Optional<Size>(), true);
+ AddChild(host.get(), Size(10, 10), absl::optional<Size>(), true);
host->SetLayoutManager(std::make_unique<FlexLayout>());
host->Layout();
@@ -336,8 +336,8 @@ TEST_F(FlexLayoutTest, Layout_VisibilitySetBeforeInstall) {
TEST_F(FlexLayoutTest, Layout_VisibilitySetAfterInstall) {
// Unlike the last test, we'll use the built-in host and layout manager since
// they're already set up.
- View* child1 = AddChild(Size(10, 10), base::Optional<Size>(), false);
- View* child2 = AddChild(Size(10, 10), base::Optional<Size>(), true);
+ View* child1 = AddChild(Size(10, 10), absl::optional<Size>(), false);
+ View* child2 = AddChild(Size(10, 10), absl::optional<Size>(), true);
host_->Layout();
EXPECT_FALSE(child1->GetVisible());
@@ -357,7 +357,7 @@ TEST_F(FlexLayoutTest, Layout_VisibilitySetBeforeAdd) {
layout_->SetInteriorMargin(kLayoutInsets);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
View* child1 = AddChild(kChild1Size);
- View* child2 = AddChild(kChild2Size, Optional<Size>(), false);
+ View* child2 = AddChild(kChild2Size, optional<Size>(), false);
View* child3 = AddChild(kChild3Size);
host_->Layout();
@@ -3132,7 +3132,7 @@ class NestedFlexLayoutTest : public FlexLayoutTest {
View* AddGrandchild(
size_t child_index,
const gfx::Size& preferred,
- const base::Optional<gfx::Size>& minimum = base::nullopt) {
+ const absl::optional<gfx::Size>& minimum = absl::nullopt) {
return AddChild(children_[child_index - 1], preferred, minimum);
}
diff --git a/chromium/ui/views/layout/flex_layout_view.cc b/chromium/ui/views/layout/flex_layout_view.cc
index 33d9eb33c49..5f850860d30 100644
--- a/chromium/ui/views/layout/flex_layout_view.cc
+++ b/chromium/ui/views/layout/flex_layout_view.cc
@@ -6,9 +6,9 @@
#include <memory>
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/views/layout/flex_layout_types.h"
#include "ui/views/layout/layout_types.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/metadata/type_conversion.h"
namespace views {
@@ -145,20 +145,6 @@ FlexRule FlexLayoutView::GetDefaultFlexRule() const {
return layout_->GetDefaultFlexRule();
}
-DEFINE_ENUM_CONVERTERS(LayoutOrientation,
- {LayoutOrientation::kHorizontal, u"kHorizontal"},
- {LayoutOrientation::kVertical, u"kVertical"})
-
-DEFINE_ENUM_CONVERTERS(LayoutAlignment,
- {LayoutAlignment::kStart, u"kStart"},
- {LayoutAlignment::kCenter, u"kCenter"},
- {LayoutAlignment::kEnd, u"kEnd"},
- {LayoutAlignment::kStretch, u"kStretch"})
-
-DEFINE_ENUM_CONVERTERS(FlexAllocationOrder,
- {FlexAllocationOrder::kNormal, u"kNormal"},
- {FlexAllocationOrder::kReverse, u"kReverse"})
-
BEGIN_METADATA(FlexLayoutView, View)
ADD_PROPERTY_METADATA(LayoutOrientation, Orientation)
ADD_PROPERTY_METADATA(LayoutAlignment, MainAxisAlignment)
@@ -172,3 +158,17 @@ ADD_PROPERTY_METADATA(FlexAllocationOrder, FlexAllocationOrder)
END_METADATA
} // namespace views
+
+DEFINE_ENUM_CONVERTERS(views::LayoutOrientation,
+ {views::LayoutOrientation::kHorizontal, u"kHorizontal"},
+ {views::LayoutOrientation::kVertical, u"kVertical"})
+
+DEFINE_ENUM_CONVERTERS(views::LayoutAlignment,
+ {views::LayoutAlignment::kStart, u"kStart"},
+ {views::LayoutAlignment::kCenter, u"kCenter"},
+ {views::LayoutAlignment::kEnd, u"kEnd"},
+ {views::LayoutAlignment::kStretch, u"kStretch"})
+
+DEFINE_ENUM_CONVERTERS(views::FlexAllocationOrder,
+ {views::FlexAllocationOrder::kNormal, u"kNormal"},
+ {views::FlexAllocationOrder::kReverse, u"kReverse"})
diff --git a/chromium/ui/views/layout/flex_layout_view.h b/chromium/ui/views/layout/flex_layout_view.h
index 0645a5dd90b..d76ee9f0e39 100644
--- a/chromium/ui/views/layout/flex_layout_view.h
+++ b/chromium/ui/views/layout/flex_layout_view.h
@@ -5,9 +5,9 @@
#ifndef UI_VIEWS_LAYOUT_FLEX_LAYOUT_VIEW_H_
#define UI_VIEWS_LAYOUT_FLEX_LAYOUT_VIEW_H_
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/layout/flex_layout.h"
#include "ui/views/layout/flex_layout_types.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/view.h"
#include "ui/views/views_export.h"
diff --git a/chromium/ui/views/layout/layout_manager_base.h b/chromium/ui/views/layout/layout_manager_base.h
index 75362409b82..9330ef9e5a3 100644
--- a/chromium/ui/views/layout/layout_manager_base.h
+++ b/chromium/ui/views/layout/layout_manager_base.h
@@ -13,7 +13,7 @@
#include "base/dcheck_is_on.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
@@ -63,32 +63,32 @@ class VIEWS_EXPORT LayoutManagerBase : public LayoutManager {
// Direct cache control for subclasses that want to override default caching
// behavior. Use at your own risk.
- base::Optional<gfx::Size> cached_minimum_size() const {
+ absl::optional<gfx::Size> cached_minimum_size() const {
return cached_minimum_size_;
}
void set_cached_minimum_size(
- const base::Optional<gfx::Size>& minimum_size) const {
+ const absl::optional<gfx::Size>& minimum_size) const {
cached_minimum_size_ = minimum_size;
}
- const base::Optional<gfx::Size>& cached_preferred_size() const {
+ const absl::optional<gfx::Size>& cached_preferred_size() const {
return cached_preferred_size_;
}
void set_cached_preferred_size(
- const base::Optional<gfx::Size>& preferred_size) const {
+ const absl::optional<gfx::Size>& preferred_size) const {
cached_preferred_size_ = preferred_size;
}
- const base::Optional<gfx::Size>& cached_height_for_width() const {
+ const absl::optional<gfx::Size>& cached_height_for_width() const {
return cached_height_for_width_;
}
void set_cached_height_for_width(
- const base::Optional<gfx::Size>& height_for_width) const {
+ const absl::optional<gfx::Size>& height_for_width) const {
cached_height_for_width_ = height_for_width;
}
- const base::Optional<gfx::Size>& cached_layout_size() const {
+ const absl::optional<gfx::Size>& cached_layout_size() const {
return cached_layout_size_;
}
void set_cached_layout_size(
- const base::Optional<gfx::Size>& layout_size) const {
+ const absl::optional<gfx::Size>& layout_size) const {
cached_layout_size_ = layout_size;
}
const ProposedLayout& cached_layout() const { return cached_layout_; }
@@ -224,10 +224,10 @@ class VIEWS_EXPORT LayoutManagerBase : public LayoutManager {
// Do some really simple caching because layout generation can cost as much
// as 1ms or more for complex views.
- mutable base::Optional<gfx::Size> cached_minimum_size_;
- mutable base::Optional<gfx::Size> cached_preferred_size_;
- mutable base::Optional<gfx::Size> cached_height_for_width_;
- mutable base::Optional<gfx::Size> cached_layout_size_;
+ mutable absl::optional<gfx::Size> cached_minimum_size_;
+ mutable absl::optional<gfx::Size> cached_preferred_size_;
+ mutable absl::optional<gfx::Size> cached_height_for_width_;
+ mutable absl::optional<gfx::Size> cached_layout_size_;
mutable ProposedLayout cached_layout_;
DISALLOW_COPY_AND_ASSIGN(LayoutManagerBase);
diff --git a/chromium/ui/views/layout/layout_manager_base_unittest.cc b/chromium/ui/views/layout/layout_manager_base_unittest.cc
index f616d87a642..aac0d345710 100644
--- a/chromium/ui/views/layout/layout_manager_base_unittest.cc
+++ b/chromium/ui/views/layout/layout_manager_base_unittest.cc
@@ -69,7 +69,7 @@ class TestLayoutManagerBase : public LayoutManagerBase {
private:
// If specified, will always return this layout.
- base::Optional<ProposedLayout> forced_layout_;
+ absl::optional<ProposedLayout> forced_layout_;
size_t layout_count_ = 0;
};
diff --git a/chromium/ui/views/layout/layout_provider.cc b/chromium/ui/views/layout/layout_provider.cc
index 856a48b6151..57ced6d363e 100644
--- a/chromium/ui/views/layout/layout_provider.cc
+++ b/chromium/ui/views/layout/layout_provider.cc
@@ -149,11 +149,11 @@ gfx::Insets LayoutProvider::GetDialogInsetsForContentType(
DialogContentType leading,
DialogContentType trailing) const {
const int top_margin =
- leading == CONTROL
+ leading == DialogContentType::kControl
? GetDistanceMetric(DISTANCE_DIALOG_CONTENT_MARGIN_TOP_CONTROL)
: GetDistanceMetric(DISTANCE_DIALOG_CONTENT_MARGIN_TOP_TEXT);
const int bottom_margin =
- trailing == CONTROL
+ trailing == DialogContentType::kControl
? GetDistanceMetric(DISTANCE_DIALOG_CONTENT_MARGIN_BOTTOM_CONTROL)
: GetDistanceMetric(DISTANCE_DIALOG_CONTENT_MARGIN_BOTTOM_TEXT);
const gfx::Insets dialog_insets = GetInsetsMetric(INSETS_DIALOG);
@@ -191,9 +191,4 @@ int LayoutProvider::GetShadowElevationMetric(Emphasis emphasis) const {
}
}
-gfx::ShadowValues LayoutProvider::MakeShadowValues(int elevation,
- SkColor color) const {
- return gfx::ShadowValue::MakeMdShadowValues(elevation, color);
-}
-
} // namespace views
diff --git a/chromium/ui/views/layout/layout_provider.h b/chromium/ui/views/layout/layout_provider.h
index 1301b8c0b71..83b37432b9d 100644
--- a/chromium/ui/views/layout/layout_provider.h
+++ b/chromium/ui/views/layout/layout_provider.h
@@ -114,9 +114,9 @@ enum DistanceMetric {
VIEWS_DISTANCE_MAX = 0x2000
};
-// The type of a dialog content element. TEXT should be used for Labels or other
-// elements that only show text. Otherwise CONTROL should be used.
-enum DialogContentType { CONTROL, TEXT };
+// The type of a dialog content element. kText should be used for Labels or
+// other elements that only show text. Otherwise kControl should be used.
+enum class DialogContentType { kControl, kText };
enum class Emphasis {
// No emphasis needed for shadows, corner radius, etc.
@@ -138,6 +138,8 @@ class VIEWS_EXPORT LayoutProvider {
virtual ~LayoutProvider();
// This should never return nullptr.
+ // TODO(crbug.com/1200584): Replace callers of this with
+ // View::GetLayoutProvider().
static LayoutProvider* Get();
// Calculates the control height based on the |font|'s reported glyph height,
@@ -177,11 +179,6 @@ class VIEWS_EXPORT LayoutProvider {
// Returns the shadow elevation metric for the given emphasis.
virtual int GetShadowElevationMetric(Emphasis emphasis) const;
- // Creates shadows for the given elevation. Use GetShadowElevationMetric for
- // the appropriate elevation.
- virtual gfx::ShadowValues MakeShadowValues(int elevation,
- SkColor color) const;
-
protected:
static constexpr int kSmallDialogWidth = 320;
static constexpr int kMediumDialogWidth = 448;
diff --git a/chromium/ui/views/layout/layout_types.h b/chromium/ui/views/layout/layout_types.h
index 85fca0ab21d..377d262dbe6 100644
--- a/chromium/ui/views/layout/layout_types.h
+++ b/chromium/ui/views/layout/layout_types.h
@@ -11,7 +11,8 @@
#include <tuple>
#include <utility>
-#include "base/optional.h"
+#include "base/check.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/views_export.h"
@@ -66,7 +67,7 @@ class VIEWS_EXPORT SizeBound {
friend constexpr bool operator!=(const SizeBound& lhs, const SizeBound& rhs);
// nullopt represents "unbounded".
- base::Optional<int> bound_;
+ absl::optional<int> bound_;
};
constexpr SizeBound::SizeBound() = default;
constexpr SizeBound::SizeBound(int bound) : bound_(bound) {}
diff --git a/chromium/ui/views/layout/normalized_geometry.h b/chromium/ui/views/layout/normalized_geometry.h
index 87a6a32d586..1c9b6507871 100644
--- a/chromium/ui/views/layout/normalized_geometry.h
+++ b/chromium/ui/views/layout/normalized_geometry.h
@@ -8,7 +8,7 @@
#include <string>
#include <utility>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/views/layout/flex_layout_types.h"
#include "ui/views/views_export.h"
diff --git a/chromium/ui/views/linux_ui/linux_ui.cc b/chromium/ui/views/linux_ui/linux_ui.cc
index 51459bd6cb5..94b24d793d7 100644
--- a/chromium/ui/views/linux_ui/linux_ui.cc
+++ b/chromium/ui/views/linux_ui/linux_ui.cc
@@ -17,17 +17,17 @@ views::LinuxUI* g_linux_ui = nullptr;
namespace views {
-void LinuxUI::SetInstance(LinuxUI* instance) {
+void LinuxUI::SetInstance(std::unique_ptr<LinuxUI> instance) {
delete g_linux_ui;
- g_linux_ui = instance;
+ g_linux_ui = instance.release();
// Do not set IME instance for ozone as we delegate creating the input method
// to OzonePlatforms instead. If this is set, OzonePlatform never sets a
// context factory.
if (!features::IsUsingOzonePlatform())
- LinuxInputMethodContextFactory::SetInstance(instance);
- SkiaFontDelegate::SetInstance(instance);
- ShellDialogLinux::SetInstance(instance);
- ui::SetTextEditKeyBindingsDelegate(instance);
+ LinuxInputMethodContextFactory::SetInstance(g_linux_ui);
+ SkiaFontDelegate::SetInstance(g_linux_ui);
+ ShellDialogLinux::SetInstance(g_linux_ui);
+ ui::SetTextEditKeyBindingsDelegate(g_linux_ui);
}
LinuxUI* LinuxUI::instance() {
diff --git a/chromium/ui/views/linux_ui/linux_ui.h b/chromium/ui/views/linux_ui/linux_ui.h
index ebcc4bea2ce..f632ca438dd 100644
--- a/chromium/ui/views/linux_ui/linux_ui.h
+++ b/chromium/ui/views/linux_ui/linux_ui.h
@@ -82,7 +82,7 @@ class VIEWS_EXPORT LinuxUI : public ui::LinuxInputMethodContextFactory,
~LinuxUI() override;
// Sets the dynamically loaded singleton that draws the desktop native UI.
- static void SetInstance(LinuxUI* instance);
+ static void SetInstance(std::unique_ptr<LinuxUI> instance);
// Returns a LinuxUI instance for the toolkit used in the user's desktop
// environment.
diff --git a/chromium/ui/views/masked_targeter_delegate.cc b/chromium/ui/views/masked_targeter_delegate.cc
index 5308dadb8bd..053d5053e7d 100644
--- a/chromium/ui/views/masked_targeter_delegate.cc
+++ b/chromium/ui/views/masked_targeter_delegate.cc
@@ -5,6 +5,7 @@
#include "ui/views/masked_targeter_delegate.h"
#include "third_party/skia/include/core/SkPath.h"
+#include "third_party/skia/include/core/SkRegion.h"
#include "ui/gfx/skia_util.h"
#include "ui/views/view.h"
diff --git a/chromium/ui/views/metadata/type_conversion.cc b/chromium/ui/views/metadata/type_conversion.cc
index 5e285feeb35..efa26762507 100644
--- a/chromium/ui/views/metadata/type_conversion.cc
+++ b/chromium/ui/views/metadata/type_conversion.cc
@@ -4,594 +4,59 @@
#include "ui/views/metadata/type_conversion.h"
-#include <cmath>
#include <string>
-#include "base/numerics/ranges.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_tokenizer.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
#include "components/url_formatter/url_fixer.h"
-#include "third_party/skia/include/core/SkScalar.h"
#include "ui/base/ime/text_input_type.h"
-#include "ui/gfx/color_utils.h"
-#include "ui/gfx/geometry/rect.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/controls/scroll_view.h"
-namespace views {
-namespace metadata {
-
-const char kNoPrefix[] = "";
-const char kSkColorPrefix[] = "--";
-
-std::u16string PointerToString(const void* pointer_val) {
- return pointer_val ? u"(assigned)" : u"(not assigned)";
-}
-
-const std::u16string& GetNullOptStr() {
- static const base::NoDestructor<std::u16string> kNullOptStr(u"<Empty>");
- return *kNullOptStr;
-}
-
-/***** String Conversions *****/
-
-#define CONVERT_NUMBER_TO_STRING(T) \
- std::u16string TypeConverter<T>::ToString(T source_value) { \
- return base::NumberToString16(source_value); \
- }
-
-CONVERT_NUMBER_TO_STRING(int8_t)
-CONVERT_NUMBER_TO_STRING(int16_t)
-CONVERT_NUMBER_TO_STRING(int32_t)
-CONVERT_NUMBER_TO_STRING(int64_t)
-CONVERT_NUMBER_TO_STRING(uint8_t)
-CONVERT_NUMBER_TO_STRING(uint16_t)
-CONVERT_NUMBER_TO_STRING(uint32_t)
-CONVERT_NUMBER_TO_STRING(uint64_t)
-CONVERT_NUMBER_TO_STRING(float)
-CONVERT_NUMBER_TO_STRING(double)
-
-std::u16string TypeConverter<bool>::ToString(bool source_value) {
- return base::ASCIIToUTF16(source_value ? "true" : "false");
-}
-
-ValidStrings TypeConverter<bool>::GetValidStrings() {
- return {u"false", u"true"};
-}
-
-std::u16string TypeConverter<const char*>::ToString(const char* source_value) {
- return base::UTF8ToUTF16(source_value);
-}
-
-std::u16string TypeConverter<base::FilePath>::ToString(
- const base::FilePath& source_value) {
- return source_value.AsUTF16Unsafe();
-}
-
-std::u16string TypeConverter<std::u16string>::ToString(
- const std::u16string& source_value) {
- return source_value;
-}
-
-std::u16string TypeConverter<base::TimeDelta>::ToString(
- const base::TimeDelta& source_value) {
- return base::NumberToString16(source_value.InSecondsF()) + u"s";
-}
-
-std::u16string TypeConverter<gfx::Insets>::ToString(
- const gfx::Insets& source_value) {
- return base::ASCIIToUTF16(source_value.ToString());
-}
-
-std::u16string TypeConverter<gfx::Point>::ToString(
- const gfx::Point& source_value) {
- return base::ASCIIToUTF16(source_value.ToString());
-}
-
-std::u16string TypeConverter<gfx::PointF>::ToString(
- const gfx::PointF& source_value) {
- return base::ASCIIToUTF16(source_value.ToString());
-}
-
-std::u16string TypeConverter<gfx::Range>::ToString(
- const gfx::Range& source_value) {
- return base::ASCIIToUTF16(source_value.ToString());
-}
-
-std::u16string TypeConverter<gfx::Rect>::ToString(
- const gfx::Rect& source_value) {
- return base::ASCIIToUTF16(source_value.ToString());
-}
-
-std::u16string TypeConverter<gfx::RectF>::ToString(
- const gfx::RectF& source_value) {
- return base::ASCIIToUTF16(source_value.ToString());
-}
-
-std::u16string TypeConverter<gfx::ShadowValues>::ToString(
- const gfx::ShadowValues& source_value) {
- std::u16string ret = u"[";
- for (auto shadow_value : source_value) {
- ret += base::ASCIIToUTF16(" " + shadow_value.ToString() + ";");
- }
-
- ret[ret.length() - 1] = ' ';
- ret += u"]";
- return ret;
-}
-
-std::u16string TypeConverter<gfx::Size>::ToString(
- const gfx::Size& source_value) {
- return base::ASCIIToUTF16(source_value.ToString());
-}
-
-std::u16string TypeConverter<gfx::SizeF>::ToString(
- const gfx::SizeF& source_value) {
- return base::ASCIIToUTF16(source_value.ToString());
-}
-
-std::u16string TypeConverter<GURL>::ToString(const GURL& source_value) {
+std::u16string ui::metadata::TypeConverter<GURL>::ToString(
+ const GURL& source_value) {
return base::ASCIIToUTF16(source_value.possibly_invalid_spec());
}
-std::u16string TypeConverter<url::Component>::ToString(
- const url::Component& source_value) {
- return base::ASCIIToUTF16(
- base::StringPrintf("{%d,%d}", source_value.begin, source_value.len));
-}
-
-base::Optional<int8_t> TypeConverter<int8_t>::FromString(
- const std::u16string& source_value) {
- int32_t ret = 0;
- if (base::StringToInt(source_value, &ret) &&
- base::IsValueInRangeForNumericType<int8_t>(ret)) {
- return static_cast<int8_t>(ret);
- }
- return base::nullopt;
-}
-
-base::Optional<int16_t> TypeConverter<int16_t>::FromString(
- const std::u16string& source_value) {
- int32_t ret = 0;
- if (base::StringToInt(source_value, &ret) &&
- base::IsValueInRangeForNumericType<int16_t>(ret)) {
- return static_cast<int16_t>(ret);
- }
- return base::nullopt;
-}
-
-base::Optional<int32_t> TypeConverter<int32_t>::FromString(
- const std::u16string& source_value) {
- int value;
- return base::StringToInt(source_value, &value) ? base::make_optional(value)
- : base::nullopt;
-}
-
-base::Optional<int64_t> TypeConverter<int64_t>::FromString(
- const std::u16string& source_value) {
- int64_t value;
- return base::StringToInt64(source_value, &value) ? base::make_optional(value)
- : base::nullopt;
-}
-
-base::Optional<uint8_t> TypeConverter<uint8_t>::FromString(
- const std::u16string& source_value) {
- unsigned ret = 0;
- if (base::StringToUint(source_value, &ret) &&
- base::IsValueInRangeForNumericType<uint8_t>(ret)) {
- return static_cast<uint8_t>(ret);
- }
- return base::nullopt;
-}
-
-base::Optional<uint16_t> TypeConverter<uint16_t>::FromString(
- const std::u16string& source_value) {
- unsigned ret = 0;
- if (base::StringToUint(source_value, &ret) &&
- base::IsValueInRangeForNumericType<uint16_t>(ret)) {
- return static_cast<uint16_t>(ret);
- }
- return base::nullopt;
-}
-
-base::Optional<uint32_t> TypeConverter<uint32_t>::FromString(
- const std::u16string& source_value) {
- unsigned value;
- return base::StringToUint(source_value, &value) ? base::make_optional(value)
- : base::nullopt;
-}
-
-base::Optional<uint64_t> TypeConverter<uint64_t>::FromString(
- const std::u16string& source_value) {
- uint64_t value;
- return base::StringToUint64(source_value, &value) ? base::make_optional(value)
- : base::nullopt;
-}
-
-base::Optional<float> TypeConverter<float>::FromString(
- const std::u16string& source_value) {
- if (base::Optional<double> temp =
- TypeConverter<double>::FromString(source_value))
- return static_cast<float>(temp.value());
- return base::nullopt;
-}
-
-base::Optional<double> TypeConverter<double>::FromString(
- const std::u16string& source_value) {
- double value;
- return base::StringToDouble(base::UTF16ToUTF8(source_value), &value)
- ? base::make_optional(value)
- : base::nullopt;
-}
-
-base::Optional<bool> TypeConverter<bool>::FromString(
- const std::u16string& source_value) {
- const bool is_true = source_value == u"true";
- if (is_true || source_value == u"false")
- return is_true;
- return base::nullopt;
-}
-
-base::Optional<std::u16string> TypeConverter<std::u16string>::FromString(
- const std::u16string& source_value) {
- return source_value;
-}
-
-base::Optional<base::FilePath> TypeConverter<base::FilePath>::FromString(
- const std::u16string& source_value) {
- return base::FilePath::FromUTF16Unsafe(source_value);
-}
-
-base::Optional<base::TimeDelta> TypeConverter<base::TimeDelta>::FromString(
- const std::u16string& source_value) {
- std::string source = base::UTF16ToUTF8(source_value);
- return base::TimeDelta::FromString(source);
-}
-
-base::Optional<gfx::Insets> TypeConverter<gfx::Insets>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitStringPiece(
- source_value, u",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- int top, left, bottom, right;
- if ((values.size() == 4) && base::StringToInt(values[0], &top) &&
- base::StringToInt(values[1], &left) &&
- base::StringToInt(values[2], &bottom) &&
- base::StringToInt(values[3], &right)) {
- return gfx::Insets(top, left, bottom, right);
- }
- return base::nullopt;
-}
-
-base::Optional<gfx::Point> TypeConverter<gfx::Point>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitStringPiece(
- source_value, u",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- int x, y;
- if ((values.size() == 2) && base::StringToInt(values[0], &x) &&
- base::StringToInt(values[1], &y)) {
- return gfx::Point(x, y);
- }
- return base::nullopt;
-}
-
-base::Optional<gfx::PointF> TypeConverter<gfx::PointF>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitStringPiece(
- source_value, u",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- double x, y;
- if ((values.size() == 2) && base::StringToDouble(values[0], &x) &&
- base::StringToDouble(values[1], &y)) {
- return gfx::PointF(x, y);
- }
- return base::nullopt;
-}
-
-base::Optional<gfx::Range> TypeConverter<gfx::Range>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitStringPiece(
- source_value, u"{,}", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- unsigned min, max;
- if ((values.size() == 2) && base::StringToUint(values[0], &min) &&
- base::StringToUint(values[1], &max)) {
- return gfx::Range(min, max);
- }
- return base::nullopt;
-}
-
-base::Optional<gfx::Rect> TypeConverter<gfx::Rect>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitString(
- source_value, u" ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- if (values.size() != 2)
- return base::nullopt;
- const base::Optional<gfx::Point> origin =
- TypeConverter<gfx::Point>::FromString(values[0]);
- const base::Optional<gfx::Size> size =
- TypeConverter<gfx::Size>::FromString(values[1]);
- if (origin && size)
- return gfx::Rect(*origin, *size);
- return base::nullopt;
-}
-
-base::Optional<gfx::RectF> TypeConverter<gfx::RectF>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitString(
- source_value, u" ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- if (values.size() != 2)
- return base::nullopt;
- const base::Optional<gfx::PointF> origin =
- TypeConverter<gfx::PointF>::FromString(values[0]);
- const base::Optional<gfx::SizeF> size =
- TypeConverter<gfx::SizeF>::FromString(values[1]);
- if (origin && size)
- return gfx::RectF(*origin, *size);
- return base::nullopt;
-}
-
-base::Optional<gfx::ShadowValues> TypeConverter<gfx::ShadowValues>::FromString(
- const std::u16string& source_value) {
- gfx::ShadowValues ret;
- const auto shadow_value_strings = base::SplitStringPiece(
- source_value, u"[;]", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-
- for (auto v : shadow_value_strings) {
- std::u16string value = std::u16string(v);
- base::String16Tokenizer tokenizer(
- value, u"(,)", base::String16Tokenizer::WhitespacePolicy::kSkipOver);
- tokenizer.set_options(base::String16Tokenizer::RETURN_DELIMS);
- int x, y;
- double blur;
- if (tokenizer.GetNext() && tokenizer.token() == u"(" &&
- tokenizer.GetNext() && base::StringToInt(tokenizer.token(), &x) &&
- tokenizer.GetNext() && tokenizer.token() == u"," &&
- tokenizer.GetNext() && base::StringToInt(tokenizer.token(), &y) &&
- tokenizer.GetNext() && tokenizer.token() == u")" &&
- tokenizer.GetNext() && tokenizer.token() == u"," &&
- tokenizer.GetNext() && base::StringToDouble(tokenizer.token(), &blur) &&
- tokenizer.GetNext() && tokenizer.token() == u"," &&
- tokenizer.GetNext()) {
- const auto color =
- SkColorConverter::GetNextColor(tokenizer.token_begin(), value.cend());
- if (color)
- ret.emplace_back(gfx::Vector2d(x, y), blur, color.value());
- }
- }
- return ret;
-}
-
-base::Optional<gfx::Size> TypeConverter<gfx::Size>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitStringPiece(
- source_value, u"x", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- int width, height;
- if ((values.size() == 2) && base::StringToInt(values[0], &width) &&
- base::StringToInt(values[1], &height)) {
- return gfx::Size(width, height);
- }
- return base::nullopt;
-}
-
-base::Optional<gfx::SizeF> TypeConverter<gfx::SizeF>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitStringPiece(
- source_value, u"x", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- double width, height;
- if ((values.size() == 2) && base::StringToDouble(values[0], &width) &&
- base::StringToDouble(values[1], &height)) {
- return gfx::SizeF(width, height);
- }
- return base::nullopt;
-}
-
-base::Optional<GURL> TypeConverter<GURL>::FromString(
+absl::optional<GURL> ui::metadata::TypeConverter<GURL>::FromString(
const std::u16string& source_value) {
const GURL url =
url_formatter::FixupURL(base::UTF16ToUTF8(source_value), std::string());
- return url.is_valid() ? base::make_optional(url) : base::nullopt;
-}
-
-base::Optional<url::Component> TypeConverter<url::Component>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitStringPiece(
- source_value, u"{,}", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- int begin, len;
- if ((values.size() == 2) && base::StringToInt(values[0], &begin) &&
- base::StringToInt(values[1], &len) && len >= -1) {
- return url::Component(begin, len);
- }
- return base::nullopt;
-}
-
-std::u16string TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ToString(
- SkColor source_value) {
- return base::UTF8ToUTF16(color_utils::SkColorToRgbaString(source_value));
-}
-
-base::Optional<SkColor> TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::FromString(
- const std::u16string& source_value) {
- return GetNextColor(source_value.cbegin(), source_value.cend());
+ return url.is_valid() ? absl::make_optional(url) : absl::nullopt;
}
-ValidStrings TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetValidStrings() {
+ui::metadata::ValidStrings
+ui::metadata::TypeConverter<GURL>::GetValidStrings() {
return {};
}
-bool TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
- std::u16string::const_iterator start,
- std::u16string::const_iterator end,
- std::u16string& color,
- std::u16string::const_iterator& next_token) {
- static const auto open_paren = u'(';
- static const auto close_paren = u')';
- static const std::vector<std::u16string> schemes = {u"hsl", u"hsla", u"rgb",
- u"rgba"};
- base::String16Tokenizer tokenizer(
- start, end, u"(,)", base::String16Tokenizer::WhitespacePolicy::kSkipOver);
- tokenizer.set_options(base::String16Tokenizer::RETURN_DELIMS);
- for (; tokenizer.GetNext();) {
- if (!tokenizer.token_is_delim()) {
- base::StringPiece16 token = tokenizer.token_piece();
- std::u16string::const_iterator start_color = tokenizer.token_begin();
- if (base::ranges::find(schemes.begin(), schemes.end(), token) !=
- schemes.end()) {
- if (!tokenizer.GetNext() || *tokenizer.token_begin() != open_paren)
- return false;
- for (;
- tokenizer.GetNext() && *tokenizer.token_begin() != close_paren;) {
- }
- if (*tokenizer.token_begin() != close_paren)
- return false;
- }
- next_token = tokenizer.token_end();
- color = std::u16string(start_color, next_token);
- return true;
- }
- }
- return false;
-}
-
-bool TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
- std::u16string::const_iterator start,
- std::u16string::const_iterator end,
- std::u16string& color) {
- std::u16string::const_iterator next_token;
- return GetNextColor(start, end, color, next_token);
-}
-
-base::Optional<SkColor> TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
- std::u16string::const_iterator start,
- std::u16string::const_iterator end,
- std::u16string::const_iterator& next_token) {
- std::u16string color;
- if (GetNextColor(start, end, color, next_token)) {
- if (base::StartsWith(color, u"hsl", base::CompareCase::SENSITIVE))
- return ParseHslString(color);
- if (base::StartsWith(color, u"rgb", base::CompareCase::SENSITIVE))
- return ParseRgbString(color);
- if (base::StartsWith(color, u"0x", base::CompareCase::INSENSITIVE_ASCII))
- return ParseHexString(color);
- SkColor value;
- if (base::StringToUint(color, &value))
- return base::make_optional(value);
- }
- return base::nullopt;
-}
-
-base::Optional<SkColor> TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
- std::u16string::const_iterator start,
- std::u16string::const_iterator end) {
- std::u16string::const_iterator next_token;
- return GetNextColor(start, end, next_token);
-}
-
-base::Optional<SkColor>
-TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::RgbaPiecesToSkColor(
- const std::vector<base::StringPiece16>& pieces,
- size_t start_piece) {
- int r, g, b;
- double a;
- return ((pieces.size() >= start_piece + 4) &&
- base::StringToInt(pieces[start_piece], &r) &&
- base::IsValueInRangeForNumericType<uint8_t>(r) &&
- base::StringToInt(pieces[start_piece + 1], &g) &&
- base::IsValueInRangeForNumericType<uint8_t>(g) &&
- base::StringToInt(pieces[start_piece + 2], &b) &&
- base::IsValueInRangeForNumericType<uint8_t>(b) &&
- base::StringToDouble(pieces[start_piece + 3], &a) && a >= 0.0 &&
- a <= 1.0)
- ? base::make_optional(SkColorSetARGB(
- base::ClampRound<SkAlpha>(a * SK_AlphaOPAQUE), r, g, b))
- : base::nullopt;
-}
-
-base::Optional<SkColor>
-TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ParseHexString(
- const std::u16string& hex_string) {
- SkColor value;
- if (base::HexStringToUInt(base::UTF16ToUTF8(hex_string), &value)) {
- // Add in a 1.0 alpha channel if it wasn't included in the input.
- if (hex_string.length() <= 8)
- value = SkColorSetA(value, 0xFF);
- return base::make_optional(value);
- }
- return base::nullopt;
-}
-
-base::Optional<SkColor>
-TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ParseHslString(
- const std::u16string& hsl_string) {
- std::u16string pruned_string;
- base::RemoveChars(hsl_string, u"(%)hsla", &pruned_string);
- const auto values = base::SplitStringPiece(
- pruned_string, u", ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- double h, s, v;
- double a = 1.0;
- if (values.size() >= 3 && values.size() <= 4 &&
- base::StringToDouble(values[0], &h) &&
- base::StringToDouble(values[1], &s) &&
- base::StringToDouble(values[2], &v) &&
- (values.size() == 3 ||
- (base::StringToDouble(values[3], &a) && a >= 0.0 && a <= 1.0))) {
- SkScalar hsv[3];
- hsv[0] = base::ClampToRange(std::fmod(h, 360.0), 0.0, 360.0);
- hsv[1] = s > 1.0 ? base::ClampToRange(s, 0.0, 100.0) / 100.0
- : base::ClampToRange(s, 0.0, 1.0);
- hsv[2] = v > 1.0 ? base::ClampToRange(v, 0.0, 100.0) / 100.0
- : base::ClampToRange(v, 0.0, 1.0);
- return base::make_optional(
- SkHSVToColor(base::ClampRound<SkAlpha>(a * SK_AlphaOPAQUE), hsv));
- }
- return base::nullopt;
-}
-
-base::Optional<SkColor>
-TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ParseRgbString(
- const std::u16string& rgb_string) {
- // Declare a constant string here for use below since it might trigger an
- // ASAN error due to the stack temp going out of scope before the call to
- // RgbaPiecesToSkColor.
- static const auto opaque_alpha = base::ASCIIToUTF16("1.0");
- std::u16string pruned_string;
- base::RemoveChars(rgb_string, u"()rgba", &pruned_string);
- auto values = base::SplitStringPiece(
- pruned_string, u", ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- // if it was just an rgb string, add the 1.0 alpha
- if (values.size() == 3)
- values.push_back(opaque_alpha);
- return RgbaPiecesToSkColor(values, 0);
-}
-
-} // namespace metadata
-} // namespace views
-
-DEFINE_ENUM_CONVERTERS(gfx::HorizontalAlignment,
- {gfx::HorizontalAlignment::ALIGN_LEFT, u"ALIGN_LEFT"},
- {gfx::HorizontalAlignment::ALIGN_CENTER,
- u"ALIGN_CENTER"},
- {gfx::HorizontalAlignment::ALIGN_RIGHT, u"ALIGN_RIGHT"},
- {gfx::HorizontalAlignment::ALIGN_TO_HEAD,
- u"ALIGN_TO_HEAD"})
+DEFINE_ENUM_CONVERTERS(
+ views::ScrollView::ScrollBarMode,
+ {views::ScrollView::ScrollBarMode::kDisabled, u"kDisabled"},
+ {views::ScrollView::ScrollBarMode::kHiddenButEnabled, u"kHiddenButEnabled"},
+ {views::ScrollView::ScrollBarMode::kEnabled, u"kEnabled"})
-DEFINE_ENUM_CONVERTERS(gfx::VerticalAlignment,
- {gfx::VerticalAlignment::ALIGN_TOP, u"ALIGN_TOP"},
- {gfx::VerticalAlignment::ALIGN_MIDDLE, u"ALIGN_MIDDLE"},
- {gfx::VerticalAlignment::ALIGN_BOTTOM, u"ALIGN_BOTTOM"})
+DEFINE_ENUM_CONVERTERS(
+ views::BubbleFrameView::PreferredArrowAdjustment,
+ {views::BubbleFrameView::PreferredArrowAdjustment::kMirror, u"kMirror"},
+ {views::BubbleFrameView::PreferredArrowAdjustment::kOffset, u"kOffset"})
-DEFINE_ENUM_CONVERTERS(gfx::ElideBehavior,
- {gfx::ElideBehavior::NO_ELIDE, u"NO_ELIDE"},
- {gfx::ElideBehavior::TRUNCATE, u"TRUNCATE"},
- {gfx::ElideBehavior::ELIDE_HEAD, u"ELIDE_HEAD"},
- {gfx::ElideBehavior::ELIDE_MIDDLE, u"ELIDE_MIDDLE"},
- {gfx::ElideBehavior::ELIDE_TAIL, u"ELIDE_TAIL"},
- {gfx::ElideBehavior::ELIDE_EMAIL, u"ELIDE_EMAIL"},
- {gfx::ElideBehavior::FADE_TAIL, u"FADE_TAIL"})
+DEFINE_ENUM_CONVERTERS(
+ views::BubbleBorder::Arrow,
+ {views::BubbleBorder::Arrow::TOP_LEFT, u"TOP_LEFT"},
+ {views::BubbleBorder::Arrow::TOP_RIGHT, u"TOP_RIGHT"},
+ {views::BubbleBorder::Arrow::BOTTOM_LEFT, u"BOTTOM_LEFT"},
+ {views::BubbleBorder::Arrow::BOTTOM_RIGHT, u"BOTTOM_RIGHT"},
+ {views::BubbleBorder::Arrow::LEFT_TOP, u"LEFT_TOP"},
+ {views::BubbleBorder::Arrow::RIGHT_TOP, u"RIGHT_TOP"},
+ {views::BubbleBorder::Arrow::LEFT_BOTTOM, u"LEFT_BOTTOM"},
+ {views::BubbleBorder::Arrow::RIGHT_BOTTOM, u"RIGHT_BOTTOM"},
+ {views::BubbleBorder::Arrow::TOP_CENTER, u"TOP_CENTER"},
+ {views::BubbleBorder::Arrow::BOTTOM_CENTER, u"BOTTOM_CENTER"},
+ {views::BubbleBorder::Arrow::LEFT_CENTER, u"LEFT_CENTER"},
+ {views::BubbleBorder::Arrow::RIGHT_CENTER, u"RIGHT_CENTER"},
+ {views::BubbleBorder::Arrow::NONE, u"NONE"},
+ {views::BubbleBorder::Arrow::FLOAT, u"FLOAT"})
DEFINE_ENUM_CONVERTERS(
ui::TextInputType,
@@ -618,48 +83,9 @@ DEFINE_ENUM_CONVERTERS(
u"TEXT_INPUT_TYPE_CONTENT_EDITABLE"},
{ui::TextInputType::TEXT_INPUT_TYPE_DATE_TIME_FIELD,
u"TEXT_INPUT_TYPE_DATE_TIME_FIELD"},
- {ui::TextInputType::TEXT_INPUT_TYPE_NULL, u"TEXT_INPUT_TYPE_NULL"},
- {ui::TextInputType::TEXT_INPUT_TYPE_MAX, u"TEXT_INPUT_TYPE_MAX"})
-
-DEFINE_ENUM_CONVERTERS(
- ui::MenuSeparatorType,
- {ui::MenuSeparatorType::NORMAL_SEPARATOR, u"NORMAL_SEPARATOR"},
- {ui::MenuSeparatorType::DOUBLE_SEPARATOR, u"DOUBLE_SEPARATOR"},
- {ui::MenuSeparatorType::UPPER_SEPARATOR, u"UPPER_SEPARATOR"},
- {ui::MenuSeparatorType::LOWER_SEPARATOR, u"LOWER_SEPARATOR"},
- {ui::MenuSeparatorType::SPACING_SEPARATOR, u"SPACING_SEPARATOR"},
- {ui::MenuSeparatorType::VERTICAL_SEPARATOR, u"VERTICAL_SEPARATOR"},
- {ui::MenuSeparatorType::PADDED_SEPARATOR, u"PADDED_SEPARATOR"})
-
-DEFINE_ENUM_CONVERTERS(
- views::ScrollView::ScrollBarMode,
- {views::ScrollView::ScrollBarMode::kDisabled, u"kDisabled"},
- {views::ScrollView::ScrollBarMode::kHiddenButEnabled, u"kHiddenButEnabled"},
- {views::ScrollView::ScrollBarMode::kEnabled, u"kEnabled"})
-
-DEFINE_ENUM_CONVERTERS(
- views::BubbleFrameView::PreferredArrowAdjustment,
- {views::BubbleFrameView::PreferredArrowAdjustment::kMirror, u"kMirror"},
- {views::BubbleFrameView::PreferredArrowAdjustment::kOffset, u"kOffset"})
-
-DEFINE_ENUM_CONVERTERS(
- views::BubbleBorder::Arrow,
- {views::BubbleBorder::Arrow::TOP_LEFT, u"TOP_LEFT"},
- {views::BubbleBorder::Arrow::TOP_RIGHT, u"TOP_RIGHT"},
- {views::BubbleBorder::Arrow::BOTTOM_LEFT, u"BOTTOM_LEFT"},
- {views::BubbleBorder::Arrow::BOTTOM_RIGHT, u"BOTTOM_RIGHT"},
- {views::BubbleBorder::Arrow::LEFT_TOP, u"LEFT_TOP"},
- {views::BubbleBorder::Arrow::RIGHT_TOP, u"RIGHT_TOP"},
- {views::BubbleBorder::Arrow::LEFT_BOTTOM, u"LEFT_BOTTOM"},
- {views::BubbleBorder::Arrow::RIGHT_BOTTOM, u"RIGHT_BOTTOM"},
- {views::BubbleBorder::Arrow::TOP_CENTER, u"TOP_CENTER"},
- {views::BubbleBorder::Arrow::BOTTOM_CENTER, u"BOTTOM_CENTER"},
- {views::BubbleBorder::Arrow::LEFT_CENTER, u"LEFT_CENTER"},
- {views::BubbleBorder::Arrow::RIGHT_CENTER, u"RIGHT_CENTER"},
- {views::BubbleBorder::Arrow::NONE, u"NONE"},
- {views::BubbleBorder::Arrow::FLOAT, u"FLOAT"})
+ {ui::TextInputType::TEXT_INPUT_TYPE_NULL, u"TEXT_INPUT_TYPE_NULL"})
#define OP(enum_name) \
- { ui::NativeTheme::enum_name, base::ASCIIToUTF16(#enum_name) }
+ { ui::NativeTheme::enum_name, u## #enum_name }
DEFINE_ENUM_CONVERTERS(ui::NativeTheme::ColorId, NATIVE_THEME_COLOR_IDS)
#undef OP
diff --git a/chromium/ui/views/metadata/type_conversion.h b/chromium/ui/views/metadata/type_conversion.h
index 1fe5e5f5ec2..b7dc263945f 100644
--- a/chromium/ui/views/metadata/type_conversion.h
+++ b/chromium/ui/views/metadata/type_conversion.h
@@ -5,359 +5,16 @@
#ifndef UI_VIEWS_METADATA_TYPE_CONVERSION_H_
#define UI_VIEWS_METADATA_TYPE_CONVERSION_H_
-#include <stdint.h>
-
-#include <algorithm> // Silence broken lint check
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/no_destructor.h"
-#include "base/optional.h"
-#include "base/ranges/algorithm.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "ui/gfx/geometry/insets.h"
-#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/geometry/point_f.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/rect_f.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/geometry/size_f.h"
-#include "ui/gfx/range/range.h"
-#include "ui/gfx/shadow_value.h"
-#include "ui/gfx/text_constants.h"
+#include "ui/base/metadata/base_type_conversion.h"
#include "ui/views/views_export.h"
#include "url/gurl.h"
-#include "url/third_party/mozilla/url_parse.h"
-
-namespace views {
-namespace metadata {
-
-using ValidStrings = std::vector<std::u16string>;
-
-// Various metadata methods pass types either by value or const ref depending on
-// whether the types are "small" (defined as "fundamental, enum, or pointer").
-// ArgType<T> gives the appropriate type to use as an argument in such cases.
-template <typename T>
-using ArgType =
- typename std::conditional<std::is_fundamental<T>::value ||
- std::is_enum<T>::value ||
- std::is_pointer<T>::value ||
- (std::is_move_assignable<T>::value &&
- std::is_move_constructible<T>::value &&
- !std::is_copy_assignable<T>::value &&
- !std::is_copy_constructible<T>::value),
- T,
- const T&>::type;
-
-VIEWS_EXPORT extern const char kNoPrefix[];
-VIEWS_EXPORT extern const char kSkColorPrefix[];
-
-// General Type Conversion Template Functions ---------------------------------
-template <bool serializable,
- bool read_only = false,
- const char* name_prefix = kNoPrefix>
-struct BaseTypeConverter {
- static constexpr bool is_serializable = serializable;
- static constexpr bool is_read_only = read_only;
- static bool IsSerializable() { return is_serializable; }
- static bool IsReadOnly() { return is_read_only; }
- static const char* PropertyNamePrefix() { return name_prefix; }
-};
-
-template <typename T>
-struct TypeConverter : BaseTypeConverter<std::is_enum<T>::value> {
- static std::u16string ToString(ArgType<T> source_value);
- static base::Optional<T> FromString(const std::u16string& source_value);
- static ValidStrings GetValidStrings();
-};
-
-// The following definitions and macros are needed only in cases where a type
-// is a mere alias to a POD type AND a specialized type converter is also needed
-// to handle different the string conversions different from the existing POD
-// type converter. See SkColor below as an example of their use.
-// NOTE: This should be a rare occurrence and if possible use a unique type and
-// a TypeConverter specialization based on that unique type.
-
-template <typename T, typename K>
-struct Uniquifier {
- using type = T;
- using tag = K;
-};
-
-#define MAKE_TYPE_UNIQUE(type_name) \
- struct type_name##Tag {}; \
- using type_name##Unique = \
- ::views::metadata::Uniquifier<type_name, type_name##Tag>
-
-#define _UNIQUE_TYPE_NAME1(type_name) type_name##Unique
-
-#define _UNIQUE_TYPE_NAME2(qualifier, type_name) qualifier::type_name##Unique
-
-#define _GET_TYPE_MACRO(_1, _2, NAME, ...) NAME
-
-#define UNIQUE_TYPE_NAME(name, ...) \
- _GET_TYPE_MACRO(name, ##__VA_ARGS__, _UNIQUE_TYPE_NAME2, _UNIQUE_TYPE_NAME1) \
- (name, ##__VA_ARGS__)
-
-// Types and macros for generating enum converters ----------------------------
-template <typename T>
-struct EnumStrings {
- struct EnumString {
- T enum_value;
- std::u16string str_value;
- };
-
- explicit EnumStrings(std::vector<EnumString> init_val)
- : pairs(std::move(init_val)) {}
-
- ValidStrings GetStringValues() const {
- ValidStrings string_values;
- for (const auto& pair : pairs)
- string_values.push_back(pair.str_value);
- return string_values;
- }
-
- const std::vector<EnumString> pairs;
-};
-
-template <typename T>
-static const EnumStrings<T>& GetEnumStringsInstance();
-
-// Generate the code to define a enum type to and from std::u16string
-// conversions. The first argument is the type T, and the rest of the argument
-// should have the enum value and string pairs defined in a format like
-// "{enum_value0, string16_value0}, {enum_value1, string16_value1} ...".
-#define DEFINE_ENUM_CONVERTERS(T, ...) \
- template <> \
- const views::metadata::EnumStrings<T>& \
- views::metadata::GetEnumStringsInstance<T>() { \
- static const base::NoDestructor<EnumStrings<T>> instance( \
- std::vector<views::metadata::EnumStrings<T>::EnumString>( \
- {__VA_ARGS__})); \
- return *instance; \
- } \
- \
- template <> \
- std::u16string views::metadata::TypeConverter<T>::ToString( \
- ArgType<T> source_value) { \
- for (const auto& pair : GetEnumStringsInstance<T>().pairs) { \
- if (source_value == pair.enum_value) \
- return pair.str_value; \
- } \
- return std::u16string(); \
- } \
- \
- template <> \
- base::Optional<T> views::metadata::TypeConverter<T>::FromString( \
- const std::u16string& source_value) { \
- for (const auto& pair : GetEnumStringsInstance<T>().pairs) { \
- if (source_value == pair.str_value) { \
- return pair.enum_value; \
- } \
- } \
- return base::nullopt; \
- } \
- \
- template <> \
- views::metadata::ValidStrings \
- views::metadata::TypeConverter<T>::GetValidStrings() { \
- return GetEnumStringsInstance<T>().GetStringValues(); \
- }
-
-// String Conversions ---------------------------------------------------------
-
-VIEWS_EXPORT std::u16string PointerToString(const void* pointer_val);
-
-#define DECLARE_CONVERSIONS(T) \
- template <> \
- struct VIEWS_EXPORT TypeConverter<T> : BaseTypeConverter<true> { \
- static std::u16string ToString(ArgType<T> source_value); \
- static base::Optional<T> FromString(const std::u16string& source_value); \
- static ValidStrings GetValidStrings() { return {}; } \
- };
-
-DECLARE_CONVERSIONS(int8_t)
-DECLARE_CONVERSIONS(int16_t)
-DECLARE_CONVERSIONS(int32_t)
-DECLARE_CONVERSIONS(int64_t)
-DECLARE_CONVERSIONS(uint8_t)
-DECLARE_CONVERSIONS(uint16_t)
-DECLARE_CONVERSIONS(uint32_t)
-DECLARE_CONVERSIONS(uint64_t)
-DECLARE_CONVERSIONS(float)
-DECLARE_CONVERSIONS(double)
-DECLARE_CONVERSIONS(const char*)
-DECLARE_CONVERSIONS(base::FilePath)
-DECLARE_CONVERSIONS(std::u16string)
-DECLARE_CONVERSIONS(base::TimeDelta)
-DECLARE_CONVERSIONS(gfx::Insets)
-DECLARE_CONVERSIONS(gfx::Point)
-DECLARE_CONVERSIONS(gfx::PointF)
-DECLARE_CONVERSIONS(gfx::Range)
-DECLARE_CONVERSIONS(gfx::Rect)
-DECLARE_CONVERSIONS(gfx::RectF)
-DECLARE_CONVERSIONS(gfx::ShadowValues)
-DECLARE_CONVERSIONS(gfx::Size)
-DECLARE_CONVERSIONS(gfx::SizeF)
-DECLARE_CONVERSIONS(GURL)
-DECLARE_CONVERSIONS(url::Component)
-
-#undef DECLARE_CONVERSIONS
-
-template <>
-struct VIEWS_EXPORT TypeConverter<bool> : BaseTypeConverter<true> {
- static std::u16string ToString(bool source_value);
- static base::Optional<bool> FromString(const std::u16string& source_value);
- static ValidStrings GetValidStrings();
-};
-
-// Special conversions for wrapper types --------------------------------------
-
-VIEWS_EXPORT const std::u16string& GetNullOptStr();
-
-template <typename T>
-struct TypeConverter<base::Optional<T>>
- : BaseTypeConverter<TypeConverter<T>::is_serializable> {
- static std::u16string ToString(ArgType<base::Optional<T>> source_value) {
- if (!source_value)
- return GetNullOptStr();
- return TypeConverter<T>::ToString(source_value.value());
- }
- static base::Optional<base::Optional<T>> FromString(
- const std::u16string& source_value) {
- if (source_value == GetNullOptStr())
- return base::make_optional<base::Optional<T>>(base::nullopt);
-
- auto ret = TypeConverter<T>::FromString(source_value);
- return ret ? base::make_optional(ret) : base::nullopt;
- }
- static ValidStrings GetValidStrings() { return {}; }
-};
-
-// Special Conversions for std:unique_ptr<T> and T* types ----------------------
-
-template <typename T>
-struct TypeConverter<std::unique_ptr<T>> : BaseTypeConverter<false, true> {
- static std::u16string ToString(const std::unique_ptr<T>& source_value) {
- return PointerToString(source_value.get());
- }
- static std::u16string ToString(const T* source_value) {
- return PointerToString(source_value);
- }
- static base::Optional<std::unique_ptr<T>> FromString(
- const std::u16string& source_value) {
- DCHECK(false) << "Type converter cannot convert from string.";
- return base::nullopt;
- }
- static ValidStrings GetValidStrings() { return {}; }
-};
-
-template <typename T>
-struct TypeConverter<T*> : BaseTypeConverter<false, true> {
- static std::u16string ToString(ArgType<T*> source_value) {
- return PointerToString(source_value);
- }
- static base::Optional<T*> FromString(const std::u16string& source_value) {
- DCHECK(false) << "Type converter cannot convert from string.";
- return base::nullopt;
- }
- static ValidStrings GetValidStrings() { return {}; }
-};
-
-template <typename T>
-struct TypeConverter<std::vector<T>>
- : BaseTypeConverter<TypeConverter<T>::is_serializable> {
- static std::u16string ToString(ArgType<std::vector<T>> source_value) {
- std::vector<std::u16string> serialized;
- base::ranges::transform(source_value, std::back_inserter(serialized),
- &TypeConverter<T>::ToString);
- return u"{" + base::JoinString(serialized, u",") + u"}";
- }
- static base::Optional<std::vector<T>> FromString(
- const std::u16string& source_value) {
- if (source_value.empty() || source_value.front() != u'{' ||
- source_value.back() != u'}')
- return base::nullopt;
- const auto values =
- base::SplitString(source_value.substr(1, source_value.length() - 2),
- u",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- std::vector<T> output;
- for (const auto& value : values) {
- auto ret = TypeConverter<T>::FromString(value);
- if (!ret)
- return base::nullopt;
- output.push_back(*ret);
- }
- return base::make_optional(output);
- }
- static ValidStrings GetValidStrings() { return {}; }
-};
-
-MAKE_TYPE_UNIQUE(SkColor);
template <>
-struct VIEWS_EXPORT TypeConverter<UNIQUE_TYPE_NAME(SkColor)>
- : BaseTypeConverter<true, false, kSkColorPrefix> {
- static std::u16string ToString(SkColor source_value);
- static base::Optional<SkColor> FromString(const std::u16string& source_value);
- static ValidStrings GetValidStrings();
-
- // Parses a string within |start| and |end| for a color string in the forms
- // rgb(r, g, b), rgba(r, g, b, a), hsl(h, s%, l%), hsla(h, s%, l%, a),
- // 0xXXXXXX, 0xXXXXXXXX, <decimal number>
- // Returns the full string in |color| and the position immediately following
- // the last token in |next_token|.
- // Returns false if the input string cannot be properly parsed. |color| and
- // |next_token| will be undefined.
- static bool GetNextColor(std::u16string::const_iterator start,
- std::u16string::const_iterator end,
- std::u16string& color,
- std::u16string::const_iterator& next_token);
- static bool GetNextColor(std::u16string::const_iterator start,
- std::u16string::const_iterator end,
- std::u16string& color);
-
- // Same as above, except returns the color string converted into an |SkColor|.
- // Returns base::nullopt if the color string cannot be properly parsed or the
- // string cannot be converted into a valid SkColor and |next_token| may be
- // undefined.
- static base::Optional<SkColor> GetNextColor(
- std::u16string::const_iterator start,
- std::u16string::const_iterator end,
- std::u16string::const_iterator& next_token);
- static base::Optional<SkColor> GetNextColor(
- std::u16string::const_iterator start,
- std::u16string::const_iterator end);
-
- // Converts the four elements of |pieces| beginning at |start_piece| to an
- // SkColor by assuming the pieces are split from a string like
- // "rgba(r,g,b,a)". Returns nullopt if conversion was unsuccessful.
- static base::Optional<SkColor> RgbaPiecesToSkColor(
- const std::vector<base::StringPiece16>& pieces,
- size_t start_piece);
-
- private:
- static base::Optional<SkColor> ParseHexString(
- const std::u16string& hex_string);
- static base::Optional<SkColor> ParseHslString(
- const std::u16string& hsl_string);
- static base::Optional<SkColor> ParseRgbString(
- const std::u16string& rgb_string);
+struct VIEWS_EXPORT ui::metadata::TypeConverter<GURL>
+ : BaseTypeConverter<true> {
+ static std::u16string ToString(const GURL& source_value);
+ static absl::optional<GURL> FromString(const std::u16string& source_value);
+ static ui::metadata::ValidStrings GetValidStrings();
};
-using SkColorConverter = TypeConverter<UNIQUE_TYPE_NAME(SkColor)>;
-
-} // namespace metadata
-} // namespace views
-
#endif // UI_VIEWS_METADATA_TYPE_CONVERSION_H_
diff --git a/chromium/ui/views/metadata/type_conversion_unittest.cc b/chromium/ui/views/metadata/type_conversion_unittest.cc
index 43630a0c7d4..b4017140ae0 100644
--- a/chromium/ui/views/metadata/type_conversion_unittest.cc
+++ b/chromium/ui/views/metadata/type_conversion_unittest.cc
@@ -1,263 +1,24 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/views/metadata/type_conversion.h"
-#include "base/ranges/ranges.h"
-#include "base/strings/string_tokenizer.h"
-#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
-#include "ui/gfx/geometry/insets.h"
-#include "ui/gfx/geometry/rect.h"
#include "ui/views/controls/button/button.h"
+#include "ui/views/controls/focus_ring.h"
-using TypeConversionTest = PlatformTest;
-
-namespace views {
-
-// Used in CheckIsSerializable test case.
-enum TestResult {
- TEST_TRUE,
- TEST_FALSE,
-};
-DEFINE_ENUM_CONVERTERS(TestResult, {TEST_TRUE, u"TRUE"}, {TEST_FALSE, u"FALSE"})
-
-TEST_F(TypeConversionTest, TestConversion_IntToString) {
- int from_int = 5;
- std::u16string to_string = metadata::TypeConverter<int>::ToString(from_int);
-
- EXPECT_EQ(to_string, u"5");
-}
-
-TEST_F(TypeConversionTest, TestConversion_StringToInt) {
- std::u16string from_string = u"10";
- EXPECT_EQ(metadata::TypeConverter<int>::FromString(from_string), 10);
-}
-
-// This tests whether the converter handles a bogus input string, in which case
-// the return value should be nullopt.
-TEST_F(TypeConversionTest, TestConversion_BogusStringToInt) {
- std::u16string from_string = u"Foo";
- EXPECT_EQ(metadata::TypeConverter<int>::FromString(from_string),
- base::nullopt);
-}
-
-TEST_F(TypeConversionTest, TestConversion_BogusStringToFloat) {
- std::u16string from_string = u"1.2";
- EXPECT_EQ(metadata::TypeConverter<float>::FromString(from_string), 1.2f);
-}
-
-TEST_F(TypeConversionTest, TestConversion_OptionalIntToString) {
- base::Optional<int> src;
- std::u16string to_string =
- metadata::TypeConverter<base::Optional<int>>::ToString(src);
- EXPECT_EQ(to_string, metadata::GetNullOptStr());
-
- src = 5;
- to_string = metadata::TypeConverter<base::Optional<int>>::ToString(src);
- EXPECT_EQ(to_string, u"5");
-}
-
-TEST_F(TypeConversionTest, TestConversion_StringToOptionalInt) {
- base::Optional<int> ret;
- EXPECT_EQ(metadata::TypeConverter<base::Optional<int>>::FromString(
- metadata::GetNullOptStr()),
- base::make_optional(ret));
-
- EXPECT_EQ(metadata::TypeConverter<base::Optional<int>>::FromString(u"10"),
- 10);
-
- EXPECT_EQ(metadata::TypeConverter<base::Optional<int>>::FromString(u"ab0"),
- base::nullopt);
-}
-
-TEST_F(TypeConversionTest, TestConversion_ShadowValuesToString) {
- gfx::ShadowValues shadow_values;
- shadow_values.emplace_back(gfx::Vector2d(1, 2), .3,
- SkColorSetARGB(128, 255, 0, 0));
-
- EXPECT_EQ(metadata::TypeConverter<gfx::ShadowValues>::ToString(shadow_values),
- u"[ (1,2),0.30,rgba(255,0,0,128) ]");
-
- shadow_values.emplace_back(gfx::Vector2d(9, 8), .76,
- SkColorSetARGB(20, 0, 64, 255));
-
- EXPECT_EQ(
- metadata::TypeConverter<gfx::ShadowValues>::ToString(shadow_values),
- base::ASCIIToUTF16(
- "[ (1,2),0.30,rgba(255,0,0,128); (9,8),0.76,rgba(0,64,255,20) ]"));
-}
-
-TEST_F(TypeConversionTest, TestConversion_StringToShadowValues) {
- base::Optional<gfx::ShadowValues> opt_result =
- metadata::TypeConverter<gfx::ShadowValues>::FromString(base::ASCIIToUTF16(
- "[ (6,4),0.53,rgba(23,44,0,1); (93,83),4.33,rgba(10,20,0,0.059) ]"));
-
- EXPECT_EQ(opt_result.has_value(), true);
- gfx::ShadowValues result = opt_result.value();
- EXPECT_EQ(result.size(), 2U);
-
- EXPECT_EQ(result[0].color(), SkColorSetARGB(255, 23, 44, 0));
- EXPECT_EQ(result[1].color(), SkColorSetARGB(15, 10, 20, 0));
-
- EXPECT_EQ(result[0].x(), 6);
- EXPECT_EQ(result[1].x(), 93);
-
- EXPECT_EQ(result[0].y(), 4);
- EXPECT_EQ(result[1].y(), 83);
-
- EXPECT_EQ(result[0].blur(), 0.53);
- EXPECT_EQ(result[1].blur(), 4.33);
-}
-
-TEST_F(TypeConversionTest, TestConversion_SkColorConversions) {
- // Check conversion from rgb hex string
- base::Optional<SkColor> result =
- metadata::SkColorConverter::FromString(u"0x112233");
- EXPECT_TRUE(result);
- EXPECT_EQ(result.value(), SkColorSetRGB(0x11, 0x22, 0x33));
-
- // Check conversion from argb hex string
- result = metadata::SkColorConverter::FromString(u"0x7F112233");
- EXPECT_TRUE(result);
- EXPECT_EQ(result.value(), SkColorSetARGB(0x7F, 0x11, 0x22, 0x33));
-
- // Check conversion from rgb(r,g,b) string
- result = metadata::SkColorConverter::FromString(u"rgb(0, 128, 192)");
- EXPECT_TRUE(result);
- EXPECT_EQ(result.value(), SkColorSetRGB(0, 128, 192));
-
- // Check conversion from rgba(r,g,b,a) string
- result = metadata::SkColorConverter::FromString(u"rgba(0, 128, 192, 0.5)");
- EXPECT_TRUE(result);
- EXPECT_EQ(result.value(), SkColorSetARGB(128, 0, 128, 192));
-
- // Check conversion from hsl(h,s,l) string
- result = metadata::SkColorConverter::FromString(u"hsl(195, 100%, 50%)");
- EXPECT_TRUE(result);
- const SkScalar hsv[3] = {195.0, 1.0, 0.5};
- EXPECT_EQ(result.value(), SkHSVToColor(hsv));
-
- // Check conversion from hsla(h,s,l,a) string
- result = metadata::SkColorConverter::FromString(u"hsl(195, 100%, 50%, 0.5)");
- EXPECT_TRUE(result);
- EXPECT_EQ(result.value(), SkHSVToColor(128, hsv));
-
- // Check conversion from a decimal integer value
- result = metadata::SkColorConverter::FromString(u"4278239231");
- EXPECT_TRUE(result);
- EXPECT_EQ(result.value(), SkColorSetARGB(255, 0, 191, 255));
-
- // Check without commas.
- result = metadata::SkColorConverter::FromString(u"rgba(92 92 92 1)");
- EXPECT_TRUE(result);
- EXPECT_EQ(result.value(), SkColorSetARGB(255, 92, 92, 92));
-
- // Don't support the CSS hash color style
- result = metadata::SkColorConverter::FromString(u"#03254");
- EXPECT_FALSE(result);
-
- // Don't support some common invalid values
- result = metadata::SkColorConverter::FromString(u"rgba(1,2,3,4)");
- EXPECT_FALSE(result);
-
- result = metadata::SkColorConverter::FromString(u"rgba(1,2,3,4");
- EXPECT_FALSE(result);
-
- result = metadata::SkColorConverter::FromString(u"hsla(1,2,3,4)");
- EXPECT_FALSE(result);
-}
-
-TEST_F(TypeConversionTest, TestConversion_ColorParserTest) {
- using converter = metadata::SkColorConverter;
- std::u16string color;
- const std::u16string source = base::ASCIIToUTF16(
- "rgb(0, 128, 192), hsl(90, 100%, 30%), rgba(128, 128, 128, 0.5), "
- "hsla(240, 100%, 50%, 0.5)");
- auto start_pos = source.cbegin();
- EXPECT_TRUE(
- converter::GetNextColor(start_pos, source.cend(), color, start_pos));
- EXPECT_EQ(color, u"rgb(0, 128, 192)");
- EXPECT_TRUE(
- converter::GetNextColor(start_pos, source.cend(), color, start_pos));
- EXPECT_EQ(color, u"hsl(90, 100%, 30%)");
- EXPECT_TRUE(
- converter::GetNextColor(start_pos, source.cend(), color, start_pos));
- EXPECT_EQ(color, u"rgba(128, 128, 128, 0.5)");
- EXPECT_TRUE(converter::GetNextColor(start_pos, source.cend(), color));
- EXPECT_EQ(color, u"hsla(240, 100%, 50%, 0.5)");
-}
-
-TEST_F(TypeConversionTest, TestConversion_InsetsToString) {
- constexpr gfx::Insets kInsets(3, 5, 7, 9);
-
- std::u16string to_string =
- metadata::TypeConverter<gfx::Insets>::ToString(kInsets);
-
- EXPECT_EQ(to_string, base::ASCIIToUTF16(kInsets.ToString()));
-}
-
-TEST_F(TypeConversionTest, TestConversion_StringToInsets) {
- std::u16string from_string = u"2,3,4,5";
- EXPECT_EQ(metadata::TypeConverter<gfx::Insets>::FromString(from_string),
- gfx::Insets(2, 3, 4, 5));
-}
-
-TEST_F(TypeConversionTest, TestConversion_VectorToString) {
- const std::vector<int> kVector{3, 5, 7, 9};
-
- std::u16string to_string =
- metadata::TypeConverter<std::vector<int>>::ToString(kVector);
-
- EXPECT_EQ(to_string, u"{3,5,7,9}");
-}
-
-TEST_F(TypeConversionTest, TestConversion_StringToVector) {
- std::u16string from_string = u"{2,3,4,5}";
- EXPECT_EQ(metadata::TypeConverter<std::vector<int>>::FromString(from_string),
- std::vector<int>({2, 3, 4, 5}));
-}
-
-TEST_F(TypeConversionTest, CheckIsSerializable) {
- // Test types with explicitly added converters.
- EXPECT_TRUE(metadata::TypeConverter<int8_t>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<int16_t>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<int32_t>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<int64_t>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<uint8_t>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<uint16_t>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<uint32_t>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<uint64_t>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<float>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<double>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<bool>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<const char*>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<std::u16string>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<gfx::ShadowValues>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<gfx::Size>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<gfx::Range>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<gfx::Insets>::IsSerializable());
-
- // Test enum type.
- EXPECT_TRUE(metadata::TypeConverter<TestResult>::IsSerializable());
-
- // Test aliased types.
- EXPECT_TRUE(metadata::TypeConverter<int>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<SkColor>::IsSerializable());
+using ViewsTypeConversionTest = PlatformTest;
+TEST_F(ViewsTypeConversionTest, CheckIsSerializable) {
// Test types with no explicit or aliased converters.
- EXPECT_FALSE(metadata::TypeConverter<
+ EXPECT_FALSE(ui::metadata::TypeConverter<
views::Button::PressedCallback>::IsSerializable());
- EXPECT_FALSE(metadata::TypeConverter<views::FocusRing*>::IsSerializable());
+ EXPECT_FALSE(
+ ui::metadata::TypeConverter<views::FocusRing*>::IsSerializable());
- // Test base::Optional type.
- EXPECT_TRUE(
- metadata::TypeConverter<base::Optional<const char*>>::IsSerializable());
- EXPECT_TRUE(metadata::TypeConverter<base::Optional<int>>::IsSerializable());
- EXPECT_FALSE(metadata::TypeConverter<
- base::Optional<views::FocusRing*>>::IsSerializable());
+ // Test absl::optional type.
+ EXPECT_FALSE(ui::metadata::TypeConverter<
+ absl::optional<views::FocusRing*>>::IsSerializable());
}
-
-} // namespace views
diff --git a/chromium/ui/views/metadata/view_factory.h b/chromium/ui/views/metadata/view_factory.h
index 972ebcfaaca..5a770ce895a 100644
--- a/chromium/ui/views/metadata/view_factory.h
+++ b/chromium/ui/views/metadata/view_factory.h
@@ -12,7 +12,7 @@
#include <utility>
#include "ui/base/class_property.h"
-#include "ui/views/metadata/type_conversion.h"
+#include "ui/base/metadata/base_type_conversion.h"
#include "ui/views/metadata/view_factory_internal.h"
#include "ui/views/views_export.h"
@@ -63,7 +63,7 @@ class BaseViewBuilderT : public internal::ViewBuilderCore {
template <typename T>
Builder& SetProperty(const ui::ClassProperty<T>* property,
- metadata::ArgType<T> value) {
+ ui::metadata::ArgType<T> value) {
auto setter =
std::make_unique<internal::ClassPropertyValueSetter<ViewClass_, T>>(
property, value);
@@ -73,7 +73,7 @@ class BaseViewBuilderT : public internal::ViewBuilderCore {
template <typename T>
Builder& SetProperty(const ui::ClassProperty<T*>* property,
- metadata::ArgType<T> value) {
+ ui::metadata::ArgType<T> value) {
auto setter =
std::make_unique<internal::ClassPropertyMoveSetter<ViewClass_, T>>(
property, value);
@@ -172,14 +172,13 @@ class BaseViewBuilderT : public internal::ViewBuilderCore {
view_class##BuilderT& operator=(view_class##BuilderT&&) = default; \
~view_class##BuilderT() override = default;
-#define VIEW_BUILDER_PROPERTY(property_type, property_name) \
- BuilderT& Set##property_name( \
- ::views::metadata::ArgType<property_type> value) { \
- auto setter = std::make_unique<::views::internal::PropertySetter< \
- ViewClass_, property_type, decltype(&ViewClass_::Set##property_name), \
- &ViewClass_::Set##property_name>>(std::move(value)); \
- ::views::internal::ViewBuilderCore::AddPropertySetter(std::move(setter)); \
- return *static_cast<BuilderT*>(this); \
+#define VIEW_BUILDER_PROPERTY(property_type, property_name) \
+ BuilderT& Set##property_name(::ui::metadata::ArgType<property_type> value) { \
+ auto setter = std::make_unique<::views::internal::PropertySetter< \
+ ViewClass_, property_type, decltype(&ViewClass_::Set##property_name), \
+ &ViewClass_::Set##property_name>>(std::move(value)); \
+ ::views::internal::ViewBuilderCore::AddPropertySetter(std::move(setter)); \
+ return *static_cast<BuilderT*>(this); \
}
#define VIEW_BUILDER_METHOD(method_name) \
@@ -213,8 +212,8 @@ class BaseViewBuilderT : public internal::ViewBuilderCore {
}
#define VIEW_BUILDER_PROPERTY_DEFAULT(property_type, property_name, default) \
- BuilderT& Set##property_name( \
- ::views::metadata::ArgType<property_type> value = default) { \
+ BuilderT& Set##property_name(::ui::metadata::ArgType<property_type> value = \
+ default) { \
auto setter = std::make_unique<::views::internal::PropertySetter< \
ViewClass_, property_type, decltype(&ViewClass_::Set##property_name), \
&ViewClass_::Set##property_name>>(std::move(value)); \
diff --git a/chromium/ui/views/metadata/view_factory_internal.h b/chromium/ui/views/metadata/view_factory_internal.h
index 29f4209be41..68ab84caae4 100644
--- a/chromium/ui/views/metadata/view_factory_internal.h
+++ b/chromium/ui/views/metadata/view_factory_internal.h
@@ -13,8 +13,7 @@
#include <vector>
#include "ui/base/class_property.h"
-#include "ui/views/metadata/type_conversion.h"
-#include "ui/views/metadata/view_factory_internal.h"
+#include "ui/base/metadata/base_type_conversion.h"
#include "ui/views/views_export.h"
namespace views {
@@ -48,7 +47,7 @@ class PropertySetterBase {
template <typename TClass, typename TValue, typename TSig, TSig Set>
class PropertySetter : public PropertySetterBase {
public:
- explicit PropertySetter(metadata::ArgType<TValue> value)
+ explicit PropertySetter(ui::metadata::ArgType<TValue> value)
: value_(std::move(value)) {}
PropertySetter(const PropertySetter&) = delete;
PropertySetter& operator=(const PropertySetter&) = delete;
diff --git a/chromium/ui/views/selection_controller.cc b/chromium/ui/views/selection_controller.cc
index ef23305628e..34b2e1008d2 100644
--- a/chromium/ui/views/selection_controller.cc
+++ b/chromium/ui/views/selection_controller.cc
@@ -9,7 +9,7 @@
#include "base/numerics/ranges.h"
#include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
+#include "ui/base/clipboard/clipboard.h"
#include "ui/events/event.h"
#include "ui/gfx/render_text.h"
#include "ui/views/metrics.h"
@@ -23,12 +23,11 @@ SelectionController::SelectionController(SelectionControllerDelegate* delegate)
: aggregated_clicks_(0),
delegate_(delegate),
handles_selection_clipboard_(false) {
-// On Linux, update the selection clipboard on a text selection.
-// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
-// of lacros-chrome is complete.
-#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
- set_handles_selection_clipboard(true);
-#endif
+ // If selection clipboard is used, update it on a text selection.
+ if (ui::Clipboard::IsSupportedClipboardBuffer(
+ ui::ClipboardBuffer::kSelection)) {
+ set_handles_selection_clipboard(true);
+ }
DCHECK(delegate);
}
diff --git a/chromium/ui/views/style/platform_style.cc b/chromium/ui/views/style/platform_style.cc
index a5d59e74dc4..b63612cc59f 100644
--- a/chromium/ui/views/style/platform_style.cc
+++ b/chromium/ui/views/style/platform_style.cc
@@ -34,7 +34,7 @@ const bool PlatformStyle::kIsOkButtonLeading = false;
const float PlatformStyle::kFocusHaloThickness = 2.f;
const float PlatformStyle::kFocusHaloInset = -1.f;
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
const int PlatformStyle::kMinLabelButtonWidth = 70;
const int PlatformStyle::kMinLabelButtonHeight = 33;
@@ -47,7 +47,6 @@ const bool PlatformStyle::kReturnClicksFocusedControl = true;
const bool PlatformStyle::kTableViewSupportsKeyboardNavigationByCell = true;
const bool PlatformStyle::kTreeViewSelectionPaintsEntireRow = false;
const bool PlatformStyle::kUseRipples = true;
-const bool PlatformStyle::kTextfieldScrollsToStartOnFocusChange = false;
const bool PlatformStyle::kTextfieldUsesDragCursorWhenDraggable = true;
const bool PlatformStyle::kInactiveWidgetControlsAppearDisabled = false;
const View::FocusBehavior PlatformStyle::kDefaultFocusBehavior =
@@ -85,7 +84,7 @@ gfx::Range PlatformStyle::RangeToDeleteBackwards(const std::u16string& text,
return gfx::Range(cursor_position, previous_grapheme_index);
}
-#endif // OS_APPLE
+#endif // OS_MAC
#if !BUILDFLAG(ENABLE_DESKTOP_AURA) || \
(!defined(OS_LINUX) && !defined(OS_CHROMEOS))
diff --git a/chromium/ui/views/style/platform_style.h b/chromium/ui/views/style/platform_style.h
index 1180b2992a0..bbcd727d3e3 100644
--- a/chromium/ui/views/style/platform_style.h
+++ b/chromium/ui/views/style/platform_style.h
@@ -61,10 +61,6 @@ class VIEWS_EXPORT PlatformStyle {
// Whether ripples should be used for visual feedback on control activation.
static const bool kUseRipples;
- // Whether to scroll text fields to the beginning when they gain or lose
- // focus.
- static const bool kTextfieldScrollsToStartOnFocusChange;
-
// Whether text fields should use a "drag" cursor when not actually
// dragging but available to do so.
static const bool kTextfieldUsesDragCursorWhenDraggable;
diff --git a/chromium/ui/views/style/platform_style_mac.mm b/chromium/ui/views/style/platform_style_mac.mm
index 8b87d755ead..218163cf51d 100644
--- a/chromium/ui/views/style/platform_style_mac.mm
+++ b/chromium/ui/views/style/platform_style_mac.mm
@@ -37,7 +37,6 @@ const int PlatformStyle::kMinLabelButtonHeight = 30;
const bool PlatformStyle::kDialogDefaultButtonCanBeCancel = false;
const bool PlatformStyle::kSelectWordOnRightClick = true;
const bool PlatformStyle::kSelectAllOnRightClickWhenUnfocused = true;
-const bool PlatformStyle::kTextfieldScrollsToStartOnFocusChange = true;
const bool PlatformStyle::kTextfieldUsesDragCursorWhenDraggable = false;
const bool PlatformStyle::kTableViewSupportsKeyboardNavigationByCell = false;
const bool PlatformStyle::kTreeViewSelectionPaintsEntireRow = true;
diff --git a/chromium/ui/views/style/typography_provider.cc b/chromium/ui/views/style/typography_provider.cc
index dff000de729..82acff9ff31 100644
--- a/chromium/ui/views/style/typography_provider.cc
+++ b/chromium/ui/views/style/typography_provider.cc
@@ -14,7 +14,7 @@
#include "ui/views/style/typography.h"
#include "ui/views/view.h"
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#include "base/mac/mac_util.h"
#endif
@@ -147,7 +147,7 @@ int TypographyProvider::GetLineHeight(int context, int style) const {
// static
gfx::Font::Weight TypographyProvider::MediumWeightForUI() {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// System fonts are not user-configurable on Mac, so there's a simpler check.
// However, 10.11 do not ship with a MEDIUM weight system font. In that
// case, trying to use MEDIUM there will give a bold font, which will look
diff --git a/chromium/ui/views/touchui/touch_selection_controller_impl.cc b/chromium/ui/views/touchui/touch_selection_controller_impl.cc
index 22476b952d6..75c90d5cab0 100644
--- a/chromium/ui/views/touchui/touch_selection_controller_impl.cc
+++ b/chromium/ui/views/touchui/touch_selection_controller_impl.cc
@@ -15,14 +15,14 @@
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_targeter.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/image/image.h"
#include "ui/resources/grit/ui_resources.h"
-#include "ui/views/metadata/metadata_header_macros.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/views_delegate.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
@@ -373,12 +373,6 @@ class TouchSelectionControllerImpl::EditingHandleView : public View {
Widget* widget_ = nullptr;
};
-DEFINE_ENUM_CONVERTERS(gfx::SelectionBound::Type,
- {gfx::SelectionBound::Type::LEFT, u"LEFT"},
- {gfx::SelectionBound::Type::RIGHT, u"RIGHT"},
- {gfx::SelectionBound::Type::CENTER, u"CENTER"},
- {gfx::SelectionBound::Type::EMPTY, u"EMPTY"})
-
BEGIN_METADATA(TouchSelectionControllerImpl, EditingHandleView, View)
ADD_READONLY_PROPERTY_METADATA(gfx::SelectionBound::Type, SelectionBoundType)
ADD_PROPERTY_METADATA(bool, WidgetVisible)
@@ -744,3 +738,9 @@ View* TouchSelectionControllerImpl::GetHandle2View() {
}
} // namespace views
+
+DEFINE_ENUM_CONVERTERS(gfx::SelectionBound::Type,
+ {gfx::SelectionBound::Type::LEFT, u"LEFT"},
+ {gfx::SelectionBound::Type::RIGHT, u"RIGHT"},
+ {gfx::SelectionBound::Type::CENTER, u"CENTER"},
+ {gfx::SelectionBound::Type::EMPTY, u"EMPTY"})
diff --git a/chromium/ui/views/touchui/touch_selection_menu_runner_views.h b/chromium/ui/views/touchui/touch_selection_menu_runner_views.h
index a78e6042168..fac09e47bf7 100644
--- a/chromium/ui/views/touchui/touch_selection_menu_runner_views.h
+++ b/chromium/ui/views/touchui/touch_selection_menu_runner_views.h
@@ -5,7 +5,6 @@
#ifndef UI_VIEWS_TOUCHUI_TOUCH_SELECTION_MENU_RUNNER_VIEWS_H_
#define UI_VIEWS_TOUCHUI_TOUCH_SELECTION_MENU_RUNNER_VIEWS_H_
-#include <memory>
#include "base/macros.h"
#include "ui/touch_selection/touch_selection_menu_runner.h"
diff --git a/chromium/ui/views/touchui/touch_selection_menu_views.cc b/chromium/ui/views/touchui/touch_selection_menu_views.cc
index 29583c4bfd3..7f5e5f810fd 100644
--- a/chromium/ui/views/touchui/touch_selection_menu_views.cc
+++ b/chromium/ui/views/touchui/touch_selection_menu_views.cc
@@ -11,6 +11,7 @@
#include "base/strings/utf_string_conversions.h"
#include "ui/aura/window.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/pointer/touch_editing_controller.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
@@ -23,7 +24,6 @@
#include "ui/touch_selection/touch_selection_menu_runner.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/layout/box_layout.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
namespace views {
namespace {
diff --git a/chromium/ui/views/vector_icons/submenu_arrow.icon b/chromium/ui/views/vector_icons/submenu_arrow.icon
deleted file mode 100644
index 9d633095483..00000000000
--- a/chromium/ui/views/vector_icons/submenu_arrow.icon
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-FLIPS_IN_RTL,
-MOVE_TO, 3, 16,
-R_LINE_TO, 11, -8,
-LINE_TO, 3, 0,
-R_V_LINE_TO, 16,
-CLOSE
-
-CANVAS_DIMENSIONS, 8,
-FLIPS_IN_RTL,
-MOVE_TO, 2, 8,
-R_LINE_TO, 5, -4,
-R_LINE_TO, -5, -4,
-R_V_LINE_TO, 8,
-CLOSE
diff --git a/chromium/ui/views/view.cc b/chromium/ui/views/view.cc
index b31be56ad2e..753206477d5 100644
--- a/chromium/ui/views/view.cc
+++ b/chromium/ui/views/view.cc
@@ -8,6 +8,7 @@
#include <memory>
#include <utility>
+#include "base/callback_helpers.h"
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/containers/adapters.h"
@@ -18,7 +19,6 @@
#include "base/macros.h"
#include "base/notreached.h"
#include "base/scoped_observation.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
@@ -29,6 +29,7 @@
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/base/ime/input_method.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/color/color_provider_manager.h"
#include "ui/compositor/clip_recorder.h"
#include "ui/compositor/compositor.h"
@@ -56,7 +57,8 @@
#include "ui/views/context_menu_controller.h"
#include "ui/views/controls/scroll_view.h"
#include "ui/views/drag_controller.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
+#include "ui/views/interaction/element_tracker_views.h"
+#include "ui/views/layout/layout_provider.h"
#include "ui/views/view_class_properties.h"
#include "ui/views/view_observer.h"
#include "ui/views/view_tracker.h"
@@ -1203,6 +1205,13 @@ const ui::ThemeProvider* View::GetThemeProvider() const {
return widget ? widget->GetThemeProvider() : nullptr;
}
+const LayoutProvider* View::GetLayoutProvider() const {
+ if (!GetWidget())
+ return nullptr;
+ // TODO(pbos): Ask the widget for a layout provider.
+ return LayoutProvider::Get();
+}
+
const ui::ColorProvider* View::GetColorProvider() const {
const auto* widget = GetWidget();
return widget ? widget->GetColorProvider() : nullptr;
@@ -1357,6 +1366,11 @@ void View::SetMouseAndGestureHandler(View* new_handler) {
parent_->SetMouseAndGestureHandler(new_handler);
}
+void View::SetMouseHandler(View* new_handler) {
+ if (parent_)
+ parent_->SetMouseHandler(new_handler);
+}
+
bool View::OnKeyPressed(const ui::KeyEvent& event) {
return false;
}
@@ -1740,6 +1754,10 @@ ui::mojom::DragOperation View::OnPerformDrop(const ui::DropTargetEvent& event) {
void View::OnDragDone() {}
+View::DropCallback View::GetDropCallback(const ui::DropTargetEvent& event) {
+ return base::NullCallback();
+}
+
// static
bool View::ExceededDragThreshold(const gfx::Vector2d& delta) {
return (abs(delta.x()) > GetHorizontalDragThreshold() ||
@@ -2060,6 +2078,9 @@ void View::OnPaintLayer(const ui::PaintContext& context) {
void View::OnLayerTransformed(const gfx::Transform& old_transform,
ui::PropertyChangeReason reason) {
NotifyAccessibilityEvent(ax::mojom::Event::kLocationChanged, false);
+
+ for (ViewObserver& observer : observers_)
+ observer.OnViewLayerTransformed(this);
}
void View::OnDeviceScaleFactorChanged(float old_device_scale_factor,
@@ -2258,31 +2279,28 @@ void View::HandlePropertyChangeEffects(PropertyEffects effects) {
SchedulePaint();
}
-base::CallbackListSubscription View::AddPropertyChangedCallback(
- PropertyKey property,
- PropertyChangedCallback callback) {
- auto entry = property_changed_vectors_.find(property);
- if (entry == property_changed_vectors_.end()) {
- entry = property_changed_vectors_
- .emplace(property, std::make_unique<PropertyChangedCallbacks>())
- .first;
+void View::AfterPropertyChange(const void* key, int64_t old_value) {
+ if (key == kElementIdentifierKey) {
+ const ui::ElementIdentifier old_element_id =
+ ui::ElementIdentifier::FromRawValue(old_value);
+ if (old_element_id) {
+ views::ElementTrackerViews::GetInstance()->UnregisterView(old_element_id,
+ this);
+ }
+ const ui::ElementIdentifier new_element_id =
+ GetProperty(kElementIdentifierKey);
+ if (new_element_id) {
+ views::ElementTrackerViews::GetInstance()->RegisterView(new_element_id,
+ this);
+ }
}
- PropertyChangedCallbacks* property_changed_callbacks = entry->second.get();
-
- return property_changed_callbacks->Add(std::move(callback));
}
-void View::OnPropertyChanged(PropertyKey property,
+void View::OnPropertyChanged(ui::metadata::PropertyKey property,
PropertyEffects property_effects) {
if (property_effects != kPropertyEffectsNone)
HandlePropertyChangeEffects(property_effects);
-
- auto entry = property_changed_vectors_.find(property);
- if (entry == property_changed_vectors_.end())
- return;
-
- PropertyChangedCallbacks* property_changed_callbacks = entry->second.get();
- property_changed_callbacks->Notify();
+ TriggerChangedCallback(property);
}
int View::GetX() const {
@@ -2464,13 +2482,10 @@ void View::AddChildViewAtImpl(View* view, int index) {
}
// Remove |view| from its parent, if any.
- ui::NativeTheme* old_theme = nullptr;
- Widget* old_widget = nullptr;
- if (parent) {
- old_theme = view->GetNativeTheme();
- old_widget = view->GetWidget();
+ Widget* old_widget = view->GetWidget();
+ ui::NativeTheme* old_theme = old_widget ? view->GetNativeTheme() : nullptr;
+ if (parent)
parent->DoRemoveChildView(view, true, false, this);
- }
view->parent_ = this;
#if DCHECK_IS_ON()
@@ -2502,11 +2517,8 @@ void View::AddChildViewAtImpl(View* view, int index) {
if (HasLayoutManager())
GetLayoutManager()->ViewAdded(this, view);
- if (widget) {
- const ui::NativeTheme* new_theme = view->GetNativeTheme();
- if (new_theme != old_theme)
- view->PropagateThemeChanged();
- }
+ if (widget && (view->GetNativeTheme() != old_theme))
+ view->PropagateThemeChanged();
ViewHierarchyChangedDetails details(true, this, view, parent);
@@ -3225,12 +3237,6 @@ int View::DefaultFillLayout::GetPreferredHeightForWidth(const View* host,
return preferred_height;
}
-DEFINE_ENUM_CONVERTERS(View::FocusBehavior,
- {View::FocusBehavior::ACCESSIBLE_ONLY,
- u"ACCESSIBLE_ONLY"},
- {View::FocusBehavior::ALWAYS, u"ALWAYS"},
- {View::FocusBehavior::NEVER, u"NEVER"})
-
// This block requires the existence of METADATA_HEADER(View) in the class
// declaration for View.
BEGIN_METADATA_BASE(View)
@@ -3262,3 +3268,9 @@ ADD_CLASS_PROPERTY_METADATA(bool, kViewIgnoredByLayoutKey)
END_METADATA
} // namespace views
+
+DEFINE_ENUM_CONVERTERS(views::View::FocusBehavior,
+ {views::View::FocusBehavior::ACCESSIBLE_ONLY,
+ u"ACCESSIBLE_ONLY"},
+ {views::View::FocusBehavior::ALWAYS, u"ALWAYS"},
+ {views::View::FocusBehavior::NEVER, u"NEVER"})
diff --git a/chromium/ui/views/view.h b/chromium/ui/views/view.h
index b13e80f12a5..cd9069a34ec 100644
--- a/chromium/ui/views/view.h
+++ b/chromium/ui/views/view.h
@@ -8,24 +8,20 @@
#include <stddef.h>
#include <algorithm>
-#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
-#include "base/bind.h"
+#include "base/as_const.h"
#include "base/callback.h"
#include "base/callback_list.h"
#include "base/compiler_specific.h"
-#include "base/i18n/rtl.h"
-#include "base/logging.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/accessibility/ax_enums.mojom-forward.h"
#include "ui/base/accelerators/accelerator.h"
@@ -34,10 +30,13 @@
#include "ui/base/dragdrop/drop_target_event.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h"
#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_types.h"
#include "ui/base/ui_base_types.h"
#include "ui/compositor/layer_delegate.h"
#include "ui/compositor/layer_observer.h"
#include "ui/compositor/layer_owner.h"
+#include "ui/compositor/layer_type.h"
#include "ui/compositor/paint_cache.h"
#include "ui/events/event.h"
#include "ui/events/event_target.h"
@@ -49,7 +48,6 @@
#include "ui/gfx/native_widget_types.h"
#include "ui/views/layout/layout_manager.h"
#include "ui/views/layout/layout_types.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/paint_info.h"
#include "ui/views/view_targeter.h"
@@ -84,6 +82,7 @@ class ContextMenuController;
class DragController;
class FocusManager;
class FocusTraversable;
+class LayoutProvider;
class ScrollView;
class ViewAccessibility;
class ViewMaskLayer;
@@ -126,11 +125,7 @@ struct VIEWS_EXPORT ViewHierarchyChangedDetails {
View* move_view = nullptr;
};
-// Used to identify the CallbackList<> within the PropertyChangedVectors map.
-using PropertyKey = const void*;
-
-using PropertyChangedCallbacks = base::RepeatingClosureList;
-using PropertyChangedCallback = PropertyChangedCallbacks::CallbackType;
+using PropertyChangedCallback = ui::metadata::PropertyChangedCallback;
// The elements in PropertyEffects represent bits which define what effect(s) a
// changed Property has on the containing class. Additional elements should
@@ -273,10 +268,14 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
public ui::EventTarget,
public ui::EventHandler,
public ui::PropertyHandler,
- public views::metadata::MetaDataProvider {
+ public ui::metadata::MetaDataProvider {
public:
using Views = std::vector<View*>;
+ using DropCallback =
+ base::OnceCallback<void(const ui::DropTargetEvent& event,
+ ui::mojom::DragOperation& output_drag_op)>;
+
METADATA_HEADER_BASE(View);
enum class FocusBehavior {
@@ -383,6 +382,8 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Creation and lifetime -----------------------------------------------------
View();
+ View(const View&) = delete;
+ View& operator=(const View&) = delete;
~View() override;
// By default a View is owned by its parent unless specified otherwise here.
@@ -893,10 +894,13 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Get the theme provider from the parent widget.
const ui::ThemeProvider* GetThemeProvider() const;
+ // Get the layout provider for the View.
+ const LayoutProvider* GetLayoutProvider() const;
+
// Returns the ColorProvider from the ColorProviderManager.
ui::ColorProvider* GetColorProvider() {
return const_cast<ui::ColorProvider*>(
- static_cast<const View*>(this)->GetColorProvider());
+ base::as_const(*this).GetColorProvider());
}
const ui::ColorProvider* GetColorProvider() const;
@@ -906,8 +910,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// set. Warning: the default theme might not be correct; you should probably
// override OnThemeChanged().
ui::NativeTheme* GetNativeTheme() {
- return const_cast<ui::NativeTheme*>(
- static_cast<const View*>(this)->GetNativeTheme());
+ return const_cast<ui::NativeTheme*>(base::as_const(*this).GetNativeTheme());
}
const ui::NativeTheme* GetNativeTheme() const;
@@ -1074,6 +1077,9 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// view hierarchy, events won't be sent.
virtual void SetMouseAndGestureHandler(View* new_handler);
+ // Sets a new mouse handler.
+ virtual void SetMouseHandler(View* new_handler);
+
// Invoked when a key is pressed or released.
// Subclasses should return true if the event has been processed and false
// otherwise. If the event has not been processed, the parent will be given a
@@ -1094,8 +1100,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Convenience method to retrieve the InputMethod associated with the
// Widget that contains this view.
ui::InputMethod* GetInputMethod() {
- return const_cast<ui::InputMethod*>(
- const_cast<const View*>(this)->GetInputMethod());
+ return const_cast<ui::InputMethod*>(base::as_const(*this).GetInputMethod());
}
const ui::InputMethod* GetInputMethod() const;
@@ -1317,6 +1322,8 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Invoked during a drag and drop session when OnDragUpdated returns a valid
// operation and the user release the mouse.
+ // TODO(crbug.com/1175682): Remove OnPerformDrop and switch to GetDropCallback
+ // instead.
virtual ui::mojom::DragOperation OnPerformDrop(
const ui::DropTargetEvent& event);
@@ -1324,6 +1331,11 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// nothing, and is intended for subclasses to do cleanup.
virtual void OnDragDone();
+ // Invoked during a drag and drop session when OnDragUpdated returns a valid
+ // operation and the user release the mouse but the drop is held because of
+ // DataTransferPolicyController.
+ virtual DropCallback GetDropCallback(const ui::DropTargetEvent& event);
+
// Returns true if the mouse was dragged enough to start a drag operation.
// delta_x and y are the distance the mouse was dragged.
static bool ExceededDragThreshold(const gfx::Vector2d& delta);
@@ -1531,7 +1543,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Overridden from ui::LayerDelegate:
void OnPaintLayer(const ui::PaintContext& context) override;
void OnLayerTransformed(const gfx::Transform& old_transform,
- ui::PropertyChangeReason reason) override;
+ ui::PropertyChangeReason reason) final;
void OnDeviceScaleFactorChanged(float old_device_scale_factor,
float new_device_scale_factor) override;
@@ -1601,12 +1613,17 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
static int GetHorizontalDragThreshold();
static int GetVerticalDragThreshold();
+ // PropertyHandler -----------------------------------------------------------
+
+ // Note: you MUST call this base method from derived classes that override it
+ // or else your class will not properly register for ElementTrackerViews and
+ // won't be available for interactive tests or in-product help/tutorials which
+ // use that system.
+ void AfterPropertyChange(const void* key, int64_t old_value) override;
+
// Property Support ----------------------------------------------------------
- base::CallbackListSubscription AddPropertyChangedCallback(
- PropertyKey property,
- PropertyChangedCallback callback) WARN_UNUSED_RESULT;
- void OnPropertyChanged(PropertyKey property,
+ void OnPropertyChanged(ui::metadata::PropertyKey property,
PropertyEffects property_effects);
private:
@@ -1645,9 +1662,6 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
int GetPreferredHeightForWidth(const View* host, int width) const override;
};
- using PropertyChangedVectors =
- std::map<PropertyKey, std::unique_ptr<PropertyChangedCallbacks>>;
-
// Painting -----------------------------------------------------------------
// Responsible for propagating SchedulePaint() to the view's layer. If there
@@ -1969,7 +1983,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Size and disposition ------------------------------------------------------
- base::Optional<gfx::Size> preferred_size_;
+ absl::optional<gfx::Size> preferred_size_;
// This View's bounds in the parent coordinate system.
gfx::Rect bounds_;
@@ -2019,7 +2033,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// The default "fill" layout manager. This is set only if |layout_manager_|
// isn't set and SetUseDefaultFillLayout(true) is called or
// |kUseDefaultFillLayout| is true.
- base::Optional<DefaultFillLayout> default_fill_layout_;
+ absl::optional<DefaultFillLayout> default_fill_layout_;
// Whether this View's layer should be snapped to the pixel boundary.
bool snap_layer_to_pixel_boundary_ = false;
@@ -2057,7 +2071,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// positioned onscreen. The default behavior should be correct in most cases,
// but can be overridden if a particular view must always be laid out in some
// direction regardless of the application's default UI direction.
- base::Optional<bool> is_mirrored_;
+ absl::optional<bool> is_mirrored_;
// Accelerated painting ------------------------------------------------------
@@ -2126,13 +2140,8 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
base::ObserverList<ViewObserver>::Unchecked observers_;
- // Property Changed Callbacks ------------------------------------------------
- PropertyChangedVectors property_changed_vectors_;
-
// http://crbug.com/1162949 : Instrumentation that indicates if this is alive.
LifeCycleState life_cycle_state_ = LifeCycleState::kAlive;
-
- DISALLOW_COPY_AND_ASSIGN(View);
};
BEGIN_VIEW_BUILDER(VIEWS_EXPORT, View, BaseView)
diff --git a/chromium/ui/views/view_class_properties.cc b/chromium/ui/views/view_class_properties.cc
index 1335c4d3543..e8163ea58e7 100644
--- a/chromium/ui/views/view_class_properties.cc
+++ b/chromium/ui/views/view_class_properties.cc
@@ -25,6 +25,7 @@ DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT,
views::HighlightPathGenerator*)
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, views::FlexSpecification*)
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, views::LayoutAlignment*)
+DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, ui::ElementIdentifier)
namespace views {
@@ -42,5 +43,8 @@ DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(LayoutAlignment,
kCrossAxisAlignmentKey,
nullptr)
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kViewIgnoredByLayoutKey, false)
+DEFINE_UI_CLASS_PROPERTY_KEY(ui::ElementIdentifier,
+ kElementIdentifierKey,
+ ui::ElementIdentifier())
} // namespace views
diff --git a/chromium/ui/views/view_class_properties.h b/chromium/ui/views/view_class_properties.h
index 260742d4c3b..7cb3698d659 100644
--- a/chromium/ui/views/view_class_properties.h
+++ b/chromium/ui/views/view_class_properties.h
@@ -6,6 +6,7 @@
#define UI_VIEWS_VIEW_CLASS_PROPERTIES_H_
#include "ui/base/class_property.h"
+#include "ui/base/interaction/element_identifier.h"
#include "ui/views/layout/flex_layout_types.h"
#include "ui/views/views_export.h"
@@ -64,6 +65,10 @@ VIEWS_EXPORT extern const ui::ClassProperty<LayoutAlignment*>* const
VIEWS_EXPORT extern const ui::ClassProperty<bool>* const
kViewIgnoredByLayoutKey;
+// Tag for the view associated with ui::ElementTracker.
+VIEWS_EXPORT extern const ui::ClassProperty<ui::ElementIdentifier>* const
+ kElementIdentifierKey;
+
} // namespace views
// Declaring the template specialization here to make sure that the
@@ -77,6 +82,7 @@ DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT,
views::HighlightPathGenerator*)
DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, views::FlexSpecification*)
DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, views::LayoutAlignment*)
+DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, ui::ElementIdentifier)
DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, bool)
#endif // UI_VIEWS_VIEW_CLASS_PROPERTIES_H_
diff --git a/chromium/ui/views/view_observer.h b/chromium/ui/views/view_observer.h
index f8ea6c4be4c..8cd99144d7d 100644
--- a/chromium/ui/views/view_observer.h
+++ b/chromium/ui/views/view_observer.h
@@ -37,6 +37,12 @@ class VIEWS_EXPORT ViewObserver {
// Called when the bounds of |observed_view|'s layer change.
virtual void OnLayerTargetBoundsChanged(View* observed_view) {}
+ // Called when the `observed_view`'s layer transform changes.
+ // TODO(crbug.com/1203386): This is temporarily added to support a migration.
+ // Do not use for new call sites, we should instead figure out how to
+ // migrate this method (and possibly others) into callbacks.
+ virtual void OnViewLayerTransformed(View* observed_view) {}
+
// Called when View::ViewHierarchyChanged() is called.
virtual void OnViewHierarchyChanged(
View* observed_view,
diff --git a/chromium/ui/views/view_unittest.cc b/chromium/ui/views/view_unittest.cc
index 6c4141b3616..309240a7ab7 100644
--- a/chromium/ui/views/view_unittest.cc
+++ b/chromium/ui/views/view_unittest.cc
@@ -33,6 +33,7 @@
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_types.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/compositor/layer.h"
@@ -55,7 +56,6 @@
#include "ui/views/controls/scroll_view.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/layout/box_layout.h"
-#include "ui/views/metadata/metadata_types.h"
#include "ui/views/paint_info.h"
#include "ui/views/test/view_metadata_test_utils.h"
#include "ui/views/test/views_test_base.h"
@@ -65,7 +65,6 @@
#include "ui/views/widget/root_view.h"
#include "ui/views/window/dialog_delegate.h"
-using base::ASCIIToUTF16;
using testing::ElementsAre;
namespace {
@@ -1964,8 +1963,8 @@ TEST_F(ViewTest, NotifyEnterExitOnChild) {
}
TEST_F(ViewTest, Textfield) {
- const std::u16string kText = ASCIIToUTF16(
- "Reality is that which, when you stop believing it, doesn't go away.");
+ const std::u16string kText =
+ u"Reality is that which, when you stop believing it, doesn't go away.";
const std::u16string kExtraText = u"Pretty deep, Philip!";
Widget* widget = new Widget;
@@ -2285,7 +2284,7 @@ TEST_F(ViewTest, HandleAccelerator) {
// TODO(themblsha): Bring this up on non-Mac platforms. It currently fails
// because TestView::AcceleratorPressed() is not called. See
// http://crbug.com/667757.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Test that BridgedContentView correctly handles Accelerator key events when
// subject to OS event dispatch.
TEST_F(ViewTest, ActivateAcceleratorOnMac) {
@@ -2328,11 +2327,11 @@ TEST_F(ViewTest, ActivateAcceleratorOnMac) {
key_down_accelerator.modifiers());
EXPECT_EQ(view->accelerator_count_map_[key_down_accelerator], 1);
}
-#endif // OS_APPLE
+#endif // OS_MAC
// TODO(crbug.com/667757): these tests were initially commented out when getting
// aura to run. Figure out if still valuable and either nuke or fix.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
TEST_F(ViewTest, ActivateAccelerator) {
ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE);
TestViewWidget test_widget(CreateParams(Widget::InitParams::TYPE_POPUP),
@@ -2414,7 +2413,7 @@ TEST_F(ViewTest, ViewInHiddenWidgetWithAccelerator) {
EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
EXPECT_EQ(1, view->accelerator_count_map_[return_accelerator]);
}
-#endif // OS_APPLE
+#endif // OS_MAC
////////////////////////////////////////////////////////////////////////////////
// Native view hierachy
@@ -5374,9 +5373,9 @@ TEST_F(ViewTest, TestEnabledPropertyMetadata) {
auto subscription = test_view->AddEnabledChangedCallback(base::BindRepeating(
[](bool* enabled_changed) { *enabled_changed = true; },
&enabled_changed));
- views::metadata::ClassMetaData* view_metadata = View::MetaData();
+ ui::metadata::ClassMetaData* view_metadata = View::MetaData();
ASSERT_TRUE(view_metadata);
- views::metadata::MemberMetaDataBase* enabled_property =
+ ui::metadata::MemberMetaDataBase* enabled_property =
view_metadata->FindMemberData("Enabled");
ASSERT_TRUE(enabled_property);
std::u16string false_value = u"false";
@@ -5388,9 +5387,9 @@ TEST_F(ViewTest, TestEnabledPropertyMetadata) {
TEST_F(ViewTest, TestMarginsPropertyMetadata) {
auto test_view = std::make_unique<View>();
- views::metadata::ClassMetaData* view_metadata = View::MetaData();
+ ui::metadata::ClassMetaData* view_metadata = View::MetaData();
ASSERT_TRUE(view_metadata);
- views::metadata::MemberMetaDataBase* insets_property =
+ ui::metadata::MemberMetaDataBase* insets_property =
view_metadata->FindMemberData("kMarginsKey");
ASSERT_TRUE(insets_property);
std::u16string insets_value = u"8,8,8,8";
diff --git a/chromium/ui/views/view_unittest_mac.mm b/chromium/ui/views/view_unittest_mac.mm
index f2e3724183b..811868e5651 100644
--- a/chromium/ui/views/view_unittest_mac.mm
+++ b/chromium/ui/views/view_unittest_mac.mm
@@ -7,7 +7,7 @@
#import <Cocoa/Cocoa.h>
#import "base/mac/scoped_nsobject.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/gesture_event_details.h"
#include "ui/views/test/widget_test.h"
@@ -75,12 +75,12 @@ class ThreeFingerSwipeView : public View {
last_swipe_gesture_ = gfx::Point(dx, dy);
}
- base::Optional<gfx::Point> last_swipe_gesture() const {
+ absl::optional<gfx::Point> last_swipe_gesture() const {
return last_swipe_gesture_;
}
private:
- base::Optional<gfx::Point> last_swipe_gesture_;
+ absl::optional<gfx::Point> last_swipe_gesture_;
DISALLOW_COPY_AND_ASSIGN(ThreeFingerSwipeView);
};
@@ -91,7 +91,7 @@ class ViewMacTest : public test::WidgetTest {
public:
ViewMacTest() = default;
- base::Optional<gfx::Point> SwipeGestureVector(int dx, int dy) {
+ absl::optional<gfx::Point> SwipeGestureVector(int dx, int dy) {
base::scoped_nsobject<FakeSwipeEvent> swipe_event(
[[FakeSwipeEvent alloc] init]);
[swipe_event setDeltaX:dx];
@@ -117,7 +117,7 @@ class ViewMacTest : public test::WidgetTest {
view_ = new ThreeFingerSwipeView;
view_->SetSize(widget_->GetClientAreaBoundsInScreen().size());
- widget_->GetContentsView()->AddChildView(view_);
+ widget_->non_client_view()->frame_view()->AddChildView(view_);
}
void TearDown() override {
diff --git a/chromium/ui/views/view_utils.cc b/chromium/ui/views/view_utils.cc
index 5df39fcb64f..b9e87d5addb 100644
--- a/chromium/ui/views/view_utils.cc
+++ b/chromium/ui/views/view_utils.cc
@@ -4,6 +4,10 @@
#include "ui/views/view_utils.h"
+#include <sstream>
+
+#include "base/logging.h"
+
namespace views {
ViewDebugWrapperImpl::ViewDebugWrapperImpl(View* view) : view_(view) {}
@@ -50,7 +54,7 @@ void ViewDebugWrapperImpl::ForAllProperties(PropCallback callback) {
views::View* view = const_cast<views::View*>(view_);
for (auto* member : *(view->GetClassMetaData())) {
auto flags = member->GetPropertyFlags();
- if (!!(flags & views::metadata::PropertyFlags::kSerializable)) {
+ if (!!(flags & ui::metadata::PropertyFlags::kSerializable)) {
callback.Run(member->member_name(),
base::UTF16ToUTF8(member->GetValueAsString(view)));
}
diff --git a/chromium/ui/views/view_utils.h b/chromium/ui/views/view_utils.h
index 11893d7752f..a2dfdb5422d 100644
--- a/chromium/ui/views/view_utils.h
+++ b/chromium/ui/views/view_utils.h
@@ -10,8 +10,8 @@
#include <type_traits>
#include <vector>
+#include "ui/base/metadata/metadata_types.h"
#include "ui/views/debug/debugger_utils.h"
-#include "ui/views/metadata/metadata_types.h"
#include "ui/views/view.h"
#include "ui/views/views_export.h"
@@ -42,8 +42,8 @@ class ViewDebugWrapperImpl : public debug::ViewDebugWrapper {
template <typename V>
bool IsViewClass(View* view) {
static_assert(std::is_base_of<View, V>::value, "Only View classes supported");
- metadata::ClassMetaData* parent = V::MetaData();
- metadata::ClassMetaData* child = view->GetClassMetaData();
+ ui::metadata::ClassMetaData* parent = V::MetaData();
+ ui::metadata::ClassMetaData* child = view->GetClassMetaData();
while (child && child != parent)
child = child->parent_class_meta_data();
return !!child;
diff --git a/chromium/ui/views/views_delegate.cc b/chromium/ui/views/views_delegate.cc
index b238d2791d7..dec3ec8705d 100644
--- a/chromium/ui/views/views_delegate.cc
+++ b/chromium/ui/views/views_delegate.cc
@@ -117,7 +117,7 @@ bool ViewsDelegate::WindowManagerProvidesTitleBar(bool maximized) {
return false;
}
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
ui::ContextFactory* ViewsDelegate::GetContextFactory() {
return nullptr;
}
diff --git a/chromium/ui/views/views_delegate.h b/chromium/ui/views/views_delegate.h
index d84acfa918e..27f4562cab6 100644
--- a/chromium/ui/views/views_delegate.h
+++ b/chromium/ui/views/views_delegate.h
@@ -29,7 +29,7 @@ class Rect;
} // namespace gfx
namespace ui {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
class ContextFactory;
#endif
class TouchEditingControllerFactory;
@@ -165,7 +165,7 @@ class VIEWS_EXPORT ViewsDelegate {
// maximized windows; otherwise to restored windows.
virtual bool WindowManagerProvidesTitleBar(bool maximized);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Returns the context factory for new windows.
virtual ui::ContextFactory* GetContextFactory();
#endif
diff --git a/chromium/ui/views/views_features.cc b/chromium/ui/views/views_features.cc
index 59f766cfe65..9acbbd6f159 100644
--- a/chromium/ui/views/views_features.cc
+++ b/chromium/ui/views/views_features.cc
@@ -12,11 +12,6 @@ namespace features {
// Please keep alphabetized.
-// Allows a "New" badge to be displayed on menu items that provide access to new
-// features.
-const base::Feature kEnableNewBadgeOnMenuItems{
- "EnableNewBadgeOnMenuItems", base::FEATURE_ENABLED_BY_DEFAULT};
-
// Use a high-contrast style for ink drops when in platform high-contrast mode,
// including full opacity and a high-contrast color
const base::Feature kEnablePlatformHighContrastInkDrop{
@@ -32,10 +27,5 @@ const base::Feature kEnableViewPaintOptimization{
const base::Feature kInheritNativeThemeFromParentWidget{
"InheritNativeThemeFromParentWidget", base::FEATURE_DISABLED_BY_DEFAULT};
-// Change views::Textfield to take focus on a completed tap, rather than
-// immediately on tap down. This only affects touch input.
-const base::Feature kTextfieldFocusOnTapUp{"TextfieldFocusOnTapUp",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
} // namespace features
} // namespace views
diff --git a/chromium/ui/views/views_features.h b/chromium/ui/views/views_features.h
index 06e35a82040..f2dc4b60567 100644
--- a/chromium/ui/views/views_features.h
+++ b/chromium/ui/views/views_features.h
@@ -13,11 +13,9 @@ namespace views {
namespace features {
// Please keep alphabetized.
-VIEWS_EXPORT extern const base::Feature kEnableNewBadgeOnMenuItems;
VIEWS_EXPORT extern const base::Feature kEnablePlatformHighContrastInkDrop;
VIEWS_EXPORT extern const base::Feature kEnableViewPaintOptimization;
VIEWS_EXPORT extern const base::Feature kInheritNativeThemeFromParentWidget;
-VIEWS_EXPORT extern const base::Feature kTextfieldFocusOnTapUp;
} // namespace features
} // namespace views
diff --git a/chromium/ui/views/views_test_suite.h b/chromium/ui/views/views_test_suite.h
index c9b048b0bc5..c9ab3d62545 100644
--- a/chromium/ui/views/views_test_suite.h
+++ b/chromium/ui/views/views_test_suite.h
@@ -17,11 +17,6 @@ class Env;
}
#endif
-#if defined(USE_OZONE)
-#include "ui/base/ui_base_features.h"
-#include "ui/ozone/public/ozone_platform.h"
-#endif
-
namespace views {
class ViewsTestSuite : public base::TestSuite {
@@ -54,17 +49,6 @@ class ViewsTestSuite : public base::TestSuite {
DISALLOW_COPY_AND_ASSIGN(ViewsTestSuite);
};
-#if defined(USE_OZONE)
-// Skips the X11-specific test on Ozone if the current platform is not X11.
-#define SKIP_TEST_IF_NOT_OZONE_X11() \
- if (features::IsUsingOzonePlatform() && \
- ui::OzonePlatform::GetPlatformNameForTest() != "x11") { \
- GTEST_SKIP() << "This test is X11-only"; \
- }
-#else
-#define SKIP_TEST_IF_NOT_OZONE_X11()
-#endif
-
} // namespace views
#endif // UI_VIEWS_VIEWS_TEST_SUITE_H_
diff --git a/chromium/ui/views/widget/any_widget_observer_unittest.cc b/chromium/ui/views/widget/any_widget_observer_unittest.cc
index e67837940af..ef95c7497b0 100644
--- a/chromium/ui/views/widget/any_widget_observer_unittest.cc
+++ b/chromium/ui/views/widget/any_widget_observer_unittest.cc
@@ -109,6 +109,14 @@ TEST_F(NamedWidgetShownWaiterTest, ShownBeforeWait) {
EXPECT_EQ(waiter.WaitIfNeededAndGet(), w0.get());
}
+TEST_F(NamedWidgetShownWaiterTest, ShownInactive) {
+ views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{},
+ "TestWidget");
+ WidgetAutoclosePtr w0(CreateNamedWidget("TestWidget"));
+ w0->ShowInactive();
+ EXPECT_EQ(waiter.WaitIfNeededAndGet(), w0.get());
+}
+
TEST_F(NamedWidgetShownWaiterTest, OtherWidgetShown) {
views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{},
"TestWidget");
diff --git a/chromium/ui/views/widget/ax_native_widget_mac_unittest.mm b/chromium/ui/views/widget/ax_native_widget_mac_unittest.mm
index a66d49953b9..bf2974b1186 100644
--- a/chromium/ui/views/widget/ax_native_widget_mac_unittest.mm
+++ b/chromium/ui/views/widget/ax_native_widget_mac_unittest.mm
@@ -7,7 +7,6 @@
#import <Cocoa/Cocoa.h>
#include "base/mac/mac_util.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#import "testing/gtest_mac.h"
@@ -96,18 +95,18 @@ class TestWidgetDelegate : public test::TestDesktopWidgetDelegate {
public:
TestWidgetDelegate() = default;
- static constexpr char kAccessibleWindowTitle[] = "My Accessible Window";
+ static constexpr char16_t kAccessibleWindowTitle[] = u"My Accessible Window";
// WidgetDelegate:
std::u16string GetAccessibleWindowTitle() const override {
- return base::ASCIIToUTF16(kAccessibleWindowTitle);
+ return kAccessibleWindowTitle;
}
private:
DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate);
};
-constexpr char TestWidgetDelegate::kAccessibleWindowTitle[];
+constexpr char16_t TestWidgetDelegate::kAccessibleWindowTitle[];
// Widget-level tests for accessibility properties - these are actually mostly
// tests of accessibility behavior for individual Views *as they appear* in
@@ -271,7 +270,7 @@ TEST_F(AXNativeWidgetMacTest, ChildrenAttribute) {
// Check ignored children don't show up in the accessibility tree.
widget()->GetContentsView()->AddChildView(
- new FlexibleRoleTestView(ax::mojom::Role::kIgnored));
+ new FlexibleRoleTestView(ax::mojom::Role::kNone));
EXPECT_EQ(kNumChildren, ax_node.accessibilityChildren.count);
}
@@ -303,7 +302,7 @@ TEST_F(AXNativeWidgetMacTest, ParentAttribute) {
EXPECT_NSEQ(NSAccessibilityGroupRole, ax_parent.accessibilityRole);
// Test an ignored role parent is skipped in favor of the grandparent.
- parent->set_role(ax::mojom::Role::kIgnored);
+ parent->set_role(ax::mojom::Role::kNone);
ASSERT_NSNE(nil, AXParentOf(ax_child));
EXPECT_NSEQ(NSAccessibilityGroupRole, AXParentOf(ax_child).accessibilityRole);
}
@@ -348,7 +347,7 @@ TEST_F(AXNativeWidgetMacTest, NativeWindowProperties) {
EXPECT_NSEQ(window, ax_view.accessibilityWindow);
EXPECT_NSEQ(window, ax_view.accessibilityTopLevelUIElement);
EXPECT_NSEQ(
- base::SysUTF8ToNSString(TestWidgetDelegate::kAccessibleWindowTitle),
+ base::SysUTF16ToNSString(TestWidgetDelegate::kAccessibleWindowTitle),
window.accessibilityTitle);
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc
index 0bac1fd035a..b9b3a72cea7 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc
@@ -21,8 +21,10 @@
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/drop_target_event.h"
+#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/base/layout.h"
#include "ui/base/ui_base_features.h"
+#include "ui/compositor/layer.h"
#include "ui/display/screen.h"
#include "ui/ozone/public/ozone_platform.h"
#include "ui/platform_window/platform_window_delegate.h"
@@ -30,9 +32,10 @@
#include "ui/views/widget/widget.h"
namespace views {
-
namespace {
+using ::ui::mojom::DragOperation;
+
aura::Window* GetTargetWindow(aura::Window* root_window,
const gfx::Point& point) {
gfx::Point root_location(point);
@@ -119,15 +122,15 @@ DesktopDragDropClientOzone::~DesktopDragDropClientOzone() {
ResetDragDropTarget(true);
}
-int DesktopDragDropClientOzone::StartDragAndDrop(
+DragOperation DesktopDragDropClientOzone::StartDragAndDrop(
std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& root_location,
- int operation,
+ int allowed_operations,
ui::mojom::DragEventSource source) {
if (!drag_handler_)
- return ui::DragDropTypes::DragOperation::DRAG_NONE;
+ return DragOperation::kNone;
DCHECK(!drag_context_);
drag_context_ = std::make_unique<DragContext>();
@@ -142,7 +145,6 @@ int DesktopDragDropClientOzone::StartDragAndDrop(
aura::client::GetCursorClient(root_window);
auto initial_cursor = source_window->GetHost()->last_cursor();
- drag_operation_ = operation;
if (cursor_client) {
cursor_client->SetCursor(ui::mojom::CursorType::kGrabbing);
}
@@ -164,14 +166,14 @@ int DesktopDragDropClientOzone::StartDragAndDrop(
auto alive = weak_factory_.GetWeakPtr();
const bool drag_succeeded = drag_handler_->StartDrag(
- *data.get(), operation, cursor_client->GetCursor(),
+ *data.get(), allowed_operations, cursor_client->GetCursor(),
!source_window->HasCapture(), this);
if (!alive)
- return ui::DragDropTypes::DRAG_NONE;
+ return DragOperation::kNone;
if (!drag_succeeded)
- drag_operation_ = ui::DragDropTypes::DRAG_NONE;
+ drag_operation_ = DragOperation::kNone;
if (cursor_client)
cursor_client->SetCursor(initial_cursor);
@@ -185,7 +187,7 @@ void DesktopDragDropClientOzone::DragCancel() {
return;
drag_handler_->CancelDrag();
- drag_operation_ = ui::DragDropTypes::DRAG_NONE;
+ drag_operation_ = DragOperation::kNone;
}
bool DesktopDragDropClientOzone::IsDragDropInProgress() {
@@ -308,7 +310,7 @@ void DesktopDragDropClientOzone::OnDragLocationChanged(
}
void DesktopDragDropClientOzone::OnDragOperationChanged(
- ui::DragDropTypes::DragOperation operation) {
+ DragOperation operation) {
aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(root_window_);
if (!cursor_client)
@@ -316,24 +318,24 @@ void DesktopDragDropClientOzone::OnDragOperationChanged(
ui::mojom::CursorType cursor_type = ui::mojom::CursorType::kNull;
switch (operation) {
- case ui::DragDropTypes::DRAG_NONE:
+ case DragOperation::kNone:
cursor_type = ui::mojom::CursorType::kDndNone;
break;
- case ui::DragDropTypes::DRAG_MOVE:
+ case DragOperation::kMove:
cursor_type = ui::mojom::CursorType::kDndMove;
break;
- case ui::DragDropTypes::DRAG_COPY:
+ case DragOperation::kCopy:
cursor_type = ui::mojom::CursorType::kDndCopy;
break;
- case ui::DragDropTypes::DRAG_LINK:
+ case DragOperation::kLink:
cursor_type = ui::mojom::CursorType::kDndLink;
break;
}
cursor_client->SetCursor(cursor_type);
}
-void DesktopDragDropClientOzone::OnDragFinished(int dnd_action) {
- drag_operation_ = dnd_action;
+void DesktopDragDropClientOzone::OnDragFinished(DragOperation operation) {
+ drag_operation_ = operation;
}
std::unique_ptr<ui::DropTargetEvent>
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h
index 3fe03e66457..a090928f8d3 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h
@@ -12,6 +12,7 @@
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/window_observer.h"
#include "ui/base/cursor/cursor.h"
+#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/native_widget_types.h"
@@ -66,16 +67,17 @@ class VIEWS_EXPORT DesktopDragDropClientOzone
// more times until the posted task is executed, but no more than a single
// call to UpdateDragWidget() is scheduled at any time; this optional is set
// means that the task is scheduled.
- base::Optional<gfx::Point> last_screen_location_px;
+ absl::optional<gfx::Point> last_screen_location_px;
};
// aura::client::DragDropClient
- int StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data,
- aura::Window* root_window,
- aura::Window* source_window,
- const gfx::Point& root_location,
- int operation,
- ui::mojom::DragEventSource source) override;
+ ui::mojom::DragOperation StartDragAndDrop(
+ std::unique_ptr<ui::OSExchangeData> data,
+ aura::Window* root_window,
+ aura::Window* source_window,
+ const gfx::Point& root_location,
+ int allowed_operations,
+ ui::mojom::DragEventSource source) override;
void DragCancel() override;
bool IsDragDropInProgress() override;
void AddObserver(aura::client::DragDropClientObserver* observer) override;
@@ -98,9 +100,8 @@ class VIEWS_EXPORT DesktopDragDropClientOzone
// ui::WmDragHandler::Delegate
void OnDragLocationChanged(const gfx::Point& screen_point_px) override;
- void OnDragOperationChanged(
- ui::DragDropTypes::DragOperation operation) override;
- void OnDragFinished(int operation) override;
+ void OnDragOperationChanged(ui::mojom::DragOperation operation) override;
+ void OnDragFinished(ui::mojom::DragOperation operation) override;
// Returns a DropTargetEvent to be passed to the DragDropDelegate.
// Updates the delegate if needed, which in its turn calls their
@@ -141,8 +142,8 @@ class VIEWS_EXPORT DesktopDragDropClientOzone
// used at dropping.
int last_drop_operation_ = 0;
- // The operation bitfield.
- int drag_operation_ = 0;
+ // The selected operation on drop.
+ ui::mojom::DragOperation drag_operation_ = ui::mojom::DragOperation::kNone;
std::unique_ptr<DragContext> drag_context_;
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
index 8217d4520ad..d282dadbf2c 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
@@ -8,11 +8,15 @@
#include <utility>
#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/notreached.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
@@ -30,6 +34,22 @@ namespace {
using ::ui::mojom::DragOperation;
+// Platforms have different approaches to handling window coordinates. For
+// instance, Wayland doesn't use window origin (it is always zero) and treats
+// coordinates of pointer events as local ones (always within the window), but
+// X11 1) uses the origin and may adjust it so that a window gets non-zero
+// origin, see X11Window::OnConfigureEvent(), and 2) treats mouse coordinates as
+// global ones, so that the event may be considered being 'outside the window'
+// and discarded, which will make some tests in this suite failing.
+//
+// To ensure the drag to be always started within the drag widget, we choose
+// size of the drag widget and location so that the location stays within the
+// widget, even if the platform adjusts its position.
+//
+// See crbug.com/1119787
+constexpr gfx::Rect kDragWidgetBounds{200, 200};
+constexpr gfx::PointF kStartDragLocation{100, 100};
+
class FakePlatformWindow : public ui::PlatformWindow, public ui::WmDragHandler {
public:
FakePlatformWindow() { SetWmDragHandler(this, this); }
@@ -58,7 +78,7 @@ class FakePlatformWindow : public ui::PlatformWindow, public ui::WmDragHandler {
}
void Activate() override {}
void Deactivate() override {}
- void SetCursor(ui::PlatformCursor cursor) override {}
+ void SetCursor(scoped_refptr<ui::PlatformCursor> cursor) override {}
void MoveCursorTo(const gfx::Point& location) override {}
void ConfineCursorToBounds(const gfx::Rect& bounds) override {}
void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override {}
@@ -121,17 +141,17 @@ class FakePlatformWindow : public ui::PlatformWindow, public ui::WmDragHandler {
drop_handler->OnDragLeave();
}
- void CloseDrag(uint32_t dnd_action) {
- drag_handler_delegate_->OnDragFinished(dnd_action);
+ void CloseDrag(DragOperation operation) {
+ drag_handler_delegate_->OnDragFinished(operation);
std::move(drag_loop_quit_closure_).Run();
}
void ProcessDrag(std::unique_ptr<OSExchangeData> data, int operation) {
- OnDragEnter(gfx::PointF(), std::move(data), operation);
- int updated_operation = OnDragMotion(gfx::PointF(), operation);
+ OnDragEnter(kStartDragLocation, std::move(data), operation);
+ int updated_operation = OnDragMotion(kStartDragLocation, operation);
OnDragDrop(nullptr);
OnDragLeave();
- CloseDrag(updated_operation);
+ CloseDrag(ui::PreferredDragOperation(updated_operation));
}
private:
@@ -201,6 +221,11 @@ class FakeDragDropDelegate : public aura::client::DragDropDelegate {
return destination_operation_;
}
+ DropCallback GetDropCallback(const ui::DropTargetEvent& event) override {
+ NOTIMPLEMENTED();
+ return base::NullCallback();
+ }
+
int num_enters_;
int num_updates_;
int num_exits_;
@@ -224,7 +249,7 @@ class DesktopDragDropClientOzoneTest : public ViewsTestBase {
platform_window_->set_modifiers(modifiers);
}
- int StartDragAndDrop(int operation) {
+ DragOperation StartDragAndDrop(int allowed_operations) {
auto data = std::make_unique<ui::OSExchangeData>();
data->SetString(u"Test");
SkBitmap drag_bitmap;
@@ -235,7 +260,7 @@ class DesktopDragDropClientOzoneTest : public ViewsTestBase {
return client_->StartDragAndDrop(
std::move(data), widget_->GetNativeWindow()->GetRootWindow(),
- widget_->GetNativeWindow(), gfx::Point(), operation,
+ widget_->GetNativeWindow(), gfx::Point(), allowed_operations,
ui::mojom::DragEventSource::kMouse);
}
@@ -249,7 +274,7 @@ class DesktopDragDropClientOzoneTest : public ViewsTestBase {
widget_ = std::make_unique<Widget>();
Widget::InitParams params(Widget::InitParams::TYPE_WINDOW);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.bounds = gfx::Rect(100, 100);
+ params.bounds = kDragWidgetBounds;
widget_->Init(std::move(params));
widget_->Show();
@@ -286,15 +311,14 @@ class DesktopDragDropClientOzoneTest : public ViewsTestBase {
DISALLOW_COPY_AND_ASSIGN(DesktopDragDropClientOzoneTest);
};
-// TODO(1119787): fix this.
-TEST_F(DesktopDragDropClientOzoneTest, DISABLED_StartDrag) {
+TEST_F(DesktopDragDropClientOzoneTest, StartDrag) {
// Set the operation which the destination can accept.
dragdrop_delegate_->SetOperation(DragOperation::kCopy);
// Start Drag and Drop with the operations suggested.
- int operation = StartDragAndDrop(ui::DragDropTypes::DRAG_COPY |
- ui::DragDropTypes::DRAG_MOVE);
+ DragOperation operation = StartDragAndDrop(ui::DragDropTypes::DRAG_COPY |
+ ui::DragDropTypes::DRAG_MOVE);
// The |operation| decided through negotiation should be 'DRAG_COPY'.
- EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, operation);
+ EXPECT_EQ(DragOperation::kCopy, operation);
EXPECT_EQ(1, dragdrop_delegate_->num_enters());
EXPECT_EQ(1, dragdrop_delegate_->num_updates());
@@ -304,16 +328,15 @@ TEST_F(DesktopDragDropClientOzoneTest, DISABLED_StartDrag) {
EXPECT_EQ(ui::EF_NONE, dragdrop_delegate_->last_event_flags());
}
-// TODO(1119787): fix this.
-TEST_F(DesktopDragDropClientOzoneTest, DISABLED_StartDragCtrlPressed) {
+TEST_F(DesktopDragDropClientOzoneTest, StartDragCtrlPressed) {
SetModifiers(ui::EF_CONTROL_DOWN);
// Set the operation which the destination can accept.
dragdrop_delegate_->SetOperation(DragOperation::kCopy);
// Start Drag and Drop with the operations suggested.
- int operation = StartDragAndDrop(ui::DragDropTypes::DRAG_COPY |
- ui::DragDropTypes::DRAG_MOVE);
+ DragOperation operation = StartDragAndDrop(ui::DragDropTypes::DRAG_COPY |
+ ui::DragDropTypes::DRAG_MOVE);
// The |operation| decided through negotiation should be 'DRAG_COPY'.
- EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, operation);
+ EXPECT_EQ(DragOperation::kCopy, operation);
EXPECT_EQ(1, dragdrop_delegate_->num_enters());
EXPECT_EQ(1, dragdrop_delegate_->num_updates());
@@ -338,10 +361,10 @@ TEST_F(DesktopDragDropClientOzoneTest, ReceiveDrag) {
// |suggested_operation|.
int suggested_operation =
ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE;
- platform_window_->OnDragEnter(gfx::PointF(), std::move(data),
+ platform_window_->OnDragEnter(kStartDragLocation, std::move(data),
suggested_operation);
int updated_operation =
- platform_window_->OnDragMotion(gfx::PointF(), suggested_operation);
+ platform_window_->OnDragMotion(kStartDragLocation, suggested_operation);
platform_window_->OnDragDrop(nullptr);
platform_window_->OnDragLeave();
@@ -374,9 +397,9 @@ TEST_F(DesktopDragDropClientOzoneTest, TargetDestroyedDuringDrag) {
// Simulate that the drag enter/motion/leave events happen with the
// |suggested_operation| in the main window.
- platform_window_->OnDragEnter(gfx::PointF(), std::move(data),
+ platform_window_->OnDragEnter(kStartDragLocation, std::move(data),
suggested_operation);
- platform_window_->OnDragMotion(gfx::PointF(), suggested_operation);
+ platform_window_->OnDragMotion(kStartDragLocation, suggested_operation);
platform_window_->OnDragLeave();
// Create another window with its own DnD facility and simulate that the drag
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
index 92a9e033a00..cb7cea0d488 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
@@ -25,7 +25,6 @@ DesktopDragDropClientWin::DesktopDragDropClientWin(
HWND window,
DesktopWindowTreeHostWin* desktop_host)
: drag_drop_in_progress_(false),
- drag_operation_(0),
desktop_host_(desktop_host) {
drop_target_ = new DesktopDropTargetWin(root_window);
drop_target_->Init(window);
@@ -36,15 +35,14 @@ DesktopDragDropClientWin::~DesktopDragDropClientWin() {
DragCancel();
}
-int DesktopDragDropClientWin::StartDragAndDrop(
+ui::mojom::DragOperation DesktopDragDropClientWin::StartDragAndDrop(
std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& screen_location,
- int operation,
+ int allowed_operations,
ui::mojom::DragEventSource source) {
drag_drop_in_progress_ = true;
- drag_operation_ = operation;
if (source == ui::mojom::DragEventSource::kTouch) {
gfx::Point screen_point = display::win::ScreenWin::DIPToScreenPoint(
{screen_location.x(), screen_location.y()});
@@ -72,13 +70,14 @@ int DesktopDragDropClientWin::StartDragAndDrop(
// Disable hang watching until the end of the function since the user can take
// unbounded time to complete the drag. (http://crbug.com/806174)
- base::HangWatchScopeDisabled disabler;
+ base::IgnoreHangsInScope disabler;
base::TimeTicks start_time = base::TimeTicks::Now();
HRESULT result = ::DoDragDrop(
ui::OSExchangeDataProviderWin::GetIDataObject(*data.get()),
drag_source_.Get(),
- ui::DragDropTypes::DragOperationToDropEffect(operation), &effect);
+ ui::DragDropTypes::DragOperationToDropEffect(allowed_operations),
+ &effect);
if (alive && source == ui::mojom::DragEventSource::kTouch) {
// In a normal drag drop, ::DoDragDrop calls QueryContinueDrag every time
// it gets a mouse or keyboard event. The windows doc
@@ -109,12 +108,12 @@ int DesktopDragDropClientWin::StartDragAndDrop(
if (result != DRAGDROP_S_DROP)
effect = DROPEFFECT_NONE;
- return ui::DragDropTypes::DropEffectToDragOperation(effect);
+ return ui::PreferredDragOperation(
+ ui::DragDropTypes::DropEffectToDragOperation(effect));
}
void DesktopDragDropClientWin::DragCancel() {
drag_source_->CancelDrag();
- drag_operation_ = 0;
}
bool DesktopDragDropClientWin::IsDragDropInProgress() {
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h
index 644de0cd15c..34ec4925626 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h
@@ -39,12 +39,13 @@ class VIEWS_EXPORT DesktopDragDropClientWin
~DesktopDragDropClientWin() override;
// Overridden from aura::client::DragDropClient:
- int StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data,
- aura::Window* root_window,
- aura::Window* source_window,
- const gfx::Point& screen_location,
- int operation,
- ui::mojom::DragEventSource source) override;
+ ui::mojom::DragOperation StartDragAndDrop(
+ std::unique_ptr<ui::OSExchangeData> data,
+ aura::Window* root_window,
+ aura::Window* source_window,
+ const gfx::Point& screen_location,
+ int allowed_operations,
+ ui::mojom::DragEventSource source) override;
void DragCancel() override;
bool IsDragDropInProgress() override;
void AddObserver(aura::client::DragDropClientObserver* observer) override;
@@ -55,8 +56,6 @@ class VIEWS_EXPORT DesktopDragDropClientWin
private:
bool drag_drop_in_progress_;
- int drag_operation_;
-
Microsoft::WRL::ComPtr<ui::DragSourceWin> drag_source_;
scoped_refptr<DesktopDropTargetWin> drop_target_;
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index b7f67fa6758..de5ad7a0142 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -9,6 +9,7 @@
#include "base/auto_reset.h"
#include "base/bind.h"
+#include "base/callback_helpers.h"
#include "base/macros.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
@@ -91,6 +92,7 @@ class DesktopNativeWidgetTopLevelHandler : public aura::WindowObserver {
// This function creates a widget with the bounds passed in which eventually
// becomes the parent of the child window passed in.
static aura::Window* CreateParentWindow(aura::Window* child_window,
+ aura::Window* context,
const gfx::Rect& bounds,
bool full_screen,
bool is_menu,
@@ -115,9 +117,14 @@ class DesktopNativeWidgetTopLevelHandler : public aura::WindowObserver {
init_params.bounds = bounds;
init_params.ownership = Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET;
init_params.layer_type = ui::LAYER_NOT_DRAWN;
- init_params.activatable = full_screen ? Widget::InitParams::ACTIVATABLE_YES
- : Widget::InitParams::ACTIVATABLE_NO;
+ init_params.activatable = full_screen
+ ? Widget::InitParams::Activatable::kYes
+ : Widget::InitParams::Activatable::kNo;
init_params.z_order = root_z_order;
+ // Also provide the context, which Ozone (in particular - Wayland) will use
+ // to parent this newly created toplevel native widget to. Please refer to
+ // https://crrev.com/c/2831291 for more details.
+ init_params.context = context;
// This widget instance will get deleted when the window is
// destroyed.
@@ -203,7 +210,7 @@ class DesktopNativeWidgetAuraWindowParentingClient
const gfx::Rect& bounds) override {
bool is_fullscreen = window->GetProperty(aura::client::kShowStateKey) ==
ui::SHOW_STATE_FULLSCREEN;
- bool is_menu = window->type() == aura::client::WINDOW_TYPE_MENU;
+ bool is_menu = window->GetType() == aura::client::WINDOW_TYPE_MENU;
if (is_fullscreen || is_menu) {
ui::ZOrderLevel root_z_order = ui::ZOrderLevel::kNormal;
@@ -213,7 +220,8 @@ class DesktopNativeWidgetAuraWindowParentingClient
root_z_order = native_widget->GetZOrderLevel();
return DesktopNativeWidgetTopLevelHandler::CreateParentWindow(
- window, bounds, is_fullscreen, is_menu, root_z_order);
+ window, root_window_ /* context */, bounds, is_fullscreen, is_menu,
+ root_z_order);
}
return root_window_;
}
@@ -1041,6 +1049,10 @@ ui::GestureRecognizer* DesktopNativeWidgetAura::GetGestureRecognizer() {
return aura::Env::GetInstance()->gesture_recognizer();
}
+ui::GestureConsumer* DesktopNativeWidgetAura::GetGestureConsumer() {
+ return content_window_;
+}
+
void DesktopNativeWidgetAura::OnSizeConstraintsChanged() {
NativeWidgetAura::SetResizeBehaviorFromDelegate(
GetWidget()->widget_delegate(), content_window_);
@@ -1091,12 +1103,16 @@ void DesktopNativeWidgetAura::OnCaptureLost() {
}
void DesktopNativeWidgetAura::OnPaint(const ui::PaintContext& context) {
+ desktop_window_tree_host_->UpdateWindowShapeIfNeeded(context);
native_widget_delegate_->OnNativeWidgetPaint(context);
}
void DesktopNativeWidgetAura::OnDeviceScaleFactorChanged(
float old_device_scale_factor,
- float new_device_scale_factor) {}
+ float new_device_scale_factor) {
+ GetWidget()->DeviceScaleFactorChanged(old_device_scale_factor,
+ new_device_scale_factor);
+}
void DesktopNativeWidgetAura::OnWindowDestroying(aura::Window* window) {
// Cleanup happens in OnHostClosed().
@@ -1255,6 +1271,13 @@ ui::mojom::DragOperation DesktopNativeWidgetAura::OnPerformDrop(
last_drop_operation_);
}
+aura::client::DragDropDelegate::DropCallback
+DesktopNativeWidgetAura::GetDropCallback(const ui::DropTargetEvent& event) {
+ // TODO(crbug.com/1197505): Return drop callback.
+ NOTREACHED();
+ return base::NullCallback();
+}
+
////////////////////////////////////////////////////////////////////////////////
// DesktopNativeWidgetAura, aura::WindowTreeHostObserver implementation:
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
index b330c4e89bc..8dd86cd6e28 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
@@ -197,6 +197,7 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
Widget::VisibilityTransition transition) override;
bool IsTranslucentWindowOpacitySupported() const override;
ui::GestureRecognizer* GetGestureRecognizer() override;
+ ui::GestureConsumer* GetGestureConsumer() override;
void OnSizeConstraintsChanged() override;
void OnNativeViewHierarchyWillChange() override;
void OnNativeViewHierarchyChanged() override;
@@ -251,6 +252,8 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
ui::mojom::DragOperation OnPerformDrop(
const ui::DropTargetEvent& event,
std::unique_ptr<ui::OSExchangeData> data) override;
+ aura::client::DragDropDelegate::DropCallback GetDropCallback(
+ const ui::DropTargetEvent& event) override;
// aura::WindowTreeHostObserver:
void OnHostCloseRequested(aura::WindowTreeHost* host) override;
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen.cc
deleted file mode 100644
index 5ced5db5288..00000000000
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/widget/desktop_aura/desktop_screen.h"
-
-#include "build/chromeos_buildflags.h"
-#include "ui/display/screen.h"
-
-namespace views {
-
-void InstallDesktopScreenIfNecessary() {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
- // ChromeOS ozone builds use another path instead, where display::Screen is
- // properly set. Thus, do early return here.
- return;
-#endif
-
- // The screen may have already been set in test initialization.
- if (!display::Screen::GetScreen())
- CreateDesktopScreen();
-}
-
-} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen.h b/chromium/ui/views/widget/desktop_aura/desktop_screen.h
index 1f1ff49fe04..32505c294f4 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen.h
@@ -5,6 +5,8 @@
#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_SCREEN_H_
#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_SCREEN_H_
+#include <memory>
+
#include "ui/views/views_export.h"
namespace display {
@@ -14,10 +16,8 @@ class Screen;
namespace views {
// Creates a Screen that represents the screen of the environment that hosts
-// a WindowTreeHost. Caller owns the result.
-VIEWS_EXPORT display::Screen* CreateDesktopScreen();
-
-VIEWS_EXPORT void InstallDesktopScreenIfNecessary();
+// a WindowTreeHost.
+VIEWS_EXPORT std::unique_ptr<display::Screen> CreateDesktopScreen();
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_linux.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_linux.cc
index 7033e867924..0eba478b86f 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_linux.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_linux.cc
@@ -58,13 +58,13 @@ class DesktopScreenOzoneLinux : public DesktopScreenOzone,
#endif
-display::Screen* CreateDesktopScreen() {
+std::unique_ptr<display::Screen> CreateDesktopScreen() {
#if defined(USE_OZONE)
if (features::IsUsingOzonePlatform())
- return new DesktopScreenOzoneLinux();
+ return std::make_unique<DesktopScreenOzoneLinux>();
#endif
#if defined(USE_X11)
- auto* screen = new DesktopScreenX11();
+ auto screen = std::make_unique<DesktopScreenX11>();
screen->Init();
return screen;
#else
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc
index 1f00883eaeb..d1195d503b2 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc
@@ -4,6 +4,8 @@
#include "ui/views/widget/desktop_aura/desktop_screen_ozone.h"
+#include <memory>
+
#include "build/build_config.h"
#include "ui/aura/screen_ozone.h"
#include "ui/views/widget/desktop_aura/desktop_screen.h"
@@ -27,8 +29,8 @@ gfx::NativeWindow DesktopScreenOzone::GetNativeWindowFromAcceleratedWidget(
// factory method for OS_LINUX as Linux has a factory method that decides what
// screen to use based on IsUsingOzonePlatform feature flag.
#if !defined(OS_LINUX) && !defined(OS_CHROMEOS)
-display::Screen* CreateDesktopScreen() {
- return new DesktopScreenOzone();
+std::unique_ptr<display::Screen> CreateDesktopScreen() {
+ return std::make_unique<aura::ScreenOzone>();
}
#endif
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client.cc
index 5a04e034a57..3d56e7ac273 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client.cc
@@ -13,7 +13,7 @@ namespace {
// Returns true if bounds passed to window in SetBounds should be treated as
// though they are in screen coordinates.
bool PositionWindowInScreenCoordinates(aura::Window* window) {
- if (window->type() == aura::client::WINDOW_TYPE_POPUP)
+ if (window->GetType() == aura::client::WINDOW_TYPE_POPUP)
return true;
Widget* widget = Widget::GetWidgetForNativeView(window);
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc
index 91c516429c2..7c352dd0d99 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc
@@ -4,6 +4,8 @@
#include "ui/views/widget/desktop_aura/desktop_screen_win.h"
+#include <memory>
+
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/views/widget/desktop_aura/desktop_screen.h"
@@ -35,8 +37,8 @@ bool DesktopScreenWin::IsNativeWindowOccluded(gfx::NativeWindow window) const {
////////////////////////////////////////////////////////////////////////////////
-display::Screen* CreateDesktopScreen() {
- return new DesktopScreenWin;
+std::unique_ptr<display::Screen> CreateDesktopScreen() {
+ return std::make_unique<DesktopScreenWin>();
}
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
index 07e724129f0..956c0824a45 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
@@ -51,12 +51,12 @@ void DesktopScreenX11::Init() {
gfx::Point DesktopScreenX11::GetCursorScreenPoint() {
TRACE_EVENT0("views", "DesktopScreenX11::GetCursorScreenPoint()");
- base::Optional<gfx::Point> point_in_pixels;
+ absl::optional<gfx::Point> point_in_pixels;
if (const auto* const event_source = ui::X11EventSource::GetInstance())
point_in_pixels = event_source->GetRootCursorLocationFromCurrentEvent();
if (!point_in_pixels) {
// This call is expensive so we explicitly only call it when
- // |point_in_pixels| is not set. We note that base::Optional::value_or()
+ // |point_in_pixels| is not set. We note that absl::optional::value_or()
// would cause it to be called regardless.
point_in_pixels = x11_display_manager_->GetCursorLocation();
}
@@ -163,14 +163,6 @@ std::string DesktopScreenX11::GetCurrentWorkspace() {
return x11_display_manager_->GetCurrentWorkspace();
}
-base::Value DesktopScreenX11::GetGpuExtraInfoAsListValue(
- const gfx::GpuExtraInfo& gpu_extra_info) {
- auto result = ui::GetDesktopEnvironmentInfoAsListValue();
- ui::StoreGpuExtraInfoIntoListValue(gpu_extra_info.system_visual,
- gpu_extra_info.rgba_visual, result);
- return result;
-}
-
void DesktopScreenX11::OnEvent(const x11::Event& event) {
x11_display_manager_->OnEvent(event);
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h
index dd7725c90bd..efbb8498cb3 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h
@@ -53,8 +53,6 @@ class VIEWS_EXPORT DesktopScreenX11 : public display::Screen,
void AddObserver(display::DisplayObserver* observer) override;
void RemoveObserver(display::DisplayObserver* observer) override;
std::string GetCurrentWorkspace() override;
- base::Value GetGpuExtraInfoAsListValue(
- const gfx::GpuExtraInfo& gpu_extra_info) override;
// x11::EventObserver:
void OnEvent(const x11::Event& event) override;
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.cc
index 5e52f080e7b..047f9a9523d 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.cc
@@ -18,6 +18,9 @@ void DesktopWindowTreeHost::SetBoundsInDIP(const gfx::Rect& bounds) {
AsWindowTreeHost()->SetBoundsInPixels(bounds_in_pixels);
}
+void DesktopWindowTreeHost::UpdateWindowShapeIfNeeded(
+ const ui::PaintContext& context) {}
+
std::unique_ptr<aura::client::ScreenPositionClient>
DesktopWindowTreeHost::CreateScreenPositionClient() {
return std::make_unique<DesktopScreenPositionClient>(
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.h
index 735ff41b55a..5ac6a910055 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.h
@@ -28,6 +28,10 @@ class ImageSkia;
class Rect;
} // namespace gfx
+namespace ui {
+class PaintContext;
+} // namespace ui
+
namespace views {
namespace corewm {
class Tooltip;
@@ -198,6 +202,9 @@ class VIEWS_EXPORT DesktopWindowTreeHost {
// Sets the bounds in screen coordinate DIPs (WindowTreeHost generally
// operates in pixels). This function is implemented in terms of Screen.
virtual void SetBoundsInDIP(const gfx::Rect& bounds);
+
+ // Updates window shape by clipping the canvas before paint starts.
+ virtual void UpdateWindowShapeIfNeeded(const ui::PaintContext& context);
};
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
index 1493ae74f47..7f7d82f5186 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
@@ -15,9 +15,11 @@
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/base/ui_base_features.h"
+#include "ui/compositor/compositor.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/event.h"
+#include "ui/platform_window/extensions/wayland_extension.h"
#include "ui/platform_window/extensions/x11_extension.h"
#include "ui/platform_window/platform_window_init_properties.h"
#include "ui/platform_window/wm/wm_move_resize_handler.h"
@@ -103,6 +105,23 @@ void DesktopWindowTreeHostLinux::CleanUpWindowList(
open_windows_ = nullptr;
}
+// static
+DesktopWindowTreeHostLinux* DesktopWindowTreeHostLinux::From(
+ WindowTreeHost* wth) {
+ DCHECK(open_windows_) << "Calling this method from non-Linux based "
+ "platform.";
+
+ for (auto widget : *open_windows_) {
+ DesktopWindowTreeHostPlatform* wth_platform =
+ DesktopWindowTreeHostPlatform::GetHostForWidget(widget);
+ if (wth_platform != wth)
+ continue;
+
+ return static_cast<views::DesktopWindowTreeHostLinux*>(wth_platform);
+ }
+ return nullptr;
+}
+
gfx::Rect DesktopWindowTreeHostLinux::GetXRootWindowOuterBounds() const {
// TODO(msisov): must be removed as soon as all X11 low-level bits are moved
// to Ozone.
@@ -139,6 +158,15 @@ base::OnceClosure DesktopWindowTreeHostLinux::DisableEventListening() {
weak_factory_.GetWeakPtr());
}
+ui::WaylandExtension* DesktopWindowTreeHostLinux::GetWaylandExtension() {
+ return ui::GetWaylandExtension(*(platform_window()));
+}
+
+const ui::WaylandExtension* DesktopWindowTreeHostLinux::GetWaylandExtension()
+ const {
+ return ui::GetWaylandExtension(*(platform_window()));
+}
+
void DesktopWindowTreeHostLinux::Init(const Widget::InitParams& params) {
DesktopWindowTreeHostPlatform::Init(params);
@@ -296,7 +324,7 @@ void DesktopWindowTreeHostLinux::AddAdditionalInitProperties(
// happening between the XWindow is mapped and the first expose event
// is completely handled less annoying. If possible, we use the content
// window's background color, otherwise we fallback to white.
- base::Optional<int> background_color;
+ absl::optional<int> background_color;
const views::LinuxUI* linux_ui = views::LinuxUI::instance();
if (linux_ui && GetContentWindow()) {
ui::NativeTheme::ColorId target_color;
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
index e0339379e1a..49c2776892f 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
@@ -25,6 +25,7 @@ class ScopedWindowTargeter;
namespace ui {
class X11Extension;
+class WaylandExtension;
} // namespace ui
namespace views {
@@ -50,6 +51,9 @@ class VIEWS_EXPORT DesktopWindowTreeHostLinux
// internal list of open windows.
static void CleanUpWindowList(void (*func)(aura::Window* window));
+ // Casts from a base WindowTreeHost instance.
+ static DesktopWindowTreeHostLinux* From(WindowTreeHost* wth);
+
// Returns the current bounds in terms of the X11 Root Window including the
// borders provided by the window manager (if any). Not in use for Wayland.
gfx::Rect GetXRootWindowOuterBounds() const;
@@ -66,6 +70,9 @@ class VIEWS_EXPORT DesktopWindowTreeHostLinux
// Disables event listening to make |dialog| modal.
base::OnceClosure DisableEventListening();
+ ui::WaylandExtension* GetWaylandExtension();
+ const ui::WaylandExtension* GetWaylandExtension() const;
+
protected:
// Overridden from DesktopWindowTreeHost:
void Init(const Widget::InitParams& params) override;
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
index 4065e82e685..a250b77813f 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
@@ -18,6 +18,8 @@
#include "ui/aura/client/transient_window_client.h"
#include "ui/base/hit_test.h"
#include "ui/base/ui_base_features.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/paint_recorder.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/dip_util.h"
@@ -29,7 +31,6 @@
#include "ui/views/corewm/tooltip_aura.h"
#include "ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
-#include "ui/views/widget/desktop_aura/window_shape_updater.h"
#include "ui/views/widget/widget_aura_utils.h"
#include "ui/views/window/native_frame_view.h"
#include "ui/wm/core/window_util.h"
@@ -110,7 +111,7 @@ ui::PlatformWindowInitProperties ConvertWidgetInitParamsToInitProperties(
ui::PlatformWindowInitProperties properties;
properties.type = GetPlatformWindowType(params.type);
properties.activatable =
- params.activatable == Widget::InitParams::ACTIVATABLE_YES;
+ params.activatable == Widget::InitParams::Activatable::kYes;
properties.force_show_in_taskbar = params.force_show_in_taskbar;
properties.keep_on_top =
params.EffectiveZOrderLevel() != ui::ZOrderLevel::kNormal;
@@ -124,19 +125,35 @@ ui::PlatformWindowInitProperties ConvertWidgetInitParamsToInitProperties(
properties.parent_widget = params.parent->GetHost()->GetAcceleratedWidget();
#if defined(USE_OZONE)
- if (properties.type == ui::PlatformWindowType::kTooltip &&
- features::IsUsingOzonePlatform() &&
+ if (features::IsUsingOzonePlatform() &&
ui::OzonePlatform::GetInstance()
->GetPlatformProperties()
.set_parent_for_non_top_level_windows) {
- properties.parent_widget =
- params.context->GetHost()->GetAcceleratedWidget();
+ // If the parent has not been provided, but there is context, use the
+ // context's widget as the parent of a new platform window.
+ if (params.context && params.context->GetHost() &&
+ !properties.parent_widget) {
+ properties.parent_widget =
+ params.context->GetHost()->GetAcceleratedWidget();
+ }
}
#endif
return properties;
}
+SkPath GetWindowMask(const Widget* widget) {
+ if (!widget->non_client_view())
+ return SkPath();
+
+ SkPath window_mask;
+ // Some frame views define a custom (non-rectanguar) window mask.
+ // If so, use it to define the window shape. If not, fall through.
+ const_cast<NonClientView*>(widget->non_client_view())
+ ->GetWindowMask(widget->GetWindowBoundsInScreen().size(), &window_mask);
+ return window_mask;
+}
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -228,13 +245,11 @@ void DesktopWindowTreeHostPlatform::OnNativeWidgetCreated(
}
void DesktopWindowTreeHostPlatform::OnWidgetInitDone() {
- // WindowShape is updated from ShapeRects transformed from
- // NonClientView::GetWindowMask. We can guarantee that |NonClientView|
- // is created OnWidgetInitDone.
- if (ShouldUseLayerForShapedWindow()) {
- WindowShapeUpdater::CreateWindowShapeUpdater(
- this, this->desktop_native_widget_aura());
- }
+ // Once we can guarantee |NonClientView| is created OnWidgetInitDone,
+ // UpdateWindowTransparency and FillsBoundsCompletely accordingly.
+ desktop_native_widget_aura_->UpdateWindowTransparency();
+ GetContentWindow()->SetFillsBoundsCompletely(
+ GetWindowMaskForClipping().isEmpty());
}
void DesktopWindowTreeHostPlatform::OnActiveWindowChanged(bool active) {}
@@ -463,10 +478,7 @@ std::string DesktopWindowTreeHostPlatform::GetWorkspace() const {
}
gfx::Rect DesktopWindowTreeHostPlatform::GetWorkAreaBoundsInScreen() const {
- // TODO(sky): GetDisplayNearestWindow() should take a const aura::Window*.
- return display::Screen::GetScreen()
- ->GetDisplayNearestWindow(const_cast<aura::Window*>(window()))
- .work_area();
+ return GetDisplayNearestRootWindow().work_area();
}
void DesktopWindowTreeHostPlatform::SetShape(
@@ -596,7 +608,7 @@ bool DesktopWindowTreeHostPlatform::ShouldUseNativeFrame() const {
bool DesktopWindowTreeHostPlatform::ShouldWindowContentsBeTransparent() const {
return platform_window()->ShouldWindowContentsBeTransparent() ||
- ShouldUseLayerForShapedWindow();
+ !(GetWindowMaskForClipping().isEmpty());
}
void DesktopWindowTreeHostPlatform::FrameTypeChanged() {
@@ -691,15 +703,26 @@ bool DesktopWindowTreeHostPlatform::ShouldCreateVisibilityController() const {
return true;
}
+void DesktopWindowTreeHostPlatform::UpdateWindowShapeIfNeeded(
+ const ui::PaintContext& context) {
+ if (is_shape_explicitly_set_)
+ return;
+
+ SkPath clip_path = GetWindowMaskForClipping();
+ if (clip_path.isEmpty())
+ return;
+
+ ui::PaintRecorder recorder(context, GetWindowBoundsInScreen().size());
+ recorder.canvas()->ClipPath(clip_path, true);
+}
+
gfx::Transform DesktopWindowTreeHostPlatform::GetRootTransform() const {
display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
// This might be called before the |platform_window| is created. Thus,
// explicitly check if that exists before trying to access its visibility and
// the display where it is shown.
- if (platform_window()) {
- display = display::Screen::GetScreen()->GetDisplayNearestWindow(
- GetWidget()->GetNativeWindow());
- }
+ if (platform_window())
+ display = GetDisplayNearestRootWindow();
float scale = display.device_scale_factor();
gfx::Transform transform;
@@ -767,27 +790,20 @@ void DesktopWindowTreeHostPlatform::OnActivationChanged(bool active) {
ScheduleRelayout();
}
-base::Optional<gfx::Size>
+absl::optional<gfx::Size>
DesktopWindowTreeHostPlatform::GetMinimumSizeForWindow() {
return ToPixelRect(gfx::Rect(native_widget_delegate()->GetMinimumSize()))
.size();
}
-base::Optional<gfx::Size>
+absl::optional<gfx::Size>
DesktopWindowTreeHostPlatform::GetMaximumSizeForWindow() {
return ToPixelRect(gfx::Rect(native_widget_delegate()->GetMaximumSize()))
.size();
}
SkPath DesktopWindowTreeHostPlatform::GetWindowMaskForWindowShapeInPixels() {
- if (!GetWidget()->non_client_view())
- return SkPath();
-
- SkPath window_mask;
- // Some frame views define a custom (non-rectanguar) window mask.
- // If so, use it to define the window shape. If not, fall through.
- GetWidget()->non_client_view()->GetWindowMask(
- GetWindowBoundsInScreen().size(), &window_mask);
+ SkPath window_mask = GetWindowMask(GetWidget());
// Convert SkPath in DIPs to pixels.
if (!window_mask.isEmpty())
window_mask.transform(SkMatrix(GetRootTransform().matrix()));
@@ -821,6 +837,11 @@ void DesktopWindowTreeHostPlatform::ScheduleRelayout() {
non_client_view->frame_view()->InvalidateLayout();
non_client_view->client_view()->InvalidateLayout();
non_client_view->InvalidateLayout();
+ // Once |NonClientView| is invalidateLayout,
+ // UpdateWindowTransparency and FillsBoundsCompletely accordingly.
+ desktop_native_widget_aura_->UpdateWindowTransparency();
+ GetContentWindow()->SetFillsBoundsCompletely(
+ GetWindowMaskForClipping().isEmpty());
}
}
@@ -843,8 +864,19 @@ void DesktopWindowTreeHostPlatform::AddAdditionalInitProperties(
const Widget::InitParams& params,
ui::PlatformWindowInitProperties* properties) {}
-bool DesktopWindowTreeHostPlatform::ShouldUseLayerForShapedWindow() const {
- return platform_window()->ShouldUseLayerForShapedWindow();
+SkPath DesktopWindowTreeHostPlatform::GetWindowMaskForClipping() const {
+ if (!platform_window()->ShouldUpdateWindowShape())
+ return SkPath();
+ return GetWindowMask(GetWidget());
+}
+
+display::Display DesktopWindowTreeHostPlatform::GetDisplayNearestRootWindow()
+ const {
+ DCHECK(window());
+ DCHECK(window()->IsRootWindow());
+ // TODO(sky): GetDisplayNearestWindow() should take a const aura::Window*.
+ return display::Screen::GetScreen()->GetDisplayNearestWindow(
+ const_cast<aura::Window*>(window()));
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
index c2f139c51db..b904b4f41cc 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
@@ -18,6 +18,10 @@
#include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
#include "ui/views/widget/desktop_aura/window_move_client_platform.h"
+namespace ui {
+class PaintContext;
+} // namespace ui
+
namespace views {
class VIEWS_EXPORT DesktopWindowTreeHostPlatform
@@ -42,8 +46,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostPlatform
aura::Window* GetContentWindow();
const aura::Window* GetContentWindow() const;
- bool is_shape_explicitly_set() const { return is_shape_explicitly_set_; }
-
// DesktopWindowTreeHost:
void Init(const Widget::InitParams& params) override;
void OnNativeWidgetCreated(const Widget::InitParams& params) override;
@@ -108,6 +110,7 @@ class VIEWS_EXPORT DesktopWindowTreeHostPlatform
bool ShouldUpdateWindowTransparency() const override;
bool ShouldUseDesktopNativeCursorManager() const override;
bool ShouldCreateVisibilityController() const override;
+ void UpdateWindowShapeIfNeeded(const ui::PaintContext& context) override;
// WindowTreeHost:
gfx::Transform GetRootTransform() const override;
@@ -120,8 +123,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostPlatform
void OnCloseRequest() override;
void OnWillDestroyAcceleratedWidget() override;
void OnActivationChanged(bool active) override;
- base::Optional<gfx::Size> GetMinimumSizeForWindow() override;
- base::Optional<gfx::Size> GetMaximumSizeForWindow() override;
+ absl::optional<gfx::Size> GetMinimumSizeForWindow() override;
+ absl::optional<gfx::Size> GetMaximumSizeForWindow() override;
SkPath GetWindowMaskForWindowShapeInPixels() override;
// ui::WorkspaceExtensionDelegate:
@@ -158,9 +161,12 @@ class VIEWS_EXPORT DesktopWindowTreeHostPlatform
const Widget::InitParams& params,
ui::PlatformWindowInitProperties* properties);
- // Returns true if WindowShapeUpdater should update the window shape by
- // window mask, otherwise false when window shape is already updated in views.
- virtual bool ShouldUseLayerForShapedWindow() const;
+ // Returns window mask to clip canvas to update window shape of
+ // the content window.
+ virtual SkPath GetWindowMaskForClipping() const;
+
+ // Helper method that returns the display for the |window()|.
+ display::Display GetDisplayNearestRootWindow() const;
internal::NativeWidgetDelegate* const native_widget_delegate_;
DesktopNativeWidgetAura* const desktop_native_widget_aura_;
@@ -182,8 +188,9 @@ class VIEWS_EXPORT DesktopWindowTreeHostPlatform
// Used for tab dragging in move loop requests.
WindowMoveClientPlatform window_move_client_;
- // ui::Layer::SetAlphaShape can be set from either SetShape or default window
- // mask. When explicitly setting from SetShape, |explicitly_set_shape_:true|.
+ // The content window shape can be set from either SetShape or default window
+ // mask. When explicitly setting from SetShape, |explicitly_set_shape_:true|
+ // to prevent clipping the canvas before painting for default window mask.
bool is_shape_explicitly_set_ = false;
base::WeakPtrFactory<DesktopWindowTreeHostPlatform> close_widget_factory_{
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_unittest.cc
index 6d431251754..51cbb691d8e 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_unittest.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_unittest.cc
@@ -11,6 +11,7 @@
#include "base/run_loop.h"
#include "ui/aura/window_tree_host.h"
#include "ui/aura/window_tree_host_observer.h"
+#include "ui/compositor/layer.h"
#include "ui/display/display_switches.h"
#include "ui/platform_window/platform_window.h"
#include "ui/views/test/views_test_base.h"
@@ -179,24 +180,25 @@ TEST_F(DesktopWindowTreeHostPlatformTest, UpdateWindowShapeFromWindowMask) {
auto* host_platform = DesktopWindowTreeHostPlatform::GetHostForWidget(
widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
ASSERT_TRUE(host_platform);
- if (!host_platform->platform_window()->ShouldUseLayerForShapedWindow())
+ if (!host_platform->platform_window()->ShouldUpdateWindowShape())
return;
auto* content_window =
DesktopWindowTreeHostPlatform::GetContentWindowForWidget(
widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
ASSERT_TRUE(content_window);
- // alpha_shape for the layer of content window is updated from the
- // |NonClientView::GetWindowMask|.
EXPECT_FALSE(host_platform->GetWindowMaskForWindowShapeInPixels().isEmpty());
- EXPECT_TRUE(content_window->layer()->alpha_shape());
+ // SetClipPath for the layer of the content window is updated from it.
+ EXPECT_TRUE(host_platform->ShouldWindowContentsBeTransparent());
+ EXPECT_FALSE(widget->GetLayer()->FillsBoundsCompletely());
- // When fullscreen mode, alpha_shape is set to empty since there is no
+ // When fullscreen mode, clip_path_ is set to empty since there is no
// |NonClientView::GetWindowMask|.
host_platform->SetFullscreen(true);
widget->SetBounds(gfx::Rect(800, 800));
EXPECT_TRUE(host_platform->GetWindowMaskForWindowShapeInPixels().isEmpty());
- EXPECT_FALSE(content_window->layer()->alpha_shape());
+ EXPECT_FALSE(host_platform->ShouldWindowContentsBeTransparent());
+ EXPECT_TRUE(widget->GetLayer()->FillsBoundsCompletely());
}
// A Widget that allows setting the min/max size for the widget.
@@ -286,62 +288,4 @@ TEST_F(DesktopWindowTreeHostPlatformTest, SetBoundsWithUnchangedSize) {
EXPECT_EQ(0, observer.resize_count());
}
-class DesktopWindowTreeHostPlatformHighDPITest
- : public DesktopWindowTreeHostPlatformTest {
- public:
- DesktopWindowTreeHostPlatformHighDPITest() = default;
- ~DesktopWindowTreeHostPlatformHighDPITest() override = default;
-
- private:
- void SetUp() override {
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- command_line->AppendSwitchASCII(switches::kForceDeviceScaleFactor, "2");
-
- DesktopWindowTreeHostPlatformTest::SetUp();
- }
-};
-
-// Tests that the window shape is updated properly from the
-// |NonClientView::GetWindowMask| in HighDPI.
-TEST_F(DesktopWindowTreeHostPlatformHighDPITest, VerifyWindowShapeInHighDPI) {
- std::unique_ptr<Widget> widget = CreateWidgetWithNativeWidget();
- widget->Show();
-
- auto* host_platform = DesktopWindowTreeHostPlatform::GetHostForWidget(
- widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
- ASSERT_TRUE(host_platform);
- if (!host_platform->platform_window()->ShouldUseLayerForShapedWindow())
- return;
-
- auto* content_window =
- DesktopWindowTreeHostPlatform::GetContentWindowForWidget(
- widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
- ASSERT_TRUE(content_window);
- // Check device scale factor.
- EXPECT_EQ(host_platform->device_scale_factor(), 2.0);
-
- // alpha_shape for the layer of content window is updated from the
- // |NonClientView::GetWindowMask|.
- SkPath path_in_pixels = host_platform->GetWindowMaskForWindowShapeInPixels();
- EXPECT_FALSE(path_in_pixels.isEmpty());
-
- // Converts path to DIPs and calculates expected region from it.
- SkPath path_in_dips;
- path_in_pixels.transform(
- SkMatrix(host_platform->GetInverseRootTransform().matrix()),
- &path_in_dips);
- SkRegion region;
- region.setRect(path_in_dips.getBounds().round());
- SkRegion expected_region;
- expected_region.setPath(path_in_dips, region);
-
- SkRegion shape_region;
- for (auto& bound : *(content_window->layer()->alpha_shape()))
- shape_region.op(gfx::RectToSkIRect(bound), SkRegion::Op::kUnion_Op);
-
- // Test that region from alpha_shape is same as the expected region from path
- // in DIPs.
- EXPECT_EQ(shape_region, expected_region);
-}
-
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index 6a804c0d36a..fb8bbb639f6 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/containers/flat_set.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event.h"
#include "base/win/win_util.h"
@@ -22,11 +23,14 @@
#include "ui/aura/client/focus_client.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/class_property.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/cursor/win/win_cursor.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ui_base_features.h"
#include "ui/base/win/event_creation_utils.h"
#include "ui/base/win/shell.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/paint_context.h"
#include "ui/display/win/dpi.h"
#include "ui/display/win/screen_win.h"
@@ -169,7 +173,7 @@ void DesktopWindowTreeHostWin::OnNativeWidgetCreated(
window()->SetProperty(kDesktopWindowTreeHostKey, this);
should_animate_window_close_ =
- content_window()->type() != aura::client::WINDOW_TYPE_NORMAL &&
+ content_window()->GetType() != aura::client::WINDOW_TYPE_NORMAL &&
!wm::WindowAnimationsDisabled(content_window());
}
@@ -606,7 +610,7 @@ void DesktopWindowTreeHostWin::ReleaseCapture() {
}
bool DesktopWindowTreeHostWin::CaptureSystemKeyEventsImpl(
- base::Optional<base::flat_set<ui::DomCode>> dom_codes) {
+ absl::optional<base::flat_set<ui::DomCode>> dom_codes) {
// Only one KeyboardHook should be active at a time, otherwise there will be
// problems with event routing (i.e. which Hook takes precedence) and
// destruction ordering.
@@ -636,10 +640,8 @@ void DesktopWindowTreeHostWin::SetCursorNative(gfx::NativeCursor cursor) {
TRACE_EVENT1("ui,input", "DesktopWindowTreeHostWin::SetCursorNative",
"cursor", cursor.type());
- ui::WinCursor* platform_cursor =
- static_cast<ui::WinCursor*>(cursor.platform());
- DCHECK(platform_cursor);
- message_handler_->SetCursor(platform_cursor->hcursor());
+ message_handler_->SetCursor(
+ ui::WinCursor::FromPlatformCursor(cursor.platform()));
}
void DesktopWindowTreeHostWin::OnCursorVisibilityChangedNative(bool show) {
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
index 5642a689cb3..07078cbdf22 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -142,7 +142,7 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
void SetCapture() override;
void ReleaseCapture() override;
bool CaptureSystemKeyEventsImpl(
- base::Optional<base::flat_set<ui::DomCode>> dom_codes) override;
+ absl::optional<base::flat_set<ui::DomCode>> dom_codes) override;
void ReleaseSystemKeyEventCapture() override;
bool IsKeyLocked(ui::DomCode dom_code) override;
base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
diff --git a/chromium/ui/views/widget/desktop_aura/window_shape_updater.cc b/chromium/ui/views/widget/desktop_aura/window_shape_updater.cc
deleted file mode 100644
index 5c145331ef0..00000000000
--- a/chromium/ui/views/widget/desktop_aura/window_shape_updater.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/widget/desktop_aura/window_shape_updater.h"
-
-#include "ui/gfx/skia_util.h"
-#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
-#include "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h"
-
-namespace {
-
-std::unique_ptr<ui::Layer::ShapeRects> ConvertToShapeRects(const SkPath& path) {
- // Converts to ShapeRects from SkPath.
- auto shape_rects = std::make_unique<ui::Layer::ShapeRects>();
- SkRegion clip_region;
- clip_region.setRect(path.getBounds().round());
- SkRegion region;
- region.setPath(path, clip_region);
- for (SkRegion::Iterator it(region); !it.done(); it.next())
- shape_rects->push_back(gfx::SkIRectToRect(it.rect()));
- return shape_rects;
-}
-
-} // namespace
-
-namespace views {
-
-// static
-WindowShapeUpdater* WindowShapeUpdater::CreateWindowShapeUpdater(
- DesktopWindowTreeHostPlatform* tree_host,
- DesktopNativeWidgetAura* native_widget_aura) {
- return new WindowShapeUpdater(tree_host, native_widget_aura);
-}
-
-WindowShapeUpdater::WindowShapeUpdater(
- DesktopWindowTreeHostPlatform* tree_host,
- DesktopNativeWidgetAura* native_widget_aura)
- : tree_host_(tree_host), native_widget_aura_(native_widget_aura) {
- tree_host_->GetContentWindow()->AddObserver(this);
- UpdateWindowShapeFromWindowMask(tree_host_->GetContentWindow());
-}
-
-void WindowShapeUpdater::OnWindowBoundsChanged(
- aura::Window* window,
- const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds,
- ui::PropertyChangeReason reason) {
- UpdateWindowShapeFromWindowMask(window);
-}
-
-void WindowShapeUpdater::OnWindowDestroying(aura::Window* window) {
- window->RemoveObserver(this);
- delete this;
-}
-
-void WindowShapeUpdater::UpdateWindowShapeFromWindowMask(aura::Window* window) {
- // If |ui::Layer::alpha_shape_| is set explicitly from SetShape,
- // we don't need to set default window mask from non_client_view.
- if (tree_host_->is_shape_explicitly_set())
- return;
- // WindowTransparency should be updated as well when the window shape is
- // changed. When a window mask exists, transparent should be true to prevent
- // compositor from filling the entire screen in AppendQuadsToFillScreen.
- // Otherwise, transparent should be false.
- native_widget_aura_->UpdateWindowTransparency();
- SkPath path = tree_host_->GetWindowMaskForWindowShapeInPixels();
- if (path.isEmpty()) {
- window->layer()->SetAlphaShape(nullptr);
- return;
- }
- SkPath path_in_dips;
- path.transform(SkMatrix(tree_host_->GetInverseRootTransform().matrix()),
- &path_in_dips);
-
- // SetAlphaShape to the layer of |content_window_|
- window->layer()->SetAlphaShape(ConvertToShapeRects(path_in_dips));
-}
-
-} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/window_shape_updater.h b/chromium/ui/views/widget/desktop_aura/window_shape_updater.h
deleted file mode 100644
index ec773625273..00000000000
--- a/chromium/ui/views/widget/desktop_aura/window_shape_updater.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_WINDOW_SHAPE_UPDATER_H_
-#define UI_VIEWS_WIDGET_DESKTOP_AURA_WINDOW_SHAPE_UPDATER_H_
-
-#include <memory>
-
-#include "ui/aura/window_observer.h"
-#include "ui/compositor/layer.h"
-
-namespace views {
-
-class DesktopNativeWidgetAura;
-class DesktopWindowTreeHostPlatform;
-
-// Class to observe the window bounds changed to update window shape
-// for the rounded corner of the browser frame.
-class WindowShapeUpdater : public aura::WindowObserver {
- public:
- static WindowShapeUpdater* CreateWindowShapeUpdater(
- DesktopWindowTreeHostPlatform* tree_host,
- DesktopNativeWidgetAura* native_widget_aura);
-
- private:
- WindowShapeUpdater(DesktopWindowTreeHostPlatform* tree_host,
- DesktopNativeWidgetAura* native_widget_aura);
- WindowShapeUpdater(const WindowShapeUpdater&) = delete;
- WindowShapeUpdater& operator=(const WindowShapeUpdater&) = delete;
- ~WindowShapeUpdater() override = default;
-
- // aura::WindowObserver:
- void OnWindowBoundsChanged(aura::Window* window,
- const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds,
- ui::PropertyChangeReason reason) override;
-
- void OnWindowDestroying(aura::Window* window) override;
-
- void UpdateWindowShapeFromWindowMask(aura::Window* window);
-
- DesktopWindowTreeHostPlatform* tree_host_ = nullptr;
- DesktopNativeWidgetAura* native_widget_aura_ = nullptr;
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_WINDOW_SHAPE_UPDATER_H_
diff --git a/chromium/ui/views/widget/desktop_aura/x11_drag_drop_client_unittest.cc b/chromium/ui/views/widget/desktop_aura/x11_drag_drop_client_unittest.cc
index d7644374df9..ed88dd603f9 100644
--- a/chromium/ui/views/widget/desktop_aura/x11_drag_drop_client_unittest.cc
+++ b/chromium/ui/views/widget/desktop_aura/x11_drag_drop_client_unittest.cc
@@ -13,6 +13,7 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
@@ -22,9 +23,9 @@
#include "ui/aura/test/test_screen.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
-#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/cursor_loader.h"
#include "ui/base/cursor/mojom/cursor_type.mojom.h"
+#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
#include "ui/base/dragdrop/os_exchange_data.h"
@@ -43,9 +44,10 @@
#include "ui/views/widget/widget.h"
namespace views {
-
namespace {
+using ::ui::mojom::DragOperation;
+
class TestDragDropClient;
// Collects messages which would otherwise be sent to |window_| via
@@ -119,12 +121,12 @@ class SimpleTestDragDropClient : public aura::client::DragDropClient,
bool IsMoveLoopRunning();
// aura::client::DragDropClient:
- int StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data,
- aura::Window* root_window,
- aura::Window* source_window,
- const gfx::Point& screen_location,
- int operation,
- ui::mojom::DragEventSource source) override;
+ DragOperation StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data,
+ aura::Window* root_window,
+ aura::Window* source_window,
+ const gfx::Point& screen_location,
+ int allowed_operations,
+ ui::mojom::DragEventSource source) override;
void DragCancel() override;
bool IsDragDropInProgress() override;
void AddObserver(aura::client::DragDropClientObserver* observer) override;
@@ -134,12 +136,11 @@ class SimpleTestDragDropClient : public aura::client::DragDropClient,
// ui::XDragDropClient::Delegate:
std::unique_ptr<ui::XTopmostWindowFinder> CreateWindowFinder() override;
int UpdateDrag(const gfx::Point& screen_point) override;
- void UpdateCursor(
- ui::DragDropTypes::DragOperation negotiated_operation) override;
+ void UpdateCursor(DragOperation negotiated_operation) override;
void OnBeginForeignDrag(x11::Window window) override;
void OnEndForeignDrag() override;
void OnBeforeDragLeave() override;
- int PerformDrop() override;
+ DragOperation PerformDrop() override;
void EndDragLoop() override;
// XDragDropClient:
@@ -306,14 +307,14 @@ std::unique_ptr<ui::X11MoveLoop> SimpleTestDragDropClient::CreateMoveLoop(
return base::WrapUnique(loop_);
}
-int SimpleTestDragDropClient::StartDragAndDrop(
+DragOperation SimpleTestDragDropClient::StartDragAndDrop(
std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& screen_location,
- int operation,
+ int allowed_operations,
ui::mojom::DragEventSource source) {
- InitDrag(operation, data.get());
+ InitDrag(allowed_operations, data.get());
auto loop = CreateMoveLoop(this);
@@ -323,10 +324,10 @@ int SimpleTestDragDropClient::StartDragAndDrop(
ui::CursorLoader cursor_loader;
ui::Cursor grabbing = ui::mojom::CursorType::kGrabbing;
cursor_loader.SetPlatformCursor(&grabbing);
- auto* last_cursor = static_cast<ui::X11Cursor*>(
- source_window->GetHost()->last_cursor().platform());
- loop_->RunMoveLoop(!source_window->HasCapture(), last_cursor,
- static_cast<ui::X11Cursor*>(grabbing.platform()));
+ auto last_cursor = source_window->GetHost()->last_cursor();
+ loop_->RunMoveLoop(!source_window->HasCapture(),
+ ui::X11Cursor::FromPlatformCursor(last_cursor.platform()),
+ ui::X11Cursor::FromPlatformCursor(grabbing.platform()));
auto resulting_operation = negotiated_operation();
CleanupDrag();
@@ -351,12 +352,12 @@ SimpleTestDragDropClient::CreateWindowFinder() {
return {};
}
void SimpleTestDragDropClient::UpdateCursor(
- ui::DragDropTypes::DragOperation negotiated_operation) {}
+ DragOperation negotiated_operation) {}
void SimpleTestDragDropClient::OnBeginForeignDrag(x11::Window window) {}
void SimpleTestDragDropClient::OnEndForeignDrag() {}
void SimpleTestDragDropClient::OnBeforeDragLeave() {}
-int SimpleTestDragDropClient::PerformDrop() {
- return 0;
+DragOperation SimpleTestDragDropClient::PerformDrop() {
+ return DragOperation::kNone;
}
void SimpleTestDragDropClient::EndDragLoop() {
// std::move(quit_closure_).Run();
@@ -462,7 +463,7 @@ class X11DragDropClientTest : public ViewsTestBase {
X11DragDropClientTest() = default;
~X11DragDropClientTest() override = default;
- int StartDragAndDrop() {
+ DragOperation StartDragAndDrop() {
auto data(std::make_unique<ui::OSExchangeData>());
data->SetString(u"Test");
SkBitmap drag_bitmap;
@@ -605,15 +606,15 @@ TEST_F(X11DragDropClientTest, Basic) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&BasicStep2, client(), toplevel));
- int result = StartDragAndDrop();
- EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, result);
+ DragOperation result = StartDragAndDrop();
+ EXPECT_EQ(DragOperation::kCopy, result);
// Do another drag and drop to test that the data is properly cleaned up as a
// result of the XdndFinished message.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&BasicStep3, client(), toplevel));
result = StartDragAndDrop();
- EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, result);
+ EXPECT_EQ(DragOperation::kCopy, result);
}
namespace {
@@ -646,8 +647,8 @@ void TargetDoesNotRespondStep2(TestDragDropClient* client) {
TEST_F(X11DragDropClientTest, TargetDoesNotRespond) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&TargetDoesNotRespondStep2, client()));
- int result = StartDragAndDrop();
- EXPECT_EQ(ui::DragDropTypes::DRAG_NONE, result);
+ DragOperation result = StartDragAndDrop();
+ EXPECT_EQ(DragOperation::kNone, result);
}
namespace {
@@ -691,8 +692,8 @@ void QueuePositionStep2(TestDragDropClient* client) {
TEST_F(X11DragDropClientTest, QueuePosition) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&QueuePositionStep2, client()));
- int result = StartDragAndDrop();
- EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, result);
+ DragOperation result = StartDragAndDrop();
+ EXPECT_EQ(DragOperation::kCopy, result);
}
namespace {
@@ -743,8 +744,8 @@ void TargetChangesStep2(TestDragDropClient* client) {
TEST_F(X11DragDropClientTest, TargetChanges) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&TargetChangesStep2, client()));
- int result = StartDragAndDrop();
- EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, result);
+ DragOperation result = StartDragAndDrop();
+ EXPECT_EQ(DragOperation::kCopy, result);
}
namespace {
@@ -812,14 +813,14 @@ void RejectAfterMouseReleaseStep3(TestDragDropClient* client) {
TEST_F(X11DragDropClientTest, RejectAfterMouseRelease) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&RejectAfterMouseReleaseStep2, client()));
- int result = StartDragAndDrop();
- EXPECT_EQ(ui::DragDropTypes::DRAG_NONE, result);
+ DragOperation result = StartDragAndDrop();
+ EXPECT_EQ(DragOperation::kNone, result);
// Repeat the test but reject the drop in the XdndFinished message instead.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&RejectAfterMouseReleaseStep3, client()));
result = StartDragAndDrop();
- EXPECT_EQ(ui::DragDropTypes::DRAG_NONE, result);
+ EXPECT_EQ(DragOperation::kNone, result);
}
} // namespace views
diff --git a/chromium/ui/views/widget/drop_helper.cc b/chromium/ui/views/widget/drop_helper.cc
index 38d1b129c2c..ce8f2d7741a 100644
--- a/chromium/ui/views/widget/drop_helper.cc
+++ b/chromium/ui/views/widget/drop_helper.cc
@@ -4,14 +4,16 @@
#include "ui/views/widget/drop_helper.h"
+#include <memory>
#include <set>
+#include "base/bind.h"
#include "base/callback.h"
+#include "base/callback_helpers.h"
#include "base/no_destructor.h"
#include "build/build_config.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
-#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
namespace views {
@@ -100,6 +102,28 @@ DragOperation DropHelper::OnDrop(const OSExchangeData& data,
return drop_view->OnPerformDrop(drop_event);
}
+View::DropCallback DropHelper::GetDropCallback(
+ const OSExchangeData& data,
+ const gfx::Point& root_view_location,
+ int drag_operation) {
+ View* drop_view = target_view_;
+ deepest_view_ = target_view_ = nullptr;
+ if (!drop_view)
+ return base::NullCallback();
+
+ if (drag_operation == ui::DragDropTypes::DRAG_NONE) {
+ drop_view->OnDragExited();
+ return base::NullCallback();
+ }
+
+ gfx::Point view_location(root_view_location);
+ View* root_view = drop_view->GetWidget()->GetRootView();
+ View::ConvertPointToTarget(root_view, drop_view, &view_location);
+ ui::DropTargetEvent drop_event(data, gfx::PointF(view_location),
+ gfx::PointF(view_location), drag_operation);
+ return drop_view->GetDropCallback(drop_event);
+}
+
View* DropHelper::CalculateTargetView(const gfx::Point& root_view_location,
const OSExchangeData& data,
bool check_can_drop) {
diff --git a/chromium/ui/views/widget/drop_helper.h b/chromium/ui/views/widget/drop_helper.h
index f878fd47ad3..f361de1408a 100644
--- a/chromium/ui/views/widget/drop_helper.h
+++ b/chromium/ui/views/widget/drop_helper.h
@@ -5,11 +5,11 @@
#ifndef UI_VIEWS_WIDGET_DROP_HELPER_H_
#define UI_VIEWS_WIDGET_DROP_HELPER_H_
-#include <utility>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h"
+#include "ui/views/view.h"
#include "ui/views/views_export.h"
namespace gfx {
@@ -24,7 +24,6 @@ using ui::OSExchangeData;
namespace views {
class RootView;
-class View;
// DropHelper provides support for managing the view a drop is going to occur
// at during dnd as well as sending the view the appropriate dnd methods.
@@ -69,10 +68,18 @@ class VIEWS_EXPORT DropHelper {
//
// NOTE: implementations must invoke OnDragOver before invoking this,
// supplying the return value from OnDragOver as the drag_operation.
+ // TODO(crbug.com/1175682): Remove OnPerformDrop and switch to GetDropCallback
+ // instead.
ui::mojom::DragOperation OnDrop(const OSExchangeData& data,
const gfx::Point& root_view_location,
int drag_operation);
+ // Invoked when the user drops data on the root view during a drag and drop
+ // operation, but the drop is held because of DataTransferPolicController.
+ View::DropCallback GetDropCallback(const OSExchangeData& data,
+ const gfx::Point& root_view_location,
+ int drag_operation);
+
// Calculates the target view for a drop given the specified location in
// the coordinate system of the rootview. This tries to avoid continually
// querying CanDrop by returning target_view_ if the mouse is still over
diff --git a/chromium/ui/views/widget/native_widget_aura.cc b/chromium/ui/views/widget/native_widget_aura.cc
index 6418459f6e3..3b63e2b9883 100644
--- a/chromium/ui/views/widget/native_widget_aura.cc
+++ b/chromium/ui/views/widget/native_widget_aura.cc
@@ -8,7 +8,7 @@
#include <utility>
#include "base/bind.h"
-#include "base/feature_list.h"
+#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
@@ -42,7 +42,6 @@
#include "ui/views/buildflags.h"
#include "ui/views/drag_utils.h"
#include "ui/views/views_delegate.h"
-#include "ui/views/views_features.h"
#include "ui/views/widget/drop_helper.h"
#include "ui/views/widget/focus_manager_event_handler.h"
#include "ui/views/widget/native_widget_delegate.h"
@@ -71,7 +70,6 @@
#if BUILDFLAG(ENABLE_DESKTOP_AURA) && \
(defined(OS_LINUX) || defined(OS_CHROMEOS))
-#include "ui/views/linux_ui/linux_ui.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h"
#endif
@@ -212,7 +210,7 @@ void NativeWidgetAura::InitNativeWidget(Widget::InitParams params) {
if (!params.child) {
// Set up the transient child before the window is added. This way the
// LayoutManager knows the window has a transient parent.
- if (parent && parent->type() != aura::client::WINDOW_TYPE_UNKNOWN) {
+ if (parent && parent->GetType() != aura::client::WINDOW_TYPE_UNKNOWN) {
wm::AddTransientChild(parent, window_);
if (!context)
context = parent;
@@ -862,6 +860,10 @@ ui::GestureRecognizer* NativeWidgetAura::GetGestureRecognizer() {
return aura::Env::GetInstance()->gesture_recognizer();
}
+ui::GestureConsumer* NativeWidgetAura::GetGestureConsumer() {
+ return window_;
+}
+
void NativeWidgetAura::OnSizeConstraintsChanged() {
SetResizeBehaviorFromDelegate(GetWidget()->widget_delegate(), window_);
}
@@ -1099,6 +1101,13 @@ ui::mojom::DragOperation NativeWidgetAura::OnPerformDrop(
last_drop_operation_);
}
+aura::client::DragDropDelegate::DropCallback NativeWidgetAura::GetDropCallback(
+ const ui::DropTargetEvent& event) {
+ // TODO(crbug.com/1197506): Return async drop callback function.
+ NOTIMPLEMENTED();
+ return base::NullCallback();
+}
+
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetAura, protected:
@@ -1160,27 +1169,6 @@ void Widget::CloseAllSecondaryWidgets() {
#endif
}
-const ui::NativeTheme* Widget::GetNativeTheme() const {
- if (base::FeatureList::IsEnabled(
- features::kInheritNativeThemeFromParentWidget) &&
- parent_) {
- return parent_->GetNativeTheme();
- }
-
-#if BUILDFLAG(ENABLE_DESKTOP_AURA) && \
- (defined(OS_LINUX) || defined(OS_CHROMEOS))
- const LinuxUI* linux_ui = LinuxUI::instance();
- if (linux_ui) {
- ui::NativeTheme* native_theme =
- linux_ui->GetNativeTheme(native_widget_->GetNativeWindow());
- if (native_theme)
- return native_theme;
- }
-#endif
-
- return ui::NativeTheme::GetInstanceForNativeUi();
-}
-
namespace internal {
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/ui/views/widget/native_widget_aura.h b/chromium/ui/views/widget/native_widget_aura.h
index eb30560515c..db6effaafce 100644
--- a/chromium/ui/views/widget/native_widget_aura.h
+++ b/chromium/ui/views/widget/native_widget_aura.h
@@ -22,7 +22,7 @@
#include "ui/wm/public/activation_change_observer.h"
#include "ui/wm/public/activation_delegate.h"
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#error This file must not be included on macOS; Chromium Mac doesn't use Aura.
#endif
@@ -156,6 +156,7 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate,
Widget::VisibilityTransition transition) override;
bool IsTranslucentWindowOpacitySupported() const override;
ui::GestureRecognizer* GetGestureRecognizer() override;
+ ui::GestureConsumer* GetGestureConsumer() override;
void OnSizeConstraintsChanged() override;
void OnNativeViewHierarchyWillChange() override;
void OnNativeViewHierarchyChanged() override;
@@ -216,6 +217,8 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate,
ui::mojom::DragOperation OnPerformDrop(
const ui::DropTargetEvent& event,
std::unique_ptr<ui::OSExchangeData> data) override;
+ aura::client::DragDropDelegate::DropCallback GetDropCallback(
+ const ui::DropTargetEvent& event) override;
protected:
~NativeWidgetAura() override;
diff --git a/chromium/ui/views/widget/native_widget_aura_unittest.cc b/chromium/ui/views/widget/native_widget_aura_unittest.cc
index d45d6cfeb83..4f442a6697e 100644
--- a/chromium/ui/views/widget/native_widget_aura_unittest.cc
+++ b/chromium/ui/views/widget/native_widget_aura_unittest.cc
@@ -5,6 +5,7 @@
#include "ui/views/widget/native_widget_aura.h"
#include <memory>
+#include <set>
#include <utility>
#include "base/command_line.h"
@@ -17,8 +18,10 @@
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/aura/window_tree_host.h"
+#include "ui/compositor/layer.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
+#include "ui/events/test/event_generator.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/test/widget_test.h"
@@ -134,6 +137,92 @@ TEST_F(NativeWidgetAuraTest, CenterWindowSmallParentNotAtOrigin) {
widget->CloseNow();
}
+// View which handles both mouse and gesture events.
+class EventHandlingView : public View {
+ public:
+ EventHandlingView() = default;
+ EventHandlingView(const EventHandlingView&) = delete;
+ EventHandlingView& operator=(const EventHandlingView&) = delete;
+ ~EventHandlingView() override = default;
+
+ // Returns whether an event specified by `type_to_query` has been handled.
+ bool HandledEventBefore(ui::EventType type_to_query) const {
+ return handled_gestures_set_.find(type_to_query) !=
+ handled_gestures_set_.cend();
+ }
+
+ // View:
+ const char* GetClassName() const override { return "EventHandlingView"; }
+ void OnMouseEvent(ui::MouseEvent* event) override { event->SetHandled(); }
+ void OnGestureEvent(ui::GestureEvent* event) override {
+ // Record the handled gesture event.
+ const ui::EventType event_type = event->type();
+ if (handled_gestures_set_.find(event_type) ==
+ handled_gestures_set_.cend()) {
+ EXPECT_TRUE(handled_gestures_set_.insert(event->type()).second);
+ } else {
+ // Only ET_GESTURE_SCROLL_UPDATE events can be received more than once.
+ EXPECT_EQ(ui::ET_GESTURE_SCROLL_UPDATE, event->type());
+ }
+
+ event->SetHandled();
+ }
+
+ private:
+ std::set<ui::EventType> handled_gestures_set_;
+};
+
+// Verifies that when the mouse click interrupts the gesture scroll, the view
+// where the gesture scroll starts should receive the scroll end event.
+TEST_F(NativeWidgetAuraTest, MouseClickInterruptsGestureScroll) {
+ Widget::InitParams init_params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+ init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ init_params.bounds = gfx::Rect(100, 100);
+ Widget widget;
+ widget.Init(std::move(init_params));
+ widget.Show();
+
+ View* contents_view = widget.SetContentsView(std::make_unique<View>());
+ View* child_view =
+ contents_view->AddChildView(std::make_unique<EventHandlingView>());
+ child_view->SetBoundsRect(gfx::Rect(gfx::Size{50, 50}));
+
+ auto scroll_callback = [](ui::test::EventGenerator* event_generator,
+ int* step_count, ui::EventType event_type,
+ const gfx::Vector2dF& offset) {
+ if (event_type != ui::ET_GESTURE_SCROLL_UPDATE)
+ return;
+
+ *step_count -= 1;
+ if (*step_count)
+ return;
+
+ // Do not interrupt the gesture scroll until the last gesture update event
+ // is handled.
+
+ DCHECK_EQ(0, *step_count);
+ event_generator->MoveMouseTo(event_generator->current_screen_location());
+ event_generator->ClickLeftButton();
+ };
+
+ const gfx::Point center_point = child_view->GetBoundsInScreen().CenterPoint();
+ gfx::Point target_point = center_point;
+ target_point.Offset(0, 20);
+ int step_count = 10;
+ ui::test::EventGenerator generator(widget.GetNativeView()->GetRootWindow());
+ generator.GestureScrollSequenceWithCallback(
+ center_point, target_point,
+ /*duration=*/base::TimeDelta::FromMilliseconds(100), step_count,
+ base::BindRepeating(scroll_callback, &generator, &step_count));
+
+ // Verify that `child_view` receives gesture end events.
+ EXPECT_TRUE(static_cast<EventHandlingView*>(child_view)
+ ->HandledEventBefore(ui::ET_GESTURE_SCROLL_END));
+ EXPECT_TRUE(static_cast<EventHandlingView*>(child_view)
+ ->HandledEventBefore(ui::ET_GESTURE_END));
+}
+
TEST_F(NativeWidgetAuraTest, CreateMinimized) {
Widget::InitParams params(Widget::InitParams::TYPE_WINDOW);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
diff --git a/chromium/ui/views/widget/native_widget_mac.h b/chromium/ui/views/widget/native_widget_mac.h
index f793df288a9..088c98a89b7 100644
--- a/chromium/ui/views/widget/native_widget_mac.h
+++ b/chromium/ui/views/widget/native_widget_mac.h
@@ -188,6 +188,7 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate,
Widget::VisibilityTransition transition) override;
bool IsTranslucentWindowOpacitySupported() const override;
ui::GestureRecognizer* GetGestureRecognizer() override;
+ ui::GestureConsumer* GetGestureConsumer() override;
void OnSizeConstraintsChanged() override;
void OnNativeViewHierarchyWillChange() override;
void OnNativeViewHierarchyChanged() override;
diff --git a/chromium/ui/views/widget/native_widget_mac.mm b/chromium/ui/views/widget/native_widget_mac.mm
index 09d3d354ecd..51358d11989 100644
--- a/chromium/ui/views/widget/native_widget_mac.mm
+++ b/chromium/ui/views/widget/native_widget_mac.mm
@@ -12,7 +12,6 @@
#include "base/base64.h"
#include "base/bind.h"
-#include "base/feature_list.h"
#include "base/mac/scoped_nsobject.h"
#include "base/no_destructor.h"
#include "base/strings/sys_string_conversions.h"
@@ -26,6 +25,7 @@
#import "ui/base/cocoa/window_size_constants.h"
#include "ui/base/ime/init/input_method_factory.h"
#include "ui/base/ime/input_method.h"
+#include "ui/compositor/layer.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/gestures/gesture_recognizer_impl_mac.h"
@@ -36,7 +36,6 @@
#import "ui/views/cocoa/drag_drop_client_mac.h"
#import "ui/views/cocoa/native_widget_mac_ns_window_host.h"
#include "ui/views/cocoa/text_input_host.h"
-#include "ui/views/views_features.h"
#include "ui/views/widget/drop_helper.h"
#include "ui/views/widget/widget_aura_utils.h"
#include "ui/views/widget/widget_delegate.h"
@@ -804,6 +803,11 @@ ui::GestureRecognizer* NativeWidgetMac::GetGestureRecognizer() {
return recognizer.get();
}
+ui::GestureConsumer* NativeWidgetMac::GetGestureConsumer() {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
void NativeWidgetMac::OnSizeConstraintsChanged() {
Widget* widget = GetWidget();
GetNSWindowMojo()->SetSizeConstraints(
@@ -944,16 +948,6 @@ void Widget::CloseAllSecondaryWidgets() {
}
}
-const ui::NativeTheme* Widget::GetNativeTheme() const {
- if (base::FeatureList::IsEnabled(
- features::kInheritNativeThemeFromParentWidget) &&
- parent_) {
- return parent_->GetNativeTheme();
- }
-
- return ui::NativeTheme::GetInstanceForNativeUi();
-}
-
namespace internal {
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm b/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm
index 77a8c22c22a..e28d988e951 100644
--- a/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm
+++ b/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm
@@ -14,6 +14,7 @@
#import "ui/events/test/cocoa_test_event_utils.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/test/native_widget_factory.h"
#include "ui/views/test/test_widget_observer.h"
#include "ui/views/test/widget_test.h"
@@ -248,6 +249,41 @@ TEST_F(NativeWidgetMacInteractiveUITest, ParentWindowTrafficLights) {
parent_widget->CloseNow();
}
+// Test activation of a window that has restoration data that was restored to
+// the dock. See crbug.com/1205683 .
+TEST_F(NativeWidgetMacInteractiveUITest,
+ DeminiaturizeWindowWithRestorationData) {
+ Widget* widget = new Widget;
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.native_widget =
+ CreatePlatformNativeWidgetImpl(widget, kStubCapture, nullptr);
+ // Start the window off in the dock.
+ params.show_state = ui::SHOW_STATE_MINIMIZED;
+ // "{}" in base64encode, to create some dummy restoration data.
+ const std::string kDummyWindowRestorationData = "e30=";
+ params.workspace = kDummyWindowRestorationData;
+ widget->Init(std::move(params));
+
+ NSWindow* window = widget->GetNativeWindow().GetNativeNSWindow();
+ EXPECT_TRUE([window isMiniaturized]);
+
+ // As part of the window restoration process,
+ // SessionRestoreImpl::ShowBrowser() -> BrowserView::Show() ->
+ // views::Widget::Show() -> views::NativeWidgetMac::Show() which calls
+ // SetVisibilityState(), the code path we want to test. Even though the method
+ // name is Show(), it "shows" the saved_show_state_ which in this case is
+ // WindowVisibilityState::kHideWindow.
+ widget->Show();
+ EXPECT_TRUE([window isMiniaturized]);
+
+ // Activate the window from the dock (i.e.
+ // SetVisibilityState(WindowVisibilityState::kShowAndActivateWindow)).
+ widget->Activate();
+ EXPECT_FALSE([window isMiniaturized]);
+
+ widget->CloseNow();
+}
+
// Test that bubble widgets are dismissed on right mouse down.
TEST_F(NativeWidgetMacInteractiveUITest, BubbleDismiss) {
Widget* parent_widget = CreateTopLevelPlatformWidget();
diff --git a/chromium/ui/views/widget/native_widget_mac_unittest.mm b/chromium/ui/views/widget/native_widget_mac_unittest.mm
index 15e1197030b..cb78da742ed 100644
--- a/chromium/ui/views/widget/native_widget_mac_unittest.mm
+++ b/chromium/ui/views/widget/native_widget_mac_unittest.mm
@@ -28,6 +28,7 @@
#import "ui/base/cocoa/constrained_window/constrained_window_animation.h"
#import "ui/base/cocoa/window_size_constants.h"
#import "ui/base/test/scoped_fake_full_keyboard_access.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/recyclable_compositor_mac.h"
#import "ui/events/test/cocoa_test_event_utils.h"
#include "ui/events/test/event_generator.h"
@@ -45,6 +46,11 @@
#include "ui/views/widget/native_widget_private.h"
#include "ui/views/window/dialog_delegate.h"
+namespace {
+// "{}" in base64encode, to create some dummy restoration data.
+const std::string kDummyWindowRestorationData = "e30=";
+} // namespace
+
// Donates an implementation of -[NSAnimation stopAnimation] which calls the
// original implementation, then quits a nested run loop.
@interface TestStopAnimationWaiter : NSObject
@@ -109,6 +115,10 @@ class BridgedNativeWidgetTestApi {
bridge_->show_animation_.get());
}
+ bool HasWindowRestorationData() {
+ return bridge_->HasWindowRestorationData();
+ }
+
private:
remote_cocoa::NativeWidgetNSWindowBridge* bridge_;
@@ -573,16 +583,19 @@ TEST_F(NativeWidgetMacTest, SetCursor) {
Widget* widget = CreateTopLevelPlatformWidget();
widget->SetBounds(gfx::Rect(0, 0, 300, 300));
- widget->GetContentsView()->AddChildView(new CursorView(0, hand));
- widget->GetContentsView()->AddChildView(new CursorView(100, ibeam));
+ auto* view_hand = widget->non_client_view()->frame_view()->AddChildView(
+ std::make_unique<CursorView>(0, hand));
+ auto* view_ibeam = widget->non_client_view()->frame_view()->AddChildView(
+ std::make_unique<CursorView>(100, ibeam));
widget->Show();
NSWindow* widget_window = widget->GetNativeWindow().GetNativeNSWindow();
// Events used to simulate tracking rectangle updates. These are not passed to
// toolkit-views, so it only matters whether they are inside or outside the
// content area.
+ const gfx::Rect bounds = widget->GetWindowBoundsInScreen();
NSEvent* event_in_content = cocoa_test_event_utils::MouseEventAtPoint(
- NSMakePoint(100, 100), NSMouseMoved, 0);
+ NSMakePoint(bounds.x(), bounds.y()), NSMouseMoved, 0);
NSEvent* event_out_of_content = cocoa_test_event_utils::MouseEventAtPoint(
NSMakePoint(-50, -50), NSMouseMoved, 0);
@@ -599,7 +612,7 @@ TEST_F(NativeWidgetMacTest, SetCursor) {
// Move the mouse over the first view, then simulate a tracking rectangle
// update. Verify that the cursor changed from arrow to hand type.
- event_generator.MoveMouseTo(gfx::Point(50, 50));
+ event_generator.MoveMouseTo(view_hand->GetBoundsInScreen().CenterPoint());
[widget_window cursorUpdate:event_in_content];
EXPECT_EQ(hand, [NSCursor currentCursor]);
@@ -609,13 +622,16 @@ TEST_F(NativeWidgetMacTest, SetCursor) {
EXPECT_EQ(arrow, [NSCursor currentCursor]);
// Now move to the second view.
- event_generator.MoveMouseTo(gfx::Point(150, 50));
+ event_generator.MoveMouseTo(view_ibeam->GetBoundsInScreen().CenterPoint());
[widget_window cursorUpdate:event_in_content];
EXPECT_EQ(ibeam, [NSCursor currentCursor]);
// Moving to the third view (but remaining in the content area) should also
// forward to the native NSWindow implementation.
- event_generator.MoveMouseTo(gfx::Point(250, 50));
+ event_generator.MoveMouseTo(widget->non_client_view()
+ ->frame_view()
+ ->GetBoundsInScreen()
+ .bottom_right());
[widget_window cursorUpdate:event_in_content];
EXPECT_EQ(arrow, [NSCursor currentCursor]);
@@ -879,8 +895,8 @@ TEST_F(NativeWidgetMacTest, Tooltips) {
const std::u16string long_tooltip(2000, 'W');
// Create a nested layout to test corner cases.
- LabelButton* back =
- widget->GetContentsView()->AddChildView(std::make_unique<LabelButton>());
+ LabelButton* back = widget->non_client_view()->frame_view()->AddChildView(
+ std::make_unique<LabelButton>());
back->SetBounds(10, 10, 80, 80);
widget->Show();
@@ -888,7 +904,8 @@ TEST_F(NativeWidgetMacTest, Tooltips) {
widget->GetNativeWindow());
// Initially, there should be no tooltip.
- event_generator.MoveMouseTo(gfx::Point(50, 50));
+ const gfx::Rect widget_bounds = widget->GetClientAreaBoundsInScreen();
+ event_generator.MoveMouseTo(widget_bounds.CenterPoint());
EXPECT_TRUE(TooltipTextForWidget(widget).empty());
// Create a new button for the "front", and set the tooltip, but don't add it
@@ -914,11 +931,11 @@ TEST_F(NativeWidgetMacTest, Tooltips) {
EXPECT_EQ(long_tooltip, TooltipTextForWidget(widget));
// Move the mouse to a different view - tooltip should change.
- event_generator.MoveMouseTo(gfx::Point(15, 15));
+ event_generator.MoveMouseTo(back->GetBoundsInScreen().origin());
EXPECT_EQ(tooltip_back, TooltipTextForWidget(widget));
// Move the mouse off of any view, tooltip should clear.
- event_generator.MoveMouseTo(gfx::Point(5, 5));
+ event_generator.MoveMouseTo(widget_bounds.origin());
EXPECT_TRUE(TooltipTextForWidget(widget).empty());
widget->CloseNow();
@@ -938,13 +955,14 @@ TEST_F(NativeWidgetMacTest, TwoWidgetTooltips) {
widget_above->SetBounds(gfx::Rect(100, 0, 100, 200));
const std::u16string tooltip_above = u"Front";
- CustomTooltipView* view_above = new CustomTooltipView(tooltip_above, nullptr);
+ CustomTooltipView* view_above = widget_above->GetContentsView()->AddChildView(
+ std::make_unique<CustomTooltipView>(tooltip_above, nullptr));
view_above->SetBoundsRect(widget_above->GetContentsView()->bounds());
- widget_above->GetContentsView()->AddChildView(view_above);
- CustomTooltipView* view_below = new CustomTooltipView(u"Back", view_above);
+ CustomTooltipView* view_below =
+ widget_below->non_client_view()->frame_view()->AddChildView(
+ std::make_unique<CustomTooltipView>(u"Back", view_above));
view_below->SetBoundsRect(widget_below->GetContentsView()->bounds());
- widget_below->GetContentsView()->AddChildView(view_below);
widget_below->Show();
widget_above->Show();
@@ -953,7 +971,8 @@ TEST_F(NativeWidgetMacTest, TwoWidgetTooltips) {
// for second. Despite that event was handled in the first one.
ui::test::EventGenerator event_generator(GetContext(),
widget_below->GetNativeWindow());
- event_generator.MoveMouseTo(gfx::Point(120, 60));
+ event_generator.MoveMouseTo(
+ widget_above->GetWindowBoundsInScreen().CenterPoint());
EXPECT_EQ(tooltip_above, TooltipTextForWidget(widget_below));
widget_above->CloseNow();
@@ -1166,6 +1185,55 @@ TEST_F(NativeWidgetMacTest, NativeWindowChildModalShowHide) {
}
}
+// Tests that the first call into SetVisibilityState() restores the window state
+// for windows that start off miniaturized in the dock.
+TEST_F(NativeWidgetMacTest, ConfirmMinimizedWindowRestoration) {
+ Widget* widget = new Widget;
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.native_widget =
+ CreatePlatformNativeWidgetImpl(widget, kStubCapture, nullptr);
+ // Start the window off in the dock.
+ params.show_state = ui::SHOW_STATE_MINIMIZED;
+ params.workspace = kDummyWindowRestorationData;
+ widget->Init(std::move(params));
+
+ BridgedNativeWidgetTestApi test_api(
+ widget->GetNativeWindow().GetNativeNSWindow());
+
+ EXPECT_TRUE(test_api.HasWindowRestorationData());
+
+ // Show() ultimately invokes SetVisibilityState().
+ widget->Show();
+
+ EXPECT_FALSE(test_api.HasWindowRestorationData());
+
+ widget->CloseNow();
+}
+
+// Tests that the first call into SetVisibilityState() restores the window state
+// for windows that start off visible.
+TEST_F(NativeWidgetMacTest, ConfirmVisibleWindowRestoration) {
+ Widget* widget = new Widget;
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.native_widget =
+ CreatePlatformNativeWidgetImpl(widget, kStubCapture, nullptr);
+ params.show_state = ui::SHOW_STATE_NORMAL;
+ params.workspace = kDummyWindowRestorationData;
+ widget->Init(std::move(params));
+
+ BridgedNativeWidgetTestApi test_api(
+ widget->GetNativeWindow().GetNativeNSWindow());
+
+ EXPECT_TRUE(test_api.HasWindowRestorationData());
+
+ // Show() ultimately invokes SetVisibilityState().
+ widget->Show();
+
+ EXPECT_FALSE(test_api.HasWindowRestorationData());
+
+ widget->CloseNow();
+}
+
// Tests that calls to Hide() a Widget cancel any in-progress show animation,
// and that clients can control the triggering of the animation.
TEST_F(NativeWidgetMacTest, ShowAnimationControl) {
@@ -2337,4 +2405,3 @@ TEST_F(NativeWidgetMacTest, InitCallback) {
return YES;
}
@end
-
diff --git a/chromium/ui/views/widget/native_widget_private.h b/chromium/ui/views/widget/native_widget_private.h
index 2c0303f5172..5738ffb8604 100644
--- a/chromium/ui/views/widget/native_widget_private.h
+++ b/chromium/ui/views/widget/native_widget_private.h
@@ -228,6 +228,7 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
Widget::VisibilityTransition transition) = 0;
virtual bool IsTranslucentWindowOpacitySupported() const = 0;
virtual ui::GestureRecognizer* GetGestureRecognizer() = 0;
+ virtual ui::GestureConsumer* GetGestureConsumer() = 0;
virtual void OnSizeConstraintsChanged() = 0;
// Called before and after re-parenting of this or an ancestor widget.
virtual void OnNativeViewHierarchyWillChange() = 0;
diff --git a/chromium/ui/views/widget/root_view.cc b/chromium/ui/views/widget/root_view.cc
index 2f44aad7cbe..14e2830ae4d 100644
--- a/chromium/ui/views/widget/root_view.cc
+++ b/chromium/ui/views/widget/root_view.cc
@@ -16,16 +16,17 @@
#include "ui/accessibility/platform/ax_platform_node.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/ui_base_switches_util.h"
#include "ui/compositor/layer.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
+#include "ui/events/gestures/gesture_recognizer.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/drag_controller.h"
-#include "ui/views/metadata/metadata_header_macros.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/view_class_properties.h"
#include "ui/views/view_targeter.h"
#include "ui/views/widget/root_view_targeter.h"
@@ -113,7 +114,7 @@ class PreEventDispatchHandler : public ui::EventHandler {
if (owner_->GetFocusManager()) // Can be NULL in unittests.
v = owner_->GetFocusManager()->GetFocusedView();
// macOS doesn't have keyboard-triggered context menus.
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// Special case to handle keyboard-triggered context menus.
if (v && v->GetEnabled() &&
((event->key_code() == ui::VKEY_APPS) ||
@@ -267,7 +268,7 @@ void RootView::DeviceScaleFactorChanged(float old_device_scale_factor,
// Accessibility ---------------------------------------------------------------
void RootView::AnnounceText(const std::u16string& text) {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
gfx::NativeViewAccessible native = GetViewAccessibility().GetNativeObject();
auto* ax_node = ui::AXPlatformNode::FromNativeViewAccessible(native);
if (ax_node)
@@ -471,11 +472,10 @@ void RootView::OnMouseReleased(const ui::MouseEvent& event) {
// configure state such that we're done first, then call View.
View* mouse_pressed_handler = mouse_pressed_handler_;
- // The gesture handler should not be reset when handling the mouse release.
- // Otherwise, the gesture movements in progress such as the gesture scroll
- // is interrupted.
- SetMouseHandler(nullptr);
-
+ // During mouse event handling, `SetMouseAndGestureHandler()` may be called
+ // to set the gesture handler. Therefore we should reset the gesture handler
+ // when mouse is released.
+ SetMouseAndGestureHandler(nullptr);
ui::EventDispatchDetails dispatch_details =
DispatchEvent(mouse_pressed_handler, &mouse_released);
if (dispatch_details.dispatcher_destroyed)
@@ -637,11 +637,36 @@ bool RootView::OnMouseWheel(const ui::MouseWheelEvent& event) {
return event.handled();
}
+void RootView::MaybeNotifyGestureHandlerBeforeReplacement() {
+ ui::GestureRecognizer* gesture_recognizer =
+ (gesture_handler_ && widget_ ? widget_->GetGestureRecognizer() : nullptr);
+ if (!gesture_recognizer)
+ return;
+
+ ui::GestureConsumer* gesture_consumer = widget_->GetGestureConsumer();
+ if (!gesture_recognizer->DoesConsumerHaveActiveTouch(gesture_consumer))
+ return;
+
+ gesture_recognizer->SendSynthesizedEndEvents(gesture_consumer);
+}
+
void RootView::SetMouseAndGestureHandler(View* new_handler) {
SetMouseHandler(new_handler);
+
+ if (new_handler == gesture_handler_)
+ return;
+
+ MaybeNotifyGestureHandlerBeforeReplacement();
gesture_handler_ = new_handler;
}
+void RootView::SetMouseHandler(View* new_mouse_handler) {
+ // If we're clearing the mouse handler, clear explicit_mouse_handler_ as well.
+ explicit_mouse_handler_ = (new_mouse_handler != nullptr);
+ mouse_pressed_handler_ = new_mouse_handler;
+ drag_info_.Reset();
+}
+
void RootView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
DCHECK(GetWidget());
auto* widget_delegate = GetWidget()->widget_delegate();
@@ -755,13 +780,6 @@ ui::EventDispatchDetails RootView::NotifyEnterExitOfDescendant(
return ui::EventDispatchDetails();
}
-void RootView::SetMouseHandler(View* new_mouse_handler) {
- // If we're clearing the mouse handler, clear explicit_mouse_handler_ as well.
- explicit_mouse_handler_ = (new_mouse_handler != nullptr);
- mouse_pressed_handler_ = new_mouse_handler;
- drag_info_.Reset();
-}
-
bool RootView::CanDispatchToTarget(ui::EventTarget* target) {
return event_dispatch_target_ == target;
}
diff --git a/chromium/ui/views/widget/root_view.h b/chromium/ui/views/widget/root_view.h
index acdb56bfc0a..b84283b6efd 100644
--- a/chromium/ui/views/widget/root_view.h
+++ b/chromium/ui/views/widget/root_view.h
@@ -124,9 +124,14 @@ class VIEWS_EXPORT RootView : public View,
void OnMouseExited(const ui::MouseEvent& event) override;
bool OnMouseWheel(const ui::MouseWheelEvent& event) override;
void SetMouseAndGestureHandler(View* new_handler) override;
+ void SetMouseHandler(View* new_mouse_handler) override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
void UpdateParentLayer() override;
+ const views::View* gesture_handler_for_testing() const {
+ return gesture_handler_;
+ }
+
protected:
// View:
void ViewHierarchyChanged(
@@ -168,8 +173,9 @@ class VIEWS_EXPORT RootView : public View,
View* view,
View* sibling) WARN_UNUSED_RESULT;
- // Updates the mouse handler and other related data members.
- void SetMouseHandler(View* new_mouse_handler);
+ // Send synthesized gesture end events to `gesture_handler` before replacement
+ // if `gesture_handler` is in progress of gesture handling.
+ void MaybeNotifyGestureHandlerBeforeReplacement();
// ui::EventDispatcherDelegate:
bool CanDispatchToTarget(ui::EventTarget* target) override;
diff --git a/chromium/ui/views/widget/root_view_unittest.cc b/chromium/ui/views/widget/root_view_unittest.cc
index fdd4c2c1deb..0f9cb4ca140 100644
--- a/chromium/ui/views/widget/root_view_unittest.cc
+++ b/chromium/ui/views/widget/root_view_unittest.cc
@@ -5,7 +5,6 @@
#include "ui/views/widget/root_view.h"
#include <memory>
-#include <set>
#include <utility>
#include "base/macros.h"
@@ -119,7 +118,7 @@ class TestContextMenuController : public ContextMenuController {
// and VKEY_APPS) by the pre-target handler installed on RootView.
TEST_F(RootViewTest, ContextMenuFromKeyEvent) {
// This behavior is intentionally unsupported on macOS.
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
Widget widget;
Widget::InitParams init_params =
CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
@@ -183,42 +182,25 @@ class GestureHandlingView : public View {
DISALLOW_COPY_AND_ASSIGN(GestureHandlingView);
};
-// View which handles both mouse and gesture events.
-class EventHandlingView : public View {
+// View which handles all mouse events.
+class MouseHandlingView : public View {
public:
- EventHandlingView() = default;
- EventHandlingView(const EventHandlingView&) = delete;
- EventHandlingView& operator=(const EventHandlingView&) = delete;
- ~EventHandlingView() override = default;
-
- // Returns whether an event specified by `type_to_query` has been handled.
- bool HandledEventBefore(ui::EventType type_to_query) const {
- return handled_gestures_set_.find(type_to_query) !=
- handled_gestures_set_.cend();
- }
+ MouseHandlingView() = default;
+ MouseHandlingView(const MouseHandlingView&) = delete;
+ MouseHandlingView& operator=(const MouseHandlingView&) = delete;
+ ~MouseHandlingView() override = default;
// View:
void OnMouseEvent(ui::MouseEvent* event) override { event->SetHandled(); }
-
- void OnGestureEvent(ui::GestureEvent* event) override {
- // Record the handled gesture event.
- auto insertion_ret = handled_gestures_set_.insert(event->type());
- EXPECT_TRUE(insertion_ret.second);
-
- event->SetHandled();
- }
-
- private:
- std::set<ui::EventType> handled_gestures_set_;
};
-// Verifies that when the mouse click interrupts the gesture scroll, the view
-// where the gesture scroll starts should receive the scroll end event.
-TEST_F(RootViewTest, MouseClickInterruptsGestureScroll) {
-#if defined(OS_MAC)
- if (base::mac::IsOS11())
- GTEST_SKIP() << "Flaky on macOS 11: https://crbug.com/1195879";
-#endif
+// Verifies that the gesture handler stored in the root view is reset after
+// mouse is released. Note that during mouse event handling,
+// `RootView::SetMouseAndGestureHandler()` may be called to set the gesture
+// handler. Therefore we should reset the gesture handler when mouse is
+// released. We may remove this test in the future if the implementation of the
+// product code changes.
+TEST_F(RootViewTest, GestureHandlerResetAfterMouseReleased) {
Widget widget;
Widget::InitParams init_params =
CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
@@ -229,41 +211,49 @@ TEST_F(RootViewTest, MouseClickInterruptsGestureScroll) {
internal::RootView* root_view =
static_cast<internal::RootView*>(widget.GetRootView());
View* contents_view = widget.SetContentsView(std::make_unique<View>());
- View* child_view =
- contents_view->AddChildView(std::make_unique<EventHandlingView>());
- child_view->SetBoundsRect(gfx::Rect(gfx::Size{50, 50}));
+
+ // Create a child view to handle gestures.
+ View* gesture_handler =
+ contents_view->AddChildView(std::make_unique<GestureHandlingView>());
+ gesture_handler->SetBoundsRect(gfx::Rect(gfx::Size{50, 50}));
+
+ // Create a child view to handle mouse events.
+ View* mouse_handler =
+ contents_view->AddChildView(std::make_unique<MouseHandlingView>());
+ mouse_handler->SetBoundsRect(
+ gfx::Rect(gesture_handler->bounds().bottom_right(), gfx::Size{50, 50}));
// Emulate to start gesture scroll on `child_view`.
- const gfx::Point center_point = child_view->GetBoundsInScreen().CenterPoint();
+ const gfx::Point gesture_handler_center_point =
+ gesture_handler->GetBoundsInScreen().CenterPoint();
ui::GestureEvent scroll_begin(
- center_point.x(), center_point.y(), ui::EF_NONE, base::TimeTicks(),
+ gesture_handler_center_point.x(), gesture_handler_center_point.y(),
+ ui::EF_NONE, base::TimeTicks(),
ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
root_view->OnEventFromSource(&scroll_begin);
ui::GestureEvent scroll_update(
- center_point.x(), center_point.y(), ui::EF_NONE, base::TimeTicks(),
+ gesture_handler_center_point.x(), gesture_handler_center_point.y(),
+ ui::EF_NONE, base::TimeTicks(),
ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, /*delta_x=*/20,
/*delta_y=*/10));
root_view->OnEventFromSource(&scroll_update);
- // Emulate the mouse click on `child_view_`.
- ui::MouseEvent pressed_event(ui::ET_MOUSE_PRESSED, center_point, center_point,
+ // Emulate the mouse click on `mouse_handler` before gesture scroll ends.
+ const gfx::Point mouse_handler_center_point =
+ mouse_handler->GetBoundsInScreen().CenterPoint();
+ ui::MouseEvent pressed_event(ui::ET_MOUSE_PRESSED, mouse_handler_center_point,
+ mouse_handler_center_point,
ui::EventTimeForNow(), ui::EF_NONE,
/*changed_button_flags=*/0);
- ui::MouseEvent released_event(ui::ET_MOUSE_RELEASED, center_point,
- center_point, ui::EventTimeForNow(),
- ui::EF_NONE, /*changed_button_flags=*/0);
+ ui::MouseEvent released_event(
+ ui::ET_MOUSE_RELEASED, mouse_handler_center_point,
+ mouse_handler_center_point, ui::EventTimeForNow(), ui::EF_NONE,
+ /*changed_button_flags=*/0);
root_view->OnMousePressed(pressed_event);
root_view->OnMouseReleased(released_event);
- // End the gesture scroll.
- ui::GestureEvent scroll_end(
- center_point.x(), center_point.y(), ui::EF_NONE, base::TimeTicks(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
- root_view->OnEventFromSource(&scroll_end);
-
- // Verify that `child_view` receives the gesture scroll end event.
- EXPECT_TRUE(static_cast<EventHandlingView*>(child_view)
- ->HandledEventBefore(ui::ET_GESTURE_SCROLL_END));
+ // Check that the gesture handler is reset.
+ EXPECT_EQ(nullptr, root_view->gesture_handler_for_testing());
}
// Tests that context menus are shown for long press by the post-target handler
@@ -851,7 +841,7 @@ TEST_F(RootViewDesktopNativeWidgetTest, SingleLayoutDuringInit) {
widget->CloseNow();
}
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// Tests that AnnounceText sets up the correct text value on the hidden view,
// and that the resulting hidden view actually stays hidden.
@@ -881,7 +871,7 @@ TEST_F(RootViewTest, AnnounceTextTest) {
node_data.GetString16Attribute(ax::mojom::StringAttribute::kName));
}
-#endif // !defined(OS_APPLE)
+#endif // !defined(OS_MAC)
TEST_F(RootViewTest, MouseEventDispatchedToClosestEnabledView) {
Widget widget;
diff --git a/chromium/ui/views/widget/tooltip_manager.h b/chromium/ui/views/widget/tooltip_manager.h
index 3bbdb7720c8..7bda767574e 100644
--- a/chromium/ui/views/widget/tooltip_manager.h
+++ b/chromium/ui/views/widget/tooltip_manager.h
@@ -5,7 +5,6 @@
#ifndef UI_VIEWS_WIDGET_TOOLTIP_MANAGER_H_
#define UI_VIEWS_WIDGET_TOOLTIP_MANAGER_H_
-#include <string>
#include "ui/views/views_export.h"
diff --git a/chromium/ui/views/widget/widget.cc b/chromium/ui/views/widget/widget.cc
index 69612ac6747..0dcab77ec0d 100644
--- a/chromium/ui/views/widget/widget.cc
+++ b/chromium/ui/views/widget/widget.cc
@@ -10,6 +10,8 @@
#include "base/auto_reset.h"
#include "base/check_op.h"
#include "base/containers/adapters.h"
+#include "base/feature_list.h"
+#include "base/i18n/rtl.h"
#include "base/macros.h"
#include "base/notreached.h"
#include "base/strings/utf_string_conversions.h"
@@ -19,6 +21,7 @@
#include "ui/base/hit_test.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/l10n/l10n_font_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/color/color_provider_manager.h"
#include "ui/compositor/compositor.h"
@@ -33,6 +36,7 @@
#include "ui/views/focus/focus_manager_factory.h"
#include "ui/views/focus/widget_focus_manager.h"
#include "ui/views/views_delegate.h"
+#include "ui/views/views_features.h"
#include "ui/views/widget/any_widget_observer_singleton.h"
#include "ui/views/widget/native_widget_private.h"
#include "ui/views/widget/root_view.h"
@@ -44,6 +48,10 @@
#include "ui/views/window/custom_frame_view.h"
#include "ui/views/window/dialog_delegate.h"
+#if defined(OS_LINUX)
+#include "ui/views/linux_ui/linux_ui.h"
+#endif
+
namespace views {
namespace {
@@ -145,8 +153,8 @@ Widget::InitParams::InitParams(InitParams&& other) = default;
Widget::InitParams::~InitParams() = default;
bool Widget::InitParams::CanActivate() const {
- if (activatable != InitParams::ACTIVATABLE_DEFAULT)
- return activatable == InitParams::ACTIVATABLE_YES;
+ if (activatable != InitParams::Activatable::kDefault)
+ return activatable == InitParams::Activatable::kYes;
return type != InitParams::TYPE_CONTROL && type != InitParams::TYPE_POPUP &&
type != InitParams::TYPE_MENU && type != InitParams::TYPE_TOOLTIP &&
type != InitParams::TYPE_DRAG;
@@ -340,8 +348,8 @@ void Widget::Init(InitParams params) {
params.opacity = views::Widget::InitParams::WindowOpacity::kOpaque;
bool can_activate = params.CanActivate();
- params.activatable =
- can_activate ? InitParams::ACTIVATABLE_YES : InitParams::ACTIVATABLE_NO;
+ params.activatable = can_activate ? InitParams::Activatable::kYes
+ : InitParams::Activatable::kNo;
widget_delegate_->SetCanActivate(can_activate);
@@ -399,7 +407,7 @@ void Widget::Init(InitParams params) {
SetInitialBoundsForFramelessWindow(bounds);
}
- observation_.Observe(GetNativeTheme());
+ native_theme_observation_.Observe(GetNativeTheme());
native_widget_initialized_ = true;
native_widget_->OnWidgetInitDone();
@@ -500,6 +508,14 @@ const Widget* Widget::GetTopLevelWidget() const {
return is_top_level() ? this : native_widget_->GetTopLevelWidget();
}
+Widget* Widget::GetPrimaryWindowWidget() {
+ return GetTopLevelWidget();
+}
+
+const Widget* Widget::GetPrimaryWindowWidget() const {
+ return const_cast<Widget*>(this)->GetPrimaryWindowWidget();
+}
+
void Widget::SetContentsView(View* view) {
// Do not SetContentsView() again if it is already set to the same view.
if (view == GetContentsView())
@@ -701,6 +717,7 @@ void Widget::ShowInactive() {
saved_show_state_ = ui::SHOW_STATE_NORMAL;
}
native_widget_->Show(ui::SHOW_STATE_INACTIVE, gfx::Rect());
+ internal::AnyWidgetObserverSingleton::GetInstance()->OnAnyWidgetShown(this);
}
void Widget::Activate() {
@@ -809,13 +826,15 @@ const ui::ThemeProvider* Widget::GetThemeProvider() const {
const ui::ColorProvider* Widget::GetColorProvider() const {
auto color_scheme = GetNativeTheme()->GetDefaultSystemColorScheme();
+ auto theme_name = GetNativeTheme()->GetNativeThemeName();
return ui::ColorProviderManager::Get().GetColorProviderFor(
{(color_scheme == ui::NativeTheme::ColorScheme::kDark)
? ui::ColorProviderManager::ColorMode::kDark
: ui::ColorProviderManager::ColorMode::kLight,
(color_scheme == ui::NativeTheme::ColorScheme::kPlatformHighContrast)
? ui::ColorProviderManager::ContrastMode::kHigh
- : ui::ColorProviderManager::ContrastMode::kNormal});
+ : ui::ColorProviderManager::ContrastMode::kNormal,
+ std::move(theme_name)});
}
FocusManager* Widget::GetFocusManager() {
@@ -926,6 +945,9 @@ FocusTraversable* Widget::GetFocusTraversable() {
void Widget::ThemeChanged() {
root_view_->ThemeChanged();
+
+ for (WidgetObserver& observer : observers_)
+ observer.OnWidgetThemeChanged(this);
}
void Widget::DeviceScaleFactorChanged(float old_device_scale_factor,
@@ -1071,6 +1093,10 @@ ui::GestureRecognizer* Widget::GetGestureRecognizer() {
return native_widget_->GetGestureRecognizer();
}
+ui::GestureConsumer* Widget::GetGestureConsumer() {
+ return native_widget_->GetGestureConsumer();
+}
+
void Widget::OnSizeConstraintsChanged() {
native_widget_->OnSizeConstraintsChanged();
if (non_client_view_)
@@ -1105,6 +1131,75 @@ bool Widget::ShouldPaintAsActive() const {
return native_widget_active_ || paint_as_active_refcount_;
}
+void Widget::SetNativeTheme(ui::NativeTheme* native_theme) {
+ native_theme_ = native_theme;
+ native_theme_observation_.Reset();
+ if (native_theme)
+ native_theme_observation_.Observe(native_theme);
+ PropagateNativeThemeChanged();
+}
+
+int Widget::GetX() const {
+ return GetRestoredBounds().x();
+}
+
+int Widget::GetY() const {
+ return GetRestoredBounds().y();
+}
+
+int Widget::GetWidth() const {
+ return GetRestoredBounds().width();
+}
+
+int Widget::GetHeight() const {
+ return GetRestoredBounds().height();
+}
+
+bool Widget::GetVisible() const {
+ return IsVisible();
+}
+
+void Widget::SetX(int x) {
+ gfx::Rect bounds = GetRestoredBounds();
+ if (x == bounds.x())
+ return;
+ bounds.set_x(x);
+ SetBounds(bounds);
+}
+
+void Widget::SetY(int y) {
+ gfx::Rect bounds = GetRestoredBounds();
+ if (y == bounds.y())
+ return;
+ bounds.set_y(y);
+ SetBounds(bounds);
+}
+
+void Widget::SetWidth(int width) {
+ gfx::Rect bounds = GetRestoredBounds();
+ if (width == bounds.width())
+ return;
+ bounds.set_width(width);
+ SetBounds(bounds);
+}
+
+void Widget::SetHeight(int height) {
+ gfx::Rect bounds = GetRestoredBounds();
+ if (height == bounds.height())
+ return;
+ bounds.set_height(height);
+ SetBounds(bounds);
+}
+
+void Widget::SetVisible(bool visible) {
+ if (visible == IsVisible())
+ return;
+ if (visible)
+ Show();
+ else
+ Hide();
+}
+
////////////////////////////////////////////////////////////////////////////////
// Widget, NativeWidgetDelegate implementation:
@@ -1531,19 +1626,6 @@ View* Widget::GetFocusTraversableParentView() {
void Widget::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) {
TRACE_EVENT0("ui", "Widget::OnNativeThemeUpdated");
-
- DCHECK(observation_.IsObservingSource(observed_theme));
-
-#if defined(OS_APPLE) || defined(OS_WIN)
- ui::NativeTheme* current_native_theme = observed_theme;
-#else
- ui::NativeTheme* current_native_theme = GetNativeTheme();
-#endif
- if (!observation_.IsObservingSource(current_native_theme)) {
- observation_.Reset();
- observation_.Observe(current_native_theme);
- }
-
PropagateNativeThemeChanged();
}
@@ -1573,6 +1655,25 @@ void Widget::OnDragWillStart() {}
void Widget::OnDragComplete() {}
+const ui::NativeTheme* Widget::GetNativeTheme() const {
+ if (native_theme_)
+ return native_theme_;
+
+ if (base::FeatureList::IsEnabled(
+ features::kInheritNativeThemeFromParentWidget) &&
+ parent_)
+ return parent_->GetNativeTheme();
+
+#if defined(OS_LINUX)
+ if (const views::LinuxUI* linux_ui = views::LinuxUI::instance()) {
+ if (auto* native_theme = linux_ui->GetNativeTheme(GetNativeWindow()))
+ return native_theme;
+ }
+#endif
+
+ return ui::NativeTheme::GetInstanceForNativeUi();
+}
+
////////////////////////////////////////////////////////////////////////////////
// Widget, private:
@@ -1690,6 +1791,20 @@ void Widget::ClearFocusFromWidget() {
focus_manager->ViewRemoved(root_view_.get());
}
+BEGIN_METADATA_BASE(Widget)
+ADD_READONLY_PROPERTY_METADATA(const char*, ClassName)
+ADD_READONLY_PROPERTY_METADATA(gfx::Rect, ClientAreaBoundsInScreen)
+ADD_READONLY_PROPERTY_METADATA(std::string, Name)
+ADD_READONLY_PROPERTY_METADATA(gfx::Rect, RestoredBounds)
+ADD_READONLY_PROPERTY_METADATA(gfx::Rect, WindowBoundsInScreen)
+ADD_PROPERTY_METADATA(int, X)
+ADD_PROPERTY_METADATA(int, Y)
+ADD_PROPERTY_METADATA(int, Width)
+ADD_PROPERTY_METADATA(int, Height)
+ADD_PROPERTY_METADATA(bool, Visible)
+ADD_PROPERTY_METADATA(ui::ZOrderLevel, ZOrderLevel)
+END_METADATA
+
namespace internal {
////////////////////////////////////////////////////////////////////////////////
@@ -1701,3 +1816,10 @@ internal::NativeWidgetPrivate* NativeWidgetPrivate::AsNativeWidgetPrivate() {
} // namespace internal
} // namespace views
+
+DEFINE_ENUM_CONVERTERS(ui::ZOrderLevel,
+ {ui::ZOrderLevel::kNormal, u"kNormal"},
+ {ui::ZOrderLevel::kFloatingWindow, u"kFloatingWindow"},
+ {ui::ZOrderLevel::kFloatingUIElement,
+ u"kFloatingUIElement"},
+ {ui::ZOrderLevel::kSecuritySurface, u"kSecuritySurface"})
diff --git a/chromium/ui/views/widget/widget.h b/chromium/ui/views/widget/widget.h
index dde160f1a38..ef3892d66fa 100644
--- a/chromium/ui/views/widget/widget.h
+++ b/chromium/ui/views/widget/widget.h
@@ -13,10 +13,12 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/scoped_observation.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_types.h"
#include "ui/base/ui_base_types.h"
#include "ui/events/event_source.h"
#include "ui/gfx/geometry/rect.h"
@@ -98,8 +100,10 @@ enum class CloseRequestResult { kCanClose, kCannotClose };
class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
public ui::EventSource,
public FocusTraversable,
- public ui::NativeThemeObserver {
+ public ui::NativeThemeObserver,
+ public ui::metadata::MetaDataProvider {
public:
+ METADATA_HEADER_BASE(Widget);
using Widgets = std::set<Widget*>;
using ShapeRects = std::vector<gfx::Rect>;
using PaintAsActiveCallbackList = base::RepeatingClosureList;
@@ -190,12 +194,12 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
kTranslucent,
};
- enum Activatable {
+ enum class Activatable {
// Infer whether the window should be activatable from the window type.
- ACTIVATABLE_DEFAULT,
+ kDefault,
- ACTIVATABLE_YES,
- ACTIVATABLE_NO
+ kYes,
+ kNo
};
enum Ownership {
@@ -229,7 +233,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
InitParams& operator=(InitParams&& rhs) = default;
// Returns the activatablity based on |activatable|, but also handles the
- // case where |activatable| is |ACTIVATABLE_DEFAULT|.
+ // case where |activatable| is |kDefault|.
bool CanActivate() const;
// Returns the z-order level, based on the overriding |z_order| but also
@@ -262,10 +266,10 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
bool accept_events = true;
- Activatable activatable = ACTIVATABLE_DEFAULT;
+ Activatable activatable = Activatable::kDefault;
// The class of window and its overall z-order.
- base::Optional<ui::ZOrderLevel> z_order;
+ absl::optional<ui::ZOrderLevel> z_order;
bool visible_on_all_workspaces = false;
@@ -278,10 +282,10 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// A hint about the size of the shadow if the type is ShadowType::kDrop. May
// be ignored on some platforms. No value indicates no preference.
- base::Optional<int> shadow_elevation;
+ absl::optional<int> shadow_elevation;
// The window corner radius. May be ignored on some platforms.
- base::Optional<int> corner_radius;
+ absl::optional<int> corner_radius;
// Specifies that the system default caption and icon should not be
// rendered, and that the client area should be equivalent to the window
@@ -509,9 +513,21 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// Returns the top level widget in a hierarchy (see is_top_level() for
// the definition of top level widget.) Will return NULL if called
// before the widget is attached to the top level widget's hierarchy.
+ //
+ // If you want to get the absolute primary application window, accounting for
+ // e.g. bubble and menu anchoring, use GetPrimaryWindowWidget() instead.
Widget* GetTopLevelWidget();
const Widget* GetTopLevelWidget() const;
+ // Returns the widget of the primary window this widget is associated with,
+ // such as an application window, accounting for anchoring and other
+ // relationships not accounted for in GetTopLevelWidget().
+ //
+ // Equivalent to GetTopLevelWidget() by default; override in derived classes
+ // that require additional logic.
+ virtual Widget* GetPrimaryWindowWidget();
+ const Widget* GetPrimaryWindowWidget() const;
+
// Gets/Sets the WidgetDelegate.
WidgetDelegate* widget_delegate() const { return widget_delegate_; }
@@ -929,6 +945,9 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// this.
ui::GestureRecognizer* GetGestureRecognizer();
+ // Returns the associated gesture consumer.
+ ui::GestureConsumer* GetGestureConsumer();
+
// Called when the delegate's CanResize or CanMaximize changes.
void OnSizeConstraintsChanged();
@@ -1007,6 +1026,11 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// Overridden from ui::NativeThemeObserver:
void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override;
+ // Set the native theme from which this widget gets color from.
+ void SetNativeThemeForTest(ui::NativeTheme* native_theme) {
+ SetNativeTheme(native_theme);
+ }
+
protected:
// Call this to propagate native theme changes to the root view. Subclasses
// may override this to customize how native theme updates are propagated.
@@ -1028,6 +1052,24 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// Notification that the drag performed by RunShellDrag() has completed.
virtual void OnDragComplete();
+ // Set the native theme from which this widget gets color from.
+ void SetNativeTheme(ui::NativeTheme* native_theme);
+
+ // The following methods are used by the property access system described in
+ // the comments on views::View. They follow the required naming convention in
+ // order to allow them to be visible via the metadata.
+ // TODO(kylixrd): Refactor code to use these methods directly.
+ int GetX() const;
+ int GetY() const;
+ int GetWidth() const;
+ int GetHeight() const;
+ bool GetVisible() const;
+ void SetX(int x);
+ void SetY(int y);
+ void SetWidth(int width);
+ void SetHeight(int height);
+ void SetVisible(bool visible);
+
private:
// Type of ways to ignore activation changes.
enum class DisableActivationChangeHandlingType {
@@ -1204,8 +1246,12 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// Block the widget from closing.
bool block_close_ = false;
+ // The native theme this widget is using.
+ // If nullptr, defaults to use the regular native theme.
+ ui::NativeTheme* native_theme_ = nullptr;
+
base::ScopedObservation<ui::NativeTheme, ui::NativeThemeObserver>
- observation_{this};
+ native_theme_observation_{this};
base::WeakPtrFactory<Widget> weak_ptr_factory_{this};
diff --git a/chromium/ui/views/widget/widget_delegate.cc b/chromium/ui/views/widget/widget_delegate.cc
index 0c1be5b7bb3..b4fa10a853f 100644
--- a/chromium/ui/views/widget/widget_delegate.cc
+++ b/chromium/ui/views/widget/widget_delegate.cc
@@ -11,10 +11,10 @@
#include "base/strings/utf_string_conversions.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/image/image_skia.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/view.h"
#include "ui/views/views_delegate.h"
#include "ui/views/widget/widget.h"
diff --git a/chromium/ui/views/widget/widget_delegate.h b/chromium/ui/views/widget/widget_delegate.h
index eba8040b8e1..a53c8102301 100644
--- a/chromium/ui/views/widget/widget_delegate.h
+++ b/chromium/ui/views/widget/widget_delegate.h
@@ -11,8 +11,8 @@
#include "base/macros.h"
#include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/ui_base_types.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
@@ -89,7 +89,7 @@ class VIEWS_EXPORT WidgetDelegate {
// The widget's initially focused view, if any. This can only be set before
// this WidgetDelegate is used to initialize a Widget.
- base::Optional<View*> initially_focused_view;
+ absl::optional<View*> initially_focused_view;
// The widget's internal name, used to identify it in window-state
// restoration (if this widget participates in that) and in debugging
diff --git a/chromium/ui/views/widget/widget_hwnd_utils.cc b/chromium/ui/views/widget/widget_hwnd_utils.cc
index 89f5b62f95d..e07a1291859 100644
--- a/chromium/ui/views/widget/widget_hwnd_utils.cc
+++ b/chromium/ui/views/widget/widget_hwnd_utils.cc
@@ -43,8 +43,8 @@ void CalculateWindowStylesFromInitParams(
*style |= WS_MINIMIZE;
if (!params.accept_events)
*ex_style |= WS_EX_TRANSPARENT;
- DCHECK_NE(Widget::InitParams::ACTIVATABLE_DEFAULT, params.activatable);
- if (params.activatable == Widget::InitParams::ACTIVATABLE_NO)
+ DCHECK_NE(Widget::InitParams::Activatable::kDefault, params.activatable);
+ if (params.activatable == Widget::InitParams::Activatable::kNo)
*ex_style |= WS_EX_NOACTIVATE;
if (params.EffectiveZOrderLevel() != ui::ZOrderLevel::kNormal)
*ex_style |= WS_EX_TOPMOST;
diff --git a/chromium/ui/views/widget/widget_interactive_uitest.cc b/chromium/ui/views/widget/widget_interactive_uitest.cc
index 2d8a1c1d0c6..c9480f71a98 100644
--- a/chromium/ui/views/widget/widget_interactive_uitest.cc
+++ b/chromium/ui/views/widget/widget_interactive_uitest.cc
@@ -183,7 +183,7 @@ ui::WindowShowState GetWidgetShowState(const Widget* widget) {
// Give the OS an opportunity to process messages for an activation change, when
// there is actually no change expected (e.g. ShowInactive()).
void RunPendingMessagesForActiveStatusChange() {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// On Mac, a single spin is *usually* enough. It isn't when a widget is shown
// and made active in two steps, so tests should follow up with a ShowSync()
// or ActivateSync to ensure a consistent state.
@@ -210,7 +210,7 @@ void ShowSync(Widget* widget) {
}
void DeactivateSync(Widget* widget) {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Deactivation of a window isn't a concept on Mac: If an application is
// active and it has any activatable windows, then one of them is always
// active. But we can simulate deactivation (e.g. as if another application
@@ -813,7 +813,7 @@ TEST_F(WidgetTestInteractive, FullscreenMaximizedWindowBounds) {
}
#endif // defined(OS_WIN)
-#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
+#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MAC)
// Tests whether the focused window is set correctly when a modal window is
// created and destroyed. When it is destroyed it should focus the owner window.
TEST_F(DesktopWidgetTestInteractive, WindowModalWindowDestroyedActivationTest) {
@@ -855,7 +855,7 @@ TEST_F(DesktopWidgetTestInteractive, WindowModalWindowDestroyedActivationTest) {
EXPECT_EQ(gfx::kNullNativeView, focus_changes[1]);
EXPECT_EQ(modal_native_view, focus_changes[2]);
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Window modal dialogs on Mac are "sheets", which animate to close before
// activating their parent widget.
views::test::WidgetActivationWaiter waiter(&top_level_widget, true);
@@ -880,7 +880,7 @@ TEST_F(DesktopWidgetTestInteractive, CanActivateFlagIsHonored) {
CreateParams(Widget::InitParams::TYPE_WINDOW);
init_params.bounds = gfx::Rect(0, 0, 200, 200);
init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- init_params.activatable = Widget::InitParams::ACTIVATABLE_NO;
+ init_params.activatable = Widget::InitParams::Activatable::kNo;
widget.Init(std::move(init_params));
widget.Show();
@@ -889,8 +889,9 @@ TEST_F(DesktopWidgetTestInteractive, CanActivateFlagIsHonored) {
#if defined(USE_AURA)
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(USE_OZONE)
// TODO(crbug.com/916272): investigate fixing and enabling on Chrome OS.
+// TODO(crbug.com/1200034): investigate fixing and enabling on Ozone/Wayland.
#define MAYBE_TouchSelectionQuickMenuIsNotActivated \
DISABLED_TouchSelectionQuickMenuIsNotActivated
#else
@@ -939,7 +940,7 @@ TEST_F(WidgetTestInteractive, DisableViewDoesNotActivateWidget) {
Widget widget1;
Widget::InitParams params1 = CreateParams(Widget::InitParams::TYPE_POPUP);
params1.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params1.activatable = Widget::InitParams::ACTIVATABLE_YES;
+ params1.activatable = Widget::InitParams::Activatable::kYes;
widget1.Init(std::move(params1));
View* view1 = new View();
@@ -958,7 +959,7 @@ TEST_F(WidgetTestInteractive, DisableViewDoesNotActivateWidget) {
Widget widget2;
Widget::InitParams params2 = CreateParams(Widget::InitParams::TYPE_POPUP);
params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params2.activatable = Widget::InitParams::ACTIVATABLE_YES;
+ params2.activatable = Widget::InitParams::Activatable::kYes;
widget2.Init(std::move(params2));
View* view2 = new View();
@@ -1039,7 +1040,7 @@ TEST_F(WidgetTestInteractive, ShowAfterShowInactive) {
EXPECT_EQ(GetWidgetShowState(widget.get()), ui::SHOW_STATE_NORMAL);
}
-#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
+#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MAC)
TEST_F(WidgetTestInteractive, InactiveWidgetDoesNotGrabActivation) {
WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget());
ShowSync(widget.get());
@@ -1055,13 +1056,13 @@ TEST_F(WidgetTestInteractive, InactiveWidgetDoesNotGrabActivation) {
EXPECT_EQ(GetWidgetShowState(widget2.get()), ui::SHOW_STATE_INACTIVE);
EXPECT_EQ(GetWidgetShowState(widget.get()), ui::SHOW_STATE_NORMAL);
}
-#endif // BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
+#endif // BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MAC)
// ExitFullscreenRestoreState doesn't use DesktopAura widgets. On Mac, there are
// currently only Desktop widgets and fullscreen changes have to coordinate with
// the OS. See BridgedNativeWidgetUITest for native Mac fullscreen tests.
// Maximize on mac is also (intentionally) a no-op.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#define MAYBE_ExitFullscreenRestoreState DISABLED_ExitFullscreenRestoreState
#else
#define MAYBE_ExitFullscreenRestoreState ExitFullscreenRestoreState
@@ -1207,7 +1208,7 @@ TEST_F(DesktopWidgetTestInteractive, MinimizeAndActivateFocus) {
#endif // defined(OS_WIN)
-#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
+#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MAC)
// Tests that minimizing a widget causes the gesture_handler
// to be cleared when the widget is minimized.
TEST_F(DesktopWidgetTestInteractive, EventHandlersClearedOnWidgetMinimize) {
@@ -1382,7 +1383,7 @@ TEST_F(WidgetCaptureTest, Capture) {
TestCapture(false);
}
-#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
+#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MAC)
// See description in TestCapture(). Creates DesktopNativeWidget.
TEST_F(WidgetCaptureTest, CaptureDesktopNativeWidget) {
TestCapture(true);
@@ -1459,7 +1460,8 @@ TEST_F(WidgetCaptureTest, FailedCaptureRequestIsNoop) {
widget.Show();
ui::test::EventGenerator generator(GetRootWindow(&widget),
widget.GetNativeWindow());
- generator.set_current_screen_location(gfx::Point(300, 10));
+ generator.set_current_screen_location(
+ widget.GetClientAreaBoundsInScreen().CenterPoint());
generator.PressLeftButton();
EXPECT_FALSE(mouse_view1->pressed());
@@ -1606,6 +1608,8 @@ TEST_F(WidgetCaptureTest, GrabUngrab) {
// Click on child1.
ui::test::EventGenerator generator(GetRootWindow(top_level.get()),
child1->GetNativeWindow());
+ generator.set_current_screen_location(
+ child1->GetClientAreaBoundsInScreen().CenterPoint());
generator.PressLeftButton();
EXPECT_FALSE(top_level->HasCapture());
@@ -1620,7 +1624,7 @@ TEST_F(WidgetCaptureTest, GrabUngrab) {
// Click on child2.
generator.SetTargetWindow(child2->GetNativeWindow());
generator.set_current_screen_location(
- generator.delegate()->CenterOfWindow(child2->GetNativeWindow()));
+ child2->GetClientAreaBoundsInScreen().CenterPoint());
generator.PressLeftButton();
EXPECT_FALSE(top_level->HasCapture());
@@ -1634,7 +1638,8 @@ TEST_F(WidgetCaptureTest, GrabUngrab) {
// Click on top_level.
generator.SetTargetWindow(top_level->GetNativeWindow());
- generator.set_current_screen_location(gfx::Point());
+ generator.set_current_screen_location(
+ top_level->GetClientAreaBoundsInScreen().origin());
generator.PressLeftButton();
EXPECT_TRUE(top_level->HasCapture());
@@ -1650,7 +1655,7 @@ TEST_F(WidgetCaptureTest, GrabUngrab) {
// Disabled on Mac. Desktop Mac doesn't have system modal windows since Carbon
// was deprecated. It does have application modal windows, but only Ash requests
// those.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#define MAYBE_SystemModalWindowReleasesCapture \
DISABLED_SystemModalWindowReleasesCapture
#elif BUILDFLAG(IS_CHROMEOS_ASH)
@@ -1705,7 +1710,7 @@ TEST_F(WidgetCaptureTest, MAYBE_SystemModalWindowReleasesCapture) {
// Regression test for http://crbug.com/382421 (Linux-Aura issue).
// TODO(pkotwicz): Make test pass on CrOS and Windows.
// TODO(tapted): Investigate for toolkit-views on Mac http;//crbug.com/441064.
-#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_APPLE)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_MAC)
#define MAYBE_MouseExitOnCaptureGrab DISABLED_MouseExitOnCaptureGrab
#else
#define MAYBE_MouseExitOnCaptureGrab MouseExitOnCaptureGrab
@@ -1800,7 +1805,7 @@ TEST_F(WidgetCaptureTest, SetCaptureToNonToplevel) {
child->AddObserver(&observer);
child->Show();
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// On Mac, activation is asynchronous. A single trip to the runloop should be
// sufficient. On Aura platforms, note that since the child widget isn't top-
// level, the aura window manager gets asked whether the widget is active, not
@@ -1911,7 +1916,7 @@ class WidgetInputMethodInteractiveTest : public DesktopWidgetTestInteractive {
DISALLOW_COPY_AND_ASSIGN(WidgetInputMethodInteractiveTest);
};
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#define MAYBE_Activation DISABLED_Activation
#else
#define MAYBE_Activation Activation
@@ -1956,7 +1961,7 @@ TEST_F(WidgetInputMethodInteractiveTest, OneWindow) {
// Widget::Deactivate() doesn't work for CrOS, because it uses NWA instead of
// DNWA (which just activates the last active window) and involves the
// AuraTestHelper which sets the input method as DummyInputMethod.
-#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
+#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MAC)
DeactivateSync(widget.get());
EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE,
widget->GetInputMethod()->GetTextInputType());
@@ -2004,7 +2009,7 @@ TEST_F(WidgetInputMethodInteractiveTest, TwoWindows) {
// Widget::Deactivate() doesn't work for CrOS, because it uses NWA instead of
// DNWA (which just activates the last active window) and involves the
// AuraTestHelper which sets the input method as DummyInputMethod.
-#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
+#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MAC)
DeactivateSync(parent.get());
EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE,
parent->GetInputMethod()->GetTextInputType());
diff --git a/chromium/ui/views/widget/widget_observer.h b/chromium/ui/views/widget/widget_observer.h
index 51adacfee40..4050dd33db5 100644
--- a/chromium/ui/views/widget/widget_observer.h
+++ b/chromium/ui/views/widget/widget_observer.h
@@ -49,6 +49,8 @@ class VIEWS_EXPORT WidgetObserver : public base::CheckedObserver {
virtual void OnWidgetBoundsChanged(Widget* widget,
const gfx::Rect& new_bounds) {}
+ virtual void OnWidgetThemeChanged(Widget* widget) {}
+
protected:
~WidgetObserver() override = default;
};
diff --git a/chromium/ui/views/widget/widget_unittest.cc b/chromium/ui/views/widget/widget_unittest.cc
index 3ae33afe803..8b107c8a08d 100644
--- a/chromium/ui/views/widget/widget_unittest.cc
+++ b/chromium/ui/views/widget/widget_unittest.cc
@@ -14,6 +14,7 @@
#include "build/chromeos_buildflags.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/hit_test.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
@@ -54,7 +55,7 @@
#include "ui/views/win/hwnd_util.h"
#endif
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#include "base/mac/mac_util.h"
#endif
@@ -84,6 +85,14 @@ gfx::Point ConvertPointFromWidgetToView(View* view, const gfx::Point& p) {
return tmp;
}
+std::unique_ptr<ui::test::EventGenerator> CreateEventGenerator(
+ gfx::NativeWindow root_window,
+ gfx::NativeWindow target_window) {
+ auto generator =
+ std::make_unique<ui::test::EventGenerator>(root_window, target_window);
+ return generator;
+}
+
class TestBubbleDialogDelegateView : public BubbleDialogDelegateView {
public:
explicit TestBubbleDialogDelegateView(View* anchor)
@@ -888,7 +897,7 @@ class WidgetObserverTest : public WidgetTest, public WidgetObserver {
};
// This test appears to be flaky on Mac.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#define MAYBE_ActivationChange DISABLED_ActivationChange
#else
#define MAYBE_ActivationChange ActivationChange
@@ -1209,7 +1218,12 @@ TEST_F(WidgetTest, GetWindowPlacement) {
#else
TEST_F(DesktopWidgetTest, GetWindowPlacement) {
#endif
- SKIP_TEST_IF_NOT_OZONE_X11();
+#if defined(USE_OZONE)
+ if (features::IsUsingOzonePlatform() &&
+ ui::OzonePlatform::GetPlatformNameForTest() != "x11") {
+ GTEST_SKIP() << "This test is X11-only";
+ }
+#endif
WidgetAutoclosePtr widget;
widget.reset(CreateTopLevelNativeWidget());
@@ -1394,7 +1408,7 @@ TEST_F(DesktopWidgetTest, MAYBE_GetRestoredBounds) {
toplevel->Maximize();
RunPendingMessages();
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Current expectation on Mac is to do nothing on Maximize.
EXPECT_EQ(toplevel->GetWindowBoundsInScreen(), toplevel->GetRestoredBounds());
#else
@@ -1779,12 +1793,12 @@ TEST_F(WidgetTest, SynthesizeMouseMoveEvent) {
View* root_view = widget->GetRootView();
widget->SetBounds(gfx::Rect(0, 0, 100, 100));
- EventCountView* v1 = new EventCountView();
+ EventCountView* v1 =
+ root_view->AddChildView(std::make_unique<EventCountView>());
v1->SetBounds(5, 5, 10, 10);
- root_view->AddChildView(v1);
- EventCountView* v2 = new EventCountView();
+ EventCountView* v2 =
+ root_view->AddChildView(std::make_unique<EventCountView>());
v2->SetBounds(5, 15, 10, 10);
- root_view->AddChildView(v2);
widget->Show();
@@ -1793,9 +1807,10 @@ TEST_F(WidgetTest, SynthesizeMouseMoveEvent) {
EXPECT_EQ(0, v1->GetEventCount(ui::ET_MOUSE_MOVED));
EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_MOVED));
- gfx::Point cursor_location(5, 5);
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
- generator.MoveMouseTo(cursor_location);
+ gfx::Point cursor_location(v1->GetBoundsInScreen().CenterPoint());
+ auto generator =
+ CreateEventGenerator(GetContext(), widget->GetNativeWindow());
+ generator->MoveMouseTo(cursor_location);
EXPECT_EQ(1, v1->GetEventCount(ui::ET_MOUSE_MOVED));
EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_MOVED));
@@ -1804,7 +1819,7 @@ TEST_F(WidgetTest, SynthesizeMouseMoveEvent) {
widget->SynthesizeMouseMoveEvent();
EXPECT_EQ(2, v1->GetEventCount(ui::ET_MOUSE_MOVED));
- delete v1;
+ root_view->RemoveChildViewT(v1);
EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_MOVED));
v2->SetBounds(5, 5, 10, 10);
EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_MOVED));
@@ -1833,7 +1848,7 @@ class MousePressEventConsumer : public ui::EventHandler {
} // namespace
// No touch on desktop Mac. Tracked in http://crbug.com/445520.
-#if !defined(OS_APPLE) || defined(USE_AURA)
+#if !defined(OS_MAC) || defined(USE_AURA)
// Test that mouse presses and mouse releases are dispatched normally when a
// touch is down.
@@ -1842,16 +1857,17 @@ TEST_F(WidgetTest, MouseEventDispatchWhileTouchIsDown) {
widget->Show();
widget->SetSize(gfx::Size(300, 300));
- EventCountView* event_count_view = new EventCountView();
+ EventCountView* event_count_view =
+ widget->GetRootView()->AddChildView(std::make_unique<EventCountView>());
event_count_view->SetBounds(0, 0, 300, 300);
- widget->GetRootView()->AddChildView(event_count_view);
MousePressEventConsumer consumer;
event_count_view->AddPostTargetHandler(&consumer);
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
- generator.PressTouch();
- generator.ClickLeftButton();
+ auto generator =
+ CreateEventGenerator(GetContext(), widget->GetNativeWindow());
+ generator->PressTouch();
+ generator->ClickLeftButton();
EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED));
EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_RELEASED));
@@ -1860,7 +1876,7 @@ TEST_F(WidgetTest, MouseEventDispatchWhileTouchIsDown) {
widget->CloseNow();
}
-#endif // !defined(OS_APPLE) || defined(USE_AURA)
+#endif // !defined(OS_MAC) || defined(USE_AURA)
// Tests that when there is no active capture, that a mouse press causes capture
// to be set.
@@ -1869,9 +1885,9 @@ TEST_F(WidgetTest, MousePressCausesCapture) {
widget->Show();
widget->SetSize(gfx::Size(300, 300));
- EventCountView* event_count_view = new EventCountView();
+ EventCountView* event_count_view =
+ widget->GetRootView()->AddChildView(std::make_unique<EventCountView>());
event_count_view->SetBounds(0, 0, 300, 300);
- widget->GetRootView()->AddChildView(event_count_view);
// No capture has been set.
EXPECT_EQ(
@@ -1880,8 +1896,10 @@ TEST_F(WidgetTest, MousePressCausesCapture) {
MousePressEventConsumer consumer;
event_count_view->AddPostTargetHandler(&consumer);
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
- generator.PressLeftButton();
+ auto generator =
+ CreateEventGenerator(GetContext(), widget->GetNativeWindow());
+ generator->MoveMouseTo(widget->GetClientAreaBoundsInScreen().CenterPoint());
+ generator->PressLeftButton();
EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED));
EXPECT_EQ(
@@ -1930,9 +1948,9 @@ TEST_F(WidgetTest, CaptureDuringMousePressNotOverridden) {
widget->Show();
widget->SetSize(gfx::Size(300, 300));
- EventCountView* event_count_view = new EventCountView();
+ EventCountView* event_count_view =
+ widget->GetRootView()->AddChildView(std::make_unique<EventCountView>());
event_count_view->SetBounds(0, 0, 300, 300);
- widget->GetRootView()->AddChildView(event_count_view);
EXPECT_EQ(
gfx::kNullNativeView,
@@ -1942,11 +1960,12 @@ TEST_F(WidgetTest, CaptureDuringMousePressNotOverridden) {
// Gives explicit capture to |widget2|
CaptureEventConsumer consumer(widget2);
event_count_view->AddPostTargetHandler(&consumer);
- ui::test::EventGenerator generator(GetRootWindow(widget),
- widget->GetNativeWindow());
+ auto generator =
+ CreateEventGenerator(GetRootWindow(widget), widget->GetNativeWindow());
+ generator->MoveMouseTo(widget->GetClientAreaBoundsInScreen().CenterPoint());
// This event should implicitly give capture to |widget|, except that
// |consumer| will explicitly set capture on |widget2|.
- generator.PressLeftButton();
+ generator->PressLeftButton();
EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED));
EXPECT_NE(
@@ -2012,8 +2031,8 @@ TEST_F(WidgetTest, DestroyedWithCaptureViaEventMonitor) {
// both need to try). Note the regression test would only fail when the
// SetCapture() handler did _not_ swallow the event, but it still needs to try
// to close the Widget otherwise it will be left open, which fails elsewhere.
- ClosingView* closing_view = new ClosingView(widget);
- widget->GetContentsView()->AddChildView(closing_view);
+ ClosingView* closing_view = widget->GetContentsView()->AddChildView(
+ std::make_unique<ClosingView>(widget));
widget->SetCapture(closing_view);
ClosingEventObserver closing_event_observer(widget);
@@ -2021,11 +2040,12 @@ TEST_F(WidgetTest, DestroyedWithCaptureViaEventMonitor) {
&closing_event_observer, widget->GetNativeWindow(),
{ui::ET_MOUSE_PRESSED});
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
- generator.set_target(ui::test::EventGenerator::Target::APPLICATION);
+ auto generator =
+ CreateEventGenerator(GetContext(), widget->GetNativeWindow());
+ generator->set_target(ui::test::EventGenerator::Target::APPLICATION);
EXPECT_FALSE(observer.widget_closed());
- generator.PressLeftButton();
+ generator->PressLeftButton();
EXPECT_TRUE(observer.widget_closed());
}
@@ -2222,19 +2242,20 @@ TEST_F(WidgetTest, WidgetDeleted_InOnMousePressed) {
widget->SetSize(gfx::Size(100, 100));
widget->Show();
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
+ auto generator =
+ CreateEventGenerator(GetContext(), widget->GetNativeWindow());
WidgetDeletionObserver deletion_observer(widget);
- generator.PressLeftButton();
+ generator->PressLeftButton();
if (deletion_observer.IsWidgetAlive())
- generator.ReleaseLeftButton();
+ generator->ReleaseLeftButton();
EXPECT_FALSE(deletion_observer.IsWidgetAlive());
// Yay we did not crash!
}
// No touch on desktop Mac. Tracked in http://crbug.com/445520.
-#if !defined(OS_APPLE) || defined(USE_AURA)
+#if !defined(OS_MAC) || defined(USE_AURA)
TEST_F(WidgetTest, WidgetDeleted_InDispatchGestureEvent) {
Widget* widget = new Widget;
@@ -2248,16 +2269,17 @@ TEST_F(WidgetTest, WidgetDeleted_InDispatchGestureEvent) {
widget->SetSize(gfx::Size(100, 100));
widget->Show();
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
+ auto generator =
+ CreateEventGenerator(GetContext(), widget->GetNativeWindow());
WidgetDeletionObserver deletion_observer(widget);
- generator.GestureTapAt(widget->GetWindowBoundsInScreen().CenterPoint());
+ generator->GestureTapAt(widget->GetWindowBoundsInScreen().CenterPoint());
EXPECT_FALSE(deletion_observer.IsWidgetAlive());
// Yay we did not crash!
}
-#endif // !defined(OS_APPLE) || defined(USE_AURA)
+#endif // !defined(OS_MAC) || defined(USE_AURA)
// See description of RunGetNativeThemeFromDestructor() for details.
class GetNativeThemeFromDestructorView : public WidgetDelegateView {
@@ -2414,7 +2436,7 @@ TEST_F(WidgetTest, CloseWidgetWhileAnimating) {
// Test Widget::CloseAllSecondaryWidgets works as expected across platforms.
// ChromeOS doesn't implement or need CloseAllSecondaryWidgets() since
// everything is under a single root window.
-#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
+#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MAC)
TEST_F(DesktopWidgetTest, CloseAllSecondaryWidgets) {
Widget* widget1 = CreateTopLevelNativeWidget();
Widget* widget2 = CreateTopLevelNativeWidget();
@@ -2476,14 +2498,15 @@ TEST_F(WidgetTest, NoCrashOnWidgetDeleteWithPendingEvents) {
std::unique_ptr<Widget> widget = CreateTestWidget();
widget->Show();
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
- generator.MoveMouseTo(10, 10);
+ auto generator =
+ CreateEventGenerator(GetContext(), widget->GetNativeWindow());
+ generator->MoveMouseTo(10, 10);
// No touch on desktop Mac. Tracked in http://crbug.com/445520.
-#if defined(OS_APPLE)
- generator.ClickLeftButton();
+#if defined(OS_MAC)
+ generator->ClickLeftButton();
#else
- generator.PressTouch();
+ generator->PressTouch();
#endif
widget.reset();
}
@@ -3413,30 +3436,31 @@ TEST_F(ChildDesktopWidgetTest, IsActiveFromDestroy) {
// Tests that events propagate through from the dispatcher with the correct
// event type, and that the different platforms behave the same.
TEST_F(WidgetTest, MouseEventTypesViaGenerator) {
- EventCountView* view = new EventCountView;
+ WidgetAutoclosePtr widget(CreateTopLevelFramelessPlatformWidget());
+ EventCountView* view =
+ widget->GetRootView()->AddChildView(std::make_unique<EventCountView>());
view->set_handle_mode(EventCountView::CONSUME_EVENTS);
view->SetBounds(10, 10, 50, 40);
- WidgetAutoclosePtr widget(CreateTopLevelFramelessPlatformWidget());
- widget->GetRootView()->AddChildView(view);
-
widget->SetBounds(gfx::Rect(0, 0, 100, 80));
widget->Show();
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
- generator.set_current_screen_location(gfx::Point(20, 20));
+ auto generator =
+ CreateEventGenerator(GetContext(), widget->GetNativeWindow());
+ const gfx::Point view_center_point = view->GetBoundsInScreen().CenterPoint();
+ generator->set_current_screen_location(view_center_point);
- generator.ClickLeftButton();
+ generator->ClickLeftButton();
EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_PRESSED));
EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_RELEASED));
EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, view->last_flags());
- generator.PressRightButton();
+ generator->PressRightButton();
EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_PRESSED));
EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_RELEASED));
EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, view->last_flags());
- generator.ReleaseRightButton();
+ generator->ReleaseRightButton();
EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_PRESSED));
EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_RELEASED));
EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, view->last_flags());
@@ -3445,32 +3469,34 @@ TEST_F(WidgetTest, MouseEventTypesViaGenerator) {
EXPECT_EQ(0, view->GetEventCount(ui::ET_MOUSE_MOVED));
EXPECT_EQ(0, view->GetEventCount(ui::ET_MOUSE_ENTERED));
- // Move the mouse within the view (20, 20) -> (30, 30).
- generator.MoveMouseTo(gfx::Point(30, 30));
+ // Move the mouse a displacement of (10, 10).
+ generator->MoveMouseTo(view_center_point + gfx::Vector2d(10, 10));
EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_MOVED));
EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_ENTERED));
EXPECT_EQ(ui::EF_NONE, view->last_flags());
// Move it again - entered count shouldn't change.
- generator.MoveMouseTo(gfx::Point(31, 31));
+ generator->MoveMouseTo(view_center_point + gfx::Vector2d(11, 11));
EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_MOVED));
EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_ENTERED));
EXPECT_EQ(0, view->GetEventCount(ui::ET_MOUSE_EXITED));
// Move it off the view.
- generator.MoveMouseTo(gfx::Point(5, 5));
+ const gfx::Point out_of_bounds_point =
+ view->GetBoundsInScreen().bottom_right() + gfx::Vector2d(10, 10);
+ generator->MoveMouseTo(out_of_bounds_point);
EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_MOVED));
EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_ENTERED));
EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_EXITED));
// Move it back on.
- generator.MoveMouseTo(gfx::Point(20, 20));
+ generator->MoveMouseTo(view_center_point);
EXPECT_EQ(3, view->GetEventCount(ui::ET_MOUSE_MOVED));
EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_ENTERED));
EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_EXITED));
// Drargging. Cover HasCapture() and NativeWidgetPrivate::IsMouseButtonDown().
- generator.DragMouseTo(gfx::Point(40, 40));
+ generator->DragMouseTo(out_of_bounds_point);
EXPECT_EQ(3, view->GetEventCount(ui::ET_MOUSE_PRESSED));
EXPECT_EQ(3, view->GetEventCount(ui::ET_MOUSE_RELEASED));
EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_DRAGGED));
@@ -3807,93 +3833,18 @@ TEST_F(WidgetTest, WidgetRemovalsObserverCalledWhenMovingBetweenWidgets) {
TEST_F(WidgetTest, MouseWheelEvent) {
WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget());
widget->SetBounds(gfx::Rect(0, 0, 600, 600));
- EventCountView* event_count_view = new EventCountView();
- widget->GetContentsView()->AddChildView(event_count_view);
+ EventCountView* event_count_view =
+ widget->client_view()->AddChildView(std::make_unique<EventCountView>());
event_count_view->SetBounds(0, 0, 600, 600);
widget->Show();
- ui::test::EventGenerator event_generator(GetContext(),
- widget->GetNativeWindow());
+ auto event_generator =
+ CreateEventGenerator(GetContext(), widget->GetNativeWindow());
- event_generator.MoveMouseWheel(1, 1);
+ event_generator->MoveMouseWheel(1, 1);
EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSEWHEEL));
}
-class LayoutCountingView : public View {
- public:
- LayoutCountingView() = default;
- ~LayoutCountingView() override = default;
-
- void set_layout_closure(base::OnceClosure layout_closure) {
- layout_closure_ = std::move(layout_closure);
- }
-
- size_t GetAndClearLayoutCount() {
- const size_t count = layout_count_;
- layout_count_ = 0u;
- return count;
- }
-
- // View:
- void Layout() override {
- ++layout_count_;
- View::Layout();
- if (layout_closure_)
- std::move(layout_closure_).Run();
- }
-
- private:
- size_t layout_count_ = 0u;
-
- // If valid, this is run when Layout() is called.
- base::OnceClosure layout_closure_;
-
- DISALLOW_COPY_AND_ASSIGN(LayoutCountingView);
-};
-
-using WidgetInvalidateLayoutTest = ViewsTestBaseWithNativeWidgetType;
-
-TEST_P(WidgetInvalidateLayoutTest, InvalidateLayout) {
- std::unique_ptr<Widget> widget =
- CreateTestWidget(Widget::InitParams::TYPE_WINDOW);
- LayoutCountingView* view =
- widget->widget_delegate()->GetContentsView()->AddChildView(
- std::make_unique<LayoutCountingView>());
- view->parent()->SetLayoutManager(std::make_unique<FillLayout>());
- // Force an initial Layout().
- // TODO(sky): this shouldn't be necessary, adding a child view should trigger
- // ScheduleLayout().
- view->Layout();
- widget->Show();
-
- ui::Compositor* compositor = widget->GetCompositor();
- ASSERT_TRUE(compositor);
- compositor->ScheduleDraw();
- ui::DrawWaiterForTest::WaitForCompositingEnded(compositor);
-
- base::RunLoop run_loop;
- view->GetAndClearLayoutCount();
- // Don't use WaitForCompositingEnded() here as it's entirely possible nothing
- // will be drawn (which means WaitForCompositingEnded() isn't run). Instead
- // wait for Layout() to be called.
- view->set_layout_closure(run_loop.QuitClosure());
- EXPECT_FALSE(ViewTestApi(view).needs_layout());
- EXPECT_FALSE(ViewTestApi(widget->GetRootView()).needs_layout());
- view->InvalidateLayout();
- EXPECT_TRUE(ViewTestApi(view).needs_layout());
- EXPECT_TRUE(ViewTestApi(widget->GetRootView()).needs_layout());
- run_loop.Run();
- EXPECT_EQ(1u, view->GetAndClearLayoutCount());
- EXPECT_FALSE(ViewTestApi(view).needs_layout());
- EXPECT_FALSE(ViewTestApi(widget->GetRootView()).needs_layout());
-}
-
-INSTANTIATE_TEST_SUITE_P(
- WidgetInvalidateLayoutTest,
- WidgetInvalidateLayoutTest,
- ::testing::Values(ViewsTestBase::NativeWidgetType::kDefault,
- ViewsTestBase::NativeWidgetType::kDesktop));
-
class WidgetShadowTest : public WidgetTest {
public:
WidgetShadowTest() = default;
@@ -3925,12 +3876,12 @@ class WidgetShadowTest : public WidgetTest {
}
protected:
- base::Optional<Widget::InitParams::Type> override_type_;
+ absl::optional<Widget::InitParams::Type> override_type_;
std::string name_;
bool force_child_ = false;
private:
-#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
+#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MAC)
void InitControllers() {}
#else
class TestFocusRules : public wm::BaseFocusRules {
@@ -3954,13 +3905,13 @@ class WidgetShadowTest : public WidgetTest {
std::unique_ptr<wm::FocusController> focus_controller_;
std::unique_ptr<wm::ShadowController> shadow_controller_;
-#endif // !BUILDFLAG(ENABLE_DESKTOP_AURA) && !defined(OS_APPLE)
+#endif // !BUILDFLAG(ENABLE_DESKTOP_AURA) && !defined(OS_MAC)
DISALLOW_COPY_AND_ASSIGN(WidgetShadowTest);
};
// Disabled on Mac: All drop shadows are managed out of process for now.
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#define MAYBE_ShadowsInRootWindow DISABLED_ShadowsInRootWindow
#else
#define MAYBE_ShadowsInRootWindow ShadowsInRootWindow
@@ -4091,7 +4042,7 @@ TEST_F(DesktopWidgetTest, WindowModalOwnerDestroyedEnabledTest) {
#endif // defined(OS_WIN)
-#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
+#if BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MAC)
namespace {
@@ -4110,6 +4061,18 @@ bool CanHaveCompositingManager() {
#endif
}
+bool ExpectWidgetTransparency(Widget::InitParams::WindowOpacity opacity) {
+ switch (opacity) {
+ case Widget::InitParams::WindowOpacity::kOpaque:
+ return false;
+ case Widget::InitParams::WindowOpacity::kTranslucent:
+ return true;
+ case Widget::InitParams::WindowOpacity::kInferred:
+ ADD_FAILURE() << "WidgetOpacity must be explicitly set";
+ return false;
+ }
+}
+
class CompositingWidgetTest : public DesktopWidgetTest {
public:
CompositingWidgetTest()
@@ -4133,7 +4096,7 @@ class CompositingWidgetTest : public DesktopWidgetTest {
const Widget::InitParams::WindowOpacity opacity) {
opacity_ = opacity;
for (const auto& widget_type : widget_types_) {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Tooltips are native on Mac. See NativeWidgetNSWindowBridge::Init.
if (widget_type == Widget::InitParams::TYPE_TOOLTIP)
continue;
@@ -4150,7 +4113,7 @@ class CompositingWidgetTest : public DesktopWidgetTest {
widget_type == Widget::InitParams::TYPE_CONTROL)
continue;
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Mac always always has a compositing window manager, but doesn't have
// transparent titlebars which is what ShouldWindowContentsBeTransparent()
// is currently used for. Asking for transparency should get it. Note that
@@ -4166,13 +4129,10 @@ class CompositingWidgetTest : public DesktopWidgetTest {
should_be_transparent);
if (CanHaveCompositingManager()) {
- if (HasCompositingManager() &&
- (widget_type == Widget::InitParams::TYPE_DRAG ||
- widget_type == Widget::InitParams::TYPE_WINDOW)) {
+ if (HasCompositingManager() && ExpectWidgetTransparency(opacity))
EXPECT_TRUE(widget->IsTranslucentWindowOpacitySupported());
- } else {
+ else
EXPECT_FALSE(widget->IsTranslucentWindowOpacitySupported());
- }
}
}
}
@@ -4187,11 +4147,8 @@ class CompositingWidgetTest : public DesktopWidgetTest {
} // namespace
-// Test opacity when compositing is enabled.
-TEST_F(CompositingWidgetTest, Transparency_DesktopWidgetInferOpacity) {
- CheckAllWidgetsForOpacity(Widget::InitParams::WindowOpacity::kInferred);
-}
-
+// Only test manually set opacity via kOpaque or kTranslucent. kInferred is
+// unpredictable and depends on the platform and window type.
TEST_F(CompositingWidgetTest, Transparency_DesktopWidgetOpaque) {
CheckAllWidgetsForOpacity(Widget::InitParams::WindowOpacity::kOpaque);
}
@@ -4200,7 +4157,7 @@ TEST_F(CompositingWidgetTest, Transparency_DesktopWidgetTranslucent) {
CheckAllWidgetsForOpacity(Widget::InitParams::WindowOpacity::kTranslucent);
}
-#endif // BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_APPLE)
+#endif // BUILDFLAG(ENABLE_DESKTOP_AURA) || defined(OS_MAC)
} // namespace test
} // namespace views
diff --git a/chromium/ui/views/widget/widget_utils.h b/chromium/ui/views/widget/widget_utils.h
index ee84051bc6c..3054fca9885 100644
--- a/chromium/ui/views/widget/widget_utils.h
+++ b/chromium/ui/views/widget/widget_utils.h
@@ -37,7 +37,7 @@ class VIEWS_EXPORT WidgetOpenTimer : public WidgetObserver {
Callback callback_;
// Time the bubble has been open. Used for UMA metrics collection.
- base::Optional<base::ElapsedTimer> open_timer_;
+ absl::optional<base::ElapsedTimer> open_timer_;
base::ScopedObservation<Widget, WidgetObserver> observed_widget_{this};
};
diff --git a/chromium/ui/views/widget/window_reorderer.cc b/chromium/ui/views/widget/window_reorderer.cc
index cba1414452d..0992ed1828c 100644
--- a/chromium/ui/views/widget/window_reorderer.cc
+++ b/chromium/ui/views/widget/window_reorderer.cc
@@ -15,6 +15,7 @@
#include "base/macros.h"
#include "ui/aura/window.h"
#include "ui/aura/window_occlusion_tracker.h"
+#include "ui/compositor/layer.h"
#include "ui/views/view.h"
#include "ui/views/view_constants_aura.h"
diff --git a/chromium/ui/views/win/fullscreen_handler.h b/chromium/ui/views/win/fullscreen_handler.h
index c76ef18a6f5..29231e2a913 100644
--- a/chromium/ui/views/win/fullscreen_handler.h
+++ b/chromium/ui/views/win/fullscreen_handler.h
@@ -8,7 +8,6 @@
#include <shobjidl.h>
#include <wrl/client.h>
-#include <map>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/ui/views/win/hwnd_message_handler.cc b/chromium/ui/views/win/hwnd_message_handler.cc
index df245fc9220..aabbdffa062 100644
--- a/chromium/ui/views/win/hwnd_message_handler.cc
+++ b/chromium/ui/views/win/hwnd_message_handler.cc
@@ -17,6 +17,7 @@
#include "base/callback_helpers.h"
#include "base/debug/gdi_debug_util_win.h"
#include "base/location.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_functions.h"
#include "base/single_thread_task_runner.h"
@@ -35,6 +36,7 @@
#include "ui/accessibility/platform/ax_fragment_root_win.h"
#include "ui/accessibility/platform/ax_platform_node_win.h"
#include "ui/accessibility/platform/ax_system_caret_win.h"
+#include "ui/base/cursor/win/win_cursor.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/base/ui_base_features.h"
@@ -402,7 +404,7 @@ HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate,
waiting_for_close_now_(false),
use_system_default_icon_(false),
restored_enabled_(false),
- current_cursor_(nullptr),
+ current_cursor_(base::MakeRefCounted<ui::WinCursor>()),
dpi_(0),
called_enable_non_client_dpi_scaling_(false),
active_mouse_tracking_flags_(0),
@@ -863,10 +865,12 @@ bool HWNDMessageHandler::SetTitle(const std::u16string& title) {
return true;
}
-void HWNDMessageHandler::SetCursor(HCURSOR cursor) {
+void HWNDMessageHandler::SetCursor(scoped_refptr<ui::WinCursor> cursor) {
+ DCHECK(cursor);
+
TRACE_EVENT1("ui,input", "HWNDMessageHandler::SetCursor", "cursor",
- static_cast<const void*>(cursor));
- ::SetCursor(cursor);
+ static_cast<const void*>(cursor->hcursor()));
+ ::SetCursor(cursor->hcursor());
current_cursor_ = cursor;
}
@@ -992,7 +996,7 @@ HICON HWNDMessageHandler::GetSmallWindowIcon() const {
LRESULT HWNDMessageHandler::OnWndProc(UINT message,
WPARAM w_param,
LPARAM l_param) {
- TRACE_EVENT("ui", "HWNDMessageHandler::OnWndProc",
+ TRACE_EVENT("ui,toplevel", "HWNDMessageHandler::OnWndProc",
[&](perfetto::EventContext ctx) {
perfetto::protos::pbzero::ChromeWindowHandleEventInfo* args =
ctx.event()->set_chrome_window_handle_event_info();
@@ -2491,12 +2495,15 @@ LRESULT HWNDMessageHandler::OnSetCursor(UINT message,
if (is_pen_active_in_client_area_)
return 1;
+ // current_cursor_ must be a ui::WinCursor, so that custom image cursors are
+ // properly ref-counted. cursor below is only used for system cursors and
+ // doesn't replace the current cursor so an HCURSOR can be used directly.
+ wchar_t* cursor = IDC_ARROW;
// Reimplement the necessary default behavior here. Calling DefWindowProc can
// trigger weird non-client painting for non-glass windows with custom frames.
// Using a ScopedRedrawLock to prevent caption rendering artifacts may allow
// content behind this window to incorrectly paint in front of this window.
// Invalidating the window to paint over either set of artifacts is not ideal.
- wchar_t* cursor = IDC_ARROW;
switch (LOWORD(l_param)) {
case HTSIZE:
cursor = IDC_SIZENWSE;
@@ -2724,8 +2731,8 @@ LRESULT HWNDMessageHandler::OnTouchEvent(UINT message,
touch_ids_.insert(input[i].dwID);
GenerateTouchEvent(ui::ET_TOUCH_PRESSED, touch_point, touch_id,
event_time, &touch_events);
- ui::ComputeEventLatencyOSWinFromTickCount(ui::ET_TOUCH_PRESSED,
- input[i].dwTime, event_time);
+ ui::ComputeEventLatencyOSFromTOUCHINPUT(ui::ET_TOUCH_PRESSED, input[i],
+ event_time);
touch_down_contexts_++;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
@@ -2736,16 +2743,16 @@ LRESULT HWNDMessageHandler::OnTouchEvent(UINT message,
if (input[i].dwFlags & TOUCHEVENTF_MOVE) {
GenerateTouchEvent(ui::ET_TOUCH_MOVED, touch_point, touch_id,
event_time, &touch_events);
- ui::ComputeEventLatencyOSWinFromTickCount(
- ui::ET_TOUCH_MOVED, input[i].dwTime, event_time);
+ ui::ComputeEventLatencyOSFromTOUCHINPUT(ui::ET_TOUCH_MOVED, input[i],
+ event_time);
}
if (input[i].dwFlags & TOUCHEVENTF_UP) {
touch_ids_.erase(input[i].dwID);
GenerateTouchEvent(ui::ET_TOUCH_RELEASED, touch_point, touch_id,
event_time, &touch_events);
- ui::ComputeEventLatencyOSWinFromTickCount(
- ui::ET_TOUCH_RELEASED, input[i].dwTime, event_time);
+ ui::ComputeEventLatencyOSFromTOUCHINPUT(ui::ET_TOUCH_RELEASED,
+ input[i], event_time);
id_generator_.ReleaseNumber(input[i].dwID);
}
}
@@ -3239,14 +3246,8 @@ LRESULT HWNDMessageHandler::HandlePointerEventTypeTouchOrNonClient(
ui::PointerDetails(ui::EventPointerType::kTouch, mapped_pointer_id,
radius_x, radius_y, pressure, rotation_angle),
ui::GetModifiersFromKeyState());
- if (pointer_info.PerformanceCount) {
- ui::ComputeEventLatencyOSWinFromPerformanceCounter(
- event_type, pointer_info.PerformanceCount, event_time);
- } else {
- ui::ComputeEventLatencyOSWinFromTickCount(event_type, pointer_info.dwTime,
- event_time);
- }
-
+ ui::ComputeEventLatencyOSFromPOINTER_INFO(event_type, pointer_info,
+ event_time);
event.latency()->AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, event_time);
diff --git a/chromium/ui/views/win/hwnd_message_handler.h b/chromium/ui/views/win/hwnd_message_handler.h
index 56b25183fac..a338ec40a40 100644
--- a/chromium/ui/views/win/hwnd_message_handler.h
+++ b/chromium/ui/views/win/hwnd_message_handler.h
@@ -17,11 +17,11 @@
#include "base/compiler_specific.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/win/scoped_gdi_object.h"
#include "base/win/win_util.h"
-#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/platform/ax_fragment_root_delegate_win.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/input_method_observer.h"
@@ -44,9 +44,10 @@ class Insets;
namespace ui {
class AXFragmentRootWin;
class AXSystemCaretWin;
+class SessionChangeObserver;
class TextInputClient;
class ViewProp;
-class SessionChangeObserver;
+class WinCursor;
} // namespace ui
namespace views {
@@ -160,7 +161,7 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
// Returns true if the title changed.
bool SetTitle(const std::u16string& title);
- void SetCursor(HCURSOR cursor);
+ void SetCursor(scoped_refptr<ui::WinCursor> cursor);
void FrameTypeChanged();
@@ -625,7 +626,7 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
bool restored_enabled_;
// The current cursor.
- HCURSOR current_cursor_;
+ scoped_refptr<ui::WinCursor> current_cursor_;
// The icon created from the bitmap image of the window icon.
base::win::ScopedHICON window_icon_;
@@ -635,7 +636,7 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
// The aspect ratio for the window. This is only used for sizing operations
// for the non-client area.
- base::Optional<float> aspect_ratio_;
+ absl::optional<float> aspect_ratio_;
// The current DPI.
int dpi_;
@@ -816,7 +817,7 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
gfx::Size exposed_pixels_;
// Populated if the cursor position is being mocked for testing purposes.
- base::Optional<gfx::Point> mock_cursor_position_;
+ absl::optional<gfx::Point> mock_cursor_position_;
base::ScopedObservation<ui::InputMethod, ui::InputMethodObserver>
observation_{this};
diff --git a/chromium/ui/views/win/pen_event_processor.cc b/chromium/ui/views/win/pen_event_processor.cc
index 3f0bb80262a..7257458f79a 100644
--- a/chromium/ui/views/win/pen_event_processor.cc
+++ b/chromium/ui/views/win/pen_event_processor.cc
@@ -201,13 +201,8 @@ std::unique_ptr<ui::Event> PenEventProcessor::GenerateTouchEvent(
std::unique_ptr<ui::TouchEvent> event = std::make_unique<ui::TouchEvent>(
event_type, point, event_time, pointer_details,
flags | ui::GetModifiersFromKeyState());
- if (pointer_info.PerformanceCount) {
- ui::ComputeEventLatencyOSWinFromPerformanceCounter(
- event_type, pointer_info.PerformanceCount, event_time);
- } else {
- ui::ComputeEventLatencyOSWinFromTickCount(event_type, pointer_info.dwTime,
- event_time);
- }
+ ui::ComputeEventLatencyOSFromPOINTER_INFO(event_type, pointer_info,
+ event_time);
event->set_hovering(event_type == ui::ET_TOUCH_RELEASED);
event->latency()->AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, event_time);
diff --git a/chromium/ui/views/win/pen_event_processor.h b/chromium/ui/views/win/pen_event_processor.h
index d40c847aa2a..f08fd60ba4a 100644
--- a/chromium/ui/views/win/pen_event_processor.h
+++ b/chromium/ui/views/win/pen_event_processor.h
@@ -9,7 +9,7 @@
#include <memory>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/event.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/sequential_id_generator.h"
@@ -58,7 +58,7 @@ class VIEWS_EXPORT PenEventProcessor {
base::flat_map<UINT32, bool> sent_mouse_down_;
base::flat_map<UINT32, bool> sent_touch_start_;
- base::Optional<unsigned int> eraser_pointer_id_;
+ absl::optional<unsigned int> eraser_pointer_id_;
DISALLOW_COPY_AND_ASSIGN(PenEventProcessor);
};
diff --git a/chromium/ui/views/win/scoped_enable_unadjusted_mouse_events_win.cc b/chromium/ui/views/win/scoped_enable_unadjusted_mouse_events_win.cc
index 13b65c78c04..4860d91f2d4 100644
--- a/chromium/ui/views/win/scoped_enable_unadjusted_mouse_events_win.cc
+++ b/chromium/ui/views/win/scoped_enable_unadjusted_mouse_events_win.cc
@@ -4,6 +4,7 @@
#include "ui/views/win/scoped_enable_unadjusted_mouse_events_win.h"
+#include "base/logging.h"
#include "ui/views/win/hwnd_message_handler.h"
namespace views {
diff --git a/chromium/ui/views/window/client_view.cc b/chromium/ui/views/window/client_view.cc
index 5527e26da27..7829ac20986 100644
--- a/chromium/ui/views/window/client_view.cc
+++ b/chromium/ui/views/window/client_view.cc
@@ -10,8 +10,8 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/hit_test.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/views/layout/fill_layout.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
@@ -87,8 +87,6 @@ void ClientView::ViewHierarchyChanged(
// TODO(weili): This seems fragile and can be refactored.
// Tracked at https://crbug.com/1012466.
AddChildViewAt(contents_view_, 0);
- } else if (!details.is_add && details.child == contents_view_) {
- contents_view_ = nullptr;
}
}
diff --git a/chromium/ui/views/window/custom_frame_view.cc b/chromium/ui/views/window/custom_frame_view.cc
index eda68f689da..9c2f931e0e4 100644
--- a/chromium/ui/views/window/custom_frame_view.cc
+++ b/chromium/ui/views/window/custom_frame_view.cc
@@ -211,6 +211,7 @@ void CustomFrameView::Layout() {
}
LayoutClientView();
+ NonClientFrameView::Layout();
}
gfx::Size CustomFrameView::CalculatePreferredSize() const {
diff --git a/chromium/ui/views/window/custom_frame_view_unittest.cc b/chromium/ui/views/window/custom_frame_view_unittest.cc
index 6a6ab78c313..c05b7529898 100644
--- a/chromium/ui/views/window/custom_frame_view_unittest.cc
+++ b/chromium/ui/views/window/custom_frame_view_unittest.cc
@@ -156,7 +156,7 @@ TEST_F(CustomFrameViewTest, MaximizeRevealsRestoreButton) {
widget()->Maximize();
custom_frame_view()->Layout();
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// Restore buttons do not exist on Mac. The maximize button is instead a kind
// of toggle, but has no effect on frame decorations.
EXPECT_FALSE(restore_button()->GetVisible());
@@ -209,7 +209,7 @@ TEST_F(CustomFrameViewTest, LargerEdgeButtonsWhenMaximized) {
widget()->Maximize();
custom_frame_view()->Layout();
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// On Mac, "Maximize" should not alter the frame. Only fullscreen does that.
EXPECT_EQ(close_button()->bounds().width(),
close_button_initial_bounds.width());
diff --git a/chromium/ui/views/window/dialog_client_view.cc b/chromium/ui/views/window/dialog_client_view.cc
index 9b74c37489c..026f9098cf5 100644
--- a/chromium/ui/views/window/dialog_client_view.cc
+++ b/chromium/ui/views/window/dialog_client_view.cc
@@ -10,6 +10,8 @@
#include <vector>
#include "build/build_config.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
@@ -20,8 +22,6 @@
#include "ui/views/controls/button/md_text_button.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/layout/layout_provider.h"
-#include "ui/views/metadata/metadata_header_macros.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/view_observer.h"
#include "ui/views/view_tracker.h"
diff --git a/chromium/ui/views/window/dialog_client_view.h b/chromium/ui/views/window/dialog_client_view.h
index 9a467cbf6ea..e6a4edf388f 100644
--- a/chromium/ui/views/window/dialog_client_view.h
+++ b/chromium/ui/views/window/dialog_client_view.h
@@ -7,7 +7,6 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/time/time.h"
#include "ui/base/ui_base_types.h"
#include "ui/views/input_event_activation_protector.h"
#include "ui/views/window/client_view.h"
diff --git a/chromium/ui/views/window/dialog_delegate.cc b/chromium/ui/views/window/dialog_delegate.cc
index 5cb2f115b10..c4a71efccfc 100644
--- a/chromium/ui/views/window/dialog_delegate.cc
+++ b/chromium/ui/views/window/dialog_delegate.cc
@@ -14,6 +14,7 @@
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_role_properties.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/color_palette.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/bubble/bubble_border.h"
@@ -21,7 +22,6 @@
#include "ui/views/buildflags.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/layout/layout_provider.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/views_features.h"
#include "ui/views/widget/widget.h"
@@ -103,7 +103,7 @@ Widget::InitParams DialogDelegate::GetDialogWidgetInitParams(
if (!dialog || dialog->use_custom_frame()) {
params.opacity = Widget::InitParams::WindowOpacity::kTranslucent;
params.remove_standard_frame = true;
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// Except on Mac, the bubble frame includes its own shadow; remove any
// native shadowing. On Mac, the window server provides the shadow.
params.shadow_type = views::Widget::InitParams::ShadowType::kNone;
diff --git a/chromium/ui/views/window/dialog_delegate.h b/chromium/ui/views/window/dialog_delegate.h
index b30f175a5fc..d0de3f31fce 100644
--- a/chromium/ui/views/window/dialog_delegate.h
+++ b/chromium/ui/views/window/dialog_delegate.h
@@ -13,8 +13,8 @@
#include "base/macros.h"
#include "base/time/time.h"
#include "ui/accessibility/ax_enums.mojom-forward.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/ui_base_types.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/view.h"
#include "ui/views/views_export.h"
@@ -43,7 +43,7 @@ class VIEWS_EXPORT DialogDelegate : public WidgetDelegate {
struct Params {
Params();
~Params();
- base::Optional<int> default_button = base::nullopt;
+ absl::optional<int> default_button = absl::nullopt;
bool round_corners = true;
bool draggable = false;
@@ -336,10 +336,10 @@ class VIEWS_EXPORT DialogDelegate : public WidgetDelegate {
Params params_;
// The extra view for this dialog, if there is one.
- std::unique_ptr<View> extra_view_ = nullptr;
+ std::unique_ptr<View> extra_view_;
// The footnote view for this dialog, if there is one.
- std::unique_ptr<View> footnote_view_ = nullptr;
+ std::unique_ptr<View> footnote_view_;
// Observers for DialogModel changes.
base::ObserverList<DialogObserver>::Unchecked observer_list_;
diff --git a/chromium/ui/views/window/dialog_delegate_unittest.cc b/chromium/ui/views/window/dialog_delegate_unittest.cc
index bf7ac390dea..89d71cd0991 100644
--- a/chromium/ui/views/window/dialog_delegate_unittest.cc
+++ b/chromium/ui/views/window/dialog_delegate_unittest.cc
@@ -21,7 +21,7 @@
#include "ui/views/widget/widget.h"
#include "ui/views/window/dialog_delegate.h"
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
#include "ui/base/test/scoped_fake_full_keyboard_access.h"
#endif
@@ -340,9 +340,9 @@ TEST_F(DialogTest, BoundsAccommodateTitle) {
}
TEST_F(DialogTest, ActualBoundsMatchPreferredBounds) {
- dialog()->set_title(base::ASCIIToUTF16(
- "La la la look at me I'm a really really long title that needs to be "
- "really really long so that the title will multiline wrap."));
+ dialog()->set_title(
+ u"La la la look at me I'm a really really long title that needs to be "
+ u"really really long so that the title will multiline wrap.");
dialog()->GetWidget()->UpdateWindowTitle();
views::View* root_view = dialog()->GetWidget()->GetRootView();
@@ -396,7 +396,7 @@ TEST_F(DialogTest, InitialFocusWithDeactivatedWidget) {
// If the initially focused View provided is unfocusable, check the next
// available focusable View is focused.
TEST_F(DialogTest, UnfocusableInitialFocus) {
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
// On Mac, make all buttons unfocusable by turning off full keyboard access.
// This is the more common configuration, and if a dialog has a focusable
// textfield, tree or table, that should obtain focus instead.
@@ -409,7 +409,7 @@ TEST_F(DialogTest, UnfocusableInitialFocus) {
dialog->AddChildView(textfield);
Widget* dialog_widget = CreateDialogWidget(dialog);
-#if !defined(OS_APPLE)
+#if !defined(OS_MAC)
// For non-Mac, turn off focusability on all the dialog's buttons manually.
// This achieves the same effect as disabling full keyboard access.
dialog->GetOkButton()->SetFocusBehavior(View::FocusBehavior::NEVER);
diff --git a/chromium/ui/views/window/frame_caption_button.cc b/chromium/ui/views/window/frame_caption_button.cc
index 0afd4b04d2f..9f05cd1d2bc 100644
--- a/chromium/ui/views/window/frame_caption_button.cc
+++ b/chromium/ui/views/window/frame_caption_button.cc
@@ -7,7 +7,9 @@
#include <memory>
#include <utility>
+#include "base/bind.h"
#include "ui/base/hit_test.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/animation/slide_animation.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_utils.h"
@@ -19,7 +21,6 @@
#include "ui/views/animation/ink_drop_impl.h"
#include "ui/views/animation/ink_drop_ripple.h"
#include "ui/views/controls/highlight_path_generator.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/window/hit_test_utils.h"
namespace views {
@@ -50,7 +51,7 @@ class FrameCaptionButton::HighlightPathGenerator
~HighlightPathGenerator() override = default;
// views::HighlightPathGenerator:
- base::Optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override {
+ absl::optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override {
gfx::Rect bounds = gfx::ToRoundedRect(rect);
bounds.Inset(frame_caption_button_->GetInkdropInsets(bounds.size()));
return gfx::RRectF(gfx::RectF(bounds),
@@ -75,9 +76,20 @@ FrameCaptionButton::FrameCaptionButton(PressedCallback callback,
swap_images_animation_->Reset(1);
SetHasInkDropActionOnClick(true);
- SetInkDropMode(InkDropMode::ON);
- SetInkDropVisibleOpacity(kInkDropVisibleOpacity);
+ ink_drop()->SetMode(views::InkDropHost::InkDropMode::ON);
+ ink_drop()->SetVisibleOpacity(kInkDropVisibleOpacity);
UpdateInkDropBaseColor();
+ views::InkDrop::UseInkDropWithoutAutoHighlight(ink_drop(),
+ /*highlight_on_hover=*/false);
+ ink_drop()->SetCreateRippleCallback(base::BindRepeating(
+ [](FrameCaptionButton* host) -> std::unique_ptr<views::InkDropRipple> {
+ return std::make_unique<views::FloodFillInkDropRipple>(
+ host->size(), host->GetInkdropInsets(host->size()),
+ host->ink_drop()->GetInkDropCenterBasedOnLastEvent(),
+ host->ink_drop()->GetBaseColor(),
+ host->ink_drop()->GetVisibleOpacity());
+ },
+ this));
views::HighlightPathGenerator::Install(
this, std::make_unique<HighlightPathGenerator>(this));
@@ -119,21 +131,21 @@ void FrameCaptionButton::SetImage(CaptionButtonIcon icon,
gfx::CreateVectorIcon(icon_definition, GetButtonColor(background_color_));
// The early return is dependent on |animate| because callers use SetImage()
- // with ANIMATE_NO to progress the crossfade animation to the end.
+ // with Animate::kNo to progress the crossfade animation to the end.
if (icon == icon_ &&
- (animate == ANIMATE_YES || !swap_images_animation_->is_animating()) &&
+ (animate == Animate::kYes || !swap_images_animation_->is_animating()) &&
new_icon_image.BackedBySameObjectAs(icon_image_)) {
return;
}
- if (animate == ANIMATE_YES)
+ if (animate == Animate::kYes)
crossfade_icon_image_ = icon_image_;
icon_ = icon;
icon_definition_ = &icon_definition;
icon_image_ = new_icon_image;
- if (animate == ANIMATE_YES) {
+ if (animate == Animate::kYes) {
swap_images_animation_->Reset(0);
swap_images_animation_->SetSlideDuration(
base::TimeDelta::FromMilliseconds(200));
@@ -185,20 +197,6 @@ views::PaintInfo::ScaleType FrameCaptionButton::GetPaintScaleType() const {
return views::PaintInfo::ScaleType::kUniformScaling;
}
-std::unique_ptr<views::InkDrop> FrameCaptionButton::CreateInkDrop() {
- auto ink_drop = std::make_unique<views::InkDropImpl>(this, size());
- ink_drop->SetAutoHighlightMode(views::InkDropImpl::AutoHighlightMode::NONE);
- ink_drop->SetShowHighlightOnHover(false);
- return ink_drop;
-}
-
-std::unique_ptr<views::InkDropRipple> FrameCaptionButton::CreateInkDropRipple()
- const {
- return std::make_unique<views::FloodFillInkDropRipple>(
- size(), GetInkdropInsets(size()), GetInkDropCenterBasedOnLastEvent(),
- GetInkDropBaseColor(), GetInkDropVisibleOpacity());
-}
-
void FrameCaptionButton::SetBackgroundColor(SkColor background_color) {
if (background_color_ == background_color)
return;
@@ -206,7 +204,7 @@ void FrameCaptionButton::SetBackgroundColor(SkColor background_color) {
background_color_ = background_color;
// Refresh the icon since the color may have changed.
if (icon_definition_)
- SetImage(icon_, ANIMATE_NO, *icon_definition_);
+ SetImage(icon_, Animate::kNo, *icon_definition_);
UpdateInkDropBaseColor();
}
@@ -255,7 +253,7 @@ void FrameCaptionButton::PaintButtonContents(gfx::Canvas* canvas) {
// the window is moving as a result of the animation from normal to
// maximized state or vice versa. https://crbug.com/840901.
cc::PaintFlags flags;
- flags.setColor(GetInkDropBaseColor());
+ flags.setColor(ink_drop()->GetBaseColor());
flags.setAlpha(highlight_alpha);
const gfx::Point center(GetMirroredRect(GetContentsBounds()).CenterPoint());
canvas->DrawCircle(center, ink_drop_corner_radius_, flags);
@@ -329,38 +327,39 @@ void FrameCaptionButton::UpdateInkDropBaseColor() {
// TODO(pkasting): It would likely be better to make the button glyph always
// be an alpha-blended version of GetColorWithMaxContrast(background_color_).
const SkColor button_color = GetButtonColor(background_color_);
- SetInkDropBaseColor(
+ ink_drop()->SetBaseColor(
GetColorWithMaxContrast(GetColorWithMaxContrast(button_color)));
}
-DEFINE_ENUM_CONVERTERS(
- views::CaptionButtonIcon,
- {{views::CaptionButtonIcon::CAPTION_BUTTON_ICON_MINIMIZE,
- u"CAPTION_BUTTON_ICON_MINIMIZE"},
- {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE,
- u"CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE"},
- {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_CLOSE,
- u"CAPTION_BUTTON_ICON_CLOSE"},
- {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_LEFT_SNAPPED,
- u"CAPTION_BUTTON_ICON_LEFT_SNAPPED"},
- {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
- u"CAPTION_BUTTON_ICON_RIGHT_SNAPPED"},
- {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_BACK,
- u"CAPTION_BUTTON_ICON_BACK"},
- {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_LOCATION,
- u"CAPTION_BUTTON_ICON_LOCATION"},
- {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_MENU,
- u"CAPTION_BUTTON_ICON_MENU"},
- {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_ZOOM,
- u"CAPTION_BUTTON_ICON_ZOOM"},
- {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_COUNT,
- u"CAPTION_BUTTON_ICON_COUNT"}})
-
BEGIN_METADATA(FrameCaptionButton, Button)
-ADD_PROPERTY_METADATA(SkColor, BackgroundColor, metadata::SkColorConverter)
+ADD_PROPERTY_METADATA(SkColor, BackgroundColor, ui::metadata::SkColorConverter)
ADD_PROPERTY_METADATA(int, InkDropCornerRadius)
ADD_READONLY_PROPERTY_METADATA(CaptionButtonIcon, Icon)
ADD_PROPERTY_METADATA(bool, PaintAsActive)
END_METADATA
} // namespace views
+
+DEFINE_ENUM_CONVERTERS(
+ views::CaptionButtonIcon,
+ {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_MINIMIZE,
+ u"CAPTION_BUTTON_ICON_MINIMIZE"},
+ {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE,
+ u"CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE"},
+ {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_CLOSE,
+ u"CAPTION_BUTTON_ICON_CLOSE"},
+ {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_LEFT_SNAPPED,
+ u"CAPTION_BUTTON_ICON_LEFT_SNAPPED"},
+ {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
+ u"CAPTION_BUTTON_ICON_RIGHT_SNAPPED"},
+ {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_BACK,
+ u"CAPTION_BUTTON_ICON_BACK"},
+ {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_LOCATION,
+ u"CAPTION_BUTTON_ICON_LOCATION"},
+ {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_MENU,
+ u"CAPTION_BUTTON_ICON_MENU"},
+ {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_ZOOM,
+ u"CAPTION_BUTTON_ICON_ZOOM"},
+ {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_COUNT,
+ u"CAPTION_BUTTON_ICON_COUNT"})
+
diff --git a/chromium/ui/views/window/frame_caption_button.h b/chromium/ui/views/window/frame_caption_button.h
index 06d8810f757..2c9d7b56a7d 100644
--- a/chromium/ui/views/window/frame_caption_button.h
+++ b/chromium/ui/views/window/frame_caption_button.h
@@ -7,10 +7,10 @@
#include <memory>
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/controls/button/button.h"
-#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/views_export.h"
#include "ui/views/window/caption_button_layout_constants.h"
#include "ui/views/window/caption_button_types.h"
@@ -22,15 +22,12 @@ struct VectorIcon;
namespace views {
-class InkDrop;
-class InkDropRipple;
-
// Base class for the window caption buttons (minimize, maximize, restore,
// close).
class VIEWS_EXPORT FrameCaptionButton : public views::Button {
public:
METADATA_HEADER(FrameCaptionButton);
- enum Animate { ANIMATE_YES, ANIMATE_NO };
+ enum class Animate { kYes, kNo };
FrameCaptionButton(PressedCallback callback,
CaptionButtonIcon icon,
@@ -45,9 +42,9 @@ class VIEWS_EXPORT FrameCaptionButton : public views::Button {
// Gets the alpha ratio for the colors of inactive frame caption buttons.
static float GetInactiveButtonColorAlphaRatio();
- // Sets the image to use to paint the button. If |animate| is ANIMATE_YES,
+ // Sets the image to use to paint the button. If |animate| is Animate::kYes,
// the button crossfades to the new visuals. If the image matches the one
- // currently used by the button and |animate| is ANIMATE_NO, the crossfade
+ // currently used by the button and |animate| is Animate::kNo, the crossfade
// animation is progressed to the end.
void SetImage(CaptionButtonIcon icon,
Animate animate,
@@ -63,8 +60,6 @@ class VIEWS_EXPORT FrameCaptionButton : public views::Button {
// views::Button:
void OnGestureEvent(ui::GestureEvent* event) override;
views::PaintInfo::ScaleType GetPaintScaleType() const override;
- std::unique_ptr<InkDrop> CreateInkDrop() override;
- std::unique_ptr<InkDropRipple> CreateInkDropRipple() const override;
void SetBackgroundColor(SkColor background_color);
SkColor GetBackgroundColor() const;
diff --git a/chromium/ui/views/window/native_frame_view.cc b/chromium/ui/views/window/native_frame_view.cc
index 12edd20f200..89b88c55f78 100644
--- a/chromium/ui/views/window/native_frame_view.cc
+++ b/chromium/ui/views/window/native_frame_view.cc
@@ -5,7 +5,7 @@
#include "ui/views/window/native_frame_view.h"
#include "build/build_config.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/views/widget/native_widget.h"
#include "ui/views/widget/widget.h"
diff --git a/chromium/ui/views/window/native_frame_view.h b/chromium/ui/views/window/native_frame_view.h
index 0b185af8709..ce1c5ed4c1f 100644
--- a/chromium/ui/views/window/native_frame_view.h
+++ b/chromium/ui/views/window/native_frame_view.h
@@ -6,7 +6,7 @@
#define UI_VIEWS_WINDOW_NATIVE_FRAME_VIEW_H_
#include "base/macros.h"
-#include "ui/views/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/window/non_client_view.h"
diff --git a/chromium/ui/views/window/non_client_view.cc b/chromium/ui/views/window/non_client_view.cc
index 73170394a79..7c45c43d07f 100644
--- a/chromium/ui/views/window/non_client_view.cc
+++ b/chromium/ui/views/window/non_client_view.cc
@@ -10,8 +10,9 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/hit_test.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/geometry/rect_conversions.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
+#include "ui/views/layout/fill_layout.h"
#include "ui/views/rect_based_targeting_utils.h"
#include "ui/views/view_targeter.h"
#include "ui/views/widget/root_view.h"
@@ -24,18 +25,6 @@
namespace views {
-namespace {
-
-// The frame view and the client view are always at these specific indices,
-// because the RootView message dispatch sends messages to items higher in the
-// z-order first and we always want the client view to have first crack at
-// handling mouse messages.
-constexpr int kFrameViewIndex = 0;
-constexpr int kClientViewIndex = 1;
-// The overlay view is always on top (view == children().back()).
-
-} // namespace
-
NonClientFrameView::~NonClientFrameView() = default;
bool NonClientFrameView::ShouldPaintAsActive() const {
@@ -129,18 +118,19 @@ void NonClientFrameView::OnThemeChanged() {
SchedulePaint();
}
-NonClientFrameView::NonClientFrameView() {
- SetEventTargeter(std::make_unique<views::ViewTargeter>(this));
-}
+void NonClientFrameView::Layout() {
+ if (GetLayoutManager())
+ GetLayoutManager()->Layout(this);
-// ViewTargeterDelegate:
-bool NonClientFrameView::DoesIntersectRect(const View* target,
- const gfx::Rect& rect) const {
- CHECK_EQ(target, this);
+ views::ClientView* client_view = GetWidget()->client_view();
+ client_view->SetBoundsRect(GetBoundsForClientView());
+ SkPath client_clip;
+ if (GetClientMask(client_view->size(), &client_clip))
+ client_view->SetClipPath(client_clip);
+}
- // For the default case, we assume the non-client frame view never overlaps
- // the client view.
- return !GetWidget()->client_view()->bounds().Intersects(rect);
+NonClientFrameView::NonClientFrameView() {
+ SetEventTargeter(std::make_unique<views::ViewTargeter>(this));
}
#if defined(OS_WIN)
@@ -165,13 +155,18 @@ NonClientView::~NonClientView() {
void NonClientView::SetFrameView(
std::unique_ptr<NonClientFrameView> frame_view) {
- // See comment in header about ownership.
- frame_view->set_owned_by_client();
- if (frame_view_.get())
- RemoveChildView(frame_view_.get());
+ // If there is an existing frame view, ensure that the ClientView remains
+ // attached to the Widget by moving the ClientView to the new frame before
+ // removing the old frame from the view hierarchy.
+ std::unique_ptr<NonClientFrameView> old_frame_view = std::move(frame_view_);
frame_view_ = std::move(frame_view);
- if (parent())
- AddChildViewAt(frame_view_.get(), kFrameViewIndex);
+ if (parent()) {
+ AddChildViewAt(frame_view_.get(), 0);
+ frame_view_->AddChildViewAt(client_view_, 0);
+ }
+
+ if (old_frame_view)
+ RemoveChildView(old_frame_view.get());
}
void NonClientView::SetOverlayView(View* view) {
@@ -262,11 +257,6 @@ void NonClientView::Layout() {
// into a View hierarchy once" ( http://codereview.chromium.org/27317 ), but
// where that is still the case it should simply be fixed.
frame_view_->SetBoundsRect(GetLocalBounds());
- client_view_->SetBoundsRect(frame_view_->GetBoundsForClientView());
-
- SkPath client_clip;
- if (frame_view_->GetClientMask(client_view_->size(), &client_clip))
- client_view_->SetClipPath(client_clip);
if (overlay_view_)
overlay_view_->SetBoundsRect(GetLocalBounds());
@@ -302,8 +292,8 @@ void NonClientView::ViewHierarchyChanged(
// the various setters, and create and add children directly in the
// constructor.
if (details.is_add && GetWidget() && details.child == this) {
- AddChildViewAt(frame_view_.get(), kFrameViewIndex);
- AddChildViewAt(client_view_, kClientViewIndex);
+ AddChildViewAt(frame_view_.get(), 0);
+ frame_view_->AddChildViewAt(client_view_, 0);
if (overlay_view_)
AddChildView(overlay_view_);
}
diff --git a/chromium/ui/views/window/non_client_view.h b/chromium/ui/views/window/non_client_view.h
index 58558cc0df4..e56193acc1f 100644
--- a/chromium/ui/views/window/non_client_view.h
+++ b/chromium/ui/views/window/non_client_view.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "build/build_config.h"
-#include "ui/views/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/view.h"
#include "ui/views/view_targeter_delegate.h"
@@ -101,11 +101,7 @@ class VIEWS_EXPORT NonClientFrameView : public View,
// View:
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
void OnThemeChanged() override;
-
- protected:
- // ViewTargeterDelegate:
- bool DoesIntersectRect(const View* target,
- const gfx::Rect& rect) const override;
+ void Layout() override;
private:
#if defined(OS_WIN)
@@ -121,10 +117,11 @@ class VIEWS_EXPORT NonClientFrameView : public View,
//
// The NonClientView is the logical root of all Views contained within a
// Window, except for the RootView which is its parent and of which it is the
-// sole child. The NonClientView has two children, the NonClientFrameView which
+// sole child. The NonClientView has one child, the NonClientFrameView which
// is responsible for painting and responding to events from the non-client
-// portions of the window, and the ClientView, which is responsible for the
-// same for the client area of the window:
+// portions of the window, and for forwarding events to its child, the
+// ClientView, which is responsible for the same for the client area of the
+// window:
//
// +- views::Widget ------------------------------------+
// | +- views::RootView ------------------------------+ |
@@ -135,23 +132,17 @@ class VIEWS_EXPORT NonClientFrameView : public View,
// | | | | << of the non-client areas of a >> | | | |
// | | | | << views::Widget. >> | | | |
// | | | | | | | |
-// | | | +----------------------------------------+ | | |
-// | | | +- views::ClientView or subclass --------+ | | |
-// | | | | | | | |
-// | | | | << all painting and event receiving >> | | | |
-// | | | | << of the client areas of a >> | | | |
-// | | | | << views::Widget. >> | | | |
-// | | | | | | | |
+// | | | | +- views::ClientView or subclass ----+ | | | |
+// | | | | | | | | | |
+// | | | | | << all painting and event >> | | | | |
+// | | | | | << receiving of the client >> | | | | |
+// | | | | | << areas of a views::Widget. >> | | | | |
+// | | | | +----------------------------------+ | | | | |
// | | | +----------------------------------------+ | | |
// | | +--------------------------------------------+ | |
// | +------------------------------------------------+ |
// +----------------------------------------------------+
//
-// The NonClientFrameView and ClientView are siblings because due to theme
-// changes the NonClientFrameView may be replaced with different
-// implementations (e.g. during the switch from DWM/Aero-Glass to Vista Basic/
-// Classic rendering).
-//
class VIEWS_EXPORT NonClientView : public View, public ViewTargeterDelegate {
public:
METADATA_HEADER(NonClientView);
diff --git a/chromium/ui/views/window/non_client_view_unittest.cc b/chromium/ui/views/window/non_client_view_unittest.cc
deleted file mode 100644
index fd66cb2c607..00000000000
--- a/chromium/ui/views/window/non_client_view_unittest.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/window/non_client_view.h"
-
-#include <memory>
-
-#include "ui/views/test/views_test_base.h"
-#include "ui/views/widget/widget_delegate.h"
-#include "ui/views/window/client_view.h"
-#include "ui/views/window/native_frame_view.h"
-
-namespace views {
-namespace test {
-
-namespace {
-
-class NonClientFrameTestView : public NativeFrameView {
- public:
- using NativeFrameView::NativeFrameView;
- int layout_count() const { return layout_count_; }
-
- // NativeFrameView:
- void Layout() override {
- NativeFrameView::Layout();
- ++layout_count_;
- }
-
- private:
- int layout_count_ = 0;
-};
-
-class ClientTestView : public ClientView {
- public:
- using ClientView::ClientView;
- int layout_count() const { return layout_count_; }
-
- // ClientView:
- void Layout() override {
- ClientView::Layout();
- ++layout_count_;
- }
-
- private:
- int layout_count_ = 0;
-};
-
-class TestWidgetDelegate : public WidgetDelegateView {
- public:
- // WidgetDelegateView:
- std::unique_ptr<NonClientFrameView> CreateNonClientFrameView(
- Widget* widget) override {
- return std::make_unique<NonClientFrameTestView>(widget);
- }
-
- views::ClientView* CreateClientView(Widget* widget) override {
- return new ClientTestView(widget, this);
- }
-};
-
-class NonClientViewTest : public ViewsTestBase {
- public:
- Widget::InitParams CreateParams(Widget::InitParams::Type type) override {
- Widget::InitParams params = ViewsTestBase::CreateParams(type);
- params.delegate = new TestWidgetDelegate;
- return params;
- }
-};
-
-} // namespace
-
-// Ensure Layout() is not called excessively on a ClientView when Widget bounds
-// are changing.
-TEST_F(NonClientViewTest, OnlyLayoutChildViewsOnce) {
- std::unique_ptr<views::Widget> widget =
- CreateTestWidget(Widget::InitParams::TYPE_WINDOW);
-
- NonClientView* non_client_view = widget->non_client_view();
- non_client_view->Layout();
-
- auto* frame_view =
- static_cast<NonClientFrameTestView*>(non_client_view->frame_view());
- auto* client_view =
- static_cast<ClientTestView*>(non_client_view->client_view());
-
- int initial_frame_view_layouts = frame_view->layout_count();
- int initial_client_view_layouts = client_view->layout_count();
-
- // Make sure it does no layout when nothing has changed.
- non_client_view->Layout();
- EXPECT_EQ(frame_view->layout_count(), initial_frame_view_layouts);
- EXPECT_EQ(client_view->layout_count(), initial_client_view_layouts);
-
- // Ensure changing bounds triggers a (single) layout.
- widget->SetBounds(gfx::Rect(0, 0, 161, 100));
- EXPECT_EQ(frame_view->layout_count(), initial_frame_view_layouts + 1);
- EXPECT_EQ(client_view->layout_count(), initial_client_view_layouts + 1);
-}
-
-} // namespace test
-} // namespace views
diff --git a/chromium/ui/views_content_client/views_content_client_main_parts.cc b/chromium/ui/views_content_client/views_content_client_main_parts.cc
index 2b646d54234..b26e9438aea 100644
--- a/chromium/ui/views_content_client/views_content_client_main_parts.cc
+++ b/chromium/ui/views_content_client/views_content_client_main_parts.cc
@@ -26,7 +26,7 @@ ViewsContentClientMainParts::~ViewsContentClientMainParts() {
}
#if !defined(OS_APPLE)
-void ViewsContentClientMainParts::PreCreateMainMessageLoop() {}
+void ViewsContentClientMainParts::PreBrowserMain() {}
#endif
int ViewsContentClientMainParts::PreMainMessageLoopRun() {
diff --git a/chromium/ui/views_content_client/views_content_client_main_parts.h b/chromium/ui/views_content_client/views_content_client_main_parts.h
index 69f8e7b917d..b19ff18f2f1 100644
--- a/chromium/ui/views_content_client/views_content_client_main_parts.h
+++ b/chromium/ui/views_content_client/views_content_client_main_parts.h
@@ -35,8 +35,7 @@ class ViewsContentClientMainParts : public content::BrowserMainParts {
const content::MainFunctionParams& content_params,
ViewsContentClient* views_content_client);
- // Invoked before the BrowserMainLoop constructor.
- static void PreCreateMainMessageLoop();
+ static void PreBrowserMain();
~ViewsContentClientMainParts() override;
diff --git a/chromium/ui/views_content_client/views_content_client_main_parts_desktop_aura.cc b/chromium/ui/views_content_client/views_content_client_main_parts_desktop_aura.cc
index c5eb0a54282..27a5253b6a3 100644
--- a/chromium/ui/views_content_client/views_content_client_main_parts_desktop_aura.cc
+++ b/chromium/ui/views_content_client/views_content_client_main_parts_desktop_aura.cc
@@ -27,6 +27,10 @@ class ViewsContentClientMainPartsDesktopAura
// ViewsContentClientMainPartsAura:
int PreMainMessageLoopRun() override;
+ void PostMainMessageLoopRun() override;
+
+ private:
+ std::unique_ptr<display::Screen> screen_;
};
ViewsContentClientMainPartsDesktopAura::ViewsContentClientMainPartsDesktopAura(
@@ -38,13 +42,19 @@ ViewsContentClientMainPartsDesktopAura::ViewsContentClientMainPartsDesktopAura(
int ViewsContentClientMainPartsDesktopAura::PreMainMessageLoopRun() {
ViewsContentClientMainPartsAura::PreMainMessageLoopRun();
- views::CreateDesktopScreen();
+ screen_ = views::CreateDesktopScreen();
views_content_client()->OnPreMainMessageLoopRun(browser_context(), nullptr);
return content::RESULT_CODE_NORMAL_EXIT;
}
+void ViewsContentClientMainPartsDesktopAura::PostMainMessageLoopRun() {
+ screen_.reset();
+
+ ViewsContentClientMainPartsAura::PostMainMessageLoopRun();
+}
+
} // namespace
// static
diff --git a/chromium/ui/views_content_client/views_content_client_main_parts_mac.mm b/chromium/ui/views_content_client/views_content_client_main_parts_mac.mm
index ec2cfe66cbb..224a1d3f7af 100644
--- a/chromium/ui/views_content_client/views_content_client_main_parts_mac.mm
+++ b/chromium/ui/views_content_client/views_content_client_main_parts_mac.mm
@@ -101,7 +101,7 @@ ViewsContentClientMainParts::Create(
}
// static
-void ViewsContentClientMainParts::PreCreateMainMessageLoop() {
+void ViewsContentClientMainParts::PreBrowserMain() {
// Simply instantiating an instance of ShellCrApplication serves to register
// it as the application class. Do make sure that no other code has done this
// first, though.
diff --git a/chromium/ui/views_content_client/views_content_main_delegate.cc b/chromium/ui/views_content_client/views_content_main_delegate.cc
index 8a85f930b5a..f4020b5dcb6 100644
--- a/chromium/ui/views_content_client/views_content_main_delegate.cc
+++ b/chromium/ui/views_content_client/views_content_main_delegate.cc
@@ -82,9 +82,9 @@ void ViewsContentMainDelegate::PreSandboxStartup() {
views_content_client_->OnResourcesLoaded();
}
-void ViewsContentMainDelegate::PreCreateMainMessageLoop() {
- content::ContentMainDelegate::PreCreateMainMessageLoop();
- ViewsContentClientMainParts::PreCreateMainMessageLoop();
+void ViewsContentMainDelegate::PreBrowserMain() {
+ content::ContentMainDelegate::PreBrowserMain();
+ ViewsContentClientMainParts::PreBrowserMain();
}
content::ContentClient* ViewsContentMainDelegate::CreateContentClient() {
diff --git a/chromium/ui/views_content_client/views_content_main_delegate.h b/chromium/ui/views_content_client/views_content_main_delegate.h
index 93c3b2a8b0b..7b8b4e3faf7 100644
--- a/chromium/ui/views_content_client/views_content_main_delegate.h
+++ b/chromium/ui/views_content_client/views_content_main_delegate.h
@@ -24,7 +24,7 @@ class ViewsContentMainDelegate : public content::ContentMainDelegate {
// content::ContentMainDelegate implementation
bool BasicStartupComplete(int* exit_code) override;
void PreSandboxStartup() override;
- void PreCreateMainMessageLoop() override;
+ void PreBrowserMain() override;
content::ContentClient* CreateContentClient() override;
content::ContentBrowserClient* CreateContentBrowserClient() override;
diff --git a/chromium/ui/web_dialogs/web_dialog_ui.h b/chromium/ui/web_dialogs/web_dialog_ui.h
index 97b467c1e6b..6ec68384599 100644
--- a/chromium/ui/web_dialogs/web_dialog_ui.h
+++ b/chromium/ui/web_dialogs/web_dialog_ui.h
@@ -5,8 +5,6 @@
#ifndef UI_WEB_DIALOGS_WEB_DIALOG_UI_H_
#define UI_WEB_DIALOGS_WEB_DIALOG_UI_H_
-#include <string>
-#include <vector>
#include "base/compiler_specific.h"
#include "base/macros.h"
diff --git a/chromium/ui/webui/PLATFORM_OWNERS b/chromium/ui/webui/PLATFORM_OWNERS
index 98b1491e276..b7da68e79eb 100644
--- a/chromium/ui/webui/PLATFORM_OWNERS
+++ b/chromium/ui/webui/PLATFORM_OWNERS
@@ -1,5 +1,4 @@
# Please use more specific OWNERS when possible.
-aee@chromium.org
antrim@chromium.org # CET
calamity@chromium.org
dpapad@chromium.org
diff --git a/chromium/ui/webui/mojo_bubble_web_ui_controller.h b/chromium/ui/webui/mojo_bubble_web_ui_controller.h
index 2cf7f5a0eaf..9ef0e527f3f 100644
--- a/chromium/ui/webui/mojo_bubble_web_ui_controller.h
+++ b/chromium/ui/webui/mojo_bubble_web_ui_controller.h
@@ -5,7 +5,6 @@
#ifndef UI_WEBUI_MOJO_BUBBLE_WEB_UI_CONTROLLER_H_
#define UI_WEBUI_MOJO_BUBBLE_WEB_UI_CONTROLLER_H_
-#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "ui/webui/mojo_web_ui_controller.h"
diff --git a/chromium/ui/webui/resources/BUILD.gn b/chromium/ui/webui/resources/BUILD.gn
index b6a39f2f7c6..67f62a5629c 100644
--- a/chromium/ui/webui/resources/BUILD.gn
+++ b/chromium/ui/webui/resources/BUILD.gn
@@ -67,8 +67,14 @@ generate_grd("build_grd") {
}
if (is_chromeos_ash) {
- deps += [ "//third_party/web-animations-js:build_grdp" ]
- grdp_files += [ "$root_gen_dir/third_party/web-animations-js/web_animations_resources.grdp" ]
+ deps += [
+ "//ash/content/common/resources:build_grdp",
+ "//third_party/web-animations-js:build_grdp",
+ ]
+ grdp_files += [
+ "$root_gen_dir/third_party/web-animations-js/web_animations_resources.grdp",
+ "$root_gen_dir/ash/content/common/resources/ash_common_resources.grdp",
+ ]
}
if (!is_android && !is_ios) {
@@ -78,7 +84,7 @@ generate_grd("build_grd") {
}
group("preprocess") {
- deps = [
+ public_deps = [
"cr_components:preprocess",
"cr_elements:preprocess",
"js:preprocess",
@@ -125,33 +131,132 @@ generate_grd("build_ts_grdp") {
manifest_files = [ "$target_gen_dir/tsconfig.manifest" ]
}
+preprocessed_folder = "$target_gen_dir/preprocessed"
+
+checked_in_dts_files = [
+ "cr_components/managed_footnote/managed_footnote.d.ts",
+ "cr_elements/cr_action_menu/cr_action_menu.m.d.ts",
+ "cr_elements/cr_button/cr_button.m.d.ts",
+ "cr_elements/cr_checkbox/cr_checkbox.m.d.ts",
+ "cr_elements/cr_container_shadow_behavior.m.d.ts",
+ "cr_elements/cr_dialog/cr_dialog.m.d.ts",
+ "cr_elements/cr_drawer/cr_drawer.d.ts",
+ "cr_elements/cr_icon_button/cr_icon_button.m.d.ts",
+ "cr_elements/cr_input/cr_input.m.d.ts",
+ "cr_elements/cr_lazy_render/cr_lazy_render.m.d.ts",
+ "cr_elements/cr_search_field/cr_search_field_behavior.d.ts",
+ "cr_elements/cr_toast/cr_toast.m.d.ts",
+ "cr_elements/cr_toolbar/cr_toolbar_search_field.d.ts",
+ "cr_elements/cr_view_manager/cr_view_manager.d.ts",
+ "cr_elements/find_shortcut_behavior.d.ts",
+ "js/cr/ui/focus_row_behavior.m.d.ts",
+ "js/i18n_behavior.m.d.ts",
+ "js/web_ui_listener_behavior.m.d.ts",
+]
+
+# Copies checked-in .d.ts files to the preprocess folder so that they are
+# discovered by TSC the same way generated .d.ts files are.
+copy("copy_checked_in_dts_files") {
+ sources = checked_in_dts_files
+ outputs = [ "$preprocessed_folder/{{source_target_relative}}" ]
+}
+
ts_library("library") {
- sources = [
+ root_dir = preprocessed_folder
+ out_dir = preprocessed_folder
+ composite = true
+ in_files = [
"js/cr/world.ts",
"js/hello_world.ts",
]
- definitions = [
- "js/assert.m.d.ts",
- "js/cr.m.d.ts",
- "js/promise_resolver.m.d.ts",
- "js/util.m.d.ts",
+
+ definitions = []
+
+ # Checked-in .d.ts files.
+ foreach(_file, checked_in_dts_files) {
+ definitions += [ "$root_dir/$_file" ]
+ }
+
+ definitions += [
+ # Auto-generated .d.ts files.
+ "$root_dir/cr_elements/cr_grid/cr_grid.d.ts",
+ "$root_dir/cr_elements/cr_input/cr_input_style_css.m.d.ts",
+ "$root_dir/cr_elements/cr_menu_selector/cr_menu_selector.d.ts",
+ "$root_dir/cr_elements/cr_splitter/cr_splitter.d.ts",
+ "$root_dir/cr_elements/cr_toolbar/cr_toolbar.d.ts",
+ "$root_dir/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.d.ts",
+ "$root_dir/cr_elements/hidden_style_css.m.d.ts",
+ "$root_dir/cr_elements/icons.m.d.ts",
+ "$root_dir/cr_elements/md_select_css.m.d.ts",
+ "$root_dir/cr_elements/shared_style_css.m.d.ts",
+ "$root_dir/cr_elements/shared_vars_css.m.d.ts",
+ "$root_dir/js/assert.m.d.ts",
+ "$root_dir/js/cr/event_target.m.d.ts",
+ "$root_dir/js/cr.m.d.ts",
+ "$root_dir/js/cr/ui/focus_grid.m.d.ts",
+ "$root_dir/js/cr/ui/focus_outline_manager.m.d.ts",
+ "$root_dir/js/cr/ui/focus_row.m.d.ts",
+ "$root_dir/js/cr/ui/store.m.d.ts",
+ "$root_dir/js/cr/ui/store_client.m.d.ts",
+ "$root_dir/js/event_tracker.m.d.ts",
+ "$root_dir/js/load_time_data.m.d.ts",
+ "$root_dir/js/parse_html_subset.m.d.ts",
+ "$root_dir/js/promise_resolver.m.d.ts",
+ "$root_dir/js/icon.m.d.ts",
+ "$root_dir/js/util.m.d.ts",
]
+
+ if (!is_android) {
+ definitions += [ "$root_dir/js/cr/ui/focus_without_ink.m.d.ts" ]
+ }
+
+ deps = [ "//third_party/polymer/v3_0:library" ]
extra_deps = [
+ ":copy_checked_in_dts_files",
":generate_definitions",
- ":generate_definitions_src",
+ "js:preprocess_src_ts",
]
}
ts_definitions("generate_definitions") {
- root_dir = "$root_gen_dir/ui/webui/resources/preprocessed"
+ root_dir = preprocessed_folder
+ out_dir = preprocessed_folder
js_files = [
+ "cr_elements/cr_grid/cr_grid.js",
+ "cr_elements/cr_input/cr_input_style_css.m.js",
+ "cr_elements/cr_menu_selector/cr_menu_selector.js",
+ "cr_elements/cr_splitter/cr_splitter.js",
+ "cr_elements/cr_toolbar/cr_toolbar.js",
+ "cr_elements/cr_toolbar/cr_toolbar_selection_overlay.js",
+ "cr_elements/hidden_style_css.m.js",
+ "cr_elements/icons.m.js",
+ "cr_elements/md_select_css.m.js",
+ "cr_elements/shared_style_css.m.js",
+ "cr_elements/shared_vars_css.m.js",
"js/assert.m.js",
+ "js/cr.m.js",
+ "js/cr/event_target.m.js",
+ "js/cr/ui/focus_grid.m.js",
+ "js/cr/ui/focus_outline_manager.m.js",
+ "js/cr/ui/store.m.js",
+ "js/cr/ui/store_client.m.js",
+ "js/cr/ui/focus_row.m.js",
+ "js/event_tracker.m.js",
+ "js/load_time_data.m.js",
+ "js/parse_html_subset.m.js",
"js/promise_resolver.m.js",
+ "js/icon.m.js",
"js/util.m.js",
]
- extra_deps = [ "js:preprocess" ]
-}
-ts_definitions("generate_definitions_src") {
- js_files = [ "js/cr.m.js" ]
+ if (!is_android) {
+ js_files += [ "js/cr/ui/focus_without_ink.m.js" ]
+ }
+
+ extra_deps = [
+ # Copy checked-in d.ts files first, so that |generate_definitions| leverages
+ # these files, instead of accidentally auto-generating them.
+ ":copy_checked_in_dts_files",
+ ":preprocess",
+ ]
}
diff --git a/chromium/ui/webui/resources/cr_components/BUILD.gn b/chromium/ui/webui/resources/cr_components/BUILD.gn
index be1d674271c..5cb62658348 100644
--- a/chromium/ui/webui/resources/cr_components/BUILD.gn
+++ b/chromium/ui/webui/resources/cr_components/BUILD.gn
@@ -12,7 +12,9 @@ preprocess_folder =
"$root_gen_dir/ui/webui/resources/preprocessed/cr_components"
preprocess_gen_manifest = "preprocessed_gen_manifest.json"
preprocess_mojom_manifest = "preprocessed_mojom_manifest.json"
-preprocess_polymer2_manifest = "preprocessed_polymer2_manifest.json"
+if (is_chromeos_ash) {
+ preprocess_polymer2_manifest = "preprocessed_polymer2_manifest.json"
+}
preprocess_src_manifest = "preprocessed_src_manifest.json"
generate_grd("build_grdp") {
@@ -43,6 +45,7 @@ generate_grd("build_grdp") {
"chromeos/network/cellular_3.svg",
"chromeos/network/cellular_4.svg",
"chromeos/network/cellular_off.svg",
+ "chromeos/network/cellular_locked.svg",
"chromeos/network/ethernet.svg",
"chromeos/network/vpn.svg",
"chromeos/network/wifi_0_with_x.svg",
@@ -119,7 +122,7 @@ preprocess_if_expr("preprocess_generated") {
"customize_themes/customize_themes.js",
"customize_themes/theme_icon.js",
"managed_dialog/managed_dialog.js",
- "managed_footnote/managed_footnote.m.js",
+ "managed_footnote/managed_footnote.js",
"omnibox/cr_autocomplete_match_list.js",
]
@@ -145,6 +148,7 @@ preprocess_if_expr("preprocess_generated") {
in_files += [
"chromeos/bluetooth/bluetooth_dialog.m.js",
"chromeos/cellular_setup/activation_code_page.m.js",
+ "chromeos/cellular_setup/activation_verification_page.m.js",
"chromeos/cellular_setup/base_page.m.js",
"chromeos/cellular_setup/button_bar.m.js",
"chromeos/cellular_setup/cellular_setup_delegate.m.js",
@@ -161,7 +165,7 @@ preprocess_if_expr("preprocess_generated") {
"chromeos/cellular_setup/profile_discovery_list_page.m.js",
"chromeos/cellular_setup/provisioning_page.m.js",
"chromeos/cellular_setup/psim_flow_ui.m.js",
- "chromeos/cellular_setup/cellular_eid_popup.m.js",
+ "chromeos/cellular_setup/cellular_eid_dialog.m.js",
"chromeos/cellular_setup/setup_loading_page.m.js",
"chromeos/cellular_setup/subflow_behavior.m.js",
"chromeos/cellular_setup/webview_post_util.m.js",
@@ -224,15 +228,12 @@ preprocess_if_expr("preprocess_generated") {
}
}
-preprocess_if_expr("preprocess_polymer2") {
- in_folder = "./"
- out_folder = "$preprocess_folder"
- out_manifest = "$target_gen_dir/$preprocess_polymer2_manifest"
- in_files = [
- "managed_footnote/managed_footnote.html",
- "managed_footnote/managed_footnote.js",
- ]
- if (is_chromeos_ash) {
+if (is_chromeos_ash) {
+ preprocess_if_expr("preprocess_polymer2") {
+ in_folder = "./"
+ out_folder = "$preprocess_folder"
+ out_manifest = "$target_gen_dir/$preprocess_polymer2_manifest"
+ in_files = []
if (!optimize_webui) {
in_files += [
"chromeos/bluetooth/bluetooth_dialog.html",
@@ -275,6 +276,8 @@ preprocess_if_expr("preprocess_polymer2") {
in_files += [
"chromeos/cellular_setup/activation_code_page.html",
"chromeos/cellular_setup/activation_code_page.js",
+ "chromeos/cellular_setup/activation_verification_page.html",
+ "chromeos/cellular_setup/activation_verification_page.js",
"chromeos/cellular_setup/base_page.html",
"chromeos/cellular_setup/base_page.js",
"chromeos/cellular_setup/button_bar.html",
@@ -306,8 +309,8 @@ preprocess_if_expr("preprocess_polymer2") {
"chromeos/cellular_setup/provisioning_page.js",
"chromeos/cellular_setup/psim_flow_ui.html",
"chromeos/cellular_setup/psim_flow_ui.js",
- "chromeos/cellular_setup/cellular_eid_popup.html",
- "chromeos/cellular_setup/cellular_eid_popup.js",
+ "chromeos/cellular_setup/cellular_eid_dialog.html",
+ "chromeos/cellular_setup/cellular_eid_dialog.js",
"chromeos/cellular_setup/setup_loading_page.html",
"chromeos/cellular_setup/setup_loading_page.js",
"chromeos/cellular_setup/subflow_behavior.html",
@@ -396,7 +399,6 @@ group("closure_compile") {
"customize_themes:closure_compile",
"managed_dialog:closure_compile",
"managed_footnote:closure_compile",
- "managed_footnote:closure_compile_module",
"omnibox:closure_compile",
]
@@ -410,7 +412,7 @@ group("polymer3_elements") {
"certificate_manager:web_components",
"customize_themes:web_components",
"managed_dialog:web_components",
- "managed_footnote:managed_footnote_module",
+ "managed_footnote:web_components",
"omnibox:web_components",
]
if (is_chromeos_ash) {
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
index 81306fb4ba5..677200e0b51 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
@@ -13,9 +13,10 @@ js_type_check("closure_compile_module") {
is_polymer3 = true
deps = [
":activation_code_page.m",
+ ":activation_verification_page.m",
":base_page.m",
":button_bar.m",
- ":cellular_eid_popup.m",
+ ":cellular_eid_dialog.m",
":cellular_setup.m",
":cellular_setup_delegate.m",
":cellular_types.m",
@@ -54,6 +55,17 @@ js_library("final_page.m") {
extra_deps = [ ":final_page_module" ]
}
+js_library("activation_verification_page.m") {
+ sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_verification_page.m.js" ]
+ deps = [
+ ":base_page.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_lottie:cr_lottie.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ ]
+ extra_deps = [ ":activation_verification_page_module" ]
+}
+
js_library("activation_code_page.m") {
sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.m.js" ]
deps = [
@@ -129,6 +141,7 @@ js_library("setup_loading_page.m") {
deps = [
":base_page.m",
":cellular_setup_delegate.m",
+ "//ui/webui/resources/cr_elements/cr_lottie:cr_lottie.m",
"//ui/webui/resources/js:assert.m",
]
extra_deps = [ ":setup_loading_page_module" ]
@@ -201,6 +214,7 @@ js_library("esim_flow_ui.m") {
sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.m.js" ]
deps = [
":activation_code_page.m",
+ ":activation_verification_page.m",
":cellular_setup_delegate.m",
":cellular_types.m",
":confirmation_code_page.m",
@@ -221,10 +235,10 @@ js_library("esim_flow_ui.m") {
externs_list = [ "$externs_path/metrics_private.js" ]
}
-js_library("cellular_eid_popup.m") {
- sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_popup.m.js" ]
+js_library("cellular_eid_dialog.m") {
+ sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.m.js" ]
deps = [ "//ui/webui/resources/js:i18n_behavior.m" ]
- extra_deps = [ ":cellular_eid_popup_module" ]
+ extra_deps = [ ":cellular_eid_dialog_module" ]
}
js_library("cellular_setup.m") {
@@ -245,9 +259,10 @@ js_library("cellular_setup.m") {
group("polymer3_elements") {
public_deps = [
":activation_code_page_module",
+ ":activation_verification_page_module",
":base_page_module",
":button_bar_module",
- ":cellular_eid_popup_module",
+ ":cellular_eid_dialog_module",
":cellular_setup_icons_module",
":cellular_setup_module",
":confirmation_code_page_module",
@@ -278,6 +293,14 @@ polymer_modulizer("final_page") {
auto_imports = cr_components_chromeos_auto_imports
}
+polymer_modulizer("activation_verification_page") {
+ js_file = "activation_verification_page.js"
+ html_file = "activation_verification_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = cr_components_chromeos_namespace_rewrites
+ auto_imports = cr_components_chromeos_auto_imports
+}
+
polymer_modulizer("activation_code_page") {
js_file = "activation_code_page.js"
html_file = "activation_code_page.html"
@@ -350,9 +373,9 @@ polymer_modulizer("esim_flow_ui") {
auto_imports = cr_components_chromeos_auto_imports
}
-polymer_modulizer("cellular_eid_popup") {
- js_file = "cellular_eid_popup.js"
- html_file = "cellular_eid_popup.html"
+polymer_modulizer("cellular_eid_dialog") {
+ js_file = "cellular_eid_dialog.js"
+ html_file = "cellular_eid_dialog.html"
html_type = "dom-module"
namespace_rewrites = cr_components_chromeos_namespace_rewrites
auto_imports = cr_components_chromeos_auto_imports
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html
index 11c8c0b61ad..c84c66833c8 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html
@@ -13,12 +13,26 @@
<dom-module id="activation-code-page">
<template>
<style include="iron-positioning">
- [slot='page-body'] {
- height: 300px;
- margin-top: -20px;
+ :host([expanded_]) #pageBody {
+ height: 340px;
+ transition-duration: 200ms;
+ }
+ :host(:not([expanded_])) #pageBody {
+ height: 282px;
+ transition-duration: 150ms;
+ }
+
+ :host([expanded_]) #esimQrCodeDetection {
+ height: 190px;
+ transition-duration: 200ms;
+ }
+ :host(:not([expanded_])) #esimQrCodeDetection {
+ height: 140px;
+ transition-duration: 150ms;
}
- :host {
- --activation-page-qr-code-detection-height: 155px;
+
+ :host(:not([expanded_])) #esimQrCodeDetection:focus-within {
+ background-color: var(--google-grey-refresh-300);
}
:host cr-button {
@@ -28,13 +42,19 @@
#esimQrCodeDetection {
background-color: var(--google-grey-refresh-100);
border-radius: 4px;
- height: var(--activation-page-qr-code-detection-height);
margin: 20px 0 20px 0;
overflow: hidden;
position: relative;
}
- cr-button {
+ paper-spinner-lite {
+ height: 20px;
+ margin-inline-end: 6px;
+ margin-top: 6px;
+ width: 20px;
+ }
+
+ cr-button:not(:focus) {
border: none;
box-shadow: none;
}
@@ -47,6 +67,15 @@
background-color: transparent;
}
+ cr-button[disabled] > iron-icon {
+ --iron-icon-fill-color: var(--google-grey-600);
+ }
+
+ .animate {
+ transition-property: height;
+ transition-timing-function: cubic-bezier(0.00, 0.00, 0.20, 1.00);
+ }
+
.center {
left: 50%;
position: absolute;
@@ -91,6 +120,20 @@
--iron-icon-fill-color: #1A73E8;
}
+ .hidden {
+ visibility: hidden;
+ }
+
+ .visually-hidden {
+ clip: rect(0 0 0 0);
+ clip-path: inset(50%);
+ height: 1px;
+ overflow: hidden;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+ }
+
#scanSucessHeader {
--iron-icon-fill-color: #1E8E3E;
margin-bottom: 8px;
@@ -101,6 +144,11 @@
font-size: medium;
}
+ #scanSuccessMessage::selection {
+ background-color: rgb(172, 206, 247);
+ color: green;
+ }
+
#scanFailureHeader {
margin-bottom: 4px;
}
@@ -132,17 +180,9 @@
--iron-icon-fill-color: #5F6368;
}
- paper-spinner-lite {
- height: 20px;
- position: absolute;
- right: 16px;
- top: 24px;
- width: 20px;
- }
-
#loadingMessage {
bottom: 0;
- color: var(--google-grey-refresh-500);
+ color: var(--google-grey-600);
font-size: var(--cr-form-field-label-font-size);
letter-spacing: .4px;
line-height: var(--cr-form-field-label-line-height);
@@ -150,18 +190,29 @@
}
#video {
- height: var(--activation-page-qr-code-detection-height);
+ height: inherit;
transform: rotateY(180deg);
}
+
+ #pageBody {
+ margin-top: -20px;
+ }
+
+ #startScanningButton {
+ max-width: 470px;
+ min-width: 345px;
+ text-align: center;
+ width: auto;
+ }
</style>
<base-page>
- <div slot="page-body">
- <span id="scanQrCodeDescription">
- [[getDescription_(showNoProfilesMessage, cameraCount_ )]]
+ <div slot="page-body" id="pageBody" class="animate">
+ <span aria-live="polite">
+ [[getDescription_(cameraCount_, qrCodeDetector_)]]
</span>
<template is="dom-if"
if="[[isScanningAvailable_(cameraCount_, qrCodeDetector_.*)]]" restamp>
- <div id="esimQrCodeDetection">
+ <div id="esimQrCodeDetection" class="animate">
<cr-button id="switchCameraButton"
on-click="onSwitchCameraButtonPressed_"
hidden$="[[isUiElementHidden_(UiElement.SWITCH_CAMERA, state_, cameraCount_)]]"
@@ -172,12 +223,16 @@
<video id="video" autoplay muted
hidden$="[[isUiElementHidden_(UiElement.VIDEO, state_)]]">
</video>
- <div class="center" id="startScanningContainer" class="blue-icon"
+ <template is="dom-if" if="[[qrCodeCameraA11yString_]]" restamp>
+ <div class="visually-hidden" aria-live="polite">
+ [[qrCodeCameraA11yString_]]
+ </div>
+ </template>
+ <div class="center blue-icon" id="startScanningContainer"
hidden$="[[isUiElementHidden_(UiElement.START_SCANNING, state_)]]">
<cr-button class="label"
id="startScanningButton"
on-click="startScanning_"
- aria-describedby="scanQrCodeDescription"
disabled="[[isUiElementDisabled_(UiElement.START_SCANNING, state_, showBusy)]]">
<iron-icon class="button-image" icon="cellular-setup:camera"></iron-icon>
[[i18n('useCamera')]]
@@ -202,12 +257,15 @@
[[i18n('scanQrCodeInvalid')]]
</span>
</div>
- <cr-button id="useCameraAgainButton" class="blue-icon"
- on-click="startScanning_"
- disabled="[[isUiElementDisabled_(UiElement.SCAN_SUCCESS, state_, showBusy)]]">
- <iron-icon class="button-image" icon="cellular-setup:camera"></iron-icon>
- [[i18n('qrCodeUseCameraAgain')]]
- </cr-button>
+ <template is="dom-if" restamp
+ if="[[!isUiElementHidden_(UiElement.SCAN_INSTALL_FAILURE, state_)]]">
+ <cr-button id="useCameraAgainButton" class="blue-icon"
+ on-click="startScanning_">
+ <iron-icon class="button-image" icon="cellular-setup:camera">
+ </iron-icon>
+ [[i18n('qrCodeUseCameraAgain')]]
+ </cr-button>
+ </template>
</div>
<div id="scanFailureContainer"
hidden$="[[isUiElementHidden_(UiElement.SCAN_FAILURE, state_)]]">
@@ -231,16 +289,19 @@
<div id="activationCodeContainer" class$="[[computeActivationCodeClass_(
cameraCount_, qrCodeDetector_.*)]]">
<cr-input id="activationCode"
- label="[[i18n('activationCode')]]"
- value="{{activationCode}}"
- disabled="[[showBusy]]"
- on-keydown="onKeyDown_"
- invalid="[[shouldActivationCodeInputBeInvalid_(state_)]]"
- error-message="[[i18n('scanQrCodeInvalid')]]">
+ label="[[i18n('activationCode')]]"
+ value="{{activationCode}}"
+ disabled="[[showBusy]]"
+ on-keydown="onKeyDown_"
+ invalid="[[shouldActivationCodeInputBeInvalid_(state_)]]"
+ error-message="[[i18n('scanQrCodeInvalid')]]">
+ <template is="dom-if" if="[[showBusy]]">
+ <div slot="suffix">
+ <paper-spinner-lite active>
+ </paper-spinner-lite>
+ </div>
+ </template>
</cr-input>
- <paper-spinner-lite active
- hidden$="[[!showBusy]]">
- </paper-spinner-lite>
<div id="loadingMessage" hidden$="[[!showBusy]]">
[[i18n('scanQrCodeLoading')]]
</div>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.js b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.js
index c6dc62de01b..22e6c60b3dc 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.js
@@ -81,10 +81,6 @@ Polymer({
value: UiElement,
},
- showNoProfilesMessage: {
- type: Boolean,
- },
-
/**
* @type {!PageState}
* @private
@@ -111,6 +107,26 @@ Polymer({
type: Object,
value: null,
},
+
+ /**
+ * If true, video is expanded.
+ */
+ expanded_: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
+
+ /**
+ * A11y string used to announce the current status of qr code camera
+ * detection. Used when device web cam is turned on and ready to scan,
+ * and also used after scan has been completed.
+ * @private
+ */
+ qrCodeCameraA11yString_: {
+ type: String,
+ value: '',
+ }
},
/**
@@ -180,7 +196,7 @@ Polymer({
detached() {
this.stopStream_(this.stream_);
if (this.qrCodeDetectorTimer_) {
- clearTimeout(this.qrCodeDetectorTimer_);
+ this.clearQrCodeDetectorTimer_();
}
this.mediaDevices_.removeEventListener(
'devicechange', this.updateCameraCount_.bind(this));
@@ -246,6 +262,13 @@ Polymer({
},
/**
+ * @returns {?number}
+ */
+ getQrCodeDetectorTimerForTest() {
+ return this.qrCodeDetectorTimer_;
+ },
+
+ /**
* @return {string}
* @private
*/
@@ -285,7 +308,7 @@ Polymer({
startScanning_() {
const oldStream = this.stream_;
if (this.qrCodeDetectorTimer_) {
- clearTimeout(this.qrCodeDetectorTimer_);
+ this.clearQrCodeDetectorTimer_();
}
const useUserFacingCamera =
@@ -337,7 +360,7 @@ Polymer({
const frame = await capturer.grabFrame();
const activationCode = await this.detectActivationCode_(frame);
if (activationCode) {
- clearTimeout(this.qrCodeDetectorTimer_);
+ this.clearQrCodeDetectorTimer_();
this.activationCode = activationCode;
this.stopStream_(this.stream_);
this.state_ = PageState.SCANNING_SUCCESS;
@@ -375,6 +398,12 @@ Polymer({
this.fire('activation-code-updated', {activationCode: activationCode});
},
+ /** @private */
+ clearQrCodeDetectorTimer_() {
+ clearTimeout(this.qrCodeDetectorTimer_);
+ this.qrCodeDetectorTimer_ = null;
+ },
+
/**
* @param {string} activationCode
* @return {string|null} The validated activation code or null if it's
@@ -417,17 +446,38 @@ Polymer({
/** @private */
onStateChanged_() {
+ this.qrCodeCameraA11yString_ = '';
if (this.state_ !== PageState.MANUAL_ENTRY_INSTALL_FAILURE &&
this.state_ !== PageState.SCANNING_INSTALL_FAILURE) {
this.showError = false;
}
if (this.state_ === PageState.MANUAL_ENTRY) {
+ // Clear |qrCodeDetectorTimer_| before closing video stream, prevents
+ // image capturer from going into an inactive state and throwing errors
+ // when |grabFrame()| is called.
+ this.clearQrCodeDetectorTimer_();
+
// Wait for the video element to be hidden by isUiElementHidden() before
// stopping the stream or the user will see a flash.
Polymer.RenderStatus.afterNextRender(this, () => {
this.stopStream_(this.stream_);
});
}
+
+ if (this.state_ === PageState.SCANNING_USER_FACING ||
+ this.state_ === PageState.SCANNING_ENVIRONMENT_FACING) {
+ this.qrCodeCameraA11yString_ = this.i18n('qrCodeA11YCameraOn');
+ this.expanded_ = true;
+ return;
+ }
+
+ // Focus on the next button after scanning is successful.
+ if (this.state_ === PageState.SCANNING_SUCCESS) {
+ this.qrCodeCameraA11yString_ = this.i18n('qrCodeA11YCameraScanSuccess');
+ this.fire('focus-default-button');
+ }
+
+ this.expanded_ = false;
},
/**
@@ -437,9 +487,16 @@ Polymer({
onKeyDown_(e) {
if (e.key === 'Enter') {
this.fire('forward-navigation-requested');
- } else {
- this.state_ = PageState.MANUAL_ENTRY;
}
+
+ // Prevents barcode detector video from closing if user tabs through
+ // window. We should only close barcode detector window if user
+ // types in activation code input.
+ if (e.key === 'Tab') {
+ return;
+ }
+
+ this.state_ = PageState.MANUAL_ENTRY;
e.stopPropagation();
},
@@ -504,8 +561,7 @@ Polymer({
if (!this.isScanningAvailable_()) {
return this.i18n('scanQRCodeEnterActivationCode');
}
- return this.showNoProfilesMessage ? this.i18n('scanQRCodeNoProfiles') :
- this.i18n('scanQRCode');
+ return this.i18n('scanQRCode');
},
/**
@@ -515,5 +571,5 @@ Polymer({
*/
shouldActivationCodeInputBeInvalid_(state) {
return state === PageState.MANUAL_ENTRY_INSTALL_FAILURE;
- }
+ },
});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_verification_page.html b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_verification_page.html
new file mode 100644
index 00000000000..6bdfa3101fb
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_verification_page.html
@@ -0,0 +1,40 @@
+<link rel="import" href="../../../html/polymer.html">
+
+<link rel="import" href="base_page.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
+<link rel="import" href="../../../html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_lottie/cr_lottie.html">
+
+<dom-module id="activation-verification-page">
+ <template>
+ <style>
+ #pageBody {
+ height: 282px;
+ margin-top: -20px;
+ overflow: hidden;
+ }
+
+ #animationContainer {
+ display: flex;
+ height: 216px;
+ margin-bottom: 30px;
+ margin-top: 24px;
+ }
+
+ cr-lottie {
+ margin: auto;
+ }
+ </style>
+
+ <base-page>
+ <div slot="page-body" id="pageBody" class="layout vertical center-center">
+ <span>[[i18n('verifyingActivationCode')]]</span>
+ <div id="animationContainer">
+ <cr-lottie id="spinner" animation-url="spinner.json" autoplay>
+ </cr-lottie>
+ </div>
+ </div>
+ </base-page>
+ </template>
+ <script src="activation_verification_page.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_verification_page.js b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_verification_page.js
new file mode 100644
index 00000000000..5868da108e2
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_verification_page.js
@@ -0,0 +1,13 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * This page is displayed when the activation code is being verified, and
+ * an ESim profile is being installed.
+ */
+Polymer({
+ is: 'activation-verification-page',
+
+ behaviors: [I18nBehavior],
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/base_page.html b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/base_page.html
index 2f8fc2a6930..854094f228c 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/base_page.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/base_page.html
@@ -8,6 +8,12 @@
<dom-module id="base-page">
<template>
<style include="iron-positioning">
+ :host {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ }
+
#title {
color: var(--google-grey-900);
font-weight: normal;
@@ -15,13 +21,13 @@
}
#message {
+ height: var(--base-page-message-height, auto);
margin-bottom: 20px;
}
:host ::slotted([slot='page-body']) {
display: block;
- height: 256px;
- width: 100%;
+ flex: 1 1 auto;
}
#message iron-icon {
@@ -31,7 +37,7 @@
<template is="dom-if" if="[[isTitleShown_(title)]]" restamp>
<h3 id="title">[[getTitle_(title)]]</h3>
</template>
- <div id="message">
+ <div id="message" aria-live="polite" aria-atomic="true">
<iron-icon
icon$="cellular-setup:[[messageIcon]]"
hidden$="[[!isMessageIconShown_(messageIcon)]]">
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/button_bar.html b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/button_bar.html
index 65323d312d2..da3132b49d0 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/button_bar.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/button_bar.html
@@ -15,7 +15,11 @@
:host {
display: flex;
justify-content: flex-end;
- padding: 10px 0;
+ padding: 10px 0 20px 0;
+ }
+
+ #forward:focus {
+ box-shadow: 0 0 0 2px var(--focus-shadow-color);
}
#flex {
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.html b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.html
new file mode 100644
index 00000000000..95d7cedf562
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.html
@@ -0,0 +1,71 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+
+<dom-module id="cellular-eid-dialog">
+ <template>
+ <style include="cr-shared-style iron-flex">
+ :host {
+ --cr-dialog-body-padding-horizontal: 24px;
+ --cr-dialog-button-container-padding-bottom: 20px;
+ --cr-dialog-button-container-padding-horizontal: 24px;
+ --cr-dialog-width: 320px;
+ --cr-dialog-title-slot-padding-bottom: 12px;
+ --cr-dialog-title-slot-padding-end: 24px;
+ --cr-dialog-title-slot-padding-start: 24px;
+ --cr-dialog-title-font-size: calc(16 / 13 * 100%);
+ }
+
+ .cellular-network-list-header {
+ border-top: var(--cr-separator-line);
+ padding: 16px 0 8px 0;
+ }
+
+ .cellular-network-content {
+ margin: 8px 0 8px 32px;
+ }
+
+ .cellular-not-setup {
+ color: var(--google-grey-700);
+ font-size: smaller;
+ margin-bottom: 16px;
+ }
+
+ #qrCodeCanvas {
+ display: block;
+ margin: 20px auto 16px auto;
+ max-width: calc(var(--cr-dialog-width) -
+ var(--cr-dialog-title-slot-padding-start) -
+ var(--cr-dialog-title-slot-padding-end));
+ }
+
+ #eid {
+ margin-top: 16px;
+ }
+ </style>
+ <cr-dialog id="eidDialog" show-on-attach>
+ <div slot="title">[[i18n('eidPopupTitle')]]</div>
+ <div slot="body" aria-label="[[getA11yLabel_(eid_)]]">
+ <div id="eidDescription" aria-hidden="true">
+ [[i18n('eidPopupDescription')]]
+ </div>
+ <div id="eid" aria-hidden="true">[[eid_]]</div>
+ <canvas id="qrCodeCanvas"
+ width="[[canvasSize_]]"
+ height="[[canvasSize_]]">
+ </canvas>
+ </div>
+ <div slot="button-container">
+ <cr-button id="done" class="action-button"
+ on-click="onDonePressed_">
+ [[i18n('done')]]
+ </cr-button>
+ </div>
+ </cr-dialog>
+ </template>
+ <script src="cellular_eid_dialog.js"></script>
+</dom-module> \ No newline at end of file
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_popup.js b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.js
index 983d4bbe040..f6a23de61f3 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_popup.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.js
@@ -8,13 +8,11 @@
// The size of each tile in pixels.
const QR_CODE_TILE_SIZE = 5;
-// Amount of padding around the QR code in pixels.
-const QR_CODE_PADDING = 4 * QR_CODE_TILE_SIZE;
// Styling for filled tiles in the QR code.
const QR_CODE_FILL_STYLE = '#000000';
Polymer({
- is: 'cellular-eid-popup',
+ is: 'cellular-eid-dialog',
behaviors: [
I18nBehavior,
@@ -22,7 +20,7 @@ Polymer({
properties: {
/**
- * The euicc object whose EID and QRCode should be shown in the popup.
+ * The euicc object whose EID and QRCode should be shown in the dialog.
*/
euicc: Object,
@@ -45,16 +43,14 @@ Polymer({
}
this.euicc.getEidQRCode().then(this.updateQRCode_.bind(this));
this.euicc.getProperties().then(this.updateEid_.bind(this));
- },
-
- /** @override */
- focus() {
- this.$$('.dialog').focus();
+ requestAnimationFrame(() => {
+ this.$.done.focus();
+ });
},
/**@private */
- onCloseTap_() {
- this.fire('close-eid-popup');
+ onDonePressed_() {
+ this.$.eidDialog.close();
},
/**
@@ -65,8 +61,7 @@ Polymer({
if (!response || !response.qrCode) {
return;
}
- this.canvasSize_ =
- response.qrCode.size * QR_CODE_TILE_SIZE + 2 * QR_CODE_PADDING;
+ this.canvasSize_ = response.qrCode.size * QR_CODE_TILE_SIZE;
Polymer.dom.flush();
const context = this.getCanvasContext_();
context.clearRect(0, 0, this.canvasSize_, this.canvasSize_);
@@ -76,8 +71,7 @@ Polymer({
for (let y = 0; y < response.qrCode.size; y++) {
if (response.qrCode.data[index]) {
context.fillRect(
- x * QR_CODE_TILE_SIZE + QR_CODE_PADDING,
- y * QR_CODE_TILE_SIZE + QR_CODE_PADDING, QR_CODE_TILE_SIZE,
+ x * QR_CODE_TILE_SIZE, y * QR_CODE_TILE_SIZE, QR_CODE_TILE_SIZE,
QR_CODE_TILE_SIZE);
}
index++;
@@ -113,5 +107,14 @@ Polymer({
*/
setCanvasContextForTest(canvasContext) {
this.canvasContext_ = canvasContext;
- }
+ },
+
+ /**
+ * @param {string} eid
+ * @return {string}
+ * @private
+ */
+ getA11yLabel_(eid) {
+ return this.i18n('eidPopupA11yLabel', eid);
+ },
});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_popup.html b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_popup.html
deleted file mode 100644
index b045ae54b57..00000000000
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_popup.html
+++ /dev/null
@@ -1,96 +0,0 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
-<link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
-<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-
-<dom-module id="cellular-eid-popup">
- <template>
- <style include="cr-shared-style iron-flex">
- :host {
- background-color: white;
- border-radius: 4px;
- box-shadow: 0 2px 5px rgba(0,0,0,0.18);
- margin: 34px 0 0 12px;
- position: absolute;
- width: 275px;
- z-index: 1;
- }
-
- .cellular-network-list-header {
- border-top: var(--cr-separator-line);
- padding: 16px 0 8px 0;
- }
-
- .body {
- margin-top: 6px;
- }
-
- .cellular-network-content {
- margin: 8px 0 8px 32px;
- }
-
- .cellular-not-setup {
- color: var(--google-grey-700);
- font-size: smaller;
- margin-bottom: 16px;
- }
-
- .header {
- display: flex;
- justify-content: space-between;
- }
-
- .title {
- align-self: center;
- }
-
- #container {
- padding: 8px 16px;
- }
-
- #closeBtn {
- align-self: center;
- cursor: pointer;
- }
-
- #qrCodeCanvas {
- width: 100%;
- }
-
- #eid {
- margin-top: 15px;
- }
- </style>
- <div id="container"
- class="dialog"
- tabindex="1"
- aria-labelledby="eidTitle"
- aria-describedby="eidDescription">
- <div class="header">
- <div id="eidTitle" class="title" arian-hidden="true">
- [[i18n('eidPopupTitle')]]
- </div>
- <cr-icon-button
- id="eidPopupCloseIcon"
- iron-icon="cr:close"
- title="[[i18n('closeEidPopupButtonLabel')]]"
- aria-label="[[i18n('closeEidPopupButtonLabel')]]"
- on-click="onCloseTap_">
- </cr-icon-button>
- </div>
- <div class="body">
- <div id="eidDescription" arian-hidden="true">
- [[i18n('eidPopupDescription')]]
- </div>
- <div id="eid">[[eid_]]</div>
- <canvas id="qrCodeCanvas"
- width="[[canvasSize_]]"
- height="[[canvasSize_]]">
- </canvas>
- </div>
- </div>
- </template>
- <script src="cellular_eid_popup.js"></script>
-</dom-module> \ No newline at end of file
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.html b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.html
index 830547c73b0..464d0994d64 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.html
@@ -31,6 +31,7 @@
button-state="{{buttonState_}}"
delegate="[[delegate]]"
id="esim-flow-ui"
+ header="{{flowHeader}}"
forward-button-label="{{forwardButtonLabel_}}">
</esim-flow-ui>
</template>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.js b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.js
index 3968c19e336..e2c7b944dda 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.js
@@ -15,9 +15,24 @@ Polymer({
/** @type {!cellular_setup.CellularSetupDelegate} */
delegate: Object,
+ /**
+ * Title of the flow, shown at the top of the dialog. No title shown if the
+ * string is empty.
+ */
flowTitle: {
type: String,
notify: true,
+ value: '',
+ },
+
+ /**
+ * Header for the flow, shown below the title. No header shown if the string
+ * is empty.
+ */
+ flowHeader: {
+ type: String,
+ notify: true,
+ value: '',
},
/**
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup_icons.html b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup_icons.html
index c68f68cdbb1..23e112bc3aa 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup_icons.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup_icons.html
@@ -13,6 +13,7 @@
<g id="switch-camera" viewBox="0 0 20 20"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 9V7H4.802A5.996 5.996 0 0 1 10 4a6 6 0 0 1 5.917 5h2.021c-.491-3.945-3.853-7-7.93-7a7.992 7.992 0 0 0-6.009 2.712L4 3H2v6h5zm5.938 2v2h2.198a5.996 5.996 0 0 1-5.198 3 6 6 0 0 1-5.917-5H2c.492 3.945 3.853 7 7.93 7a7.992 7.992 0 0 0 6.009-2.712V17h2v-6h-5zM10 12a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"></g>
<g id="try-again" viewBox="0 0 20 20"><path path fill-rule="evenodd" clip-rule="evenodd" d="M10 3C6.136 3 3 6.136 3 10C3 13.864 6.136 17 10 17C12.1865 17 14.1399 15.9959 15.4239 14.4239L13.9984 12.9984C13.0852 14.2129 11.6325 15 10 15C7.24375 15 5 12.7563 5 10C5 7.24375 7.24375 5 10 5C11.6318 5 13.0839 5.78641 13.9972 7H11V9H17V3H15V5.10253C13.7292 3.80529 11.9581 3 10 3Z"></g>
<g id="warning" viewBox="0 0 20 20"><path d="M9 12H11V8H9V12Z"></path><path d="M11 15H9V13H11V15Z"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M9.13177 2.50386C9.51566 1.83205 10.4844 1.83205 10.8683 2.50386L18.8683 16.5039C19.2492 17.1705 18.7678 18 18 18H2.00001C1.23219 18 0.750823 17.1705 1.13177 16.5039L9.13177 2.50386ZM10 5.01556L3.72321 16H16.2768L10 5.01556Z"></g>
+ <g id="info" viewBox="0 0 24 24"><path d="M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 9h2V7h-2v2z"></path></g>
</defs>
</svg>
</iron-iconset-svg> \ No newline at end of file
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/confirmation_code_page.html b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/confirmation_code_page.html
index c814032de0e..5cd1eda37e4 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/confirmation_code_page.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/confirmation_code_page.html
@@ -9,6 +9,7 @@
<template>
<style include="iron-flex iron-positioning">
[slot='page-body'] {
+ height: 282px;
margin-top: -20px;
}
@@ -45,7 +46,7 @@
#loadingMessage {
bottom: 0;
- color: var(--google-grey-refresh-500);
+ color: var(--google-grey-600);
font-size: var(--cr-form-field-label-font-size);
letter-spacing: .4px;
line-height: var(--cr-form-field-label-line-height);
@@ -54,7 +55,9 @@
</style>
<base-page>
<div slot="page-body">
- <div id="description">[[i18n('confirmationCodeMessage')]]</div>
+ <div aria-live="polite">
+ [[i18n('confirmationCodeMessage')]]
+ </div>
<div id="outerDiv" class="layout horizontal center">
<div class="container">
<div id="details" hidden$="[[!shouldShowProfileDetails_(profile)]]">
@@ -68,7 +71,6 @@
<cr-input id="confirmationCode"
label="[[i18n('confirmationCodeInput')]]"
value="{{confirmationCode}}"
- aria-describedby="description"
error-message="[[i18n('confirmationCodeError')]]"
invalid="[[showError]]"
disabled="[[showBusy]]"
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.html b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.html
index 9f077302b5d..21614dde755 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.html
@@ -12,6 +12,7 @@
<link rel="import" href="cellular_setup_delegate.html">
<link rel="import" href="setup_loading_page.html">
<link rel="import" href="activation_code_page.html">
+<link rel="import" href="activation_verification_page.html">
<link rel="import" href="final_page.html">
<link rel="import" href="profile_discovery_list_page.html">
<link rel="import" href="confirmation_code_page.html">
@@ -29,9 +30,7 @@
<iron-pages attr-for-selected="id"
selected="[[selectedESimPageName_]]">
<setup-loading-page id="profileLoadingPage"
- delegate="[[delegate]]"
- loading-message="[[i18n('eSimProfileDetectMessage')]]"
- state="[[getLoadingPageState_(hasHadActivePSimNetwork_)]]">
+ loading-message="[[getLoadingMessage_(hasHadActiveCellularNetwork_)]]">
</setup-loading-page>
<profile-discovery-list-page id="profileDiscoveryPage"
pending-profiles="[[pendingProfiles_]]"
@@ -40,10 +39,12 @@
</profile-discovery-list-page>
<activation-code-page id="activationCodePage"
activation-code="{{activationCode_}}"
- show-no-profiles-message="[[getShowNoProfilesMessage_(pendingProfiles_)]]"
show-error="{{showError_}}"
show-busy="[[shouldShowSubpageBusy_(state_)]]">
</activation-code-page>
+ <setup-loading-page id="activationVerificationPage"
+ loading-message="[[i18n('verifyingActivationCode')]]">
+ </setup-loading-page>
<confirmation-code-page id="confirmationCodePage"
confirmation-code="{{confirmationCode_}}"
profile="[[selectedProfile_]]"
@@ -51,11 +52,11 @@
show-busy="[[shouldShowSubpageBusy_(state_)]]">
</confirmation-code-page>
<final-page
- id="finalPage"
- delegate="[[delegate]]"
- show-error="[[showError_]]"
- message="[[i18n('eSimFinalPageMessage')]]"
- error-message="[[i18n('eSimFinalPageErrorMessage')]]">
+ id="finalPage"
+ delegate="[[delegate]]"
+ show-error="[[showError_]]"
+ message="[[i18n('eSimFinalPageMessage')]]"
+ error-message="[[i18n('eSimFinalPageErrorMessage')]]">
</final-page>
</iron-pages>
</template>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.js b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.js
index 4b33637f8f7..891470fbecf 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.js
@@ -8,6 +8,7 @@ cr.define('cellular_setup', function() {
PROFILE_LOADING: 'profileLoadingPage',
PROFILE_DISCOVERY: 'profileDiscoveryPage',
ACTIVATION_CODE: 'activationCodePage',
+ ACTIVATION_VERIFCATION: 'activationVerificationPage',
CONFIRMATION_CODE: 'confirmationCodePage',
FINAL: 'finalPage',
};
@@ -69,6 +70,16 @@ cr.define('cellular_setup', function() {
/** @type {!cellular_setup.CellularSetupDelegate} */
delegate: Object,
+ /**
+ * Header shown at the top of the flow. No header shown if the string is
+ * empty.
+ */
+ header: {
+ type: String,
+ notify: true,
+ computed: 'computeHeader_(selectedESimPageName_, showError_)',
+ },
+
forwardButtonLabel: {
type: String,
notify: true,
@@ -133,7 +144,7 @@ cr.define('cellular_setup', function() {
},
/** @private */
- hasHadActivePSimNetwork_: {
+ hasHadActiveCellularNetwork_: {
type: Boolean,
value: false,
},
@@ -354,9 +365,11 @@ cr.define('cellular_setup', function() {
break;
case ESimUiState.ACTIVATION_CODE_ENTRY:
case ESimUiState.ACTIVATION_CODE_ENTRY_READY:
- case ESimUiState.ACTIVATION_CODE_ENTRY_INSTALLING:
this.selectedESimPageName_ = ESimPageName.ACTIVATION_CODE;
break;
+ case ESimUiState.ACTIVATION_CODE_ENTRY_INSTALLING:
+ this.selectedESimPageName_ = ESimPageName.ACTIVATION_VERIFCATION;
+ break;
case ESimUiState.CONFIRMATION_CODE_ENTRY:
case ESimUiState.CONFIRMATION_CODE_ENTRY_READY:
case ESimUiState.CONFIRMATION_CODE_ENTRY_INSTALLING:
@@ -433,6 +446,10 @@ cr.define('cellular_setup', function() {
this.delegate.shouldShowCancelButton() ?
cellularSetup.ButtonState.ENABLED :
cellularSetup.ButtonState.HIDDEN;
+ const cancelButtonStateIfDisabled =
+ this.delegate.shouldShowCancelButton() ?
+ cellularSetup.ButtonState.DISABLED :
+ cellularSetup.ButtonState.HIDDEN;
switch (this.state_) {
case ESimUiState.PROFILE_SEARCH:
this.forwardButtonLabel = this.i18n('next');
@@ -454,7 +471,7 @@ cr.define('cellular_setup', function() {
break;
case ESimUiState.ACTIVATION_CODE_ENTRY_INSTALLING:
buttonState = this.generateButtonStateForActivationPage_(
- /*enableForwardBtn*/ false, cancelButtonStateIfEnabled,
+ /*enableForwardBtn*/ false, cancelButtonStateIfDisabled,
/*isInstalling*/ true);
break;
case ESimUiState.CONFIRMATION_CODE_ENTRY:
@@ -469,7 +486,7 @@ cr.define('cellular_setup', function() {
break;
case ESimUiState.CONFIRMATION_CODE_ENTRY_INSTALLING:
buttonState = this.generateButtonStateForConfirmationPage_(
- /*enableForwardBtn*/ false, cancelButtonStateIfEnabled,
+ /*enableForwardBtn*/ false, cancelButtonStateIfDisabled,
/*isInstalling*/ true);
break;
case ESimUiState.PROFILE_SELECTION:
@@ -485,7 +502,7 @@ cr.define('cellular_setup', function() {
case ESimUiState.PROFILE_SELECTION_INSTALLING:
buttonState = {
backward: cellularSetup.ButtonState.HIDDEN,
- cancel: cancelButtonStateIfEnabled,
+ cancel: cancelButtonStateIfDisabled,
forward: cellularSetup.ButtonState.DISABLED,
};
break;
@@ -635,19 +652,14 @@ cr.define('cellular_setup', function() {
}
},
- /** @private */
- getShowNoProfilesMessage_() {
- return !(this.pendingProfiles_ && this.pendingProfiles_.length > 0);
- },
-
/** NetworkListenerBehavior override */
onNetworkStateListChanged() {
- hasActivePSimNetwork().then((hasActive) => {
- // If hasHadActivePSimNetwork_ has been set to true, don't set to false
- // again as we should show the cellular disconnect warning for the
+ hasActiveCellularNetwork().then((hasActive) => {
+ // If hasHadActiveCellularNetwork_ has been set to true, don't set to
+ // false again as we should show the cellular disconnect warning for the
// duration of the flow's lifecycle.
if (hasActive) {
- this.hasHadActivePSimNetwork_ = hasActive;
+ this.hasHadActiveCellularNetwork_ = hasActive;
}
});
},
@@ -659,14 +671,24 @@ cr.define('cellular_setup', function() {
this.state_ === ESimUiState.PROFILE_SELECTION_INSTALLING;
},
+ /** @private */
+ getLoadingMessage_() {
+ return this.hasHadActiveCellularNetwork_ ?
+ this.i18n('eSimProfileDetectDuringActiveCellularConnectionMessage') :
+ this.i18n('eSimProfileDetectMessage');
+ },
+
/**
- * @param {boolean} hasActivePSimNetwork
+ * @return {string}
* @private
*/
- getLoadingPageState_(hasActivePSimNetwork) {
- return hasActivePSimNetwork ?
- LoadingPageState.CELLULAR_DISCONNECT_WARNING :
- LoadingPageState.LOADING;
+ computeHeader_() {
+ if (this.selectedESimPageName_ === ESimPageName.FINAL &&
+ !this.showError_) {
+ return this.i18n('eSimFinalPageSuccessHeader');
+ }
+
+ return '';
},
});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_utils.js b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_utils.js
index 4f5613aedad..85941bc472b 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_utils.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_utils.js
@@ -15,20 +15,41 @@ cr.define('cellular_setup', function() {
*/
/* #export */ function getPendingESimProfiles(euicc) {
return euicc.getProfileList().then(response => {
- return filterForPendingProfiles_(response.profiles);
+ return filterByProfileProperties_(response.profiles, properties => {
+ return properties.state ===
+ chromeos.cellularSetup.mojom.ProfileState.kPending;
+ });
});
}
/**
+ * Fetches the EUICC's eSIM profiles with status not 'Pending'.
+ * @param {!chromeos.cellularSetup.mojom.EuiccRemote} euicc
+ * @return {!Promise<!Array<!chromeos.cellularSetup.mojom.ESimProfileRemote>>}
+ */
+ /* #export */ function getNonPendingESimProfiles(euicc) {
+ return euicc.getProfileList().then(response => {
+ return filterByProfileProperties_(response.profiles, properties => {
+ return properties.state !==
+ chromeos.cellularSetup.mojom.ProfileState.kPending;
+ });
+ });
+ }
+
+ /**
+ * Filters each profile in profiles by callback, which is given the profile's
+ * properties as an argument and returns true or false. Does not guarantee
+ * that profiles retains the same order.
* @private
* @param {!Array<!chromeos.cellularSetup.mojom.ESimProfileRemote>} profiles
+ * @param {function(chromeos.cellularSetup.mojom.ESimProfileProperties)}
+ * callback
* @return {!Promise<Array<!chromeos.cellularSetup.mojom.ESimProfileRemote>>}
*/
- function filterForPendingProfiles_(profiles) {
+ function filterByProfileProperties_(profiles, callback) {
const profilePromises = profiles.map(profile => {
return profile.getProperties().then(response => {
- if (response.properties.state !==
- chromeos.cellularSetup.mojom.ProfileState.kPending) {
+ if (!callback(response.properties)) {
return null;
}
return profile;
@@ -42,6 +63,19 @@ cr.define('cellular_setup', function() {
}
/**
+ * @return {!Promise<number>}
+ */
+ /* #export */ function getNumESimProfiles() {
+ return getEuicc()
+ .then(euicc => {
+ return euicc.getProfileList();
+ })
+ .then(response => {
+ return response.profiles.length;
+ });
+ }
+
+ /**
* Returns the Euicc that should be used for eSim operations or null
* if there is none available.
* @return {!Promise<?chromeos.cellularSetup.mojom.EuiccRemote>}
@@ -62,12 +96,14 @@ cr.define('cellular_setup', function() {
}
/**
- * Returns the eSIM profile with iccid in the first EUICC and null if none
- * found.
* @param {string} iccid
- * @return {!Promise<?chromeos.cellularSetup.mojom.ESimProfileRemote>}
+ * @return {!Promise<?{
+ * profileRemote: chromeos.cellularSetup.mojom.ESimProfileRemote,
+ * profileProperties: chromeos.cellularSetup.mojom.ESimProfileProperties
+ * }>} Returns a eSIM profile remote and profile properties for given
+ * |iccid|.
*/
- /* #export */ async function getESimProfile(iccid) {
+ async function getESimProfileDetails(iccid) {
if (!iccid) {
return null;
}
@@ -80,19 +116,54 @@ cr.define('cellular_setup', function() {
const esimProfilesRemotes = await euicc.getProfileList();
for (const profileRemote of esimProfilesRemotes.profiles) {
- const profileProperties = await profileRemote.getProperties();
+ const profilePropertiesResponse = await profileRemote.getProperties();
+ if (!profilePropertiesResponse || !profilePropertiesResponse.properties) {
+ return null;
+ }
- if (profileProperties.properties.iccid === iccid) {
- return profileRemote;
+ const profileProperties = profilePropertiesResponse.properties;
+ if (profileProperties.iccid === iccid) {
+ return {profileRemote, profileProperties};
}
}
return null;
}
+ /**
+ * Returns the eSIM profile with iccid in the first EUICC or null if none
+ * is found.
+ * @param {string} iccid
+ * @return {!Promise<?chromeos.cellularSetup.mojom.ESimProfileRemote>}
+ */
+ /* #export */ async function getESimProfile(iccid) {
+ const details = await getESimProfileDetails(iccid);
+ if (!details) {
+ return null;
+ }
+ return details.profileRemote;
+ }
+
+ /**
+ * Returns properties for eSIM profile with iccid in the first EUICC or null
+ * if none is found.
+ * @param {string} iccid
+ * @return {!Promise<?chromeos.cellularSetup.mojom.ESimProfileProperties>}
+ */
+ /* #export */ async function getESimProfileProperties(iccid) {
+ const details = await getESimProfileDetails(iccid);
+ if (!details) {
+ return null;
+ }
+ return details.profileProperties;
+ }
+
// #cr_define_end
return {
getEuicc,
getESimProfile,
+ getESimProfileProperties,
getPendingESimProfiles,
+ getNonPendingESimProfiles,
+ getNumESimProfiles,
};
});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page.html b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page.html
index 262113316ef..97cbedd7db9 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page.html
@@ -14,6 +14,7 @@
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
+ height: 242px;
}
.error[slot='page-body'] {
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.html b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.html
index 057152092b6..809db7dc92b 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.html
@@ -22,13 +22,18 @@
flex: 1 1 auto;
flex-direction: column;
}
+
+ iron-pages {
+ height: 400px;
+ }
</style>
<iron-pages attr-for-selected="id"
selected="[[selectedPSimPageName_]]"
selected-item="{{selectedPage_}}">
<setup-loading-page id="simDetectPage"
- delegate="[[delegate]]" state="[[getLoadingPageState_(state_)]]"
- loading-message="[[i18n('establishNetworkConnectionMessage')]]">
+ loading-title="[[getLoadingTitle_(state_)]]"
+ loading-message="[[getLoadingMessage_(state_)]]"
+ is-sim-detect-error="[[isSimDetectError_(state_)]]">
</setup-loading-page>
<provisioning-page id="provisioningPage"
delegate="[[delegate]]" show-error="{{showError_}}"
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.js b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.js
index 295ad42fef7..860748a72e9 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.js
@@ -304,6 +304,7 @@ cr.define('cellularSetup', function() {
this.state_ = PSimUIState.STARTING_ACTIVATION;
this.startActivationAttempts_ = 0;
this.updateButtonBarState_();
+ this.fire('focus-default-button');
},
navigateForward() {
@@ -575,17 +576,28 @@ cr.define('cellularSetup', function() {
PSimUIState.ACTIVATION_FAILURE;
},
- /**
- * @return {LoadingPageState}
- * @private
- */
- getLoadingPageState_() {
+ /** @return {string} */
+ getLoadingMessage_() {
if (this.state_ === PSimUIState.TIMEOUT_START_ACTIVATION) {
- return LoadingPageState.SIM_DETECT_ERROR;
+ return this.i18n('simDetectPageErrorMessage');
} else if (this.state_ === PSimUIState.FINAL_TIMEOUT_START_ACTIVATION) {
- return LoadingPageState.FINAL_SIM_DETECT_ERROR;
+ return this.i18n('simDetectPageFinalErrorMessage');
}
- return LoadingPageState.LOADING;
+ return this.i18n('establishNetworkConnectionMessage');
+ },
+
+ /** @return {boolean} */
+ isSimDetectError_() {
+ return this.state_ === PSimUIState.TIMEOUT_START_ACTIVATION ||
+ this.state_ === PSimUIState.FINAL_TIMEOUT_START_ACTIVATION;
+ },
+
+ /** @return {string} */
+ getLoadingTitle_() {
+ if (this.delegate.shouldShowPageTitle() && this.isSimDetectError_()) {
+ return this.i18n('simDetectPageErrorTitle');
+ }
+ return '';
},
});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/setup_loading_page.html b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/setup_loading_page.html
index 3b03de44d5b..e09c8b0a788 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/setup_loading_page.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/setup_loading_page.html
@@ -6,15 +6,17 @@
<link rel="import" href="../../../cr_elements/hidden_style_css.html">
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_lottie/cr_lottie.html">
<dom-module id="setup-loading-page">
<template>
<style include="iron-flex cr-hidden-style">
- paper-spinner-lite {
- height: 32px;
- margin-bottom: 8px;
- width: 32px;
+ #animationContainer {
+ align-items: flex-end;
+ display: flex;
+ height: 216px;
+ justify-content: center;
+ margin-bottom: 54px;
}
#simDetectError {
@@ -26,20 +28,28 @@
width: 100%;
}
- #networkConnectionMessage {
- text-align: center;
+ #pageBody {
+ height: 222px;
+ }
+
+ cr-lottie {
+ height: 85%;
+ }
+
+ base-page {
+ --base-page-message-height: 40px;
}
</style>
- <base-page title="[[getTitle_(state)]]"
- message="[[getMessage_(state)]]"
- message-icon="[[getMessageIcon_(state)]]">
- <div slot="page-body" class="layout vertical center-center">
- <paper-spinner-lite active hidden$="[[shouldShowSimDetectError_(state)]]">
- </paper-spinner-lite>
- <div id="networkConnectionMessage" hidden$="[[shouldShowSimDetectError_(state)]]">
- [[loadingMessage]]
+ <base-page title="[[loadingTitle]]" message="[[loadingMessage]]">
+ <div slot="page-body" id="pageBody" class="layout vertical center-center">
+ <template is="dom-if" if="[[!isSimDetectError]]" restamp>
+ <div id="animationContainer">
+ <cr-lottie id="spinner" animation-url="spinner.json" autoplay>
+ </cr-lottie>
+ </div>
+ </template>
+ <div id="simDetectError" hidden$="[[!isSimDetectError]]">
</div>
- <div id="simDetectError" hidden$="[[!shouldShowSimDetectError_(state)]]"></div>
</div>
</base-page>
</template>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/setup_loading_page.js b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/setup_loading_page.js
index 4656295e61d..c2c7772cd05 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/setup_loading_page.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/setup_loading_page.js
@@ -2,19 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-/** @enum {number} */
-/* #export */ const LoadingPageState = {
- LOADING: 1,
- SIM_DETECT_ERROR: 2,
- FINAL_SIM_DETECT_ERROR: 3,
- CELLULAR_DISCONNECT_WARNING: 4,
-};
-
/**
- * Loading subpage in Cellular Setup flow. This element contains image
- * asset and description to indicate that a SIM detection or eSIM profiles
- * loading is in progress. It can show a 'detecting sim' error or a 'cellular
- * disconnection' warning depending on its state.
+ * Loading subpage in Cellular Setup flow that shows an in progress operation or
+ * an error. This element contains error image asset and loading animation.
*/
Polymer({
is: 'setup-loading-page',
@@ -22,15 +12,6 @@ Polymer({
behaviors: [I18nBehavior],
properties: {
- /** @type {!cellular_setup.CellularSetupDelegate} */
- delegate: Object,
-
- /** @type {!LoadingPageState} */
- state: {
- type: Object,
- value: LoadingPageState.LOADING,
- },
-
/**
* Message displayed with spinner when in LOADING state.
*/
@@ -38,58 +19,22 @@ Polymer({
type: String,
value: '',
},
- },
-
- /**
- * @param {LoadingPageState} state
- * @return {?string}
- * @private
- */
- getTitle_(state) {
- if (this.delegate.shouldShowPageTitle() &&
- state === LoadingPageState.SIM_DETECT_ERROR) {
- return this.i18n('simDetectPageErrorTitle');
- }
- return null;
- },
-
- /**
- * @param {LoadingPageState} state
- * @return {string}
- * @private
- */
- getMessage_(state) {
- switch (state) {
- case LoadingPageState.SIM_DETECT_ERROR:
- return this.i18n('simDetectPageErrorMessage');
- case LoadingPageState.FINAL_SIM_DETECT_ERROR:
- return this.i18n('simDetectPageFinalErrorMessage');
- case LoadingPageState.CELLULAR_DISCONNECT_WARNING:
- return this.i18n('eSimConnectionWarning');
- case LoadingPageState.LOADING:
- return '';
- default:
- assertNotReached();
- }
- },
- /**
- * @param {LoadingPageState} state
- * @return {string}
- * @private
- */
- getMessageIcon_(state) {
- return state === LoadingPageState.CELLULAR_DISCONNECT_WARNING ? 'warning' :
- '';
- },
+ /**
+ * Title for page if needed.
+ * @type {?string}
+ */
+ loadingTitle: {
+ type: Object,
+ value: '',
+ },
- /**
- * @param {LoadingPageState} state
- * @return {boolean}
- * @private
- */
- shouldShowSimDetectError_(state) {
- return state === LoadingPageState.SIM_DETECT_ERROR ||
- state === LoadingPageState.FINAL_SIM_DETECT_ERROR;
+ /**
+ * Displays a sim detect error graphic if true.
+ */
+ isSimDetectError: {
+ type: Boolean,
+ value: false,
+ },
},
});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/BUILD.gn b/chromium/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
index 975267ff4f6..61ff21cddb5 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
@@ -72,6 +72,7 @@ js_library("network_apnlist") {
"//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:load_time_data",
]
+ externs_list = [ "$externs_path/metrics_private.js" ]
}
js_library("network_choose_mobile") {
@@ -195,6 +196,7 @@ js_library("network_siminfo") {
":mojo_interface_provider",
":onc_mojo",
":sim_lock_dialogs",
+ "//ui/webui/resources/cr_elements/cr_button:cr_button",
"//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js/cr/ui:focus_without_ink",
]
@@ -356,6 +358,7 @@ js_library("network_apnlist.m") {
"//ui/webui/resources/js:load_time_data.m",
]
extra_deps = [ ":network_apnlist_module" ]
+ externs_list = [ "$externs_path/metrics_private.js" ]
}
js_library("network_choose_mobile.m") {
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/cellular_locked.svg b/chromium/ui/webui/resources/cr_components/chromeos/network/cellular_locked.svg
new file mode 100644
index 00000000000..9ed810090fa
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/cellular_locked.svg
@@ -0,0 +1,3 @@
+<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M14.1876 9.58912C14.4644 9.58912 14.7358 9.6125 15 9.65744V3.82508C15 3.09148 14.1249 2.7241 13.6131 3.24283L2.23957 15.5943C1.72779 16.113 2.09026 17 2.81403 17H9.96527C9.55054 16.2733 9.31317 15.4296 9.31317 14.5297C9.31317 11.8011 11.4955 9.58912 14.1876 9.58912ZM16 16V14H13V16H16ZM13 13C12.4477 13 12 13.4477 12 14V16C12 16.5523 12.4477 17 13 17H16C16.5523 17 17 16.5523 17 16V14C17 13.4477 16.5523 13 16 13V12.5C16 11.6716 15.3284 11 14.5 11C13.6716 11 13 11.6716 13 12.5V13ZM14 13H15V12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5V13Z"/>
+</svg>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/cellular_utils.js b/chromium/ui/webui/resources/cr_components/chromeos/network/cellular_utils.js
index 27ab8f4fe33..ce089662586 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/cellular_utils.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/cellular_utils.js
@@ -8,10 +8,11 @@
// clang-format on
/**
- * Checks if the device has a currently active pSIM network.
+ * Checks if the device has a cellular network with connectionState not
+ * kNotConnected.
* @return {!Promise<boolean>}
*/
-/* #export */ function hasActivePSimNetwork() {
+/* #export */ function hasActiveCellularNetwork() {
const mojom = chromeos.networkConfig.mojom;
const networkConfig = network_config.MojoInterfaceProviderImpl.getInstance()
.getMojoServiceRemote();
@@ -22,35 +23,14 @@
limit: mojom.NO_LIMIT,
})
.then((response) => {
- // Filter out non-connected networks and check the remaining if they are
- // pSIM.
- return Promise.all(response.result
- .filter(network => {
- return network.connectionState !==
- mojom.ConnectionStateType.kNotConnected;
- })
- .map(networkIsPSim_));
- })
- .then((networkIsPSimResults) => {
- return networkIsPSimResults.some((isPSimNetwork) => isPSimNetwork);
+ return response.result.some(network => {
+ return network.connectionState !==
+ mojom.ConnectionStateType.kNotConnected;
+ });
});
}
/**
- * Returns whether a network is a pSIM network or not.
- * @private
- * @param {!chromeos.networkConfig.mojom.NetworkStateProperties} network
- * @return {!Promise<boolean>}
- */
-function networkIsPSim_(network) {
- const networkConfig = network_config.MojoInterfaceProviderImpl.getInstance()
- .getMojoServiceRemote();
- return networkConfig.getManagedProperties(network.guid).then((response) => {
- return !response.result.typeProperties.cellular.eid;
- });
-}
-
-/**
* Returns number of phyical SIM and eSIM slots on the current device
* @param {!chromeos.networkConfig.mojom.DeviceStateProperties|undefined}
* deviceState
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html
index 3ba9ea1eef9..26acaae2c03 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html
@@ -16,7 +16,6 @@
<style include="network-shared md-select">
:host {
--cr-property-box-width: 200px;
- padding-bottom: 16px;
}
cr-button {
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.js
index 6e82d5aff8d..00711c271a5 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.js
@@ -10,6 +10,9 @@
const kDefaultAccessPointName = 'NONE';
const kOtherAccessPointName = 'Other';
+const USE_ATTACH_APN_ON_SAVE_METRIC_NAME =
+ 'Network.Cellular.Apn.UseAttachApnOnSave';
+
Polymer({
is: 'network-apnlist',
@@ -313,16 +316,19 @@ Polymer({
/**
* Event triggered when the Other APN 'Save' button is tapped.
- * @param {!Event} event
* @private
*/
- onSaveOtherTap_(event) {
- this.sendApnChange_(this.selectedApn_);
+ onSaveOtherTap_() {
+ if (this.sendApnChange_(this.selectedApn_) && this.isAttachApnAllowed_) {
+ chrome.metricsPrivate.recordBoolean(
+ USE_ATTACH_APN_ON_SAVE_METRIC_NAME, this.isAttachApnToggleEnabled_);
+ }
},
/**
- * Send the apn-change event.
+ * Attempts to send the apn-change event. Returns true if it succeeds.
* @param {string} name The APN name property.
+ * @return {boolean}
* @private
*/
sendApnChange_(name) {
@@ -331,7 +337,7 @@ Polymer({
if (!this.otherApn_.accessPointName ||
this.otherApn_.accessPointName === kDefaultAccessPointName) {
// No valid APN set, do nothing.
- return;
+ return false;
}
apn = {
accessPointName: this.otherApn_.accessPointName,
@@ -345,10 +351,11 @@ Polymer({
if (apn === undefined) {
// Potential edge case if an update is received before this is invoked.
console.error('Selected APN not in list');
- return;
+ return false;
}
}
this.fire('apn-change', apn);
+ return true;
},
/**
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config.js
index 63e32766bcc..8ce3f503813 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config.js
@@ -445,6 +445,7 @@ Polymer({
response.success, response.errorMessage, connect);
});
}
+ this.fire('properties-set');
},
/** @private */
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_icon.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_icon.html
index e25a5c4001d..0649dc017f5 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_icon.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_icon.html
@@ -3,6 +3,7 @@
<link rel="import" href="../../chromeos/network/network_icons.html">
<link rel="import" href="../../../cr_elements/hidden_style_css.html">
<link rel="import" href="../../../html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/load_time_data.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="onc_mojo.html">
@@ -32,6 +33,11 @@
width: 20px;
}
+ :host-context([dir='rtl']) #technology {
+ left: auto;
+ right: 4px;
+ }
+
/* Lower-right corner */
#secure {
--iron-icon-fill-color: #5a5a5a;
@@ -42,6 +48,11 @@
width: 8px;
}
+ :host-context([dir='rtl']) #secure {
+ left: auto;
+ right: 0;
+ }
+
/* Images */
#icon.ethernet {
background: url(chrome://resources/cr_components/chromeos/network/ethernet.svg);
@@ -135,6 +146,10 @@
background: url(chrome://resources/cr_components/chromeos/network/cellular_off.svg);
}
+ #icon.cellular-locked {
+ background: url(chrome://resources/cr_components/chromeos/network/cellular_locked.svg);
+ }
+
#icon.cellular-connecting {
animation: cellular-levels 750ms infinite;
animation-direction: alternate;
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_icon.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_icon.js
index e2a74ac7726..92b8fd800a6 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_icon.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_icon.js
@@ -61,6 +61,14 @@ Polymer({
reflectToAttribute: true,
computed: 'computeAriaLabel_(locale, networkState)'
},
+
+ /** @private */
+ isUpdatedCellularUiEnabled_: {
+ type: Boolean,
+ value() {
+ return loadTimeData.getBoolean('updatedCellularActivationUi');
+ }
+ },
},
/**
@@ -91,6 +99,13 @@ Polymer({
}
const prefix = OncMojo.networkTypeIsMobile(type) ? 'cellular-' : 'wifi-';
+
+ if (this.networkState.type === mojom.NetworkType.kCellular &&
+ this.networkState.typeState.cellular.simLocked &&
+ this.isUpdatedCellularUiEnabled_) {
+ return prefix + 'locked';
+ }
+
if (!this.isListItem && !this.networkState.guid) {
const device = this.deviceState;
if (!device || device.deviceState === mojom.DeviceStateType.kEnabled ||
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html
index bb16a2bf14b..24c9225c0ec 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html
@@ -15,21 +15,23 @@
margin-inline-start: var(--settings-control-label-spacing);
}
</style>
- <div class="property-box">
- <div id="autoIPConfigLabel" class="start">
- [[i18n('networkIPConfigAuto')]]
+ <template is="dom-if" if="[[shouldShowAutoIpConfigToggle_]]" restamp>
+ <div id="autoConfig" class="property-box">
+ <div id="autoIPConfigLabel" class="start">
+ [[i18n('networkIPConfigAuto')]]
+ </div>
+ <cr-policy-indicator indicator-type="[[getPolicyIndicatorType(
+ managedProperties.ipAddressConfigType)]]">
+ </cr-policy-indicator>
+ <cr-toggle id="autoConfigIpToggle" checked="{{automatic_}}"
+ disabled="[[!canChangeIPConfigType_(managedProperties, disabled)]]"
+ on-change="onAutomaticChange_"
+ aria-labelledby="autoIPConfigLabel">
+ </cr-toggle>
</div>
- <cr-policy-indicator indicator-type="[[getPolicyIndicatorType(
- managedProperties.ipAddressConfigType)]]">
- </cr-policy-indicator>
- <cr-toggle id="autoConfigIpToggle" checked="{{automatic_}}"
- disabled="[[!canChangeIPConfigType_(managedProperties, disabled)]]"
- on-change="onAutomaticChange_"
- aria-labelledby="autoIPConfigLabel">
- </cr-toggle>
- </div>
+ </template>
<template is="dom-if" if="[[hasIpConfigFields_(ipConfig_)]]">
- <div class="property-box single-column indented stretch">
+ <div class$="[[getFieldsClassList_(shouldShowAutoIpConfigToggle_)]]">
<network-property-list-mojo fields="[[ipConfigFields_]]"
all-fields-read-only="[[automatic_]]"
property-dict="[[ipConfig_]]"
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js
index 646365ae876..d82ac7b3918 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js
@@ -140,6 +140,24 @@ Polymer({
},
readOnly: true
},
+
+ /**
+ * True if automatically-configured IP address toggle should be visible.
+ * @private
+ */
+ shouldShowAutoIpConfigToggle_: {
+ type: Boolean,
+ value: true,
+ computed: 'computeShouldShowAutoIpConfigToggle_(managedProperties)',
+ },
+
+ /** @private */
+ isUpdatedCellularUiEnabled_: {
+ type: Boolean,
+ value() {
+ return loadTimeData.getBoolean('updatedCellularActivationUi');
+ }
+ },
},
/**
@@ -384,4 +402,29 @@ Polymer({
{}
});
},
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ computeShouldShowAutoIpConfigToggle_() {
+ if (this.managedProperties.type ===
+ chromeos.networkConfig.mojom.NetworkType.kCellular &&
+ this.isUpdatedCellularUiEnabled_) {
+ return false;
+ }
+ return true;
+ },
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getFieldsClassList_() {
+ let classes = 'property-box single-column stretch';
+ if (this.shouldShowAutoIpConfigToggle_) {
+ classes += ' indented';
+ }
+ return classes;
+ }
});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.html
index fb6f3eb47c8..06ab36603a3 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.html
@@ -29,18 +29,9 @@
}
#divOuter {
+ height: var(--cr-network-row-height, 48px);
overflow: auto;
- padding-bottom: 0;
padding-inline-end: var(--cr-icon-ripple-padding);
- padding-top: 0;
- }
-
- .div-outer-with-standard-height {
- height: var(--cr-network-item-with-standard-height, 48px);
- }
-
- .div-outer-with-subtitle-height {
- height: var(--cr-network-item-with-subtitle-height, 60px);
}
:host([disabled_]) {
@@ -60,13 +51,16 @@
opacity: var(--network-list-item-disabled-opacity);
}
- :host(:not([is-e-sim-pending-profile_])) #divIcon {
+ :host(:not([is-e-sim-pending-profile_])
+ :not([is-e-sim-installing-profile_])) #divIcon {
height: 24px;
width: 24px;
}
- :host([is-e-sim-pending-profile_]) #divIcon {
+ :host([is-e-sim-pending-profile_]) #divIcon,
+ :host([is-e-sim-installing-profile_]) #divIcon {
height: 20px;
+ padding-inline-end: 20px;
width: 20px;
}
@@ -129,8 +123,7 @@
<div id="wrapper" focus-row-container
class="layout horizontal center flex">
<div id="divOuter"
- class$="layout horizontal center flex
- [[getContainerClassName_(networkState.*, subtitle_)]]"
+ class="layout horizontal center flex"
actionable
focus-row-control
selectable
@@ -152,13 +145,8 @@
<iron-icon id="divIcon" icon="[[item.polymerIcon]]"></iron-icon>
</template>
<div id="divText" class="layout horizontal flex">
- <div id="networkName" aria-hidden="true">
- [[getItemName_(item)]]
- </div>
- <div id="subtitle"
- hidden$="[[!isSubtitleVisible_(subtitle_)]]"
- aria-hidden="true">
- [[getSubtitle(subtitle_)]]
+ <div id="itemTitle" aria-hidden="true">
+ [[itemTitle_]]
</div>
<div id="networkStateText"
class$="[[getNetworkStateTextClass_(networkState.*,
@@ -177,7 +165,9 @@
</cr-policy-indicator>
</template>
<!-- This can only be shown if isUpdatedCellularUiEnabled_ is enabled. -->
- <template is="dom-if" if="[[isPSimPendingActivationNetwork_]]" restamp>
+ <template is="dom-if"
+ if="[[shouldShowActivateButton_(isPSimPendingActivationNetwork_,
+ showButtons)]]" restamp>
<cr-button id="activateButton"
aria-label$="[[getActivateBtnA11yLabel_(item)]]"
on-click="onActivateButtonClick_"
@@ -191,12 +181,12 @@
<paper-spinner-lite id="activatingPSimSpinner" active>
</paper-spinner-lite>
[[i18n('networkListItemActivating')]]
- <div class="separator"></div>
+ <div class="separator" hidden$="[[!showButtons]]"></div>
</template>
<template is="dom-if"
if="[[isSubpageButtonVisible_(networkState, showButtons, disabled_,
networkState.typeState.cellular.simLocked,
- isPSimPendingActivationNetwork_)]]" restamp>
+ isPSimPendingActivationNetwork_, isPSimActivatingNetwork_)]]" restamp>
<div>
<cr-icon-button class="subpage-arrow"
id="subpageButton"
@@ -209,7 +199,7 @@
</div>
</template>
<template is="dom-if" if="[[shouldShowUnlockButton_(networkState,
- networkState.typeState.cellular.simLocked)]]" restamp>
+ networkState.typeState.cellular.simLocked, showButtons)]]" restamp>
<cr-button id="unlockButton"
aria-label$="[[getUnlockBtnA11yLabel_(item)]]"
on-click="onUnlockButtonClick_"
@@ -217,13 +207,8 @@
[[i18n('networkListItemUnlock')]]
</cr-button>
</template>
- <template is="dom-if" if="[[isCellularUnlockDialogOpen_]]" restamp>
- <sim-lock-dialogs
- is-dialog-open="{{isCellularUnlockDialogOpen_}}"
- device-state="[[deviceState]]">
- </sim-lock-dialogs>
- </template>
- <template is="dom-if" if="[[isESimPendingProfile_]]" restamp>
+ <template is="dom-if" if="[[shouldShowInstallButton_(
+ isESimPendingProfile_, showButtons)]]" restamp>
<cr-button id="installButton"
aria-label$="[[getInstallBtnA11yLabel_(item)]]"
on-click="onInstallButtonClick_"
@@ -232,13 +217,19 @@
[[i18n('networkListItemDownload')]]
</cr-button>
</template>
- <template is="dom-if" if="[[isESimInstallingProfile_(item, item.customItemType)]]" restamp>
+ <template is="dom-if" if="[[isESimInstallingProfile_]]" restamp>
<paper-spinner-lite id="installingESimSpinner" active>
</paper-spinner-lite>
[[i18n('networkListItemAddingProfile')]]
</template>
</div>
</div>
+ <template is="dom-if" if="[[isCellularUnlockDialogOpen_]]" restamp>
+ <sim-lock-dialogs
+ is-dialog-open="{{isCellularUnlockDialogOpen_}}"
+ device-state="[[deviceState]]">
+ </sim-lock-dialogs>
+ </template>
</template>
<script src="network_list_item.js"></script>
</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.js
index c09cea23c31..8b32d486e9d 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.js
@@ -67,7 +67,8 @@ Polymer({
rowLabel: {
type: String,
notify: true,
- computed: 'getRowLabel_(item, networkState, subtitle_)',
+ computed:
+ 'getRowLabel_(item, networkState, subtitle_, isPSimPendingActivationNetwork_)',
},
buttonLabel: {
@@ -111,6 +112,15 @@ Polymer({
managedProperties_: Object,
/**
+ * Title containing the item's name and subtitle.
+ * @private {string}
+ */
+ itemTitle_: {
+ type: String,
+ value: '',
+ },
+
+ /**
* Subtitle for item.
* @private {string}
*/
@@ -174,6 +184,18 @@ Polymer({
computed: 'computeIsESimPendingProfile_(item, item.customItemType)',
},
+ /**
+ * Whether the network item is a cellular one and is of an esim
+ * installing profile.
+ * @private
+ */
+ isESimInstallingProfile_: {
+ type: Boolean,
+ reflectToAttribute: true,
+ value: false,
+ computed: 'computeIsESimInstallingProfile_(item, item.customItemType)',
+ },
+
/**@private {boolean} */
isCellularUnlockDialogOpen_: {
type: Boolean,
@@ -201,14 +223,17 @@ Polymer({
},
/** @private */
- itemChanged_() {
+ async itemChanged_() {
if (this.item && !this.item.hasOwnProperty('customItemType')) {
this.networkState =
/** @type {!OncMojo.NetworkStateProperties} */ (this.item);
} else {
this.networkState = undefined;
}
- this.setSubtitle_();
+ // The order each property is set here matters. We don't use observers to
+ // set each property or else the ordering is indeterminate.
+ await this.setSubtitle_();
+ this.setItemTitle_();
},
/** @private */
@@ -227,6 +252,10 @@ Polymer({
return;
}
+ // Clear subtitle to ensure that stale values are not displayed when this
+ // component is recycled for a case without subtitles.
+ this.subtitle_ = '';
+
// Show service provider subtext only when networkState is an eSIM cellular
// network.
if (!this.networkState ||
@@ -236,20 +265,24 @@ Polymer({
return;
}
- const eSimProfileRemote = await cellular_setup.getESimProfile(
+ const properties = await cellular_setup.getESimProfileProperties(
this.networkState.typeState.cellular.iccid);
- if (!eSimProfileRemote) {
+ if (!properties) {
return;
}
- const propertiesResponse = await eSimProfileRemote.getProperties();
- if (!propertiesResponse || !propertiesResponse.properties) {
+ // The parent list component could recycle the same component to show
+ // different networks. So networkState could have changed while the async
+ // operations above were in progress. Skip updating subtitle if network
+ // state does not match the fetched eSIM profile.
+ if (!this.networkState || !this.networkState.typeState.cellular ||
+ this.networkState.typeState.cellular.iccid !== properties.iccid) {
return;
}
// Service provider from mojo API is a string16 value represented as an
// array of characters. Convert to string for display.
- this.subtitle_ = propertiesResponse.properties.serviceProvider.data
+ this.subtitle_ = properties.serviceProvider.data
.map((charCode) => String.fromCharCode(charCode))
.join('');
},
@@ -261,9 +294,10 @@ Polymer({
return;
}
- // Temporarily place fetching managedProperties behind this flag so OOBE
- // tests pass. TODO(crbug.com/1196507) Remove this check.
- if (this.isUpdatedCellularUiEnabled_) {
+ // network-list-item supports dummy networkStates that may have an empty
+ // guid, such as those set by network-select. Only fetch managedProperties_
+ // if the network's guid is defined.
+ if (this.networkState.guid) {
this.networkConfig_.getManagedProperties(this.networkState.guid)
.then((response) => {
this.managedProperties_ = response.result;
@@ -280,6 +314,17 @@ Polymer({
this.fire('network-connect-changed', this.networkState);
},
+ /** @private */
+ setItemTitle_() {
+ const itemName = this.getItemName_();
+ const subtitle = this.getSubtitle();
+ if (!subtitle) {
+ this.itemTitle_ = itemName;
+ return;
+ }
+ this.itemTitle_ = this.i18n('networkListItemTitle', itemName, subtitle);
+ },
+
/**
* This gets called for network items and custom items.
* @return {string}
@@ -373,6 +418,12 @@ Polymer({
this.getItemName_(), this.item.typeState.cellular.signalStrength);
}
if (status) {
+ if (this.isPSimPendingActivationNetwork_) {
+ return this.i18n(
+ 'networkListItemLabelCellularUnactivatedWithConnectionStatus',
+ index, total, this.getItemName_(), status,
+ this.item.typeState.cellular.signalStrength);
+ }
if (this.subtitle_) {
return this.i18n(
'networkListItemLabelCellularWithConnectionStatusAndProviderName',
@@ -385,6 +436,12 @@ Polymer({
this.item.typeState.cellular.signalStrength);
}
+ if (this.isPSimPendingActivationNetwork_) {
+ return this.i18n(
+ 'networkListItemLabelCellularUnactivated', index, total,
+ this.getItemName_(), this.item.typeState.cellular.signalStrength);
+ }
+
if (this.subtitle_) {
return this.i18n(
'networkListItemLabelCellularWithProviderName', index, total,
@@ -475,7 +532,7 @@ Polymer({
return this.i18n(
'networkListItemLabelESimPendingProfile', index, total,
this.getItemName_());
- } else if (this.isESimInstallingProfile_()) {
+ } else if (this.isESimInstallingProfile_) {
if (this.subtitle_) {
return this.i18n(
'networkListItemLabelESimPendingProfileWithProviderNameInstalling',
@@ -499,17 +556,6 @@ Polymer({
},
/**
- * @return {string}
- * @private
- */
- getContainerClassName_() {
- if (this.isStateTextVisible_() && this.isSubtitleVisible_()) {
- return 'div-outer-with-subtitle-height';
- }
- return 'div-outer-with-standard-height';
- },
-
- /**
* This only gets called for network items once networkState is set.
* @return {string}
* @private
@@ -521,19 +567,17 @@ Polymer({
}
if (this.networkState.type === mojom.NetworkType.kCellular) {
- if (this.networkState.typeState.cellular.simLocked &&
- !this.isUpdatedCellularUiEnabled_) {
- return this.i18n('networkListItemSimCardLocked');
- }
- if (this.networkState.typeState.cellular.simLocked &&
- this.isUpdatedCellularUiEnabled_) {
- return this.i18n('networkListItemUpdatedCellularSimCardLocked');
+ if (this.networkState.typeState.cellular.simLocked) {
+ return this.isUpdatedCellularUiEnabled_ ?
+ this.i18n('networkListItemUpdatedCellularSimCardLocked') :
+ this.i18n('networkListItemSimCardLocked');
}
-
- if (this.shouldShowNotAvailableText_()) {
+ if (!this.isUpdatedCellularUiEnabled_ &&
+ this.shouldShowNotAvailableText_()) {
return this.i18n('networkListItemNotAvailable');
}
- if (this.isCellularNetworkScanning_()) {
+ if (!this.isUpdatedCellularUiEnabled_ &&
+ this.isCellularNetworkScanning_()) {
return this.i18n('networkListItemScanning');
}
if (this.isPSimUnavailableNetwork_) {
@@ -580,25 +624,19 @@ Polymer({
},
/**
- * @return {boolean}
- * @private
- */
- isSubtitleVisible_() {
- return !!this.subtitle_;
- },
-
- /**
* @param {!OncMojo.NetworkStateProperties|undefined} networkState
* @param {boolean} showButtons
* @return {boolean}
* @private
*/
isSubpageButtonVisible_(networkState, showButtons, disabled_) {
+ if (!this.showButtons) {
+ return false;
+ }
if (this.isPSimPendingActivationNetwork_ || this.isPSimActivatingNetwork_) {
return true;
}
- return !!networkState && showButtons && !disabled_ &&
- !this.shouldShowUnlockButton_();
+ return !!networkState && !disabled_ && !this.shouldShowUnlockButton_();
},
/**
@@ -649,15 +687,17 @@ Polymer({
this.networkState, this.showButtons, this.disabled_) &&
this.$$('#subpageButton') === this.shadowRoot.activeElement) {
this.fireShowDetails_(event);
- } else if (this.isESimPendingProfile_) {
+ } else if (this.shouldShowInstallButton_()) {
this.onInstallButtonClick_(event);
} else if (this.shouldShowUnlockButton_()) {
this.onUnlockButtonClick_();
} else if (this.item && this.item.hasOwnProperty('customItemName')) {
this.fire('custom-item-selected', this.item);
+ } else if (this.shouldShowActivateButton_()) {
+ this.fireShowDetails_(event);
} else if (
- this.isPSimPendingActivationNetwork_ ||
- this.isPSimUnavailableNetwork_ || this.isPSimActivatingNetwork_) {
+ this.showButtons &&
+ (this.isPSimUnavailableNetwork_ || this.isPSimActivatingNetwork_)) {
this.fireShowDetails_(event);
} else {
this.fire('selected', this.item);
@@ -741,7 +781,7 @@ Polymer({
* @return {boolean}
* @private
*/
- isESimInstallingProfile_() {
+ computeIsESimInstallingProfile_() {
return !!this.item && this.item.hasOwnProperty('customItemType') &&
this.item.customItemType ===
NetworkList.CustomItemType.ESIM_INSTALLING_PROFILE;
@@ -795,6 +835,17 @@ Polymer({
},
/**
+ * @return {boolean}
+ * @private
+ */
+ shouldShowActivateButton_() {
+ if (!this.showButtons) {
+ return false;
+ }
+ return this.isPSimPendingActivationNetwork_;
+ },
+
+ /**
* @return {string}
* @private
*/
@@ -878,6 +929,9 @@ Polymer({
* @private
*/
shouldShowUnlockButton_() {
+ if (!this.showButtons) {
+ return false;
+ }
if (!this.networkState || !this.networkState.typeState.cellular ||
!this.isUpdatedCellularUiEnabled_) {
return false;
@@ -894,6 +948,17 @@ Polymer({
},
/**
+ * @return {boolean}
+ * @private
+ */
+ shouldShowInstallButton_() {
+ if (!this.showButtons) {
+ return false;
+ }
+ return this.isESimPendingProfile_;
+ },
+
+ /**
* @return {string}
* @private
*/
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_password_input.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_password_input.html
index 61f1bb1dd3a..2b06e2ffe3e 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_password_input.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_password_input.html
@@ -13,6 +13,15 @@
<dom-module id="network-password-input">
<template>
<style include="network-shared">
+ :host {
+ display: block;
+ }
+
+ :host([allow-error-message]) #input {
+ --cr-input-error-display: block;
+ margin-bottom: 0;
+ }
+
#container {
align-items: center;
display: flex;
@@ -38,20 +47,26 @@
type="[[getInputType_(showPassword)]]"
on-mousedown="onMousedown_"
on-touchstart="onMousedown_"
- on-keydown="onKeydown_">
+ on-keydown="onKeydown_"
+ invalid="[[invalid]]"
+ error-message="[[errorMessage]]">
+ <template is="dom-if" if="[[!showPolicyIndicator_]]" restamp>
+ <div slot="suffix">
+ <cr-icon-button id="icon"
+ class$="[[getIconClass_(showPassword)]]"
+ aria-describedby="passwordVisibilityTooltip"
+ on-click="onShowPasswordTap_"
+ on-touchend="onShowPasswordTap_">
+ </cr-icon-button>
+ <paper-tooltip id="passwordVisibilityTooltip"
+ for="icon"
+ position="left"
+ fit-to-visible-bounds role="tooltip">
+ [[getShowPasswordTitle_(showPassword)]]
+ </paper-tooltip>
+ </div>
+ </template>
</cr-input>
- <template is="dom-if" if="[[!showPolicyIndicator_]]" restamp>
- <cr-icon-button id="icon" slot="suffix"
- class$="[[getIconClass_(showPassword)]]"
- aria-describedby="passwordVisibilityTooltip"
- on-click="onShowPasswordTap_"
- on-touchend="onShowPasswordTap_">
- </cr-icon-button>
- <paper-tooltip id="passwordVisibilityTooltip" for="icon" position="left"
- fit-to-visible-bounds role="tooltip">
- [[getShowPasswordTitle_(showPassword)]]
- </paper-tooltip>
- </template>
<template is="dom-if" if="[[showPolicyIndicator_]]" restamp>
<cr-policy-network-indicator-mojo
property="[[property]]" tooltip-position="left">
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_password_input.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_password_input.js
index a0e28e58858..71f0c96947b 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_password_input.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_password_input.js
@@ -36,6 +36,28 @@ Polymer({
value: false,
},
+ invalid: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * Whether an errorMessage can be shown beneath the input.
+ */
+ allowErrorMessage: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * Error message shown beneath input (only shown if allowErrorMessage is
+ * true).
+ */
+ errorMessage: {
+ type: String,
+ value: '',
+ },
+
showPolicyIndicator_: {
type: Boolean,
value: false,
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list_mojo.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list_mojo.js
index 888491ac07a..3bc0d011186 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list_mojo.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list_mojo.js
@@ -229,6 +229,10 @@ Polymer({
result += 'VPN';
} else if (subKey === 'wifi') {
result += 'WiFi';
+ } else if (subKey === 'iccid') {
+ result += 'ICCID';
+ } else if (subKey === 'imei') {
+ result += 'IMEI';
} else {
result += subKey.charAt(0).toUpperCase() + subKey.slice(1);
}
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_select.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_select.js
index 1e6757de278..e11459065c8 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_select.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_select.js
@@ -86,12 +86,6 @@ Polymer({
type: Boolean,
value: false,
},
-
- /**
- * The cellular DeviceState, or undefined if there is no Cellular device.
- * @private {!OncMojo.DeviceStateProperties|undefined} deviceState
- */
- cellularDeviceState_: Object,
},
/** @type {!OncMojo.NetworkStateProperties|undefined} */
@@ -262,12 +256,6 @@ Polymer({
* @private
*/
onGetNetworkStateList_(deviceStates, networkStates) {
- this.cellularDeviceState_ = deviceStates.find(function(device) {
- return device.type === mojom.NetworkType.kCellular;
- });
- if (this.cellularDeviceState_) {
- this.ensureCellularNetwork_(networkStates);
- }
this.networkStateList_ = networkStates;
this.fire('network-list-changed', networkStates);
@@ -289,37 +277,6 @@ Polymer({
},
/**
- * Modifies |networkStates| to include a cellular network if one is required
- * but does not exist.
- * @param {!Array<!OncMojo.NetworkStateProperties>} networkStates
- * @private
- */
- ensureCellularNetwork_(networkStates) {
- if (networkStates.find(function(network) {
- return network.type === mojom.NetworkType.kCellular;
- })) {
- return;
- }
- const deviceState = this.cellularDeviceState_.deviceState;
- if (deviceState === mojom.DeviceStateType.kDisabled ||
- deviceState === mojom.DeviceStateType.kProhibited) {
- return; // No Cellular network
- }
-
- // Note: the default connectionState is kNotConnected.
- // TODO(khorimoto): Maybe set an 'initializing' CellularState property if
- // the device state is initializing, see TODO in network_list_item.js.
-
- // Insert the Cellular network after the Ethernet network if it exists.
- const idx = (networkStates.length > 0 &&
- networkStates[0].type === mojom.NetworkType.kEthernet) ?
- 1 :
- 0;
- networkStates.splice(
- idx, 0, OncMojo.getDefaultNetworkState(mojom.NetworkType.kCellular));
- },
-
- /**
* Event triggered when a network-list-item is selected.
* @param {!{target: HTMLElement, detail: !OncMojo.NetworkStateProperties}} e
* @private
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html
index 73d81f6e113..255b6d8f708 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html
@@ -26,6 +26,10 @@
margin-inline-end: 10px;
}
+ cr-toggle {
+ margin-inline-start: var(--cr-button-edge-spacing);
+ }
+
.error {
color: red;
font-weight: 500;
@@ -39,63 +43,71 @@
margin-inline-start: var(--cr-section-padding);
}
- cr-toggle {
- margin-inline-start: var(--cr-button-edge-spacing);
+ .pin-required-subtext {
+ color: var(--google-grey-700);
}
</style>
<!-- SIM missing UI -->
- <div id="simMissing" class="property-box two-line"
- hidden$="[[!showSimMissing_(deviceState)]]">
- <div class="start layout horizontal center">
- <iron-icon icon="cr:sim-card-alert"></iron-icon>
- <div class="error">[[i18n('networkSimCardMissing')]]</div>
+ <template is="dom-if" if="[[eq_(State.SIM_MISSING, state_)]]" restamp>
+ <div id="simMissing" class="property-box two-line">
+ <div class="start layout horizontal center">
+ <iron-icon id="simMissingIcon" icon="cr:sim-card-alert"></iron-icon>
+ <div class="error">[[i18n('networkSimCardMissing')]]</div>
+ </div>
</div>
- </div>
+ </template>
<!-- SIM locked -->
- <div id="simLocked" class="property-box two-line"
- hidden$="[[!showSimLocked_(deviceState, isActiveSim_)]]">
- <div class="start layout horizontal center"
- hidden="[[isUpdatedCellularUiEnabled_]]">
- <iron-icon icon="cr:sim-lock"></iron-icon>
- <div class="error">[[i18n('networkSimCardLocked')]]</div>
+ <template is="dom-if" if="[[eq_(State.SIM_LOCKED, state_)]]" restamp>
+ <div id="simLocked" class="property-box two-line">
+ <div class="start layout horizontal center"
+ hidden="[[isUpdatedCellularUiEnabled_]]">
+ <iron-icon icon="cr:sim-lock"></iron-icon>
+ <div class="error">[[i18n('networkSimCardLocked')]]</div>
+ </div>
+ <div class="separator" hidden="[[isUpdatedCellularUiEnabled_]]"></div>
+ <cr-button id="unlockPinButton"
+ on-click="onUnlockPinTap_"
+ disabled="[[disabled]]">
+ [[i18n('networkSimUnlock')]]
+ </cr-button>
</div>
- <div class="separator" hidden="[[isUpdatedCellularUiEnabled_]]"></div>
- <cr-button id="unlockPinButton"
- on-click="onUnlockPinTap_"
- disabled="[[disabled]]">
- [[i18n('networkSimUnlock')]]
- </cr-button>
- </div>
+ </template>
<!-- SIM unlocked -->
- <div class="property-box two-line"
- hidden$="[[!showSimUnlocked_(deviceState)]]">
- <div id="simLockToggleLabel" class="start">
- [[i18n('networkSimLockEnable')]]
+ <template is="dom-if" if="[[eq_(State.SIM_UNLOCKED, state_)]]" restamp>
+ <div class="property-box two-line">
+ <div class="flex layout vertical" aria-hidden="true">
+ <div id="pinRequiredLabel">
+ [[i18n('networkSimLockEnable')]]
+ </div>
+ <div id="pinRequiredSublabel" class="pin-required-subtext">
+ [[i18n('networkSimLockEnableSublabel')]]
+ </div>
+ </div>
+ <cr-button id="changePinButton" on-click="onChangePinTap_"
+ hidden$="[[!showChangePinButton_(deviceState, isActiveSim_)]]"
+ disabled="[[disabled]]">
+ [[i18n('networkSimChangePin')]]
+ </cr-button>
+ <template is="dom-if" if="[[!isActiveSim_]]" restamp>
+ <iron-icon id="help-icon" tabindex="0" icon="cr:help-outline"
+ aria-labelledby="pinRequiredLabel pinRequiredSublabel inActiveSimLockTooltip">
+ </iron-icon>
+ <paper-tooltip id="inActiveSimLockTooltip" for="help-icon" position="bottom"
+ aria-hidden="true" fit-to-visible-bounds>
+ [[i18n('networkSimLockedTooltip')]]
+ </paper-tooltip>
+ <div class="separator"></div>
+ </template>
+ <cr-toggle id="simLockButton"
+ disabled="[[isSimLockButtonDisabled_(disabled, isActiveSim_)]]"
+ on-change="onSimLockEnabledChange_" checked="{{lockEnabled_}}"
+ aria-labelledby="pinRequiredLabel pinRequiredSublabel">
+ </cr-toggle>
</div>
- <cr-button id="changePinButton" on-click="onChangePinTap_"
- hidden$="[[!showChangePinButton_(deviceState, isActiveSim_)]]"
- disabled="[[disabled]]">
- [[i18n('networkSimChangePin')]]
- </cr-button>
- <template is="dom-if" if="[[!isActiveSim_]]" restamp>
- <iron-icon id="help-icon" tabindex="0" icon="cr:help-outline"
- aria-labelledby="simLockToggleLabel inActiveSimLockTooltip">
- </iron-icon>
- <paper-tooltip id="inActiveSimLockTooltip" for="help-icon" position="bottom"
- aria-hidden="true" fit-to-visible-bounds>
- [[i18n('networkSimLockedTooltip')]]
- </paper-tooltip>
- <div class="separator"></div>
- </template>
- <cr-toggle id="simLockButton"
- disabled="[[isSimLockButtonDisabled_(disabled, isActiveSim_)]]"
- on-change="onSimLockEnabledChange_" checked="{{lockEnabled_}}"
- aria-labelledby="simLockToggleLabel">
- </cr-toggle>
- </div>
+ </template>
<template is="dom-if" if="[[isDialogOpen_]]" restamp>
<sim-lock-dialogs
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js
index 5d2cff912df..570b5e32a82 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js
@@ -10,6 +10,22 @@
const TOGGLE_DEBOUNCE_MS = 500;
+/**
+ * State of the element. <network-siminfo> shows 1 of 3 modes:
+ * SIM_MISSING: Shows a UI explaining that no SIM card is present. Note that
+ * this UI is only shown if the isUpdatedCellularUiEnabled_ flag is off.
+ * SIM_LOCKED: Shows an alert that the SIM is locked and provides an "Unlock"
+ * button which allows the user to unlock the SIM.
+ * SIM_UNLOCKED: Provides an option to lock the SIM if desired. If SIM-lock is
+ * on, this UI also allows the user to update the PIN used.
+ * @enum {number}
+ */
+const State = {
+ SIM_MISSING: 0,
+ SIM_LOCKED: 1,
+ SIM_UNLOCKED: 2
+};
+
Polymer({
is: 'network-siminfo',
@@ -34,6 +50,12 @@ Polymer({
value: false,
},
+ /** Used to reference the State enum in HTML. */
+ State: {
+ type: Object,
+ value: State,
+ },
+
/**
* Reflects deviceState.simLockStatus.lockEnabled for the
* toggle button.
@@ -77,6 +99,14 @@ Polymer({
return loadTimeData.getBoolean('updatedCellularActivationUi');
}
},
+
+ /** @private {!State} */
+ state_: {
+ type: Number,
+ value: State.SIM_UNLOCKED,
+ computed: 'computeState_(networkState, deviceState, deviceState.*, ' +
+ 'isUpdatedCellularUiEnabled_, isActiveSim_)',
+ },
},
/** @private {boolean|undefined} */
@@ -90,6 +120,13 @@ Polymer({
return /** @type {?CrToggleElement} */ (this.$$('#simLockButton'));
},
+ /**
+ * @return {?CrButtonElement}
+ */
+ getUnlockButton() {
+ return /** @type {?CrButtonElement} */ (this.$$('#unlockPinButton'));
+ },
+
/** @private */
onDialogOpenChanged_() {
if (this.isDialogOpen_) {
@@ -97,6 +134,29 @@ Polymer({
}
this.delayUpdateLockEnabled_();
+ this.updateFocus_();
+ },
+
+ /**
+ * Sets default focus when dialog is closed.
+ * @private
+ */
+ updateFocus_() {
+ const state = this.computeState_();
+ // State.SIM_MISSING state is not needed here because it does not have a
+ // click event to open the sim lock dialogs
+ switch (state) {
+ case State.SIM_LOCKED:
+ if (this.$$('#unlockPinButton')) {
+ this.$$('#unlockPinButton').focus();
+ }
+ break;
+ case State.SIM_UNLOCKED:
+ if (this.$$('#simLockButton')) {
+ this.$$('#simLockButton').focus();
+ }
+ break;
+ }
},
/** @private */
@@ -109,7 +169,7 @@ Polymer({
return;
}
- const lockEnabled = simLockStatus.lockEnabled;
+ const lockEnabled = this.isActiveSim_ && simLockStatus.lockEnabled;
if (lockEnabled !== this.lockEnabled_) {
this.setLockEnabled_ = lockEnabled;
this.updateLockEnabled_();
@@ -182,38 +242,6 @@ Polymer({
},
/**
- * @return {boolean}
- * @private
- */
- showSimMissing_() {
- return !!this.deviceState && !this.deviceState.simLockStatus;
- },
-
- /**
- * @return {boolean}
- * @private
- */
- showSimLocked_() {
- const simLockStatus = this.deviceState && this.deviceState.simLockStatus;
- if (!simLockStatus) {
- return false;
- }
- return !!simLockStatus.lockType && this.isActiveSim_;
- },
-
- /**
- * @return {boolean}
- * @private
- */
- showSimUnlocked_() {
- const simLockStatus = this.deviceState && this.deviceState.simLockStatus;
- if (!simLockStatus) {
- return false;
- }
- return !simLockStatus.lockType;
- },
-
- /**
* @param {boolean} showChangePin
* @private
*/
@@ -263,5 +291,41 @@ Polymer({
isSimLockButtonDisabled_() {
return this.disabled || !this.isActiveSim_;
},
+
+ /**
+ * @return {!State}
+ * @private
+ */
+ computeState_() {
+ const simLockStatus = this.deviceState && this.deviceState.simLockStatus;
+
+ // No SIM lock status corresponds to a missing SIM. Note that this state is
+ // only returned if the updated UI flag is *off*, since we show a
+ // "Mobile data" subpage in place of this warning UI when the flag is on.
+ if (!this.isUpdatedCellularUiEnabled_ && !simLockStatus) {
+ return State.SIM_MISSING;
+ }
+
+ // If a lock is set and the network in question is the active SIM, show the
+ // "locked SIM" UI. Note that we can only detect the locked state of the
+ // active SIM, so it is possible that we fall through to the SIM_UNLOCKED
+ // case below even for a locked SIM if that SIM is not the active one.
+ if (this.isActiveSim_ && simLockStatus && !!simLockStatus.lockType) {
+ return State.SIM_LOCKED;
+ }
+
+ // Note that if this is not the active SIM, we cannot read to lock state, so
+ // we default to showing the "unlocked" UI unless we know otherwise.
+ return State.SIM_UNLOCKED;
+ },
+
+ /**
+ * @param {!State} state1
+ * @param {!State} state2
+ * @return {boolean} Whether state1 is the same as state2.
+ */
+ eq_(state1, state2) {
+ return state1 === state2;
+ },
});
})();
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js b/chromium/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js
index 270642f769a..d4e2f457e83 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js
@@ -218,7 +218,8 @@
}
/**
- * @param {?chromeos.networkConfig.mojom.DeviceStateProperties} device
+ * @param {?chromeos.networkConfig.mojom.DeviceStateProperties|undefined}
+ * device
* @return {boolean}
*/
static deviceIsInhibited(device) {
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.html b/chromium/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.html
index cad4531df7c..c02c275d836 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.html
@@ -3,6 +3,7 @@
<link rel="import" href="../../../cr_elements/cr_button/cr_button.html">
<link rel="import" href="../../../cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="../../../cr_elements/icons.html">
+<link rel="import" href="../../../cr_elements/shared_style_css.html">
<link rel="import" href="../../../html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
@@ -20,26 +21,72 @@
font-weight: 500;
margin-bottom: 10px;
}
+
+ #enter-pin-description {
+ margin-bottom: 16px;
+ }
+
+ .pinEntrySubtext {
+ font-size: var(--cr-form-field-label-font-size);
+ font-weight: 400;
+ margin-top: -10px;
+ }
+
+ :host([has-error-text_]) .pinEntrySubtext {
+ color: red;
+ }
+
+ #changePinOld {
+ margin-top: 24px;
+ }
+
+ #unlockPin {
+ margin-top: 24px;
+ }
+
+ #puk-warning-container {
+ display: flex;
+ margin-bottom: 24px;
+ margin-top: 20px;
+ }
+
+ #puk-warning-icon {
+ --iron-icon-fill-color: var(--google-red-600);
+ --iron-icon-height: 24px;
+ --iron-icon-width: 24px;
+ margin-inline-end: 4px;
+ }
+
+ :host([has-error-text_]) #puk-warning-container {
+ color: var(--google-red-600);
+ }
</style>
<!-- Enter PIN dialog -->
- <cr-dialog id="enterPinDialog" close-text="[[i18n('close')]]">
+ <cr-dialog id="enterPinDialog"
+ on-cancel="onCancel_"
+ close-text="[[i18n('close')]]">
<div slot="title">[[i18n('networkSimEnterPinTitle')]]</div>
<div slot="body">
+ <div id="enter-pin-description" aria-hidden="true">
+ [[i18n('networkSimEnterPinDescription')]]
+ </div>
<network-password-input id="enterPin"
value="{{pin_}}"
- label="[[i18n('networkSimEnterPin')]]"
on-enter="sendEnterPin_"
- disabled="[[inProgress_]]">
+ disabled="[[inProgress_]]"
+ invalid="[[hasErrorText_]]"
+ aria-labeledby="pinEntrySubtext">
</network-password-input>
- <div class="dialog-error">
- [[getErrorMsg_(error_, deviceState)]]
+ <div class="pinEntrySubtext" aria-live="assertive">
+ [[getPinEntrySubtext_(error_, deviceState)]]
</div>
</div>
<div slot="button-container">
- <cr-button class="cancel-button" on-click="onCancelClick_">
+ <cr-button class="cancel-button" on-click="onCancel_">
[[i18n('cancel')]]
</cr-button>
<cr-button class="action-button"
+ aria-describedby="enter-pin-description"
on-click="sendEnterPin_"
disabled="[[!enterPinEnabled_]]">
[[i18n('networkSimEnter')]]
@@ -48,31 +95,37 @@
</cr-dialog>
<!-- Change PIN dialog -->
- <cr-dialog id="changePinDialog" close-text="[[i18n('close')]]">
+ <cr-dialog id="changePinDialog"
+ on-cancel="onCancel_"
+ close-text="[[i18n('close')]]">
<div slot="title">[[i18n('networkSimChangePinTitle')]]</div>
<div slot="body">
<network-password-input id="changePinOld"
value="{{pin_}}"
label="[[i18n('networkSimEnterOldPin')]]"
- disabled="[[inProgress_]]">
+ disabled="[[inProgress_]]"
+ invalid="[[isOldPinInvalid_(error_, deviceState)]]"
+ error-message="[[getOldPinErrorMessage_(error_, deviceState)]]"
+ allow-error-message>
</network-password-input>
<network-password-input id="changePinNew1"
value="{{pin_new1_}}"
label="[[i18n('networkSimEnterNewPin')]]"
- disabled="[[inProgress_]]">
+ disabled="[[inProgress_]]"
+ allow-error-message>
</network-password-input>
<network-password-input id="changePinNew2"
value="{{pin_new2_}}"
label="[[i18n('networkSimReEnterNewPin')]]"
on-enter="sendChangePin_"
- disabled="[[inProgress_]]">
+ disabled="[[inProgress_]]"
+ invalid="[[isSecondNewPinInvalid_(error_, deviceState)]]"
+ error-message="[[getSecondNewPinErrorMessage_(error_, deviceState)]]"
+ allow-error-message>
</network-password-input>
- <div class="dialog-error">
- [[getErrorMsg_(error_, deviceState)]]
- </div>
</div>
<div slot="button-container">
- <cr-button class="cancel-button" on-click="onCancelClick_">
+ <cr-button class="cancel-button" on-click="onCancel_">
[[i18n('cancel')]]
</cr-button>
<cr-button class="action-button"
@@ -84,21 +137,22 @@
</cr-dialog>
<!-- Unlock PIN dialog -->
- <cr-dialog id="unlockPinDialog" close-text="[[i18n('close')]]">
+ <cr-dialog id="unlockPinDialog"
+ on-cancel="onCancel_"
+ close-text="[[i18n('close')]]">
<div slot="title">[[i18n('networkSimLockedTitle')]]</div>
<div slot="body">
<network-password-input id="unlockPin"
value="{{pin_}}"
- label="[[i18n('networkSimEnterPin')]]"
on-enter="sendUnlockPin_"
disabled="[[inProgress_]]">
</network-password-input>
- <div class="dialog-error">
- [[getErrorMsg_(error_, deviceState)]]
+ <div class="pinEntrySubtext" aria-live="assertive">
+ [[getPinEntrySubtext_(error_, deviceState)]]
</div>
</div>
<div slot="button-container">
- <cr-button class="cancel-button" on-click="onCancelClick_">
+ <cr-button class="cancel-button" on-click="onCancel_">
[[i18n('cancel')]]
</cr-button>
<cr-button class="action-button"
@@ -110,42 +164,55 @@
</cr-dialog>
<!-- Unlock PUK dialog -->
- <cr-dialog id="unlockPukDialog" close-text="[[i18n('close')]]">
+ <cr-dialog id="unlockPukDialog"
+ on-cancel="onCancel_"
+ close-text="[[i18n('close')]]">
<div slot="title">[[i18n('networkSimLockedTitle')]]</div>
<div slot="body">
- <div>
+ <div id="puk-subtitle">
[[i18n('networkSimPukDialogSubtitle')]]
</div>
+ <div id="puk-warning-container">
+ <template is="dom-if" if="[[hasErrorText_]]">
+ <iron-icon id="puk-warning-icon" icon="cellular-setup:warning">
+ </iron-icon>
+ </template>
+ <div aria-live="assertive">
+ [[getPukWarningMessage_(error_, deviceState)]]
+ </div>
+ </div>
<network-password-input id="unlockPuk"
value="{{puk_}}"
label="[[i18n('networkSimEnterPuk')]]"
- disabled="[[inProgress_]]">
+ disabled="[[inProgress_]]"
+ invalid="[[isPukInvalid_(error_, deviceState)]]"
+ error-message="[[getPukErrorMessage_(error_, deviceState)]]"
+ allow-error-message>
</network-password-input>
- <div class="dialog-error">
- [[getErrorMsg_(error_, deviceState)]]
- </div>
<network-password-input id="unlockPin1"
value="{{pin_new1_}}"
label="[[i18n('networkSimEnterNewPin')]]"
- disabled="[[inProgress_]]">
+ disabled="[[inProgress_]]"
+ allow-error-message>
</network-password-input>
<network-password-input id="unlockPin2"
value="{{pin_new2_}}"
label="[[i18n('networkSimReEnterNewPin')]]"
on-enter="sendUnlockPuk_"
- disabled="[[inProgress_]]">
+ disabled="[[inProgress_]]"
+ invalid="[[isSecondNewPinInvalid_(error_, deviceState)]]"
+ error-message="[[getSecondNewPinErrorMessage_(error_, deviceState)]]"
+ allow-error-message>
</network-password-input>
- <div class="dialog-error">
- [[i18n('networkSimLockedWarning')]]
- </div>
</div>
<div slot="button-container">
- <cr-button class="cancel-button" on-click="onCancelClick_">
+ <cr-button class="cancel-button" on-click="onCancel_">
[[i18n('cancel')]]
</cr-button>
<cr-button class="action-button"
on-click="sendUnlockPuk_"
- disabled="[[!enterPukEnabled_]]">
+ disabled="[[!enterPukEnabled_]]"
+ aria-describedby="puk-subtitle">
[[i18n('networkSimUnlock')]]
</cr-button>
</div>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.js b/chromium/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.js
index 9c844be6edb..e8859592e98 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.js
@@ -73,6 +73,22 @@ Polymer({
observer: 'updateSubmitButtonEnabled_',
},
+ /** @private */
+ hasErrorText_: {
+ type: Boolean,
+ computed: 'computeHasErrorText_(error_, deviceState)',
+ reflectToAttribute: true,
+ },
+
+ /**
+ * Error, if defined, that error_ should be set as the next time deviceState
+ * updates.
+ * @private {ErrorType|undefined}
+ */
+ pendingError_: {
+ type: Object,
+ },
+
/**
* Used to enable enter button in |enterPin| dialog.
* @private
@@ -164,6 +180,12 @@ Polymer({
if (!oldDeviceState || !newDeviceState) {
return;
}
+ if (this.pendingError_) {
+ // If pendingError_ is defined, we were waiting for the next deviceState
+ // change to set error_ to the same value as pendingError_.
+ this.error_ = this.pendingError_;
+ this.pendingError_ = undefined;
+ }
this.updateDialogVisibility_();
},
@@ -357,7 +379,10 @@ Polymer({
this.networkConfig_.setCellularSimState(cellularSimState).then(response => {
this.inProgress_ = false;
if (!response.success) {
- this.error_ = ErrorType.INCORRECT_PIN;
+ // deviceState is not updated with the new cellularSimState when the
+ // response returns, set pendingError_ as the value error_ should be set
+ // as on the next deviceState change.
+ this.pendingError_ = ErrorType.INCORRECT_PIN;
this.focusDialogInput_();
} else {
this.error_ = ErrorType.NONE;
@@ -391,10 +416,17 @@ Polymer({
},
/**
+ * Used by test to simulate dialog cancel click.
+ */
+ closeDialogsForTest() {
+ this.closeDialogs_();
+ },
+
+ /**
* @param {!Event} event
* @private
*/
- onCancelClick_(event) {
+ onCancel_(event) {
event.stopPropagation();
this.closeDialogs_();
},
@@ -433,7 +465,10 @@ Polymer({
this.networkConfig_.setCellularSimState(cellularSimState).then(response => {
this.inProgress_ = false;
if (!response.success) {
- this.error_ =
+ // deviceState is not updated with the new cellularSimState when the
+ // response returns, set pendingError_ as the value error_ should be set
+ // as on the next deviceState change.
+ this.pendingError_ =
opt_puk ? ErrorType.INCORRECT_PUK : ErrorType.INCORRECT_PIN;
this.focusDialogInput_();
} else {
@@ -448,7 +483,11 @@ Polymer({
if (this.$.enterPinDialog.open) {
this.$.enterPin.focus();
} else if (this.$.changePinDialog.open) {
- this.$.changePinOld.focus();
+ if (this.isSecondNewPinInvalid_()) {
+ this.$.changePinNew2.focus();
+ } else {
+ this.$.changePinOld.focus();
+ }
} else if (this.$.unlockPinDialog.open) {
this.$.unlockPin.focus();
} else if (this.$.unlockPukDialog.open) {
@@ -498,7 +537,10 @@ Polymer({
return true;
},
- /** @private */
+ /**
+ * @return {string}
+ * @private
+ */
getErrorMsg_() {
if (this.error_ === ErrorType.NONE) {
return '';
@@ -524,14 +566,128 @@ Polymer({
assertNotReached();
}
- const retriesLeft = (this.deviceState && this.deviceState.simLockStatus) ?
- this.deviceState.simLockStatus.retriesLeft :
- 0;
- if (retriesLeft !== 1) {
+ // Invalid PIN errors show a separate string based on whether there is 1
+ // retry left or not.
+ const retriesLeft = this.getNumRetriesLeft_();
+ if (retriesLeft !== 1 &&
+ (this.error_ === ErrorType.INCORRECT_PIN ||
+ this.error_ === ErrorType.INVALID_PIN)) {
errorStringId += 'Plural';
}
+
return this.i18n(errorStringId, retriesLeft);
},
+ /**
+ * @return {number}
+ * @private
+ */
+ getNumRetriesLeft_() {
+ if (!this.deviceState || !this.deviceState.simLockStatus) {
+ return 0;
+ }
+
+ return this.deviceState.simLockStatus.retriesLeft;
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ computeHasErrorText_() {
+ return !!this.getErrorMsg_();
+ },
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getPinEntrySubtext_() {
+ const errorMessage = this.getErrorMsg_();
+ if (errorMessage) {
+ return errorMessage;
+ }
+
+ return this.i18n('networkSimEnterPinSubtext');
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ isOldPinInvalid_() {
+ return this.error_ === ErrorType.INCORRECT_PIN ||
+ this.error_ === ErrorType.INVALID_PIN;
+ },
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getOldPinErrorMessage_() {
+ if (this.isOldPinInvalid_()) {
+ return this.getErrorMsg_();
+ }
+
+ return '';
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ isSecondNewPinInvalid_() {
+ return this.error_ === ErrorType.MISMATCHED_PIN;
+ },
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getSecondNewPinErrorMessage_() {
+ if (this.isSecondNewPinInvalid_()) {
+ return this.getErrorMsg_();
+ }
+
+ return '';
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ isPukInvalid_() {
+ return this.error_ === ErrorType.INCORRECT_PUK ||
+ this.error_ === ErrorType.INVALID_PUK;
+ },
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getPukErrorMessage_() {
+ if (this.isPukInvalid_()) {
+ return this.getErrorMsg_();
+ }
+
+ return '';
+ },
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getPukWarningMessage_() {
+ if (this.isPukInvalid_()) {
+ const retriesLeft = this.getNumRetriesLeft_();
+ if (retriesLeft === 1) {
+ return this.i18n('networkSimPukDialogWarningWithFailure', retriesLeft);
+ }
+
+ return this.i18n('networkSimPukDialogWarningWithFailures', retriesLeft);
+ }
+
+ return this.i18n('networkSimPukDialogWarningNoFailures');
+ },
});
})(); \ No newline at end of file
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/os_cr_components.gni b/chromium/ui/webui/resources/cr_components/chromeos/os_cr_components.gni
index 4b0c3289811..09b92ec7004 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/os_cr_components.gni
+++ b/chromium/ui/webui/resources/cr_components/chromeos/os_cr_components.gni
@@ -21,8 +21,11 @@ cr_components_chromeos_namespace_rewrites = [
"cellular_setup.setESimManagerRemoteForTesting|setESimManagerRemoteForTesting",
"cellular_setup.observeESimManager|observeESimManager",
"cellular_setup.getPendingESimProfiles|getPendingESimProfiles",
+ "cellular_setup.getNonPendingESimProfiles|getNonPendingESimProfiles",
+ "cellular_setup.getNumESimProfiles|getNumESimProfiles",
"cellular_setup.getEuicc|getEuicc",
"cellular_setup.getESimProfile|getESimProfile",
+ "cellular_setup.getESimProfileProperties|getESimProfileProperties",
"cellular_setup.CellularSetupDelegate|CellularSetupDelegate",
"multidevice_setup.BrowserProxy|BrowserProxy",
"multidevice_setup.BrowserProxyImpl|BrowserProxyImpl",
@@ -44,15 +47,14 @@ cr_components_chromeos_auto_imports = [
"ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup_delegate.html|CellularSetupDelegate",
"ui/webui/resources/cr_components/chromeos/cellular_setup/subflow_behavior.html|SubflowBehavior",
"ui/webui/resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.html|setCellularSetupRemoteForTesting,getCellularSetupRemote,setESimManagerRemoteForTesting,getESimManagerRemote,observeESimManager",
- "ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_utils.html|getPendingESimProfiles,getEuicc,getESimProfile",
+ "ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_utils.html|getPendingESimProfiles,getNonPendingESimProfiles,getNumESimProfiles,getEuicc,getESimProfile,getESimProfileProperties",
"ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_listener_behavior.html|ESimManagerListenerBehavior",
- "ui/webui/resources/cr_components/chromeos/cellular_setup/setup_loading_page.html|LoadingPageState",
"ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.html|BrowserProxy,BrowserProxyImpl",
"ui/webui/resources/cr_components/chromeos/multidevice_setup/mojo_api.html|MojoInterfaceProvider,MojoInterfaceProviderImpl",
"ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.html|MultiDeviceSetupDelegate",
"ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page_container_behavior.html|UiPageContainerBehavior",
"ui/webui/resources/cr_components/chromeos/network/cr_policy_network_behavior_mojo.html|CrPolicyNetworkBehaviorMojo",
- "ui/webui/resources/cr_components/chromeos/network/cellular_utils.html|getSimSlotCount,hasActivePSimNetwork,isConnectedToNonCellularNetwork,isActiveSim",
+ "ui/webui/resources/cr_components/chromeos/network/cellular_utils.html|getSimSlotCount,hasActiveCellularNetwork,isConnectedToNonCellularNetwork,isActiveSim",
"ui/webui/resources/cr_components/chromeos/network/onc_mojo.html|OncMojo",
"ui/webui/resources/cr_components/chromeos/network/network_config_element_behavior.html|NetworkConfigElementBehavior",
"ui/webui/resources/cr_components/chromeos/network/network_listener_behavior.html|NetworkListenerBehavior",
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn
index 2307509d23e..ffb8d5041d7 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn
+++ b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn
@@ -24,10 +24,7 @@ js_library("pin_keyboard") {
}
js_library("lock_screen_constants") {
- deps = [
- "//ui/webui/resources/cr_elements/cr_profile_avatar_selector:cr_profile_avatar_selector",
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("setup_pin_keyboard") {
@@ -54,7 +51,6 @@ js_library("lock_screen_constants.m") {
sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.m.js" ]
deps = [
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
- "//ui/webui/resources/cr_elements/cr_profile_avatar_selector:cr_profile_avatar_selector.m",
"//ui/webui/resources/js:cr.m",
]
extra_deps = [ ":modulize" ]
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/DIR_METADATA b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/DIR_METADATA
deleted file mode 100644
index b39cd583495..00000000000
--- a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/DIR_METADATA
+++ /dev/null
@@ -1,11 +0,0 @@
-# Metadata information for this directory.
-#
-# For more information on DIR_METADATA files, see:
-# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/README.md
-#
-# For the schema of this file, see Metadata message:
-# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/proto/dir_metadata.proto
-
-monorail {
- component: "OS>Systems>Settings"
-} \ No newline at end of file
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/smb_shares/OWNERS b/chromium/ui/webui/resources/cr_components/chromeos/smb_shares/OWNERS
index 704b95c8e4b..5189b388693 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/smb_shares/OWNERS
+++ b/chromium/ui/webui/resources/cr_components/chromeos/smb_shares/OWNERS
@@ -1 +1 @@
-khorimoto@chromium.org \ No newline at end of file
+khorimoto@chromium.org
diff --git a/chromium/ui/webui/resources/cr_components/customize_themes/OWNERS b/chromium/ui/webui/resources/cr_components/customize_themes/OWNERS
index 66d3eb7d65c..9ff00b8db5e 100644
--- a/chromium/ui/webui/resources/cr_components/customize_themes/OWNERS
+++ b/chromium/ui/webui/resources/cr_components/customize_themes/OWNERS
@@ -1,4 +1,3 @@
-aee@chromium.org
alexilin@chromium.org
mahmadi@chromium.org
tiborg@chromium.org
diff --git a/chromium/ui/webui/resources/cr_components/customize_themes/customize_themes.html b/chromium/ui/webui/resources/cr_components/customize_themes/customize_themes.html
index e5c0dc13012..2089fca68a2 100644
--- a/chromium/ui/webui/resources/cr_components/customize_themes/customize_themes.html
+++ b/chromium/ui/webui/resources/cr_components/customize_themes/customize_themes.html
@@ -68,6 +68,7 @@
}
#autogeneratedThemeContainer {
+ cursor: pointer;
position: relative;
}
diff --git a/chromium/ui/webui/resources/cr_components/managed_footnote/BUILD.gn b/chromium/ui/webui/resources/cr_components/managed_footnote/BUILD.gn
index 3f4a86dcdc7..b18cd08e05f 100644
--- a/chromium/ui/webui/resources/cr_components/managed_footnote/BUILD.gn
+++ b/chromium/ui/webui/resources/cr_components/managed_footnote/BUILD.gn
@@ -3,39 +3,22 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
-import("//tools/polymer/polymer.gni")
+import("//tools/polymer/html_to_js.gni")
-js_type_check("closure_compile") {
- uses_legacy_modules = true
- deps = [ ":managed_footnote" ]
-}
-
-js_library("managed_footnote") {
- deps = [
- "//ui/webui/resources/js:i18n_behavior",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- ]
-}
-
-polymer_modulizer("managed_footnote") {
- js_file = "managed_footnote.js"
- html_file = "managed_footnote.html"
- html_type = "dom-module"
+html_to_js("web_components") {
+ js_files = [ "managed_footnote.js" ]
}
-js_type_check("closure_compile_module") {
+js_type_check("closure_compile") {
is_polymer3 = true
- deps = [ ":managed_footnote.m" ]
+ deps = [ ":managed_footnote" ]
}
-js_library("managed_footnote.m") {
- sources = [ "$root_gen_dir/ui/webui/resources/cr_components/managed_footnote/managed_footnote.m.js" ]
+js_library("managed_footnote") {
deps = [
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/js:i18n_behavior.m",
"//ui/webui/resources/js:load_time_data.m",
"//ui/webui/resources/js:web_ui_listener_behavior.m",
]
- extra_deps = [ ":managed_footnote_module" ]
}
diff --git a/chromium/ui/webui/resources/cr_components/managed_footnote/managed_footnote.d.ts b/chromium/ui/webui/resources/cr_components/managed_footnote/managed_footnote.d.ts
new file mode 100644
index 00000000000..d74515769dd
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/managed_footnote/managed_footnote.d.ts
@@ -0,0 +1,17 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js';
+
+interface ManagedFootnoteElement extends LegacyElementMixin, HTMLElement {
+ showDeviceInfo: boolean;
+}
+
+export {ManagedFootnoteElement};
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'managed-footnote': ManagedFootnoteElement;
+ }
+}
diff --git a/chromium/ui/webui/resources/cr_components/managed_footnote/managed_footnote.html b/chromium/ui/webui/resources/cr_components/managed_footnote/managed_footnote.html
index fc3dc1d2826..6b0617314aa 100644
--- a/chromium/ui/webui/resources/cr_components/managed_footnote/managed_footnote.html
+++ b/chromium/ui/webui/resources/cr_components/managed_footnote/managed_footnote.html
@@ -1,15 +1,3 @@
-<link rel="import" href="../../html/polymer.html">
-
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
-<link rel="import" href="../../cr_elements/icons.html">
-<link rel="import" href="../../cr_elements/shared_vars_css.html">
-<link rel="import" href="../../html/i18n_behavior.html">
-<link rel="import" href="../../html/load_time_data.html">
-<link rel="import" href="../../html/web_ui_listener_behavior.html">
-
-<dom-module id="managed-footnote">
- <template>
<style>
:host {
align-items: center;
@@ -46,6 +34,3 @@
inner-h-t-m-l="[[getManagementString_(showDeviceInfo)]]">
</div>
</template>
- </template>
- <script src="managed_footnote.js"></script>
-</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/managed_footnote/managed_footnote.js b/chromium/ui/webui/resources/cr_components/managed_footnote/managed_footnote.js
index 468dd537b53..8bc144c89e7 100644
--- a/chromium/ui/webui/resources/cr_components/managed_footnote/managed_footnote.js
+++ b/chromium/ui/webui/resources/cr_components/managed_footnote/managed_footnote.js
@@ -11,10 +11,22 @@
* becomes visible.
*/
-(function() {
+import '//resources/polymer/v3_0/iron-icon/iron-icon.js';
+import '//resources/polymer/v3_0/paper-styles/color.js';
+import '../../cr_elements/icons.m.js';
+import '../../cr_elements/shared_vars_css.m.js';
+
+import {html, Polymer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {I18nBehavior} from '../../js/i18n_behavior.m.js';
+import {loadTimeData} from '../../js/load_time_data.m.js';
+import {WebUIListenerBehavior} from '../../js/web_ui_listener_behavior.m.js';
+
Polymer({
is: 'managed-footnote',
+ _template: html`{__html_template__}`,
+
behaviors: [I18nBehavior, WebUIListenerBehavior],
properties: {
@@ -66,4 +78,3 @@ Polymer({
});
chrome.send('observeManagedUI');
-})();
diff --git a/chromium/ui/webui/resources/cr_elements/BUILD.gn b/chromium/ui/webui/resources/cr_elements/BUILD.gn
index 9580c9c4b16..316ee961c4c 100644
--- a/chromium/ui/webui/resources/cr_elements/BUILD.gn
+++ b/chromium/ui/webui/resources/cr_elements/BUILD.gn
@@ -51,6 +51,7 @@ preprocess_if_expr("preprocess_src") {
"cr_search_field/cr_search_field_behavior.js",
"cr_splitter/cr_splitter.js",
"find_shortcut_behavior.js",
+ "mouse_hoverable_mixin.js",
]
}
@@ -86,10 +87,6 @@ preprocess_if_expr("preprocess_polymer2") {
"cr_lazy_render/cr_lazy_render.js",
"cr_lottie/cr_lottie.html",
"cr_lottie/cr_lottie.js",
- "cr_profile_avatar_selector/cr_profile_avatar_selector_grid.html",
- "cr_profile_avatar_selector/cr_profile_avatar_selector_grid.js",
- "cr_profile_avatar_selector/cr_profile_avatar_selector.html",
- "cr_profile_avatar_selector/cr_profile_avatar_selector.js",
"cr_radio_button/cr_card_radio_button.html",
"cr_radio_button/cr_card_radio_button.js",
"cr_radio_button/cr_radio_button_behavior.html",
@@ -126,6 +123,14 @@ preprocess_if_expr("preprocess_polymer2") {
"shared_vars_css.html",
]
+ # TODO(crbug.com/1184053): Fully remove once no longer used by CrOS.
+ if (is_chromeos) {
+ in_files += [
+ "cr_searchable_drop_down/cr_searchable_drop_down.html",
+ "cr_searchable_drop_down/cr_searchable_drop_down.js",
+ ]
+ }
+
if (is_chromeos_ash) {
in_files += [
"chromeos/cros_color_overrides.html",
@@ -140,8 +145,6 @@ preprocess_if_expr("preprocess_polymer2") {
"chromeos/cr_picture/icons.html",
"chromeos/cr_picture/png.html",
"chromeos/cr_picture/png.js",
- "cr_searchable_drop_down/cr_searchable_drop_down.html",
- "cr_searchable_drop_down/cr_searchable_drop_down.js",
]
}
}
@@ -173,8 +176,8 @@ preprocess_if_expr("preprocess_generated") {
"cr_lottie/cr_lottie.m.js",
"cr_menu_selector/cr_menu_selector.js",
"cr_page_host_style_css.js",
- "cr_profile_avatar_selector/cr_profile_avatar_selector_grid.m.js",
- "cr_profile_avatar_selector/cr_profile_avatar_selector.m.js",
+ "cr_profile_avatar_selector/cr_profile_avatar_selector_grid.js",
+ "cr_profile_avatar_selector/cr_profile_avatar_selector.js",
"cr_radio_button/cr_card_radio_button.m.js",
"cr_radio_button/cr_radio_button_behavior.m.js",
"cr_radio_button/cr_radio_button.m.js",
@@ -207,6 +210,11 @@ preprocess_if_expr("preprocess_generated") {
"shared_vars_css.m.js",
]
+ # TODO(crbug.com/1184053): Fully remove once no longer used by CrOS.
+ if (is_chromeos) {
+ in_files += [ "cr_searchable_drop_down/cr_searchable_drop_down.m.js" ]
+ }
+
if (is_chromeos_ash) {
in_files += [
"chromeos/cros_color_overrides.m.js",
@@ -216,7 +224,6 @@ preprocess_if_expr("preprocess_generated") {
"chromeos/cr_picture/cr_picture_types.m.js",
"chromeos/cr_picture/icons.m.js",
"chromeos/cr_picture/png.m.js",
- "cr_searchable_drop_down/cr_searchable_drop_down.m.js",
]
}
}
@@ -235,7 +242,6 @@ group("closure_compile") {
"cr_input:closure_compile",
"cr_lottie:closure_compile",
"cr_menu_selector:closure_compile",
- "cr_profile_avatar_selector:closure_compile",
"cr_radio_button:closure_compile",
"cr_radio_group:closure_compile",
"cr_slider:closure_compile",
@@ -271,7 +277,7 @@ group("closure_compile") {
"policy:closure_compile_module",
]
- if (is_chromeos_ash) {
+ if (is_chromeos) {
deps += [
"chromeos:closure_compile",
@@ -299,6 +305,12 @@ js_library("cr_container_shadow_behavior") {
deps = [ "//ui/webui/resources/js:assert" ]
}
+js_library("mouse_hoverable_mixin") {
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+}
+
# Targets for auto-generating Polymer 3 JS Modules.
polymer_modulizer("action_link_css") {
@@ -382,7 +394,7 @@ group("polymer3_elements") {
"cr_link_row:cr_link_row_module",
"cr_lottie:cr_lottie_module",
"cr_menu_selector:web_components",
- "cr_profile_avatar_selector:polymer3_elements",
+ "cr_profile_avatar_selector:web_components",
"cr_radio_button:polymer3_elements",
"cr_radio_group:cr_radio_group_module",
"cr_search_field:web_components",
@@ -395,7 +407,7 @@ group("polymer3_elements") {
"policy:polymer3_elements",
]
- if (is_chromeos_ash) {
+ if (is_chromeos) {
public_deps += [
"chromeos:polymer3_elements",
diff --git a/chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.m.d.ts b/chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.m.d.ts
new file mode 100644
index 00000000000..463ed64e8b9
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.m.d.ts
@@ -0,0 +1,58 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js';
+
+export interface ShowAtConfig {
+ top?: number;
+ left?: number;
+ width?: number;
+ height?: number;
+ anchorAlignmentX?: number;
+ anchorAlignmentY?: number;
+ minX?: number;
+ minY?: number;
+ maxX?: number;
+ maxY?: number;
+ noOffset?: boolean;
+}
+
+export interface ShowAtPositionConfig {
+ top: number;
+ left: number;
+ width?: number;
+ height?: number;
+ anchorAlignmentX?: number;
+ anchorAlignmentY?: number;
+ minX?: number;
+ minY?: number;
+ maxX?: number;
+ maxY?: number;
+}
+
+export enum AnchorAlignment {
+ BEFORE_START = -2,
+ AFTER_START = -1,
+ CENTER = 0,
+ BEFORE_END = 1,
+ AFTER_END = 2,
+}
+
+interface CrActionMenuElement extends LegacyElementMixin, HTMLElement {
+ autoReposition: boolean|null|undefined;
+ open: boolean|null|undefined;
+ roleDescription: string|null|undefined;
+ getDialog(): HTMLDialogElement;
+ close(): void;
+ showAt(anchorElement: Element, opt_config?: ShowAtConfig|null): void;
+ showAtPosition(config: ShowAtPositionConfig): void;
+}
+
+export {CrActionMenuElement};
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'cr-action-menu': CrActionMenuElement;
+ }
+}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_actionable_row_style.html b/chromium/ui/webui/resources/cr_elements/cr_actionable_row_style.html
index f3e177fe021..15d1e7a3372 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_actionable_row_style.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_actionable_row_style.html
@@ -12,24 +12,31 @@
:host {
align-items: center;
align-self: stretch;
- cursor: pointer;
display: flex;
margin: 0;
outline: none;
}
- :host(:not([no-hover]):hover) {
+ /* [effectively-disabled_] is a private attribute to allow custom elements
+ * to toggle the attribute based on state, such as whether or not the
+ * internal control element is disabled, without affecting any public
+ * attributes or properties. */
+ :host(:not([effectively-disabled_])) {
+ cursor: pointer;
+ }
+
+ :host(:not([no-hover], [effectively-disabled_]):hover) {
background-color: var(--cr-hover-background-color);
}
- :host(:not([no-hover]):active) {
+ :host(:not([no-hover], [effectively-disabled_]):active) {
background-color: var(--cr-active-background-color);
}
/* Do not show hover or active states for cr-icon-buttons that are
* embedded within the row to avoid showing multiple layers of
* backgrounds. */
- :host(:not([no-hover])) cr-icon-button {
+ :host(:not([no-hover], [effectively-disabled_])) cr-icon-button {
--cr-icon-button-hover-background-color: transparent;
--cr-icon-button-active-background-color: transparent;
}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_button/cr_button.html b/chromium/ui/webui/resources/cr_elements/cr_button/cr_button.html
index dcff6dafb5e..7d6bb600f4b 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_button/cr_button.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_button/cr_button.html
@@ -74,6 +74,7 @@
justify-content: center;
min-width: 5.14em;
outline-width: 0;
+ overflow: hidden;
padding: 8px 16px;
position: relative;
user-select: none;
diff --git a/chromium/ui/webui/resources/cr_elements/cr_button/cr_button.m.d.ts b/chromium/ui/webui/resources/cr_elements/cr_button/cr_button.m.d.ts
new file mode 100644
index 00000000000..782075c98a5
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_button/cr_button.m.d.ts
@@ -0,0 +1,19 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js';
+
+interface CrButtonElement extends LegacyElementMixin, HTMLElement {
+ disabled: boolean|null|undefined;
+ customTabIndex: number|null|undefined;
+ hostAttributes: object|null;
+}
+
+export {CrButtonElement};
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'cr-button': CrButtonElement;
+ }
+}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.m.d.ts b/chromium/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.m.d.ts
new file mode 100644
index 00000000000..3e5b847a023
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.m.d.ts
@@ -0,0 +1,22 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js';
+
+interface CrCheckboxElement extends LegacyElementMixin, HTMLElement {
+ checked: boolean|null|undefined;
+ disabled: boolean|null|undefined;
+ ariaDescription: string|null|undefined;
+ tabIndex: number;
+ focus(): void;
+ getFocusableElement(): Element;
+}
+
+export {CrCheckboxElement};
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'cr-checkbox': CrCheckboxElement;
+ }
+}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_container_shadow_behavior.m.d.ts b/chromium/ui/webui/resources/cr_elements/cr_container_shadow_behavior.m.d.ts
new file mode 100644
index 00000000000..f45debcaa10
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_container_shadow_behavior.m.d.ts
@@ -0,0 +1,12 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+export {CrContainerShadowBehavior};
+
+interface CrContainerShadowBehavior {
+ enableShadowBehavior(enable: boolean): void;
+ showDropShadows(): void;
+}
+
+declare const CrContainerShadowBehavior: object;
diff --git a/chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html b/chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
index 66a36e9747a..42af22f1c83 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
@@ -65,7 +65,7 @@
:host ::slotted([slot=body]) {
color: var(--cr-secondary-text-color);
- padding: 0 20px;
+ padding: 0 var(--cr-dialog-body-padding-horizontal, 20px);
}
:host ::slotted([slot=title]) {
@@ -83,9 +83,9 @@
:host ::slotted([slot=button-container]) {
display: flex;
justify-content: flex-end;
- padding-bottom: 16px;
- padding-inline-end: 16px;
- padding-inline-start: 16px;
+ padding-bottom: var(--cr-dialog-button-container-padding-bottom, 16px);
+ padding-inline-end: var(--cr-dialog-button-container-padding-horizontal, 16px);
+ padding-inline-start: var(--cr-dialog-button-container-padding-horizontal, 16px);
padding-top: 24px;
}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.m.d.ts b/chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.m.d.ts
new file mode 100644
index 00000000000..0b235244d2a
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.m.d.ts
@@ -0,0 +1,32 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js';
+import {CrContainerShadowBehavior} from '../cr_container_shadow_behavior.m.js';
+
+interface CrDialogElement extends CrContainerShadowBehavior, LegacyElementMixin,
+ HTMLElement {
+ open: boolean|null|undefined;
+ closeText: string|null|undefined;
+ ignorePopstate: boolean|null|undefined;
+ ignoreEnterKey: boolean|null|undefined;
+ consumeKeydownEvent: boolean|null|undefined;
+ noCancel: boolean|null|undefined;
+ showCloseButton: boolean|null|undefined;
+ showOnAttach: boolean|null|undefined;
+ showModal(): void;
+ cancel(): void;
+ close(): void;
+ setTitleAriaLabel(title: string): void;
+ getNative(): HTMLDialogElement;
+ focus(): void;
+}
+
+export {CrDialogElement};
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'cr-dialog': CrDialogElement;
+ }
+}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.d.ts b/chromium/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.d.ts
new file mode 100644
index 00000000000..d3fdbbc6fb7
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.d.ts
@@ -0,0 +1,26 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js';
+
+interface CrDrawerElement extends LegacyElementMixin, HTMLElement {
+ heading: string|null|undefined;
+ align: string|null|undefined;
+ iconName: string|null|undefined;
+ iconTitle: string|null|undefined;
+ open: any;
+ toggle(): void;
+ openDrawer(): void;
+ cancel(): void;
+ close(): void;
+ wasCanceled(): boolean;
+}
+
+export {CrDrawerElement};
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'cr-drawer': CrDrawerElement;
+ }
+}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_grid/cr_grid.js b/chromium/ui/webui/resources/cr_elements/cr_grid/cr_grid.js
index 03203ca71f7..21963e4a923 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_grid/cr_grid.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_grid/cr_grid.js
@@ -17,15 +17,20 @@ export class CrGridElement extends PolymerElement {
static get properties() {
return {
- /** @type {number} */
columns: {
type: Number,
- value: 1,
observer: 'onColumnsChange_',
},
};
}
+ constructor() {
+ super();
+
+ /** @type {number} */
+ this.columns = 1;
+ }
+
/** @private */
onColumnsChange_() {
this.updateStyles({'--cr-grid-columns': this.columns});
diff --git a/chromium/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.m.d.ts b/chromium/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.m.d.ts
new file mode 100644
index 00000000000..cc31c31044c
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.m.d.ts
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js';
+
+interface CrIconButtonElement extends LegacyElementMixin, HTMLElement {
+ disabled: boolean|null|undefined;
+ customTabIndex: number|null|undefined;
+ ironIcon: string|null|undefined;
+ hostAttributes: object|null;
+}
+
+export {CrIconButtonElement};
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'cr-icon-button': CrIconButtonElement;
+ }
+}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.html b/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.html
index 13d6012b761..3beffd1920f 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.html
@@ -139,6 +139,7 @@
readonly$="[[readonly]]" maxlength$="[[maxlength]]"
pattern$="[[pattern]]" required="[[required]]"
minlength$="[[minlength]]" inputmode$="[[inputmode]]"
+ aria-description$="[[ariaDescription]]"
aria-label$="[[getAriaLabel_(ariaLabel, label, placeholder)]]"
aria-invalid$="[[getAriaInvalid_(invalid)]]"
max="[[max]]" min="[[min]]" on-focus="onInputFocus_"
@@ -151,7 +152,7 @@
</div>
<slot name="suffix"></slot>
</div>
- <div id="error">[[displayErrorMessage_]]</div>
+ <div id="error" aria-live="assertive">[[displayErrorMessage_]]</div>
</template>
<script src="cr_input.js"></script>
</dom-module>
diff --git a/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.js b/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.js
index 1c455bbb1ad..3019a6329c8 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.js
@@ -52,6 +52,11 @@ Polymer({
is: 'cr-input',
properties: {
+ /** @type {string|undefined} */
+ ariaDescription: {
+ type: String,
+ },
+
ariaLabel: {
type: String,
value: '',
diff --git a/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.m.d.ts b/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.m.d.ts
new file mode 100644
index 00000000000..233212f1a77
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.m.d.ts
@@ -0,0 +1,42 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js';
+
+interface CrInputElement extends LegacyElementMixin, HTMLElement {
+ ariaDescription: string|undefined;
+ ariaLabel: string|null|undefined;
+ autofocus: boolean;
+ autoValidate: boolean|null|undefined;
+ disabled: boolean|null|undefined;
+ errorMessage: string|null|undefined;
+ invalid: boolean|null|undefined;
+ max: number|null|undefined;
+ min: number|null|undefined;
+ maxlength: number|null|undefined;
+ minlength: number|null|undefined;
+ pattern: string|null|undefined;
+ inputmode: string|null|undefined;
+ label: string|null|undefined;
+ placeholder: string|null;
+ readonly: boolean|null|undefined;
+ required: boolean|null|undefined;
+ tabindex: number|null;
+ type: string|null|undefined;
+ value: string|null|undefined;
+ hostAttributes: object|null;
+ readonly inputElement: HTMLInputElement;
+
+ focusInput(): boolean;
+ select(start?: number, end?: number): void;
+ validate(): boolean;
+}
+
+export {CrInputElement};
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'cr-input': CrInputElement;
+ }
+}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_lazy_render/cr_lazy_render.m.d.ts b/chromium/ui/webui/resources/cr_elements/cr_lazy_render/cr_lazy_render.m.d.ts
new file mode 100644
index 00000000000..7f9abac7f1f
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_lazy_render/cr_lazy_render.m.d.ts
@@ -0,0 +1,18 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js';
+
+interface CrLazyRenderElement extends LegacyElementMixin, HTMLElement {
+ get(): Element;
+ getIfExists(): (Element|null);
+}
+
+export {CrLazyRenderElement};
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'cr-lazy-render': CrLazyRenderElement;
+ }
+}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/BUILD.gn b/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/BUILD.gn
index 9090f8c61b6..4a7fd4d82bc 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/BUILD.gn
+++ b/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/BUILD.gn
@@ -3,82 +3,35 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
-import("//tools/polymer/polymer.gni")
+import("//tools/polymer/html_to_js.gni")
-js_type_check("closure_compile") {
- uses_legacy_modules = true
- deps = [
- ":cr_profile_avatar_selector",
- ":cr_profile_avatar_selector_grid",
- ]
-}
-
-js_library("cr_profile_avatar_selector") {
- deps = [
- ":cr_profile_avatar_selector_grid",
- "//ui/webui/resources/js:icon",
- ]
-}
-
-js_library("cr_profile_avatar_selector_grid") {
- deps = [
- "//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:util",
- ]
-}
-
-group("polymer3_elements") {
- public_deps = [
- ":cr_profile_avatar_selector_grid_module",
- ":cr_profile_avatar_selector_module",
- ]
-}
-
-polymer_modulizer("cr_profile_avatar_selector") {
- js_file = "cr_profile_avatar_selector.js"
- html_file = "cr_profile_avatar_selector.html"
- html_type = "dom-module"
- namespace_rewrites = [ "cr.icon.getImage|getImage" ]
- auto_imports = [
- "ui/webui/resources/html/assert.html|assert",
- "ui/webui/resources/html/icon.html|getImage",
- ]
-}
-
-polymer_modulizer("cr_profile_avatar_selector_grid") {
- js_file = "cr_profile_avatar_selector_grid.js"
- html_file = "cr_profile_avatar_selector_grid.html"
- html_type = "dom-module"
- auto_imports = [
- "ui/webui/resources/html/assert.html|assert",
- "ui/webui/resources/html/util.html|hasKeyModifiers",
+html_to_js("web_components") {
+ js_files = [
+ "cr_profile_avatar_selector_grid.js",
+ "cr_profile_avatar_selector.js",
]
}
js_type_check("closure_compile_module") {
is_polymer3 = true
deps = [
- ":cr_profile_avatar_selector.m",
- ":cr_profile_avatar_selector_grid.m",
+ ":cr_profile_avatar_selector",
+ ":cr_profile_avatar_selector_grid",
]
}
-js_library("cr_profile_avatar_selector.m") {
- sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.m.js" ]
+js_library("cr_profile_avatar_selector") {
deps = [
- ":cr_profile_avatar_selector_grid.m",
+ ":cr_profile_avatar_selector_grid",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/js:icon.m",
]
- extra_deps = [ ":cr_profile_avatar_selector_module" ]
}
-js_library("cr_profile_avatar_selector_grid.m") {
- sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector_grid.m.js" ]
+js_library("cr_profile_avatar_selector_grid") {
deps = [
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/js:assert.m",
"//ui/webui/resources/js:util.m",
]
- extra_deps = [ ":cr_profile_avatar_selector_grid_module" ]
}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html b/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html
index 7bf7f4a1e7e..fe45be1e39d 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html
@@ -1,15 +1,3 @@
-<link rel="import" href="../../html/polymer.html">
-
-<link rel="import" href="../cr_button/cr_button.html">
-<link rel="import" href="../shared_vars_css.html">
-<link rel="import" href="../shared_style_css.html">
-<link rel="import" href="../../html/icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-tooltip/paper-tooltip.html">;
-<link rel="import" href="cr_profile_avatar_selector_grid.html">
-
-<dom-module id="cr-profile-avatar-selector">
- <template>
<style include="cr-shared-style">
:host {
--avatar-size: 96px;
@@ -87,6 +75,3 @@
</paper-tooltip>
</template>
</cr-profile-avatar-selector-grid>
- </template>
- <script src="cr_profile_avatar_selector.js"></script>
-</dom-module>
diff --git a/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js b/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js
index 9b7a4e708c0..f0b92a1b396 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js
@@ -14,11 +14,23 @@
* isGaiaAvatar: (boolean),
* selected: (boolean)}}
*/
-/* #export */ let AvatarIcon;
+export let AvatarIcon;
+
+import {Polymer, html} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import '../cr_button/cr_button.m.js';
+import '../shared_vars_css.m.js';
+import '../shared_style_css.m.js';
+import {getImage} from '../../js/icon.m.js';
+import '//resources/polymer/v3_0/paper-styles/color.js';
+import '//resources/polymer/v3_0/paper-tooltip/paper-tooltip.js';
+import './cr_profile_avatar_selector_grid.js';
Polymer({
is: 'cr-profile-avatar-selector',
+ _template: html`{__html_template__}`,
+
properties: {
/**
* The list of profile avatar URLs and labels.
@@ -127,7 +139,7 @@ Polymer({
* @private
*/
getIconImageSet_(iconUrl) {
- return cr.icon.getImage(iconUrl);
+ return getImage(iconUrl);
},
/**
@@ -141,4 +153,3 @@ Polymer({
/** @type {!{model: {item: !AvatarIcon}}} */ (e).model.item;
},
});
-/* #ignore */ console.warn('crbug/1173575, non-JS module files deprecated.');
diff --git a/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector_grid.html b/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector_grid.html
index 8c590b02f13..0fdcbd0a9e9 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector_grid.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector_grid.html
@@ -1,10 +1,3 @@
-<link rel="import" href="../../html/polymer.html">
-
-<link rel="import" href="../../html/assert.html">
-<link rel="import" href="../../html/util.html">
-
-<dom-module id="cr-profile-avatar-selector-grid">
- <template>
<style>
:host {
display: inline-flex;
@@ -13,6 +6,3 @@
}
</style>
<slot></slot>
- </template>
- <script src="cr_profile_avatar_selector_grid.js"></script>
-</dom-module>
diff --git a/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector_grid.js b/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector_grid.js
index 5e223742c5c..4861abeefae 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector_grid.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector_grid.js
@@ -7,9 +7,16 @@
* profile avatar icons that allows keyboard navigation with all arrow keys.
*/
+import {html, Polymer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {assert} from '../../js/assert.m.js';
+import {hasKeyModifiers} from '../../js/util.m.js';
+
Polymer({
is: 'cr-profile-avatar-selector-grid',
+ _template: html`{__html_template__}`,
+
properties: {
ignoreModifiedKeyEvents: {
type: Boolean,
@@ -95,4 +102,3 @@ Polymer({
assert(this.parentNode.activeElement === nextItem);
}
});
-/* #ignore */ console.warn('crbug/1173575, non-JS module files deprecated.');
diff --git a/chromium/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js b/chromium/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js
index 115f054e170..5b5bdfe327c 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js
@@ -58,7 +58,7 @@
/** @private {Array<!CrRadioButtonElement>} */
buttons_: null,
- /** @private {EventTracker} */
+ /** @private {cr.EventTracker} */
buttonEventTracker_: null,
/** @private {Map<string, number>} */
@@ -84,7 +84,7 @@
['PageDown', 1],
['PageUp', -1],
]);
- this.buttonEventTracker_ = new EventTracker();
+ this.buttonEventTracker_ = new cr.EventTracker();
this.populateBound_ = () => this.populate_();
// Needed for when the radio buttons change when using dom-repeat or
diff --git a/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.d.ts b/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.d.ts
new file mode 100644
index 00000000000..291713ade04
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.d.ts
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+export interface CrSearchFieldBehaviorInterface {
+ label: string;
+ clearLabel: string;
+ hasSearchText: boolean;
+ getSearchInput(): HTMLInputElement;
+ getValue(): string;
+ setValue(value: string, noEvent?: boolean): void;
+ onSearchTermSearch(): void;
+ onSearchTermInput(): void;
+}
+
+export {CrSearchFieldBehavior};
+
+interface CrSearchFieldBehavior extends CrSearchFieldBehaviorInterface {}
+
+declare const CrSearchFieldBehavior: object;
diff --git a/chromium/ui/webui/resources/cr_elements/cr_slider/OWNERS b/chromium/ui/webui/resources/cr_elements/cr_slider/OWNERS
deleted file mode 100644
index 4a5f69474e8..00000000000
--- a/chromium/ui/webui/resources/cr_elements/cr_slider/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-aee@chromium.org
diff --git a/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.js b/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.js
index 9ce4c4a2498..064e8456d72 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.js
@@ -187,7 +187,7 @@ cr.define('cr_slider', function() {
/** @private {Map<string, number>} */
deltaKeyMap_: null,
- /** @private {EventTracker} */
+ /** @private {cr.EventTracker} */
draggingEventTracker_: null,
/** @override */
@@ -201,7 +201,7 @@ cr.define('cr_slider', function() {
['ArrowLeft', this.isRtl_ ? 1 : -1],
['ArrowRight', this.isRtl_ ? -1 : 1],
]);
- this.draggingEventTracker_ = new EventTracker();
+ this.draggingEventTracker_ = new cr.EventTracker();
},
/**
diff --git a/chromium/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.js b/chromium/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.js
index 6a6bd4e7a3a..c2f0fc7f709 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.js
@@ -15,10 +15,7 @@ export class CrSplitterElement extends PolymerElement {
static get properties() {
return {
- resizeNextElement: {
- type: Boolean,
- value: false,
- },
+ resizeNextElement: Boolean,
};
}
@@ -33,6 +30,9 @@ export class CrSplitterElement extends PolymerElement {
/** @private {number} */
this.startWidth_ = -1;
+
+ /** @type {boolean} */
+ this.resizeNextElement = false;
}
ready() {
diff --git a/chromium/ui/webui/resources/cr_elements/cr_tabs/cr_tabs.html b/chromium/ui/webui/resources/cr_elements/cr_tabs/cr_tabs.html
index 3b51d9059c2..39ceb68df49 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_tabs/cr_tabs.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_tabs/cr_tabs.html
@@ -11,6 +11,11 @@
user-select: none;
}
+ :host([new-material]) {
+ cursor: auto;
+ justify-content: space-around;
+ }
+
.tab {
align-items: center;
color: var(--cr-secondary-text-color);
@@ -22,6 +27,12 @@
transition: opacity 100ms cubic-bezier(.4, 0, 1, 1);
}
+ :host([new-material]) .tab {
+ cursor: pointer;
+ flex: 0;
+ white-space: nowrap;
+ }
+
:host(:not(.keyboard-focus)) .tab {
outline: none;
}
@@ -56,6 +67,22 @@
transition: transform;
}
+ :host([new-material]) #selectionBar {
+ background: var(--google-blue-600);
+ border: none;
+ border-radius: 3px 3px 0 0;
+ height: 3px;
+ opacity: 0;
+ overflow: hidden;
+ transform: none;
+ }
+
+ :host([new-material]) #selectionBar.initiated {
+ opacity: 1;
+ transition: transform 250ms cubic-bezier(.4, 0, .2, 1),
+ width 250ms cubic-bezier(.4, 0, .2, 1);
+ }
+
@media (prefers-color-scheme: dark) {
#selectionBar {
border-bottom-color: var(--google-blue-refresh-300);
diff --git a/chromium/ui/webui/resources/cr_elements/cr_tabs/cr_tabs.js b/chromium/ui/webui/resources/cr_elements/cr_tabs/cr_tabs.js
index 6dca04e0e24..34714713d33 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_tabs/cr_tabs.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_tabs/cr_tabs.js
@@ -125,6 +125,18 @@ Polymer({
const leftPercent = 100 * left / containerWidth;
const widthRatio = width / containerWidth;
+ if (this.hasAttribute('new-material')) {
+ // Initiate with initial transform and width, then add |initiated| class
+ // in a timeout so that only all subsequent updates to transform and width
+ // are transitioned.
+ this.$.selectionBar.style.transform = `translateX(${left}px)`;
+ this.$.selectionBar.style.width = `${width}px`;
+ setTimeout(() => {
+ this.$.selectionBar.classList.add('initiated');
+ });
+ return;
+ }
+
// When there are two tabs, the selection bar will expand to underline both
// tabs. If a user quickly changes tabs multiple times, the selection bar
// will no longer have any room to expand the transitionend event will be
@@ -182,6 +194,12 @@ Polymer({
return;
}
+ if (this.hasAttribute('new-material')) {
+ const selectedTab = tabs[this.selected];
+ this.updateSelectionBar_(selectedTab.offsetLeft, selectedTab.offsetWidth);
+ return;
+ }
+
// Expand bar to underline the last selected tab, the newly selected tab and
// everything in between. After expansion is complete, contract bar to
// underline the selected tab.
diff --git a/chromium/ui/webui/resources/cr_elements/cr_toast/cr_toast.m.d.ts b/chromium/ui/webui/resources/cr_elements/cr_toast/cr_toast.m.d.ts
new file mode 100644
index 00000000000..bab14da47c5
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_toast/cr_toast.m.d.ts
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js';
+
+interface CrToastElement extends LegacyElementMixin, HTMLElement {
+ duration: number|null|undefined;
+ readonly open: boolean|null|undefined;
+ show(): void;
+ hide(): void;
+}
+
+export {CrToastElement};
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'cr-toast': CrToastElement;
+ }
+}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.js b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.js
index 98d4d1fda4b..46f862f22c6 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.js
@@ -4,82 +4,90 @@
import '../cr_icon_button/cr_icon_button.m.js';
import '../cr_icons_css.m.js';
-import './cr_toolbar_search_field.js';
import '../hidden_style_css.m.js';
import '../icons.m.js';
import '../shared_vars_css.m.js';
import '//resources/polymer/v3_0/iron-media-query/iron-media-query.js';
-import {html, Polymer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-Polymer({
- is: 'cr-toolbar',
+import {CrToolbarSearchFieldElement} from './cr_toolbar_search_field.js';
- _template: html`{__html_template__}`,
-
- properties: {
- // Name to display in the toolbar, in titlecase.
- pageName: String,
-
- // Prompt text to display in the search field.
- searchPrompt: String,
-
- // Tooltip to display on the clear search button.
- clearLabel: String,
-
- // Tooltip to display on the menu button.
- menuLabel: String,
-
- // Value is proxied through to cr-toolbar-search-field. When true,
- // the search field will show a processing spinner.
- spinnerActive: Boolean,
-
- // Controls whether the menu button is shown at the start of the menu.
- showMenu: {type: Boolean, value: false},
-
- // Controls whether the search field is shown.
- showSearch: {type: Boolean, value: true},
-
- // Controls whether the search field is autofocused.
- autofocus: {
- type: Boolean,
- value: false,
- reflectToAttribute: true,
- },
-
- // True when the toolbar is displaying in narrow mode.
- narrow: {
- type: Boolean,
- reflectToAttribute: true,
- readonly: true,
- notify: true,
- },
+export class CrToolbarElement extends PolymerElement {
+ static get is() {
+ return 'cr-toolbar';
+ }
- /**
- * The threshold at which the toolbar will change from normal to narrow
- * mode, in px.
- */
- narrowThreshold: {
- type: Number,
- value: 900,
- },
+ static get template() {
+ return html`{__html_template__}`;
+ }
- /** @private */
- showingSearch_: {
- type: Boolean,
- reflectToAttribute: true,
- },
- },
+ static get properties() {
+ return {
+ // Name to display in the toolbar, in titlecase.
+ pageName: String,
+
+ // Prompt text to display in the search field.
+ searchPrompt: String,
+
+ // Tooltip to display on the clear search button.
+ clearLabel: String,
+
+ // Tooltip to display on the menu button.
+ menuLabel: String,
+
+ // Value is proxied through to cr-toolbar-search-field. When true,
+ // the search field will show a processing spinner.
+ spinnerActive: Boolean,
+
+ // Controls whether the menu button is shown at the start of the menu.
+ showMenu: {type: Boolean, value: false},
+
+ // Controls whether the search field is shown.
+ showSearch: {type: Boolean, value: true},
+
+ // Controls whether the search field is autofocused.
+ autofocus: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
+
+ // True when the toolbar is displaying in narrow mode.
+ narrow: {
+ type: Boolean,
+ reflectToAttribute: true,
+ readonly: true,
+ notify: true,
+ },
+
+ /**
+ * The threshold at which the toolbar will change from normal to narrow
+ * mode, in px.
+ */
+ narrowThreshold: {
+ type: Number,
+ value: 900,
+ },
+
+ /** @private */
+ showingSearch_: {
+ type: Boolean,
+ reflectToAttribute: true,
+ },
+ };
+ }
/** @return {!CrToolbarSearchFieldElement} */
getSearchField() {
return /** @type {!CrToolbarSearchFieldElement} */ (this.$.search);
- },
+ }
/** @private */
onMenuTap_() {
- this.fire('cr-toolbar-menu-tap');
- },
+ this.dispatchEvent(new CustomEvent(
+ 'cr-toolbar-menu-tap', {bubbles: true, composed: true}));
+ }
focusMenuButton() {
requestAnimationFrame(() => {
@@ -90,11 +98,13 @@ Polymer({
menuButton.focus();
}
});
- },
+ }
/** @return {boolean} */
isMenuFocused() {
return Boolean(this.shadowRoot.activeElement) &&
this.shadowRoot.activeElement.id === 'menuButton';
}
-});
+}
+
+customElements.define(CrToolbarElement.is, CrToolbarElement);
diff --git a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.d.ts b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.d.ts
new file mode 100644
index 00000000000..e619a792235
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.d.ts
@@ -0,0 +1,30 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js';
+
+import {CrSearchFieldBehaviorInterface} from '../cr_search_field/cr_search_field_behavior.js';
+
+interface CrToolbarSearchFieldElement extends CrSearchFieldBehaviorInterface,
+ LegacyElementMixin, HTMLElement {
+ narrow: boolean;
+ showingSearch: boolean;
+ autofocus: boolean;
+ label: string;
+ clearLabel: string;
+ spinnerActive: boolean;
+
+ getSearchInput(): HTMLInputElement;
+ isSearchFocused(): boolean;
+ showAndFocus(): void;
+ onSearchTermInput(): void;
+}
+
+export {CrToolbarSearchFieldElement};
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'cr-toolbar-search-field': CrToolbarSearchFieldElement;
+ }
+}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js
index 47be44f37d3..15dd22e2e4f 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js
@@ -9,91 +9,108 @@ import '../shared_style_css.m.js';
import '../shared_vars_css.m.js';
import '//resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js';
-import {html, Polymer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-import {CrSearchFieldBehavior} from '../cr_search_field/cr_search_field_behavior.js';
-
-Polymer({
- is: 'cr-toolbar-search-field',
-
- _template: html`{__html_template__}`,
-
- behaviors: [CrSearchFieldBehavior],
-
- properties: {
- narrow: {
- type: Boolean,
- reflectToAttribute: true,
- },
-
- showingSearch: {
- type: Boolean,
- value: false,
- notify: true,
- observer: 'showingSearchChanged_',
- reflectToAttribute: true
- },
-
- autofocus: {
- type: Boolean,
- value: false,
- reflectToAttribute: true,
- },
-
- // Prompt text to display in the search field.
- label: String,
-
- // Tooltip to display on the clear search button.
- clearLabel: String,
-
- // When true, show a loading spinner to indicate that the backend is
- // processing the search. Will only show if the search field is open.
- spinnerActive: {type: Boolean, reflectToAttribute: true},
-
- /** @private */
- isSpinnerShown_: {
- type: Boolean,
- computed: 'computeIsSpinnerShown_(spinnerActive, showingSearch)'
- },
-
- /** @private */
- searchFocused_: {type: Boolean, value: false},
- },
-
- listeners: {
- // Deliberately uses 'click' instead of 'tap' to fix crbug.com/624356.
- 'click': 'showSearch_',
- },
+import {html, mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {CrSearchFieldBehavior, CrSearchFieldBehaviorInterface} from '../cr_search_field/cr_search_field_behavior.js';
+
+/**
+ * @constructor
+ * @extends {PolymerElement}
+ * @implements {CrSearchFieldBehaviorInterface}
+ */
+const CrToolbarSearchFieldElementBase =
+ mixinBehaviors(CrSearchFieldBehavior, PolymerElement);
+
+/** @polymer */
+export class CrToolbarSearchFieldElement extends
+ CrToolbarSearchFieldElementBase {
+ static get is() {
+ return 'cr-toolbar-search-field';
+ }
+
+ static get template() {
+ return html`{__html_template__}`;
+ }
+
+ static get properties() {
+ return {
+ narrow: {
+ type: Boolean,
+ reflectToAttribute: true,
+ },
+
+ showingSearch: {
+ type: Boolean,
+ value: false,
+ notify: true,
+ observer: 'showingSearchChanged_',
+ reflectToAttribute: true,
+ },
+
+ autofocus: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
+
+ // Prompt text to display in the search field.
+ label: String,
+
+ // Tooltip to display on the clear search button.
+ clearLabel: String,
+
+ // When true, show a loading spinner to indicate that the backend is
+ // processing the search. Will only show if the search field is open.
+ spinnerActive: {type: Boolean, reflectToAttribute: true},
+
+ /** @private */
+ isSpinnerShown_: {
+ type: Boolean,
+ computed: 'computeIsSpinnerShown_(spinnerActive, showingSearch)'
+ },
+
+ /** @private */
+ searchFocused_: {type: Boolean, value: false},
+ };
+ }
+
+ /** @override */
+ ready() {
+ super.ready();
+
+ this.addEventListener('click', e => this.showSearch_(e));
+ }
/** @return {!HTMLInputElement} */
getSearchInput() {
return /** @type {!HTMLInputElement} */ (this.$.searchInput);
- },
+ }
/** @return {boolean} */
isSearchFocused() {
return this.searchFocused_;
- },
+ }
showAndFocus() {
this.showingSearch = true;
this.focus_();
- },
+ }
onSearchTermInput() {
CrSearchFieldBehavior.onSearchTermInput.call(this);
this.showingSearch = this.hasSearchText || this.isSearchFocused();
- },
+ }
/** @private */
onSearchIconClicked_() {
- this.fire('search-icon-clicked');
- },
+ this.dispatchEvent(new CustomEvent(
+ 'search-icon-clicked', {bubbles: true, composed: true}));
+ }
/** @private */
focus_() {
this.getSearchInput().focus();
- },
+ }
/**
* @param {boolean} narrow
@@ -102,7 +119,7 @@ Polymer({
*/
computeIconTabIndex_(narrow) {
return narrow && !this.hasSearchText ? 0 : -1;
- },
+ }
/**
* @param {boolean} narrow
@@ -111,7 +128,7 @@ Polymer({
*/
computeIconAriaHidden_(narrow) {
return Boolean(!narrow || this.hasSearchText).toString();
- },
+ }
/**
* @return {boolean}
@@ -123,12 +140,12 @@ Polymer({
this.$.spinnerTemplate.if = true;
}
return showSpinner;
- },
+ }
/** @private */
onInputFocus_() {
this.searchFocused_ = true;
- },
+ }
/** @private */
onInputBlur_() {
@@ -136,14 +153,14 @@ Polymer({
if (!this.hasSearchText) {
this.showingSearch = false;
}
- },
+ }
/** @private */
onSearchTermKeydown_(e) {
if (e.key === 'Escape') {
this.showingSearch = false;
}
- },
+ }
/**
* @param {Event} e
@@ -153,7 +170,7 @@ Polymer({
if (e.target !== this.$.clearSearch) {
this.showingSearch = true;
}
- },
+ }
/**
* @param {Event} e
@@ -163,7 +180,7 @@ Polymer({
this.setValue('');
this.focus_();
this.spinnerActive = false;
- },
+ }
/**
* @param {boolean} current
@@ -183,5 +200,8 @@ Polymer({
this.setValue('');
this.getSearchInput().blur();
- },
-});
+ }
+}
+
+customElements.define(
+ CrToolbarSearchFieldElement.is, CrToolbarSearchFieldElement);
diff --git a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.js b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.js
index 280f185f5a2..ac7b5f28b22 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.js
@@ -13,82 +13,112 @@
* tab-traversal.
*/
-import {Polymer, html} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-import {IronA11yAnnouncer} from '//resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js';
import '../cr_button/cr_button.m.js';
import '../cr_icon_button/cr_icon_button.m.js';
import '../icons.m.js';
import '../shared_vars_css.m.js';
-Polymer({
- is: 'cr-toolbar-selection-overlay',
+import {IronA11yAnnouncer} from '//resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js';
+import {Debouncer, html, microTask, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+export class CrToolbarSelectionOverlayElement extends PolymerElement {
+ static get is() {
+ return 'cr-toolbar-selection-overlay';
+ }
- _template: html`{__html_template__}`,
+ static get template() {
+ return html`{__html_template__}`;
+ }
- properties: {
- show: {
- type: Boolean,
- observer: 'onShowChanged_',
- reflectToAttribute: true,
- },
+ static get properties() {
+ return {
+ show: {
+ type: Boolean,
+ observer: 'onShowChanged_',
+ reflectToAttribute: true,
+ },
- deleteLabel: String,
+ deleteLabel: String,
- cancelLabel: String,
+ cancelLabel: String,
- selectionLabel: String,
+ selectionLabel: String,
- deleteDisabled: Boolean,
+ deleteDisabled: Boolean,
- /** @private */
- hasShown_: Boolean,
+ /** @private */
+ hasShown_: Boolean,
- /** @private */
- selectionLabel_: String,
- },
+ /** @private */
+ selectionLabel_: String,
+ };
+ }
- observers: [
- 'updateSelectionLabel_(show, selectionLabel)',
- ],
+ static get observers() {
+ return [
+ 'updateSelectionLabel_(show, selectionLabel)',
+ ];
+ }
- hostAttributes: {
- 'role': 'toolbar',
- },
+ constructor() {
+ super();
+
+ /** @private {Debouncer} */
+ this.debouncer_;
+ }
+
+ ready() {
+ super.ready();
+ this.setAttribute('role', 'toolbar');
+ }
/** @return {HTMLElement} */
get deleteButton() {
- return /** @type {HTMLElement} */ (this.$$('#delete'));
- },
+ return /** @type {HTMLElement} */ (
+ this.shadowRoot.querySelector('#delete'));
+ }
+
+ /**
+ * @param {string} eventName
+ * @param {*=} detail
+ * @private
+ */
+ fire_(eventName, detail) {
+ this.dispatchEvent(
+ new CustomEvent(eventName, {bubbles: true, composed: true, detail}));
+ }
/** @private */
onClearSelectionClick_() {
- this.fire('clear-selected-items');
- },
+ this.fire_('clear-selected-items');
+ }
/** @private */
onDeleteClick_() {
- this.fire('delete-selected-items');
- },
+ this.fire_('delete-selected-items');
+ }
/** @private */
updateSelectionLabel_() {
// Do this update in a microtask to ensure |show| and |selectionLabel|
// are both updated.
- this.debounce('updateSelectionLabel_', () => {
+ this.debouncer_ = Debouncer.debounce(this.debouncer_, microTask, () => {
this.selectionLabel_ =
this.show ? this.selectionLabel : this.selectionLabel_;
this.setAttribute('aria-label', this.selectionLabel_);
IronA11yAnnouncer.requestAvailability();
- this.fire('iron-announce', {text: this.selectionLabel});
+ this.fire_('iron-announce', {text: this.selectionLabel});
});
- },
+ }
/** @private */
onShowChanged_() {
if (this.show) {
this.hasShown_ = true;
}
- },
-});
+ }
+}
+
+customElements.define(
+ CrToolbarSelectionOverlayElement.is, CrToolbarSelectionOverlayElement);
diff --git a/chromium/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.d.ts b/chromium/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.d.ts
new file mode 100644
index 00000000000..d0431fd228c
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.d.ts
@@ -0,0 +1,19 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js';
+
+interface CrViewManagerElement extends LegacyElementMixin, HTMLElement {
+ switchView(
+ newViewId: string, enterAnimation?: string,
+ exitAnimation?: string): Promise<any>;
+}
+
+export {CrViewManagerElement};
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'cr-view-manager': CrViewManagerElement;
+ }
+}
diff --git a/chromium/ui/webui/resources/cr_elements/find_shortcut_behavior.d.ts b/chromium/ui/webui/resources/cr_elements/find_shortcut_behavior.d.ts
new file mode 100644
index 00000000000..8926cb8b61c
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/find_shortcut_behavior.d.ts
@@ -0,0 +1,17 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+export interface FindShortcutBehaviorInterface {
+ findShortcutListenOnAttach: boolean;
+ becomeActiveFindShortcutListener(): void;
+ handleFindShortcut(modalContextOpen: boolean): boolean;
+ removeSelfAsFindShortcutListener(): void;
+ searchInputHasFocus(): boolean;
+}
+
+export {FindShortcutBehavior};
+
+interface FindShortcutBehavior extends FindShortcutBehaviorInterface {}
+
+declare const FindShortcutBehavior: object;
diff --git a/chromium/ui/webui/resources/cr_elements/find_shortcut_behavior.js b/chromium/ui/webui/resources/cr_elements/find_shortcut_behavior.js
index c39e6067101..751197032df 100644
--- a/chromium/ui/webui/resources/cr_elements/find_shortcut_behavior.js
+++ b/chromium/ui/webui/resources/cr_elements/find_shortcut_behavior.js
@@ -121,3 +121,28 @@ export const FindShortcutBehavior = {
assertNotReached();
},
};
+
+/** @interface */
+export class FindShortcutBehaviorInterface {
+ constructor() {
+ /**
+ * @type {boolean}
+ * @protected
+ */
+ this.findShortcutListenOnAttach = true;
+ }
+
+ becomeActiveFindShortcutListener() {}
+
+ /**
+ * If handled, return true.
+ * @param {boolean} modalContextOpen
+ * @return {boolean}
+ */
+ handleFindShortcut(modalContextOpen) {}
+
+ removeSelfAsFindShortcutListener() {}
+
+ /** @return {boolean} */
+ searchInputHasFocus() {}
+}
diff --git a/chromium/ui/webui/resources/cr_elements/mouse_hoverable_mixin.js b/chromium/ui/webui/resources/cr_elements/mouse_hoverable_mixin.js
new file mode 100644
index 00000000000..e503dd07a5d
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/mouse_hoverable_mixin.js
@@ -0,0 +1,50 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview This file provides a mixin to manage a `hovered` style on mouse
+ * events. Relies on listening for pointer events as touch devices may fire
+ * mouse events too.
+ */
+
+import {dedupingMixin} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+/** @type {string} */
+const HOVERED_STYLE = 'hovered';
+
+/** @interface */
+export class MouseHoverableMixinInterface {}
+
+/**
+ * @polymer
+ * @mixinFunction
+ */
+export const MouseHoverableMixin = dedupingMixin(superClass => {
+ /**
+ * @polymer
+ * @mixinClass
+ * @implements {MouseHoverableMixinInterface}
+ */
+ class MouseHoverableMixin extends superClass {
+ ready() {
+ super.ready();
+
+ this.addEventListener('pointerenter', (e) => {
+ const hostElement = /** @type {!Element} */ (e.currentTarget);
+ hostElement.classList.toggle(HOVERED_STYLE, e.pointerType === 'mouse');
+ });
+
+ this.addEventListener('pointerleave', (e) => {
+ if (e.pointerType !== 'mouse') {
+ return;
+ }
+
+ const hostElement = /** @type {!Element} */ (e.currentTarget);
+ hostElement.classList.remove(HOVERED_STYLE);
+ });
+ }
+ }
+
+ return MouseHoverableMixin;
+});
diff --git a/chromium/ui/webui/resources/cr_elements/mwb_shared_style.html b/chromium/ui/webui/resources/cr_elements/mwb_shared_style.html
index 0dc24281c8e..62a71dcfdf2 100644
--- a/chromium/ui/webui/resources/cr_elements/mwb_shared_style.html
+++ b/chromium/ui/webui/resources/cr_elements/mwb_shared_style.html
@@ -26,7 +26,7 @@
padding: 0 var(--mwb-list-item-horizontal-margin);
}
- .mwb-list-item:hover {
+ .mwb-list-item.hovered {
background-color: var(--mwb-list-item-hover-background-color);
}
diff --git a/chromium/ui/webui/resources/css/text_defaults.css b/chromium/ui/webui/resources/css/text_defaults.css
index 33942fba407..4724fdfa65f 100644
--- a/chromium/ui/webui/resources/css/text_defaults.css
+++ b/chromium/ui/webui/resources/css/text_defaults.css
@@ -15,11 +15,6 @@
* to an HTML string.
* Otherwise its placeholders won't be expanded. */
-html {
- /* TODO(dbeam): remove this soon. Prefer dir= in HTML. */
- direction: $i18n{textDirection};
-}
-
body {
font-family: $i18nRaw{fontFamily};
font-size: $i18n{fontSize};
diff --git a/chromium/ui/webui/resources/css/text_defaults_md.css b/chromium/ui/webui/resources/css/text_defaults_md.css
index a862419be6d..d85fc32bd40 100644
--- a/chromium/ui/webui/resources/css/text_defaults_md.css
+++ b/chromium/ui/webui/resources/css/text_defaults_md.css
@@ -17,11 +17,6 @@
@import url(chrome://resources/css/roboto.css);
-html {
- /* TODO(dbeam): remove this soon. Prefer dir= in HTML. */
- direction: $i18n{textDirection};
-}
-
body {
font-family: Roboto, $i18nRaw{fontFamily};
font-size: 81.25%;
diff --git a/chromium/ui/webui/resources/html/BUILD.gn b/chromium/ui/webui/resources/html/BUILD.gn
index 5ae61e89f5a..fef8ed4a40f 100644
--- a/chromium/ui/webui/resources/html/BUILD.gn
+++ b/chromium/ui/webui/resources/html/BUILD.gn
@@ -53,7 +53,6 @@ generate_grd("build_grdp") {
"i18n_behavior.html",
"list_property_update_behavior.html",
"polymer.html",
- "search_highlight_utils.html",
"web_ui_listener_behavior.html",
]
}
diff --git a/chromium/ui/webui/resources/html/search_highlight_utils.html b/chromium/ui/webui/resources/html/search_highlight_utils.html
deleted file mode 100644
index 933de815945..00000000000
--- a/chromium/ui/webui/resources/html/search_highlight_utils.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<link rel="import" href="assert.html">
-<script src="../js/search_highlight_utils.js"></script>
diff --git a/chromium/ui/webui/resources/images/BUILD.gn b/chromium/ui/webui/resources/images/BUILD.gn
index d3625a5eea2..9035e41117c 100644
--- a/chromium/ui/webui/resources/images/BUILD.gn
+++ b/chromium/ui/webui/resources/images/BUILD.gn
@@ -30,12 +30,14 @@ generate_grd("build_grdp") {
"disabled_select.png",
"error.svg",
"icon_copy_content.svg",
+ "icon_cancel.svg",
"icon_search.svg",
"icon_refresh.svg",
"open_in_new.svg",
"select.png",
"throbber_medium.svg",
"throbber_small.svg",
+ "dark/icon_search.svg",
]
if (!is_android && !is_ios) {
@@ -45,11 +47,9 @@ generate_grd("build_grdp") {
"arrow_right.svg",
"business.svg",
"dark/arrow_down.svg",
- "dark/icon_search.svg",
"icon_arrow_back.svg",
"icon_arrow_dropdown.svg",
"icon_bookmark.svg",
- "icon_cancel.svg",
"icon_clear.svg",
"icon_delete_gray.svg",
"icon_edit.svg",
diff --git a/chromium/ui/webui/resources/images/incognito_icon.svg b/chromium/ui/webui/resources/images/incognito_icon.svg
new file mode 100644
index 00000000000..5a8fe3c9421
--- /dev/null
+++ b/chromium/ui/webui/resources/images/incognito_icon.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24" fill="#455A64"><path fill="none" d="M0 0h24v24H0z"/><path d="M3 11h18v1H3zm14.62-1l-2.29-6.1c-.19-.5-.74-.77-1.25-.6L12 4l-2.09-.7c-.51-.17-1.06.1-1.25.6L6.38 10h11.24zm-1.12 3c-1.66 0-3.04 1.16-3.4 2.71-.84-.36-1.62-.26-2.2-.01A3.503 3.503 0 0 0 7.5 13C5.57 13 4 14.57 4 16.5S5.57 20 7.5 20c1.84 0 3.33-1.42 3.47-3.22.3-.21 1.09-.6 2.06.02.16 1.79 1.64 3.2 3.47 3.2 1.93 0 3.5-1.57 3.5-3.5S18.43 13 16.5 13zm-9 6a2.5 2.5 0 0 1 0-5 2.5 2.5 0 0 1 0 5zm9 0a2.5 2.5 0 0 1 0-5 2.5 2.5 0 0 1 0 5z"/></svg> \ No newline at end of file
diff --git a/chromium/ui/webui/resources/js/BUILD.gn b/chromium/ui/webui/resources/js/BUILD.gn
index dbcd3eeb998..a049d0ef052 100644
--- a/chromium/ui/webui/resources/js/BUILD.gn
+++ b/chromium/ui/webui/resources/js/BUILD.gn
@@ -7,6 +7,7 @@ import("//third_party/closure_compiler/compile_js.gni")
import("//tools/grit/preprocess_if_expr.gni")
import("//ui/webui/resources/tools/generate_grd.gni")
import("../tools/js_modulizer.gni")
+import("../tools/js_unmodulizer.gni")
preprocess_folder = "$root_gen_dir/ui/webui/resources/preprocessed/js"
preprocess_gen_manifest = "preprocessed_gen_manifest.json"
@@ -29,6 +30,7 @@ group("preprocess") {
public_deps = [
":preprocess_generated",
":preprocess_src",
+ ":preprocess_src_ts",
"cr/ui:preprocess",
]
}
@@ -41,18 +43,12 @@ preprocess_if_expr("preprocess_src") {
"action_link.js",
"assert.js",
"color_utils.js",
- "cr/event_target.js",
- "cr.js",
"cr.m.js",
- "cr/ui.js",
"custom_element.js",
- "event_tracker.js",
"i18n_template_no_process.js",
- "icon.js",
- "load_time_data.js",
- "parse_html_subset.js",
+ "load_time_data.m.js",
"plural_string_proxy.js",
- "promise_resolver.js",
+ "search_highlight_utils.js",
"test_loader.js",
"test_loader_util.js",
"util.js",
@@ -66,10 +62,16 @@ preprocess_if_expr("preprocess_src") {
# TODO(crbug.com/1184053): Fully remove once no longer used by CrOS.
if (is_chromeos_ash) {
in_files += [
+ "cr/event_target.js",
+ "cr/ui.js",
+ "cr.js",
+ "event_tracker.js",
"i18n_behavior.js",
+ "icon.js",
"list_property_update_behavior.js",
+ "parse_html_subset.js",
"polymer_config.js",
- "search_highlight_utils.js",
+ "promise_resolver.js",
"web_ui_listener_behavior.js",
]
}
@@ -82,8 +84,22 @@ preprocess_if_expr("preprocess_src") {
}
}
+# Put TS files on a separate target, so that they are not included in the
+# manifest file.
+preprocess_if_expr("preprocess_src_ts") {
+ in_folder = "./"
+ out_folder = "$preprocess_folder"
+ in_files = [
+ "cr/world.ts",
+ "hello_world.ts",
+ ]
+}
+
preprocess_if_expr("preprocess_generated") {
- deps = [ ":modulize" ]
+ deps = [
+ ":modulize",
+ ":unmodulize",
+ ]
in_folder = target_gen_dir
out_folder = "$preprocess_folder"
out_manifest = "$target_gen_dir/$preprocess_gen_manifest"
@@ -93,7 +109,7 @@ preprocess_if_expr("preprocess_generated") {
"cr/ui.m.js",
"event_tracker.m.js",
"icon.m.js",
- "load_time_data.m.js",
+ "load_time_data.js",
"parse_html_subset.m.js",
"promise_resolver.m.js",
"util.m.js",
@@ -103,7 +119,6 @@ preprocess_if_expr("preprocess_generated") {
in_files += [
"i18n_behavior.m.js",
"list_property_update_behavior.m.js",
- "search_highlight_utils.m.js",
"web_ui_listener_behavior.m.js",
]
}
@@ -131,7 +146,6 @@ js_type_check("js_resources") {
":load_time_data",
":parse_html_subset",
":promise_resolver",
- ":search_highlight_utils",
":util",
":web_ui_listener_behavior",
":webui_resource_test",
@@ -159,13 +173,7 @@ js_library("cr") {
}
js_library("event_tracker") {
-}
-
-js_library("search_highlight_utils") {
- deps = [
- ":assert",
- ":cr",
- ]
+ deps = [ ":cr" ]
}
js_library("icon") {
@@ -184,18 +192,18 @@ js_library("i18n_template_process") {
}
js_library("i18n_behavior") {
- deps = [ ":load_time_data" ]
+ deps = [
+ ":load_time_data",
+ ":parse_html_subset",
+ ]
}
js_library("list_property_update_behavior") {
}
js_library("load_time_data") {
- deps = [
- ":assert",
- ":parse_html_subset",
- "//third_party/jstemplate:jstemplate",
- ]
+ sources = [ "$root_gen_dir/ui/webui/resources/js/load_time_data.js" ]
+ extra_deps = [ ":unmodulize" ]
}
js_library("parse_html_subset") {
@@ -234,10 +242,8 @@ js_modulizer("modulize_local") {
"icon.js",
"i18n_behavior.js",
"list_property_update_behavior.js",
- "load_time_data.js",
"parse_html_subset.js",
"promise_resolver.js",
- "search_highlight_utils.js",
"util.js",
"web_ui_listener_behavior.js",
]
@@ -247,6 +253,11 @@ js_modulizer("modulize_local") {
]
}
+js_unmodulizer("unmodulize") {
+ input_files = [ "load_time_data.m.js" ]
+ output_files = [ "load_time_data.js" ]
+}
+
group("closure_compile_modules") {
deps = [
":js_resources_modules",
@@ -268,7 +279,7 @@ js_type_check("js_resources_modules") {
":parse_html_subset.m",
":plural_string_proxy",
":promise_resolver.m",
- ":search_highlight_utils.m",
+ ":search_highlight_utils",
":util.m",
":web_ui_listener_behavior.m",
]
@@ -321,13 +332,6 @@ js_library("list_property_update_behavior.m") {
}
js_library("load_time_data.m") {
- sources = [ "$root_gen_dir/ui/webui/resources/js/load_time_data.m.js" ]
- deps = [
- ":assert.m",
- ":parse_html_subset.m",
- "//third_party/jstemplate:jstemplate",
- ]
- extra_deps = [ ":modulize_local" ]
}
js_library("parse_html_subset.m") {
@@ -345,11 +349,8 @@ js_library("promise_resolver.m") {
extra_deps = [ ":modulize_local" ]
}
-js_library("search_highlight_utils.m") {
- sources =
- [ "$root_gen_dir/ui/webui/resources/js/search_highlight_utils.m.js" ]
+js_library("search_highlight_utils") {
deps = [ ":assert.m" ]
- extra_deps = [ ":modulize_local" ]
}
js_library("util.m") {
diff --git a/chromium/ui/webui/resources/js/cr/ui/context_menu_handler.js b/chromium/ui/webui/resources/js/cr/ui/context_menu_handler.js
index 801d4bdd7ea..3a6f1fdb3e7 100644
--- a/chromium/ui/webui/resources/js/cr/ui/context_menu_handler.js
+++ b/chromium/ui/webui/resources/js/cr/ui/context_menu_handler.js
@@ -26,8 +26,8 @@ cr.define('cr.ui', function() {
class ContextMenuHandler extends cr.EventTarget {
constructor() {
super();
- /** @private {!EventTracker} */
- this.showingEvents_ = new EventTracker();
+ /** @private {!cr.EventTracker} */
+ this.showingEvents_ = new cr.EventTracker();
/**
* The menu that we are currently showing.
diff --git a/chromium/ui/webui/resources/js/cr/ui/focus_grid.js b/chromium/ui/webui/resources/js/cr/ui/focus_grid.js
index 151749bba59..23477ae4a62 100644
--- a/chromium/ui/webui/resources/js/cr/ui/focus_grid.js
+++ b/chromium/ui/webui/resources/js/cr/ui/focus_grid.js
@@ -3,8 +3,8 @@
// found in the LICENSE file.
// clang-format off
-// #import {assert} from 'chrome://resources/js/assert.m.js'
-// #import {FocusRow, FocusRowDelegate} from 'chrome://resources/js/cr/ui/focus_row.m.js';
+// #import {assert} from '../../assert.m.js'
+// #import {FocusRow, FocusRowDelegate} from './focus_row.m.js';
// clang-format on
cr.define('cr.ui', function() {
diff --git a/chromium/ui/webui/resources/js/cr/ui/focus_row.js b/chromium/ui/webui/resources/js/cr/ui/focus_row.js
index c297608a0d4..1a22300f95e 100644
--- a/chromium/ui/webui/resources/js/cr/ui/focus_row.js
+++ b/chromium/ui/webui/resources/js/cr/ui/focus_row.js
@@ -40,8 +40,8 @@ cr.define('cr.ui', function() {
/** @type {cr.ui.FocusRowDelegate|undefined} */
this.delegate = delegate;
- /** @protected {!EventTracker} */
- this.eventTracker = new EventTracker;
+ /** @protected {!cr.EventTracker} */
+ this.eventTracker = new cr.EventTracker;
}
/**
diff --git a/chromium/ui/webui/resources/js/cr/ui/focus_row_behavior.m.d.ts b/chromium/ui/webui/resources/js/cr/ui/focus_row_behavior.m.d.ts
new file mode 100644
index 00000000000..24a752797e6
--- /dev/null
+++ b/chromium/ui/webui/resources/js/cr/ui/focus_row_behavior.m.d.ts
@@ -0,0 +1,22 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {FocusRow} from './focus_row.m.js';
+
+export interface FocusRowBehaviorInterface {
+ id: string|null|undefined;
+ isFocused: boolean|null|undefined;
+ focusRowIndex: number|null|undefined;
+ lastFocused: Element|null;
+ ironListTabIndex: number;
+ listBlurred: boolean|null|undefined;
+ focusRowIndexChanged(newIndex: number, oldIndex: number): void;
+ getFocusRow(): FocusRow;
+}
+
+export {FocusRowBehavior};
+
+interface FocusRowBehavior extends FocusRowBehaviorInterface {}
+
+declare const FocusRowBehavior: object;
diff --git a/chromium/ui/webui/resources/js/cr/ui/menu_button.js b/chromium/ui/webui/resources/js/cr/ui/menu_button.js
index 0cfd92b6fb0..00ec20abb6e 100644
--- a/chromium/ui/webui/resources/js/cr/ui/menu_button.js
+++ b/chromium/ui/webui/resources/js/cr/ui/menu_button.js
@@ -63,7 +63,7 @@ cr.define('cr.ui', function() {
// An event tracker for events we only connect to while the menu is
// displayed.
- this.showingEvents_ = new EventTracker();
+ this.showingEvents_ = new cr.EventTracker();
this.anchorType = cr.ui.AnchorType.BELOW;
this.invertLeftRight = false;
diff --git a/chromium/ui/webui/resources/js/cr/ui/store_client.js b/chromium/ui/webui/resources/js/cr/ui/store_client.js
index e2ba2efaadd..e682f04461a 100644
--- a/chromium/ui/webui/resources/js/cr/ui/store_client.js
+++ b/chromium/ui/webui/resources/js/cr/ui/store_client.js
@@ -134,6 +134,33 @@ cr.define('cr.ui', function() {
},
};
+ /* #export */ class StoreClientInterface {
+ /**
+ * Helper to dispatch an action to the store, which will update the store
+ * data and then (possibly) flow through to the UI.
+ * @param {?cr.ui.Action} action
+ */
+ dispatch(action) {}
+
+ /**
+ * Helper to dispatch a DeferredAction to the store, which will
+ * asynchronously perform updates to the store data and UI.
+ * @param {cr.ui.DeferredAction} action
+ */
+ dispatchAsync(action) {}
+
+ /** @param {Object} newState */
+ onStateChanged(newState) {}
+
+ updateFromStore() {}
+
+ watch(localProperty, valueGetter) {}
+
+ getState() {}
+
+ getStore() {}
+ }
+
// #cr_define_end
console.warn('crbug/1173575, non-JS module files deprecated.');
return {
diff --git a/chromium/ui/webui/resources/js/event_tracker.js b/chromium/ui/webui/resources/js/event_tracker.js
index 21fe8f72a22..58bf1df5cff 100644
--- a/chromium/ui/webui/resources/js/event_tracker.js
+++ b/chromium/ui/webui/resources/js/event_tracker.js
@@ -11,83 +11,86 @@
* calling Function.bind.
*/
-// eslint-disable-next-line no-var
-/* #export */ var EventTracker = class {
- /**
- * Create an EventTracker to track a set of events.
- * EventTracker instances are typically tied 1:1 with other objects or
- * DOM elements whose listeners should be removed when the object is disposed
- * or the corresponding elements are removed from the DOM.
- */
- constructor() {
+cr.define('cr', function() {
+ /* #export */ class EventTracker {
/**
- * @type {Array<EventTracker.Entry>}
- * @private
+ * Create an EventTracker to track a set of events.
+ * EventTracker instances are typically tied 1:1 with other objects or
+ * DOM elements whose listeners should be removed when the object is
+ * disposed or the corresponding elements are removed from the DOM.
*/
- this.listeners_ = [];
- }
+ constructor() {
+ /**
+ * @type {Array<EventTrackerEntry>}
+ * @private
+ */
+ this.listeners_ = [];
+ }
- /**
- * Add an event listener - replacement for EventTarget.addEventListener.
- * @param {!EventTarget} target The DOM target to add a listener to.
- * @param {string} eventType The type of event to subscribe to.
- * @param {EventListener|Function} listener The listener to add.
- * @param {boolean=} opt_capture Whether to invoke during the capture phase.
- */
- add(target, eventType, listener, opt_capture) {
- const capture = !!opt_capture;
- const h = {
- target: target,
- eventType: eventType,
- listener: listener,
- capture: capture,
- };
- this.listeners_.push(h);
- target.addEventListener(eventType, listener, capture);
- }
+ /**
+ * Add an event listener - replacement for EventTarget.addEventListener.
+ * @param {!EventTarget} target The DOM target to add a listener to.
+ * @param {string} eventType The type of event to subscribe to.
+ * @param {EventListener|Function} listener The listener to add.
+ * @param {boolean=} opt_capture Whether to invoke during the capture phase.
+ */
+ add(target, eventType, listener, opt_capture) {
+ const capture = !!opt_capture;
+ const h = {
+ target: target,
+ eventType: eventType,
+ listener: listener,
+ capture: capture,
+ };
+ this.listeners_.push(h);
+ target.addEventListener(eventType, listener, capture);
+ }
- /**
- * Remove any specified event listeners added with this EventTracker.
- * @param {!EventTarget} target The DOM target to remove a listener from.
- * @param {?string} eventType The type of event to remove.
- */
- remove(target, eventType) {
- this.listeners_ = this.listeners_.filter(listener => {
- if (listener.target === target &&
- (!eventType || (listener.eventType === eventType))) {
- EventTracker.removeEventListener(listener);
- return false;
- }
- return true;
- });
- }
+ /**
+ * Remove any specified event listeners added with this EventTracker.
+ * @param {!EventTarget} target The DOM target to remove a listener from.
+ * @param {?string} eventType The type of event to remove.
+ */
+ remove(target, eventType) {
+ this.listeners_ = this.listeners_.filter(listener => {
+ if (listener.target === target &&
+ (!eventType || (listener.eventType === eventType))) {
+ EventTracker.removeEventListener(listener);
+ return false;
+ }
+ return true;
+ });
+ }
- /** Remove all event listeners added with this EventTracker. */
- removeAll() {
- this.listeners_.forEach(
- listener => EventTracker.removeEventListener(listener));
- this.listeners_ = [];
+ /** Remove all event listeners added with this EventTracker. */
+ removeAll() {
+ this.listeners_.forEach(
+ listener => EventTracker.removeEventListener(listener));
+ this.listeners_ = [];
+ }
+
+ /**
+ * Remove a single event listener given it's tracking entry. It's up to the
+ * caller to ensure the entry is removed from listeners_.
+ * @param {EventTrackerEntry} entry The entry describing the listener to
+ * remove.
+ */
+ static removeEventListener(entry) {
+ entry.target.removeEventListener(
+ entry.eventType, entry.listener, entry.capture);
+ }
}
/**
- * Remove a single event listener given it's tracking entry. It's up to the
- * caller to ensure the entry is removed from listeners_.
- * @param {EventTracker.Entry} entry The entry describing the listener to
- * remove.
+ * The type of the internal tracking entry.
+ * @typedef {{target: !EventTarget,
+ * eventType: string,
+ * listener: (EventListener|Function),
+ * capture: boolean}}
*/
- static removeEventListener(entry) {
- entry.target.removeEventListener(
- entry.eventType, entry.listener, entry.capture);
- }
-};
-
-/**
- * The type of the internal tracking entry.
- * @typedef {{target: !EventTarget,
- * eventType: string,
- * listener: (EventListener|Function),
- * capture: boolean}}
- */
-EventTracker.Entry;
+ let EventTrackerEntry;
-/* #ignore */ console.warn('crbug/1173575, non-JS module files deprecated.');
+ // #cr_define_end
+ console.warn('crbug/1173575, non-JS module files deprecated.');
+ return {EventTracker};
+});
diff --git a/chromium/ui/webui/resources/js/i18n_behavior.js b/chromium/ui/webui/resources/js/i18n_behavior.js
index 01acdcdba65..c1b9a2c8141 100644
--- a/chromium/ui/webui/resources/js/i18n_behavior.js
+++ b/chromium/ui/webui/resources/js/i18n_behavior.js
@@ -10,8 +10,8 @@
* handled by a C++ templatizer.
*/
-// #import {parseHtmlSubset} from './parse_html_subset.m.js';
-// #import {loadTimeData, SanitizeInnerHtmlOpts} from './load_time_data.m.js';
+// #import {parseHtmlSubset, SanitizeInnerHtmlOpts, sanitizeInnerHtml} from './parse_html_subset.m.js';
+// #import {loadTimeData} from './load_time_data.m.js';
/** @polymerBehavior */
/* #export */ const I18nBehavior = {
@@ -83,7 +83,7 @@
opts = opts || {};
const args = [id].concat(opts.substitutions || []);
const rawString = this.i18nRaw_.apply(this, args);
- return loadTimeData.sanitizeInnerHtml(rawString, opts);
+ return sanitizeInnerHtml(rawString, opts);
},
/**
@@ -132,16 +132,54 @@
},
};
-/**
- * TODO(stevenjb): Replace with an interface. b/24294625
- * @typedef {{
- * i18n: function(string, ...string): string,
- * i18nAdvanced: function(string, SanitizeInnerHtmlOpts=): string,
- * i18nDynamic: function(string, string, ...string): string,
- * i18nExists: function(string),
- * i18nUpdateLocale: function()
- * }}
- */
-I18nBehavior.Proto;
+/** @interface */
+/* #export */ class I18nBehaviorInterface {
+ constructor() {
+ // <if expr="chromeos">
+ /** @type {string} */
+ this.locale;
+ // </if>
+ }
+
+ // <if expr="chromeos">
+ i18nUpdateLocale() {}
+ // </if>
+
+ /**
+ * @param {string} id
+ * @param {...string|number} var_args
+ * @return {string}
+ */
+ i18n(id, var_args) {}
+
+ /**
+ * @param {string} id
+ * @param {SanitizeInnerHtmlOpts=} opts
+ * @return {string}
+ */
+ i18nAdvanced(id, opts) {}
+
+ /**
+ * @param {string} locale
+ * @param {string} id
+ * @param {...string} var_args
+ * @return {string}
+ */
+ i18nDynamic(locale, id, var_args) {}
+
+ /**
+ * @param {string} locale
+ * @param {string} id
+ * @param {...string} var_args
+ * @return {string}
+ */
+ i18nRecursive(locale, id, var_args) {}
+
+ /**
+ * @param {string} id
+ * @return {boolean}
+ */
+ i18nExists(id) {}
+}
/* #ignore */ console.warn('crbug/1173575, non-JS module files deprecated.');
diff --git a/chromium/ui/webui/resources/js/i18n_behavior.m.d.ts b/chromium/ui/webui/resources/js/i18n_behavior.m.d.ts
new file mode 100644
index 00000000000..ca03f9448d1
--- /dev/null
+++ b/chromium/ui/webui/resources/js/i18n_behavior.m.d.ts
@@ -0,0 +1,21 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {SanitizeInnerHtmlOpts} from './parse_html_subset.m.js';
+
+export interface I18nBehaviorInterface {
+ locale: string|null|undefined;
+ i18nUpdateLocale(): void;
+ i18n(id: string, ...var_args: Array<string|number>): string;
+ i18nAdvanced(id: string, opts?: SanitizeInnerHtmlOpts): string;
+ i18nDynamic(locale: string, id: string, ...var_args: string[]): string;
+ i18nRecursive(locale: string, id: string, ...var_args: string[]): string;
+ i18nExists(id: string): boolean;
+}
+
+export {I18nBehavior};
+
+interface I18nBehavior extends I18nBehaviorInterface {}
+
+declare const I18nBehavior: object;
diff --git a/chromium/ui/webui/resources/js/ios/web_ui.js b/chromium/ui/webui/resources/js/ios/web_ui.js
index ba821ab74b4..ac2cdc9f96f 100644
--- a/chromium/ui/webui/resources/js/ios/web_ui.js
+++ b/chromium/ui/webui/resources/js/ios/web_ui.js
@@ -18,3 +18,82 @@ window['chrome']['send'] = function(message, args) {
'arguments': args || []
});
};
+
+
+try {
+ new EventTarget().constructor;
+} catch {
+ /**
+ * Minimal EventTarget polyfill for webui.
+ * TODO(crbug.com/1173902): delete once iOS 13 is deprecated.
+ * @constructor
+ */
+ const EventTarget = function() {
+ /**
+ * @type {Object}
+ */
+ this.listeners_ = {};
+ };
+
+ /**
+ * Registers an event handler of a specific event type on the EventTarget.
+ * @param {string} type event type.
+ * @param {function} listener event callback.
+ * @param {object|boolean|null} options event options.
+ */
+ EventTarget.prototype.addEventListener = function(type, listener, options) {
+ if (!(type in this.listeners_)) {
+ this.listeners_[type] = [];
+ }
+ this.listeners_[type].push({listener: listener, options: options});
+ };
+
+ /**
+ * Removes an event listener from the EventTarget.
+ * @param {string} type event type.
+ * @param {function} listener event callback.
+ * @param {object|boolean|null} options event options.
+ */
+ EventTarget.prototype.removeEventListener = function(
+ type, listener, options) {
+ if (!(type in this.listeners_)) {
+ return;
+ }
+
+ const stubs = this.listeners_[type];
+ let i = 0;
+ while (i < stubs.length) {
+ if (stubs[i].listener === listener &&
+ JSON.stringify(stubs[i].options) === JSON.stringify(options)) {
+ stubs.splice(i, 1);
+ } else {
+ i++;
+ }
+ }
+ };
+
+ /**
+ * Dispatches an event to this EventTarget.
+ * @param {!Event} event event to dispatch.
+ * @return {boolean}
+ */
+ EventTarget.prototype.dispatchEvent = function(event) {
+ if (!(event.type in this.listeners)) {
+ return true;
+ }
+
+ // Iterate on copy, in case options.once requires removing listener.
+ const stubs = this.listeners_[type].slice(0);
+ for (let i = 0; i < stubs.length; i++) {
+ stubs[i].listener.call(this, event);
+ if (typeof stubs[i].options === 'object' && stubs[i].options.once) {
+ this.removeEventListener(
+ event.type, stubs[i].listener, stubs[i].options);
+ }
+ }
+
+ return !event.defaultPrevented;
+ };
+
+ window.EventTarget = EventTarget;
+}
diff --git a/chromium/ui/webui/resources/js/list_property_update_behavior.js b/chromium/ui/webui/resources/js/list_property_update_behavior.js
index 5a9f75a2abd..ff553459f44 100644
--- a/chromium/ui/webui/resources/js/list_property_update_behavior.js
+++ b/chromium/ui/webui/resources/js/list_property_update_behavior.js
@@ -24,7 +24,7 @@
* @param {function(!Object): (!Object|string)} identityGetter
* @param {!Array<!Object>} updatedList
* @param {boolean=} identityBasedUpdate
- * @returns {boolean} True if notifySplices was called.
+ * @return {boolean} True if notifySplices was called.
*/
updateList(
propertyPath, identityGetter, updatedList, identityBasedUpdate = false) {
@@ -79,4 +79,16 @@
return updated;
}
+/* #export */ class ListPropertyUpdateBehaviorInterface {
+ /**
+ * @param {string} propertyPath
+ * @param {function(!Object): (!Object|string)} identityGetter
+ * @param {!Array<!Object>} updatedList
+ * @param {boolean=} identityBasedUpdate
+ * @return {boolean} True if notifySplices was called.
+ */
+ updateList(
+ propertyPath, identityGetter, updatedList, identityBasedUpdate = false) {}
+}
+
/* #ignore */ console.warn('crbug/1173575, non-JS module files deprecated.');
diff --git a/chromium/ui/webui/resources/js/load_time_data.js b/chromium/ui/webui/resources/js/load_time_data.m.js
index aaf2dd0a290..773f32aad84 100644
--- a/chromium/ui/webui/resources/js/load_time_data.js
+++ b/chromium/ui/webui/resources/js/load_time_data.m.js
@@ -14,20 +14,9 @@
* change if the page is re-opened later.
*/
-// #import {assert} from './assert.m.js';
-// #import {parseHtmlSubset} from './parse_html_subset.m.js';
-
-/**
- * @typedef {{
- * substitutions: (!Array<string>|undefined),
- * attrs: (!Array<string>|undefined),
- * tags: (!Array<string>|undefined),
- * }}
- */
-/* #export */ let SanitizeInnerHtmlOpts;
-
+/** @type {!LoadTimeData} */
// eslint-disable-next-line no-var
-/* #export */ /** @type {!LoadTimeData} */ var loadTimeData;
+export var loadTimeData;
class LoadTimeData {
constructor() {
@@ -50,14 +39,6 @@ class LoadTimeData {
}
/**
- * Returns a JsEvalContext for |data_|.
- * @returns {JsEvalContext}
- */
- createJsEvalContext() {
- return new JsEvalContext(this.data_);
- }
-
- /**
* @param {string} id An ID of a value that might exist.
* @return {boolean} True if |id| is a key in the dictionary.
*/
@@ -108,20 +89,6 @@ class LoadTimeData {
}
/**
- * Make a string safe for use with with Polymer bindings that are
- * inner-h-t-m-l (or other innerHTML use).
- * @param {string} rawString The unsanitized string.
- * @param {SanitizeInnerHtmlOpts=} opts Optional additional allowed tags and
- * attributes.
- * @return {string}
- */
- sanitizeInnerHtml(rawString, opts) {
- opts = opts || {};
- return parseHtmlSubset('<b>' + rawString + '</b>', opts.tags, opts.attrs)
- .firstChild.innerHTML;
- }
-
- /**
* Returns a formatted localized string where $1 to $9 are replaced by the
* second to the tenth argument. Any standalone $ signs must be escaped as
* $$.
@@ -134,7 +101,7 @@ class LoadTimeData {
substituteString(label, var_args) {
const varArgs = arguments;
return label.replace(/\$(.|$|\n)/g, function(m) {
- assert(m.match(/\$[$1-9]/), 'Unescaped $ found in localized string.');
+ expect(m.match(/\$[$1-9]/), 'Unescaped $ found in localized string.');
return m === '$$' ? '$' : varArgs[m[1]];
});
}
@@ -159,7 +126,7 @@ class LoadTimeData {
// Pieces that are not $1-9 should be returned after replacing $$
// with $.
if (!p.match(/^\$[1-9]$/)) {
- assert(
+ expect(
(p.match(/\$/g) || []).length % 2 === 0,
'Unescaped $ found in localized string.');
return {value: p.replace(/\$\$/g, '$'), arg: null};
@@ -207,16 +174,21 @@ class LoadTimeData {
this.data_[key] = replacements[key];
}
}
+
+ /** Reset loadTimeData's data to empty. Should only be used in tests. */
+ resetForTesting() {
+ this.data_ = {};
+ }
}
/**
- * Checks condition, displays error message if expectation fails.
+ * Checks condition, throws error message if expectation fails.
* @param {*} condition The condition to check for truthiness.
* @param {string} message The message to display if the check fails.
*/
function expect(condition, message) {
if (!condition) {
- console.error(
+ throw new Error(
'Unexpected condition on ' + document.location.href + ': ' + message);
}
}
@@ -235,9 +207,8 @@ class LoadTimeData {
expect(!loadTimeData, 'should only include this file once');
loadTimeData = new LoadTimeData;
- // Expose |loadTimeData| directly on |window|. This is only necessary by the
- // auto-generated load_time_data.m.js, since within a JS module the scope is
- // local.
+ // Expose |loadTimeData| directly on |window|, since within a JS module the
+ // scope is local and not all files have been updated to import the exported
+ // |loadTimeData| explicitly.
window.loadTimeData = loadTimeData;
-/* #ignore */ console.warn('crbug/1173575, non-JS module files deprecated.');
diff --git a/chromium/ui/webui/resources/js/parse_html_subset.js b/chromium/ui/webui/resources/js/parse_html_subset.js
index 95407fff946..01b33d23840 100644
--- a/chromium/ui/webui/resources/js/parse_html_subset.js
+++ b/chromium/ui/webui/resources/js/parse_html_subset.js
@@ -3,6 +3,30 @@
// found in the LICENSE file.
/**
+ * @typedef {{
+ * substitutions: (!Array<string>|undefined),
+ * attrs: (!Array<string>|undefined),
+ * tags: (!Array<string>|undefined),
+ * }}
+ */
+/* #export */ let SanitizeInnerHtmlOpts;
+
+/**
+ * Make a string safe for Polymer bindings that are inner-h-t-m-l or other
+ * innerHTML use.
+ * @param {string} rawString The unsanitized string
+ * @param {SanitizeInnerHtmlOpts=} opts Optional additional allowed tags and
+ * attributes.
+ * @return {string}
+ */
+/* #export */ const sanitizeInnerHtml = function(rawString, opts) {
+ opts = opts || {};
+ return parseHtmlSubset('<b>' + rawString + '</b>', opts.tags, opts.attrs)
+ .firstChild.innerHTML;
+};
+
+
+/**
* Parses a very small subset of HTML. This ensures that insecure HTML /
* javascript cannot be injected into WebUI.
* @param {string} s The string to parse.
@@ -71,7 +95,7 @@
* @const
*/
const allowedTags =
- new Set(['A', 'B', 'BR', 'DIV', 'P', 'PRE', 'SPAN', 'STRONG']);
+ new Set(['A', 'B', 'BR', 'DIV', 'KBD', 'P', 'PRE', 'SPAN', 'STRONG']);
/**
* Allow-list of optional tag names in parseHtmlSubset.
diff --git a/chromium/ui/webui/resources/js/search_highlight_utils.js b/chromium/ui/webui/resources/js/search_highlight_utils.js
index aca22d545df..2dad9f29968 100644
--- a/chromium/ui/webui/resources/js/search_highlight_utils.js
+++ b/chromium/ui/webui/resources/js/search_highlight_utils.js
@@ -2,180 +2,167 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// #import {assert} from 'chrome://resources/js/assert.m.js';
-
-cr.define('cr.search_highlight_utils', function() {
- /** @type {string} */
- const WRAPPER_CSS_CLASS = 'search-highlight-wrapper';
-
- /** @type {string} */
- const ORIGINAL_CONTENT_CSS_CLASS = 'search-highlight-original-content';
-
- /** @type {string} */
- const HIT_CSS_CLASS = 'search-highlight-hit';
-
- /** @type {string} */
- const SEARCH_BUBBLE_CSS_CLASS = 'search-bubble';
-
- /** @typedef {{start: number, length: number}} */
- /* #export */ let Range;
-
- /**
- * Replaces the the highlight wrappers given in |wrappers| with the original
- * search nodes.
- * @param {!Array<!Node>} wrappers
- */
- /* #export */ function removeHighlights(wrappers) {
- for (const wrapper of wrappers) {
- // If wrapper is already removed, do nothing.
- if (!wrapper.parentElement) {
- continue;
- }
-
- const textNode =
- wrapper.querySelector(`.${ORIGINAL_CONTENT_CSS_CLASS}`).firstChild;
- wrapper.parentElement.replaceChild(textNode, wrapper);
- }
- }
+import {assert} from 'chrome://resources/js/assert.m.js';
- /**
- * Finds all previous highlighted nodes under |node| and replaces the
- * highlights (yellow rectangles) with the original search node. Searches only
- * within the same shadowRoot and assumes that only one highlight wrapper
- * exists under |node|.
- * @param {!Node} node
- */
- /* #export */ function findAndRemoveHighlights(node) {
- const wrappers = Array.from(node.querySelectorAll(`.${WRAPPER_CSS_CLASS}`));
- assert(wrappers.length === 1);
- removeHighlights(wrappers);
- }
+/** @type {string} */
+const WRAPPER_CSS_CLASS = 'search-highlight-wrapper';
- /**
- * Applies the highlight UI (yellow rectangle) around all matches in |node|.
- * @param {!Node} node The text node to be highlighted. |node| ends up
- * being hidden.
- * @param {!Array<!cr.search_highlight_utils.Range>} ranges
- * @return {!Node} The new highlight wrapper.
- */
- /* #export */ function highlight(node, ranges) {
- assert(ranges.length > 0);
-
- const wrapper = document.createElement('span');
- wrapper.classList.add(WRAPPER_CSS_CLASS);
- // Use existing node as placeholder to determine where to insert the
- // replacement content.
- node.parentNode.replaceChild(wrapper, node);
-
- // Keep the existing node around for when the highlights are removed. The
- // existing text node might be involved in data-binding and therefore should
- // not be discarded.
- const span = document.createElement('span');
- span.classList.add(ORIGINAL_CONTENT_CSS_CLASS);
- span.style.display = 'none';
- span.appendChild(node);
- wrapper.appendChild(span);
-
- const text = node.textContent;
- /** @type {!Array<string>} */ const tokens = [];
- for (let i = 0; i < ranges.length; ++i) {
- const range = ranges[i];
- const prev = ranges[i - 1] || {start: 0, length: 0};
- const start = prev.start + prev.length;
- const length = range.start - start;
- tokens.push(text.substr(start, length));
- tokens.push(text.substr(range.start, range.length));
- }
- const last = ranges.slice(-1)[0];
- tokens.push(text.substr(last.start + last.length));
-
- for (let i = 0; i < tokens.length; ++i) {
- if (i % 2 === 0) {
- wrapper.appendChild(document.createTextNode(tokens[i]));
- } else {
- const hitSpan = document.createElement('span');
- hitSpan.classList.add(HIT_CSS_CLASS);
- hitSpan.style.backgroundColor = '#ffeb3b'; // var(--paper-yellow-500)
- hitSpan.style.color = '#202124'; // var(--google-grey-900)
- hitSpan.textContent = tokens[i];
- wrapper.appendChild(hitSpan);
- }
- }
- return wrapper;
- }
+/** @type {string} */
+const ORIGINAL_CONTENT_CSS_CLASS = 'search-highlight-original-content';
- /**
- * Creates an empty search bubble (styled HTML element without text).
- * |node| should already be visible or the bubble will render incorrectly.
- * @param {!Node} node The node to be highlighted.
- * @param {boolean=} horizontallyCenter Whether or not to horizontally center
- * the shown search bubble (if any) based on |node|'s left and width.
- * @return {!Node} The search bubble that was added, or null if no new bubble
- * was added.
- */
- /* #export */ function createEmptySearchBubble(node, horizontallyCenter) {
- let anchor = node;
- if (node.nodeName === 'SELECT') {
- anchor = node.parentNode;
- }
- if (anchor instanceof ShadowRoot) {
- anchor = anchor.host.parentNode;
- }
+/** @type {string} */
+const HIT_CSS_CLASS = 'search-highlight-hit';
- let searchBubble = anchor.querySelector(`.${SEARCH_BUBBLE_CSS_CLASS}`);
- // If the node has already been highlighted, there is no need to do
- // anything.
- if (searchBubble) {
- return searchBubble;
- }
+/** @type {string} */
+const SEARCH_BUBBLE_CSS_CLASS = 'search-bubble';
- searchBubble = document.createElement('div');
- searchBubble.classList.add(SEARCH_BUBBLE_CSS_CLASS);
- const innards = document.createElement('div');
- innards.classList.add('search-bubble-innards');
- innards.textContent = '\u00a0'; // Non-breaking space for offsetHeight.
- searchBubble.appendChild(innards);
- anchor.appendChild(searchBubble);
-
- const updatePosition = function() {
- assert(typeof node.offsetTop === 'number');
- searchBubble.style.top = node.offsetTop +
- (innards.classList.contains('above') ? -searchBubble.offsetHeight :
- node.offsetHeight) +
- 'px';
- if (horizontallyCenter) {
- const width = node.offsetWidth - searchBubble.offsetWidth;
- searchBubble.style.left = node.offsetLeft + width / 2 + 'px';
- }
- };
- updatePosition();
+/** @typedef {{start: number, length: number}} */
+export let Range;
- searchBubble.addEventListener('mouseover', function() {
- innards.classList.toggle('above');
- updatePosition();
- });
- // TODO(crbug.com/355446): create a way to programmatically update these
- // bubbles (i.e. call updatePosition()) when outer scope knows they need to
- // be repositioned.
- return searchBubble;
+/**
+ * Replaces the the highlight wrappers given in |wrappers| with the original
+ * search nodes.
+ * @param {!Array<!Node>} wrappers
+ */
+export function removeHighlights(wrappers) {
+ for (const wrapper of wrappers) {
+ // If wrapper is already removed, do nothing.
+ if (!wrapper.parentElement) {
+ continue;
+ }
+
+ const textNode =
+ wrapper.querySelector(`.${ORIGINAL_CONTENT_CSS_CLASS}`).firstChild;
+ wrapper.parentElement.replaceChild(textNode, wrapper);
+ }
+}
+
+/**
+ * Finds all previous highlighted nodes under |node| and replaces the
+ * highlights (yellow rectangles) with the original search node. Searches only
+ * within the same shadowRoot and assumes that only one highlight wrapper
+ * exists under |node|.
+ * @param {!Node} node
+ */
+export function findAndRemoveHighlights(node) {
+ const wrappers = Array.from(node.querySelectorAll(`.${WRAPPER_CSS_CLASS}`));
+ assert(wrappers.length === 1);
+ removeHighlights(wrappers);
+}
+
+/**
+ * Applies the highlight UI (yellow rectangle) around all matches in |node|.
+ * @param {!Node} node The text node to be highlighted. |node| ends up
+ * being hidden.
+ * @param {!Array<!Range>} ranges
+ * @return {!Node} The new highlight wrapper.
+ */
+export function highlight(node, ranges) {
+ assert(ranges.length > 0);
+
+ const wrapper = document.createElement('span');
+ wrapper.classList.add(WRAPPER_CSS_CLASS);
+ // Use existing node as placeholder to determine where to insert the
+ // replacement content.
+ node.parentNode.replaceChild(wrapper, node);
+
+ // Keep the existing node around for when the highlights are removed. The
+ // existing text node might be involved in data-binding and therefore should
+ // not be discarded.
+ const span = document.createElement('span');
+ span.classList.add(ORIGINAL_CONTENT_CSS_CLASS);
+ span.style.display = 'none';
+ span.appendChild(node);
+ wrapper.appendChild(span);
+
+ const text = node.textContent;
+ /** @type {!Array<string>} */ const tokens = [];
+ for (let i = 0; i < ranges.length; ++i) {
+ const range = ranges[i];
+ const prev = ranges[i - 1] || {start: 0, length: 0};
+ const start = prev.start + prev.length;
+ const length = range.start - start;
+ tokens.push(text.substr(start, length));
+ tokens.push(text.substr(range.start, range.length));
+ }
+ const last = ranges.slice(-1)[0];
+ tokens.push(text.substr(last.start + last.length));
+
+ for (let i = 0; i < tokens.length; ++i) {
+ if (i % 2 === 0) {
+ wrapper.appendChild(document.createTextNode(tokens[i]));
+ } else {
+ const hitSpan = document.createElement('span');
+ hitSpan.classList.add(HIT_CSS_CLASS);
+ hitSpan.style.backgroundColor = '#ffeb3b'; // var(--paper-yellow-500)
+ hitSpan.style.color = '#202124'; // var(--google-grey-900)
+ hitSpan.textContent = tokens[i];
+ wrapper.appendChild(hitSpan);
+ }
+ }
+ return wrapper;
+}
+
+/**
+ * Creates an empty search bubble (styled HTML element without text).
+ * |node| should already be visible or the bubble will render incorrectly.
+ * @param {!Node} node The node to be highlighted.
+ * @param {boolean=} horizontallyCenter Whether or not to horizontally center
+ * the shown search bubble (if any) based on |node|'s left and width.
+ * @return {!Node} The search bubble that was added, or null if no new bubble
+ * was added.
+ */
+export function createEmptySearchBubble(node, horizontallyCenter) {
+ let anchor = node;
+ if (node.nodeName === 'SELECT') {
+ anchor = node.parentNode;
+ }
+ if (anchor instanceof ShadowRoot) {
+ anchor = anchor.host.parentNode;
}
- /**
- * @param {string} text
- * @return {string}
- */
- /* #export */ function stripDiacritics(text) {
- return text.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
+ let searchBubble = anchor.querySelector(`.${SEARCH_BUBBLE_CSS_CLASS}`);
+ // If the node has already been highlighted, there is no need to do
+ // anything.
+ if (searchBubble) {
+ return searchBubble;
}
- // #cr_define_end
- console.warn('crbug/1173575, non-JS module files deprecated.');
- return {
- Range,
- createEmptySearchBubble,
- findAndRemoveHighlights,
- highlight,
- removeHighlights,
- stripDiacritics,
+ searchBubble = document.createElement('div');
+ searchBubble.classList.add(SEARCH_BUBBLE_CSS_CLASS);
+ const innards = document.createElement('div');
+ innards.classList.add('search-bubble-innards');
+ innards.textContent = '\u00a0'; // Non-breaking space for offsetHeight.
+ searchBubble.appendChild(innards);
+ anchor.appendChild(searchBubble);
+
+ const updatePosition = function() {
+ assert(typeof node.offsetTop === 'number');
+ searchBubble.style.top = node.offsetTop +
+ (innards.classList.contains('above') ? -searchBubble.offsetHeight :
+ node.offsetHeight) +
+ 'px';
+ if (horizontallyCenter) {
+ const width = node.offsetWidth - searchBubble.offsetWidth;
+ searchBubble.style.left = node.offsetLeft + width / 2 + 'px';
+ }
};
-});
+ updatePosition();
+
+ searchBubble.addEventListener('mouseover', function() {
+ innards.classList.toggle('above');
+ updatePosition();
+ });
+ // TODO(crbug.com/355446): create a way to programmatically update these
+ // bubbles (i.e. call updatePosition()) when outer scope knows they need to
+ // be repositioned.
+ return searchBubble;
+}
+
+/**
+ * @param {string} text
+ * @return {string}
+ */
+export function stripDiacritics(text) {
+ return text.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
+}
diff --git a/chromium/ui/webui/resources/js/web_ui_listener_behavior.js b/chromium/ui/webui/resources/js/web_ui_listener_behavior.js
index 837518397f7..ffe11ba7bb7 100644
--- a/chromium/ui/webui/resources/js/web_ui_listener_behavior.js
+++ b/chromium/ui/webui/resources/js/web_ui_listener_behavior.js
@@ -47,4 +47,13 @@
},
};
+/** @interface */
+/* #export */ class WebUIListenerBehaviorInterface {
+ /**
+ * @param {string} eventName
+ * @param {!Function} callback
+ */
+ addWebUIListener(eventName, callback) {}
+}
+
/* #ignore */ console.warn('crbug/1173575, non-JS module files deprecated.');
diff --git a/chromium/ui/webui/resources/js/web_ui_listener_behavior.m.d.ts b/chromium/ui/webui/resources/js/web_ui_listener_behavior.m.d.ts
new file mode 100644
index 00000000000..3f09fd1961e
--- /dev/null
+++ b/chromium/ui/webui/resources/js/web_ui_listener_behavior.m.d.ts
@@ -0,0 +1,13 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+export interface WebUIListenerBehaviorInterface {
+ addWebUIListener(eventName: string, callback: Function): void;
+}
+
+export {WebUIListenerBehavior};
+
+interface WebUIListenerBehavior extends WebUIListenerBehaviorInterface {}
+
+declare const WebUIListenerBehavior: object;
diff --git a/chromium/ui/webui/resources/tools/js_modulizer.gni b/chromium/ui/webui/resources/tools/js_modulizer.gni
index 1fb046a68b3..d4ca2084b1d 100644
--- a/chromium/ui/webui/resources/tools/js_modulizer.gni
+++ b/chromium/ui/webui/resources/tools/js_modulizer.gni
@@ -3,10 +3,10 @@
# found in the LICENSE file.
common_namespace_rewrites = [
- "cr_slider.SliderTick|SliderTick",
"cr.addSingletonGetter|addSingletonGetter",
"cr.addWebUIListener|addWebUIListener",
"cr.dispatchSimpleEvent|dispatchSimpleEvent",
+ "cr.EventTracker|EventTracker",
"cr.icon.getFavicon|getFavicon",
"cr.icon.getImage|getImage",
"cr.isAndroid|isAndroid",
@@ -19,6 +19,7 @@ common_namespace_rewrites = [
"cr.png.convertImageSequenceToPng|convertImageSequenceToPng",
"cr.removeWebUIListener|removeWebUIListener",
"cr.sendWithPromise|sendWithPromise",
+ "cr_slider.SliderTick|SliderTick",
"cr.toastManager.getToastManager|getToastManager",
"cr.ui.FocusOutlineManager|FocusOutlineManager",
"cr.ui.FocusRowBehavior|FocusRowBehavior",
@@ -36,18 +37,16 @@ common_namespace_rewrites = [
]
template("js_modulizer") {
+ _outputs = []
+ foreach(_input, invoker.input_files) {
+ _outputs += [ "$target_gen_dir/" + get_path_info(_input, "name") + ".m.js" ]
+ }
+
action(target_name) {
script = "//ui/webui/resources/tools/js_modulizer.py"
inputs = invoker.input_files
-
- outputs = []
- foreach(_input, invoker.input_files) {
- outputs +=
- [ "$target_gen_dir/" + get_path_info(_input, "name") + ".m.js" ]
- }
-
- data = outputs
+ outputs = _outputs
args = [
"--in_folder",
@@ -61,5 +60,19 @@ template("js_modulizer") {
if (defined(invoker.namespace_rewrites)) {
args += invoker.namespace_rewrites
}
+
+ # TODO(crbug.com/1030998) Remove when File Manager uses JS modules only.
+ if (defined(invoker.preserve_offsets)) {
+ args += [ "--preserve_offsets" ] + invoker.preserve_offsets
+ }
+ }
+
+ # Appends the compiled outputs of |target_name| to the dependent's
+ # runtime_data list.
+ source_set("${target_name}_runtime_data") {
+ testonly = true
+
+ deps = [ ":${invoker.target_name}" ]
+ data = _outputs
}
}
diff --git a/chromium/ui/webui/resources/tools/js_unmodulizer.gni b/chromium/ui/webui/resources/tools/js_unmodulizer.gni
new file mode 100644
index 00000000000..1daa59e996b
--- /dev/null
+++ b/chromium/ui/webui/resources/tools/js_unmodulizer.gni
@@ -0,0 +1,26 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+template("js_unmodulizer") {
+ action(target_name) {
+ script = "//ui/webui/resources/tools/js_unmodulizer.py"
+
+ inputs = invoker.input_files
+
+ outputs = []
+ foreach(_output, invoker.output_files) {
+ outputs += [ "$target_gen_dir/" + _output ]
+ }
+
+ data = outputs
+
+ args = [
+ "--in_folder",
+ rebase_path(".", root_build_dir),
+ "--out_folder",
+ rebase_path(target_gen_dir, root_build_dir),
+ "--input_files",
+ ] + invoker.input_files + [ "--output_files" ] + invoker.output_files
+ }
+}
diff --git a/chromium/ui/webui/resources/tools/js_unmodulizer.py b/chromium/ui/webui/resources/tools/js_unmodulizer.py
new file mode 100644
index 00000000000..1733c436ed5
--- /dev/null
+++ b/chromium/ui/webui/resources/tools/js_unmodulizer.py
@@ -0,0 +1,68 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Generates JS files that can be used as standard scripts rather than native
+# JS modules, by removing module-only keywords:
+# import --> Removes entire line
+# export --> Removes "export" keyword only
+# Appends a console warning about using pre-JS module files.
+#
+# This script is intentionally very simple and is intended only to support
+# legacy UIs that are not served from a standard chrome:// URL and therefore
+# need to inline all scripts into a single HTML file. It does not, for example,
+# restore other deprecated patterns like cr.define().
+
+import argparse
+import io
+import os
+import re
+import sys
+
+_CWD = os.getcwd()
+
+IMPORT_LINE_REGEX = 'import'
+EXPORT_LINE_REGEX = 'export '
+
+
+def ProcessFile(filename, out_filename):
+ with io.open(filename, encoding='utf-8', mode='r') as f:
+ lines = f.readlines();
+
+ for i, line in enumerate(lines):
+ # Since this tool is used to generate non-module files that are expected
+ # to be inlined, any imported dependencies will be missing. Imports should
+ # not be used by files passed to this tool.
+ assert not re.match(IMPORT_LINE_REGEX, line), 'Unexpected import'
+ lines[i] = line.replace(EXPORT_LINE_REGEX, '')
+
+ lines.append(
+ ' console.warn(\'crbug/1173575, non-JS module files deprecated.\');');
+
+ # Reconstruct file.
+ # Specify the newline character so that the exact same file is generated
+ # across platforms.
+ with io.open(out_filename, 'wb') as f:
+ for l in lines:
+ f.write(l.encode('utf-8'))
+ return
+
+def main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--input_files', nargs='*', required=True)
+ parser.add_argument('--output_files', nargs='*', required=True)
+ parser.add_argument('--in_folder', required=True)
+ parser.add_argument('--out_folder', required=True)
+ args = parser.parse_args(argv)
+
+ in_folder = os.path.normpath(os.path.join(_CWD, args.in_folder))
+ out_folder = os.path.normpath(os.path.join(_CWD, args.out_folder))
+
+ index = 0
+ for f in args.input_files:
+ ProcessFile(os.path.join(in_folder, f),
+ os.path.join(out_folder, args.output_files[index]))
+ index = index + 1
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/chromium/ui/webui/untrusted_web_ui_browsertest_util.cc b/chromium/ui/webui/untrusted_web_ui_browsertest_util.cc
index 2167ab28f0c..018fe45e3d2 100644
--- a/chromium/ui/webui/untrusted_web_ui_browsertest_util.cc
+++ b/chromium/ui/webui/untrusted_web_ui_browsertest_util.cc
@@ -25,25 +25,24 @@ TestUntrustedWebUIConfig::TestUntrustedWebUIConfig(base::StringPiece host)
TestUntrustedWebUIConfig::TestUntrustedWebUIConfig(
base::StringPiece host,
- const content::TestUntrustedDataSourceCSP& content_security_policy)
- : WebUIConfig(content::kChromeUIUntrustedScheme, host),
- content_security_policy_(content_security_policy) {}
+ const content::TestUntrustedDataSourceHeaders& headers)
+ : WebUIConfig(content::kChromeUIUntrustedScheme, host), headers_(headers) {}
TestUntrustedWebUIConfig::~TestUntrustedWebUIConfig() = default;
std::unique_ptr<content::WebUIController>
TestUntrustedWebUIConfig::CreateWebUIController(content::WebUI* web_ui) {
- return std::make_unique<TestUntrustedWebUIController>(
- web_ui, host(), content_security_policy_);
+ return std::make_unique<TestUntrustedWebUIController>(web_ui, host(),
+ headers_);
}
TestUntrustedWebUIController::TestUntrustedWebUIController(
content::WebUI* web_ui,
const std::string& host,
- const content::TestUntrustedDataSourceCSP& content_security_policy)
+ const content::TestUntrustedDataSourceHeaders& headers)
: ui::UntrustedWebUIController(web_ui) {
content::AddUntrustedDataSource(web_ui->GetWebContents()->GetBrowserContext(),
- host, content_security_policy);
+ host, headers);
}
TestUntrustedWebUIController::~TestUntrustedWebUIController() = default;
diff --git a/chromium/ui/webui/untrusted_web_ui_browsertest_util.h b/chromium/ui/webui/untrusted_web_ui_browsertest_util.h
index dc9f124301b..791ce19fb67 100644
--- a/chromium/ui/webui/untrusted_web_ui_browsertest_util.h
+++ b/chromium/ui/webui/untrusted_web_ui_browsertest_util.h
@@ -33,22 +33,23 @@ class TestUntrustedWebUIControllerFactory
class TestUntrustedWebUIConfig : public ui::WebUIConfig {
public:
explicit TestUntrustedWebUIConfig(base::StringPiece host);
- explicit TestUntrustedWebUIConfig(
+ TestUntrustedWebUIConfig(
base::StringPiece host,
- const content::TestUntrustedDataSourceCSP& content_security_policy);
+ const content::TestUntrustedDataSourceHeaders& headers);
~TestUntrustedWebUIConfig() override;
std::unique_ptr<content::WebUIController> CreateWebUIController(
content::WebUI* web_ui) override;
- const content::TestUntrustedDataSourceCSP content_security_policy_;
+
+ const content::TestUntrustedDataSourceHeaders headers_;
};
class TestUntrustedWebUIController : public ui::UntrustedWebUIController {
public:
- explicit TestUntrustedWebUIController(
+ TestUntrustedWebUIController(
content::WebUI* web_ui,
const std::string& host,
- const content::TestUntrustedDataSourceCSP& content_security_policy);
+ const content::TestUntrustedDataSourceHeaders& headers);
~TestUntrustedWebUIController() override;
};
diff --git a/chromium/ui/wm/DIR_METADATA b/chromium/ui/wm/DIR_METADATA
deleted file mode 100644
index f31293e3139..00000000000
--- a/chromium/ui/wm/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail: {
- component: "UI"
-}
diff --git a/chromium/ui/wm/core/capture_controller_unittest.cc b/chromium/ui/wm/core/capture_controller_unittest.cc
index c515aa38d9a..f3e252607d3 100644
--- a/chromium/ui/wm/core/capture_controller_unittest.cc
+++ b/chromium/ui/wm/core/capture_controller_unittest.cc
@@ -4,6 +4,7 @@
#include "ui/wm/core/capture_controller.h"
+#include <memory>
#include <utility>
#include "base/macros.h"
@@ -63,8 +64,8 @@ class CaptureControllerTest : public aura::test::AuraTestBase {
second_host_->InitHost();
second_host_->window()->Show();
second_host_->SetBoundsInPixels(gfx::Rect(800, 600));
- second_capture_controller_.reset(
- new ScopedCaptureClient(second_host_->window()));
+ second_capture_controller_ =
+ std::make_unique<ScopedCaptureClient>(second_host_->window());
}
void TearDown() override {
@@ -88,7 +89,7 @@ class CaptureControllerTest : public aura::test::AuraTestBase {
delegate
? delegate
: aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate());
- window->set_id(id);
+ window->SetId(id);
window->Init(ui::LAYER_TEXTURED);
parent->AddChild(window);
window->SetBounds(bounds);
diff --git a/chromium/ui/wm/core/compound_event_filter.cc b/chromium/ui/wm/core/compound_event_filter.cc
index 4938b32a4ea..2ee68654a28 100644
--- a/chromium/ui/wm/core/compound_event_filter.cc
+++ b/chromium/ui/wm/core/compound_event_filter.cc
@@ -8,6 +8,7 @@
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
+#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/env.h"
@@ -75,6 +76,30 @@ gfx::NativeCursor CompoundEventFilter::CursorForWindowComponent(
}
}
+gfx::NativeCursor CompoundEventFilter::NoResizeCursorForWindowComponent(
+ int window_component) {
+ switch (window_component) {
+ case HTBOTTOM:
+ return ui::mojom::CursorType::kNorthSouthNoResize;
+ case HTBOTTOMLEFT:
+ return ui::mojom::CursorType::kNorthEastSouthWestNoResize;
+ case HTBOTTOMRIGHT:
+ return ui::mojom::CursorType::kNorthWestSouthEastNoResize;
+ case HTLEFT:
+ return ui::mojom::CursorType::kEastWestNoResize;
+ case HTRIGHT:
+ return ui::mojom::CursorType::kEastWestNoResize;
+ case HTTOP:
+ return ui::mojom::CursorType::kNorthSouthNoResize;
+ case HTTOPLEFT:
+ return ui::mojom::CursorType::kNorthWestSouthEastNoResize;
+ case HTTOPRIGHT:
+ return ui::mojom::CursorType::kNorthEastSouthWestNoResize;
+ default:
+ return ui::mojom::CursorType::kNull;
+ }
+}
+
void CompoundEventFilter::AddHandler(ui::EventHandler* handler) {
handlers_.AddObserver(handler);
}
@@ -104,7 +129,13 @@ void CompoundEventFilter::UpdateCursor(aura::Window* target,
if (target->delegate()) {
int window_component =
target->delegate()->GetNonClientComponent(event->location());
- cursor = CursorForWindowComponent(window_component);
+
+ if ((target->GetProperty(aura::client::kResizeBehaviorKey) &
+ aura::client::kResizeBehaviorCanResize) != 0) {
+ cursor = CursorForWindowComponent(window_component);
+ } else {
+ cursor = NoResizeCursorForWindowComponent(window_component);
+ }
} else {
// Allow the OS to handle non client cursors if we don't have a
// a delegate to handle the non client hittest.
diff --git a/chromium/ui/wm/core/compound_event_filter.h b/chromium/ui/wm/core/compound_event_filter.h
index e012f7254c5..8920c3ca358 100644
--- a/chromium/ui/wm/core/compound_event_filter.h
+++ b/chromium/ui/wm/core/compound_event_filter.h
@@ -41,6 +41,10 @@ class WM_CORE_EXPORT CompoundEventFilter : public ui::EventHandler {
// Returns the cursor for the specified component.
static gfx::NativeCursor CursorForWindowComponent(int window_component);
+ // Returns the not-resizable cursor for the specified component.
+ static gfx::NativeCursor NoResizeCursorForWindowComponent(
+ int window_component);
+
// Adds/removes additional event filters. This does not take ownership of
// the EventHandler.
// NOTE: These handlers are deprecated. Use env::AddPreTargetEventHandler etc.
diff --git a/chromium/ui/wm/core/focus_controller.cc b/chromium/ui/wm/core/focus_controller.cc
index 30d779881e6..e0aff607400 100644
--- a/chromium/ui/wm/core/focus_controller.cc
+++ b/chromium/ui/wm/core/focus_controller.cc
@@ -318,8 +318,8 @@ bool FocusController::SetActiveWindow(
if (window)
DCHECK_EQ(window, rules_->GetActivatableWindow(window));
- base::AutoReset<base::Optional<aura::Window*>> updating_activation(
- &pending_activation_, base::make_optional(window));
+ base::AutoReset<absl::optional<aura::Window*>> updating_activation(
+ &pending_activation_, absl::make_optional(window));
aura::Window* lost_activation = active_window_;
// Allow for the window losing activation to be deleted during dispatch. If
// it is deleted pass NULL to observers instead of a deleted window.
diff --git a/chromium/ui/wm/core/focus_controller.h b/chromium/ui/wm/core/focus_controller.h
index 19014a7c255..42f7c0c7d47 100644
--- a/chromium/ui/wm/core/focus_controller.h
+++ b/chromium/ui/wm/core/focus_controller.h
@@ -10,9 +10,9 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/scoped_multi_source_observation.h"
#include "base/strings/string_piece.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/window_observer.h"
#include "ui/events/event_handler.h"
@@ -130,7 +130,7 @@ class WM_CORE_EXPORT FocusController : public ActivationClient,
// An optional value. It is set to the window being activated and is unset
// after it is activated.
- base::Optional<aura::Window*> pending_activation_;
+ absl::optional<aura::Window*> pending_activation_;
std::unique_ptr<FocusRules> rules_;
diff --git a/chromium/ui/wm/core/focus_controller_unittest.cc b/chromium/ui/wm/core/focus_controller_unittest.cc
index 5ae62683ac0..5a49dc30c7d 100644
--- a/chromium/ui/wm/core/focus_controller_unittest.cc
+++ b/chromium/ui/wm/core/focus_controller_unittest.cc
@@ -560,7 +560,7 @@ class FocusControllerTestBase : public aura::test::AuraTestBase {
}
int GetFocusedWindowId() {
aura::Window* focused_window = GetFocusedWindow();
- return focused_window ? focused_window->id() : -1;
+ return focused_window ? focused_window->GetId() : -1;
}
void ActivateWindow(aura::Window* window) {
GetActivationClient(root_window())->ActivateWindow(window);
@@ -573,7 +573,7 @@ class FocusControllerTestBase : public aura::test::AuraTestBase {
}
int GetActiveWindowId() {
aura::Window* active_window = GetActiveWindow();
- return active_window ? active_window->id() : -1;
+ return active_window ? active_window->GetId() : -1;
}
TestFocusRules* test_focus_rules() { return test_focus_rules_; }
diff --git a/chromium/ui/wm/core/native_cursor_manager.h b/chromium/ui/wm/core/native_cursor_manager.h
index 1df3489cc9d..165f0f65a70 100644
--- a/chromium/ui/wm/core/native_cursor_manager.h
+++ b/chromium/ui/wm/core/native_cursor_manager.h
@@ -5,7 +5,6 @@
#ifndef UI_WM_CORE_NATIVE_CURSOR_MANAGER_H_
#define UI_WM_CORE_NATIVE_CURSOR_MANAGER_H_
-#include <string>
#include "ui/base/cursor/cursor.h"
#include "ui/wm/core/native_cursor_manager_delegate.h"
diff --git a/chromium/ui/wm/core/shadow_types.cc b/chromium/ui/wm/core/shadow_types.cc
index c8e0c2536ca..7f9fa1bcb9c 100644
--- a/chromium/ui/wm/core/shadow_types.cc
+++ b/chromium/ui/wm/core/shadow_types.cc
@@ -15,7 +15,7 @@ void SetShadowElevation(aura::Window* window, int elevation) {
}
int GetDefaultShadowElevationForWindow(const aura::Window* window) {
- switch (window->type()) {
+ switch (window->GetType()) {
case aura::client::WINDOW_TYPE_NORMAL:
return kShadowElevationInactiveWindow;
diff --git a/chromium/ui/wm/core/transient_window_manager_unittest.cc b/chromium/ui/wm/core/transient_window_manager_unittest.cc
index 5d4bc9fdc85..3dbf995aa36 100644
--- a/chromium/ui/wm/core/transient_window_manager_unittest.cc
+++ b/chromium/ui/wm/core/transient_window_manager_unittest.cc
@@ -78,7 +78,7 @@ class TransientWindowManagerTest : public aura::test::AuraTestBase {
// Creates a transient window that is transient to |parent|.
Window* CreateTransientChild(int id, Window* parent) {
Window* window = new Window(NULL);
- window->set_id(id);
+ window->SetId(id);
window->SetType(aura::client::WINDOW_TYPE_NORMAL);
window->Init(ui::LAYER_TEXTURED);
AddTransientChild(parent, window);
diff --git a/chromium/ui/wm/core/transient_window_stacking_client_unittest.cc b/chromium/ui/wm/core/transient_window_stacking_client_unittest.cc
index b1d8ecd1b4f..86f239ede58 100644
--- a/chromium/ui/wm/core/transient_window_stacking_client_unittest.cc
+++ b/chromium/ui/wm/core/transient_window_stacking_client_unittest.cc
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/test_windows.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/test/test_layers.h"
#include "ui/wm/core/window_util.h"
diff --git a/chromium/ui/wm/core/visibility_controller.cc b/chromium/ui/wm/core/visibility_controller.cc
index 4888a1290da..1904e8f90e1 100644
--- a/chromium/ui/wm/core/visibility_controller.cc
+++ b/chromium/ui/wm/core/visibility_controller.cc
@@ -45,8 +45,8 @@ bool VisibilityController::CallAnimateOnChildWindowVisibilityChanged(
void VisibilityController::UpdateLayerVisibility(aura::Window* window,
bool visible) {
- bool animated = window->type() != aura::client::WINDOW_TYPE_CONTROL &&
- window->type() != aura::client::WINDOW_TYPE_UNKNOWN &&
+ bool animated = window->GetType() != aura::client::WINDOW_TYPE_CONTROL &&
+ window->GetType() != aura::client::WINDOW_TYPE_UNKNOWN &&
ShouldAnimateWindow(window);
animated = animated &&
CallAnimateOnChildWindowVisibilityChanged(window, visible);
diff --git a/chromium/ui/wm/core/window_animations.cc b/chromium/ui/wm/core/window_animations.cc
index 0d27971f235..166f4530220 100644
--- a/chromium/ui/wm/core/window_animations.cc
+++ b/chromium/ui/wm/core/window_animations.cc
@@ -202,7 +202,8 @@ base::TimeDelta GetWindowVisibilityAnimationDuration(
const aura::Window& window) {
base::TimeDelta duration =
window.GetProperty(kWindowVisibilityAnimationDurationKey);
- if (duration.is_zero() && window.type() == aura::client::WINDOW_TYPE_MENU) {
+ if (duration.is_zero() &&
+ window.GetType() == aura::client::WINDOW_TYPE_MENU) {
return base::TimeDelta::FromMilliseconds(
kDefaultAnimationDurationForMenuMS);
}
@@ -214,8 +215,8 @@ base::TimeDelta GetWindowVisibilityAnimationDuration(
int GetWindowVisibilityAnimationType(aura::Window* window) {
int type = window->GetProperty(kWindowVisibilityAnimationTypeKey);
if (type == WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT) {
- return (window->type() == aura::client::WINDOW_TYPE_MENU ||
- window->type() == aura::client::WINDOW_TYPE_TOOLTIP)
+ return (window->GetType() == aura::client::WINDOW_TYPE_MENU ||
+ window->GetType() == aura::client::WINDOW_TYPE_TOOLTIP)
? WINDOW_VISIBILITY_ANIMATION_TYPE_FADE
: WINDOW_VISIBILITY_ANIMATION_TYPE_DROP;
}
diff --git a/chromium/ui/wm/core/window_animations.h b/chromium/ui/wm/core/window_animations.h
index 4f425caa7aa..066de998103 100644
--- a/chromium/ui/wm/core/window_animations.h
+++ b/chromium/ui/wm/core/window_animations.h
@@ -5,7 +5,6 @@
#ifndef UI_WM_CORE_WINDOW_ANIMATIONS_H_
#define UI_WM_CORE_WINDOW_ANIMATIONS_H_
-#include <vector>
#include "base/macros.h"
#include "ui/compositor/scoped_layer_animation_settings.h"